web-dev-qa-db-fra.com

Création d'un type de champ de formulaire personnalisé étendu à partir d'un champ de balise standard

J'essaie de créer un type de champ de formulaire personnalisé pour mon composant. Fonctionnellement, il devrait fonctionner de la même manière que le type de champ de formulaire de balise standard, sauf que je veux stocker les balises dans ma propre table de base de données (plutôt que la table par défaut #__tags utilisée par Joomla) et que je veux forcer que toutes les balises entrées soient uniques. n'y a pas de doublons dans la base de données.

J'ai commencé par créer une nouvelle classe qui étend JFormFieldTag mais je ne sais pas trop comment procéder à partir de là.

Toute aide ou conseils seraient appréciés.

1
jptech0313

J'ai trouvé que le moyen le plus simple de procéder consiste à ne pas utiliser du tout le champ du formulaire de balise. Je sais que cela semble fou, mais lorsque vous souhaitez stocker les balises et les associations de balises dans votre propre table de base de données, il est plus facile de choisir un autre chemin.

La meilleure façon consiste à utiliser un champ de formulaire SQL qui autorise les multiples. Vous allez définir le code SQL à extraire de votre table de base de données contenant les balises. Ensuite, dans la méthode getItem () de votre modèle, récupérez les ID des balises associées à votre enregistrement et stockez-les sous forme de tableau dans la propriété appropriée pour votre objet (par exemple, $ item-> tags).

Ensuite, dans le modèle de votre vue, utilisez des fichiers JavaScirpt volés dans /layouts/joomla/html/tag.php pour que le champ se comporte comme le champ des balises. Il y a quelques variables à remplacer (sélecteur et minTermLength), mais vous devriez trouver cela assez simple. Voici le code:

jQuery(document).ready(function ($) {

        var customTagPrefix = '#new#';

        // Method to add tags pressing enter
        $('" . $selector . "_chzn input').keyup(function(event) {

            // Tag is greater than the minimum required chars and enter pressed
            if (this.value && this.value.length >= " . $minTermLength . " && (event.which === 13 || event.which === 188)) {

                // Search a highlighted result
                var highlighted = $('" . $selector . "_chzn').find('li.active-result.highlighted').first();

                // Add the highlighted option
                if (event.which === 13 && highlighted.text() !== '')
                {
                    // Extra check. If we have added a custom tag with this text remove it
                    var customOptionValue = customTagPrefix + highlighted.text();
                    $('" . $selector . " option').filter(function () { return $(this).val() == customOptionValue; }).remove();

                    // Select the highlighted result
                    var tagOption = $('" . $selector . " option').filter(function () { return $(this).html() == highlighted.text(); });
                    tagOption.attr('selected', 'selected');
                }
                // Add the custom tag option
                else
                {
                    var customTag = this.value;

                    // Extra check. Search if the custom tag already exists (typed faster than AJAX ready)
                    var tagOption = $('" . $selector . " option').filter(function () { return $(this).html() == customTag; });
                    if (tagOption.text() !== '')
                    {
                        tagOption.attr('selected', 'selected');
                    }
                    else
                    {
                        var option = $('<option>');
                        option.text(this.value).val(customTagPrefix + this.value);
                        option.attr('selected','selected');

                        // Append the option and repopulate the chosen field
                        $('" . $selector . "').append(option);
                    }
                }

                this.value = '';
                $('" . $selector . "').trigger('liszt:updated');
                event.preventDefault();

            }
        });
    });

Enfin, revenez à votre modèle et modifiez la méthode save () pour gérer les entrées de balise et stocker les données dans votre base de données. Quelque chose comme ça marche bien:

if(isset($data['tags'])){
    // store the data locally
    $tags = $data['tags'];

    // remove the data from the array
    unset($data['tags']);

    // check whether the provided tag is new or old
    $tagIds = array();
    $newtags = array();
    foreach($tags as $tag){
        if(strpos($tag, '#') !== false){
            // this is a new tag
            $newtags[] = str_replace('#new#', '', strtolower($tag));
        }else{
            // this is an existing tag
            $tagIds[] = (int)$tag;
        }
    }

    // handle any new tags
    if($newtags){

        // create the new tag records
        $query = $db->getQuery(true);
        $query->insert($db->quoteName('#__my_component_tags'));
        $query->columns($db->quoteName('tag'));
        foreach($newtags as $tag){
            $query->values($db->quote($tag));
        }
        $db->setQuery($query);
        if($db->execute()){

            // get the IDs of these tags
            $query = $db->getQuery(true);
            $query->select($db->quoteName('id'));
            $query->from($db->quoteName('#__my_component_tags'));
            $query->where($db->quoteName('tag') . ' IN(' . join(',', $db->quote($newtags)) . ')');
            $db->setQuery($query);
            if($newtagIds = $db->loadColumn()){

                // combine the new IDs with the existing ones
                $tagIds = array_merge($tagIds, $newtagIds);
            }else{
                $this->setError('Unable to retrieve IDs of newly created tags');
                return false;
            }                       
        }else{
            $this->setError('Unable to create new tags');
            return false;
        }
    }

    // associate this item with all of its selected tags, ignoring duplicates and removing 
    if($tagIds){

        // craft the SQL value strings
        $values = array();
        foreach($tagIds as $tagId){
            $values[] = '(' . (int)$tagId . ',' . (int)$table->id . ')';
        }

        // build and set the query
        $db->setQuery('INSERT INTO ' . $db->quoteName('#__my_component_tag_map') . ' (' . $db->quoteName('tag') . ',' . $db->quoteName('my_record') . ') VALUES ' . join(',', $values) . ' ON DUPLICATE KEY UPDATE ' . $db->quoteName('my_record') . ' = ' . $db->quoteName('my_record') . ';');
        if(!$db->execute()){
            $this->setError('Unable to associate tags to landing page');
            return false;
        }

        // remove all tags that are no longer associated with this record
        $query = $db->getQuery(true);
        $query->delete($db->quoteName('#__my_component_tag_map'));
        $query->where($db->quoteName('tag') . ' NOT IN(' . join(',', $tagIds) . ')');
        $query->where($db->quoteName('my_record') . '=' . (int)$table->id);
        $db->setQuery($query);
        if(!$db->execute()){
            $this->setError('Unable to remove old tag associations');
            return false;
        }
    }else{
        // remove all tags
        $query = $db->getQuery(true);
        $query->delete($db->quoteName('#__my_component_tag_map'));
        $query->where($db->quoteName('my_record') . '=' . (int)$table->id);
        $db->setQuery($query);
        if(!$db->execute()){
            $this->setError('Unable to remove all old tag associations');
            return false;
        }
    }

    // delete any tags that no longer have an association
    $db->setQuery('DELETE FROM ' . $db->quoteName('#__my_component_tags') . ' WHERE ' . $db->quoteName('id') . ' NOT IN(SELECT DISTINCT ' . $db->quoteName('tag') . ' FROM ' . $db->quoteName('#__my_component_tag_map') . ');');
    if(!$db->execute()){
        $this->setError('Unable to remove unassociated tags');
        return false;
    }
}else{
    // delete any paths that no longer have an association
    $db->setQuery('DELETE FROM ' . $db->quoteName('#__my_component_tags') . ' WHERE ' . $db->quoteName('id') . ';');
    if(!$db->execute()){
        $this->setError('Unable to remove unassociated tags');
        return false;
    }
}

J'espère que ça aide.

1
Zachary Draper