Hallo,
ich habe ebenfalls nach einer Lösung für dieses Problem gesucht und bin zur folgenden etwas umfangreicheren Umsetzung gekommen:
Damit immer jeder Wrapper 'start' auch mit genau einem Wrapper 'stop' verlinkt ist, erstelle ich für jeden Wrapper 'start' automatisch einen Wrapper 'stop' und speichere dessen ID ein einem Feld 'wrapper_stop_id'. Immer wenn ich Änderungen im Wrapper 'start' speichere, aktualisiere ich dann die Daten des zugehörigen Wrapper 'stop'.
Um das Verhalten umzusetzen verwende ich den onsubmit und den oncopy callback:
PHP-Code:
$GLOBALS['TL_DCA']['tl_content']['config']['onsubmit_callback'][] = array('RSCustomElementHelper','createWrapperStop');
$GLOBALS['TL_DCA']['tl_content']['config']['oncopy_callback'][] = array('RSCustomElementHelper','createWrapperStopOnCopy');
und folgende Helper-Klasse:
PHP-Code:
<?php
use Contao\Database;
use Contao\Input;
use DC_Table;
use MadeYourDay\RockSolidCustomElements\CustomElements;
use function json_decode;
use function json_encode;
class RSCustomElementHelper
{
/**
* Automatically creates a wrapper-stop element and connects it with the current wrapper start
*
* @param $objDC
*/
public function createWrapperStop(DC_Table $objDC)
{
if (!$objDC->activeRecord) {
$objDC->activeRecord = $this->getActiveRecord($objDC->table, $objDC->id);
}
$type = $objDC->activeRecord->type;
$config = $this->getWrapperStartConfig($type);
if ($config) {
$wrapperClose = $config['wrapperClose'];
if ($objDC->activeRecord->rsce_data == null) {
//create wrapper stop
$res = $this->createRsceDatabaseEntry($objDC, $wrapperClose);
if ($res->affectedRows) {
$arrData = array('wrapper_stop_id' => $res->insertId);
$this->updateRsceDatabaseEntry($objDC->table, $objDC->activeRecord->id, $arrData);
}
} elseif (!empty($objDC->activeRecord->rsce_field_wrapper_stop_id)) {
$arrData = $this->createWrapperStopData($objDC->activeRecord);
$this->updateRsceDatabaseEntry(
$objDC->table,
$objDC->activeRecord->rsce_field_wrapper_stop_id,
$arrData
);
}
}
}
/**
* Creates a wrapper-stop element at copy-action of a single wrapper-start element
*
* @param $id
* @param $objDC
*/
public function createWrapperStopOnCopy($id, DC_Table $objDC)
{
//check if custom element has wrapper config
$objDC->activeRecord = $this->getActiveRecord($objDC->table, $id);
$type = $objDC->activeRecord->type;
$config = $this->getWrapperStartConfig($type);
if ($config) {
$wrapperClose = $config['wrapperClose'];
$rsceData = json_decode($objDC->activeRecord->rsce_data, true);
$rsceData['wrapper_stop_id'] = 0;
if (Input::get('act') == "copy") {
//create wrapper stop
$arrData = $this->createWrapperStopData($objDC->activeRecord);
$res = $this->createRsceDatabaseEntry($objDC, $wrapperClose, $arrData);
if ($res->affectedRows) {
//update wrapper start
$rsceData['wrapper_stop_id'] = $res->insertId;
}
}
$this->updateRsceDatabaseEntry($objDC->table, $id, $rsceData);
}
}
private function getActiveRecord($table, $id)
{
return Database::getInstance()
->prepare("SELECT * FROM " . $table . " WHERE id=?")
->limit(1)->execute($id);
}
/**
* Gets the config of a start wrapper, if it contains a wrapperClose definition
*
* @param $type
* @return array|bool|null
*/
private function getWrapperStartConfig($type)
{
//check if element is rocksolid custom element
if (preg_match("/^rsce_/", $type)) {
$config = CustomElements::getConfigByType($type);
$wrapperType = $config['wrapper'];
if ($wrapperType['type'] == 'start' && isset($config['wrapperClose'])) {
return $config;
}
}
return false;
}
private function createRsceDatabaseEntry($objDC, $type, $rsceData = "")
{
$objDB = Database::getInstance();
//set sorting to value between current and next entry
$currentSorting = $objDC->activeRecord->sorting;
$nextSorting = $objDB->prepare('SELECT sorting FROM tl_content WHERE sorting > ? AND pid = ? AND ptable = ? ORDER BY sorting LIMIT 1')
->execute($currentSorting, $objDC->activeRecord->pid, $objDC->activeRecord->ptable)->fetchRow()[0];
$newSorting = (($nextSorting - $currentSorting) / 2 + $currentSorting);
//create database entry
return Database::getInstance()
->prepare(
"INSERT INTO " . $objDC->table . " (pid, ptable, tstamp, type, sorting, invisible, rsce_data) VALUES (?,?,?,'$type',?,?,?)"
)
->execute(
$objDC->activeRecord->pid,
$objDC->activeRecord->ptable,
time(),
$newSorting,
$objDC->activeRecord->invisible,
json_encode($rsceData)
);
}
private function updateRsceDatabaseEntry($table, $id, $rsceData)
{
return Database::getInstance()
->prepare("UPDATE " . $table . " SET rsce_data = ? WHERE id=?")
->execute(json_encode($rsceData), $id);
}
private function createWrapperStopData($activeRecord)
{
$arrData = array();
//todo create wrapper stop data from active record
return $arrData;
}
}
In der Funktion createWrapperStopData() kannst du dann die rsce_data Daten für den Wrapper 'stop' generieren.
In der config des Wrapper 'start' muss dann noch der "wrapperClose" definiert und das Feld "wrapper_stop_id" hinzugefügt werden:
PHP-Code:
...
'wrapper' => array('type' => 'start'),
'wrapperClose' => 'rsce_wrapper_stop',
'fields' => array(
....
'wrapper_stop_id' => array(
'inputType' => 'text',
'default' => 0,
'eval' => array('rgxp'=>'natural', 'tl_class'=>'w50'),
),
Der Verlinkung kann auf Wunsch aufgehoben werden, indem man die ID auf 0 setzt.
Ich nehme jeden Verbesserungsvorschlag gerne entgegen
LG Maria