<?php if (!defined('HTTP_SERVER')) die('You can not access this file directly!');
/**
  @licence GPL 2005-2010  The osCSS developers - osCSS Open Source E-commerce
  @portion code Copyright (c) 2002 osCommerce
  @package osCSS-2 <www http://www.oscss.org>
  @version 2.1.0
  @date  10/06/10, 09:08
  @author oscim <mail aurelien@oscim.fr> <www http://www.oscim.fr>
  @encode UTF-8
  @brief
 Constructeur du menu de l'espace d'admin. Ce base sur les boxes pour construire l'arboresances. Si l'entrée n'est pas dispo dans la table admin_file, alors elle est ajouté. Tous les menu sont disponible pour l'admin (grpid 1)
 Controle les droits pour chaque entrée.

 La db est automatiquement mise a jour avec les entrées menu et boite trouvé.

 appel
    new menu(options);
    Si $option['for_user'] est precisé alors groupe_id = $option['for_user'], sinon  tep_session_register('login_group_id')

 */
error_reporting(E_ALL);
class menu  {

  protected static $exclude=array();
  protected static $include=array();
  protected static $_instance;

  protected function menu($exclude=array(),$include=array()) {
    if(is_array($exclude) && count($exclude)>0) self::$exclude=$exclude;
    if(is_array($include) && count($include)>0) self::$include=$include;
    /* Liste global entree db*/
	$this->menu_maintenance=$this->in_sql_for_maintenance();
    /* Chargement des boite trouve */
	$this->peuple_menu_by_box(self::$exclude);
    /* */
	$this->list_id=array();


  }

  public static function getInstance($exclude=array(),$include=array()){
      if(self::$_instance == null) self::$_instance = new self($exclude,$include);
      return self::$_instance;
  }

  public static function resetInstance($exclude=array(),$include=array()){
      self::$_instance = null;
      self::$exclude=self::$include=array();
      return self::getInstance($exclude,$include);
  }



    /**
        Calcul des acl pour l'utilisateur en cours
    */
    static private function in_sql_for_user($for_user){
        $sortie=array();
        $dbquery = tep_db_query("select * from " . TABLE_ADMIN_FILES . " where FIND_IN_SET( '" . $for_user . "', admin_groups_id)  ");
        while ($s=tep_db_fetch_array($dbquery))
            $sortie[md5($s['admin_files_name'])]=$s;
        return $sortie;
    }

    /**
        Recuperation complete de la table pour verification des absent
    */
    static private function in_sql_for_maintenance(){
        $sortie=array();
        $dbquery = tep_db_query("select * from " . TABLE_ADMIN_FILES . "   ");
        while ($s=tep_db_fetch_array($dbquery))
            $sortie[md5($s['admin_files_name'])]=$s;

        return $sortie;
    }

    /**
        Insertion des menu, elements trouve dans les box.
        @arg [[$filename string liens complet avec get],$num_box numeric(1-9) boite de référence ]
    */
    static private function insert_box_menu($filename,$num_box=1){
        $dbquery = tep_db_query("INSERT INTO " . TABLE_ADMIN_FILES . " (admin_files_name,admin_files_is_boxes,admin_files_to_boxes,admin_groups_id) VALUES ('" . str_replace('&amp;','&',$filename) . "', '0','".substr($num_box,0,1)."','1,') ");
    }

    /**
        Insertion des  box trouvé dans DIR_WS_BOXES.
        @arg [[$filename string liens complet avec get],$num_box numeric(1-9) boite de référence ]
    */
    static private function insert_box($filename){
        $dbquery = tep_db_query("INSERT INTO " . TABLE_ADMIN_FILES . " (admin_files_name,admin_files_is_boxes,admin_files_to_boxes,admin_groups_id) VALUES ('" . $filename . "', '1','0','1,') ");
    }

    /**
    Insertion acl mini .
    @arg [[$filename string liens complet avec get],$num_box numeric(1-9) boite de référence ]
    */
    static private function update_acl_mini($admin_files_id){
        $dbquery = tep_db_query("update " . TABLE_ADMIN_FILES . " set admin_groups_id='1,' where admin_files_id = '" . $admin_files_id . "'  ");
    }

    /**
        Index des id pour eviter les doublons. Fonction recusive.Produits des id qui n'on pas encore été attribué
        @arg l'id proposé
        */
     private function id_css($id_propose){
         $id_propose=str_replace(array('.'),array('_'),$id_propose);
         if (!isset($this->list_id[$id_propose])){
            $this->list_id[$id_propose]=$id_propose;
            $a= $id_propose;
         } else {
            preg_match("/(.*)__([0-9]*)/i",$id_propose,$reg);

            $index=(isset($reg[2]))? ($reg[2]+1) : 1 ;
            $prim=(isset($reg[1]))? $reg[1] : $id_propose ;
            /* recusive */
            $a=$this->id_css($prim.'__'.$index);
         }
         return $a;
    }

    /**
        Recuperation du contenu des fichier de menu
    */
    private function peuple_menu_by_box($exclude=array()){
	global $language;
        $dir = dir(DIR_FS_ADMIN . DIR_WS_BOXES );
        $themes_array = array();
        $link1='';

        while ($file = $dir->read())
          if(preg_match('#\.php$#i', $file)){
            $reg=array(substr($file, 0, strpos($file, '_')), substr($file, strpos($file, '_')+1, -4));
// 	    if(!in_array($reg[1],$exclude) || in_array($reg[1],self::$include)){
	      /* Add box absente ds db */
	      if(!isset($this->menu_maintenance[md5($reg[1].'.php')])) $this->insert_box($reg[1].'.php');
	      $key=md5($reg[1].'.php');
	      include(DIR_FS_ADMIN .DIR_WS_BOXES .$reg[0].'_'. $reg[1].'.php');
	      include_once(DIR_FS_ADMIN.DIR_WS_LANGUAGES.$language.'/boxes/'.$reg[0].'_'. $reg[1].'.php');
	      $menu[$key] = array( 'ss_menu',$reg[1],$reg[1],@$this->tableau_img[$reg[1]],(array)@$tabl_link);
	      $menu_sort[$reg[0]]=$key;
	      unset($tabl_link);
// 	    }
          }
        $dir->close();
        ksort($menu_sort);

        foreach($menu_sort as $value) $menu_w[]=$menu[$value];

        $this->menu_w=$menu_w;
    }

    /**
        Prise en charge des option passé au constructeur
        @arg [option array]
    */
    private function add_option($option){
            $this->option =(is_array($option))? $option : array();

        $this->for_user= (isset($option['for_user']))? $option['for_user'] : $_SESSION['login_groups_id'] ;
    /* Format de l'action js */
        $this->format_js= (isset($this->option['format_js']))? $this->option['format_js'] : '';
    /* Format de la sortie */
        $this->format= (isset($this->option['format']))? $this->option['format'] : '<a id="'."%1\$s".'" href="'."%2\$s".'" '."%4\$s".'>'."%3\$s".'</a>' ."\n";
    /* Format entete 1 er niveau */
        $this->format_line_box_open_entete= (isset($this->option['format_line_box_open_entete']))? $this->option['format_line_box_open_entete'] : '<li class="'."%4\$s".'" id="'."%3\$s".'">'."%1\$s".'<ul id="'."fils%3\$s".'" class="ssmenu">'."%2\$s".'</ul></li>' ."\n";
    /* Format d'une ligne avec sous menu*/
        $this->format_line_box_open=(isset($this->option['format_line_box_open']))? $this->option['format_line_box_open'] : '<li class="'."%4\$s".'" id="'."%3\$s".'">'."%1\$s".'<ul id="'."fils%3\$s".'" class="ssmenu">'."%2\$s".'</ul></li>' ."\n";
    /* format d'une ligne sans sous menu */
        $this->format_line_box=(isset($this->option['format_line_box']))? $this->option['format_line_box_open'] : '<li class="'."%4\$s".'" id="'."%3\$s".'">'."%1\$s".''."%2\$s".'</li>' ."\n";
    /* tableau image, place dans balise img */
        $this->tableau_img= (isset($this->option['tabl_img']))  ? $this->option['tabl_img'] : array();
    }

    /**
        Function recursive qui met en forme le tableau de sortie des menu
        Si abs de la db, alors insert les element manquants
        @arg [[$array array contenant le menu],$rec (option) boolean/numeric bollean pour false non recursif, ou le numero hierachique en cour]
    */
    private function cstr_tbl_rec($array,$rec=false){
        $i=0; $ssmenu=0;$link1='';
        $struct_menu=array();
        while ($r=each($array)){
          if (isset($r['value'][1]) && $r['value'][1] != 'hidden' && ( !in_array($r['value'][1],self::$exclude) && ( (count(self::$include)>0 &&  in_array($r['value'][1],self::$include)) || count(self::$include)==0 ) ) ){
            if (isset($r['value'][0]) && $r['value'][0] == 'separateur') {
                $link1 .=sprintf($this->format_line_box,
                                 sprintf($this->format,$this->id_css('act'.$i),'#',tep_cst_menu_conf($r['value'][1]),' class="menuBoxContentLink '.$r['value'][2].'" '.
                                         sprintf($this->format_js,$i)
                                        ),
                                '',$this->id_css('menu'.$i.'Container'),$r['value'][2].' '.$regi[1] );

            }
            elseif (isset($r['value'][4]) && is_array($r['value'][4]) && $r['value'][0] == 'ss_menu') {
                preg_match("/(.*)[?](.*)/i",$r['value'][0],$regi);
                $path= (!isset($regi[1]) || empty($regi[1]))?$r['value'][2].'.php':$r['value'][0] ;
                $acl_for_ctr=md5(str_replace('&amp;','&',$path));

                $format=(!$rec)?$this->format_line_box_open_entete: $this->format_line_box_open ;
                /* Boucle pour sous menu avec entete de menu non clickable*/
                $link1 .=sprintf($format,
                                 sprintf($this->format,$this->id_css('act'.$i),'index.php?type='.$r['value'][2],tep_cst_menu_conf($r['value'][1]),' class="menuBoxContentLink '.$r['value'][2].'" '.
                                         sprintf($this->format_js,$i)
                                        ),
                                $this->cstr_tbl_rec($r['value'][4],$r['key']),
                                $this->id_css('menu'.$i.'Container'),
                                $r['key'].'_'.$r['value'][2].((isset($this->menu_acl[$acl_for_ctr])) ?'' : ' disabled ')
                                    );
                $ssmenu++;

            }
            elseif (isset($r['value'][4]) && is_array($r['value'][4])) {
                preg_match("/(.*)[?](.*)/i",$r['value'][0],$regi);
                if (!isset($regi[1]) || empty($regi[1])) $regi[1]=$r['value'][0];
//                 $acl_for_ctr=str_replace('&amp;','&',$r['value'][0]);
                $acl_for_ctr=md5(str_replace('&amp;','&',$r['value'][0]));
                $format=(!$rec)?$this->format_line_box_open_entete: $this->format_line_box_open ;
                /* Boucle pour sous menu avec entete de menu en liens vers page*/
                $link=(preg_match("/[0-9]{2}_[a_z].*/",$r['value'][0]))? 'index.php?type='.$r['value'][2]: $r['value'][0];
                $link1 .=sprintf($format,
                                 sprintf($this->format,$this->id_css('act'.$i),tep_href_link($link),tep_cst_menu_conf($r['value'][1]),' class="menuBoxContentLink '.$r['value'][2].'" '.
                                         sprintf($this->format_js,$i)
                                        ),
                            $this->cstr_tbl_rec($r['value'][4],$r['key']),
                            $this->id_css('menu'.$i.'Container'),
                                          $r['key'].'_'.$r['value'][2].((isset($this->menu_acl[$acl_for_ctr])) ?'' : ' disabled ')
                                );

            }
            elseif ( is_array($r['value'])) {
	      $regi=array();
	      preg_match("/(.*)[?](.*)/i",$r['value'][0],$regi);
	      if (!isset($regi[1]) || empty($regi[1])) $regi[1]=$r['value'][0];
              $acl_for_ctr=md5(str_replace('&amp;','&',$r['value'][0]));

	      $link1 .=sprintf($this->format_line_box,
                             sprintf($this->format,$this->id_css('act'.$i),tep_href_link($regi[1],@$regi[2]),tep_cst_menu_conf($r['value'][1]),' class="menuBoxContentLink '.$r['value'][2].'" '.
                                     sprintf($this->format_js,$i).' '.addslashes(@$r['value'][4])
                            ),
                            '',$this->id_css('menu'.$i.'Container'),$r['value'][2].' '.$regi[1].((isset($this->menu_acl[$acl_for_ctr])) ?'' : ' disabled ') );

                $this->hierac[$regi[1]]=$rec;
                unset($regi);
            }
          }
          $i++;
        }
        return $link1;
    }

    /**
        Function recursive qui met en forme le tableau de sortie des menu
        Si abs de la db, alors insert les element manquants
        @arg [[$array array contenant le menu],$rec (option) boolean/numeric bollean pour false non recursif, ou le numero hierachique en cour]
    */
    private function cstr_tbl_rec2($array,$rec=false){
        $i=0;$ssmenu=0;$link1='';
        $array_s=array();
        while ($r=each($array)){
//  print_r($r['value']);
            if (isset($r['value'][0]) && $r['value'][0] == 'separateur') {
                $acl_for_ctr=md5(str_replace('&amp;','&',$r['value'][0]));
                $array_s[$r['key']]=array('type'=>'separateur',
                                          'etat'=>((!isset($this->menu_acl[$acl_for_ctr])) ?false : true),
                                            'admin_files_name'=>tep_cst_menu_conf($r['value'][1]),
                                            'link'=>'#',
                                            'CONTENEUR_class'=>'menuBoxContentLink '.$r['value'][2],
                                            'CONTENEUR_id'=>$this->id_css('act'.$i),
                                            'CONTENU_class'=>$r['value'][2].' '.$regi[1],
                                            'CONTENU_id'=>$this->id_css('menu'.$i.'Container'),
                                            'js'=> sprintf($this->format_js,$i),
                                            '',''
                                            );
            }
            elseif (isset($r['value'][4]) && is_array($r['value'][4]) && $r['value'][0] == 'ss_menu') {
                /* Add entree menu absente ds db */
                preg_match("/(.*)[?](.*)/i",$r['value'][0],$regi);
                $path= (!isset($regi[1]) || empty($regi[1]))?$r['value'][2].'.php':$r['value'][0] ;
                $acl_for_ctr=md5(str_replace('&amp;','&',$path));// str_replace('&amp;','&',$r['value'][0].$ssmenu).count($array_s);
                /* Add entree menu absente ds db */
                if(!isset( $this->menu_maintenance[$acl_for_ctr]) ) {
                    $this->insert_box_menu($path,((!$rec)? $r['key']: $rec ) );
                    $this->menu_maintenance=$this->in_sql_for_maintenance();
                }
                if(!isset($this->menu_acl[$acl_for_ctr]) || empty($this->menu_maintenance[$acl_for_ctr]['admin_groups_id'])) {
                    $this->update_acl_mini($this->menu_maintenance[$acl_for_ctr]['admin_files_id']);
                }
//                 echo $r['key'].'  '.$acl_for_ctr.'<br >';
                $array_s[$r['key']]=array('type'=>'ss_menu',
                                          'etat'=>((!isset($this->menu_acl[$acl_for_ctr])) ? 'false' : 'true'),
                                          'admin_files_id'=>$this->menu_maintenance[$acl_for_ctr]['admin_files_id'],
                                          'admin_files_name'=>tep_cst_menu_conf($r['value'][1]),
                                          'admin_files_to_boxes'=>$this->menu_maintenance[$acl_for_ctr]['admin_files_to_boxes'],
                                          'admin_files_is_boxes'=>$this->menu_maintenance[$acl_for_ctr]['admin_files_is_boxes'],
                                        'file'=>$r['value'][2],
                                        'key'=>$acl_for_ctr,
                                        'link'=>'#',
                                        'class'=>'menuBoxContentLink '.$r['value'][2],
                                        'CONTENEUR_class'=>'menuBoxContentLink '.$r['value'][2],
                                        'CONTENEUR_id'=>$this->id_css('act'.$i),
                                                'CONTENU_class'=>$r['key'].'_'.$r['value'][2].((!isset($this->menu_acl[$acl_for_ctr])) ?' disabled ' : ''),
                                        'CONTENU_id'=>$this->id_css('menu'.$i.'Container'),
                                        'id'=>$this->id_css('act'.$i),
                                        'js'=> sprintf($this->format_js,$i),
                                        'fils'=> $this->cstr_tbl_rec2($r['value'][4],$acl_for_ctr),
                                        '',''
                                        );
                $ssmenu++;
            }
            elseif (isset($r['value'][4]) && is_array($r['value'][4])) {
                /* Add entree menu absente ds db */
                preg_match("/(.*)[?](.*)/i",$r['value'][0],$regi);
                if (!isset($regi[1]) || empty($regi[1])) $regi[1]=$r['value'][0];
//                 $acl_for_ctr=str_replace('&amp;','&',$r['value'][0]);
                $acl_for_ctr=md5(str_replace('&amp;','&',$r['value'][0]));
                /* Add entree menu absente ds db */
                if(!isset( $this->menu_maintenance[$acl_for_ctr]) ) {
                    $this->insert_box_menu($r['value'][0],((!$rec)? $r['key']: $rec ) );
                    $this->menu_maintenance=$this->in_sql_for_maintenance();
                }
                if(!isset($this->menu_acl[$acl_for_ctr]) || empty($this->menu_maintenance[$acl_for_ctr]['admin_groups_id'])) {
                    $this->update_acl_mini($this->menu_maintenance[$acl_for_ctr]['admin_files_id']);
                }

                /* Boucle pour sous menu avec entete de menu en liens vers page*/
                        $link=(preg_match("/[0-9]{2}_[a_z].*/",$r['value'][0]))? '#'.$r['value'][0]: $r['value'][0];

                $array_s[$r['key']]=array(  'type'=>'recursif',
                                            'etat'=>((!isset($this->menu_acl[$acl_for_ctr])) ?false : true),
                                            'admin_files_id'=>$this->menu_maintenance[$acl_for_ctr]['admin_files_id'],
                                            'admin_files_name'=>(!empty($r['value'][1])?tep_cst_menu_conf($r['value'][1]) : $regi[1]),
                                            'admin_files_to_boxes'=>$this->menu_maintenance[$acl_for_ctr]['admin_files_to_boxes'],
                                            'admin_files_is_boxes'=>$this->menu_maintenance[$acl_for_ctr]['admin_files_is_boxes'],
                                            'file'=>$r['value'][2],
                                            'link'=>$link,
                                            'class'=>'menuBoxContentLink '.$r['value'][2],
                                            'CONTENEUR_class'=>'menuBoxContentLink '.$r['value'][2],
                                            'CONTENEUR_id'=>$this->id_css('act'.$i),
                                            'CONTENU_class'=>$r['key'].'_'.$r['value'][2].((!isset($this->menu_acl[$acl_for_ctr])) ?' disabled ' : ''),
                                            'CONTENU_id'=>$this->id_css('menu'.$i.'Container'),
                                            'js'=> sprintf($this->format_js,$i),
                                            'fils'=> $this->cstr_tbl_rec2($r['value'][4],$r['key']),
                                            '',''
                                            );
            }
            elseif ( is_array($r['value'])) {

                preg_match("/(.*)[?](.*)/i",$r['value'][0],$regi);
                if (!isset($regi[1]) || empty($regi[1])) $regi[1]=$r['value'][0];
//                 $acl_for_ctr=str_replace('&amp;','&',$r['value'][0]);
                $acl_for_ctr=md5(str_replace('&amp;','&',$r['value'][0]));
                /* Add entree menu absente ds db */
                if(!isset( $this->menu_maintenance[$acl_for_ctr]) ) {
                    $this->insert_box_menu($r['value'][0],((!$rec)? $r['key']: $rec ) );
                    $this->menu_maintenance=$this->in_sql_for_maintenance();
                }
                if(!isset($this->menu_acl[$acl_for_ctr]) || empty($this->menu_maintenance[$acl_for_ctr]['admin_groups_id'])) {
                    $this->update_acl_mini($this->menu_maintenance[$acl_for_ctr]['admin_files_id']);
                }


            $array_s[$r['key']]=array(  'type'=>'enfant',
                                        'etat'=>((!isset($this->menu_acl[$acl_for_ctr])) ?false : true),
                                        'admin_files_id'=>$this->menu_maintenance[$acl_for_ctr]['admin_files_id'],
                                        'admin_files_name'=>(!empty($r['value'][1])?tep_cst_menu_conf($r['value'][1]) : $regi[1]),
                                        'admin_files_to_boxes'=>$this->menu_maintenance[$acl_for_ctr]['admin_files_to_boxes'],
                                        'admin_files_is_boxes'=>$this->menu_maintenance[$acl_for_ctr]['admin_files_is_boxes'],
                                        'file'=>$r['value'][2],
                                        'link'=>'#',
                                        'CONTENEUR_class'=>'menuBoxContentLink '.$r['value'][2],
                                        'CONTENEUR_id'=>$this->id_css('act'.$i),
                                        'CONTENU_class'=>$r['key'].'_'.$r['value'][2].((isset($this->menu_acl[$acl_for_ctr])) ?'' : ' disabled '),
                                        'CONTENU_id'=>$this->id_css('menu'.$i.'Container'),
                                        'js'=> sprintf($this->format_js,$i),
                                        '',''
                                        );
            unset($regi);
            }

            $i++;
        }

        return $array_s;
    }
    /**
        Constructeur public, retourne le tableau de menu complet avec sa mise en forme
        @arg [$option array]
    */
    public function cstr($option=''){
        $this->add_option($option);

        $this->menu_acl=$this->in_sql_for_user($this->for_user);
// print_r($this->menu_w);
        $menu= $this->cstr_tbl_rec($this->menu_w);

        return $menu;
    }
    /**
      Retour du numero d'appartenance au menu
      @param string filename de la page
    */
    public function in_rub($filename){
      if (isset($this->hierac[$filename])){
        return $this->hierac[$filename];
      }
    }
    /**
    Constructeur public, retourne le tableau de menu complet avec sa mise en forme
    @arg [$option array]
    */
    public function cstr_return($option=''){
        $this->add_option($option);

//         echo $this->for_user;
        $this->menu_acl=$this->in_sql_for_user($this->for_user);
//         print_r($this->menu_acl);
//         print_r($this->menu_w);
        $menu= $this->cstr_tbl_rec2($this->menu_w,false,true);
//   print_r($menu);
        return $menu;
    }
  }
?>