it-swarm.com.de

Joomla / PHP Wie kann ein Plugin eine CSS-Klasse an den Body-Abschnitt anhängen?

Hallo Joomla Community,

Wie kann eine CSS-Klasse in einem System-Plugin an <body> Angehängt werden?

Jeder möglicher Rat wird geschätzt, danke.

6
SePröbläm

Wenn Sie mit dem Ereignis OnAfterRender Code in den HTML-Code einfügen möchten (Klasse in Body-Tag einfügen):

$content= JFactory::getApplication()->getBody();
/* your modification of $content here */
if (preg_match('/(<body.*?)(class *= *"|\')(.*)("|\')(.*>)/', $content))
{
    $content = preg_replace(
        '/(<body.*?)(class *= *"|\')(.*)("|\')(.*>)/',
        '$1$2$3 new_class$4$5',
        $content);
} 
elseif (preg_match('/(<body.*?)(>)/', $content))
{
    $content = preg_replace(
        '/(<body.*?)(>)/',
        '$1 class ="new_class">',
        $content);
}
JFactory::getApplication()->setBody($content);

Anmerkung des Herausgebers:

Laut Joomla Documentation sind JResponse::getBody() und JResponse::setBody() seit Joomla 3.2 veraltet.

3.2 Verwenden Sie stattdessen JApplicationWeb::getBody() und JApplicationWeb::setBody()

Außerdem kann Regex ein unzuverlässiges Tool zum Parsen von HTML sein. PHP bietet Zugriff auf mehrere DOM-Parser .

6
pl71

Die Verwendung regulärer Ausdrücke zum Manipulieren von gültigem HTML ist nicht ratsam, da reguläre Ausdrücke "DOM-unbewusst" sind, was bedeutet, dass sie nicht wissen, ob sie tatsächlich ein Tag oder nur Text ändern, der scheint wie ein Tag ist. Wenn Sie nicht ausdrücklich dazu aufgefordert werden, nur einmal zu ersetzen, werden mehrere übereinstimmende Zeichenfolgen geändert (wodurch Ihr Inhalt effektiv beschädigt wird). Schließlich ist die Verwendung von DomDocument eine überlegene Technik, da sie ein Klassenattribut unabhängig von der Position des Attributs im Tag und unabhängig von dem Zeichen, mit dem der Wert in Anführungszeichen gesetzt wird (einfache oder doppelte Anführungszeichen), intelligent/zuverlässig analysiert und modifiziert.

Code: ( PHP Demo )

$new_class = "new_class_attr";

$body = JFactory::getApplication()->getBody();

$dom = new DOMDocument; 
$dom->loadHTML($body, LIBXML_HTML_NOIMPLIED | LIBXML_HTML_NODEFDTD);
$bodytag = $dom->getElementsByTagName('body')->item(0);
if ($bodytag->hasAttribute("class")) {
    $new_class = $bodytag->getAttribute("class") . " " . $new_class;
}
$bodytag->setAttribute("class", $new_class);
JFactory::getApplication()->setBody($dom->saveHTML());

Und für den Fall, dass jemand aus Angst vor regulären Ausdrücken mein Indossament von DOMDocument verwechselt, hier ist, wie ich es mit raffinierten Regex-Aufrufen verschlüsseln würde.

Code: ( PHP Demo ) ( Erste Regex Demo ) ( Zweite Regex Demo )

$new_class = "new_class_attr";

$body = JFactory::getApplication()->getBody();

$body = preg_replace('~<body[^>]*class *= *["\']\K~', "$new_class ", $body, 1, $count);  // add to existing class attribute
if (!$count) {
    $body = preg_replace('~<body\K~', " class=\"$new_class\"", $body, 1);  // create class with attribute
}
JFactory::getApplication()->setBody($body);

Aber ich empfehle auch hier nicht, Regex für diesen Job zu verwenden, da er weniger stabil ist. Stellen Sie sich vor, Sie hätten ein Attribut wie specialclass oder data-class. Schauen wir also mal, lassen Sie uns nicht in die Irre gehen, indem wir einen Body-String erstellen, der das Muster zerstört, und dann das Muster anpassen, um es der Sicherheitsanfälligkeit anzupassen - verwenden Sie einfach einen DOM-Parser.

1
mickmackusa

Ich habe darüber nachgedacht und mir eine andere Lösung ausgedacht. Angenommen, Ihr Plugin hat ein Feld namens "class" in der XML.

$app = JFactory::getApplication();
$appParams = $app->getParams();

$class = "";
if ($this->params['class'])
{
    $class = $this->params['class'];
}

$pageClass = $appParams['pageclass_sfx'];
if(!empty($pageClass)) 
{
    $class = " " . $this->params['class'];
}
else 
{
    $class = $this->params['class'];
}
$pageClass = $pageClass . $class;
$app->setParams($pageClass);

Da die Menü-/Seitenklasse bereits zum Hauptteil hinzugefügt wurde, können wir Ihre neue Klasse einfach verketten

0
Eoin