gridblock icon indicating copy to clipboard operation
gridblock copied to clipboard

Deprecated Meldung bei Modul ohne input value

Open fietstouring opened this issue 9 months ago • 36 comments

Deprecated: htmlspecialchars_decode(): Passing null to parameter #1 ($string) of type string is deprecated in redaxo/src/core/lib/var/var.php on line 420

setze ich ein Modul ein welches keinen Input Value hat kommt diese Meldung.

fietstouring avatar Mar 27 '25 18:03 fietstouring

Arg. Alle meine Website sind voll von der Meldung und ich hab nie rausgefunden woher das kommt...

olien avatar Mar 27 '25 18:03 olien

Wenn ich richtig verstehe, dann habt Ihr ein leeres Inhaltsmodul (also nur ein Modul ohne INPUT - nur OUTPUT), welches Ihr in eine Grid-Spalte im BE einfügt - richtig? Der Fehler kommt dann im BE beim Edit oder im FE?

Nachtrag 1: Habe es gerade bei mir auf 3 verschiedenen Servern getestet. Ich bekomme diese Fehlermeldung nicht.

Einen StackTrace zum Fehler habt Ihr nicht zufällig?

Nachtrag 2: Die Funktion htmlspecialchars_decode() wird innerhalb von GB nicht genutzt. Es kann daher eigentlich nicht vom GB kommen.

iceman-fx avatar Mar 28 '25 07:03 iceman-fx

@fietstouring Wie sieht denn Dein Output-Code aus?

iceman-fx avatar Mar 28 '25 07:03 iceman-fx

Bei mir ist der dann auch "leer" weil ich das "grid" als Platzhalter nutze

Image

olien avatar Mar 28 '25 07:03 olien

@olien Und wann erscheint denn der Fehler? Beim Anlegen eines Inhaltsmoduls, beim editieren, bei der Ausgabe im FE?

Teste es bitte bei Dir nochmal, ob der Fehler wirklich bei Dir bei diesen Aktionen erscheint.

iceman-fx avatar Mar 28 '25 08:03 iceman-fx

@olien Mir ist nicht ganz klar, warum Du ein komplett leeres Modul in eine GB.Spalte setzt. Was soll dies bringen? Da kannst Du die GB-Spalte doch auch gleich leer lassen = keine Module einsetzen.

iceman-fx avatar Mar 28 '25 08:03 iceman-fx

  1. ich lasse die Spalte leer. es gibt aber auch so eineiige modul bei mir die keine eingäbe erfordern.
  2. gucke ich gleich

olien avatar Mar 28 '25 08:03 olien

  1. ok. ich habs getötete . ich bekomme die fehlte rauch wenn ich ein komplett leeres modul in einen Artikel einfüge. ist als kein gridblock Fehler. sondern mein problem. ich bin raus (sorry)

olien avatar Mar 28 '25 08:03 olien

Danke für die Rückmeldung @olien

iceman-fx avatar Mar 28 '25 09:03 iceman-fx

@iceman-fx bei mir kommt die Meldung im FE, aber nur wenn ich das Modul in Gridblock einsetze, ohne GB nicht. wenn ich ein input Feld reingebe dann kommt der Fehler nicht mehr.

fietstouring avatar Mar 31 '25 21:03 fietstouring

@fietstouring Was hast Du denn für einen Output-Code im Modul?

iceman-fx avatar Apr 01 '25 05:04 iceman-fx

@iceman-fx ich habe den Ausgabe-Code zum Testen auskommentiert und bekam den Fehler immer noch.

fietstouring avatar Apr 01 '25 06:04 fietstouring

Was passiert denn, wenn Du einfach nur ein leere GB anlegst - ohne Inhaltsmodule? Auch den cache mal geleert?

iceman-fx avatar Apr 01 '25 06:04 iceman-fx

Hi, dann passiert nichts. Der Fehler kommt nur wenn der Input des Moduls keinen Value hat.

fietstouring avatar Apr 01 '25 06:04 fietstouring

Dann muss aber etwas im Output des Moduls drin sein. Denn nur dieser wird im FE ausgegeben.

Wenn Du mir den Output nicht bereitstellen willst - OK. Dann teste bitte noch einmal folgendes. Input so belassen wie es ist - ohne Value - und den Output des Moduls komplett löschen (nicht aus kommentieren).

Alternativ kannst Du mir auch gern einen Zugang zum CMS zukommen lassen, damit ich selber einmal schauen kann.

iceman-fx avatar Apr 01 '25 06:04 iceman-fx

habe jetzt ein komplett leeres Modul angelegt und der Fehler erscheint nach wie vor.

fietstouring avatar Apr 01 '25 10:04 fietstouring

Ohne einen Zugang zu Deinem CMS werde ich das leider nicht nachvollziehen können.

iceman-fx avatar Apr 01 '25 11:04 iceman-fx

ok schicke dir gerne einen Zugang kein Problem, über welchen Kanal soll ich es schicken?

fietstouring avatar Apr 01 '25 11:04 fietstouring

Bist Du im Redaxo Slack-Channel? Dort wäre es am einfachsten.

iceman-fx avatar Apr 01 '25 12:04 iceman-fx

Könnt ihr da mal testen bitte

Image

Image

/*
	Redaxo-Addon Gridblock
	Grid-Basisklasse
	v1.1.9
	by Falko Müller @ 2021-2023 (based on 0.1.0-dev von bloep)
*/

class rex_gridblock {

	private static $isBackend = false;		//bool
	private static $identifier = '/* GRID_MODULE_IDENTIFIER | DONT REMOVE */';
	
	public $sliceID = 0;					//int
	public $artID = 0;						//int
	public $tmplID = 0;						//int
	public $clangID = 0;						//int
	public $ctypeID = 0;					//int -> ist aktuell nicht auslesbar !!!
	
	public $rexVars = [];					//array -> ctypeID ist aktuell nicht verfügbar !!!
	
    public $ingoredModules = [];			//array
	public $allowedModules = [];			//array
    private $values = [];					//array
    private $modules = [];					//array

	public $maxCols = 12;					//int
	

    public function getModules()
	{
		//Standard-Modulauswahl holen
		$config = rex_addon::get('gridblock')->getConfig('config');
		if (!empty($config['modules'])):
			if (@$config['modulesmode'] == 'ignore'):
				$this->ignoreModule(explode("#", $config['modules']));
			else:
				$this->allowModule(explode("#", $config['modules']));
			endif;
		endif;
		
		//Modulauswahl setzen
		$where_im = (count($this->ingoredModules) > 0 ? 'id not in ('.join(',', $this->ingoredModules).')' : '');
		$where_am = (count($this->allowedModules) > 0 ? 'id in ('.join(',', $this->allowedModules).')' : '');
			
		$where = "";	
			$where .= (!empty($where_im)) ? " AND $where_im" : '';
			$where .= (!empty($where_am)) ? " AND $where_am" : '';
		$where = (!empty($where) || @$config['modulesmode'] == 'ignore') ? 'input NOT LIKE "%/* GRID_MODULE_IDENTIFIER | DONT REMOVE */%" '.$where : '0';
		
		//Module aus DB holen und zwischenspeichern
		$sql = 'SELECT id, name, output, input FROM '.rex::getTable('module').' WHERE '.$where.' ORDER BY name, id';
		$db = rex_sql::factory();
		$db->setQuery($sql);

        $modules = [];
        while ($db->hasNext()):
            $modules[$db->getValue('id')] = [
                'name' => $db->getValue('name') ?? '',
                'output' => $db->getValue('output') ?? '',
                'input' => $db->getValue('input') ?? '',
            ];
			
            $db->next();
        endwhile;
		
		if (rex::isBackend()) { $_SESSION['gridAllowedModules'] = $modules; }
        return $modules;
    }
	

    public function ignoreModule($moduleID)
	{
		$this->checkModule($moduleID, 'ignore');
    }


    public function allowModule($moduleID)
	{
		$this->checkModule($moduleID, 'allow');
    }


    private function checkModule($moduleID, $type = 'allow')
	{
		if (is_array($moduleID)):
			foreach ($moduleID as $mid):
				if (!empty($mid)):
					if ($type == 'ignore'):
						$this->ingoredModules[] = (int) $mid;
					else:
						$this->allowedModules[] = (int) $mid;
					endif;
				endif;
			endforeach;
		
		elseif (is_int($moduleID)):
			if ($type == 'ignore'):
				$this->ingoredModules[] = (int) $moduleID;
			else:
				$this->allowedModules[] = (int) $moduleID;
			endif;
		endif;
    }
	

	//gesamten Modulinput (Rex-BE) holen und ausgeben
    public function getModuleInput()
	{
        $this->modules = self::getModules();
        $cols = [];

		for ($i = 1; $i <= $this->maxCols; ++$i):
            $cols[$i] = ['content' => $this->genCol($i)];
        endfor;

        $fragment = new rex_fragment();
		$fragment->setVar('maxCols', $this->maxCols, false);
        $fragment->setVar('cols', $cols, false);
        $fragment->setVar('values', $this->values, false);
		$fragment->setVar('rexVars', $this->rexVars, false);
		
        return $fragment->parse('gridblock/module_input.php');
    }
	

	//gesamten Spalteninput (Rex-BE) holen und ausgeben
    private function genCol($id)
	{
        $fragment = new rex_fragment();
        $fragment->setVar('id', $id, true);
        $fragment->setVar('modules', $this->modules, false);
        $fragment->setVar('values', $this->safeValues($this->values), false);
		$fragment->setVar('rexVars', $this->rexVars, false);

		self::$isBackend = true;
        return $fragment->parse('gridblock/column.php');
    }


    public function getSliceValues($sliceID)
    {
		$sliceID = intval($sliceID);
		$this->rexVars['sliceID'] = (int) $sliceID;
		
		$art = rex_article::get(rex_article::getCurrentId());
		if ($art):
			$this->rexVars['artID'] = (int) $art->getId();
			$this->rexVars['tmplID'] = (int) $art->getTemplateId();
			$this->rexVars['clangID'] = (int) $art->getClangId();
			$this->rexVars['ctypeID'] = rex_request('ctype', 'int');
			$this->rexVars['revision'] = 0;
			if (rex::isBackend() && rex::getProperty('login')):
				$this->rexVars['revision'] = (int) @rex::getProperty('login')->getSessionVar('rex_version_article')[rex_article::getCurrentId()];
			endif;
		else:
			$this->rexVars['artID'] = $this->rexVars['tmplID'] = $this->rexVars['clangID'] = $this->rexVars['revision'] = 0;
		endif;
		
		$_SESSION['gridRexVars'] = $this->rexVars;
		//dump($_SESSION['gridRexVars']);
		
        $sql = rex_sql::factory();
        $sql->prepareQuery('SELECT value1, value2, value3, value4, value5, value6, value7, value8, value9, value10, value11, value12, value13, value14, value15, value16, value17, value18, value19, value20 FROM '.rex::getTable('article_slice').' WHERE id = ?');
        $sql->execute([$sliceID]);
		
        if ($sql->hasNext()):
            $this->values = [];
			
            for ($i = 1; $i <= 20; ++$i):
                $this->values[$i] = $sql->getValue('value'.$i) ?? '';
            endfor;
        endif;
    }


	//gesamten Moduloutput (Rex-BE + FE) holen und ausgeben
    public function getModuleOutput()
	{
        $fragment = new rex_fragment();
        $fragment->setVar('maxCols', $this->maxCols, false);
		$fragment->setVar('values', $this->safeValues($this->values), false);
		$fragment->setVar('rexVars', $this->rexVars, false);
		
        return $fragment->parse('gridblock/module_output.php');
    }
	

    public static function getBlankValues()
	{
        $values = [];
		
        for ($i = 1; $i <= 20; ++$i):
            $values['value'.$i] = '';
        endfor;
		
        for ($i = 1; $i <= 10; ++$i):
            $values['media'.$i] = '';
        endfor;
		
        for ($i = 1; $i <= 10; ++$i):
            $values['medialist'.$i] = '';
        endfor;
		
        for ($i = 1; $i <= 10; ++$i):
            $values['link'.$i] = '';
        endfor;
		
        for ($i = 1; $i <= 10; ++$i):
            $values['linklist'.$i] = '';
        endfor;
		
        return $values;
    }


    public static function getConfig($sKey=null)
	{
        $aConfig = rex_addon::get('gridblock')->getConfig('config');
        if ($sKey != "") {
            return isset($aConfig[$sKey]) ? $aConfig[$sKey] : '';
        }
        return $aConfig;
    }
	

	public static function getSettings()
	{
		//alle Settings aus Property auslesen
		$settings = rex_addon::get('gridblock')->getProperty('REX_GRID_SETTINGS');
		
		return $settings;
	}
	

	//prüfen ob im Editmode des Gridblock (BE)
	public static function isBackend($override = false)
	{
		if ($override) { self::$isBackend = true; }
		return (rex::isBackend() && self::$isBackend) ? true : false;
	}
	

	//prüfen ob Modul das Gridblock-Modul ist
	public static function isGridblockModule($moduleID = 0)
	{
		$return = false;
		$id = intval($moduleID);
		
		if ($id > 0):
			$db = rex_sql::factory();
			$db->setQuery('SELECT id FROM '.rex::getTable('module').' WHERE id = "'.$id.'" AND (input LIKE "%'.self::$identifier.'%" OR output LIKE "%'.self::$identifier.'%")');

			$return = ($db->hasNext()) ? true : false;
		endif;
		
		return $return;
	}
	

	//alle Gridblock-Module holen
	public static function getGridblockModules()
	{
		$db = rex_sql::factory();
		$db->setQuery('SELECT id, `key`, name FROM '.rex::getTable('module').' WHERE (input LIKE "%'.self::$identifier.'%" OR output LIKE "%'.self::$identifier.'%")');
		
		$result = $db->getArray();
		
		// Stellen sicher, dass keine NULL-Werte zurückgegeben werden
		foreach ($result as &$module) {
			$module['id'] = $module['id'] ?? '';
			$module['key'] = $module['key'] ?? '';
			$module['name'] = $module['name'] ?? '';
		}
		
		return $result;
	}
	
	// Hilfsfunktion, um NULL-Werte in Werte-Arrays zu ersetzen
	private function safeValues($values)
	{
		if (!is_array($values)) {
			return [];
		}
		
		$safeValues = [];
		foreach ($values as $key => $value) {
			$safeValues[$key] = $value ?? '';
		}
		
		return $safeValues;
	}
}
?>

olien avatar Apr 04 '25 08:04 olien

@olien Das checke ich nächste Woche gern mal. Aber kannst Du mir noch einmal ganz genau das Testszenario aufführen, um diese Meldungen zu reproduzieren (bitte sehr sehr detailliert)?

Nur mit einem leeren Input und/oder Output im Modul passiert bei mir nix.

iceman-fx avatar Apr 04 '25 08:04 iceman-fx

Puh. würde ich gerne. ich habe in meinen Modulinputs oft stehen "Keine Eingabe notwendig". Vielleicht ist aber auch ein Fehler im Moduloutput der eine leere Var erzeugt schuld? Muß grad passen. Aber mit den Änderungen oben habe ich keine Fehler mehr...

olien avatar Apr 04 '25 08:04 olien

Einen Namen/Titel haben die Module aber alle?

iceman-fx avatar Apr 04 '25 09:04 iceman-fx

ja

olien avatar Apr 04 '25 09:04 olien

@olien Wie kann denn bei Dir ein NULL in den besagten Spalten des Moduls stehen? Die Spalten name, input, ouput sind doch immer Strings lt. DB. Wenn dort NULL drin steht, dann doch eigentlich als String.

iceman-fx avatar Apr 07 '25 06:04 iceman-fx

@olien #2 Hast Du vorher mal gecheckt, ob da wirklich NULL zurückgegeben wird?

iceman-fx avatar Apr 07 '25 06:04 iceman-fx

Weiß nicht. Mform vielleicht?

olien avatar Apr 07 '25 06:04 olien

Welche PHP-Version und Rex-Version nutzt Du eigentlich, dort wo die Fehlermeldungen kommen?

iceman-fx avatar Apr 07 '25 06:04 iceman-fx

meist php 8.3.x und alle recht aktuellen READXO Versionen

olien avatar Apr 07 '25 06:04 olien

@olien Wenn Du mir bei Dir mal einen Zugang geben kannst, dann würde ich es mit mal live bei Dir anschauen wollen.

MForm kann es ja auch nicht sein, da ja dann eine gültige Modulausgabe da wäre.

iceman-fx avatar Apr 07 '25 07:04 iceman-fx