hschottm / tags

Contao tags extension
11 stars 16 forks source link

4.10 Tags lassen sich nicht mehr speichern #68

Closed Sioweb closed 3 years ago

Sioweb commented 3 years ago

Ho!

ich habe gerade das Problem, dass sich Tags nicht speichern lassen.

Das hängt wohl mit den Einstellungen in der Klasse /classes/TagField.php zusammen.

Hier steht: protected $blnSubmitInput = FALSE

Dadurch wird das Feld nicht gespeichert, aber es ist gleichzeitig nötig, damit die Tags in die Tabell tl_tags gespeichert wird?

Irgendwie scheint es noch mit 'eval' => ['isTag' => true|false] zusammen?

LG Sascha

Sioweb commented 3 years ago

Wenn ich die Klasse wie folgt umschreibe, kann ich Tags wieder abspeichern - aber ich weiß nicht, was damit dann nicht mehr funktioniert :smile:

<?php

namespace Contao;

/**
 * Contao Open Source CMS - tags extension
 *
 * Copyright (c) 2009-2016 Helmut Schottmüller
 *
 * @license LGPL-3.0+
 */

class TagField extends \TextField
{
    protected $blnSubmitInput = true;
    protected $strTagTable = "";
    protected $intMaxTags = 0;

    /**
     * Save tags to database
     * @param string
     * @return string
     */
    protected function saveTags($value)
    {
        if ($this->blnSubmitInput)
        {
            $this->import('Database');
            $this->Database->prepare("DELETE FROM tl_tag WHERE from_table = ? AND tid = ?")
                ->execute($this->table, $this->activeRecord->id);
            $tags = array_filter(trimsplit(",", $value), 'strlen');
            foreach ($tags as $tag)
            {
                $this->Database->prepare("INSERT INTO tl_tag (tid, tag, from_table) VALUES (?, ?, ?)")
                    ->execute($this->activeRecord->id, $tag, $this->table);
            }
            return "";
        }
        else return $value;
    }

    /**
     * Read tags from database
     * @return string
     */
    protected function readTags()
    {
        $arrTags = array();
        $tags = \TagModel::findByIdAndTable($this->activeRecord->id, $this->table);
        if ($tags)
        {
            while ($tags->next())
            {
                array_push($arrTags, $tags->tag);
            }
        }
        return count($arrTags) ? implode(",", $arrTags) : '';
    }

    /**
     * Add specific attributes
     * @param string
     * @param mixed
     */
    public function __set($strKey, $varValue)
    {
        switch ($strKey)
        {
            case 'isTag':
                $this->blnSubmitInput = !$varValue;
                break;
            case 'table':
                $this->strTagTable = $varValue;
                break;
            case 'value':
                $this->varValue = implode(",", array_filter(trimsplit(",", $varValue), 'strlen'));
                break;
            case 'maxtags':
                $this->intMaxTags = $varValue;
                break;

            default:
                parent::__set($strKey, $varValue);
                break;
        }
    }

    /**
     * Return a parameter
     * @return string
     * @throws Exception
     */
    public function __get($strKey)
    {
        switch ($strKey)
        {
            case 'isTag':
                return !$this->blnSubmitInput;
                break;
            case 'table':
                return strlen($this->strTagTable) ? $this->strTagTable : $this->strTable;
                break;
            case 'value':
                return '';
                break;
            case 'maxtags':
                return $this->intMaxTags;
                break;

            default:
                return parent::__get($strKey);
                break;
        }
    }

    /**
     * Generate the widget and return it as string
     * @return string
     */
    public function generate()
    {
        $taglist = new TagList($this->table);
        $taglist->maxtags = $this->intMaxTags;
        $tags = $taglist->getTagList();
        $list = '<div class="tags"><ul class="cloud">';
        foreach ($tags as $tag)
        {
            $list .= '<li class="' . $tag['tag_class'] . '">';
            $list .= '<a href="javascript:Tag.selectedTag(\'' . $tag['tag_name'] . '\', \'ctrl_' . $this->strId . '\');" title="' . $tag['tag_name'] . ' (' . $tag['tag_count'] . ')' . '">' . $tag['tag_name'] . '</a>';
            $list .= '</li> ';
        }
        $list .= '</ul></div>';
        $value = (!$this->blnSubmitInput) ? $this->readTags() : $this->varValue;
        $value = $this->readTags();
        return $list.sprintf('<input type="text" name="%s" id="ctrl_%s" class="tl_text%s" value="%s"%s onfocus="Backend.getScrollOffset();" />',
                        $this->strName,
                        $this->strId,
                        (strlen($this->strClass) ? ' ' . $this->strClass : ''),
                        specialchars($value),
                        $this->getAttributes());
    }

    /**
     * Validate input and set value
     */
    public function validate()
    {
        $varInput = $this->validator(deserialize($this->getPost($this->strName)));
        $this->saveTags(implode(",", array_filter(trimsplit(",", $varInput), 'strlen')));
        parent::validate();
    }
}
hschottm commented 3 years ago

Ja, das müsste funktionieren. Das Problem ist, dass Contao mit 4.10 die Variable blnSubmitInput zur Voraussetzung macht, dass die Validation für ein Feld aufgerufen wird und damit dann auch der Speicherprozess gestartet wird, das war bis 4.9 nicht der Fall. Da das Tag-Feld von der Erweiterung ja eigentlich gar nicht benutzt wird, um irgendwelche Daten hineinzuschreiben (ist nur 1 Byte groß), war das Feld bislang natürlich so eingestellt, dass es eigentlich bei der Datenspeicherung übergangen wird blnSubmitInput = FALSE. Der Validator ist aber trotzdem aufgerufen worden, was dann die eigentliche Speicherung in der tl_tags-Tabelle ausgelöst hat.

Der Ansatz, das Feld jetzt als Speicherbar zu machen, aber einfach nichts in das Datenbankfeld zu schreiben ist die perfekte Lösung.

hschottm commented 3 years ago

Fixed in 92469a489a3feacdb040ae083db598e0f213940a