web-dev-qa-db-fra.com

Joomla / PHP Comment un plugin peut-il ajouter une classe css à la section body?

Bonjour Joomla Community,

Comment une classe css peut-elle être ajoutée au <body> de l'intérieur d'un plugin système?

Tout conseil est apprécié, merci.

6
SePröbläm

Si vous souhaitez injecter du code dans le code html (ajout d'une classe dans une balise body) à l'aide de l'événement OnAfterRender:

$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);

Note de l'éditeur:

Selon documentation Joomla , JResponse::getBody() et JResponse::setBody() sont obsolètes depuis Joomla 3.2.

3.2 Utilisez JApplicationWeb::getBody() et JApplicationWeb::setBody() à la place

En outre, regex peut être un outil peu fiable pour l'analyse HTML; PHP donne accès à plusieurs analyseurs DOM .

6
pl71

L'utilisation d'expressions régulières pour manipuler du code HTML valide n'est pas recommandée, car regex est "DOM -aware", ce qui signifie qu'il ne sait pas s'il modifie réellement une balise ou uniquement du texte qui semble comme une balise. De plus, à moins d'indication expresse de ne remplacer qu'une seule fois, il modifiera avec plaisir plusieurs chaînes correspondantes (ce qui endommagerait votre contenu). Enfin, l'utilisation de DomDocument est une technique supérieure, car elle analyse et modifie de manière intelligente/fiable un attribut de classe, quelle que soit la position de l'attribut dans la balise et le caractère utilisé pour citer la valeur (guillemets simples ou doubles).

Code: ( Démo PHP )

$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());

Et juste au cas où quelqu'un prendrait mon approbation de DOMDocument par crainte d'expressions régulières, voici comment je le coderais à l'aide d'appels de regex raffinés.

Code: ( Démo PHP ) ( Première démo Regex ) ( Deuxième démo Regex )

$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);

Mais, encore une fois, je ne recommande pas regex pour ce travail car il sera moins stable ... Imaginez si vous aviez un attribut (et ne le réalisiez pas) comme specialclass ou data-class. Alors, n'allons pas dans le gouffre du lapin pour créer une chaîne de corps qui brisera le motif, puis ajustez le motif en fonction de la vulnérabilité - utilisez simplement un analyseur DOM.

1
mickmackusa

J'ai réfléchi à cela et j'ai trouvé une solution différente. En supposant que votre plugin ait un champ appelé "classe" dans le 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);

Comme la classe/menu est déjà ajoutée au corps, nous pouvons simplement concaténer votre nouvelle classe

0
Eoin