But

Arrêter de faire du copier/coller de code dans les plugins.
Il est possible de mutualiser un certain nombre de fonctionnalités présentes dans (presque) tous les plugins :
  • vérification de l'installation du plugin
  • installation du plugin
  • désinstallation du plugin
  • gestion des profils du plugin
  • changement de profil du plugin
  • configuration des notifications

On pourrait aussi réfléchir à l'extension du framework pour se passer du fichier includes du plugin (par exemple un tableau NEEDED_PLUGIN_ITEMS).

Proposition

Une page, dans le coeur, qui permet la gestion des plugins.
Celle-ci serait composée de 3 onglets :
  • installation/migration/désinstallation :

L'onglet installation comprendrait une liste de tous les plugins. Pour chacun d'entre eux, l'état du plugin (installé, version schéma ok, ou pas). Si le plugin n'est pas installé, un lien pour l'installer s'affiche. S'il est installé, un lien pour le déinstaller est proposé (avec confirmation avant la déinstallation) et un lien pour la migration si le schéma n'est plus valide.

  • configuration

Cet onglet liste tous les plugins, et affiche un lien pour chacun d'eux qui donne une possibilité de configuration.

  • gestion des droits

Cet onglet contient un premier formulaire qui permet de sélectionner le profil sur lequel on veut travailler. Il affiche ensuite la liste des plugins avec tous les droits par plugin.

Cette page de gestion centralisée permettrait d'éviter de devoir gérer cela dans les plugins : en effet, ça permettrait de gagner du temps dans la conception des plugins, et d'être sûr qu'ils vont tous utiliser le même système de gestion des droits.

  • Configuration des notifications

Pouvoir utiliser le système de notification de glpi (en pouvant bien sur ajouter des destinataires si besoin). Il faut peut être ouvir un ticket pour en prendre compte au moment de la refonte des notifications de glpi ?

Proposition...Suite

Il faudrait pouvoir utiliser aussi d'autres outils à partir du core :
  • ajout dans le log.
  • actions massives (avec la notion de transfert et copie si besoin pour surmonter les entités).
  • moteur de recherche, de selection.
  • gérer les boutons ajout, Gerer Gabarits.
  • avoir un mécanisme qui permet pouvoir réaliser des checks standards (vérification de la version de PHP, vérification des droits d'un répertoire, etc.)
  • ... a completer si besoin

Au niveau accès à la configuration du plugin, il faut penser à un système d'accès basé sur un singleton. Celui-ci permettra d'éviter les lectures successives sur ces tables.

Tables partagées

Il doit être possible de définir des tables qui seront partagées entre différents plugins :
  • couleur pour des niveaux d'alertes des plugins réseau
  • etc

Il faudra prévoir un système qui permet de définir toutes les tables qui sont communes aux plugins.

Références dans le forum

http://www.glpi-project.org/forum/viewtopic.php?id=7139

Séminaire

Modification du coeur

Le coeur doit fournit :
  • une liste prototypes de fonctionnalités de base qui seront implémentées dans les plugins :
    • installation
    • désinstallation
    • activation
    • désactivation
  • une table qui stocke la liste des plugins, et l'état de chacun d'entre eux
  • un formulaire qui liste les plugins, et permet de faire des actions de base :
    • lien vers l'install d'un plugin
    • lien vers la déinstall d'un plugin
    • lien vers l'activation/désactivation
    • lien vers la configuration
    • lien vers une page 'à propos'

Considération sur les plugins

Il faut mettre en place des branches pour les plugins.

Méta plugin

Il fournit les services suivants :
  • install / déinstall
  • activation / désactivation
  • indique si un plugin est installé
  • gestion des droits (ajout des droits en base, formulaire d'édition des droits)
  • page de recherche unique
  • service d'export de rapports PDF (il prend un objet pdf pour l'envoyer en tant que fichier)
  • gestion des tables de relations => type plugin | type source | source id | type destination | destination id
    • ajout de relations
    • suppression de relations
    • récupération de relations
    • formulaire d'affichage de relations
  • répertoire lib/ commun pour déposer des libs qui pourraient être utilisées par tous les plugins

Ajout JCharles :

Proposition sur les liens entre plugins et glpi

Une classe générique pourrait gérer les liaisons entre les différents élements glpi et les éléments des plugins.

Dans la suite je considére GLPI lui-même comme un plugin

  • Une table gére les définitions de liaisons ou les plugin viennent enregistrer leurs types d'élements ( par ex tracking peut enregistrer TRACKING_TYPE)
  • Une ou plusieurs tables les liaisons entre les éléments
  • la classe a aussi pour fonction de supprimer les liaisons entre items lors de la suppression d'un plugin ou d'un item, de retourner les references d'items en relation ...
  • exemple d'usage :
            $link1 = new Links($DB);
            $link1->register('projet', 'PROJET');
                Ajout du type PROJET pour les liaisons
    
            $link2 = new Links($DB, 'TASK');
            // Création d'un objet sur un type déjà enregistré
            //$link2->register('projet', 'TASK');
    
            $link1->addLink (1, 'PROJET', 2);
            $link1->addLink (4, 'TASK', 3);
                 Ajout d'une liaison entre le projet 1 et le projet 2
                 Ajout d'une liaison entre le projet 4  et la tache 3
    
            $link2->addLink (2, 'PROJET', 1);
            $link2->addLink (2, 'PROJET', 7);
                 Ajout d'une liaison entre la tache 2 et les projet 1 et 7
    
            $link2->addLink (2, 'TASK', 5);
                 Ajout d'une liaison entre la tache 2 et la tache 5
            $link2->addLink (6, 'TASK', 5);
                 Ajout d'une liaison entre la tache 6 et la tache 5
    
            $rows = $link2->getLinks(2);
                 Liste des liaisons sur la tache 2 
    
            $rows = $link2->getLinks(2, 'TASK');
                 Liste des liaisons avec des taches sur la tache 2 
    
            $link2->deleteLink (2, 'TASK', 5);
                 Suppression de la liaison entre la tache 2 et la tache 5
            $link1->deleteItem (1);
                 Suppression du projet 1 et des liaisons afférentes
    
            $link2->unregister();
                 désenregistrement du type tache et des liasions afférentes
    
  • un exemple pour la classe
    
    <?php
    
    /**
    * Links class
    *
    * this class use to manage link between items in glpi
    * table glpi_links_definitions ( id(int), plugin(charr16), type(charr16) )
    * tables glpi_links_<name> ( FK_ID_origin(int), FK_link(int), FK_ID_destination(int) ) 
    * notices : 
    *    tables glpi_types_<name> could be gathered in only one table ?
    */
    class Links
    {
        var $DB;
        var $name;
        var $ID;
    
        /**
         * +construct 
         * 
         * @param string $name 
         * @access protected
         * @return void
         */
        function +construct(&$DB, $name="")
        {
            $this->DB = $DB;
            $this->name = $name;
            if ( !empty($name) ) {
                $this->ID = $this->getIDbyName();
            }
        }
    
        /**
         * register 
         * 
         * register the type in glpi_links_definitions
         * Create a table for this new type glpi_links_<name>
         *
         * @param string $plugin_name 
         * @param string $type_name 
         * @access public
         * @return true if (plugin, type) is registered
         */
        function register($plugin_name, $type_name)
        {
            $query = $this->DB->query("select * from glpi_links_definitions where links_plugin='$plugin_name' and links_type='$type_name'");
            if ( $query &&  $this->DB->numrows($query) ) {
                return true;
            }
            $query = $this->DB->query("insert into glpi_links_definitions (links_plugin, links_type) values ('$plugin_name', '$type_name')");
            if ( $query ) {
                $this->ID = $this->DB->insert_id($query);
                $this->name = $type_name;
                $queryString  = "create table glpi_links_$type_name ";
                $queryString .= "( FK_ID_origin int(11) not null, FK_link int(11), FK_ID_destination int(11) );";
                $query =  $this->DB->query($queryString);
                if ( $query ) return true;
            }
            return false;
        }
    
        /**
         * unregister 
         * 
         * search and delete in all glpi_types_<*> tables all references to <name>
         * destroy table glpi_types_<name>
         * unregister the plugin in glpi_link_definition
         *
         * @access public
         * @return void
         */
        function unregister ()
        {
            $query = $this->DB->query("select links_type from glpi_links_definitions where ID <>" . $this->ID . ";");
    
                    while ( $row = $this->DB->fetch_assoc($query) ) {
                $deletionString = 'delete from glpi_links_' . $row['links_type'] .
                          ' where FK_link=' . $this->ID . ';';
                if ( ! $this->DB->query($deletionString) ) return false;
            }
    
                    if ( ! $this->DB->query('drop table glpi_links_' . $this->name . ';') ) return false;
            if ( ! $this->DB->query('delete from links_type from glpi_links_definitions where ID=' . $this->ID . ";") ) return false;
                    return true;
        }
    
        /**
         * addLink 
         * 
         * add a link in glpi_types_<name>
         *
         * @param int $ID_origin 
         * @param string $type_destination or int ID of type_destination
         * @param int $ID_destination 
         * @access public
         * @return true if the link is successfully added
         */
        function addLink($ID_origin, $type_destination, $ID_destination)
        {
    
            $type_destination = ( (int)$type_destination ) ? $type_destination : $this->getIDByName($type_destination);
            if ( ! $type_destination ) return false;
    
            if ($this->isLinkExists($ID_origin, $type_destination, $ID_destination) ) return true;
            $queryString  = 'insert into glpi_links_' . $this->name .
                    " (FK_ID_origin, FK_ID_destination, FK_link) " .
                    "values ($ID_origin, $ID_destination, $type_destination)";
            $query = $this->DB->query($queryString);
    
            if ( $query ) return true;
            return false;
        }
    
        /**
         * deleteLink 
         * 
         * delete a link in glpi_types_<name>
         *
         * @param int $ID_origin 
         * @param string $type_destination or int ID of type_destination
         * @param int $ID_destination 
         * @access public
         * @return true if the link is successfully deleted
         */
        function deleteLink($ID_origin, $type_destination, $ID_destination)
        {
            $type_destination = ( (int)$type_destination ) ? $type_destination : $this->getIDByName($type_destination);
                    if ( ! $type_destination ) return false;
            if ( ! $this->isLinkExists($ID_origin, $type_destination, $ID_destination) ) return true;
    
            $queryString  = 'delete from glpi_links_' . $this->name .
                    " where FK_ID_origin=$ID_origin and FK_ID_destination=$ID_destination and FK_link=$type_destination;";
            $query = $this->DB->query($queryString);
    
            if ( $query ) return true;
                    return false;
        }
    
        /**
         * deleteItem 
         * 
         * search and delete in all glpi_types_<*> tables all references to <name, ID>
         *
         * @param int $ID or array of $ID of item(s) to which links have to be deleted
         * @access public
         * @return true if all links have been sucessfully deleted
         */
        function deleteItem($ID)
        {
            $query = $this->DB->query("select links_type from glpi_links_definitions where ID <>" . $this->ID . ";");
            $ID = ( is_array ($ID) ) ? $ID : array($ID);
    
            while ( $row = $this->DB->fetch_assoc($query) ) {
                foreach ( $ID as $v ) {
                    $deletionString = 'delete from glpi_links_' . $row['links_type'] .
                              ' where FK_link=' . $this->ID . " and FK_ID_destination=$v;";
                    if ( ! $this->DB->query($deletionString) ) return false;
                }
            }
            $deletionString = 'delete from glpi_links_' . $this->name .
                      ' where FK_ID_origin in (' . join (',', $ID) . ');';
            if ( $this->DB->query($deletionString) ) return true;
            return false;
    
        }    
    
        /**
         * getLinks 
         * 
         * search all link to ID with <type> if specified
         *
         * @param int $ID 
         * @param string $type or int ID of a type
         * @access public
         * @return array of link
         */
        function getLinks($ID, $type=0)
        {
            $type = ( (int)$type || $type == 0 ) ? $type : $this->getIDByName($type);
    
            $queryString = 'select * from glpi_links_' . $this->name . " where FK_ID_origin=$ID";
            $queryString .= ( $type ) ? " and FK_link=$type;" : ";";
    
            $query = $this->DB->query($queryString);
            $links = $types = array();
            while ( $row = $this->DB->fetch_assoc($query) ) {
                if ( ! isset($types[$row['FK_link']]) ) {
                    $types[$row['FK_link']] = $this->getNameByID($row['FK_link']);
                }
                $links[$types[$row['FK_link']]][] = $row['FK_ID_destination'];
            }
            return $links;
    
        }
    
        /**
         * getIDByName 
         * 
         * @param string $type 
         * @access public
         * @return void
         */
        function getIDByName($type="")
        {
            $type = ( $type == "" ) ? $this->name : $type;
            $query = $this->DB->query("select ID from glpi_links_definitions where links_type='$type'");
            if ( $query && $this->DB->numrows($query) ) {
                return $this->DB->result($query, 0, 'ID');
            }
            return 0;
        }
    
        /**
         * getNameByID 
         * 
         * @param int $ID 
         * @access public
         * @return void
         */
        function getNameByID($ID=0)
            {
                    $ID = ( $ID ) ? $ID : $this->ID;
                    $query = $this->DB->query("select links_type from glpi_links_definitions where ID=$ID");
                    if ( $query && $this->DB->numrows($query) ) {
                            return $this->DB->result($query, 0, 'links_type');
                    }
                    return 0;
            }
    
        /**
         * isLinkExists 
         * 
         * @param int $ID_origin 
         * @param string $type_destination or int ID of a type
         * @param int $ID_destination 
         * @access public
         * @return void
         */
        function isLinkExists($ID_origin, $type_destination, $ID_destination)
        {
            $type_destination = ( (int)$type_destination ) ? $type_destination : $this->getIDbyName($type_destination);
            if ( !$type_destination ) return false;
    
            $query = $this->DB->query('select * from glpi_links_' . $this->name .
                                              " where FK_ID_origin=$ID_origin and FK_ID_destination=$ID_destination and FK_link=$type_destination;");
    
            if ( $query && $this->DB->numrows($query) ) return true;
            return false;
        }
    }