<?php
/**
 * @version $Id$
 * @author Thomas Crespin <thomas.crespin@sesamath.net>
 * @copyright Thomas Crespin 2009-2022
 * 
 * ****************************************************************************************************
 * SACoche <https://sacoche.sesamath.net> - Suivi d’Acquisitions de Compétences
 * © Thomas Crespin pour Sésamath <https://www.sesamath.net> - Tous droits réservés.
 * Logiciel placé sous la licence libre Affero GPL 3 <https://www.gnu.org/licenses/agpl-3.0.html>.
 * ****************************************************************************************************
 * 
 * Ce fichier est une partie de SACoche.
 * 
 * SACoche est un logiciel libre ; vous pouvez le redistribuer ou le modifier suivant les termes 
 * de la “GNU Affero General Public License” telle que publiée par la Free Software Foundation :
 * soit la version 3 de cette licence, soit (à votre gré) toute version ultérieure.
 * 
 * SACoche est distribué dans l’espoir qu’il vous sera utile, mais SANS AUCUNE GARANTIE :
 * sans même la garantie implicite de COMMERCIALISABILITÉ ni d’ADÉQUATION À UN OBJECTIF PARTICULIER.
 * Consultez la Licence Publique Générale GNU Affero pour plus de détails.
 * 
 * Vous devriez avoir reçu une copie de la Licence Publique Générale GNU Affero avec SACoche ;
 * si ce n’est pas le cas, consultez : <http://www.gnu.org/licenses/>.
 * 
 */

if(!defined('SACoche')) {exit('Ce fichier ne peut être appelé directement !');}
if($_SESSION['SESAMATH_ID']==ID_DEMO){Json::end( FALSE , 'Action désactivée pour la démo.' );}

// malgré encodeURIComponent() quand PHP reçoit la chaîne il traite %2C comme les autres virgules séparant les données, d’où l’usage d’un autre séparateur
$action            = Clean::post('f_action'       , 'texte');
$tab_catalogue_id  = Clean::post('f_catalogue_id' , array('array',','));
$tab_catalogue_val = Clean::post('f_catalogue_val', array('array','⁞'));

define('CATEGORIE_LENGTH',50);
define('APPRECIATION_LENGTH',500);

// ////////////////////////////////////////////////////////////////////////////////////////////////////
// Retourner les options (formulaire select) d’un catalogue d’appréciations
// ////////////////////////////////////////////////////////////////////////////////////////////////////

if($action=='recuperer_options')
{
  $tab_catalogue_user = DB_STRUCTURE_CATALOGUE::DB_OPT_lister_appreciations($_SESSION['USER_ID']);
  $options_catalogue_user = empty($tab_catalogue_user) ? '<option value="0" disabled>Aucune appréciation ne figure dans votre catalogue.</option>' : HtmlForm::afficher_select( $tab_catalogue_user , '' /*select_nom*/ , '' /*option_first*/ , FALSE /*selection*/ , 'appr_categorie' /*optgroup*/ ) ;
  Json::end( TRUE , $options_catalogue_user );
}

// ////////////////////////////////////////////////////////////////////////////////////////////////////
// Enregistrer catégories et appréciations
// ////////////////////////////////////////////////////////////////////////////////////////////////////

if($action=='enregistrer')
{
  // Besoin de retourner les nouveaux identifiants éventuels
  $tab_retour = array();
  $is_new_id = FALSE;
  // On récupère le contenu de la base afin de la comparer à l’existant
  $tab_categories_bdd    = array();
  $tab_appreciations_bdd = array();
  $DB_TAB = DB_STRUCTURE_CATALOGUE::DB_lister_appreciations_avec_categories($_SESSION['USER_ID']);
  if(!empty($DB_TAB))
  {
    $categorie_id = 0;
    foreach($DB_TAB as $DB_ROW)
    {
      if($DB_ROW['categorie_id']!=$categorie_id)
      {
        $tab_categories_bdd[$DB_ROW['categorie_id']] = array(
          'ordre'   => $DB_ROW['categorie_ordre'],
          'contenu' => $DB_ROW['categorie_titre'],
        );
        $categorie_id = $DB_ROW['categorie_id'];
      }
      if(!empty($DB_ROW['appreciation_id']))
      {
        $tab_appreciations_bdd[$DB_ROW['appreciation_id']] = array(
          'cat_id'  => $DB_ROW['categorie_id'],
          'ordre'   => $DB_ROW['appreciation_ordre'],
          'contenu' => $DB_ROW['appreciation_contenu'],
        );
      }
    }
  }
  // On récupère ce qui est transmis ; au passage on ajoute les nouveaux éléments et on modifie ceux qui le nécessitent
  if(!empty($tab_catalogue_id))
  {
    if( count($tab_catalogue_id) != count($tab_catalogue_val) )
    {
      Json::end( FALSE , 'Erreur avec les données transmises !<br>'.pathinfo(__FILE__,PATHINFO_FILENAME).':'.__LINE__ );
    }
    if( substr($tab_catalogue_id[0],0,3) == 'app' )
    {
      // Catégorie par défaut si appréciations sans catégorie
      array_unshift( $tab_catalogue_id  , 'cat_0' );
      array_unshift( $tab_catalogue_val , 'Catégorie par défaut' );
    }
    $categorie_ordre = 0;
    foreach($tab_catalogue_id as $key => $ref)
    {
      list($objet,$id) = explode('_',$ref);
      $contenu = $tab_catalogue_val[$key];
      if($objet=='cat')
      {
        $contenu = Clean::texte($contenu,CATEGORIE_LENGTH);
        $categorie_ordre++;
        $appreciation_ordre = 0;
        if(!$id)
        {
          $categorie_id = DB_STRUCTURE_CATALOGUE::DB_ajouter_categorie( $_SESSION['USER_ID'] , $categorie_ordre , $contenu );
          $is_new_id = TRUE;
        }
        else
        {
          $categorie_id = $id;
          if( !isset($tab_categories_bdd[$categorie_id]) )
          {
            Json::end( FALSE , 'Erreur catégorie n°'.$categorie_id.' introuvable !' );
          }
          $info_bdd = $tab_categories_bdd[$categorie_id];
          if( ($info_bdd['ordre']!=$categorie_ordre) || ($info_bdd['contenu']!=$contenu) )
          {
            DB_STRUCTURE_CATALOGUE::DB_modifier_categorie( $categorie_id , $_SESSION['USER_ID'] , $categorie_ordre , $contenu );
          }
          unset($tab_categories_bdd[$categorie_id]);
        }
        $tab_retour[] = '<li id="cat_'.$categorie_id.'"><span class="b u">'.html($contenu).'</span>{{QC}}</li>';
      }
      else
      {
        $contenu = Clean::texte($contenu,APPRECIATION_LENGTH);
        $appreciation_ordre++;
        if(!$id)
        {
          $appreciation_id = DB_STRUCTURE_CATALOGUE::DB_ajouter_appreciation( $_SESSION['USER_ID'] , $categorie_id , $appreciation_ordre , $contenu ) ;
          $is_new_id = TRUE;
        }
        else
        {
          $appreciation_id = $id;
          if( !isset($tab_appreciations_bdd[$appreciation_id]) )
          {
            Json::end( FALSE , 'Erreur appréciation n°'.$appreciation_id.' introuvable !' );
          }
          $info_bdd = $tab_appreciations_bdd[$appreciation_id];
          if( ($info_bdd['cat_id']!=$categorie_id) || ($info_bdd['ordre']!=$appreciation_ordre) || ($info_bdd['contenu']!=$contenu) )
          {
            DB_STRUCTURE_CATALOGUE::DB_modifier_appreciation( $appreciation_id , $_SESSION['USER_ID'] , $categorie_id , $appreciation_ordre , $contenu );
          }
          unset($tab_appreciations_bdd[$appreciation_id]);
        }
        $tab_retour[] = '<li id="app_'.$appreciation_id.'"><span>'.html($contenu).'</span>{{QA}}</li>';
      }
    }
  }
  // Il reste à supprimer ce qui reste
  foreach($tab_categories_bdd as $categorie_id => $tab)
  {
    DB_STRUCTURE_CATALOGUE::DB_supprimer_categorie( $categorie_id );
  }
  foreach($tab_appreciations_bdd as $appreciation_id => $tab)
  {
    DB_STRUCTURE_CATALOGUE::DB_supprimer_appreciation( $appreciation_id );
  }
  // Terminé !
  $retour = ($is_new_id) ? implode('',$tab_retour) : NULL ;
  Json::end( TRUE , $retour );
}

// ////////////////////////////////////////////////////////////////////////////////////////////////////
// Exporter les données dans un fichier
// ////////////////////////////////////////////////////////////////////////////////////////////////////

if($action=='export')
{
  // Lister les données de l’utilisateur
  $xml_categorie = '  <categories>'."\r\n";
  $xml_appreciation = '  <appreciations>'."\r\n";
  $DB_TAB = DB_STRUCTURE_CATALOGUE::DB_lister_appreciations_avec_categories($_SESSION['USER_ID']);
  if(!empty($DB_TAB))
  {
    $categorie_id = 0;
    foreach($DB_TAB as $DB_ROW)
    {
      if($DB_ROW['categorie_id']!=$categorie_id)
      {
        $categorie_id = $DB_ROW['categorie_id'];
        $xml_categorie.= '    <categorie id="'.$categorie_id.'" titre="'.html($DB_ROW['categorie_titre']).'">'."\r\n";
      }
      if(!empty($DB_ROW['appreciation_id']))
      {
        $xml_appreciation.= '    <appreciation categorie="'.$categorie_id.'" contenu="'.html($DB_ROW['appreciation_contenu']).'">'."\r\n";
      }
    }
  }
  $xml_categorie.= '  </categories>'."\r\n";
  $xml_appreciation.= '  </appreciations>'."\r\n";
  // On enregistre le fichier
  $fichier_nom = 'catalogue_appreciations_'.$_SESSION['BASE'].'_'.$_SESSION['USER_ID'].'_'.Clean::fichier($_SESSION['USER_NOM'].' '.$_SESSION['USER_PRENOM']).'_'.FileSystem::generer_fin_nom_fichier__date_et_alea().'.xml';
  $fichier_contenu = '<catalogue_appreciations>'."\r\n".$xml_categorie.$xml_appreciation.'</catalogue_appreciations>'."\r\n";
  FileSystem::ecrire_fichier( CHEMIN_DOSSIER_EXPORT.$fichier_nom , $fichier_contenu );
  // Afficher le retour
  Json::end( TRUE , '<a target="_blank" rel="noopener noreferrer" href="./force_download.php?fichier='.$fichier_nom.'"><span class="file file_xml">Fichier d’export au format <em>xml</em>.' );
}

// ////////////////////////////////////////////////////////////////////////////////////////////////////
// Importer un fichier d’appréciations
// ////////////////////////////////////////////////////////////////////////////////////////////////////

if($action=='import')
{
  // Récupération du fichier
  $fichier_upload_nom = 'catalogue_appreciations_'.$_SESSION['BASE'].'_'.FileSystem::generer_fin_nom_fichier__date_et_alea().'.xml';
  $result = FileSystem::recuperer_upload( CHEMIN_DOSSIER_IMPORT /*fichier_chemin*/ , $fichier_upload_nom /*fichier_nom*/ , array('xml') /*tab_extensions_autorisees*/ , NULL /*tab_extensions_interdites*/ , NULL /*taille_maxi*/ , NULL /*filename_in_zip*/ );
  if($result!==TRUE)
  {
    Json::end( FALSE , $result );
  }
  // Vérification du fichier
  $xml = @simplexml_load_file(CHEMIN_DOSSIER_IMPORT.$fichier_upload_nom);
  if($xml===FALSE)
  {
    Json::end( FALSE , 'Le fichier transmis n’est pas un XML valide !' );
  }
  if( !$xml->categories || !$xml->appreciations )
  {
    Json::end( FALSE , 'Le fichier transmis ne comporte pas les données attendues !' );
  }
  // Pour comparer avec la base (et éventuellement fusionner)
  $tab_base_categorie = array();
  $tab_base_appreciation = array();
  $DB_TAB = DB_STRUCTURE_CATALOGUE::DB_lister_appreciations_avec_categories($_SESSION['USER_ID']);
  if(!empty($DB_TAB))
  {
    $categorie_id = 0;
    foreach($DB_TAB as $DB_ROW)
    {
      if($DB_ROW['categorie_id']!=$categorie_id)
      {
        $categorie_id = $DB_ROW['categorie_id'];
        $tab_base_categorie[$categorie_id] = $DB_ROW['categorie_titre'];
      }
      if(!empty($DB_ROW['appreciation_id']))
      {
        $tab_base_appreciation[$categorie_id][$DB_ROW['appreciation_id']] = $DB_ROW['appreciation_contenu'];
      }
    }
  }
  // On récupère le contenu du fichier
  $tab_categorie = array();
  $tab_appreciation = array();
  if($xml->categories->categorie)
  {
    foreach ($xml->categories->categorie as $categorie)
    {
      $categorie_id = Clean::entier($categorie->attributes()->id);
      $categorie_titre = Clean::texte($categorie->attributes()->titre,CATEGORIE_LENGTH);
      $find_categorie_titre = array_search( $categorie_titre , $tab_base_categorie ); // FALSE si non trouvée
      $tab_categorie[$categorie_id] = array(
        'base_id' => $find_categorie_titre,
        'titre'   => $categorie_titre,
      );
    }
  }
  if($xml->appreciations->appreciation)
  {
    foreach ($xml->appreciations->appreciation as $appreciation)
    {
      $categorie_id = Clean::entier($appreciation->attributes()->categorie);
      $appreciation_contenu = Clean::texte($appreciation->attributes()->contenu,APPRECIATION_LENGTH);
      if( isset($tab_categorie[$categorie_id]) )
      {
        $find_appreciation_contenu = ($tab_categorie[$categorie_id]['base_id']) ? array_search( $appreciation_contenu , $tab_base_appreciation[$tab_categorie[$categorie_id]['base_id']] ) : FALSE ; // FALSE si non trouvée
        $tab_appreciation[] = array(
          'base_id'      => $find_appreciation_contenu,
          'categorie_id' => $categorie_id,
          'contenu'      => $appreciation_contenu,
        );
      }
    }
  }
  // Insertion en base et décompte pour le bilan
  $nb_categories_valides = count($tab_categorie);
  $nb_appreciations_valides = count($tab_appreciation);
  $nb_categories_ajoutees = 0;
  $nb_appreciations_ajoutees = 0;
  $categorie_ordre = count($tab_base_categorie) + 1;
  foreach($tab_categorie as $categorie_id => $tab)
  {
    if( !$tab['base_id'] )
    {
      $tab_categorie[$categorie_id]['base_id'] = DB_STRUCTURE_CATALOGUE::DB_ajouter_categorie( $_SESSION['USER_ID'] , $categorie_ordre , $tab['titre'] );
      $nb_categories_ajoutees++;
      $categorie_ordre++;
    }
  }
  $categorie_id = 0;
  foreach($tab_appreciation as $tab)
  {
    if( !$tab['base_id'] )
    {
      $categorie_base_id = $tab_categorie[$tab['categorie_id']]['base_id'];
      if($tab['categorie_id']!=$categorie_id)
      {
        $categorie_id = $tab['categorie_id'];
        $appreciation_ordre = isset($tab_base_appreciation[$categorie_base_id]) ? count($tab_base_appreciation[$categorie_base_id]) + 1 : 1 ;
      }
      $appreciation_id = DB_STRUCTURE_CATALOGUE::DB_ajouter_appreciation( $_SESSION['USER_ID'] , $categorie_base_id , $appreciation_ordre , $tab['contenu'] );
      $nb_appreciations_ajoutees++;
      $appreciation_ordre++;
    }
  }
  $scv = ($nb_categories_valides>1)  ? 's' : '' ;
  $sca = ($nb_categories_ajoutees>1) ? 's' : '' ;
  $sav = ($nb_appreciations_valides>1)  ? 's' : '' ;
  $saa = ($nb_appreciations_ajoutees>1) ? 's' : '' ;
  // Afficher le retour
  Json::end( TRUE , $nb_categories_valides.' catégorie'.$scv.' trouvée'.$scv.', dont '.$nb_categories_ajoutees.' ajoutée'.$sca.', et '.$nb_appreciations_valides.' appréciation'.$sav.' trouvée'.$sav.', dont '.$nb_appreciations_ajoutees.' ajoutée'.$saa.' ; rechargement dans 5 secondes&hellip;' );
}

// ////////////////////////////////////////////////////////////////////////////////////////////////////
// Il se peut que rien n’ait été récupéré à cause de l’upload d’un fichier trop lourd
// ////////////////////////////////////////////////////////////////////////////////////////////////////

if(empty($_POST))
{
  Json::end( FALSE , 'Aucune donnée reçue ! Fichier trop lourd ? '.InfoServeur::minimum_limitations_upload() );
}

// ////////////////////////////////////////////////////////////////////////////////////////////////////
// On ne devrait pas en arriver là...
// ////////////////////////////////////////////////////////////////////////////////////////////////////

Json::end( FALSE , 'Erreur avec les données transmises !<br>'.pathinfo(__FILE__,PATHINFO_FILENAME).':'.__LINE__ );

?>
