Contao – manuelles Sortieren im „sorting mode 2“
Ab Contao 4: https://github.com/hh-com/contao-listviewsortable
Bei der Erstellung von Backend-Module bietet Contao einige Möglichkeiten die Datensätze automatisch zu sortieren (Contao Reference).
Unter anderem können im Sortier-Mode 4 die Datensätze manuell via Drag an Drop sortiert werden. Im Mode 2 ist dies nicht möglich.
Nachfolgend ein Script wie man einem Up/Down Button nachrüsten kann (btw. das Script kann gerne optimiert werden). Die Sortierung erfolgt dabei über den Array-Key.
Felder für die Sortierung: groupBy, sorting ASC
Das Feld „groupBy“ liefert ein Select, welches die Datensätze kategorisiert.
/*...*/
'sorting' => array
(
'sql' => "int(10) unsigned NOT NULL default '0'"
),
...
'groupBy' => array
(
'label' => &$GLOBALS['TL_LANG']['tl_example']['groupBy'],
'default' => 'ascending',
'exclude' => true,
'filter' => true,
'inputType' => 'select',
'options' => array("Erde","Luft","Wasser","Feuer"),
'eval' => array('tl_class'=>'clr w50', 'includeBlankOption'=>true),
'sql' => "varchar(255) NOT NULL default ''"
),
...
Beide Felder werden im Array „list->sorting“ eingetragen:
Mode 2 = Sortierung nach einem variablen Feld
Flag 11 = Aufsteigende Sortierung
'sorting' => array
(
'mode' => 2,
'fields' => array('groupBy', 'sorting ASC'),
'flag' => 11,
'panelLayout' => 'search,limit',
),
Für den Up/Down – Button wird „operations“ um diese Felder erweitert:
'up' => array
(
'label' => &$GLOBALS['TL_LANG']['tl_example']['up'],
'href' => 'sorting=up',
'icon' => 'up.gif',
'button_callback' => array('tl_example', 'sortingUp')
),
'down' => array
(
'label' => &$GLOBALS['TL_LANG']['tl_example']['down'],
'href' => 'sorting=down',
'icon' => 'down.gif',
'button_callback' => array('tl_example', 'sortingDown')
),
Der „button_callback“ ruft die jeweilige Funktion für die Sortierung und gibt gleichzeitig den richtigen Button aus.
/* insert into class tl_example extends Backend */
public function sortingUp($row, $href, $label, $title, $icon, $attributes)
{
/* Redirect to module home after change position*/
if ($this->Input->get('sortId') AND $this->Input->get('sorting') == "up")
{
$thisId = $this->Input->get('sortId');
$sortByGroup = $this->Input->get('groupBy');
$dbObj = $this->Database->prepare("SELECT * FROM tl_example WHERE groupBy = ? ORDER BY sorting ASC")
->execute( $sortByGroup );
if ($dbObj->numRows == NULL)
return false;
$allData = $dbObj->fetchAllAssoc();
/* Get all data from DB, save temp array, get new position and unset the array by key */
foreach ( $allData AS $key => $data )
{
if ( $data['id'] == $thisId )
{
$temp = $data;
$newPosition = $key - 1;
unset($allData[$key]);
}
}
if ($newPosition < 0)
$newPosition = 0;
if ($newPosition > count($allData))
$newPosition = count($allData);
$newPosition = intval($newPosition);
$allData = array_values( $allData );
$newSorting = array();
$counter = 0;
foreach ( $allData AS $key => $data )
{
/* Insert the item on new position in this helper array*/
/*
if ($key == $newPosition)
{
$newSorting[] = $temp;
}
$newSorting[] = $data;
*/
if ($key == $newPosition)
{
$this->Database->prepare("UPDATE tl_example SET sorting=? WHERE id=?")
->execute( $counter , $temp['id']);
$counter ++;
}
$this->Database->prepare("UPDATE tl_example SET sorting=? WHERE id=?")
->execute( $counter, $data['id']);
$counter ++;
}
$this->redirect($this->getReferer());
}
$dbObj = $this->Database->prepare("SELECT * FROM tl_example WHERE groupBy = ? ORDER BY sorting ASC")
->execute( $row['groupBy'] );
$anzObj = $dbObj->numRows;
if ( $anzObj != NULL)
{
$counter = 0;
while ($dbObj->next())
{
if ($dbObj->id == $row['id'] )
{
if ($counter == 0 )
{
/* First */
return '<span>'.$this->generateImage('demagnify.gif', $label).'</span> ';
}
else
{
$href .= '&sortId='.$row['id'].'&groupBy='.$row['groupBy'].'&sortValue='.$row['sorting'];
return '<a href="'.$this->addToUrl($href).'" title="'.specialchars($title).'"'.$attributes.'>'.$this->generateImage($icon, $label).'</a> ';
}
}
$counter++;
}
}
}
public function sortingDown($row, $href, $label, $title, $icon, $attributes)
{
/* Redirect to module home after change position*/
if ($this->Input->get('sortId') AND $this->Input->get('sorting') == "down" )
{
$thisId = $this->Input->get('sortId');
$sortByGroup = $this->Input->get('groupBy');
$dbObj = $this->Database->prepare("SELECT * FROM tl_example WHERE groupBy = ? ORDER BY sorting ASC")
->execute( $sortByGroup );
if ($dbObj->numRows == NULL)
return false;
$allData = $dbObj->fetchAllAssoc();
#echo "<pre>";
#var_dump($allData);
/* Get all data from DB, save temp array, get new position and unset the array by key */
foreach ( $allData AS $key => $data )
{
if ( $data['id'] == $thisId )
{
$temp = $data;
$newPosition = $key + 1;
unset($allData[$key]);
}
}
if ($newPosition < 0)
$newPosition = 0;
if ($newPosition > count($allData))
$newPosition = count($allData);
$newPosition = intval($newPosition);
$allData = array_values( $allData );
#var_dump($newPosition);
#exit;
$newSorting = array();
$counter = 0;
foreach ( $allData AS $key => $data )
{
/* Insert the item on new position in this helper array*/
/*
if ($key == $newPosition)
{
$newSorting[] = $temp;
}
$newSorting[] = $data;
*/
if ($key == $newPosition)
{
$this->Database->prepare("UPDATE tl_example SET sorting=? WHERE id=?")
->execute( $counter , $temp['id']);
$counter ++;
}
$this->Database->prepare("UPDATE tl_example SET sorting=? WHERE id=?")
->execute( $counter, $data['id']);
$counter ++;
}
$this->redirect($this->getReferer());
}
/* Dont show first and last Arrow*/
$dbObj = $this->Database->prepare("SELECT * FROM tl_example WHERE groupBy = ? ORDER BY sorting ASC")
->execute( $row['groupBy'] );
$anzObj = $dbObj->numRows;
if ( $anzObj != NULL)
{
$counter = 0;
while ($dbObj->next())
{
if ($dbObj->id == $row['id'] )
{
if ($counter == $anzObj-1 )
{
/* Last */
return '<span>'.$this->generateImage('demagnify.gif', $label).'</span> ';
}
else
{
$href .= '&sortId='.$row['id'].'&groupBy='.$row['groupBy'].'&sortValue='.$row['sorting'];
return '<a href="'.$this->addToUrl($href).'" title="'.specialchars($title).'"'.$attributes.'>'.$this->generateImage($icon, $label).'</a> ';
}
}
$counter++;
}
}
}
Das Ergebnis sieht dann so aus:
Das Script kann sicher optimiert werden, besonders die Bestimmung der neuen Position – wer möchte. Für mich erfüllt es seinen Zweck.
Contao 3.5