Stratégie d'implémentation
| API MediaWiki Action |
|---|
| Fonctions de base |
| Authentification |
| Comptes et utilisateurs |
| Opérations sur les pages |
|
| Chercher |
| Outils pour les développeurs |
| Tutoriels |
| v · d · e |
Ceci explique l'implémentation de la mécanique de l'API MediaWiki dans le noyau. Si vous voulez fournir une API dans votre code pour des clients consommateurs, voir API:Extensions .
Structure des fichiers et modules
api.phpest le point d'entrée situé à la racine du wiki. Voir Point d'accès de l'API.ApiEntryPointest l'implémentation du point d'accès (factuée en Gerrit change 959047).includes/apicontiendra tous les fichiers liés à l'API, mais aucun d'eux ne pourra être un point d'entrée.- Toutes les classes de l'API sont dérivées de la classe abstraite commune
ApiBase. La classe de base fournit des fonctionnalités communes telles que l'analyse des paramètres, le profilage et la gestion des erreurs. ApiMainest la classe principale instanciée parApiEntryPoint. Elle détermine quel est le module à exécuter en fonction du paramètreaction=XXX.ApiMaincrée également une instance de la classeApiResultqui contient l'ensemble de données de sortie et les fonctions d'aide associées. Enfin,ApiMaininstancie la classe de formatage qui génèrera les données de sortie pour le client à partir deApiResultdans les formats XML ou JSON ou PHP ou autre.- Tout module dérivé de
ApiBaserecevra une référence à une instance deApiMainpendant l'instanciation, de sorte qu'à l'exécution le module puisse accéder aux ressources partagées comme par exemple l'objet résultat.
Modules de requête
ApiQueryse comporte commeApiMaindans le sens où il exécute les sous-modules. Chaque sous-module est dérivé deApiQueryBase(sauf leApiQuerylui-même, qui est un module de premier niveau). Pendant l'instanciation, les sous-modules reçoivent la référence de l'instance ApiQuery.- Tous les modules de requête d'extension doivent utiliser des préfixes à 3 lettres ou plus. Les modules du noyau utilisent des préfixes à 2 lettres.
- Plan d'exécution de
ApiQuery:- Obtenir les paramètres de requête partagés
list/prop/metapour déterminer les sous-modules nécessaires. - Créer un objet
ApiPageSetet l'initialiser à partir des paramètrestitles/pageids/revids. L'objetpagesetcontient la liste des pages ou des révisions avec lesquelles les modules de requête vont travailler. - S'il est demandé, un module générateur est exécuté pour créer un autre
ApiPageSet. Similaire aux flux redirigés (pipes) dans UNIX. Les pages données sont l'entrée du générateur qui produit un autre ensemble de pages à utiliser par tous les autres modules.
- Obtenir les paramètres de requête partagés
- Conditions pour continuer la requête :
- La requête SQL doit être entièrement ordonnée. En d'autres termes, la requête doit utiliser toutes les colonnes d'une clé unique soit comme des constantes dans la clause
WHEREou dans les clausesORDER BY.- Dans MySQL, il s'agit d'un OU exclusif, au point où la requête de Foo et Bar doit trier en fonction du titre et non de l'espace de noms (celui-ci vaut toujours 0), Foo et Talk:Foo doivent trier par espace de noms mais pas par titre (le titre est constant et vaut Foo), et Foo et Talk:Bar doivent trier à la fois par espace de noms et par titre.
- La requête SQL ne doit pas trier par fichier.
- La valeur donnée à
setContinueEnumParameter()doit inclure toutes les colonnes de la clauseORDER BY. - Lors d'une continuation, une condition composée unique doit être ajoutée à la clause
WHERE. Si la requête contientORDER BY column_0, column_1, column_2, cette condition doit ressembler à :
- La requête SQL doit être entièrement ordonnée. En d'autres termes, la requête doit utiliser toutes les colonnes d'une clé unique soit comme des constantes dans la clause
(column_0 > value_0 OR (column_0 = value_0 AND (column_1 > value_1 OR (column_1 = value_1 AND (column_2 >= value_2) )) ))
Bien sûr, échangez ">" et "<" si vos colonnes ORDER BY utilisent DESC.
Veillez à éviter l'injection de SQL dans les valeurs.
Structures des données internes
- L'API de requête a eu une structure très réussie d'une structure globale
array()imbriquée qui a été transportée. Différents modules viendront ajouter des données en de nombreux points différents de ce tableau, jusqu'à ce qu'il soit rendu pour le client par l'une des imprimantes (modules de sortie). Pour l'API, nous suggérons de mettre ce tableau dans une classe avec des fonctions d'aide pour ajouter des feuilles aux nœuds individuels.
Rapporter les erreurs et les états
Pour l'instant, nous avons décidé d'inclure les informations d'erreur dans la même sortie structurée que les résultats standard (option numéro 2).
Pour le résultat, nous pouvons utiliser les codes d'erreur standard de HTTP, ou renvoyer toujours les données correctement formatées :
- En utilisant le code HTTP
void header( string reason_phrase [, bool replace [, int http_response_code]] )
header() peut être utilisé pour définir l'état au retour de l'opération.
Nous pouvons définir toutes les valeurs possibles de reason_phrase, donc pour le login en échec nous pouvons renvoyer code=403 et phrase="BadPassword", alors qu'en cas de succès nous renverrons simplement la réponse sans modifier l'entête.
Les pour : C'est une norme. Le client doit toujours traiter les erreurs HTTP, donc l'utilisation du code HTTP pour le résultat supprimerait toute gestion d'erreur séparée à réaliser par le client. Comme le client peut demander des données dans plusieurs formats, un paramètre de format non valide serait toujours correctement géré, car il s'agira simplement d'un autre code d'erreur HTTP.
Les contre : ...
- Inclure des informations d'erreur dans une réponse appropriée
Cette méthode renverrait toujours un objet de réponse correctement formaté, mais l'état de l'erreur ou la description seront les seules valeurs à l'intérieur de cet objet. Ceci est similaire à la façon dont l'API Query actuelle renvoie les codes d'état.
Les pour : Les codes d'erreur HTTP sont utilisés uniquement pour les problèmes de réseau, mais pas pour les données (erreurs logiques). Nous ne sommes pas liés aux codes d'erreur HTTP existants.
Les contre : Si le paramètre de format des données n'est pas correctement spécifié, quel est le format des données en sortie ? L'application doit analyser l'objet pour connaître une erreur (performances ?). Le code de vérification d'erreur doit être présenté à la fois au niveau de la connexion et et au niveau de l'analyse des données.
Squelette de code
| Module d'API simple |
|---|
<?php class Api<nom de module> extends ApiBase { public function __construct( $main, $action ) { parent::__construct( $main, $action ); } public function execute() { } public function getAllowedParams() { return array( '<nom du paramètre>' => array( ApiBase::PARAM_TYPE => array( 'foo', 'bar', 'baz' ), ), ); } public function getParamDescription() { return array( '<nom du paramètre>' => '<description de paramètre>', ); } public function getDescription() { return '<Description du module ici>'; } public function getExamples() { return array( 'api.php?action=<nom de module>&<nom du paramètre>=foo' ); } public function getHelpUrls() { return ''; } } |