Extension:JsonConfig

From mediawiki.org
This page is a translated version of the page Extension:JsonConfig and the translation is 100% complete.
Manuel des extensions MediaWiki
JsonConfig
État de la version : stable
Implémentation ContentHandler , MyWiki
Description Fournit un système de paramètrage JSON basé sur wiki
Auteur(s) Yuri Astrakhan (yurikdiscussion)
Dernière version 1.1.1
Politique de compatibilité Versions ponctuelles alignées avec MediaWiki. Le master n'est pas compatible arrière.
MediaWiki 1.38+
Modifie la base
de données
Non
Licence Licence publique générale GNU v2.0 ou supérieur
Téléchargement
RFC

  • $wgJsonConfigs
  • $wgJsonConfigModels
Téléchargements trimestriels 302 (Ranked 20th)
Utilisé par les wikis publics 897 (Ranked 264th)
Traduire l’extension JsonConfig sur translatewiki.net si elle y est disponible
Problèmes Tâches ouvertes · Signaler un bogue

L'extension JsonConfig permet aux autres extensions de stocker leurs données de configuration en tant que blob JSON à l'intérieur d'une page wiki.

Fonctionnalités disponibles et cas d'utilisation

Exemple d'affichage JSON généré par l'extension JsonConfig
  • Vous pouvez utiliser JsonConfig pour stocker les données de plusieurs façons :
    • dans une page de configuration unique, par exemple la liste des paramètres de votre extension de Config:MyExtSettings (Config étant l'espace de noms par défaut associé à l'extension JsonConfig);
    • dans un ensemble de pages ayant une structure similaire stockées dans leur propre espace de noms, par exemple les adresses IP des proxy connus ou les schémas des journaux d'événements nommés "Proxy:Opera", ou les schémas nommés Schema:AccountCreation
    • pour l'utiliser simplement pour les pages dont les titres répondent au motif d'une expression régulière, par exemple Config:Proxy:Opera ou Config:Opera.proxy. ce qui évite d'encombrer les wikis avec de multiples espaces de noms, un par modèle de contenu.
  • Vous pouvez fournir une classe de contenu pour faire la validation des données (après le JSON valide) et la normalisation.
  • Vous pouvez fournir une classe de visualisation pour personnaliser l'affichage du HTML.
  • Vous pouvez stocker des données :
    • données par wiki, données par grappe (cluster), ou même données par famille (structure différente de la clé du cache pour le cache mémoire partagé);
    • dans un wiki publique ou privé et accédé à l'aide d'informations personnelles;
    • dans une grappe séparée, en réalisant la notification à distance en cas de modification.

Utilisation sur les wikis

Actuellement

  • Ensembles communs de données de type tableaux
  • Ensembles communs de données de type cartes
  • Configurations de tableaux de bord Dashiki
  • Autres ?

Précédemment

Installation

  • Téléchargez et placez le(s) fichier(s) dans un répertoire appelé JsonConfig dans votre dossier extensions/.
    Les développeurs et les contributeurs au code doivent à la place installer l'extension à partir de Git en utilisant:cd extensions/
    git clone https://gerrit.wikimedia.org/r/mediawiki/extensions/JsonConfig
  • Ajoutez le code suivant à la fin de votre fichier LocalSettings.php  :
    wfLoadExtension( 'JsonConfig' );
    
  • Configurer si nécessaire.
  • Yes Fait – Accédez à Special:Version sur votre wiki pour vérifier que l'extension a bien été installée.

Configuration

$wgJsonConfigs

Cette variable définit les profils pour chaque type de page de configuration. $wgJsonConfigs est un tableau associatif de sous-tableaux dont chacun contient zéro ou plusieurs des paramètres suivants. Par défaut, JsonConfig utilise la clé en chaîne de caractères comme ID du modèle représenté par ce profil, mais si vous voulez réutiliser le même ID de modèle dans plusieurs profils, vous pouvez la réécraser à l'aide du paramètre model .

paramètre type par défaut description
model string (clé dans $wgJsonConfigs) ID du modèle à utiliser pour créer une nouvelle page. Si aucune valeur n'est fournie, la clé du tableau de ce profil devient l'ID du modèle. Si cette valeur est initialisée à null, l'ID du module prédéfini JsonConfig sera utilisé. L'ID du modèle doit également être listé dans $wgJsonConfigModels sauf pour null et 'JsonConfig'.
namespace int NS_CONFIG (482) Espace de noms dans lequel ces configurations vont se trouver, ou 'Config:' par défaut
nsName string/false Pour un espace de noms qui n'est pas celui par défaut (autre que NS_CONFIG 482) , donnez lui un nom canonique (anglais). Si plus d'un tableau $wgJsonConfigs utilise le même espace de noms, ne définissez ce nom qu'une fois. S'il n'est pas trouvé, un avertissement sera retourné et l'espace de noms recevra automatiquement le nom « ConfigNNN ». Dans le cas où cette configuration n'est pas stockée localement, nsName sera utilisé en tant qu'espace de noms distant, sans déclaration locale.

Si vous voulez partager l'espace de noms avec d'autres pages de contenu qui ne sont pas JsonConfig, initialisez cette valeur à false.

nsTalk string nsName+_talk Pour les espaces de noms qui ne sont pas ceux par défaut, leur page de discussion reçoit un nom canonique (anglais).
pattern string (all) Expression régulière pour détecter le titre de page dans l'espace de noms donné. Si vide, le paramètre s'applique à toutes les pages de l'espace de noms. Pour retrouver le comportement de l'ancien sous-espace, pour isSubspace=true, utilisez le motif ^/^name:./ , et pour isSubspace=false, utilisez le motif /^name$/ .
isLocal bool true Si la valeur est true, ce paramètre ne sera pas partagé sur la grappe, mais plutôt chaque wiki aura un paramètre local. Si false, cette configuration est partagée avec plusieurs wikis, et pour qu'elle soit particulière à un wiki, vous devez la stocker localement et initialiser le champ 'store'.
Cette indication impacte la clé du cache, et donc une page de configuration avec le même nom sera partagée en mémoire cache si ce paramètre est à false, mais sera unique par wiki si la valeur est true.
cacheExp int 24*60*60 Durée (en secondes) pendant laquelle la valeur doit rester dans le cache mémoire
cacheKey string Si la valeur est définie, ajoute cette chaîne à la clé du cache. Utilisez cacheKey pour invalider les valeurs en cache précédentes - par exemple quand vous faites une modification incompatible qui modifie les valeurs du cache et que vous vous inquiétez de ne pas pouvoir revenir en arrière. Cette clé peut être également utilisée pour permettre à tous les wikis de langues d'une même famille de partager les mêmes valeurs en cache, figurant dans la même page mais sur des wikis différents. Par exemple, Wikipedia peut utiliser « wp » et Wikiquotes peut utiliser « wq ».
flaggedRevs bool false Si la valeur est true, on essaie de récupérer la dernière version qui a été vérifiée par l'extension des révisions marquées. Si la valeur est null, la révision marquée sera vérifiée et utilisée quand elle est disponible. Si la valeur est false, on utilise toujours la dernière version.
remote array Un objet avec des paramètres décrivant comment accéder à la configuration à partir d'un autre wiki. Doit être présent si 'store' n'est pas initialisé, et si isLocal vaut false.
  ‑ url string Point d'accès de l'API (qui n'est pas celui par défaut) pour récupérer la configuration à partir d'un wiki distant, uniquement pour ce profil de configuration. Si non spécifié, $wgJsonConfigApiUri est utilisé.
  ‑ username string S'il est fourni il est utilisé pour s'authentifier sur le dépot de configuration distant.
  ‑ password string Voir username.
store array Initialisez cette valeur à true ou avec un tableau, pour que le wiki actuel héberge ces données de configuration. Cette valeur sera remplie automatiquement si elle est absente et isLocal vaudra true.
  ‑ cacheNewValue bool true Indique l'impact du changement des paramètres sur le contenu du cache. Si false, les valeurs en cache sont supprimées ce qui oblige les autres wiki à les redemander. true rafraîchit le cache avec la nouvele valeur. Ceci est surtout utile lorsque le wiki qui stocke ces paramètres et les wikis qui les récupèrent, partagent le même cache. Notez bien que dans le cas de false, si le wiki consommateur demande la nouvelle valeur trop rapidement, il est possible qu'il la récupère d'une base de données esclave obsolète.
  ‑ notifyUrl string Spécifiez en option l'URL de l'API distante qui sera appelée lorsque lors des changements de configuration.
  ‑ notifyUsername string Nom d'utilisateur optionnel à utiliser avec notifyUrl
  ‑ notifyPassword string Mot de passe optionnel à utiliser avec notifyUrl

$wgJsonConfigModels

Cette variable déclare l'ID du modèle géré par chacune des classes de contenu personnalisées. La même classe de contenu peut gèrer plusieurs ID de modèles. Toutes les classes de contenu doivent dériver de la classe JCContent ; si le modelID correspond à null, alors la classe par défaut JCContent prend en charge l'ID du modèle.

Exemple :

$wgJsonConfigModels['Config.MyExtSettings'] = 'MyExt\MyContentClass';

Si vous implémentez une classe séparée pour la génération du HTML, vous pouvez spécifier votre modèle de configuration comme un tableau avec une classe supplémentaire view :

$wgJsonConfigModels['Config.MyExtSettings'] = [
    'class' => 'MyExt\MyContentClass',
    'view'  => 'MyExt\MyContentViewClass', // easier to extend JCDefaultObjContentView or JCDefaultContentView
];

Exemples

Avant la version 1.0.0, JsonConfig utilisait les valeurs name et isSubspace pour personnaliser les pages qui appartenaient au modèle de contenu concerné. Les deux ont été supprimés en version 1.0.0 et remplacés par le paramètre pattern qui accepte une expression régulière. Vérifiez que vos motifs sont bien délimités avec les symboles ^ et $ , et ajoutez des barres obliques (style PHP)

Hello World

Le cas le plus simple est une page de paramètres unique sans aucune validation stockée localement sur chaque wiki. Ajoutez simplement ces déclarations à LocalSettings.php

// Content model is 'JsonConfig.MySettings'
// Model class is set to NULL to allow non-validated data
$wgJsonConfigModels['JsonConfig.MySettings'] = null;

$wgJsonConfigs['JsonConfig.MySettings'] = array(
  'pattern' => '/^MySettings$/', // Page name in Config namespace
);

Ci-dessus, l'espace de noms Config est activé sur le wiki local, mais il ne permet de créer à l'intérieur, que la page Config:MySettings, et aucune autre page. Vous pouvez stocker dans la page, des données JSON correctement formatées.

Pour lire les données de MySettings en PHP, utilisez un objet TitleValue pour accéder à la page, puis demandez son contenu :

use JsonConfig\JCSingleton;
$tv = new TitleValue( NS_CONFIG, 'MySettings' ); // DB Key
$content = JCSingleton::GetContent( $tv );
if ( $content->isValid() ) {
    $data = $content->getData();
    ...
}

Prend en charge les modèles Wikimedia

Certains modèles tels que (par exemple Template:TNT) des projets Wikimedia nécessitent JsonConfig pour prendre en charge l'espace de noms 'Data' sur Commons pour mw.ext.data.get. Vous pouvez utiliser la configuration suivante pour prendre en charge ce cas d'utilisation.

wfLoadExtension( 'JsonConfig' );

$wgJsonConfigEnableLuaSupport = true; // required to use JsonConfig in Lua
$wgJsonConfigModels['Tabular.JsonConfig'] = 'JsonConfig\JCTabularContent';
$wgJsonConfigs['Tabular.JsonConfig'] = [ 
        'namespace' => 486, 
        'nsName' => 'Data',
        // page name must end in ".tab", and contain at least one symbol
        'pattern' => '/.\.tab$/',
        'license' => 'CC0-1.0',
        'isLocal' => false,
];

$wgJsonConfigModels['Map.JsonConfig'] = 'JsonConfig\JCMapDataContent';
$wgJsonConfigs['Map.JsonConfig'] = [ 
        'namespace' => 486,
        'nsName' => 'Data',
        // page name must end in ".map", and contain at least one symbol
        'pattern' => '/.\.map$/',
        'license' => 'CC0-1.0',
        'isLocal' => false,
];
$wgJsonConfigInterwikiPrefix = "commons";

$wgJsonConfigs['Tabular.JsonConfig']['remote'] = [ 
        'url' => 'https://commons.wikimedia.org/w/api.php'
];
$wgJsonConfigs['Map.JsonConfig']['remote'] = [
        'url' => 'https://commons.wikimedia.org/w/api.php'
];

Congurations multiples partagées au sein d'une grappe

Si nous décidons de stocker les adresses IP des proxy de confiance dans les pages « Config:Proxy:SomeName » sur Meta-Wiki et de partager ces données avec la grappe.

// All wikis must have this configuration:
$wgJsonConfigs['JsonConfig.Proxy'] = [
  'pattern' => '/^Proxy\:./', // require at least one letter after the ':'
  'isLocal' => false,
];

// The LocalSettings.php for all wikis except Meta-Wiki will set this URL to Meta-Wiki's API endpoint:
$wgJsonConfigs['JsonConfig.Proxy']['remote'] = 'http://meta.wikimedia.org/w/api.php';

// LocalSettings.php for Meta-Wiki will indicate that the data should be stored there
$wgJsonConfigs['JsonConfig.Proxy']['store'] = true;

Si par contre vous voulez avoir un espace de noms spécifique pour les proxy, les paramètres seront changés en :

$wgJsonConfigs['JsonConfig.Proxy'] = [
  'namespace' => NNN, // NNN is the number you would reserve for Proxy namespace
  'nsName' => 'Proxy', // Canonical namespace name
];

Validation

Souvent on souhaite aussi avoir une classe de contenu personnalisée avec sa propre validation. Les pages JSON sont gérées par les classes de contenu qui dérivent de JCContent. La classe de contenu est responsable de l'analyse syntaxique et de la validation du texte brut. JCContent ne fait aucune validation au-delà de l'analyse JSON, mais vous pouvez choisir d'en dériver et de redéfinir JCContent::validate(). Encore mieux, vous pouvez dériver la classe JCObjContent qui fournit un nombre de primitives de validation, et redéfinir seulement JCObjContent::validateContent().

// This should be done on all wikis, including Meta-Wiki
$wgJsonConfigModels['JsonConfig.Proxy'] = 'ProxyExt\ProxyContent';

Grâce à cette documentation, supposons que la page de configuration du proxy qui décrit les serveurs Opera Mini possède ces formats :

{
    "enabled": true,
    "comment": "See http://... for updates",
    "ips": [
        '37.228.104.0/21',
        ...
    ]
}

Voici la classe de contenu pour valider ces données.

use JsonConfig\JCObjContent;
use JsonConfig\JCValidators;

class ProxyContent extends JCObjContent {

    /**
     * Derived classes must implement this method to perform custom validation
     * using the check(...) calls
     */
    public function validateContent() {
        // 'enabled' must be a boolean, true by default.
        // JCValidators::* already handle localized error messages
        $this->testOptional( 'enabled', true, JCValidators::isBool() );
        // an optional field 'comment' of type string
        $this->testOptional( 'comment', '', JCValidators::isString() );
        // 'ips' must be a list of valid CIDR ranges
        // field is not optional when default value would not pass validation
        $this->test( 'ips', self::getIpValidator() );
    }

    private static function getIpValidator() {
        // JCValue $value is a value of the field being checked wrapped with the status information.
        //              $v->getValue() actual value being examined
        //              $v->isMissing() if the value is not present in the data
        //              $v->defaultUsed() if the value did not exist and a default was supplied
        // array $path the location of this field in the hierarchy - each value is either string or an int
        // JCObjContent $self - this object, useful to get access to other fields via $self->getField()
        // You may modify the value stored inside, set additional flags, or report an error
        // using the $v->error( $key, $path, ... ) function
        return function ( JCValue $value, array $path, JCObjContent $self ) {
            $isErr = false;
            $v = $value->getValue();
            if ( is_string( $v ) ) {
                // user supplied a single string, treat as an non-assoc array
                $v = array( $v );
            } else {
                // ensure that $v is an non-assoc array, and all of its values are strings
                $isErr = !JCUtils::isList( $v ) || !JCUtils::allValuesAreStrings( $v );
            }
            if ( !$isErr ) {
                // @todo: do the rest of the IP validation and set $isErr to true on failure
            }
            // Error message might be in this form:
            // "Parameter \"$1\" must be an array of valid non-restricted (no private networks) CIDR IP blocks"
            if ( $isErr ) {
                $value->error( 'my-proxyconfig-err-ips', $path );
            } else {
                $value->setValue( $v );
            }
        };
    }
}

Personnaliser le comportement sur le wiki de stockage

Vous pouvez aussi personnaliser l'affichage et la création de page sur le wiki de stockage (Meta-Wiki dans l'exemple ci-dessus). Deux moyens pour faire cela  : soit dans votre classe dérivée de JCContent, soit par une classe « view » séparée qui dérive de JCContentView. La seconde approche est préférable car elle sépare clairement l'architecture, et la classe de visualisation n'a besoin d'exister uniquement que sur le wiki de stockage (c'est à dire Meta-Wiki) et non pas sur tous les wikis qui utilisent les données.

Pour redéfinir la valeur par défaut dans la classe dérivée de JCContent, redéfinissez le constructeur et initialisez la valeur $text avec la nouvelle valeur par défaut si la valeur d'entrée est NULL, avant de la passer au constructeur du parent. Pour substituer la génération du HTML, réécrasez JCContent::getHtml().

En suivant la méthode recommandée, créez une classe de visualisation qui dérive de JCContentView ou d'une classe avec plus de fonctionnalités JCDefaultContentView. Pour JCContentView, vous devrez implémenter valueToHtml() et getDefault(). Par défaut, la vue est implémentée par la classe JCDefaultContentView, qui peut aussi être utilisée comme base personnalisable si vous avez besoin simplement d'ajustements mineurs concernant l'apparence.

// Modification de la définition du modèle ci-dessus - doit être fait sur tous les wikis, y compris META
$wgJsonConfigModels['JsonConfig.Proxy'] = [ 'class' => 'ProxyExt\ProxyContent' ];

// Ajout de la classe view - ne doit être fait que sur le wiki de stockage (par exemple META)
$wgJsonConfigModels['JsonConfig.Proxy']['view'] = 'ProxyExt\ProxyView';
class ProxyView extends JsonConfig\JCDefaultObjContentView {
    public function getDefault( $modelId ) {
        return <<<JSON
{
    "comment": "See http://... for updates",
    "ips": [
        "N.N.N.N/NN",...
    ]
}
JSON;
    }
}


Meilleures pratiques

  • Les extensions qui utilisent JsonConfig doivent ajouter leurs configurations à $wgJsonConfigs et à $wgJsonConfigModels dans le fichier principal de l'extension.
  • Si vous partagez des données de configuration à travers plusieurs wikis, renseignez le nom de clé utilisé dans $wgJsonConfigs[], et initialisez la section 'store' / 'remote' de LocalSettings.php. C'est mieux que d'introduire un nombre de variables globales qui double la fonction des paramètres. Voir par exemple les paramètres Wikimedia de l'extension Graph pour plusieurs wikis (bien qu'elle utilise une configuration complexe multi-wiki plutôt que de simples variables de configuration).

État

Fonctionnalités implémentées

  • L' analyse syntaxique JSON convertit le texte JSON soit en tableau soit en objet.
  • La visualisation affiche le JSON sous forme de table facile à visualiser plutôt que le code, avec quelques mises en valeur supplémentaires. Par exemple si la valeur n'est pas fournie et qu'une valeur par défaut est utilisée, l'affichage est en gris, et lorsque la valeur est la même que celle par défaut, alors l'affichage est en violet. Pour les exemples, voir ici et ici.
  • L' éditeur de code simplifie l'édition JSON
  • la validation utilisateur réalise des contrôles complexes tels que vérifier que la valeur est au bon format ou bien que l'ID d'un utilisatuer existe bien.
  • la mise en cache mémoire enregistre les blobs JSON dans le cache mémoire sous des clés personnalisées et des règles d'expiration, et les réinitialise à l'enregistrement.
  • la prise en charge du marquage des révisions autorise de marquer les configurations « a été revu » (reviewed) avant de passer en production
  • la traduction de la plupart des éléments d'interface de base a été faite en plusieurs langues, et cela réduirait le travail de traduction si la plupart des messages communs étaient traduits et centralisés en un même endroit.

Fonctionnalités non implémentées mais bienvenues

Ces fonctionnalités sont souhaitables pour plus d'un type de configurations :

  • le valideur de schéma - valide le schéma JSON, étant donné que la plupart des extensions ne nécessitent pas de règles de validation complexes, ou si elles auraient besoin de combiner la validation du schéma et des règles supplémentaires.
  • l' éditeur personnalisé - l'équipe zéro pense à implémenter un éditeur plus complexe, événtuellement basé sur le schéma JSON.
  • la prise en charge de l' API de requête - elle permet de recevoir les pages de configuration en tant que résultats réguliers d'API dans tous les formats - json/xml/... au lieu de blobs textuels :
    api.php ? action=query & titles=Config:Proxy:Opera & prop=jsonconfig
  • la localisation - il serait utile de pouvoir afficher les descriptions traduites pour chaque clé de configuration.

Liens externes

Les données de configuration enregistrées peuvent souvent être nécessaires à un agent externe quelconque tel que du JavaScript, un robot ou d'autres programmes. Le JavaScript peut utiliser soit JSONP pour accéder aux données nécessaires en appelant l'API standard action=query&rvprop=content, ou nous pouvons développer un service de retransmission si CORS n'est pas disponible. Les auteurs d'extensions peuvent choisir d'ajouter leur propres modules d'API pour fournir les informations spécifiques au domaine. Enfin, le paramètre de requête rvprop=jcddata doit renvoyer les données JSON dans les résultats de l'API, et non pas en tant que blob textuel renvoyé par rvprop=content.

// NON IMPLéMENTé! Utiliser l'API régulière action=query tant que nous n'avons pas décidé la manière correcte
var req = {
    format: 'json', action: 'query',
    titles: 'Proxy:Opera',
    prop: 'revisions', rvprop: 'jcdcontent', indexpageids: '',
};
$.ajax({
    url: '//meta.wikipedia.org/w/api.php',
    data: req, cache: true, dataType: 'jsonp',
    success: function(result) { /* gérer les erreurs et avertissements, traiter le contenu */ }
});

Voir aussi