<?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/>.
 * 
 */

class To
{

  // //////////////////////////////////////////////////
  // Méthodes publiques
  // //////////////////////////////////////////////////

  /**
   * Convertir l’utf-8 en windows-1252 pour compatibilité avec FPDF
   * => plus d’actualité car maintenant on utilise tFPDF qui gère l’UTF-8.
   * 
   * @param string $text
   * @return string
   */
  public static function pdf($text)
  {
    // Depuis le passage de FPDF à tFPDF, il faut au contraire envoyer de l’UTF-8 !
    // (string) ajouté car pour des notes écrites en gras dans le livret on s’est retrouvé avec des carrés ou des blancs... pas compris pourquoi...
    //
    // Olivier <oliver@fpdf.org> indique que tFPDF de gère pas "les caractères décomposés" (cf ;/_lib/info_FPDF.txt).
    // Il faut donc préalablement les recomposer : avec l’extension "intl" il suffit d’appeler Normalizer::normalize() sur les chaînes.
    // @see http://php.net/manual/fr/normalizer.normalize.php

    return function_exists('normalizer_normalize') ? normalizer_normalize((string)$text) : (string)$text ;
    //
    // Ancien code pour info
    // mb_substitute_character(0x00A0);  // Pour mettre " " au lieu de "?" en remplacement des caractères non convertis.
    // return mb_convert_encoding($text,'Windows-1252','UTF-8');
  }

  /**
   * Convertir un contenu en UTF-8 si besoin ; à effectuer en particulier pour les imports tableur.
   * Remarque : si on utilise utf8_encode() ou mb_convert_encoding() sans le paramètre 'Windows-1252' ça pose des pbs pour '’' 'Œ' 'œ' etc.
   * 
   * @param string $text
   * @return string
   */
  public static function utf8($text)
  {
    return ( (!perso_mb_detect_encoding_utf8($text)) || (!mb_check_encoding($text,'UTF-8')) ) ? mb_convert_encoding($text,'UTF-8','Windows-1252') : $text ;
  }

  /**
   * Nettoie le BOM éventuel d’un contenu UTF-8.
   * Code inspiré de http://libre-d-esprit.thinking-days.net/2009/03/et-bom-le-script/
   * 
   * @param string $text
   * @return string
   */
  public static function deleteBOM($text)
  {
    return (substr($text,0,3) == "\xEF\xBB\xBF") ? substr($text,3) : $text ; // Ne pas utiliser mb_substr() sinon ça ne fonctionne pas
  }

  /**
   * Afficher un équivalent texte de note pour une sortie CSV ou LaTeX.
   *
   * @param string $note
   * @return string
   */
  public static function note_sigle($note)
  {
    return isset($_SESSION['NOTE'][$note]) ? $_SESSION['NOTE'][$note]['SIGLE'] : $note ;
  }

  /**
   * Passer d’une date SQL AAAA-MM-JJ à une date française JJ/MM/AAAA.
   * Remarque : l’année peut éventuellement être sur 2 chiffres.
   *
   * @param string $date_sql AAAA-MM-JJ
   * @param string $without_year
   * @return string|NULL     JJ/MM/AAAA
   */
  public static function date_sql_to_french($date_sql, $without_year=FALSE)
  {
    if($date_sql===NULL) return (!$without_year) ? '00/00/0000' : '00/00' ;
    list($annee,$mois,$jour) = explode('-',$date_sql);
    return (!$without_year) ? $jour.'/'.$mois.'/'.$annee : $jour.'/'.$mois ;
  }

  /**
   * Passer d’une date SQL AAAA-MM-JJ HH:MM:SS à une date française JJ/MM/AAAA HH:MM.
   * Remarque : l’année peut éventuellement être sur 2 chiffres.
   *
   * @param string $datetime_sql AAAA-MM-JJ HH:MM:SS
   * @param bool   $return_time
   * @return string              JJ/MM/AAAA HHhMMmin
   */
  public static function datetime_sql_to_french( $datetime_sql , $return_time=TRUE )
  {
    list( $partie_jour , $partie_heure ) = explode( ' ' , $datetime_sql);
    list( $annee , $mois , $jour       ) = explode( '-' , $partie_jour);
    list( $heure , $minute , $seconde  ) = explode( ':' , $partie_heure);
    return ($return_time) ? $jour.'/'.$mois.'/'.$annee.' '.$heure.'h'.$minute.'min' : $jour.'/'.$mois.'/'.$annee ;
  }

  /**
   * Passer d’une date française JJ/MM/AAAA à une date SQL AAAA-MM-JJ.
   * Remarque : l’année peut éventuellement être sur 2 chiffres.
   *
   * @param string $date_fr JJ/MM/AAAA
   * @return string|NULL    AAAA-MM-JJ
   */
  public static function date_french_to_sql($date_fr)
  {
    if(!(int)substr($date_fr,0,2)) return NULL;
    list($jour,$mois,$annee) = explode('/',$date_fr);
    return $annee.'-'.$mois.'-'.$jour;
  }

  /**
   * Passer d’une date française JJ/MM/AAAA à une date J mois AAAA.
   * Remarque : l’année peut éventuellement être sur 2 chiffres.
   *
   * @param string $date_fr JJ/MM/AAAA
   * @return string         J mois AAAA
   */
  public static function date_french_to_texte($date_fr)
  {
    $tab_mois = array('01'=>'janvier','02'=>'février','03'=>'mars','04'=>'avril','05'=>'mai','06'=>'juin','07'=>'juillet','08'=>'août','09'=>'septembre','10'=>'octobre','11'=>'novembre','12'=>'décembre');
    if(!(int)substr($date_fr,0,2)) return '';
    list($jour,$mois,$annee) = explode('/',$date_fr);
    return intval($jour).' '.$tab_mois[$mois].' '.$annee;
  }

  /**
   * Déterminer le nombre d’années et de mois séparant deux dates françaises JJ/MM/AAAA.
   * Remarque : l’année peut éventuellement être sur 2 chiffres.
   *
   * Il existe des fonctions utilisables qu’à partir de PHP 5.2 ou 5.3.
   * @see http://fr.php.net/manual/fr/class.datetime.php
   * Ceci dit, le code élaboré est assez simple.
   *
   * @param string $date_deb_fr JJ/MM/AAAA
   * @param string $date_fin_fr JJ/MM/AAAA
   * @return array   { nb_annees , nb_mois }
   */
  public static function ecarts_mois_annee( $date_deb_fr , $date_fin_fr )
  {
    list($jour_deb,$mois_deb,$annee_deb) = explode('/',$date_deb_fr);
    list($jour_fin,$mois_fin,$annee_fin) = explode('/',$date_fin_fr);
    $nb_annees = $annee_fin - $annee_deb;
    $nb_mois   = $mois_fin - $mois_deb;
    if( ($mois_deb>$mois_fin) || (($mois_deb==$mois_fin)&&($jour_deb>$jour_fin)) )
    {
      $nb_annees-=1;
      $nb_mois+=12;
    }
    if($jour_deb>$jour_fin)
    {
      $nb_mois-=1;
    }
    return array($nb_annees,$nb_mois);
  }

  /**
   * Passer d’une date française JJ/MM/AAAA à l’âge X ans et Y mois.
   * Remarque : l’année peut éventuellement être sur 2 chiffres.
   *
   * @param string $date_fr JJ/MM/AAAA
   * @return string         X ans et Y mois
   */
  public static function texte_age($date_fr)
  {
    list($nb_annees,$nb_mois) = To::ecarts_mois_annee( $date_fr , TODAY_FR );
    $s_annee = ($nb_annees>1) ? 's' : '' ;
    $aff_mois = ($nb_mois) ? ' et '.$nb_mois.' mois' : '' ;
    return $nb_annees.' an'.$s_annee.$aff_mois;
  }

  /**
   * Passer d’une date française JJ/MM/AAAA à l’affichage de la date de naissance et de l’âge.
   * Remarque : l’année peut éventuellement être sur 2 chiffres.
   *
   * @param string $date_fr JJ/MM/AAAA
   * @return string
   */
  public static function texte_ligne_naissance($date_fr)
  {
    return 'Âge : '.To::texte_age($date_fr).' ('.To::date_french_to_texte($date_fr).').';
  }

  /**
   * Retourner un nom suivi d’un prénom (ou le contraire) dont l’un ou les deux sont éventuellement remplacés par leur initiale.
   * En cas de genre présent, la deuxième partie sera retirée si seule son initiale est demandée.
   *
   * @param string $partie1
   * @param bool   $is_initiale1
   * @param string $partie2
   * @param bool   $is_initiale2
   * @param string $genre   (facultatif)
   * @return string
   */
  public static function texte_genre_identite( $partie1 , $is_initiale1 , $partie2 , $is_initiale2 , $genre='I' )
  {
    $tab_genre = array( 'M'=>'M.' , 'F'=>'Mme' );
    $genre = ($genre!='I') ? $tab_genre[$genre] : '' ;
    // Ne pas utiliser la syntaxe $partie[0] qui pose pb pour les majuscules accentuées.
    $partie1 = ( $is_initiale1 && strlen($partie1) ) ? mb_substr($partie1,0,1).'.' : $partie1 ;
    $partie2 = ( $is_initiale2 && strlen($partie2) ) ? mb_substr($partie2,0,1).'.' : $partie2 ;
    return ($genre && $is_initiale2) ? trim($genre.' '.$partie1) : trim($genre.' '.$partie1.' '.$partie2) ;
  }

  /**
   * Retourner un nom suivi d’un prénom, ou le contraire si l’ordre est par prénom.
   *
   * @param string $nom
   * @param string $prenom
   * @param string $ordre   nom | prenom | classe | identifiant de plan de classe
   * @return string
   */
  public static function texte_eleve_identite( $nom , $prenom , $ordre='nom' )
  {
    return ($ordre!='prenom') ? $nom.' '.$prenom : $prenom.' '.$nom ;
  }

  /**
   * Renvoyer le 1er jour de l’année scolaire en cours, au format français JJ/MM/AAAA ou SQL AAAA-MM-JJ.
   *
   * @param string $format           'sql'|'fr'
   * @param int    $annee_decalage   facultatif, pour les années scolaires précédentes ou suivantes
   * @return string
   */
  public static function jour_debut_annee_scolaire( $format , $annee_decalage=0 )
  {
    $jour  = '01';
    $mois  = sprintf("%02u",$_SESSION['MOIS_BASCULE_ANNEE_SCOLAIRE']);
    $annee = (date('n')<$_SESSION['MOIS_BASCULE_ANNEE_SCOLAIRE']) ? date('Y')+$annee_decalage-1 : date('Y')+$annee_decalage ;
    return ($format=='sql') ? $annee.'-'.$mois.'-'.$jour : $jour.'/'.$mois.'/'.$annee ;
  }

  /**
   * Renvoyer le dernier jour de l’année scolaire en cours, au format français JJ/MM/AAAA ou SQL AAAA-MM-JJ.
   *
   * @param string $format           'sql'|'fr'
   * @param int    $annee_decalage   facultatif, pour les années scolaires précédentes ou suivantes
   * @return string
   */
  public static function jour_fin_annee_scolaire( $format , $annee_decalage=0 )
  {
    $jour  = '01';
    $mois  = sprintf("%02u",$_SESSION['MOIS_BASCULE_ANNEE_SCOLAIRE']);
    $annee = (date('n')<$_SESSION['MOIS_BASCULE_ANNEE_SCOLAIRE']) ? date('Y')+$annee_decalage : date('Y')+$annee_decalage+1 ;
    $date_veille_stamp = strtotime($annee.'-'.$mois.'-'.$jour.' -1 day');
    return ($format=='sql') ? date('Y-m-d',$date_veille_stamp) : date('d/m/Y',$date_veille_stamp) ;
  }

  /**
   * Renvoyer le jour correspondant à la veille ou le lendemain du jour transmis, au format français JJ/MM/AAAA ou SQL AAAA-MM-JJ.
   *
   * @param string $date
   * @param string $decalage '+1' | '-1'
   * @param string $format   'sql'|'fr'
   * @return string
   */
  public static function jour_decale( $date , $decalage , $format )
  {
    if($format=='sql')
    {
      list($annee,$mois,$jour) = explode('-',$date);
    }
    else
    {
      list($jour,$mois,$annee) = explode('/',$date);
    }
    $date_decale_stamp = strtotime($annee.'-'.$mois.'-'.$jour.' '.$decalage.' day');
    return ($format=='sql') ? date('Y-m-d',$date_decale_stamp) : date('d/m/Y',$date_decale_stamp) ;
  }

  /**
   * Retourner le nb de mois restants avant la fin de l’année scolaire
   *
   * @param void
   * @return int
   */
  public static function mois_restants_annee_scolaire()
  {
    list($nb_annees,$nb_mois) = To::ecarts_mois_annee( TODAY_FR , To::jour_fin_annee_scolaire('fr') );
    return $nb_annees*12 + $nb_mois;
  }

  /**
   * Renvoyer l’année de session du DNB.
   * N’EST PLUS UTILISÉ AU 08/2017
   *
   * @param void
   * @return string
   */
  public static function annee_session_brevet()
  {
    $mois_actuel    = date('n');
    $annee_actuelle = date('Y');
    $mois_bascule   = $_SESSION['MOIS_BASCULE_ANNEE_SCOLAIRE'];
    if($mois_bascule==1)
    {
      return $annee_actuelle;
    }
    else if($mois_actuel < $mois_bascule)
    {
      return $annee_actuelle;
    }
    else
    {
      return $annee_actuelle+1;
    }
  }

  /**
   * Renvoyer l’année scolaire en cours.
   *
   * format 'texte'  : Année scolaire 2016 / 2017
   * format 'code'   : 2016-2017
   * format 'siecle' : 2016
   *
   * @param string   $format           'texte' | 'code' | 'siecle'
   * @param int      $annee_decalage   facultatif, pour les années scolaires précédentes ou suivantes
   * @return string
   */
  public static function annee_scolaire( $format , $annee_decalage=0 )
  {
    $mois_actuel    = date('n');
    $annee_actuelle = date('Y')+$annee_decalage;
    $mois_bascule   = $_SESSION['MOIS_BASCULE_ANNEE_SCOLAIRE'];
    if($format=='siecle')
    {
      return ($mois_actuel >= $mois_bascule) ? (string)$annee_actuelle : (string)($annee_actuelle-1) ;
    }
    $sep = ($format=='code') ? '-' : ' / ' ;
    $txt = ($format=='code') ? '' : Lang::_('Année scolaire').' ' ;
    if($mois_bascule==1)
    {
      return $txt.$annee_actuelle;
    }
    else if($mois_actuel < $mois_bascule)
    {
      return $txt.($annee_actuelle-1).$sep.$annee_actuelle;
    }
    else
    {
      return $txt.$annee_actuelle.$sep.($annee_actuelle+1);
    }
  }

}

?>