ArchitecturePostNuke

        Manipulation variable
        Variables d'utilisateur
        Validation des variables
        Gestion d'erreurs

Ce chapitre décrit l'architecture de base de PostNuke, il explique les majeures parties, et contient l'information sur les choix de conception faits pour le système.


Manipulation variable

Vous DEVEZ passer toutes les variables par pnVarCleanFromInput() etc.., ce qui les enregistres dans des variables de session



Variables d'utilisateur

Une variable d'utilisateur est une entité identifiée par un nom qui stocke une valeur possédée par exactement un seul utilisateur. PostNuke offre deux fonctions d'api pour manoeuvrer des variables d'utilisateur, elles sont pnUserGetVar() et pnUserSetVar() .
Le but du pnUserGetVar() est de permettre l'accès en lecture à une variable d'utilisateur. Le pnUserSetVar() permet l'accès en écriture à une variable d'utilisateur. $name Le paramètre est vérifié contre le metadata pour s'assurer que la variable est enregistrée. PostNuke garde un certain metadata au sujet de chaque variable d'utilisateur, ainsi vous ne pouvez pas accéder $name à la variable d'utilisateur si son metadata n'est pas enregistré.
Un module peut enregistrer une nouvelle variable d'utilisateur en fournissant son metadata seulement s'il a les bonnes permissions (des permissions sont vérifiées par la fonction d'enregistrement).Habituellement le procédé d'enregistrement devrait avoir lieu a l'initialisation pour un module qui veut employer $name la variable d'utilisateur pendant son cycle de vie.
PostNuke n'impose aucune restriction à la valeur de $name excepté des noms doubles et réservés.

La liste de noms réservés se compose ainsi :

uid : L'identification de l'utilisateur.
nom : Le nom d'utilisateur (pleine épellation).
uname : Le nom d'utilisateur (forme courte, 'entaille ').
email : Le email address de l'utilisateur.
URL : L'URL d'utilisateur.
statut : Le statut etc.. d'utilisateur (actif, inactif, supprimé).
auth_module : Le module d'autentification qui a été pour la dernière fois utilisé pour cet utilisateur.

Il est conseillé (même pour des raisons d'exécution) d'employer la convention d'appellation suivante: $name := $module_name. '_ '. $real_name

Pour enregistrer $name la variable d'utilisateur vous devez employer le register_user_var() de fonction du module api exporté par le module de modules.

Voici un exemple:

$module_name = 'MyModule';
$variable_name = 'MaxLinesPerPage';
$metadata['label'] = $module_name . '_' . $variable_name;
$metadata['dtype'] = _UDCONST_INTEGER; //une des valeurs définies pour les types variables de données dynamiques 

d'utilisateur
$metadata['default'] = 20;
$metadata['validation'] = 'num:>=:10&num:<=:100';

pnModAPILoad('Modules', 'admin');

$result = pnModAPIFunc('Modules', 'admin', 'register_user_var', $metadata);
if (!isset($result)) {
  // pnModAPIFunc() échoue
} elseif ($result == false)
  // enregistrement échoué
} else {
  // enregistrement réussi
}

Comme vous pouvez voir dans cet exemple, une rangée descriptive pour la nouvelle variable d'utilisateur est créée d'abord, et register_user_var() postérieur s'appelle avec cette rangée comme paramètre. Les clefs signicatives pour la rangée sont: label, dtype, défaut et validation. Le champ label est obligatoire; il indique le nom variable d'utilisateur car vous vous référerez plus tard dans le paramètre de pnUserGetVar() et $name de pnUserSetVar().
Le champ de dtype est obligatoire; il peut prendre un des valeurs suivantes: _UDCONST_STRING, _UDCONST_TEXT, _UDCONST_FLOAT, _UDCONST_INTEGER.
Vous devriez évidemment choisir la bonne valeur pour le type de données que la nouvelle variable d'utilisateur contiendra. Le champ de défaut est facultatif; il est employé quand l'utilisateur n'a pas encore placé une valeur pour la nouvelle variable d'utilisateur.Le champ de validation est facultatif; référez-vous à la prochaine section pour obtenir une vue d'ensemble de validation variable. A l'enregistrement d'une variable d'utilisateur vous devez appeler l'unregister_user_var() , qui est situé dans le module admin API. Vous devez appeler cet api seulement au temps d'uninstallation pour vos modules. Maintenez dans votre tête qu'en appelant l'unregister_user_var() toutes les valeurs existantes pour cette variable d'utilisateur seront supprimées des données d'utilisateur. voici une peu d'explications :
Les variables de module sont au niveau système des variables, partagées entre chaque utilisateur de module, comme des variables de configuration. Elles ne sont possédées par aucun utilisateur particulier, et même si elles sont souvent protégées par des permissions pour protéger l'accès, elles sont typiquement des variables "administratives". Vous êtes encouragés à les employer quand vous avez un besoin de donner à des administrateurs la possibilité de choisir le comportement de votre module. Mais quand ces comportements sont d'avantage liés aux préférences d'utilisateur vous devriez éviter d'employer des variables de module et enregistrer une nouvelle variable d'utilisateur à employer en votre code. Imaginez une nouvelle variable d'utilisateur est enregistrée dans le listing ci-dessus pour permettre à chaque utilisateur simple de choisir son propre arrangement de MaxLinePerPage?.Maintenant il est raisonnable d'avoir fait ce choix, mais ici nous pourrions avoir choisi une variété partagée unique de module aussi bien. D'autre part il y a quelques cas ou vous n'avez pas ce genre de liberté, par exemple en considerant le module d'authldap. Il doit accéder à un serveur de LDAP, ainsi il a besoin d'une variable qui contient le hostname de serveur de LDAP. Évidemment cette variable devrait être une variable de module, et on devrait accorder l'accès à lui seulement aux administrateurs avec les bonnes permissions.
Nous vous invitons à réfléchir à celà pendant un moment avant que vous utilisiez celà sur des variabless de module ou des variables d'utilisateur.


Validation des variables

PostNuke inclut un mécanisme transparent pour la validation variable.
Il est actuellement employé par deux fonctions d'api: pnUserValidateVar() et pnUserSetVar() .
Grâce de travaux de validation à l'architecture dynamique de données d'utilisateur. Comme vous avez vu dans la section ci-dessus, avec des données dynamiques d'utilisateur vous pouvez enregistrer de nouvelles variables d'utilisateur simplement en fournissant son metadata.
Le metadata peut également contenir un champ spécial dénoté par la clef de validation. Une syntaxe puissante a été inventée pour ce champ. Tout ce que vous devez faire doit suivre la bonne syntaxe et écrit votre propre validateur, plus tard vous enregistrez le metadata contenant la variable d'utilisateur et maintenant vous pouvez vous débarasser de la validation dans vos fonctions de module. Simplement quand vous appelez le pnUserSetVar() , PostNuke appliquera automatiquement votre validateur et si le contrôle échoue vous serez avisés de cela par la valeur de retour. Pour compenser toute cette perte de commande sur la validation, une nouvelle fonction d'api a été créée. Vous pouvez valider une valeur variable d'utilisateur avec la fonction pnUserValidateVar(). Cela vous donne la possibilité d'abord de valider toutes les variables d'entrée d'utilisateur et ensuite une mise à jour quand tous les contrôles de validation ont réussi.

Voici la grammaire pour la validation:

validation_string := validator_list
validator_list := validator [ + '&' + validator_list ]
validator := ['!' +] type + ':' + operator + ':' + param

Les caractères réservés à l'échappement sont '\' , ':' et '&'

le type peut être un de ces valeurs: 'num', 'string', 'stringlen', 'func'

l'opérateur est réagis à la casse:

les opérateurs valides pour le type num sont: ==,! =, <, >, < =, > =

les opérateurs valides pour le type string sont: is, contains, starts, ends, regex

les opérateurs valides pour le type stringlen sont les mêmes que pour le type num.

il y a seulement un opérateur valide pour le type fonc: c'est une corde composée de ModName + ', '+ FuncName.

FuncName DOIT être exporté comme fonction de l'utilisateur api du module de ModName?.

le param est le deuxième paramètre à employer avec l'opérateur, excepté le type fonc: ici le param est le

deuxième paramètre qui sera passé à la fonction de FuncName.

Vous pouvez créer des validators complexes simplement en les enchaînant avec l'opérateur & (AND).

Voici quelques exemples:

// validation string = "string:starts:foo bar"
// validation faite avec succès
pnUserSetVar("myVar", "foo bar is better than bar foo");
// erreur de validation 
pnUserSetVar("myVar", "bar foo is ugly");

// validation string = "string:starts:foo\\: bar&stringlen:<=:16"
// NOTE: si vous avez besoin du caractère :
//       vous devez le faire précéder par '\'
// validation faite avec succès
pnUserSetVar("myVar", "foo: bar is good");
// erreur de validation, la chaine est trop longue
pnUserSetVar("myVar", "foo: bar is better");

// validation string = "!string:regex:/(censored1|censored2)/"
// NOTE: opérateur NON avant le type
// validation faite avec succès
pnUserSetVar("myVar", "i'm a good boy, i'm not posting something bad");
// erreur de validation
pnUserSetVar("myVar", "i'm a bad boy, you are a censored1");

// validation string = "num:>=:1&num:<=:10"
// validation will succeed
pnUserSetVar("myVar", "5");
// erreur de validation
pnUserSetVar("myVar", "12");

// validation string = "func:MyModule,MyFunc:none"
// IMPORTANT: si votre fonction de validation fonctionne seulement avec
//  la valeur variable que vous devez indiquer que le param a pas
// à passer à la fonction
// vous réalisez cela en le plaçant simplement à 'none'

// IMPORTANT: if your validation function works only with the
//            variable value you must specify that param has not
//            to be passed to function.
//            You achieve that by simply setting it to 'none'
// validation faite avec succès
pnUserSetVar("myVar", "Homer Simpson");
// erreur de validation 
pnUserSetVar("myVar", "Marco Canini");

// MyModule user API

function MyModule_userapi_MyFunc($args)
{
    extract($args);  // $value
    $ssconn = StarShip::openConnection();
    return !$ssconn->isAlienLifeForm($value);
}



Gestion d'erreurs

PostNuke est capable de la gestion d'erreur par un système de transport puissant d'exception.
Puisque PHP ne soutient pas le mecanisme des exceptions, PostNuke fournit un mécanisme artificiel à pour les exceptions. PostNuke divise des exceptions en deux types: exceptions de système et exceptions d'utilisateur. Des exceptions de système sont employées par des fonctions de PostNuke API, mais vous pouvez les employer s'il est signicatif du fait une telle situation; par exemple considérez l'exception de DATABASE_ERROR, vous êtes fortement encouragés à employer cette exception quand une erreur de base de données se produit et à ne pas employer votre propre exception. Car un autre exemple considèrent l'exception de BAD_PARAM, vous devriez choisir d'employer cette exception dans vos fonctions de module et fonctions d'api quand des paramètres passés sont considérés mal. Enfin les exceptions de système sont des exceptions bien connues pour lesquelles PostNuke peut entreprendre des actions particulières comme noter ou emailing, de l'autre et des exceptions d'utilisateur ne sont pas connues par PostNuke, et puisqu'elles sont indistinguibles, PostNuke les traitera car elles étaient toute la même chose. Un autre point positif dans la distinction entre le système et les exceptions d'utilisateur est le fait que vous ne devriez pas laisser des exceptions d'utilisateur non-traitées comme vous pouvez faire pour des exceptions de système. Par conséquent vous devriez traiter toutes les exceptions d'utilisateur au lieu de les renvoyer à PostNuke, ceci parce que des exceptions d'utilisateur peuvent être vues en tant qu'exceptions douces, ainsi vous pourriez être en position de faire d'autres actions et/ou de renvoyer un message d'erreur correctement composé qui rendra un message d'erreur plus précis.
Toutefois il n'est pas interdit de renvoyer des exceptions d'utilisateur à PostNuke, ainsi est tombé librement pour faire cela si c'est le cas. D'autre part vous devriez éviter aux exceptions , excepté des cas particuliers. Une exception de système est une exception dure, ceci signifie que quelque chose s'est très mal produit et PostNuke devrait être informé de cela. Vous réalisez ceci simplement en renvoyant des exceptions de système. En outre ici il y a des circonstances particulières dans lesquelles vous pourriez et peut-être si les exceptions de captage . Par exemple considérez la fonction du pnUserGetVar() api: elle soulève une exception de système de NO_PERMISSION dans le cas que vous n'avez pas la bonne permission, toutefois vous n'étiez pas en position pour obtenir le niveau d'accès pour des variables d'utilisateur, ainsi il est parfaitement acceptable ici d'intercepter cette exception et de traiter ce qu'elle est signifie pour avancer. Maintenant c'est le moment d'explorer comment PostNuke laisse traiter des exceptions. Ici nous commençons en exposant comment intercepter des exceptions. Quand une fonction, peut potentiellement soulever des exceptions, des résultats avec une valeur vide vous DEVEZ vérifier si une certaine exception n'est pas ressortie. Vous pouvez faire cela en appelant la fonction de pnExceptionMajor() et en comparant sa valeur de retour à la constante de PN_NO_EXCEPTION. S'ils sont différents vous savez qu'une exception a été produite. La valeur de retour de pnExceptioMajor() peut avoir une de ces valeurs: PN_NO_EXCEPTION, PN_USER_EXCEPTION, PN_SYSTEM_EXCEPTION. Évidemment la valeur PN_NO_EXCEPTION indique qu'aucune exception n'a
été produite, PN_USER_EXCEPTION pour les exceptions d'utilisateur. PN_SYSTEM_EXCEPTION pour les exceptions de système. Quand vous voyez qu'une exception a été augmentée vous avez deux possibilités: Renvoyez là ou manipulez-la. Pour renvoyer une exception que vous pouvez retourner seulement avec une valeur vide. Pour manipuler une exception que vous devez examiner pour assurer le type d'exception, l'identification et la valeur si il y en a une.

Considérez l'exemple suivant:

$res = pnModFunc('MyModule', 'user', 'MyFunc');
if (!isset($res) && pnExceptionMajor() != PN_NO_EXCEPTION) {
    // Got an exception
    if (pnExcepionMajor() == PN_SYSTEM_EXCEPTION) {
        return; // throw back
    }
    // Got a user exception
    if (pnExceptionId() == 'MyException1') {
        $value = pnExceptionValue();
        $output->Text("Syntax error at line: ".$value->lineNumber);
    } elseif (pnExceptionId() == 'MyException2') {
        /* Do something useful */
    } else { // MyException3
        /* Do something useful */
    }
    // reset exception status
    // NOTE: il est important d'utiliser cette fonction avant de sortir de la fonction
    pnExceptionFree();
    return $output->GetOutput();
}

Pour déclarer une exception utilisez pnExceptionSet(). Vous appelez simplement cette fonction en passant l'exception (id ou valeur s'il y en a un) et après cet appel, retournez void

Regardez cet exemple:

class MyException1
{
    var $lineNumber;
}

/* ... */

MyModule_user_MyFunc()
{
    /* ... */
    if ($syntax == false) {
        // Syntax error
        $exc = new MyException1;
        $exc->lineNumber = $line;
        pnExceptionSet(PN_USER_EXCEPTION, 'MyException1', $exc);return;
    }
    /* ... */
    pnExceptionSet(PN_USER_EXCEPTION, 'MyException2');
    /* ... */
    pnExceptionSet(PN_USER_EXCEPTION, 'MyException3');
    /* ... */
    return true;
}
      

Notez à ce qu'aucune valeur est associé MyException2 et MyException3, il n'y a aucun besoin de créer une classe pour la valeur d'exception. Comme vous pouvez voir la manipulation d'exception est très puissante mais également alésante et pénible. Cependant vous pouvez toujours choisir de ne pas employer des exceptions d'utilisateur et de ne pas toujours renvoyer des exceptions de système. Mais maintenez dans l'esprit que la bonne gestion d'erreur n'est pas quelque chose qui devrait être laissée pour la fin de la conception. Ce devrait faire partie du procédé de développement. Notez qui est erroné de ne pas vérifier le statut des exceptions après un appel à une fonction qui peut potentiellement soulever quelque chose. Et notez également que si vous choisissez de manipuler une ou plusieurs exceptions que vous DEVEZ appeler le pnExceptionFree() avant de sortir, autrement le rapport de confiance sur lequel le mécanisme de manipulation d'exception est basé ne fonctionnera pas et vous produirez des choses très mauvaises. Une chose ultérieure pour qui de vous vise à coder un module officiel de PostNuke: vous DEVEZ toujours vérifier les exceptions probables et pas le code avec la pensée que quelque chose ne se produira jamais; vous DEVEZ également soulever DATABASE_ERROR dans chaque fonction qui appel la base de donnée.