<?php

/*
 *   This file is part of NOALYSS.
 *
 *   NOALYSS is free software; you can redistribute it and/or modify
 *   it under the terms of the GNU General Public License as published by
 *   the Free Software Foundation; either version 2 of the License, or
 *   (at your option) any later version.
 *
 *   NOALYSS is distributed in the hope that it will be useful,
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *   GNU General Public License for more details.
 *
 *   You should have received a copy of the GNU General Public License
 *   along with NOALYSS; if not, write to the Free Software
 *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 */

// Copyright Author Dany De Bontridder danydb@aevalys.eu

/*!\file
 * \brief the class for the dossier, everywhere we need to know to
 * which folder we are connected, because we can't use $_SESSION, we
 * need to pass the dossier_id via a _GET or a POST variable
 */

/*! \brief manage the current dossier, everywhere we need to know to
 * which folder we are connected, because we can't use $_SESSION, we
 * need to pass the dossier_id via a _GET or a POST variable
 *  private static $variable=array("id"=>"dos_id",
  "name"=>"dos_name",
  "desc"=>"dos_description");
 *
 */
require_once NOALYSS_INCLUDE.'/lib/ac_common.php';

class Dossier
{

    private static $variable=array("id"=>"dos_id",
        "name"=>"dos_name",
        "desc"=>"dos_description",
        "max_email"=>'dos_email');

    var $cn; //!< Database connexion
    var $dos_id; //!< number of db
    var $dos_name;
    var $dos_description;
    var $dos_email;

    function __construct($p_id)
    {
        $this->cn=new Database();  // Connect to the repository
        $this->dos_id=$p_id;
    }

    /*!\brief return the 'gDossier' value after a check */

    static function id()
    {
        $http=new HttpInput();
        
        return $http->request('gDossier','number');
    }

    /**
     * @brief Show the folder where user have access. 
     * @param  p_type string   
      - A for all dossiers
      - R for accessible folders
      - X forbidden folders
     * @param p_login is the user name
     * @param p_text is a part of the name where are looking for
     * @return     nothing
     *
     */
    static function show_dossier($p_type, $p_login="", $p_text="", $limit=0)
    {
        $cn=new Database();
        $str_limit=($limit==0)?'':' limit '.$limit;
        if ($p_type=="A")
        {
            $l_sql="select *, 'W' as priv_priv "
                    ."from ac_dossier "
                    ."where "
                    ."dos_name ilike '%'|| $2 ||'%'"
                    ."or dos_description ilike '%'|| $2 || '%' "
                    ."ORDER BY dos_name $str_limit  ";
            $a_row=$cn->get_array($l_sql, $p_text);
            return $a_row;
        }
        else if ($p_type=="R")
        {
            $l_sql="select * from jnt_use_dos
                   natural join ac_dossier
                   natural join ac_users
                   where
                   use_login=$1
                   and ( dos_name ilike '%'||  $2 || '%'  or dos_description ilike '%'|| $2|| '%' )
                   
                   order by dos_name 
                   $str_limit
                   ";

            $a_row=$cn->get_array($l_sql, array($p_login, $p_text));
            return $a_row;
        }
        else if ($p_type=='X')
        {
            $l_sql=" select * from ac_dossier where dos_id not in 
                  (select dos_id from jnt_use_dos where use_id=$1)
                  and ( dos_name ilike '%'||  $2|| '%'  or dos_description ilike '%'||  $2 || '%')
                  order by dos_name ".$str_limit;
            $a_row=$cn->get_array($l_sql, array($p_login, $p_text));
            return $a_row;
        }
        else
        {
            throw new Exception(_("Erreur paramètre"));
        }
    }

    /**
     * Count the number of folder in the repository
     * @return integer
     */
    function count()
    {
        $nb_folder=$this->cn->get_value('select count(*) from ac_dossier');
        return $nb_folder;
    }

    /**
     * \brief Return all the users as an array but NOALYSS_ADMINISTRATOR, that user cannot be changed by the
     * interface for administrating user
     * \param SQL $sql sql string to add to the query :
     * \note that string MUST be the result of  Database::escape_string
     */
    function get_user_folder($sql="")
    {

        $sql="
            select
                use_id,
                use_first_name,
                use_name,
                use_email,
                use_login,
                use_active,
                use_admin,
                ag_dossier,
                use_auth_method
            from
            ac_users  as ac
            left join    
                (select array_to_string(array_agg(dos_name),',') as ag_dossier,
                        jt.use_id as jt_use_id
                  from ac_dossier as ds
                    join  jnt_use_dos as jt on (jt.dos_id=ds.dos_id)
                    group by jt.use_id) as dossier_name on (jt_use_id=ac.use_id)
            $sql
            ";

        $res=$this->cn->get_array($sql);
        return $res;
    }

    /*!\brief check if gDossier is set
    * ?? dead code ???
    */

    static function check()
    {
        try {
            $http=new HttpInput();
            $id=$http->request("gDossier","number");
            if ($id > 999999 || $id < 0) throw new \Exception(_("Dossier max dépassé "));
        } catch (\Exception $e) {

            die('Dossier invalide ');
        }

    }

    /*!
     * \brief return a string to put to gDossier into a GET 
     */

    static function get()
    {
        $http=new \HttpInput();
        return "gDossier=".$http->request("gDossier","number");
    }

    /*!
     * \brief return a string to set gDossier into a FORM
    */

    static function hidden()
    {
        $http=new \HttpInput();

        return '<input type="hidden" id="gDossier" name="gDossier" value="'.$http->request("gDossier","number").'">';
    }

    /*!\brief retrieve the name of the current dossier */

    static function name($id=0)
    {

        $http=new \HttpInput();
        $cn=new Database();
        $id=($id==0)?$http->request("gDossier","number"):$id;
        $name=$cn->get_value("select dos_name from ac_dossier where dos_id=$1", array($id));
        return $name;
    }

    public function get_parameter($p_string)
    {
        if (array_key_exists($p_string, self::$variable))
        {
            $idx=self::$variable[$p_string];
            return $this->$idx;
        }
        else
            throw new Exception("Attribut inexistant $p_string");
    }

    public function set_parameter($p_string, $p_value)
    {
        if (array_key_exists($p_string, self::$variable))
        {
            $idx=self::$variable[$p_string];
            $this->$idx=$p_value;
        }
        else
            throw new Exception("Attribut inexistant $p_string");
    }

    public function get_info()
    {
        return var_export(self::$variable, true);
    }

    public function save()
    {
        $this->update();
    }

    public function update()
    {
        if (noalyss_strlentrim($this->dos_name)==0)
            return;

        if ($this->cn->get_value("select count(*) from ac_dossier "
                        ." where dos_name=$1 and dos_id<>$2", array($this->dos_name, $this->dos_id))!=0)
            return;

        $sql="update ac_dossier set dos_name=$1,dos_description=$2 ,dos_email=$3".
                " where dos_id = $4";
        $res=$this->cn->exec_sql(
                $sql, array(trim($this->dos_name),
            trim($this->dos_description),
            $this->dos_email,
            $this->dos_id)
        );
    }

    public function load()
    {

        $sql="select * from ac_dossier where dos_id=$1";

        $res=$this->cn->exec_sql(
                $sql, array($this->dos_id)
        );

        if (Database::num_row($res)==0)
            return;
        $row=Database::fetch_array($res, 0);
        foreach ( self::$variable as $idx)
        {
            $this->$idx=$row[$idx];
        }
    }

    static function get_version($p_cn)
    {
        return $p_cn->get_value('select max(val) from version');
    }

    static function connect()
    {
        static $cn=null;
        if ($cn!=null)
            return $cn;
        $id=Dossier::id();
        $cn=new Database($id);
        return $cn;
    }

    /**
     * @brief connect to folder and give to admin. the profile Admin(builtin)
     * @param int $p_id dossier::id()
     */
    static function synchro_admin($p_id)
    {
// connect to target
        $cn=new Database($p_id);

        if (!$cn->exist_table("profile_menu"))
        {
            echo_warning("Dossier invalide");
            return;
        }
// connect to repo
        $repo=new Database();

        $a_admin=$repo->get_array("select use_login from ac_users where
			use_admin=1 and use_active=1");
        try
        {
            /**
             * synchro global
             */
            $cn->start();
            for ($i=0; $i<count($a_admin); $i++)
            {
                Noalyss_user::grant_admin_access($a_admin[$i]['use_login'], $p_id);
            }
            $cn->commit();
        }
        catch (Exception $e)
        {

            echo_warning($e->getMessage());
              record_log($e);
            $cn->rollback();
        }
    }
    /**
     * @brief Upgrade check if the folder ACCOUNT_REPOSITORY  needs to be upgrade thanks the variable DBVERSIONREPO
     * and run  all the SQL script named  ac-upgradeX.sql from the folder noalyss/include/sql/patch 
     * until  X equal DBVERSIONREPO-1
     * After it will call the function apply_patch, remove_inexistant_user and clean_orphan_log for each folder
     * 
     */
    static function upgrade()
    {
        $rep=new Database();
        /* If multi folders */
        $Resdossier=$rep->exec_sql("select dos_id, dos_name from ac_dossier");
        $MaxDossier=$rep->size($Resdossier);

        //----------------------------------------------------------------------
        // Upgrade the account_repository
        //----------------------------------------------------------------------
        echo "<h2>"._("Mise à jour de la base de données principale")."</h2>";
        $cn=new Database();
        if (DEBUGNOALYSS == 0)
            ob_start();
        $MaxVersion=DBVERSIONREPO-1;
        for ($i=4; $i<=$MaxVersion; $i++)
        {
            if ($cn->get_version()<=$i)
            {
                $cn->execute_script(NOALYSS_INCLUDE.'/sql/patch/ac-upgrade'.$i.'.sql');
            }
        }
        if (DEBUGNOALYSS == 0)             ob_end_clean();
        //----------------------------------------------------------------------
        // Upgrade the folders
        //----------------------------------------------------------------------
        echo "<h2>"._("Mise à jour dossiers")."</h2>";

        for ($e=0; $e<$MaxDossier; $e++)
        {
            $db_row=Database::fetch_array($Resdossier, $e);
            $name=$rep->format_name($db_row['dos_id'], 'dos');
            echo "<h3>Patching ".$db_row['dos_name'].'</h3>';
            echo _('Base de données')." ".$name;

            if ($rep->exist_database($name)>0)
            {
                $db=new Database($db_row['dos_id'], 'dos');
                $db->apply_patch($db_row['dos_name']);
                Dossier::synchro_admin($db_row['dos_id']);
                Noalyss_user::remove_inexistant_user($db_row['dos_id']);
                $db->clean_orphan_lob();
            }
            else
            {
                echo_warning(_("Dossier inexistant")." $name");
            }
        }

        //----------------------------------------------------------------------
        // Upgrade the template
        //----------------------------------------------------------------------
        $Resdossier=$rep->exec_sql("select mod_id, mod_name from modeledef");
        $MaxDossier=$rep->size();
        echo "<h2>"._("Mise à jour modèles")."</h2>";

        for ($e=0; $e<$MaxDossier; $e++)
        {
            $db_row=Database::fetch_array($Resdossier, $e);
            $name=$rep->format_name($db_row['mod_id'], 'mod');
            echo "<h3>Patching ".$db_row['mod_name']."</h3>";
            echo _('Base de données')." ".$name;
            if ($rep->exist_database($name)>0)
            {
                $db=new Database($db_row['mod_id'], 'mod');
                $db->apply_patch($db_row['mod_name']);
                $db->clean_orphan_lob();
            }
            else
            {
                echo_warning(_("Modèle inexistant")." $name");
            }
        }
    }
    
    /**
     * Set the current dossier to $p_dossier
     * @param numeric $p_dossier
     */
    static function set_current($p_dossier) {
        
        self::check($p_dossier);
        put_global([ [ "key"=>"gDossier","value"=>$p_dossier]]);

    }

}
