<?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 Cookie
{

  // //////////////////////////////////////////////////
  // Méthodes privées (internes)
  // //////////////////////////////////////////////////

  // Paramètres aussi définis dans le fichier javascript de gestion des cookies et dans la classe Session
  private static $path     = '/'; // par défaut
  private static $domain   = '';
  private static $secure   = FALSE;
  private static $httponly = FALSE;
  private static $samesite = 'Lax'; // @see https://developer.mozilla.org/fr/docs/Web/HTTP/Headers/Set-Cookie/SameSite

  /**
   * Méthode pour indiquer le domaine
   * 
   * /!\ N’est plus utilisé (et $domain définit à '' au début) : voir explication dans la méthode Cookie::set().
   * 
   * @return string
   */
  private static function domaine()
  {
    if(is_null(Cookie::$domain))
    {
      // HOST peut contenir le port, auquel cas il faut l’en retirer
      Cookie::$domain = strtok(HOST,':');
    }
    return Cookie::$domain;
  }

  /**
   * Méthode pour écrire la valeur du cookie (création / modification ou suppression)
   * @see https://www.php.net/setcookie
   * 
   * @param string $cookie_name
   * @param mixed  $cookie_value
   * @param int    $expires
   * @return void
   */
  private static function set( $cookie_name , $cookie_value , $expires )
  {
    // Pour éviter l’avertissement "Le cookie sera bientôt rejeté car son attribut « SameSite » est défini sur « None » ou une valeur invalide et il n’a pas l’attribut « secure »."
    // - paramètre "secure" à TRUE ne fonctionne que si protocole HTTPS forcé
    // - paramètre "SameSite" à "Lax" si sous-domaines ou "Strict" si restreint au domaine
    // Attention, si on précise un domaine, par exemple "sacoche.sesamath.net", alors il est enregistré par PHP comme étant ".sacoche.sesamath.net" (pour inclure de force les sous-domaines...)
    // et du coup le paramétrage "Strict" ne retrouve pas le cookie, du coup on reste à "Lax" par précaution.
    // Pour la même raison, le domaine n’est plus précisé, la méthode Cookie::domaine() n’est plus utilisée.
    if(version_compare(PHP_VERSION,'7.3','<'))
    {
      setcookie( $cookie_name , $cookie_value , $expires , Cookie::$path.'; samesite='.Cookie::$samesite , Cookie::domaine() , Cookie::$secure , Cookie::$httponly );
    }
    else
    {
      setcookie( $cookie_name , $cookie_value , array(
        'expires'  => $expires,
        'path'     => Cookie::$path,
        'domain'   => Cookie::$domain,
        'secure'   => Cookie::$secure,
        'httponly' => Cookie::$httponly,
        'samesite' => Cookie::$samesite,
      ) );
    }
  }

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

  /**
   * Définir un cookie
   * 
   * @param string $cookie_name
   * @param mixed  $cookie_value
   * @param int    $cookie_time   le délai en secondes (ou rien pour ne pas expirer)
   * @return void
   */
  public static function definir( $cookie_name , $cookie_value , $cookie_time=NULL )
  {
    $expires = $cookie_time ? $_SERVER['REQUEST_TIME']+$cookie_time : 0 ;
    Cookie::set( $cookie_name , $cookie_value , $expires );
  }

  /**
   * Effacer un cookie
   * 
   * @param string $cookie_name
   * @return void
   */
  public static function effacer( $cookie_name )
  {
    $expires  = $_SERVER['REQUEST_TIME']-42000;
    Cookie::set( $cookie_name , '' /*value*/ , $expires );
  }

  /**
   * Définir un cookie avec le contenu de paramètres transmis en GET puis rappeler la page
   * 
   * @param string $query_string   éventuellement avec 'url_redirection' en dernier paramètre
   * @return void
   */
  public static function save_get_and_exit_reload( $query_string )
  {
    Cookie::definir( COOKIE_MEMOGET , $query_string , 300 /* 60*5 = 5 min */ );
    $param_redir_pos = mb_strpos($query_string,'&url_redirection');
    $param_sans_redir = ($param_redir_pos) ? mb_substr( $query_string , 0 , $param_redir_pos ) : $query_string ; // J’ai déjà eu un msg d’erreur car il n’aime pas les chaines trop longues + Pas la peine d’encombrer avec le paramètre de redirection qui sera retrouvé dans le cookie de toutes façons
    exit_redirection(URL_BASE.$_SERVER['SCRIPT_NAME'].'?'.$param_sans_redir);
  }

  /**
   * Définir un cookie avec le contenu de paramètres transmis en GET puis rappeler la page
   * 
   * @return void
   */
  public static function load_get()
  {
    $tab_get = explode('&',$_COOKIE[COOKIE_MEMOGET]);
    foreach($tab_get as $get)
    {
      list($get_name,$get_value) = explode('=',$get) + array(NULL,TRUE) ;
      $_GET[$get_name] = $get_value;
    }
  }

}
?>