Ergebnis 1 bis 13 von 13

Thema: config.onbeforesubmit $record/$dc->activeRecord wird nicht aktualisiert

  1. #1
    Contao-Fan Avatar von Monique Hahnefeld
    Registriert seit
    22.11.2011.
    Ort
    Berlin
    Beiträge
    283

    Frage config.onbeforesubmit $record/$dc->activeRecord wird nicht aktualisiert

    Hi,

    ich brauche in meiner Erweiterung den Callback config.onbeforesubmit

    Ich aktualisiere da Werte je nach Umgebung der Operation.
    Leider funktioniert es nicht. Der Callback wird geladen, die Session-Werte sind auch ok, aber in der Datenbank landet nichts.

    Mein Callback sieht so aus:
    .
    Code:
    <?php
    
    namespace Bits\FlyUxBundle\EventListener;
    
    use Contao\CoreBundle\DependencyInjection\Attribute\AsCallback;
    use Contao\DataContainer;
    use Contao\System;
    use Contao\Input;
    
    
    #[AsCallback(table: 'tl_content', target: 'config.onbeforesubmit', method:'savePid')]
    class ContentElementSaveListener
    {
        public function savePid($record, DataContainer $dc)
        {
            
            
            
            if (Input::get('op_add') === 'add_content_element') {
    
                
                $session = System::getContainer()->get('request_stack')->getSession();
                $pid = $session->getBag('contao_backend')->get('OP_ADD_PID');
                $ptable = $session->getBag('contao_backend')->get('OP_ADD_PTABLE');
            
                $dc->activeRecord->pid = $pid;
                $record['pid'] = $pid;
                $dc->activeRecord->parentTable = $ptable;
                $record['parentTable'] = $ptable;
                $this->dc = $dc;
            }
                return $record;
                
            
        }
    }
    Hab ich da irgendeinen Fehler im Callback?

    Viele Grüße und danke schonmal fürs lesen.
    Geändert von Monique Hahnefeld (30.04.2025 um 12:14 Uhr)
    Curiosity killed the cat

  2. #2
    Community-Moderator
    Wandelndes Contao-Lexikon
    Avatar von Spooky
    Registriert seit
    12.04.2012.
    Ort
    Scotland
    Beiträge
    37.158
    Partner-ID
    10107

    Standard

    $dc->activeRecord ist deprecated. Du nimmst entweder $dc->getCurrentRecord() (aktueller Stand in der Datenbank) - oder im DC_Table auch $dc->getActiveRecord() (Stand in der Datenbank + übermittelte Änderungen kombiniert).
    » sponsor me via GitHub or Revolut

  3. #3
    Contao-Fan Avatar von Monique Hahnefeld
    Registriert seit
    22.11.2011.
    Ort
    Berlin
    Beiträge
    283

    Frage

    Ok, also wenn ich das richtig verstehe wird das Array $record mit seinen Werten dann in die DB übernommen.

    (Also es tut sich nix in der DB nach den Speichern)
    Geändert von Monique Hahnefeld (30.04.2025 um 12:48 Uhr)
    Curiosity killed the cat

  4. #4
    Community-Moderator
    Wandelndes Contao-Lexikon
    Avatar von Spooky
    Registriert seit
    12.04.2012.
    Ort
    Scotland
    Beiträge
    37.158
    Partner-ID
    10107

    Standard

    Sollte so sein, ja.

    Übrigens, du solltest immer DI verwenden, nicht System::getContainer()
    » sponsor me via GitHub or Revolut

  5. #5
    Contao-Fan Avatar von Monique Hahnefeld
    Registriert seit
    22.11.2011.
    Ort
    Berlin
    Beiträge
    283

    Frage

    Shit geht doch nicht...


    Code:
    <?php
    
    namespace Bits\FlyUxBundle\EventListener;
    
    use Contao\CoreBundle\DependencyInjection\Attribute\AsCallback;
    use Contao\DataContainer;
    use Contao\System;
    use Contao\Input;
    
    
    #[AsCallback(table: 'tl_content', target: 'config.onbeforesubmit', method:'savePid')]
    class ContentElementSaveListener
    {
        public function savePid($record, DataContainer $dc):array
        {
            
            
            
            if (Input::get('op_add') === 'add_content_element') {
    
                
                $session = System::getContainer()->get('request_stack')->getSession();
                $pid = $session->getBag('contao_backend')->get('OP_ADD_PID');
                $ptable = $session->getBag('contao_backend')->get('OP_ADD_PTABLE');
            
                $record['id'] = Input::get('id');
                $record['pid'] = $pid;
                $record['inColumn'] = $dc->getActiveRecord()['inColumn'];
                $record['parentTable'] = $ptable;
               
            }
                return $record;
                
            
        }
    }
    Habe jetzt nochmal den DC_Table analysiert:
    $this->arrSubmit ist ein leeres Array und $this->strTable ist Null. Da dürfte der Hund begraben liegen...
    Code:
    	protected function submit()
    	{
            
            
    		if (Input::post('FORM_SUBMIT') != $this->strTable)
    		{
                var_dump(Input::post('FORM_SUBMIT'),$this->strTable,$this->arrSubmit);exit;
     
                return;
    		}
    Wie kann ich das am besten debuggn?
    Geändert von Monique Hahnefeld (30.04.2025 um 14:29 Uhr)
    Curiosity killed the cat

  6. #6
    Community-Moderator
    Wandelndes Contao-Lexikon
    Avatar von Spooky
    Registriert seit
    12.04.2012.
    Ort
    Scotland
    Beiträge
    37.158
    Partner-ID
    10107

    Standard

    Was genau willst du denn machen, was genau funktioniert nicht und wie genau sieht dein Code nun aus?
    » sponsor me via GitHub or Revolut

  7. #7
    Contao-Fan Avatar von Monique Hahnefeld
    Registriert seit
    22.11.2011.
    Ort
    Berlin
    Beiträge
    283

    Standard

    Also was ich mache übergeift etwas das gewohnt DC_Table-Schema. Ich liste zuerst tl_content-Datensätze mit der ptable=tl_page. Da funktioniert alles super wenn ich ein neues Inhaltselement erstelle.

    Dann kommt Ebene 2: Inhaltselemente mit der Eigenschaft "Plus", wie der ContentSlider (nicht contao-core). Es ist der selbe Request aber Contao kommt damit nicht gut zurecht das da der ptable ja 'tl_content' ist.

    Habe gerade mal probiert ob es daran liegt das getParentEntries im Controller null zurückgibt, aber das ist es nicht. Naja ich suche mal weiter

    Also in der Methode edit im DC_Table ist die Variable $this->strTable noch richtig, aber bei submit ist sie null

    Mein DC_Content sieht so aus:
    PHP-Code:
    <?php
    namespace Bits\FlyUxBundle\Driver;

    use 
    Contao\DC_Table;
    use 
    Contao\ContaoBundle\RequestToken;
    use 
    Contao\System;
    use 
    Contao\Database;
    use 
    Contao\Input;
    use 
    Contao\Image;
    use 
    Contao\FilesModel;
    use 
    Contao\ContentModel;
    use 
    Contao\PageModel;
    use 
    Contao\LayoutModel;
    use 
    Symfony\Component\HttpFoundation\RequestStack;
    use 
    Bits\FlyUxBundle\Service\ImageResizer;

    class 
    DC_Content extends DC_Table
    {

        private 
    $imageResizer;
        private 
    $container;

        protected 
    $arrModule;

        public function 
    __construct($strTable$arrModule = array())
        {

            
    parent::__construct($strTable$arrModule);
            
    $this->container System::getContainer();

            
    $this->strTable $strTable;
            
    $this->arrModule $arrModule;
        }

        
    /**
         * Insert a new row into a database table
         *
         * @param array $set
         *
         * @throws AccessDeniedException
         */
        
    public function create($set = array())
        {

            
    $db Database::getInstance();
            
    $databaseFields $db->getFieldNames($this->strTable);
            
    $objSession $this
                
    ->container
                
    ->get('request_stack')
                ->
    getSession();

            
    // Get all default values for the new entry
            
    foreach ($GLOBALS['TL_DCA'][$this->strTable]['fields'] as $k => $v)
            {
                
    // Use array_key_exists here (see #5252)
                
    if (\array_key_exists('default'$v) && \in_array($k$databaseFieldstrue))
                {
                    
    $default $v['default'];

                    if (
    $default instanceof \Closure)
                    {
                        
    $default $default($this);
                    }

                    
    $this->set[$k] = \is_array($default) ? serialize($default) : $default;
                }
                if (
    $k === 'pid')
                {

                    
    $this->set[$k] = $objSession->getBag('contao_backend')
                        ->
    get('OP_ADD_PID');

                }

                if (
    $k === 'inColumn')
                {

                    
    $this->set[$k] = $objSession->getBag('contao_backend')
                        ->
    get('OP_ADD_COLUMN');
                    
    //  System::getContainer()->get('monolog.logger.contao.general')->info('On create "' . $objSession->getBag('contao_backend')->get('OP_ADD_PTABLE'));
                    

                    
                
    }
            }

            
    // Set passed values
            
    if (!empty($set) && \is_array($set))
            {
                
    $this->set array_merge($this->set$set);
            }

            
    //var_dump( $this->set);exit;
            
    $this->set['tstamp'] = 0// time();
            // Insert the record if the table is not closed and switch to edit mode
            
    if (!($GLOBALS['TL_DCA'][$this->strTable]['config']['closed'] ? ? null))
            {

                
    //  var_dump($this->set);exit;
                
    $objInsertStmt $db->prepare("INSERT INTO " $this->strTable " %s")
                    ->
    set($this->set)
                    ->
    execute();

                if (
    $objInsertStmt->affectedRows)
                {
                    
    $s2e = ($GLOBALS['TL_DCA'][$this->strTable]['config']['switchToEdit'] ? ? null) ? '&s2e=1' '';

                    
    $insertID $objInsertStmt->insertId;

                    
    $objSessionBag $objSession->getBag('contao_backend');

                    
    // Save new record in the session
                    
    $new_records $objSessionBag->get('new_records');
                    
    $new_records[$this->strTable][] = $insertID;

                    
    $objSessionBag->set('new_records'$new_records);

                    
    System::getContainer()->get('monolog.logger.contao.general')
                        ->
    info('A new entry "' $this->strTable '.id=' $insertID '" has been created' $this->getParentEntries($this->strTable$insertID));

                    
    $this->redirect($this->switchToEdit($insertID) . $s2e);
                }
            }

            
    $this->redirect($this->getReferer());
        }

        public function 
    generateTree($table$id$arrPrevNext$blnHasSorting$intMargin 0$arrClipboard null$blnCircularReference false$protectedPage false$blnNoRecursion false$arrFound = array())
        {

            if (
    Input::get('do') === 'content' && Input::get('mode') === 'layout')
            {

                
    $pTable 'tl_page';
                
    $objSession System::getContainer()->get('request_stack')
                    ->
    getSession();
                if (
    Input::get('pid'))
                {
                    
    $objSession->getBag('contao_backend')
                        ->
    set('OP_ADD_PID'Input::get('pid'));

                }
                
    $objSession->getBag('contao_backend')
                    ->
    set('OP_ADD_MODE'Input::get('mode'));

                
    $objSession->getBag('contao_backend')
                    ->
    set('OP_ADD_PTABLE'$pTable);
                
    $objSession->getBag('contao_backend')
                    ->
    set('OP_ADD_COLUMN''main');

                
    //find Layout of the page
                
    $pageModel = new PageModel;
                
    $objPage $pageModel::findById(Input::get('pid'));
                
    $layoutId $objPage->loadDetails()->layout;

                
    $layoutModel = new LayoutModel;
                
    $objLayout $layoutModel::findById($layoutId);
                
    // find layout sections within sections and modules
                // make an assoc array about the posibilities to include a section
                
    $attrBlock = ['position' => 'default'];

                
    $htmlBlocks = [];
                
    $htmlBlocks['container'] = $attrBlock;

                foreach (
    unserialize($objLayout->modules) as $module)
                {
                    if (
    $module['mod'] !== '0')
                    {
                        continue;
                    }

                    
    //var_dump(unserialize($objLayout->sections));exit;
                    
    foreach (unserialize($objLayout->sections) as $section)
                    {

                        
    //  var_dump($module['col'] === $section['id'],$section['id'],$module['col']);
                        
    if ($section['position'] === 'top' && $module['col'] === $section['id'])
                        {
                            
    $htmlBlocks[$section['id']] = ['position' => 'top'];
                        }
                        elseif (
    $section['position'] === 'before' && $module['col'] === $section['id'])
                        {

                            
    $htmlBlocks['container'][$section['id']] = ['position' => 'before'];
                            
    $htmlBlocks['container'][$module['col']] = $attrBlock;

                        }
                        elseif (
    $section['position'] === $module['col'] && $module['col'] === $section['id'])
                        {

                            
    $htmlBlocks['container'][$module['col']][$section['id']] = ['position' => 'main'];
                        }
                        elseif (
    $section['position'] === 'after' && $module['col'] === $section['id'])
                        {

                            
    $htmlBlocks['container'][$module['col']] = $attrBlock;
                            
    $htmlBlocks['container'][$section['id']] = ['position' => 'after'];
                        }
                        elseif (
    $section['position'] === 'bottom' && $module['col'] === $section['id'])
                        {

                            
    $htmlBlocks[$section['id']] = ['position' => 'bottom'];
                        }
                        else
                        {
                            
    $htmlBlocks['container'][$module['col']] = $attrBlock;

                        }

                    }
                }
                
    $arrElements = array();
                
    $dbElements $this
                    
    ->container
                    
    ->get('database_connection')
                    ->
    fetchAllAssociative("SELECT id, pid, headline, type, inColumn, cssId, el_count
                                 FROM tl_content
                                 WHERE pid = :pid
                                   AND parentTable = :ptable
                                 ORDER BY pid ASC, sorting ASC"
    , ['pid' => (int)Input::get('pid') , 'ptable' => (string)$pTable, ]);

                if (
    $dbElements !== null)
                {
                    
    $arrElements $this->buildElements($dbElementsInput::get('pid'));
                    
    // var_dump($arrElements);exit;
                    
                
    }

                return 
    $this->renderDetailView($objLayout$htmlBlocks$arrElements$objPage);

                
    // var_dump($htmlBlocks);exit;
                
            
    }
            if (
    Input::get('do') === 'content' && Input::get('mode') === 'plus')
            {
                
    $pTable 'tl_content';
                
    $objSession System::getContainer()->get('request_stack')
                    ->
    getSession();
                if (
    Input::get('id') && Input::get('op_add') !== 'add_content_element')
                {
                    
    $objSession->getBag('contao_backend')
                        ->
    set('OP_ADD_PID'Input::get('id'));
                }
                
    $objSession->getBag('contao_backend')
                    ->
    set('OP_ADD_MODE'Input::get('mode'));
                
    $objSession->getBag('contao_backend')
                    ->
    set('OP_ADD_PTABLE'$pTable);
                if (
    Input::get('el'))
                {
                    
    $objSession->getBag('contao_backend')
                        ->
    set('OP_ADD_EL'Input::get('el'));
                }
                if (
    Input::get('plus'))
                {
                    
    $objSession->getBag('contao_backend')
                        ->
    set('OP_ADD_PLUS'Input::get('plus'));
                    
    $objSession->getBag('contao_backend')
                        ->
    set('OP_ADD_COLUMN'Input::get('plus') . '-el-1');
                }
                
    $htmlBlocks = [];
                
    $htmlBlocks[Input::get('plus') ] = [];
                for (
    $i 0;$i Input::get('el');$i++)
                {
                    
    $htmlBlocks[Input::get('plus') ][Input::get('plus') . '-el-' $i 1] = [];
                }
                
    $arrElements = array();
                
    $dbElements $this
                    
    ->container
                    
    ->get('database_connection')
                    ->
    fetchAllAssociative("SELECT id, pid, headline, type, inColumn, cssId, el_count
                                 FROM tl_content
                                 WHERE pid = :pid
                                   AND parentTable = :ptable
                                 ORDER BY pid ASC, sorting ASC"
    , ['pid' => (int)Input::get('id') , 'ptable' => (string)$pTable, ]);

                
    //var_dump($dbElements);exit;
                
    if ($dbElements !== null)
                {
                    
    $arrElements $this->buildElements($dbElementsInput::get('id'));
                    
    // var_dump($arrElements);exit;
                    
                
    }

                return 
    $this->renderDetailView(Null$htmlBlocks$arrElementsNull);

            }

        }

        protected function 
    renderDetailView($objLayout Null$htmlBlocks$arrElements$objPage Null)
        {

            
    $requestStack $this
                
    ->container
                
    ->get('request_stack');
            
    $request $requestStack->getCurrentRequest();

            
    $baseUrl $request->getSchemeAndHttpHost();

            
    $tokenManager $this
                
    ->container
                
    ->get('contao.csrf.token_manager');

            return 
    $this
                
    ->container
                
    ->get('twig')
                ->
    render('@Contao/be_content_details.html.twig', array(
                
    'baseUrl' => $request->getSchemeAndHttpHost() . $request->getBaseUrl() ,
                
    'pageName' => ($objPage) ? $objPage->__get('title') : 'Content Plus',
                
    'layoutClass' => ($objLayout) ? $objLayout->__get('cssClass') : '',
                
    'htmlBlocks' => $htmlBlocks,
                
    'elementsByBlock' => $arrElements
            
    ));

        }
        protected function 
    buildTree(array $elementsint $parentId 0) : array
        {
            
    $branch = [];

            foreach (
    $elements as $element)
            {
                if ((int)
    $element['pid'] === $parentId)
                {
                    
    $children $this->buildTree($elements, (int)$element['id']);
                    if (
    $children)
                    {
                        
    $element['children'] = $children;
                    }
                    if (
    $element['pid'] === 'root')
                    {
                        
    $branch[$element['id']] = $element;
                    }
                    else
                    {
                        
    $branch[] = $element;
                    }

                }
            }

            return 
    $branch;
        }
        protected function 
    buildElements(array $elementsint $parentId 0) : array
        {
            
    $branch = [];
            
    $token System::getContainer()->get('contao.csrf.token_manager')
                ->
    getDefaultTokenValue();
            foreach (
    $elements as $element)
            {
                if ((int)
    $element['pid'] === $parentId)
                {
                    
    $children $this->buildTree($elements, (int)$element['id']);
                    
    $element['content_element'] = $this->getElement($element);

                    if (
    is_array(unserialize($element['cssId'])))
                    {
                        
    $cssId unserialize($element['cssId']) [1];
                    }
                    else
                    {
                        
    $cssId $this->cssId;
                    }

                    
    $element['css_class'] = $cssId;
                    
    $element['href_act_edit'] = 'contao?do=content&id=' $element['id'] . '&table=tl_content&act=edit';
                    
    $element['href_act_delete'] = 'contao?do=content&id=' $element['id'] . '&table=tl_content&act=delete&rt=' $token;
                    
    $element['is_content_plus'] = ($element['type'] === 'contentslider' || $element['type'] === 'grid') ? true false;
                    
    $element['href_act_edit_plus'] = 'contao?do=content&mode=plus&pid=' $element['pid'] . '&id=' $element['id'] . '&plus=' $element['type'] . '&el=' $element['el_count'];

                    if (
    $children)
                    {
                        
    $element['children'] = $children;
                    }
                    
    $branch[$element['inColumn']][] = $element;
                }
            }

            return 
    $branch;
        }

        protected function 
    getElement(array $element)
        {

            
    $objCte ContentModel::findById($element['id']);

            if (
    $objCte !== null)
            {

                
    $row $objCte;

                
    // Optional: nur wenn Spalte passt
                
    if ($row->type !== 'module' && $row->type !== 'form' && $row->type !== 'contentslider' && $row->type !== 'grid')
                {
                    
    $strClass 'Contao\\Content' ucfirst($row->type);

                }
                elseif (
    $row->type === 'module' || $row->type === 'contentslider' || $row->type === 'grid')
                {
                    
    // $row->__set('cssId',$element['css_class']);
                    
    $strClass 'Bits\\FlyUxBundle\\Content\\Content' ucfirst($row->type);

                }
                elseif (
    $row->type === 'form')
                {
                    
    $strClass 'Contao\\Form';
                }

                if (
    class_exists($strClass))
                {
                    
    /** @var \Contao\ContentElement $objElement */
                    
    $objElement = new $strClass($row);

                    return 
    $objElement->generate();
                }
            }
            else
            {
                return 
    '';
            }

        }

    }
    Das hier ist Ebene 1: mode = layout und ptable = tl_page
    Wenn du auf das Plus neben "ContentSlider" klickst kommst du auf Ebene2 um den Slider-Inhalt zu bearbeiten (ptable='tl_content' und mode=plus)
    Firefox_Screenshot_2025-04-30T14-26-09.994Z.png

    Ebene 2
    Firefox_Screenshot_2025-04-30T14-24-24.084Z.png
    Geändert von Monique Hahnefeld (30.04.2025 um 15:29 Uhr)
    Curiosity killed the cat

  8. #8
    Community-Moderator
    Wandelndes Contao-Lexikon
    Avatar von Spooky
    Registriert seit
    12.04.2012.
    Ort
    Scotland
    Beiträge
    37.158
    Partner-ID
    10107

    Standard

    Aber in Contao 5.3 hast du doch schon Nested Content Elements. Wieso brauchst du da eine eigene Lösung?
    » sponsor me via GitHub or Revolut

  9. #9
    Contao-Fan Avatar von Monique Hahnefeld
    Registriert seit
    22.11.2011.
    Ort
    Berlin
    Beiträge
    283

    Frage

    Naja mein Gedanke war das der Redakteur beim ContentSlider zum Beispiel eben kein Umschlag-Anfang und -Ende anlegen muss. Ich möchte stattdesser gerne auf eine View linken, wo x Slides als Panels zur Verfügung stehen. Der Redaktuer kann dann Inhaltselemente in die Slide-Panels generieren und auch per Drag and Drop hin und her sortieren.(Die Anzahl wird im Parent-Element eingegeben)

    Nestet Elements würde ja heisen es wäre die Struktur mit den Umschlag-Elementen oder verstehe ich das einfach nur nicht richtig?
    Curiosity killed the cat

  10. #10
    Community-Moderator
    Wandelndes Contao-Lexikon
    Avatar von Spooky
    Registriert seit
    12.04.2012.
    Ort
    Scotland
    Beiträge
    37.158
    Partner-ID
    10107

    Standard

    Zitat Zitat von Monique Hahnefeld Beitrag anzeigen
    Naja mein Gedanke war das der Redakteur beim ContentSlider zum Beispiel eben kein Umschlag-Anfang und -Ende anlegen muss.
    Nested Content Elements haben keinen Umschlag-Anfang/Ende. Die Nested Content Elements ersetzen diese Funktion.
    » sponsor me via GitHub or Revolut

  11. #11
    Contao-Fan Avatar von Monique Hahnefeld
    Registriert seit
    22.11.2011.
    Ort
    Berlin
    Beiträge
    283

    Frage

    Ja aber Nested Content Elements haben eben keine eigene View. oder?
    Welches Nestet Element kann ich mir denn mal angucken, den Content-Slider vom Core?
    Curiosity killed the cat

  12. #12
    Community-Moderator
    Wandelndes Contao-Lexikon
    Avatar von Spooky
    Registriert seit
    12.04.2012.
    Ort
    Scotland
    Beiträge
    37.158
    Partner-ID
    10107

    Standard

    Zitat Zitat von Monique Hahnefeld Beitrag anzeigen
    Welches Nestet Element kann ich mir denn mal angucken, den Content-Slider vom Core?
    • Elementgruppe
    • Content-Slider
    • Akkordeon
    » sponsor me via GitHub or Revolut

  13. #13
    Contao-Fan Avatar von Monique Hahnefeld
    Registriert seit
    22.11.2011.
    Ort
    Berlin
    Beiträge
    283

    Daumen hoch

    Ok, schau ich mir mal genauer an


    YEAH es geht doch :-)

    Firefox_Screenshot_2025-05-01T03-13-16.448Z.png
    Geändert von Monique Hahnefeld (01.05.2025 um 04:14 Uhr)
    Curiosity killed the cat

Aktive Benutzer

Aktive Benutzer

Aktive Benutzer in diesem Thema: 2 (Registrierte Benutzer: 0, Gäste: 2)

Berechtigungen

  • Neue Themen erstellen: Nein
  • Themen beantworten: Nein
  • Anhänge hochladen: Nein
  • Beiträge bearbeiten: Nein
  •