web-dev-qa-db-fra.com

Joomla 2.5 différences dans JFormField à partir de 3.x

J'utilise un plugin pour aider à ajouter des paramètres supplémentaires aux modules. Pour ce faire, j'utilise JForm pour charger un fichier xml fourni avec divers plugins.

C’est ce que j’utilise et cela fonctionne à partir de la version 3.0, il est pris sous forme de boucle de champs et chaque "champ" est une instance de JFormField.

$field->name = 'plg_form_settings['.$field->name.']';
$content .= '<div class="control-group">';
    $content .= '<div class="control-label">';
        $content .= $field->label;
    $content .= '</div>';
    $content .= '<div class="controls">';
        $content .= $field->input;
    $content .= '</div>';
$content .= '</div>';

Comme vous pouvez le voir, cela a fonctionné en supposant que $field->name Soit public, mais en 2.5 il est protégé (il est également en 3 ce qui me déroute, il n'a jamais été travaillé dans aucune version de 3).

J'ai vérifié les différences entre JFormField dans les versions 2.5 et 3 et il existe des différences énormes, bien que d'une manière ou d'une autre je dois accéder à la propriété $field->name (Je vois que je peux faire $field->__get('name') pour un accès en lecture seule), je pouvais ignorer les fonctionnalités de JFormField mais cela semble un peu contre-productif d’ajouter une compatibilité ascendante.

Dans Joomla 3, il existe une fonction appelée __set($name,$value) mais ce n’est pas dans Joomla 2.5.

Existe-t-il un moyen "simple" de remplacer un nom de champ (ou une autre propriété) dans Joomla 2.5?

5
Jordan Ramstad

J'ai beaucoup travaillé sur ce problème et proposé une solution. C'est la manière "appropriée" de le faire, contrairement aux autres modules, mais elle est cachée derrière plusieurs couches d'objets (donc un peu difficile à comprendre).

D'abord, je pensais que le problème était dans JFormField mais ce n'était pas le cas. Il n’a pas besoin d’accéder à ces propriétés car elles "analysent" uniquement les champs n’ont pas été conçues pour donner un contrôle direct.

Donc, voici un peu de l'autre code que j'ai.

if($form->loadFile($path.'/fields.xml')){
        $fieldset = $form->getFieldset();
        //SQL STUFF HERE TO GET $result
        $result = $db->loadObject();
        if(isset($result->params)){
            $moduleParams = json_decode($result->params);
        }else{
            $moduleParams = new stdClass;
        }
        foreach($fieldset as $index=>$field){
            $field->name = 'plg_form_settings['.$field->name.']';
            $content .= '<div class="control-group">';
                $content .= '<div class="control-label">';
                    $content .= $field->label;
                $content .= '</div>';
                $content .= '<div class="controls">';
                    $content .= $field->input;
                $content .= '</div>';
            $content .= '</div>';
        }
    }

Cela boucle chaque champ dans le fieldset et retourne une instance de JFormField une classe plus ou moins lisible. Ce que vous devez faire, c'est que toutes les modifications que vous voulez faire se font via JForm lui-même.

if($form->loadFile($path.'/fields.xml')){
    $fieldset = $form->getFieldset();
    //SQL STUFF HERE TO GET $result
    $result = $db->loadObject();
    if(isset($result->params)){
        $moduleParams = json_decode($result->params);
    }else{
        $moduleParams = new stdClass;
    }
    $dataArray = array();
    //split the loop into 2, this way the data can be bound
    foreach($fieldset as $index=>$field){
        if($id!=0&&isset($moduleParams->{$index})){
            $dataArray[$index] = $moduleParams->{$index};
        }
    }
    //bind and reset to ensure it worked
    $form->bind($dataArray);
    $fieldset = $form->getFieldset();
    foreach($fieldset as $index=>$field){
        $output = '<div class="control-group">';
            $output .= '<div class="control-label">';
                $output .= $field->label;
            $output .= '</div>';
            $output .= '<div class="controls">';
                $output .= $field->input;
            $output .= '</div>';
        $output .= '</div>';
        $content .= $output;
    }
}

Comme vous pouvez le constater, j'utilise 2 boucles. L'une consiste simplement à faire correspondre un paramètre à un champ (je pourrais probablement l'améliorer en lisant en boucle l'objet réel $ moduleParams). Tandis que l'autre est le même que celui que j'avais auparavant. Entre les deux, je lie les données pour former et "réinitialise" la variable fieldset (je ne sais pas si elle est nécessaire, mais cela ne fait pas mal dans le processus de débogage. Ceci ne changera cependant que correctement la $field->value lorsque vous liez une valeur de formulaire, les autres variables sont toujours protégées.

Je suis donc venu avec une solution pour le nom, qui cette question était principalement. JForm est assez strict sur le nom car il utilise ce nom comme base pour son interaction avec d'autres objets. Il est donc préférable de ne pas le toucher pendant que JForm analyse le formulaire, mais après.

La fonction que j'ai montrée fait partie d'un "assistant", alors je l'ai déplacée à l'extérieur et dans le plugin lui-même. Depuis que je crée une chaîne html, je peux utiliser regex pour trouver/remplacer.

$regex  = '/(?:name=")([^"]*)(?:")/';
//CALL HELPER TO GET $content
$content = '<input type="text" name="cc_field"/>'; //example of part of output from helper
$content = preg_replace($regex,"name=\"cc_settings[$1]\"",$content);

Cela devrait également vous permettre de modifier le nom, en dehors des problèmes pouvant être causés par sa modification pendant que l'objet JForm analysait les champs.

1
Jordan Ramstad