# Les addons (LSaddon)

Les [LSaddons](../../conf/index.md#configuration-des-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](../../conf/index.md#declencheurs_1) 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 de [vues personnalisées](#les-vues-personnalisees) proposées dans l'interface

- l'implémentation d'action personnalisée sur les [objets](../../conf/index.md#customactions) (synchronisation,
  archivage…) ou sur les [résultats de recherches](../../conf/LSobject/LSsearch.md#customactions)
  (export, rapport personnalisé…) ;

## Structure d'écriture

L'écriture d'un [LSaddon](../../conf/index.md#configuration-des-lsaddons) 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](../../conf/index.md#configuration-des-lsaddons).
  On y retrouvera la déclaration de constances et/ou variables de configuration permettant d'adapter
  votre [LSaddon](../../conf/index.md#configuration-des-lsaddons) à une installation et à un environnement.

- `includes/addons/LSaddons.[addon name].php`

  Ce fichier contiendra le code à proprement dit de votre [LSaddon](../../conf/index.md#configuration-des-lsaddons).

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

  ```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](../../conf/index.md#configuration-des-lsaddons) en commençant par les messages d'erreurs liés au
  support de cet [LSaddon](../../conf/index.md#configuration-des-lsaddons). 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](../../conf/global/LSformat.md#format-parametrable) du message d'erreur. Par convention,
  les identifiants des messages d'erreurs seront en majuscule et préfixés du nom du
  [LSaddon](../../conf/index.md#configuration-des-lsaddons).

- 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 :

  - que les librairies dont l'addon dépends sont bien chargées et fonctionnelles ;
  - que ses variables et constantes de configuration sont bien définies ;
  - de déclarer [les vues personnalisées](#les-vues-personnalisees) fournies par cet
    [LSaddon](../../conf/index.md#configuration-des-lsaddons) ;
  - de déclarer [les commandes *CLI* personnalisées](#les-commandes-cli-personnalisees) fournies par
    cet [LSaddon](../../conf/index.md#configuration-des-lsaddons) ;

- 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-commandes-cli-personnalisees), 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](#les-commandes-cli-personnalisees) et leur éventuelle fonction
  gérant l'autocomplétion des arguments qu'elles acceptent.
