Ich habe es jetzt hinbekommen, wenn auch extrem umständlich.
Über den Callback list-sorting-panel-callback-subpanel habe ich mir jetzt eigene Select-Felder gebaut, die wie die klassischen Filter die ausgewählten Werte in die Session schreiben.
PHP-Code:
<?php
// src\EventListener\DataContainer\TicketsPanelCallbackListener.php
namespace BohnMedia\TicketToolBundle\EventListener\DataContainer;
use Contao\CoreBundle\ServiceAnnotation\Callback;
use Contao\DataContainer;
use Doctrine\DBAL\Connection;
use Symfony\Component\HttpFoundation\RequestStack;
use Symfony\Component\HttpFoundation\Session\SessionInterface;
/**
* @Callback(table="tl_calendar_tickets", target="list.sorting.panel_callback.customfilter")
*/
class TicketsPanelCallbackListener
{
private $request;
private $conn;
private $sessionBag;
public function __construct(RequestStack $requestStack, Connection $conn, SessionInterface $session)
{
$this->request = $requestStack->getMainRequest();
$this->conn = $conn;
$this->sessionBag = $session->getBag('contao_backend');
}
private function createSelect($field, $table, $selectfield, $order, $label, $dc)
{
// Read selected option from post
$active = $this->request->get($field);
// Get session
$session = $this->sessionBag->all();
// Update session
if ($active) {
if ($active !== 'tl_' . $field) {
$session['filter'][$dc->table][$field] = $active;
} else {
unset($session['filter'][$dc->table][$field]);
}
$this->sessionBag->replace($session);
}
// Get active from session
if (isset($session['filter'][$dc->table][$field])) {
$active = $session['filter'][$dc->table][$field];
}
// Build query
$query = 'SELECT id, ' . $selectfield . ' FROM ' . $table . ' ORDER BY ' . $order;
// Open select tag
$select = '<select name="' . $field . '" id="' . $field . '" class="tl_select' . ($active ? ' active' : '') . '">';
// Add default options
$select .= '<option value="tl_' . $field . '">' . $label . '</option>';
$select .= '<option value="tl_' . $field . '">---</option>';
// Fetch options from database
$stmt = $this->conn->query($query);
while (($row = $stmt->fetchNumeric()) !== false)
{
// Add option from row
$select .= '<option value="' . $row[0] . '"' . (($active == $row[0]) ? ' selected' : '') .'>' . htmlspecialchars($row[1]) . '</option>';
}
// Close select tag
$select .= '</select>';
return $select;
}
public function __invoke(DataContainer $dc): string
{
$select = '';
// Event select
$select .= $this->createSelect(
'event',
'tl_calendar_events',
'CONCAT(title, DATE_FORMAT(FROM_UNIXTIME(startTime), CHAR(32, 91, 37, 100, 46, 37, 109, 46, 37, 89, 93)))',
'startTime DESC',
$GLOBALS['TL_LANG']['tl_calendar_tickets']['event'][0],
$dc
);
// Member select
$select .= $this->createSelect(
'member',
'tl_member',
'CONCAT(lastname, ", ", firstname)',
'lastname ASC, firstname ASC',
$GLOBALS['TL_LANG']['tl_calendar_tickets']['member'][0],
$dc
);
return '<div class="tl_filter tl_subpanel"><strong>' . $GLOBALS['TL_LANG']['MSC']['filter'] . ':</strong>' . $select . '</div>';
}
}
Über den Callback config.onload werden die Werte aus der Session dann als Filter im DCA angefügt.
PHP-Code:
<?php
// src\EventListener\DataContainer\TicketsOnloadCallbackListener.php
namespace BohnMedia\TicketToolBundle\EventListener\DataContainer;
use Contao\CoreBundle\ServiceAnnotation\Callback;
use Contao\DataContainer;
use Symfony\Component\HttpFoundation\Session\SessionInterface;
/**
* @Callback(table="tl_calendar_tickets", target="config.onload")
*/
class TicketsOnloadCallbackListener
{
private $sessionBag;
public function __construct(SessionInterface $session)
{
$this->sessionBag = $session->getBag('contao_backend');
}
public function __invoke(DataContainer $dc = null): void
{
$filter = [];
// Get session data
$session = $this->sessionBag->all();
// Look for event and member filter in session
foreach (['event', 'member'] as $field) {
if (isset($session['filter']['tl_calendar_tickets'][$field])) {
// Set filter for field in dca
$value = $session['filter']['tl_calendar_tickets'][$field];
$filter[] = [$field . '=?', $value];
}
}
// Overwrite dca filter
$GLOBALS['TL_DCA']['tl_calendar_tickets']['list']['sorting']['filter'] = $filter;
}
}
Die Klassen wurden wie folgt der services.yml hinzugefügt.
Code:
services:
BohnMedia\TicketToolBundle\EventListener\DataContainer\TicketsPanelCallbackListener:
arguments: ['@request_stack', '@database_connection', '@session']
BohnMedia\TicketToolBundle\EventListener\DataContainer\TicketsOnloadCallbackListener:
arguments: ['@session']
Leider ist die Lösung nur bedingt updatesicher. Falls jemand eine einfachere Lösung kennt, Filter nach einem bestimmten Feld zu sortieren, bin ich weiterhin für jeden Tipp dankbar.
Lesezeichen