Accueil > > > XML TEMPLATE
XML TEMPLATE
Information sur la source
Description
XML Template permet le gestion de templates par fichiers XML. C'est une extension de Fast Template (Copyright © 1999 The WebMaster's Net, All Rights Reserved). Elle permet de gérer la construction d'un site par fichiers XML. A chaque balise XML doit correspondre un template avec un nom similaire. XML Template utilise alors les noms des balises et leurs paramètes pour imbriquer les templates associés les uns dans les autres.
Source
- <?php
- //* ////////////////////////////
- //* classe XMLTemplate
- //* >> extension de la classe "FastTemplate"
- //* localisation : include/classe_XMLTemplate.php
- //* version initiale : v1.00 - 24/02/2003
- //* version courante : v1.01 - 02/07/2003
- //* auteur : Grégory NICOL <devphp at daynos point net>
- //* ////////////////////////////
-
- //
- // NOTE : cette version à la base est une version épurée de ma version 2.5
- // Il se peut que quelques lignes inutiles subsistent...
- // Consultez http://www.daynos.net/xmltemplate/ pour un exemple en ligne
- // et obtenir l'intégralité des fichiers nécessaire à son utilisation
-
- class XMLTemplate extends FastTemplate
- {
- function XMLTemplate ($pathToTemplates = "", $id_page=1)
- {
- /*
- 1. récupérer dans la base de données les informations de la page :
- - $modele_xml, qui détermine la structure générale de la page
- - $page_xml, qui détermine le contenu de la page
- 2. vérifier les droits d'accès (vérifier plus tard les accès hérités)
- 3. récupérer le fichier xml contenant la structure du site et le mémoriser sous "$this->siteNode"
- 4. récupérer le fichier xml contenant le contenu du site et le mémoriser sous "$this->pageNode"
- */
-
- // INITIALISATION
- // initialisation de la classe parente
- parent::FastTemplate ($pathToTemplates);
- $this->startTime = $this->utime();
-
- // création d'une instance de "Main"
- $this->root = new Main ();
- // Mémoriser "root_local"
- $this->root_local = $GLOBALS['root_local'];
- // Vu qu'on en a besoin un peu partout, on mémorise l'id de la page
- $this->id_page = $id_page;
-
- // Récupérer le fichier XML contenant la structure du site
- $fichier = new Fichier ();
- $xmlFile = $fichier->lireFichier (STRUCTURE_SITE);
-
- // Mémoriser la structure du site dans un tableau d'objets XML
- // dans $this->siteNode
- $oXML = new XML_Array ();
- $oXML->parse ($xmlFile);
- $this->siteNode = $oXML->getRootNode ();
-
- // Mémoriser les noeuds ouverts lors de la recherche
- // dans $this->openedNodes
- $oXML->searchNode ('id', $this->id_page, $this->siteNode, 0);
- $this->openedNodes = $oXML->searchArray;
-
- // Récupérer le nom du fichier XML contenant le modèle de la page
- // s'il n'est pas défini dans le fichier XML, on récupère le modèle par défaut
- $fromXML = $oXML->currentNode->attributes['modele_xml'];
- $modele_xml = empty ($fromXML) ? MODELE_DEFAULT : $fromXML;
-
- if (empty($modele_xml)) $this->root->error ("Nom du fichier XML du modèle non défini");
-
- // Récupérer le modèle de la page
- // dans $this->modeleNode
- $this->modeleNode = $this->getXMLFile ($modele_xml);
-
- // Récupérer le nom du fichier XML contenant le contenu de la page
- // s'il n'est pas défini dans le fichier XML, on récupère celui par défaut
- $fromXML = $oXML->currentNode->attributes['page_xml'];
-
- $page_xml = empty ($fromXML) ? PAGE_DEFAULT : $fromXML;
-
- if (empty($page_xml)) $this->root->error ("Nom du fichier XML de la page non défini");
-
- // Récupérer le contenu de la page
- // dans $this->pageNode
- $this->pageNode = $this->getXMLFile ($page_xml);
- }
-
- function getXMLFile ($file)
- {
- $fichier = new Fichier ();
- $oXML = new XML_Array ();
- $xmlFile = $fichier->lireFichier ($this->root_local.$file);
- if ($xmlFile)
- {
- $oXML->parse ($xmlFile);
- return $oXML->getRootNode ();
- }
- else $this->error ("le fichier XML de la page n'est pas valide", true);
- return;
- }
-
- function affPage ()
- {
- $this->switchNode ($this->modeleNode, 0);
- }
-
- function switchNode ($node, $lvl)
- {
- // traiter les noeuds XML d'après leur nom dans le fichier XML
-
- // action selon type de noeud - traitement des cas particuliers
- // Les noeuds "particuliers" (arbitrairement précédés de "dyn_") sont remplacés par des noeuds "normaux" qui
- // ne nécessitent aucun traitement particulier, ou par d'autres neouds "dyn_" qui seront repassés à la moulinette
- // NB : en conséquence, les noeuds enfant d'un noeud "dyn" sont supprimés
- if (substr($node->nodeName, 0, 4) == "dyn_")
- {
- switch (substr($node->nodeName, 4))
- {
- case "page" :
- $aNodes = $this->pageNode->childNodes;
- break;
- default :
- // Ceci est un reste de la version 2.5 avant épuration.
- // On interprète le nom COMPLET de la balise comme le nom de la fonction à appeler
- $aNodes = $this->{$node->nodeName} ($node, $lvl);
- break;
- }
-
- foreach ($aNodes as $newNode)
- {
- $this->switchNode ($newNode, $lvl);
- }
- }
- else
- {
- // On interprète la balise comme un template
- $this->parseBalise ($node, $lvl);
- }
- }
-
- function switchVariable ($aVariables)
- {
- // traiter les cas particuliers de variables
- foreach ($aVariables as $key=>$elem)
- {
- switch (strtoupper($key))
- {
- case "CSS" :
- $aVariables[$key] = $GLOBALS['root_skin']."css/default.css";
- break;
- case "CSS_INFO" :
- // fake pour l'instant
- $aVariables[$key] = "default";
- break;
- case "RUNTIME" :
- $this->endTime = $this->utime();
- $aVariables[$key] = $this->endTime - $this->startTime;
- break;
- case "SKIN_INFO" :
- // fake pour l'instant
- $aVariables[$key] = "default";
- break;
- default :
- //$aVariables[$key] = $elem;
- break;
- }
- }
- return $aVariables;
- }
-
- ///////////////////////////////////////////////////////
- // PARSEUR DE BALISE XML
- ///////////////////////////////////////////////////////
- // C'est ici que se déroule le plus gros du travail de XML Template
- function parseBalise ($node, $lvl=0)
- {
- // ------------------------------
- // INITIALISATION
- // ------------------------------
-
- // Nom de la balise
- $this->aMemoBaliseCourante[$lvl] = $node->nodeName;
- $this->aMemoParseAs[$lvl] = $node->nodeName;
-
- //////////////////////////////////////////////////////////
- // Nom sous lequel il faut parser le template et nom de la
- // variable sous laquelle le template est sauvegardé
- // >> par défaut, le template est parsé sous le nom de la balise précédente
- // >>> $sParseAs = $this->aMemoBaliseCourante[$lvl-1]
- // >> si $sParseAs spécifié, il est parsé sous le nom spécifié
- // >>> $this->aMemoParseAs[$lvl] = $sParseAs
-
- if (isset($node->attributes['parseAs']) && !empty($node->attributes['parseAs']))
- {
- $this->aMemoParseAs[$lvl] = $node->attributes['parseAs'];
- }
- else
- {
- $this->aMemoParseAs[$lvl] = ($lvl>0) ? $this->aMemoBaliseCourante[$lvl-1] : $this->aMemoBaliseCourante[$lvl];
- }
-
- $PARSE_AS = strtoupper ($this->aMemoParseAs[$lvl]);
- $sTplFile = $this->aMemoBaliseCourante[$lvl].".tpl";
- $sTplName = $this->aMemoBaliseCourante[$lvl];
-
- $this->aMemoParseAsCourant[$lvl] = $this->aMemoParseAs[$lvl];
-
- if ($this->aMemoParseAsCourant[$lvl] == $this->aMemoParseAsPrecedent[$lvl])
- {
- // Ajouter à ce qui existe
- $modeAdd = true;
- }
- else
- {
- // Remplacer ce qui existe
- $modeAdd = false;
- }
-
- //////////////////////////////////////////////////////////
- // Assignement des valeurs communes à tous les niveaux
- // aMemoAssignements[$level] = array (...);
- $this->aMemoAssignements[$lvl] = array (
- "ROOT_LOCAL" => $GLOBALS['root_local'],
- "ROOT_SKIN" => $GLOBALS['root_skin'],
- );
-
- // ------------------------------
- // DEFINE
- // ------------------------------
- // Récupérer le template et l'assigner à une variable du même nom
- $temp = ($sTplName{0} == "." ? substr($sTplName, 1) : $sTplName);
- $this->define (array ("$temp" => "$sTplFile"));
-
- // ------------------------------
- // ASSIGN
- // ------------------------------
- // Récupérer les paramètres de la balise
- if (count($node->attributes) >0)
- {
- $aParamBalise = $this->switchVariable (array_change_key_case($node->attributes, CASE_UPPER));
-
- // Rajouter au tableau des assignations les paramètres de la balise comme paramètres du template
- if (is_array ($this->aMemoAssignements[$lvl]))
- $this->aMemoAssignements[$lvl] = array_merge($this->aMemoAssignements[$lvl], $aParamBalise);
- else
- $this->aMemoAssignements[$lvl] = $aParamBalise;
- }
-
- // S'il y a des noeuds enfant, les incorporer au template ouvert
- foreach ($node->childNodes as $childNode)
- {
- $this->switchNode ($childNode, $lvl+1);
- }
-
- // Effacer ce qu'un éventuel noeud enfant aurait pu laisser traîner
- // (ben ouais c'est connu, les enfants ça laisse toujours pleins de trucs traîner partout...)
- // >> assignements
- $this->clear_assign ();
- // >> balises de niveau supérieur
- unset ($this->aMemoBaliseCourante[$lvl+1]);
- unset ($this->aMemoParseAsCourant[$lvl+1]);
- unset ($this->aMemoParseAsPrecedent[$lvl+1]);
-
- // assigner les valeurs du niveau
- $this->assign ($this->aMemoAssignements[$lvl]);
-
- // ------------------------------
- // PARSE
- // ------------------------------
- $this->parse($PARSE_AS, $sTplName);
- if ($lvl>0)
- {
- $temp = $this->fetch($PARSE_AS, $sTplName);
- if ($modeAdd)
- {
- // Mode ajout
- $valeurActuelle = $this->aMemoAssignements[$lvl-1][$PARSE_AS];
- $temp = $valeurActuelle.$temp;
- $this->aMemoAssignements[$lvl-1] = array_merge ($this->aMemoAssignements[$lvl-1], array ($PARSE_AS => $temp));
- }
- else
- {
- // Mode remplacement
- $this->aMemoAssignements[$lvl-1] = array_merge ($this->aMemoAssignements[$lvl-1], array ($PARSE_AS => $temp));
- }
- // vider
- unset($temp);
- }
- else
- {
- $this->FastPrint($PARSE_AS);
- }
- // mémoriser "parseAs"
- $this->aMemoParseAsPrecedent[$lvl] = $this->aMemoParseAs[$lvl];
-
- // ------------------------------
- // CLEAR
- // ------------------------------
- // NE PAS OUBLIER DE NETTOYER AVANT DE PARTIR !!!
-
- // Vider le tableau d'assignement du niveau actuel
- unset ($this->aMemoAssignements[$lvl]);
-
- // supprimer toute assignation existante :
- $this->clear_assign ();
- }
- }
- ?>
<?php
//* ////////////////////////////
//* classe XMLTemplate
//* >> extension de la classe "FastTemplate"
//* localisation : include/classe_XMLTemplate.php
//* version initiale : v1.00 - 24/02/2003
//* version courante : v1.01 - 02/07/2003
//* auteur : Grégory NICOL <devphp at daynos point net>
//* ////////////////////////////
//
// NOTE : cette version à la base est une version épurée de ma version 2.5
// Il se peut que quelques lignes inutiles subsistent...
// Consultez http://www.daynos.net/xmltemplate/ pour un exemple en ligne
// et obtenir l'intégralité des fichiers nécessaire à son utilisation
class XMLTemplate extends FastTemplate
{
function XMLTemplate ($pathToTemplates = "", $id_page=1)
{
/*
1. récupérer dans la base de données les informations de la page :
- $modele_xml, qui détermine la structure générale de la page
- $page_xml, qui détermine le contenu de la page
2. vérifier les droits d'accès (vérifier plus tard les accès hérités)
3. récupérer le fichier xml contenant la structure du site et le mémoriser sous "$this->siteNode"
4. récupérer le fichier xml contenant le contenu du site et le mémoriser sous "$this->pageNode"
*/
// INITIALISATION
// initialisation de la classe parente
parent::FastTemplate ($pathToTemplates);
$this->startTime = $this->utime();
// création d'une instance de "Main"
$this->root = new Main ();
// Mémoriser "root_local"
$this->root_local = $GLOBALS['root_local'];
// Vu qu'on en a besoin un peu partout, on mémorise l'id de la page
$this->id_page = $id_page;
// Récupérer le fichier XML contenant la structure du site
$fichier = new Fichier ();
$xmlFile = $fichier->lireFichier (STRUCTURE_SITE);
// Mémoriser la structure du site dans un tableau d'objets XML
// dans $this->siteNode
$oXML = new XML_Array ();
$oXML->parse ($xmlFile);
$this->siteNode = $oXML->getRootNode ();
// Mémoriser les noeuds ouverts lors de la recherche
// dans $this->openedNodes
$oXML->searchNode ('id', $this->id_page, $this->siteNode, 0);
$this->openedNodes = $oXML->searchArray;
// Récupérer le nom du fichier XML contenant le modèle de la page
// s'il n'est pas défini dans le fichier XML, on récupère le modèle par défaut
$fromXML = $oXML->currentNode->attributes['modele_xml'];
$modele_xml = empty ($fromXML) ? MODELE_DEFAULT : $fromXML;
if (empty($modele_xml)) $this->root->error ("Nom du fichier XML du modèle non défini");
// Récupérer le modèle de la page
// dans $this->modeleNode
$this->modeleNode = $this->getXMLFile ($modele_xml);
// Récupérer le nom du fichier XML contenant le contenu de la page
// s'il n'est pas défini dans le fichier XML, on récupère celui par défaut
$fromXML = $oXML->currentNode->attributes['page_xml'];
$page_xml = empty ($fromXML) ? PAGE_DEFAULT : $fromXML;
if (empty($page_xml)) $this->root->error ("Nom du fichier XML de la page non défini");
// Récupérer le contenu de la page
// dans $this->pageNode
$this->pageNode = $this->getXMLFile ($page_xml);
}
function getXMLFile ($file)
{
$fichier = new Fichier ();
$oXML = new XML_Array ();
$xmlFile = $fichier->lireFichier ($this->root_local.$file);
if ($xmlFile)
{
$oXML->parse ($xmlFile);
return $oXML->getRootNode ();
}
else $this->error ("le fichier XML de la page n'est pas valide", true);
return;
}
function affPage ()
{
$this->switchNode ($this->modeleNode, 0);
}
function switchNode ($node, $lvl)
{
// traiter les noeuds XML d'après leur nom dans le fichier XML
// action selon type de noeud - traitement des cas particuliers
// Les noeuds "particuliers" (arbitrairement précédés de "dyn_") sont remplacés par des noeuds "normaux" qui
// ne nécessitent aucun traitement particulier, ou par d'autres neouds "dyn_" qui seront repassés à la moulinette
// NB : en conséquence, les noeuds enfant d'un noeud "dyn" sont supprimés
if (substr($node->nodeName, 0, 4) == "dyn_")
{
switch (substr($node->nodeName, 4))
{
case "page" :
$aNodes = $this->pageNode->childNodes;
break;
default :
// Ceci est un reste de la version 2.5 avant épuration.
// On interprète le nom COMPLET de la balise comme le nom de la fonction à appeler
$aNodes = $this->{$node->nodeName} ($node, $lvl);
break;
}
foreach ($aNodes as $newNode)
{
$this->switchNode ($newNode, $lvl);
}
}
else
{
// On interprète la balise comme un template
$this->parseBalise ($node, $lvl);
}
}
function switchVariable ($aVariables)
{
// traiter les cas particuliers de variables
foreach ($aVariables as $key=>$elem)
{
switch (strtoupper($key))
{
case "CSS" :
$aVariables[$key] = $GLOBALS['root_skin']."css/default.css";
break;
case "CSS_INFO" :
// fake pour l'instant
$aVariables[$key] = "default";
break;
case "RUNTIME" :
$this->endTime = $this->utime();
$aVariables[$key] = $this->endTime - $this->startTime;
break;
case "SKIN_INFO" :
// fake pour l'instant
$aVariables[$key] = "default";
break;
default :
//$aVariables[$key] = $elem;
break;
}
}
return $aVariables;
}
///////////////////////////////////////////////////////
// PARSEUR DE BALISE XML
///////////////////////////////////////////////////////
// C'est ici que se déroule le plus gros du travail de XML Template
function parseBalise ($node, $lvl=0)
{
// ------------------------------
// INITIALISATION
// ------------------------------
// Nom de la balise
$this->aMemoBaliseCourante[$lvl] = $node->nodeName;
$this->aMemoParseAs[$lvl] = $node->nodeName;
//////////////////////////////////////////////////////////
// Nom sous lequel il faut parser le template et nom de la
// variable sous laquelle le template est sauvegardé
// >> par défaut, le template est parsé sous le nom de la balise précédente
// >>> $sParseAs = $this->aMemoBaliseCourante[$lvl-1]
// >> si $sParseAs spécifié, il est parsé sous le nom spécifié
// >>> $this->aMemoParseAs[$lvl] = $sParseAs
if (isset($node->attributes['parseAs']) && !empty($node->attributes['parseAs']))
{
$this->aMemoParseAs[$lvl] = $node->attributes['parseAs'];
}
else
{
$this->aMemoParseAs[$lvl] = ($lvl>0) ? $this->aMemoBaliseCourante[$lvl-1] : $this->aMemoBaliseCourante[$lvl];
}
$PARSE_AS = strtoupper ($this->aMemoParseAs[$lvl]);
$sTplFile = $this->aMemoBaliseCourante[$lvl].".tpl";
$sTplName = $this->aMemoBaliseCourante[$lvl];
$this->aMemoParseAsCourant[$lvl] = $this->aMemoParseAs[$lvl];
if ($this->aMemoParseAsCourant[$lvl] == $this->aMemoParseAsPrecedent[$lvl])
{
// Ajouter à ce qui existe
$modeAdd = true;
}
else
{
// Remplacer ce qui existe
$modeAdd = false;
}
//////////////////////////////////////////////////////////
// Assignement des valeurs communes à tous les niveaux
// aMemoAssignements[$level] = array (...);
$this->aMemoAssignements[$lvl] = array (
"ROOT_LOCAL" => $GLOBALS['root_local'],
"ROOT_SKIN" => $GLOBALS['root_skin'],
);
// ------------------------------
// DEFINE
// ------------------------------
// Récupérer le template et l'assigner à une variable du même nom
$temp = ($sTplName{0} == "." ? substr($sTplName, 1) : $sTplName);
$this->define (array ("$temp" => "$sTplFile"));
// ------------------------------
// ASSIGN
// ------------------------------
// Récupérer les paramètres de la balise
if (count($node->attributes) >0)
{
$aParamBalise = $this->switchVariable (array_change_key_case($node->attributes, CASE_UPPER));
// Rajouter au tableau des assignations les paramètres de la balise comme paramètres du template
if (is_array ($this->aMemoAssignements[$lvl]))
$this->aMemoAssignements[$lvl] = array_merge($this->aMemoAssignements[$lvl], $aParamBalise);
else
$this->aMemoAssignements[$lvl] = $aParamBalise;
}
// S'il y a des noeuds enfant, les incorporer au template ouvert
foreach ($node->childNodes as $childNode)
{
$this->switchNode ($childNode, $lvl+1);
}
// Effacer ce qu'un éventuel noeud enfant aurait pu laisser traîner
// (ben ouais c'est connu, les enfants ça laisse toujours pleins de trucs traîner partout...)
// >> assignements
$this->clear_assign ();
// >> balises de niveau supérieur
unset ($this->aMemoBaliseCourante[$lvl+1]);
unset ($this->aMemoParseAsCourant[$lvl+1]);
unset ($this->aMemoParseAsPrecedent[$lvl+1]);
// assigner les valeurs du niveau
$this->assign ($this->aMemoAssignements[$lvl]);
// ------------------------------
// PARSE
// ------------------------------
$this->parse($PARSE_AS, $sTplName);
if ($lvl>0)
{
$temp = $this->fetch($PARSE_AS, $sTplName);
if ($modeAdd)
{
// Mode ajout
$valeurActuelle = $this->aMemoAssignements[$lvl-1][$PARSE_AS];
$temp = $valeurActuelle.$temp;
$this->aMemoAssignements[$lvl-1] = array_merge ($this->aMemoAssignements[$lvl-1], array ($PARSE_AS => $temp));
}
else
{
// Mode remplacement
$this->aMemoAssignements[$lvl-1] = array_merge ($this->aMemoAssignements[$lvl-1], array ($PARSE_AS => $temp));
}
// vider
unset($temp);
}
else
{
$this->FastPrint($PARSE_AS);
}
// mémoriser "parseAs"
$this->aMemoParseAsPrecedent[$lvl] = $this->aMemoParseAs[$lvl];
// ------------------------------
// CLEAR
// ------------------------------
// NE PAS OUBLIER DE NETTOYER AVANT DE PARTIR !!!
// Vider le tableau d'assignement du niveau actuel
unset ($this->aMemoAssignements[$lvl]);
// supprimer toute assignation existante :
$this->clear_assign ();
}
}
?>
Conclusion
Le code présenté ici n'est que le coeur du code. La version est complète est téléchargeable sur www.daynos.net/xmltemplate/
Sources de la même categorie
Commentaires et avis
|
Derniers Blogs
GESTION D'EXCEPTION AVEC LES TASKSGESTION D'EXCEPTION AVEC LES TASKS par richardc
Nous avons vu dans un précédent article comment utiliser Task pour effectuer des opérations dans un autre thread.
Malheureusement, comme tout le monde n'est pas parfait, il se peut que cette exécution se passe mal et qu'une exception se produise.
La...
Cliquez pour lire la suite de l'article par richardc DéMARRONS AVEC LES TASKSDéMARRONS AVEC LES TASKS par richardc
Que vous le vouliez ou non, le développement multi-tâche est maintenant une obligation pour toute nouvelle application. Il est donc vital d'en comprendre les mécanismes et de s'y mettre le plus tôt possible.
En attendant le .NET Framework 4.5 avec le...
Cliquez pour lire la suite de l'article par richardc SLIDE & DéMO TECHDAYS 2012 - FAST & FURIOUS XAML APPSSLIDE & DéMO TECHDAYS 2012 - FAST & FURIOUS XAML APPS par Vko
Retrouvez les slides et les démo de ma session Fast & Furious XAML Apps. A ceux qui se posent la question : "est-ce que le code de la DataGrid est disponible?", je vous répondrais "pas encore". Je vais mettre en place un projet codeplex pour part...
Cliquez pour lire la suite de l'article par Vko XNA IS DEAD!XNA IS DEAD! par richardc
Depuis la semaine dernière (et grâce aux TechDays 2012), je me penche activement sur la nouvelle version de Windows, aka Windows 8. Vous me direz, il était temps puisque la première preview date de Septembre dernier.
OK. Remarquez, on n'en est qu'aux...
Cliquez pour lire la suite de l'article par richardc TECHDAYS PARIS 2012 : WINDOWS SERVER "8" QUOI DE 9 !TECHDAYS PARIS 2012 : WINDOWS SERVER "8" QUOI DE 9 ! par ROMELARD Fabrice
Speakers: Fabrice Meillon et Stanislas Quastana Cette session est basée entièrement sur celle donnée lors de la BUILD cet hiver. Il n'y a pas d'ajout d'information en rapport avec cet évènement passé. Windows 8 Server sera intégralem...
Cliquez pour lire la suite de l'article par ROMELARD Fabrice
Forum
CHAMPS TIMECHAMPS TIME par vargas
Cliquez pour lire la suite par vargas
Logiciels
DocTranslate (V3.1.0.0)DOCTRANSLATE (V3.1.0.0)DocTranslate est un traducteur de document Microsoft Word, PowerPoint et Excel. Il permet d'autom... Cliquez pour télécharger DocTranslate Tribler (2012)TRIBLER (2012)Tribler est un client pair à pair (P2P/Peer-to-Peer) open source avec la capacité de regarder des... Cliquez pour télécharger Tribler OneSwarm (2012)ONESWARM (2012)Le peer-to-peer qui protège votre vie privée, c'est OneSwarm.
Ce logiciel de peer-to-peer crypté... Cliquez pour télécharger OneSwarm PONAMEDIA PREMIUM - HELLLOOO FLASH DEMO (V8.4)PONAMEDIA PREMIUM - HELLLOOO FLASH DEMO (V8.4)PONAMEDIA TV DEVIENS HELLLOOO FLASH
LA TV SUR VOTRE ORDINATEUR.
Toute une plateforme Multi... Cliquez pour télécharger PONAMEDIA PREMIUM - HELLLOOO FLASH DEMO Academy System (17.2.1.0)ACADEMY SYSTEM (17.2.1.0)Logiciel de gestion des établissements.
- élèves/étudiants (inscription, dossier, absence...)
-... Cliquez pour télécharger Academy System
|