Aller au contenu

Les addons (LSaddon)

Les LSaddons sont utilisés pour implémenter dans LdapSaisie des fonctionnalités spécifiques tel que :

  • le support d'une famille d'attributs spécifiques (POSIX, Samba, SUPANN…) par le biais de méthodes de génération de la valeur de ces attributs par exemple (paramètre generate_function) ;
  • des tâches communes et génériques (envoi de mails, connexion FTP/SSH…) ;
  • l'implémentation de déclencheurs spécifiques à votre environnement : création automatique du dossier client sur le serveur de fichiers de l'entreprise, création de la boite mail de l'utilisateur… ;
  • l'implémentation d'action personnalisée sur les objets (synchronisation, archivage…) ou sur les résultats de recherches (export, rapport personnalisé…) ;

Structure d'écriture

L'écriture d'un LSaddon doit respecter une structure suffisamment souple afin de ne pas être un frein à vos contributions, tout en permettant d'assurer la bonne intégration de votre contribution au projet. Le code que vous écrirez sera réparti dans deux fichiers :

  • conf/LSaddons/config.LSaddons.[addon name].php

    Ce fichier contiendra la configuration de votre LSaddon. On y retrouvera la déclaration de constances et/ou variables de configuration permettant d'adapter votre LSaddon à une installation et à un environnement.

  • includes/addons/LSaddons.[addon name].php

    Ce fichier contiendra le code à proprement dit de votre LSaddon.

    Structure du fichier includes/addons/LSaddons.[addon name].php :

    <?php
    
    /*
     * Error messages
     */
    
    // Support error messages
    LSerror :: defineError('MYADDON_SUPPORT_01',
      ___("MYADDON Support :  Unable to load %{dep}.")
    );
    
    LSerror :: defineError('MYADDON_SUPPORT_02',
      ___("MYADDON Support : The constant %{const} is not defined.")
    );
    
    // Other orror messages
    LSerror :: defineError('MYADDON_01',
      ___("An error : %{msg}.")
    );
    
    LSerror :: defineError('MYADDON_02',
      ___("An other error about %{about} : %{msg}")
    );
    
    LSerror :: defineError('MYADDON_03',
      ___("Unknown error.")
    );
    
    /**
     * Verify support of my addon by LdapSaisie
     *
     * @author My Name <my.email@example.com>
     *
     * @return boolean true if my addon is totaly supported, false in other cases
     **/
    function LSaddon_myaddon_support() {
    
      $retval=true;
    
      // Check/load dependencies
      if ( !class_exists('mylib') ) {
        if ( !LSsession::includeFile(LS_LIB_DIR . 'class.mylib.php') ) {
          LSerror :: addErrorCode('MYADDON_SUPPORT_01', 'mylib');
          $retval=false;
        }
      }
    
    
      $MUST_DEFINE_CONST= array(
        'LS_MYADDON_CONF_O1',
        'LS_MYADDON_CONF_O2',
        ...
      );
    
      foreach($MUST_DEFINE_CONST as $const) {
        if ( (!defined($const)) || (constant($const) == "")) {
          LSerror :: addErrorCode('MYADDON_SUPPORT_02',$const);
          $retval=false;
        }
      }
    
      if ($retval) {
          // Register LSaddon view using LSsession :: registerLSaddonView()
    
          if (php_sapi_name() == 'cli') {
              // Register LSaddon CLI command using LScli :: add_command()
          }
      }
    
      return $retval;
    }
    
    /**
     * My first function
     *
     * Description of this wonderfull function
     *
     * @author My Name <my.email@example.com>
     *
     * @return [type(s) of returned values (pipe separator)] Description of the return of this function
     **/
    function myaddon_first_function($arg1, $arg2) {
      // Do some stuff
      if (something) {
        LSerror :: addErrorCode(
          'MYADDON_01',
          'something went wrong'    // Error LSformat unique argument
        );
        return false;
      }
    
      if (something else) {
        LSerror :: addErrorCode(
          'MYADDON_02',
          array(                    // Error LSformat arguments
            'about' => 'second step',
            'msg' => 'something went wrong'
          )
        );
        return false;
      }
    
      if (still something else) {
        LSerror :: addErrorCode('MYADDON_03'); // Error without argument
        return false;
      }
      return true;
    }
    
    [...]
    
    // Defined custom CLI commands functions only on CLI context
    if (php_sapi_name() != 'cli')
        return true;  // Always return true to avoid some warning in log
    
    // Defined functions handling custom CLI commands and optionnaly
    // their arguments autocompleter functions.
    

Par convention, la structure de ce fichier est toujours à peu près la même:

  • On déclare tout d'abord les messages d'erreurs qui seront potentiellement émis par notre LSaddon en commençant par les messages d'erreurs liés au support de cet LSaddon. On utilise pour cela la méthode LSerror :: defineError() qui attends en premier argument, l'identifiant du message d'erreur et en tant que second argument, le LSformat du message d'erreur. Par convention, les identifiants des messages d'erreurs seront en majuscule et préfixés du nom du LSaddon.
  • On déclare ensuite une fonction LSaddon_[myaddon]_support qui sera exécutée lors du chargement de l'addon et qui permettra de s'assurer du support de celui-ci. Cette fonction devra retourner True si c'est le cas ou False dans le cas contraire.

    Cette fonction s'assura notamment :

  • On déclare ensuite les fonctions, classes et éléments fournis et manipulés par l'addon.
  • Si notre addon offre des commandes CLI personnalisées, les fonctions les implémentant ne seront définies, dans un souci de performance, que dans un contexte ou elles seraient potentiellement appelables, c'est à dire dans un contexte d'exécution CLI. Pour cela, nous utilisons communément la fonction php_sapi_name pour déterminer le contexte d'exécution et si celui-ci vaut cli, nous stoppons l'exécution du reste du code du fichier via un return true.

    Note

    Il est important dans ce contexte de ne jamais retourner autre chose que True pour éviter tout message d'erreur inutile dans les logs.

  • On déclare, pour finir, les fonctions implémentant les commandes CLI personnalisées et leur éventuelle fonction gérant l'autocomplétion des arguments qu'elles acceptent.