<?
include_once(_DIR_TO_ENGINE.'/i_descr_tables.php') ;
function SETUP(){ if (!is_object($GLOBALS['SETUP'])) $GLOBALS['SETUP']=new i_setup();return($GLOBALS['SETUP']);return(new i_setup());}
function SETUP_LEVEL($level_name) { if (_sizeof($GLOBALS['install_options']) and $GLOBALS['install_options'][$level_name]) return(1) ; else return(0) ; }

class i_setup
{
 var $setup_mode='second' ;
 var $ext_array=array() ;
 var $report_indx=0; // счетчик добавляемых отчетов для контроля очередности загрузки

 function check_setting($options=array())
 {  $this->exec_moduls_setup('check_dir_files','Проверка файлов и директорий') ;
    $this->exec_moduls_setup('reg_clss','Регистрация классов') ;
    create_class_model() ;

    // сначала проверяем базу, потом все остальные операции
    if (ESMO_STATUS!='SETUP_FIRST')
    {
        $this->check_db($options) ; //- при инсталяции проверка не требуется, так как таблицы были созданы в полном соответствии с описаниями классов
    }

    $this->exec_moduls_setup('db_updates','Коррекция БД') ;

    if (ESMO_STATUS!='SETUP_FIRST') $this->clear_event_lister() ; // сбрасываем список обработчиков событий в базе
    if (ESMO_STATUS!='SETUP_FIRST') $this->clear_event_types() ; // сбрасываем список обработчиков событий в базе
    if (ESMO_STATUS!='SETUP_FIRST') $this->mark_crontab_for_remove() ; // сбрасываем список обработчиков событий в базе
    if (ESMO_STATUS!='SETUP_FIRST') $this->mark_roles_for_remove() ; // сбрасываем список обработчиков событий в базе
    if (ESMO_STATUS!='SETUP_FIRST') $this->mark_reports_for_remove() ; // сбрасываем список обработчиков событий в базе
    if (ESMO_STATUS!='SETUP_FIRST') $this->mark_setting_for_remove() ; // сбрасываем список обработчиков событий в базе

    $this->exec_moduls_setup('ini_value','Регистрация и обновление настроек INI-файла') ;
    $this->exec_moduls_setup('old_ini_section','Проверка корректности файла конфиграции') ;

    $this->exec_moduls_setup('roles','Регистрация ролей системы') ;
    if (ESMO_STATUS=='SETUP_FIRST') multiSQL_insert('roles')->flush() ;

    $this->exec_moduls_setup('declare_list','Регистрация списков') ;
    if (ESMO_STATUS=='SETUP_FIRST') multiSQL_insert(TM_LIST)->flush() ;

    $this->exec_moduls_setup('vars','Регистрация настроек') ;
    if (ESMO_STATUS=='SETUP_FIRST') multiSQL_insert(TM_SETTING)->flush() ;

    $this->exec_moduls_setup('reports','Регистрация отчетов') ;
    if (ESMO_STATUS=='SETUP_FIRST') multiSQL_insert('reports')->flush() ;

    $this->exec_moduls_setup('cron','Регистрация заданий планировщика') ;
    if (ESMO_STATUS=='SETUP_FIRST') multiSQL_insert('obj_site_crontab')->flush() ;

    $this->exec_moduls_setup('event_lister','Регистрация обработчиков событий') ;
    multiSQL_insert('event_lister')->flush() ; // обработчики событий всегда добавляются через  multiSQL_insert так как таблица обработчиков очищается перед установкой

    $this->exec_moduls_setup('event_type','Регистрация мероприятий') ;
    multiSQL_insert('events_types')->flush() ; // обработчики событий всегда добавляются через  multiSQL_insert так как таблица обработчиков очищается перед установкой

    $this->exec_moduls_setup('menu_config','Формирование меню ЛК') ;

    $this->exec_moduls_setup('reg_ext','Регистрация ext-директорий') ;
    $this->save_reg_ext() ;

    //$this->change_tables_attr() ;


    $this->exec_moduls_setup('viewers','Создание вьюверов') ;
    $this->exec_moduls_setup('create_default_objects','Создание типовых объектов') ;



    if (ESMO_STATUS!='SETUP_FIRST') $this->delete_marked_crontab() ;
    if (ESMO_STATUS!='SETUP_FIRST') $this->delete_marked_roles() ;
    if (ESMO_STATUS!='SETUP_FIRST') $this->delete_marked_reports() ;
    if (ESMO_STATUS!='SETUP_FIRST') $this->delete_marked_setting() ;

    //if (ESMO_STATUS!='SETUP_FIRST')
        ENGINE()->upload_reports_docs() ;
    boot_roles() ;
//    if (ESMO_STATUS!='SETUP_FIRST')
        boot_index_list() ;
    //reboot_setting_from_DB() ;
 }

 function exec_moduls_setup($mode,$title)
 {   global $__functions,$install_options ;
     $t1=fixed_time() ;
     include_once(_DIR_TO_ROOT.'/ini/'._INIT_) ;
     //include_once(_DIR_TO_ENGINE.'/admin/i_setup.php') ;
     include_once(_DIR_TO_ENGINE.'/admin/i_admin_system.php') ;
     $install_options=array($mode=>1) ;
     FILE_LOG()->append($title) ;
     ?><h2><?echo $title?></h2><?
     if (_sizeof($__functions['install'])) foreach($__functions['install'] as $func_name)
     {   /*?><strong><?echo $func_name?></strong><br><?*/
         ${$func_name(0)} ;
         set_time_point('exec_moduls_setup - '.$mode.' - '.$func_name) ;
     }
     // новый способ - подключаем скрипт m_XXX_admin.php, в нем будет класс с инсталятором модуля
     // в дальнейшем, когда вариант через $__functions['install'][]	='_mailer_install_modul' ; будет отключен, админкский файл подключаться не будет
     //damp_array($GLOBALS['_SETTING']['modules']) ;
     $arr_modules=$GLOBALS['_SETTING']['modules'] ;
     $arr_modules_locals=$GLOBALS['_SETTING']['modules_local'] ;
     $modules_istaller=&$GLOBALS['installer_modules'] ;
     if (_sizeof($arr_modules)) foreach($arr_modules as $modul_name=>$enabled) if ($enabled and !$arr_modules_locals[$modul_name])
     {  include_once(_DIR_TO_MODULES.'/'.$modul_name.'/m_'.$modul_name.'_admin.php');
        if (!is_object($modules_istaller[$modul_name]) and class_exists('c_'.$modul_name.'_system_install'))
        { $installer_class_name='c_'.$modul_name.'_system_install' ;
          $modules_istaller[$modul_name]=new $installer_class_name ;
        }
        // если объект класса инсталяционного модуля успешно создан - дергаем процедуру инсталяции
        if (is_object($modules_istaller[$modul_name]))
        { if (method_exists($modules_istaller[$modul_name],$mode)) $modules_istaller[$modul_name]->$mode() ;
          else echo '<div class="red">Инсталятор модуля <strong>'.$modul_name.'</strong> - не найден метод <strong>'.$mode.'</strong></div>' ;
        }
     }
     if (_sizeof($arr_modules_locals)) foreach($arr_modules_locals as $modul_name=>$enabled) if ($enabled)
     {  include_once(_DIR_TO_MODULES_LOCAL.'/'.$modul_name.'/m_'.$modul_name.'_admin.php');
        if (!is_object($modules_istaller[$modul_name]) and class_exists('c_'.$modul_name.'_system_install'))
        { $installer_class_name='c_'.$modul_name.'_system_install' ;
          $modules_istaller[$modul_name]=new $installer_class_name ;
        }
        // если объект класса инсталяционного модуля успешно создан - дергаем процедуру инсталяции
        if (is_object($modules_istaller[$modul_name]))
        { if (method_exists($modules_istaller[$modul_name],$mode)) $modules_istaller[$modul_name]->$mode() ;
          else echo '<div class="red">Инсталятор модуля <strong>'.$modul_name.'</strong> - не найден метод <strong>'.$mode.'</strong></div>' ;
        }
     }


     $arr_plugins=$GLOBALS['_SETTING']['plugins'] ;
     $arr_plugins_locals=$GLOBALS['_SETTING']['plugins_local'] ;
     if (_sizeof($arr_plugins)) foreach($arr_plugins as $plugin_name=>$enabled) if ($enabled and !$arr_plugins_locals[$plugin_name])
     {   $plugin=strtoupper($plugin_name) ;
         if (function_exists($plugin) and method_exists($plugin(),'install'))
         { $plugin()->install() ;
     }
     }
     if (_sizeof($arr_plugins_locals)) foreach($arr_plugins_locals as $plugin_name=>$enabled) if ($enabled)
     {   $plugin=strtoupper($plugin_name) ;
         if (function_exists($plugin) and method_exists($plugin(),'install'))
         { $plugin()->install() ;
         }
     }
     //damp_array($modules_istaller) ;
     fixed_time($t1,'Выполнено '.$mode) ;
 }

  function check_setting_and_log()
  { $t1=fixed_time() ; ob_start() ;   $cnt_sql_before=_sizeof($GLOBALS['sql_stats']) ;

    // проверка окружения
    ?><h2>Проверка окружения</h2><?
    $this->check_version_soft() ;

    // ---------- набор обязательных проверок ---------------------- //
    ?><h2>Проверка наличия системных таблиц</h2><?
    create_sys_table() ;
    $this->exec_moduls_setup('db_tables','Проверка наличия таблиц ЭСМО') ;

   $this->check_setting()  ;

    create_model_obj_tables(array('no_describe_tables'=>1)) ;

    /*?><h2>Проверка структуры БД</h2><?
    $this->check_db(array('no_reboot_engine'=>1)) ;
    // ---------- набор обязательных проверок ---------------------- //
     */


   $t2=fixed_time($t1,'Время выполения проверки: ') ;
   $cnt_sql_after=_sizeof($GLOBALS['sql_stats']) ;
   echo 'Выполнено SQL-запросов: <strong>'.($cnt_sql_after-$cnt_sql_before).'</strong><br>' ;
   echo $text=ob_get_clean() ;
   LOGS()->reg_log('system_check','Проверка настроек',array('save_to_file'=>$text,'start'=>$t1));
  }

  // более не используется, вынесено в плагины, которые подключаются в ini.yaml
  /*function collect_ext_setup_functions()
  {  global $__functions ;
     //damp_array($__functions) ;
     echo _sizeof($__functions['init']).' / '._sizeof($__functions['boot_site']).' / '._sizeof($__functions['boot_admin']).' / '._sizeof($__functions['install']).'<br>' ;
     $files=get_all_files(_DIR_EXT.'/') ;
     if (_sizeof($files)) foreach($files as $fname)
     { $script_name=basename($fname) ;
       if (strpos($script_name,'i_')===0)
       { include_once($fname) ;
         echo 'Подключен скрипт <strong>'.hide_server_dir($fname).'</strong><br>' ;
         echo _sizeof($__functions['init']).' / '._sizeof($__functions['boot_site']).' / '._sizeof($__functions['boot_admin']).' / '._sizeof($__functions['install']).'<br>' ;
       }
     }
  } */

  function check_version_soft()
  {
    // проверяем наличие функции mysqli_fetch_all
    if (function_exists('mysqli_fetch_all')) $this->append_ini_value('main_db','use_mysqli_fetch_all',1);
  }

 function check_db($options=array())
   { //if (!$options['no_reboot_engine']) reboot_engine() ;
    FILE_LOG()->append('Проверка полей таблиц') ;
    ?><h2>Проверка полей таблиц</h2><?
        $cnt_sql_cmd=0 ;
         $options_checked=array('no_update_descr_tables'=>1,
                        'no_show_button'=>1,
                        'show_in_outer_table'=>1,
                        'no_check_not_used_field'=>1,
                        'no_check_type_fields'=>1,
                        'log_sql'=>1
                       );
       if (is_array($options) and _sizeof($options)) $options_checked=array_merge($options_checked,$options) ;

        include_once(_DIR_EXT.'/db/i_table_checked.php') ;
        ?><table class=table_checked><?

        $table_rows=execSQL_row('
              SELECT TABLE_NAME,table_rows 
              FROM information_schema.TABLES 
              WHERE table_schema = "'.$GLOBALS['_SETTING']['main_db']['db_name'].'" and TABLE_TYPE!="VIEW"');

         if (_sizeof($_SESSION['descr_obj_tables'])) foreach ($_SESSION['descr_obj_tables'] as $obj)
         {   $table_name=$obj->table_name ;
             if (isset($table_rows[$table_name]))
             {   if (!$options['no_check_big_tables'] or ($options['no_check_big_tables'] and $table_rows[$table_name]<10000))
                $cnt_sql_cmd+=table_checked($obj->pkey,$options_checked) ;
             else echo '<strong>'.$table_name.'</strong> - проверка отложена, в таблице <strong>'.$table_rows[$table_name].'</strong> строк<br>' ;
         }
             else
             {
                 echo '<strong>'.$table_name.'</strong> - <span class="red">проверка отменена, таблица отсутствует в БД</span><br>' ;
             }
         }
        ?></table><?


       //damp_array($GLOBALS['sql_cache'],1,-1);
        //return(array('no_default_panel'=>1)) ;
       }



    //-----------------------------------------------------------------------------------------------------------------------------
    // РАБОТАЕМ С НАБОРОМ ТАБЛИЦ
    // описание классов
    // 101 - объектная таблицы
    // 106 - индексная таблицы
    // 108 - журнальная таблица
    // 103 - набор таблиц
    // 104 - поддерживаемый класс таблицы
    // 105 - клон изображения
    // 107 - описание поля для редактирования (класс,тип,размер)
    //-----------------------------------------------------------------------------------------------------------------------------

    function create_table_DOT()
           {   echo 'Создаем корневую таблицу DOT<br>' ;
               //execSQL_update('DROP TABLE IF EXISTS obj_descr_obj_tables;') ;
               $sql="
               CREATE TABLE obj_descr_obj_tables (
                 pkey int(11) NOT NULL AUTO_INCREMENT,
                 clss int(11) NOT NULL DEFAULT '0',
                 enabled int(1) NOT NULL DEFAULT '1',
                 indx int(11) DEFAULT NULL,
                 obj_name text,
                 parent int(11) NOT NULL DEFAULT '1',
                 c_data int(11) DEFAULT NULL,
                 r_data int(11) DEFAULT NULL,
                 table_name text,
                 dir_to_image text,
                 img_pattern varchar(255) DEFAULT NULL,
                 temp int(11) DEFAULT NULL,
                 setting text,
                 tkey int(11) NOT NULL DEFAULT 2,  
                 _enabled int(1) NOT NULL DEFAULT 1,
                 code varchar(32) DEFAULT NULL,
                 doc_name varchar(32) DEFAULT NULL,
                 fields_info text,
                 PRIMARY KEY (pkey),
                 KEY parent (parent),
                 KEY clss (clss)
               ) ENGINE=InnoDB DEFAULT CHARSET=utf8;" ;
               execSQL_update($sql) ;
               execSQL_update('INSERT INTO obj_descr_obj_tables (pkey, clss, enabled, indx, obj_name, parent, c_data, r_data, table_name, dir_to_image, img_pattern, temp, setting, tkey, _enabled, code, doc_name, fields_info) VALUES (1, 1, 1, 1, "Объектные таблицы", 0, 1339704156, 1339704156, NULL, NULL, NULL, NULL, NULL, 2, 1, NULL, NULL, NULL);') ;
         }

    // создаем запись в DOT для объектной таблицы
    // parent - объект, которому принадлежит таблица
    // table_clss - класс таблицы: 101,106,108
    // table_title - название таблицы (по назначению)
    // table_name - название таблицы (в базе данных)
    // dir - директория файлов таблицы
    function DOT_append_table($options)
    {  if (!$options['table_parent']) $options['table_parent']=1 ;
       if (!$options['table_clss'])   $options['table_clss']=101 ;
       if (!$options['table_title'])  $options['table_title']='Новая таблица' ;
       if (!$options['table_name'])   $options['table_name']='obj_site_'.rand(1,100) ;

       $finfo=array('parent'		=>  $options['table_parent'],
   					'clss'			=>	$options['table_clss'],
   					'obj_name' 		=> 	$options['table_title'],
   					'table_name'	=>  $options['table_name'],
   					'dir_to_image'	=>  $options['dir_to_image'],
   					'img_pattern'	=>  $options['img_pattern'],
   					'indx'	        =>  1
   		  		) ;
   	   //damp_array($finfo) ;
    	$DOT_id=adding_rec_to_table('obj_descr_obj_tables',$finfo) ;
    	//echo 'DOT: adding item '.$options['table_clss'].' for object '.$options['table_parent'].' (<strong>'.$options['table_title'].'</strong>)<br/>' ;
    	return($DOT_id) ;
    }

    // создаем запись в DOT для поддерживаемого класса
    function DOT_append_clss($parent,$clss)
    { //echo '$clss='.$clss.'<br>';
      //echo 'Текущий список поддерживаемых классов: ' ; print_r(_DOT($parent)->list_clss) ; echo '<br>' ;
      $list_exists_clss=array();
      if (ESMO_STATUS!='SETUP_FIRST') $list_exists_clss=execSQL_line('select indx from obj_descr_obj_tables where clss=104 and parent='.$parent) ;
      if (!$clss) { echo 'Не указан код класса для добавления в DOT<br>' ; return ; }
      $list_clss=explode(',',$clss) ; //damp_array($list_clss) ;
      if (_sizeof($list_clss)) foreach($list_clss as $clss) if (!in_array($clss,$list_exists_clss))
      	 { $finfo=array('parent'=>$parent,'clss'=>104,'indx'=>$clss,'obj_name'=>_CLSS($clss)->name) ;
      	   //print_r($finfo) ; echo '<br>' ;
           if (ESMO_STATUS=='SETUP_FIRST') multiSQL_insert('obj_descr_obj_tables')->append($finfo) ;
           else                      adding_rec_to_table('obj_descr_obj_tables',$finfo,array('no_return_id'=>1)) ;
   	       //echo 'DOT: adding item 104 for object '.$parent.' (поддержка класса <strong>'.$clss.'</strong>)<br/>' ;
      	 }
    }

    // функция объединяет создание записей в DOT, создание таблицы в БД, обновление модели и проверку таблицы
    // title - наименование
    // table_name - название таблицы
    // type - тип таблицы: 101 -объектная, 106 - индексная, 108 - журнал
    // mode - режим таблицы: main, out
    // use_clss - поддерживаемые классы
    // pattern - шаблон таблицы

    function DOT_append_object_table($options)
    {
      // создаем запись в DOT для новой таблицы
      $id=$this->DOT_append_table($options) ;
      // создаем запись в DOT по поддерживаемым классам
      $this->DOT_append_clss($id,$options['use_clss']) ;
      // обновляем модель таблиц - в ней уже будет вся инфоримация по поддерживаемым классам
      create_model_obj_tables(array('use_tkey_table'=>$id,'no_describe_tables'=>1)) ;
      // создаем физическую таблицу в базе данных по описанию в DOT
      $this->create_object_table_by_DOT($id,$options['def_recs']) ;
      // делаем проверку таблицы
      include_once(_DIR_EXT.'/db/i_table_checked.php') ;
      table_checked($id) ;

      return($id)  ;
    }

    // создать системную таблицу по записи в DOT
    // для таблицы уже должно существовать описание в DOT, tkey - код описания
    // через $def_recs можно передать набор записей, добавляемых по умолчанию в таблицу
    function create_object_table_by_DOT($id,$def_recs=array())
   	 {
   	   $table_obj=_DOT($id) ; if (!is_object($table_obj)) {echo '<div class=alert>Объект DOT с кодом '.$id.' не существует<br>';}
   	   $table_name=$table_obj->table_name ; if (!$table_name) {echo '<div class=alert>Не указано имя таблицы для объекта DOT с кодом '.$id.'<br>';}
     	   $table_title=$table_obj->name ;
   	   // собираем в массив все поля объектов, которые должны присутствовать в таблице
   	   // !!! конфликтность на одноименные полей различных классов (несоответствие типов) должна проверяться при назначении классов таблице
   	   //damp_array($table_obj->list_clss_ext) ;
   	   // в таблице должны присутствовать только поля тех классов, которые в list_clss_ext прописаны в поле main для данной таблицы
   	   if (_sizeof($table_obj->list_clss_ext)) foreach($table_obj->list_clss_ext as $clss=>$clss_info) if ($clss_info['main']==$id) $arr_clss[]=$clss ;
          if (_sizeof($arr_clss)) $use_clss=implode(',',$arr_clss) ;

   	   create_object_table($id,$table_name,$table_title,$use_clss,$def_recs) ;
   	 }



 // используется тока в режиме инсталяции движка
 function create_table_by_pattern($pattern)
 {  global $install_options ;
    if (_sizeof($install_options) and !$install_options['db_tables']) return($_SESSION['list_db_tables'][$pattern['table_name']]) ;

    if (!_sizeof($_SESSION['list_db_tables'])) $_SESSION['list_db_tables']=execSQL_row('select table_name,pkey from obj_descr_obj_tables where clss=101 order by pkey') ;

    // проверяем, что таблица реально существует, если нет - убираем запись и DOT - она будет создана занов
    $table_exists=execSQL('show tables like "'.$pattern['table_name'].'"') ;
    if (!_sizeof($table_exists) and $_SESSION['list_db_tables'][$pattern['table_name']])
    {  $table_id=$_SESSION['list_db_tables'][$pattern['table_name']] ;
       execSQL_update('delete from obj_descr_obj_tables where pkey='.$table_id) ;
       execSQL_update('delete from obj_descr_obj_tables where parent='.$table_id) ;
       unset($_SESSION['list_db_tables'][$pattern['table_name']]) ;
    }

    if (!isset($_SESSION['list_db_tables'][$pattern['table_name']]))
    { echo 'Добавляем описание таблицы: '.$pattern['table_name'].'<br>' ;
      if ($pattern['table_name'])
      { // создаем запись в DOT по таблице
        $id=$this->DOT_append_table($pattern) ;

        // создаем запись в DOT по поддерживаемым классам
        $this->DOT_append_clss($id,$pattern['use_clss']) ;

        // создаем таблицу в базе данных
        if (!_sizeof($GLOBALS['arr_exists_tables'])) $GLOBALS['arr_exists_tables']=execSQL_line('show tables') ;
        if (!in_array($pattern['table_name'],$GLOBALS['arr_exists_tables'])) $this->create_object_table($id,$pattern['table_name'],$pattern['table_title'],$pattern['use_clss'],$pattern['def_recs'],$pattern) ;

      }
      else  { echo '<span class=red>Не указано имя таблицы, pattern=' ; print_r($pattern)  ; echo '</span><br>' ; }
    } else 	{ echo '<strong>'.$pattern['table_name'].'</strong> - checked is <span class="green">OK</span><br>' ;
              $this->check_table_clss_list($_SESSION['list_db_tables'][$pattern['table_name']],$pattern['use_clss']) ;
              $id=$_SESSION['list_db_tables'][$pattern['table_name']] ;
            }
    return($id) ;
 }

 function create_object_table($id,$table_name,$table_title,$use_clss,$def_recs=array(),$options=array())
      { ?>Создаем таблицу <strong>"<?echo $table_title?>"</strong> [<?echo $table_name?>]<br><?
    	   $list_field=array() ;
    	   //$table_obj=_DOT($id) ; if (!is_object($table_obj)) {echo '<div class=alert>Объект DOT с кодом '.$id.' не существует<br>';}
    	   // собираем в массив все поля объектов, которые должны присутствовать в таблице
    	   // !!! конфликтность одноименные полей различных классов (несоответствие типов) должна
    	   // проверяться при назначении классов таблице
    	   $arr_clss=explode(',',$use_clss) ;    $arr_index=array() ;
    	   if (_sizeof($arr_clss)) foreach($arr_clss as $clss)
           {  $obj_clss=_CLSS($clss);
              if (_sizeof($obj_clss->fields)) foreach ($obj_clss->fields as $fname=>$ftype)
              { $list_field[$fname]=$ftype ;
                if (isset($obj_clss->default[$fname])) $list_def[$fname]=($fname=='tkey')? $id:$obj_clss->default[$fname] ;
                if (_sizeof($obj_clss->index))$arr_index=array_merge($arr_index,$obj_clss->index) ;
              }
              else echo 'Класс '.$clss.' - не описаны поля!<br>' ;
           }

    	   if (_sizeof($list_field)) foreach ($list_field as $fname=>$ftype)
    	    { $add_usl= ($fname=='pkey')? "auto_increment":"" ;
              $real_type=convert_virt_type_to_db_type($ftype) ;
              $def=isset($list_def[$fname])? "DEFAULT  '".$list_def[$fname]."'":'' ;
    	      $_sql[]="$fname $real_type $def $add_usl" ;
    	    }
           $_sql[]="`temp` int(11) NULL" ;

    	   $sql ="CREATE TABLE `".$table_name."` (" ;
    	   $sql.=implode(',',$_sql) ;
    	   if (isset($list_field['pkey'])) 		$sql.=", PRIMARY KEY  (`pkey`) " ;
    	   if (_sizeof($arr_index)) foreach($arr_index as $index_name=>$index_fields) $sql.=', INDEX  '.$index_name.'('.$index_fields.') ' ;
    	   //if (isset($list_field['parent'])) 	$sql.=", KEY  (`parent`) " ;
    	   //if (isset($list_field['clss'])) 		$sql.=", KEY  (`clss`) " ;

    	   //damp_array($arr)

           $table_engine=($options['table_engine'])? $options['table_engine']:'InnoDB' ;
           $table_charset=($options['table_charset'])? $options['table_charset']:'utf8' ;
    	   $sql.=") ENGINE=".$table_engine." CHARSET=".$table_charset ;
    	   //echo $sql.'<br>' ;
    	   //$result = mysqli_query($GLOBALS['DB_LINK'],$sql) or die("Invalid query: " . mysqli_error($GLOBALS['DB_LINK']));
           $result = execSQL_update($sql) ;

    	   if ($options['auto_increment']) execSQL_update('ALTER TABLE '.$table_name.' AUTO_INCREMENT = '.$options['auto_increment']) ;

             //echo "<strong class=green>Создана объектная таблица '".$table_name."'</strong><br>" ;
             $GLOBALS['arr_exists_tables'][]=$table_name ;

           // добавление строк по умолчанию в таблицу
           if (_sizeof($def_recs))  foreach ($def_recs as $def_rec) multiSQL_insert($table_name)->append($def_rec) ;
           multiSQL_insert($table_name)->flush() ;

             //    adding_rec_to_table($table_name,$def_rec,array('no_check_exist_fields'=>1,'no_auto_indx'=>1,'no_return_id'=>1)) ;
             //_event_reg('Создание в БД таблицы',$table_title.' ('.$table_name.')')  ; // регистрируем событие 'Создание в БД таблицы'

           //$test=execSQL('select * from '.$table_name) ;
    	   // добавлям в таблицу записи согласно щаблону, если он указан

    	   //damp_array($def_recs);
          //die('stop') ;



    	 }

 function check_table_clss_list($tkey,$str_clss)
   { $set_clss=explode(',',$str_clss) ;
     if (!_sizeof($GLOBALS['cach_DOT_clss']))
     { $arr=execSQL('select parent,indx from obj_descr_obj_tables where clss=104',0,1) ;
       if (_sizeof($arr)) foreach($arr as $rec_clss) $GLOBALS['cach_DOT_clss'][$rec_clss['parent']][]=$rec_clss['indx'] ;
     }
     if (_sizeof($set_clss)) foreach($set_clss as $clss)
     if (!in_array($clss,$GLOBALS['cach_DOT_clss'][$tkey])) // 7.05.2011 - изменяем проверку по модели на проверку по базе - так как при инсталяции модель не всегда корректа
       { echo '<div class=red>Класс ['.$clss.'] - не поддерживается, будет добавлен</div>' ;
         SETUP()->DOT_append_clss($tkey,$clss) ;
         $GLOBALS['cach_DOT_clss'][$tkey][]=$clss ;
       }
   }

 // используется тока в режиме инсталяции движка
 function change_tables_attr()
 { execSQL_update('update obj_descr_obj_tables set parent=1 where clss=101 and table_name="obj_descr_obj_tables"') ;
    execSQL_update('update obj_descr_obj_tables set dir_to_image="/public/account/" where table_name="obj_site_account_image"') ;
    execSQL_update('update obj_descr_obj_tables set dir_to_image="/public/account/" where table_name="obj_site_account_files"') ;
    execSQL_update('update obj_descr_obj_tables set dir_to_image="/public/personals/",img_pattern="personal" where table_name="obj_site_personals_image"') ;

 }

 function create_viewer($name,$sql_crate)
 {  global $install_options ;
    ob_start() ;
    if (_sizeof($install_options) and !$install_options['viewers']) return ;
    $sql=preg_replace('/create (.+?) as/is','',$sql_crate) ;
    $sql='CREATE OR REPLACE view '.$name.' as '.$sql ;;
    $result='<span class="green">OK</span>' ;
    ob_start() ;
    execSQL_update($sql,array('debug'=>0)) ;
    $text=ob_get_clean() ;
    if (preg_match('/Ошибка при отработке SQL запроса/is',$text)) $result='<span class="red">ERROR</span><br>'.$text ; ;
    if (preg_match('/is not VIEW/is',$text))
    { echo $name.' создана как таблица, будет удалена.<br>' ;
      execSQL_update('drop table '.$name,array('debug'=>0)) ;
      execSQL_update($sql,array('debug'=>0)) ;
      $result='<span class="green">OK</span>' ;
    }
     FILE_LOG()->append('create_viewer - '.$name) ;

    echo 'viewer <strong>'.$name.'</strong> - '.$result.'<br>' ;
    $text=ob_get_clean() ;
    LOGS()->reg_log('create_viewer',$text) ;
 }

 function create_ids_table($name,$sql_crate)
 {  global $install_options ;
    if (_sizeof($install_options) and !$install_options['viewers']) return ;

     execSQL_update('drop view if exists '.$name) ;
     execSQL_update('DROP TABLE IF EXISTS '.$name) ;


    //$sql=preg_replace('/create (.+?) as/is','',$sql_crate) ;
    $sql='CREATE table '.$name.' (pkey INT(11) NOT NULL, PRIMARY KEY (pkey)) ENGINE=Innodb AS '.$sql_crate ;;
    $result='<span class="green">OK</span>' ;
    echo nl2br($sql).'<br>' ;
    ob_start() ;
    execSQL_update($sql,array('debug'=>0)) ;
    $text=ob_get_clean() ;
    if (preg_match('/Ошибка при отработке SQL запроса/is',$text)) $result='<span class="red">ERROR</span><br>'.$text ; ;
    /*if (preg_match('/is not VIEW/is',$text))
    { echo $name.' создана как таблица, будет удалена.<br>' ;
      execSQL_update('drop table '.$name,array('debug'=>0)) ;
      execSQL_update($sql,array('debug'=>0)) ;
      $result='<span class="green">OK</span>' ;
    }*/
     FILE_LOG()->append('create_table_ids - '.$name) ;

    echo 'table ids <strong>'.$name.'</strong> - '.$result.'<br>' ;
 }

 function create_temporary_table($name,$sql_create,$options=[])
 {  //$sql='CREATE TEMPORARY TABLE IF NOT EXISTS '.$name.' (pkey INT(11) NOT NULL, PRIMARY KEY (pkey))  '.$sql_create ;;
    //$sql='CREATE TEMPORARY TABLE IF NOT EXISTS '.$name.'   '.$sql_create ;;
    ob_start() ;
    $sql='DROP TEMPORARY TABLE IF EXISTS '.$name ;;
    execSQL_update($sql,array('debug'=>0)) ;
    $sql='CREATE TEMPORARY TABLE  '.$name.'   '.$sql_create ;;
    $result='<span class="green">OK</span>' ;
    if ($options['debug']) echo nl2br($sql).'<br>' ;
    execSQL_update($sql,array('debug'=>$options['debug'])) ;
    $text=ob_get_clean() ;
    if (preg_match('/Ошибка при отработке SQL запроса/is',$text)) $result='<span class="red">ERROR</span><br>'.$text ; ;
    echo $text ;
    echo 'TEMPORARY table <strong>'.$name.'</strong> - '.$result.'<br>' ;

 }
 function create_table($name,$sql_create,$options=[])
 {  //$sql='CREATE TEMPORARY TABLE IF NOT EXISTS '.$name.' (pkey INT(11) NOT NULL, PRIMARY KEY (pkey))  '.$sql_create ;;
    //$sql='CREATE TEMPORARY TABLE IF NOT EXISTS '.$name.'   '.$sql_create ;;
    ob_start() ;
    $sql='DROP TABLE IF EXISTS '.$name ;;
    execSQL_update($sql,array('debug'=>0)) ;
    $sql='CREATE TABLE  '.$name.'   '.$sql_create ;;
    $result='<span class="green">OK</span>' ;
    if ($options['debug']) echo nl2br($sql).'<br>' ;
    execSQL_update($sql,array('debug'=>$options['debug'])) ;
    $text=ob_get_clean() ;
    if (preg_match('/Ошибка при отработке SQL запроса/is',$text)) $result='<span class="red">ERROR</span><br>'.$text ; ;
    echo $text ;
    echo 'Table <strong>'.$name.'</strong> - '.$result.'<br>' ;

 }

// операции с настройками сайта
function SETUP_add_section_to_site_setting($sect_name)
{ global $install_options ;
  if (_sizeof($install_options) and !$install_options['vars']) return ;
  $GLOBALS['current_var_in_section_position']=0 ;
  $GLOBALS['current_vars_section_position']++ ;
  if (!_sizeof($GLOBALS['site_section_settings_name_id'])) $GLOBALS['site_section_settings_name_id']=execSQL_row('select obj_name,pkey from '.TM_SETTING.' where clss=1') ;
  if (!isset($GLOBALS['site_section_settings_name_id'][$sect_name]))
  { $id=adding_rec_to_table(TM_SETTING,array('parent'=>1,'clss'=>1,'obj_name'=>$sect_name,'indx'=>$GLOBALS['current_vars_section_position'],'temp'=>0)) ;
    echo 'Настройки: раздел <strong>'.$sect_name.'</strong>' ;
    if ($id) echo ' - <span class="green">CREATE</span>' ; else echo ' - <span class="red">ERROR</span>' ;
    echo '<br>' ;
  }
  else
  { $id=$GLOBALS['site_section_settings_name_id'][$sect_name] ;
    $this->arr_settings_ids[]=$id ; // отложенные обновление, будет сброшен флаг temp сразу для всех переменных в массиве, экономит порядка 200 запросов к БД
    echo 'Настройки: раздел <strong>'.$sect_name.'</strong> - <span class="green">OK</span><br>' ;
  }
  return($id) ;
}


 // операции с настройками сайта
 var $arr_settings_ids=array() ;
 function SETUP_add_rec_to_site_setting($sect_id,$name,$value,$code,$options=array())
 { global $install_options ;
   if (_sizeof($install_options) and !$install_options['vars']) return ;
   if ($GLOBALS['add_rec_to_site_setting_is_block']) return ;
   $GLOBALS['current_var_in_section_position']++ ;

   if (!is_array($options)) $options=array() ;
   if (ESMO_STATUS!='SETUP_FIRST' and !_sizeof($GLOBALS['site_settings']))
   {   /// !!! если запрос выдаст ошибку из-за отстуствующих полей - необходимо отменить добавление переменной
       /// иначе будут созданы дубликаты переменных
       ob_start() ;
       $GLOBALS['site_settings']=execSQL('select comment,pkey,parent,hidden,obj_name,comment,crypt,keywords,value,ext_info,indx from '.TM_SETTING.' where clss=99') ;
       ob_get_clean() ;
       $err_id=mysqli_errno($GLOBALS['DB_LINK']) ;//mysqli_error($GLOBALS['DB_LINK'])
       if ($err_id)
       { echo '<div class="alert">Внимание, в таблице настроет отсутствуют необходимые поля, необходимо выполнить проверку таблиц, затем повторить проверку настроек.</div>' ;
         $GLOBALS['add_rec_to_site_setting_is_block']=1 ;
         return ;
       } else $GLOBALS['add_rec_to_site_setting_is_block']=0 ;
   }
   if (!isset($GLOBALS['site_settings'][$code]))
   { $data=array('parent'=>$sect_id,'clss'=>99,'obj_name'=>$name,'value'=>$value,'comment'=>$code,'indx'=>$GLOBALS['current_var_in_section_position'],'temp'=>0) ;
     $data['crypt']=(isset($options['crypt']))? (int)$options['crypt']:0 ;
     $data['enabled']=(isset($options['enabled']))? (int)$options['enabled']:1 ;
     $data['keywords']=(isset($options['keywords']))? $options['keywords']:0 ;
     $data['hidden']=(isset($options['hidden']))? $options['hidden']:0 ;
     unset($options['crypt'],$options['enabled'],$options['keywords']) ;
     if (_sizeof($options)) $data['ext_info']=$options ;
     //if (isset($options['hidden'])) $data['hidden']=(int)$options['hidden'] ;
     //if (isset($options['el'])) $data['el']=$options['el'] ;
     //if (isset($options['human'])) $data['human']=$options['human'] ;
     //if (isset($options['descr'])) $data['descr']=$options['descr'] ;
     if (ESMO_STATUS=='SETUP_FIRST') multiSQL_insert(TM_SETTING)->append($data) ;
     else                      adding_rec_to_table(TM_SETTING,$data,array('no_return_id'=>1)) ;
     echo 'Настройки: запись <strong>'.$name.'</strong>' ;
     // если передана опция что храним данные в ini.yaml - сохраняем туда настройку в блок
     if ($options['place']=='ini') $this->append_ini_value('LocalSettings',$code,$value,array('no_check_setup_level'=>1));
     /*if ($id) */echo ' - <span class="green">CREATE</span>' ;
     //else echo ' - <span class="red">CREATE ERROR</span>' ;
     echo '<br>' ;
   }
   else
   { $id=$GLOBALS['site_settings'][$code]['pkey'] ;
     $rec_item=$GLOBALS['site_settings'][$code] ;
     $ext_info=unserialize($rec_item['ext_info']) ;
     $arr_chages=array() ;
     if ($rec_item['parent']!=$sect_id) { $arr_chages['parent']=$sect_id ; }
     if ($rec_item['obj_name']!=$name)  { $arr_chages['obj_name']=$name ; }
     if ($options['update_current_value'] and $rec_item['value']!=$value)  { $arr_chages['value']=$value ; }
     if (isset($options['crypt']) and $rec_item['crypt']!=$options['crypt'])
     { $arr_chages['crypt']=(int)$options['crypt'] ;
       // необходимо зашифровать/расшифровать текущее значение переменной
       if ($options['crypt'])  $arr_chages['value']=encrypt_string($rec_item['value']) ;
       else                    $arr_chages['value']=decrypt_string($rec_item['value']) ;
       //echo $rec_item['value'].' => '.$arr_chages['value'].'<br>' ;
     }
     if (isset($options['enabled'])  and $rec_item['enabled']!=$options['enabled'])      $arr_chages['enabled']=(int)$options['enabled'] ;
     if (isset($options['keywords']) and $rec_item['keywords']!=$options['keywords'])    $arr_chages['keywords']=$options['keywords'] ;
     if (isset($options['hidden']) and $rec_item['hidden']!=$options['hidden'])          $arr_chages['hidden']=$options['hidden'] ;

       unset($options['crypt'],$options['enabled'],$options['keywords'],$options['hidden']) ;
     // все остальные значения options автоматически сохраняются в ext_info
     if (_sizeof($options)) foreach($options as $key=>$val) if ($ext_info[$key]!=$val)  { $ext_info[$key]=$val ;  $arr_chages['ext_info']=$ext_info ; }

     if (_sizeof($arr_chages)) { $status='UPDATE' ;  /*damp_array($arr_chages,1,-1) ;*/}
     else                       $status='OK' ;

     if ($GLOBALS['current_var_in_section_position']!=$rec_item['indx']) $arr_chages['indx']=$GLOBALS['current_var_in_section_position'] ;
     // no_append_serialize_data - не делать слияние $ext_info с уже сохраненными данными, так как слияние уже сделано ранее

     if (_sizeof($arr_chages))
     {   $arr_chages['temp']=0 ;
         update_rec_in_table(TM_SETTING,$arr_chages,'pkey='.$id,array('no_append_serialize_data'=>1,'debug'=>0)) ;
     }
     $this->arr_settings_ids[]=$rec_item['pkey'] ; // отложенные обновление, будет сброшен флаг temp сразу для всех переменных в массиве, экономит порядка 200 запросов к БД

     // если передана опция что храним данные в ini.yaml - сохраняем туда настройку в блок
     if ($options['place']=='ini' and !isset($GLOBALS['_SETTING']['LocalSettings'][$code])) $this->append_ini_value('LocalSettings',$code,$value,array('no_check_setup_level'=>1));


     echo 'Настройки: запись <strong>'.$name.'</strong> - <span class="green">'.$status.'</span><br>' ;
   }
   //return($id) ;
 }

  function update_site_setting($name,$value,$options=array())
  { $old_rec=execSQL_van('select * from obj_site_setting where comment="'.$name.'"') ;
    $new_value=($old_rec['crypt'])? encrypt_string($value):$value ;
    if ($old_rec['value']!=$new_value)
      { execSQL_update('update obj_site_setting set value="'.$new_value.'" where comment="'.$name.'"',array('debug'=>$options['debug'])) ;
        $GLOBALS[$name]=$value ;
        $text=$old_rec['obj_name'].' ['.$name.']: '.$old_rec['value'].' => '.$new_value ;
        if ($old_rec['crypt']) $text.=' (crypt)' ;
        if (!$options['no_log']) LOGS()->reg_log('save_setting',$text) ;
      }
  }

 function check_exists_file($dir,$options=array())
 {  global $install_options ;
    if (_sizeof($install_options) and !$install_options['check_dir_files']) return ;
    if ($options['remove_old_file'] and file_exists(_DIR_TO_ROOT.$dir)) { unlink(_DIR_TO_ROOT.$dir) ; }
    if (!file_exists(_DIR_TO_ROOT.$dir))
     {   echo 'Будет создан скрипт <strong>'.$dir.'</strong> из '.(_DIR_TO_CLASS.'/setup'.$dir).' ' ;
         //$source_file=(file_exists(_DIR_TO_CLASS.'/setup'.$dir))? _DIR_TO_CLASS.'/setup'.$dir:_DIR_TO_ROOT.'/setup/in'.$dir ;
         $source_file=_DIR_TO_CLASS.'/setup'.$dir;
         if (copy($source_file,_DIR_TO_ROOT.$dir)) echo ' - <span class="green">OK</span>' ;
         else                                                   echo ' - <span class="red">ERROR</span>' ;
     }
    else echo 'Скрипт <strong>'.$dir.'</strong> - <span class="green">OK</span>' ;
    echo '<br>' ;
 }

    function check_dir_protection($dir)
    {  global $install_options ;
       if (_sizeof($install_options) and !$install_options['check_dir_files']) return ;

       if (file_exists(_DIR_TO_ROOT.$dir))
       {  echo 'Защита директории <strong>'.$dir.'</strong> от запуска скриптов ' ;
          $cont='' ;
          if (file_exists(_DIR_TO_ROOT.$dir.'/.htaccess'))
          { $cont=file_get_contents(_DIR_TO_ROOT.$dir.'/.htaccess') ;
            $cont.="\n" ;
          }
          if (strpos($cont,'RemoveHandler')===false)
          { $cont.="RemoveHandler .php\n".
                  "RemoveType .php\n".
                  "AddType application/x-httpd-php-source .php\n".
                  "Options -ExecCGI -Indexes\n".
                  "php_flag engine off\n" ;
             $res=file_put_contents(_DIR_TO_ROOT.$dir.'/.htaccess',$cont) ;
            if ($res) echo ' - <span class="green">CREATE</span>' ;
            else echo ' - <span class="red">ERROR</span> (не удалось создать файл .htaccess)' ;
          }
          else echo ' - <span class="green">ОК</span>' ;
          echo '<br>' ;
       }
    }

    // проверить наличие каталога изображений для объектной таблицы
   function check_obj_table_file_dir($tkey)
   {  global $install_options ;
      if (_sizeof($install_options) and !$install_options['check_dir_files']) return ;


      // проверяем, существует ли каталог для хранения изображений
      // если нет, то создаем
      $show_file_pars=0 ;
      $cur_table=_DOT($tkey) ;
      if (_sizeof($cur_table->list_clss)) foreach($cur_table->list_clss as $clss=>$clss_tkey)
      {
          $obj_clss=_CLSS($clss);
          if (is_object(_CLSS($clss)) and $obj_clss->has_parent_clss(5) and $cur_table->list_clss[$clss]==$tkey) $show_file_pars=1 ;
      }


      if (_DOT($tkey)->dir_to_file and $show_file_pars)
      { echo "<br><strong>Проверка существования каталога файлов для '"._DOT($tkey)->table_name."'</strong><br>" ;
        $dir=_DOT($tkey)->dir_to_file ;
        //if (is_dir($dir))
        {  echo $dir.": " ;
           if (!is_dir($dir)) create_dir($dir) ; else echo 'OK<br>'  ;

  	  } //else echo 'Каталог '.$dir.' не существует<br>' ;
  	  echo '<br>' ;
  	}
   }

    // проверить наличие каталога изображений для объектной таблицы
   function check_obj_table_image_dir($tkey)
   {  global $install_options ;
      if (_sizeof($install_options) and !$install_options['check_dir_files']) return ;

      // проверяем, существует ли каталог для хранения изображений
      // если нет, то создаем
      $show_img_pars=0 ;
      $cur_table=_DOT($tkey) ;
      if (_sizeof($cur_table->list_clss)) foreach($cur_table->list_clss as $clss=>$clss_tkey)
        if (is_object(_CLSS($clss)) and _CLSS($clss)->has_parent_clss(3) and $cur_table->list_clss[$clss]==$tkey) $show_img_pars=1 ;

      if (_DOT($tkey)->dir_to_file and $show_img_pars)
      { echo "<strong>Проверка существования каталога изображений для '"._DOT($tkey)->table_name."'</strong><br>" ;
        $dir=_DOT($tkey)->dir_to_file ;
        $this->check_exists_dir(hide_server_dir($dir.'small/')) ;
        $this->check_exists_dir(hide_server_dir($dir.'source/')) ;
  	    if (_sizeof(_DOT($tkey)->list_clone_img())) foreach( _DOT($tkey)->list_clone_img() as $dir_clone=>$info) $this->check_exists_dir(hide_server_dir($dir.$dir_clone.'/')) ;
  	  }
   }

function check_exists_dir($dir)
{   global $install_options ;
    if (_sizeof($install_options) and !$install_options['check_dir_files']) return ;

    if (!file_exists(_DIR_TO_ROOT.$dir))
     {   $arr=explode('/',$dir) ;
         unset($arr[_sizeof($arr)-1]) ;
         $parent_dir=implode('/',$arr) ;
	     if ($parent_dir) $this->check_exists_dir($parent_dir)  ;
     	 echo 'Будет создана директория <strong>'.$dir.'</strong>' ;
         if (@mkdir(_DIR_TO_ROOT.$dir)) echo ' - <span class="green">OK</span>' ;
         else                          echo ' - <span class="red">ERROR</span>' ;
     }
    else
    { echo 'Директория <strong>'.$dir.'</strong> - <span class="green">OK</span>' ;
    }
    $check_fname='test_'.ENGINE()->generate_UID().'.txt' ;
    $cnt=file_put_contents(_DIR_TO_ROOT.$dir.'/'.$check_fname,'test write') ;
    $write_status=($cnt)? 'ok':'error' ;
    if ($write_status=='ok')
    { $cont=file_get_contents((_DIR_TO_ROOT.$dir.'/'.$check_fname)) ;
      $read_status=(strlen($cont))? 'ok':'error' ;
    }
    unlink(_DIR_TO_ROOT.$dir.'/'.$check_fname) ;

    if ($write_status=='ok') echo ' '.(($read_status=='ok')? '<span class="green">READ</span>':'<span class="red">READ ERROR</span>').' /' ;
    echo ($write_status=='ok')? ' <span class="green">WRITE</span>':'<span class="red">WRITE ERROR</span>' ;
    echo '<br>' ;
}

function check_attr_X($file)
 {  global $install_options ;
    if (_sizeof($install_options) and !$install_options['check_dir_files']) return ;
    echo 'Права доступа <strong>'.$file.'</strong>' ;
    $result=chmod(_DIR_TO_ROOT.$file,0755) ;
    if ($result) echo ' - <span class="green">OK</span>' ;
    else         echo ' - <span class="red">ERROR</span>' ;
    echo '<br>' ;
 }

 function check_AddOns_dir($dir)
 {   global $install_options ;
     if (_sizeof($install_options) and !$install_options['check_dir_files']) return(0) ;

     if (!file_exists(_DIR_TO_ADDONS.'/'.$dir))
     {   echo 'Отсутствует AddOns <strong>'.$dir.'</strong><br>' ;
         return(1) ;
     } else return(0) ;
 }

function remove_old_script($dir)
  {  global $install_options ;
     if (_sizeof($install_options) and !$install_options['check_dir_files']) return ;

     if (file_exists(_DIR_TO_ROOT.$dir))
     { $res=unlink(_DIR_TO_ROOT.$dir) ;
       if (!$res) echo '<div class=red>Не удалось удалить файл '.$dir.'</div>' ;
       echo 'Удален неиспользуемый файл <strong>'.$dir.'</strong><br>' ;
     }
  }

  // добавлен разбор сообщений об ошибках типа "/class/engine_moduls/engine/i_setup.php(851):rmdir(/setup/): Directory not empty" и вывод их в читаемом виде
  function remove_old_dir($dir)
  {   global $install_options ;
      if (_sizeof($install_options) and !$install_options['check_dir_files']) return ;
      ob_start() ;
      $result='' ;
      if ($dir and $dir!='/')
      {  $dir_full=_DIR_TO_ROOT.$dir ;

     if (file_exists($dir_full))
     { $list=get_all_files($dir_full,array('include_dir'=>1));
       rsort($list) ;
       //echo 'Содержимое директории '.$dir_full.'<br>' ; damp_array($list,1,-1);
       echo 'Удаляем содержимое директрии <strong>'.$dir.'</strong><br>' ;
       $cnt_file=0 ; $cnt_remove_file=0 ; $cnt_dir=0 ; $cnt_remove_dir=0 ;
       if (_sizeof($list)) foreach($list as $i=>$fname) if (is_file($fname))
       {  $result_remove=$this->remove_dir_or_file($fname) ;
          if ($result_remove['success'])  { unset($list[$i]) ; $cnt_remove_file++ ; }
          else echo $result_remove['error'].'<br>' ;
       }
       if ($cnt_file) echo 'Удалено <strong>'.$cnt_remove_file.'</strong> из <strong>'.$cnt_file.'</strong> файлов<br>' ;
       if (_sizeof($list)) foreach($list as $i=>$fname) if (is_dir($fname))
       {  $result_remove=$this->remove_dir_or_file($fname) ;
          if ($result_remove['success'])  { unset($list[$i]) ; $cnt_remove_dir++ ; }
          else echo $result_remove['error'].'<br>' ;
          $cnt_dir++ ;
       }
       if ($cnt_dir) echo 'Удалено <strong>'.$cnt_remove_dir.'</strong> из <strong>'.$cnt_dir.'</strong> поддиректорий<br>' ;

       $result_remove=$this->remove_dir_or_file($dir_full) ;
       if ($result_remove['success']) { echo 'Удалена директория <strong>'.$dir.'</strong><br>' ; $result='OK' ; }
       else  { echo $result_remove['error'].'<br>' ; $result='ERROR' ; }
     }
      } else $result=' - заблокировано' ;
     $text=ob_get_clean() ;
     LOGS()->reg_log('Дисковые операции','Удаление директории '.$dir.' - '.$result,array('save_to_file'=>$text)) ;
     echo $text ;
  }

  function remove_dir_or_file($fname)
  {
      $result=[] ;
      ob_start() ;
      if (is_file($fname) and unlink($fname))  $result['success']=1 ;
      if (is_dir($fname) and rmdir($fname))  $result['success']=1 ;
      $text=ob_get_clean() ;
      if (!$result['success'])
      {   $result=explode(':',$text) ;
          $result['error']=hide_server_dir($fname).' : <span class=red>'.$result[2].'</span>' ;
      }
      return($result) ;
  }

  function alert_old_dir($dir)
  {  global $install_options ;
     if (_sizeof($install_options) and !$install_options['check_dir_files']) return ;

     if (is_dir(_DIR_TO_ROOT.$dir))
     { echo '<span class="red">Удалите неиспользуемую директорию хоста <strong>'.$dir.'</strong></span><br>' ;
     }
  }

    function recurse_copy($src,$dst) {
         $dir = opendir($src); $result=[] ; $cnt_errors=0 ;
         ob_start() ;
         if (!file_exists($dst)) mkdir($dst);
         $text=ob_get_clean() ;
         if ($text)
         {   $arr=explode(':',$text) ;
             echo '<div class=gray>Не удалось создать директорию '.hide_server_dir($dst).' - <span class="red">'.$arr[2].'</span></div>' ;
             $cnt_errors++ ;
         }
         else while(false !== ( $file = readdir($dir)) ) {
             if (( $file != '.' ) && ( $file != '..' )) {
                 if ( is_dir($src . '/' . $file) ) {
                     $cnt_errors+=$this->recurse_copy($src . '/' . $file,$dst . '/' . $file);
                 }
                 else {
                     ob_start() ;
                         copy($src . '/' . $file,$dst . '/' . $file);
                     $text=ob_get_clean() ;
                     if ($text)
                         {
                             $arr=explode(':',$text) ;
                             //damp_array($arr,1,-1);
                             echo '<div class=gray>'.hide_server_dir($dst.'/'.$file).' -  <span class="red">'.$arr[3].'</span></div>' ;
                             $cnt_errors++ ;


                         }
                 }
             }
         }
         closedir($dir);
         return($cnt_errors);
     }

// создаем скрипты пунктов меню
function create_menu_item($file_items)
{ global $install_options ;
  if (_sizeof($install_options) and !$install_options['script_to_admin']) return ;
  create_script_file($file_items,_DIR_TO_ROOT.'/'._ADMIN_.'/','../ini/patch.php') ;
}


// создаем скрипты пунктов меню
function create_script_to_page($file_items,$dir_to='',$patch_dir='')
{ global $install_options ;
  // для выполения необходимо или вообще не задавать опции $install_options или задать опцию $install_options['install_copy_script']
  if (_sizeof($install_options) and !$install_options['install_copy_script']) return ;
  echo '<div class="green bold">Создаем входные скрипты модуля</div>' ;
  create_script_file($file_items,$dir_to,$patch_dir) ;
}

    function create_list_viewers()
    {   global $install_options ;
        if (_sizeof($install_options) and !$install_options['viewers']) return ;

        $recs_index_list=execSQL('select * from obj_site_list where clss=21 and enabled=1') ;
        if (_sizeof($recs_index_list)) foreach($recs_index_list as $rec) $this->create_list_viewer($rec['pkey'],get_IL_array_name($rec),$rec['obj_name']) ;
    }

    function create_list_viewer($list_id,$list_code,$list_name)
    {   $viewer_name='view_'.$list_code ;
    	$sql='select  t1.id as _id,t1.*
                     from obj_site_list t1 
                     where t1.parent='.$list_id.' 
                     order by t1.id,t1.pkey
                     ' ;
        $this->create_viewer($viewer_name,$sql) ;
        echo 'viewer <strong>'.$viewer_name.'</strong>:  to list '.$list_name.' - <span class="green">OK</span><br>' ;
    }


    // Добавление нового раздела в списказ
    function SETUP_add_section_to_site_list($sect_name,$options=array())
    { global $install_options ;
      if (_sizeof($install_options) and !$install_options['declare_list']) return(0) ;

      if (!_sizeof($GLOBALS['site_section_list_name_id'])) $GLOBALS['site_section_list_name_id']=execSQL_row('select pkey,obj_name from '.TM_LIST.' where clss=1') ;
      if (!in_array($sect_name,$GLOBALS['site_section_list_name_id']))
      { if (!$options['hidden']) $options['hidden']=0 ;
      $id=adding_rec_to_table(TM_LIST,array('parent'=>1,'clss'=>1,'obj_name'=>$sect_name,'hidden'=>$options['hidden'])) ;
      if ($id) echo '<div class="green">Добавлен раздел <strong>'.$sect_name.'</strong></div>' ; else echo 'Не удалось добавить раздел <strong>'.$sect_name.'</strong><br>' ;
      }  else $id=$GLOBALS['site_section_list_name_id'][$sect_name] ;
      return($id) ;
    }

    // Добавление нового списка в раздел
    function SETUP_add_list_to_site_list($sect_id,$name,$arr_name,$options=array())
    { global $install_options ;   // echo '11' ;
      if (_sizeof($install_options) and !$install_options['declare_list']) return(0) ;

      if (ESMO_STATUS=='SETUP_FIRST') $GLOBALS['site_list_name_id']=array() ; // при первой установке не проверяем существование записи по crontab в БД
      else if (!_sizeof($GLOBALS['site_list_name_id'])) $GLOBALS['site_list_name_id']=execSQL_row('select pkey,arr_name from '.TM_LIST.' where clss=21') ;
      if (!in_array($arr_name,$GLOBALS['site_list_name_id']))
      {
          $id=adding_rec_to_table(TM_LIST,array('parent'=>$sect_id,'clss'=>21,'obj_name'=>$name,'arr_name'=>$arr_name,'indx'=>1)) ;
          echo 'Список: <strong>'.$name.'</strong>' ;
          if ($id)  echo ' - <span class="green">CREATE</span>' ; else echo ' - <span class="red">ERROR</span>' ;
          echo '<br>' ;
          if ($id) $this->create_list_viewer($id,'IL_'.$arr_name,$name) ;
      }
      else
      {
          echo 'Список <strong>'.$name.'</strong> - <span class="green">OK</span><br>' ;
          //$id=array_search($arr_name,$GLOBALS['site_list_name_id']) ;
          $id=0 ; // возвращаем 0 если список уже создан

      }
      return($id) ;
    }

    // Добавление записи в список
    function SETUP_add_rec_to_site_list($list_id,$clss,$rec=array(),$options=array())
    { global $install_options ;
      if (_sizeof($install_options) and !$install_options['declare_list']) return(0) ;
      // для значений, которые можно добавлять только SETUP_FIRST
      if (isset($options['setup_mode']) and $options['setup_mode']!=ESMO_STATUS) return(0) ;
      if (!$list_id)
      {   echo '<div class="yellow">Отклонено добавление записи <strong>"'.$rec['obj_name'].'"</strong> - список уже сформирован</div>' ;
          return(0) ; // если список уже был создан раннее - не делаем проверку существования в нем записей
      }

      // в режиме инсталятора на чистую базу нет необходимости проверять наличие записей в базе
      if (ESMO_STATUS=='SETUP_FIRST') $id=0 ;
      else  $id=execSQL_value('select pkey from '.TM_LIST.' where parent="'.$list_id.'" and id="'.$rec['id'].'"') ; // проверяем запись в списке по parent и id

      if ($id)
      {
          echo '<div class="light_gray">Запись <strong>'.$rec['obj_name'].'</strong> - <span class="green">OK</span></div>' ;
      }
      else
      {   $rec['parent']=$list_id ;
          $rec['clss']=$clss ;

          if (ESMO_STATUS=='SETUP_FIRST') multiSQL_insert(TM_LIST)->append($rec) ;
          else adding_rec_to_table(TM_LIST,$rec,array('no_return_id'=>1)) ;
          echo 'Список: запись <strong>'.$rec['obj_name'].'</strong>' ;
          //if ($id)
          echo ' - <span class="green">CREATE</span>' ;
          //else echo ' - <span class="red">ERROR</span>' ;
          echo '<br>' ;
      }
      return($id) ;
    }


    function import_setting_from_xml($file_name='',$options=array())
    { global $install_options ;
      if (_sizeof($install_options) and !$install_options['install_setting_from_XML']) return ;

      $source=file_get_contents($file_name) ;
      $dom = new DomDocument();
      if ($dom->loadXML($source))
      { list($all_count,$sum_count)=import_OBJ_from_XML($dom,$options) ;
        echo '<strong>Импортировано '.$all_count.' из '.$sum_count.' объектов.</strong><br>' ;
      }
      else echo 'Неверный формат XML' ;
    }

    function mark_crontab_for_remove()
    { execSQL_update('update obj_site_crontab set temp=1') ;
    }

    function delete_marked_crontab()
    {  if (_sizeof($this->arr_cron_ids)) execSQL_update('update obj_site_crontab set temp=0 where pkey in ('.implode(',',$this->arr_cron_ids).')') ;
       $recs=execSQL('select pkey,obj_name from obj_site_crontab where temp=1') ;
       if (_sizeof($recs))
       {  echo 'Будет отменена регистрация отсутствующих заданий планировщика:' ;
          print_2x_arr($recs) ;
          execSQL_update('delete from obj_site_crontab where temp=1') ;
       }
    }

    var $recs_cron=array() ;
    var $arr_cron_ids=array() ;
    function reg_cron($name,$cmd,$intr,$options=array())
      {  global $install_options ;
         if (_sizeof($install_options) and !$install_options['cron']) return ;

         if (ESMO_STATUS=='SETUP_FIRST') $this->recs_cron=array() ; // при первой установке не проверяем существование записи по crontab в БД
         elseif (!_sizeof($this->recs_cron)) $this->recs_cron=execSQL('select * from obj_site_crontab',array('use_fname_indx'=>'cmd')) ;
         $rec_cron=isset($this->recs_cron[$cmd])? $this->recs_cron[$cmd]:array();
         if (!$rec_cron['pkey'])
         {  $enabled=($options['enabled'])? 1:0 ;
            $rec_cron=array('cmd'=>$cmd,'obj_name'=>$name,'intr'=>$intr,'clss'=>276,'parent'=>1,'enabled'=>$enabled,'temp'=>0) ;
            if (ESMO_STATUS=='SETUP_FIRST')  multiSQL_insert('obj_site_crontab')->append($rec_cron) ;
            else  adding_rec_to_table('obj_site_crontab',$rec_cron,array('debug'=>0)) ;
            echo 'Зарегистрирован крон <strong>'.$name.'</strong><br>' ;
            if (!$options['no_log'] and ESMO_STATUS!='SETUP_FIRST') LOGS()->reg_log('CRONTAB','Добавлено задание планировщика "'.$name.'" ['.$cmd.'], время запуска: '.$intr) ;
         }
         else
         {  echo 'Крон <strong>'.$name.'</strong>' ;
            $arr_changes=array() ;
            if ($name!=$rec_cron['obj_name']) $arr_changes['Наименование']=$rec_cron['obj_name'].' => '.$name ;
            //проверяем что время запуска не было изменено вручную
            if ($intr!=$rec_cron['intr'] and !$rec_cron['default_intr']) $arr_changes['Время запуска']=$rec_cron['intr'].' => '.$intr ;
            //$options['enabled']=(int)$options['enabled'] ;
            //if ($options['enabled']!=$rec_cron['enabled']) $arr_changes['Активен']=$rec_cron['enabled'].' => '.$options['enabled'] ;
            //damp_array($result,1,-1) ;
            //damp_array($_SESSION['descr_obj_tables'],1,-1) ;

            if (_sizeof($arr_changes))
            {  $result=update_rec_in_table('obj_site_crontab',array('obj_name'=>$name,'intr'=>$intr,'temp'=>0),'pkey='.$rec_cron['pkey'],array('debug'=>0)) ;
               if ($result['error']) echo '<div class="alert">'.$result['error'].'</div>' ;

               LOGS()->reg_log('CRONTAB','Изменено задание планировщика "'.$rec_cron['obj_name'].' ['.$rec_cron['cmd'].']"',array('data'=>$arr_changes)) ;
               echo ' - <span class="green">UPDATE</span> ['.print_r($arr_changes,true).']<br>' ;
            }
            else
            { echo ' - <span class="green">OK</span><br>' ;
              $this->arr_cron_ids[]=$rec_cron['pkey'] ;
            }
         }
      }

    function change_cron_status($cron_cmd,$status)
       {  $rec_cron=execSQL_van('select * from obj_site_crontab where cmd="'.$cron_cmd.'"') ;
          if ($rec_cron['enabled']!=$status)
          { update_rec_in_table('obj_site_crontab',array('enabled'=>$status,'status'=>0),'pkey='.$rec_cron['pkey']) ;
            LOGS()->reg_log('Изменение состояния задания крона',$rec_cron['obj_name'].': '.(($status)? 'ВКЛЮЧЕНО':'ВЫКЛЮЧЕНО')) ;
          }
       }

    function clear_event_lister()
    { execSQL_update('delete from event_lister',array('debug'=>0)) ;
    }

   function reg_event_lister($event_name,$system,$method_name)
   { global $install_options ;
     if (_sizeof($install_options) and !$install_options['event_lister']) return;
     echo 'Обработчик события: <strong>'.$system.'/'.$event_name.'</strong>' ;
     //$event_id=execSQL_value('select * from event_lister where system_name="'.$system.'" and obj_name="'.$event_name.'"') ;
     //if ($event_id) echo ' - <span class="green">OK</span>' ;
     //else
     { $rec_event=array('clss'=>219,'obj_name'=>$event_name,'system_name'=>$system,'method_name'=>$method_name) ;
       multiSQL_insert('event_lister')->append($rec_event) ;
       //adding_rec_to_table('event_lister',$rec_event,array('debug'=>0,'no_auto_indx'=>1,'no_return_id'=>1)) ;
       echo ' - <span class="green">REGISTER</span>' ;
     }
     echo '<br>' ;
   }

  function clear_event_types()
    { execSQL_update('delete from events_types',array('debug'=>0)) ;
    }

   function reg_event_type($event_name,$system,$ext)
   { global $install_options ;
     if (_sizeof($install_options) and !$install_options['event_type']) return;
     echo 'Тип мероприятия: <strong>'.$event_name.': '.$ext.'</strong>' ;
     { $rec_event=array('clss'=>213,'obj_name'=>$event_name,'system_name'=>$system,'ext'=>$ext) ;
       multiSQL_insert('events_types')->append($rec_event) ;
       echo ' - <span class="green">REGISTER</span>' ;
     }
     echo '<br>' ;
   }

    function mark_reports_for_remove()
    { execSQL_update('update reports set temp=1') ;
    }

    function delete_marked_reports()
    { if (_sizeof($this->arr_reports_ids)) execSQL_update('update reports set temp=0 where pkey in ('.implode(',',$this->arr_reports_ids).')') ;
      $recs=execSQL('select pkey,obj_name,script from reports where temp=1 and virt=0') ;
      if (_sizeof($recs))
        {  echo 'Будет отменена регистрация отсутствующих отчетов и документов:' ;
           print_2x_arr($recs) ;
           execSQL_update('delete from reports where temp=1 and virt=0') ;
        }

    }

    function mark_setting_for_remove()
    { execSQL_update('update obj_site_setting set temp=1') ;
    }

    function delete_marked_setting()
     { if ($GLOBALS['add_rec_to_site_setting_is_block']) { echo 'Во время проверки настроек была ошибка, работа с настройками отклонена<br>' ; return ; } // ничего не делаем, если работа с настройками была заблокирована из-за ошибки
       if (_sizeof($this->arr_settings_ids)) execSQL_update('update obj_site_setting set temp=0 where pkey in ('.implode(',',$this->arr_settings_ids).')') ;

       $recs=execSQL('select pkey,obj_name,comment from obj_site_setting where temp=1 and enabled=1 and parent>0 and hidden=0 order by parent') ;
       if (_sizeof($recs))
         {  echo 'Будут отключены отсутствующие настройки:' ;
            print_2x_arr($recs) ;
            execSQL_update('update obj_site_setting set enabled=0 where temp=1 and parent>0 and hidden=0') ;
         }
       $recs=execSQL('select pkey,obj_name,comment from obj_site_setting where temp=0 and enabled=0 and parent>0 order by parent') ;
       if (_sizeof($recs))
         {  echo 'Будут включены следующие настройки:' ;
            print_2x_arr($recs) ;
            execSQL_update('update obj_site_setting set enabled=1 where temp=0 and parent>0') ;
         }
       $recs=execSQL('select pkey,obj_name,comment from obj_site_setting where temp=0 and enabled=0 and parent>0 and hidden=0 order by parent') ;
       if (_sizeof($recs))
       {  echo 'Будут включены следующие скрытые настройки настройки:' ;
          print_2x_arr($recs) ;
          execSQL_update('update obj_site_setting set enabled=1 where temp=0 and parent>0 and hidden=0 ') ;
       }
     }


    // type=1 - отчет
    // type=2 - документ
    var $arr_reports=null ;
    var $arr_reports_ids ;

    function reg_report($group_name,$script,$type=1,$options=array())
    { global $install_options ;
      if (_sizeof($install_options) and !$install_options['reports']) return;     // при вызове из инсталяционной части

      if (ESMO_STATUS=='SETUP_FIRST') $this->arr_reports=array() ;
      else if ($this->arr_reports==null) $this->arr_reports=execSQL('select script,class_name,code,type,pkey,group_name,obj_name,indx from reports order by indx') ;

      //if (!$install_options['reports']) return;    // при вызове из конструктора класса
      $type_name=($type==1)? 'Отчет':'Документ' ;
      $fdir=_DIR_EXT.'/'.$script ;
      if (!file_exists($fdir)) { $fdir=_DIR_EXT_LOCAL.'/'.$script ;
                                 if (!file_exists($fdir))
                                 { echo $type_name.': <strong>'.$script.'</strong> - <span class="red">Не найден скрипт '.$type_name.'а</span>, проверьте корректность регистрации<br>' ;
                                   return ;
                                 }
                               }
      include_once($fdir) ;
      $arr=explode('/',$script) ;
      $arr2=explode('.',$arr[1]) ;
      $class_name=$arr2[0] ;
      //if ($options['debug']) echo 'Используем наименование класса <strong>'.$class_name.'</strong><br>' ;
      if (!class_exists($class_name)) { echo $type_name.': <strong>'.$script.'</strong> - <span class="red">Не найден класса '.$type_name.'а ".$class_name."</span><br>' ; return ;}
      $report_obj=new $class_name() ;
      $title=$report_obj->title ;
      // код отчета - оставлен временном для обратной совместимости
      // для отчетов код отчета = имя класса
      // для документов = имя класса без "doc_"
      //$code=($report_obj->doc_code!="")? $report_obj->doc_code:str_replace('doc_','',$class_name) ;
      // добавлено корректное задание $report_obj->doc_code в i_report
      $code=$report_obj->doc_code;
////        if ($options['debug']) damp_array($report_obj,1,-1);
////      if ($options['debug']) echo 'Класс документа [report_class]: <strong>'.$report_obj->report_class.'</strong><br>' ;
////      if ($options['debug']) echo 'Скрипт документа [report_script]: <strong>'.$report_obj->report_script.'</strong><br>' ;
////      if ($options['debug']) echo 'Публичный код документа [doc_code]: <strong>'.$report_obj->doc_code.'</strong><br>' ;
////      if ($options['debug']) echo 'Публичный код документа: <strong>'.$code.'</strong><br>' ;

      $this->report_indx++ ;
      $rec_report=$this->arr_reports[$script] ; //execSQL_van('select * from reports where script="'.$script.'"') ;
        if (!$rec_report['pkey'])
        {  $rec=array('indx'=>$this->report_indx,
                      'script'=>$script,
                      'obj_name'=>$title,
                      'group_name'=>$group_name,
                      'class_name'=>$class_name,
                      'code'=>$code,
                      'type'=>$type,
                      'clss'=>255,
                      'parent'=>1,
                      'enabled'=>1,
                      'temp'=>0
                  ) ;
        //damp_array($rec,1,-1);
           if (ESMO_STATUS=='SETUP_FIRST') multiSQL_insert('reports')->append($rec) ;
           else adding_rec_to_table('reports',$rec,array('debug'=>0,'no_return_id'=>1)) ;
           echo 'Зарегистрирован '.$type_name.' <strong>'.$title.'</strong> ['.$code.']<br>' ;
        }
        else
        {  echo $type_name.' <strong>'.$title.'</strong>' ;
           $arr_changes=array() ;
           if ($group_name!=$rec_report['group_name']) $arr_changes['Раздел']=$rec_report['group_name'].' => '.$group_name ;
           if ($title!=$rec_report['obj_name'])        $arr_changes['Наименование']=$rec_report['obj_name'].' => '.$title ;
           if ($code!=$rec_report['code'])        $arr_changes['Код документа']=$rec_report['code'].' => '.$code ;
           if ($class_name!=$rec_report['class_name']) $arr_changes['Класс документа']=$rec_report['class_name'].' => '.$class_name ;
           if ($this->report_indx!=$rec_report['indx']) $arr_changes['Позиция документа']=$rec_report['indx'].' => '.$this->report_indx ;
           //if ($intr!=$rec_cron['intr']) $arr_changes['Время запуска']=$rec_cron['intr'].' => '.$intr ;
           //$options['enabled']=(int)$options['enabled'] ;
           //if ($options['enabled']!=$rec_cron['enabled']) $arr_changes['Активен']=$rec_cron['enabled'].' => '.$options['enabled'] ;

           if (_sizeof($arr_changes))
           {  update_rec_in_table('reports',array('group_name'=>$group_name,'obj_name'=>$title,'code'=>$code,'class_name'=>$class_name,'indx'=>$this->report_indx,'temp'=>0),'pkey='.$rec_report['pkey'],array('debug'=>0)) ;
              //LOGS()->reg_log('CRONTAB','Изменено задание планировщика "'.$rec_cron['obj_name'].' ['.$rec_cron['cmd'].']"',array('data'=>$arr_changes)) ;
              echo ' - <span class="green">UPDATE</span><br>' ;
              print_r($arr_changes) ; echo '<br>' ;
           }
           else
           { echo ' - <span class="green">OK</span><br>' ;
             $this->arr_reports_ids[]=$rec_report['pkey'] ;
           }
        }
    }



    function save_ini_setting($fname,$setting=array())
       {   include_once('Spyc.php');
           $yaml = Spyc::YAMLDump($setting,4,60);
           $success=file_put_contents(_DIR_TO_ROOT.$fname,$yaml) ;
           if (!$success)
           { ?><div style="color:red;">Не удалось сохранить изменения в "<?echo $fname?>". Проверьте права доступа файлов хоста, они должны принадлежать esmo или apache</div><?
             exit ;
           }
       }

    function load_ini_setting($fname,$setting=array())
       {   include_once('Spyc.php');
           $arr=(file_exists(_DIR_TO_ROOT.$fname))? Spyc::YAMLLoad(_DIR_TO_ROOT.$fname):array();
           return($arr) ;
       }

    function get_default_patch_file()
    {  $content='<?php'."\n" ;
       $content.='include($_SERVER[\'DOCUMENT_ROOT\'].\'/ini/spyc.php\');'."\n" ;
       $content.='$_SETTING = Spyc::YAMLLoad($_SERVER[\'DOCUMENT_ROOT\'].\'/ini/ini.yaml\');'."\n" ;
       $content.='include($_SERVER[\'DOCUMENT_ROOT\'].\'/\'.$_SETTING[\'dist\'][\'engine_version\'].\'/i_base.php\')'."\n" ;
       $content.='?>' ;
       return($content) ;
    }

    function remove_old_ini_section($section,$params='')
    {   global $install_options ;
        if (_sizeof($install_options) and !$install_options['old_ini_section']) return;     // при вызове из инсталяционной части

        include_once('Spyc.php');
        $setting = Spyc::YAMLLoad(_DIR_TO_ROOT.'/ini/ini.yaml');
        if (!$params)
        {   if (isset($setting[$section])) { unset($setting[$section]) ; $result='REMOVE' ; }
            else $result='NOT FOUND' ;
        }
        else
        { if (isset($setting[$section][$params])) { unset($setting[$section][$params]) ;  $result='REMOVE' ; }
          else $result='NOT FOUND' ;
        }
        echo 'Неподдерживаемый параметр файла конфигурации: <strong>'.$section.'/'.$params.'</strong> - <span class="green">'.$result.'</span><br>'  ;
        $this->save_ini_setting('/ini/ini.yaml',$setting) ;
    }

    function append_ini_value($section,$params,$value,$options=array())
    {   global $install_options ;
        if (_sizeof($install_options) and !$install_options['ini_value'] and !$options['no_check_setup_level']) return;     // при вызове из инсталяционной части

        include_once('Spyc.php');
        $setting = Spyc::YAMLLoad(_DIR_TO_ROOT.'/ini/ini.yaml');
        if (!isset($setting[$section][$params])) {$setting[$section][$params]=$value ;  $result='CREATE' ; }
        else $result='EXIST' ;

        echo 'Параметр файла конфигурации: <strong>'.$section.'/'.$params.'</strong>='.$value.' <span class="green">'.$result.'</span><br>'  ;
        $this->save_ini_setting('/ini/ini.yaml',$setting) ;
    }

    function update_ini_value($section,$params,$value='',$options=array())
    {   global $install_options ;
        if (_sizeof($install_options) and !$install_options['ini_value'] and !$options['no_check_setup_level']) return;     // при вызове из инсталяционной части

        include_once('Spyc.php');
        $setting = Spyc::YAMLLoad(_DIR_TO_ROOT.'/ini/ini.yaml');
        if (!$value)
        {   if (isset($setting[$section][$params])) { unset($setting[$section][$params]) ; $result='REMOVE' ; }
            else $result='NOT FOUND' ;
        }
        else
        { if (isset($setting[$section][$params])) {$setting[$section][$params]=$value ;  $result='UPDATE' ; }
          else $result='NOT FOUND' ;
        }
        echo 'Параметр файла конфигурации: <strong>'.$section.'/'.$params.'</strong>='.$value.' <span class="green">'.$result.'</span><br>'  ;
        $this->save_ini_setting('/ini/ini.yaml',$setting) ;
    }

    function append_key_value($section,$value)
    {   global $install_options ;
        if (_sizeof($install_options) and !$install_options['ini_value']) return;     // при вызове из инсталяционной части

        include_once('Spyc.php');
        $setting = (file_exists(_DIR_TO_ROOT.'/cab/ic13267832.yaml'))? Spyc::YAMLLoad(_DIR_TO_ROOT.'/cab/ic13267832.yaml'):array();
        if (!isset($setting[$section])) {$setting[$section]=$value ;  $result='CREATE' ; }
        else $result='EXIST' ;

        echo 'Параметр файла ключей: <strong>'.$section.'</strong>: <span class="green">'.$result.'</span><br>'  ;
        $this->save_ini_setting('/cab/ic13267832.yaml',$setting) ;
    }

    function update_key_value($section,$value='')
    {   global $install_options ;
        if (_sizeof($install_options) and !$install_options['ini_value']) return;     // при вызове из инсталяционной части

        include_once('Spyc.php');
        $setting = Spyc::YAMLLoad(_DIR_TO_ROOT.'/cab/ic13267832.yaml');
        if (!$value)
        {   if (isset($setting[$section])) { unset($setting[$section]) ; $result='REMOVE' ; }
            else $result='NOT FOUND' ;
        }
        else
        { if (isset($setting[$section])) {$setting[$section]=$value ;  $result='UPDATE' ; }
          else $result='NOT FOUND' ;
        }
        echo 'Параметр файла ключей: <strong>'.$section.'</strong>='.$value.' <span class="green">'.$result.'</span><br>'  ;
        $this->save_ini_setting('/cab/ic13267832.yaml',$setting) ;
    }

    function move_crypt_key_to_one_file($ini2_fname,$crypt_key_name,$value)
    { // сохраняем текущий  crypt_key в ini2.yaml
      $setting[$crypt_key_name]=$value ;
      $yaml = Spyc::YAMLDump($setting,4,60);
      $success=file_put_contents($ini2_fname,$yaml) ;
      if ($success)
         { //echo 'ключ сохранен в ini2<br>' ;
           include_once(_DIR_TO_MODULES.'/engine/i_setup.php');
           if ($GLOBALS['_SETTING']['main_db']['crypt_key']) SETUP()->remove_old_ini_section('main_db','crypt_key') ;
           if ($GLOBALS['_SETTING']['ActiveDirectory']['app_key']) SETUP()->remove_old_ini_section('ActiveDirectory','app_key') ;
         }
    }

    //==============================================================================================================================================================================================
    //
    // работта с ролями
    //
    //==============================================================================================================================================================================================

    function import_local_roles()
    {   if (!_sizeof($_SESSION['index_list_names']) or !array_search('IL_roll',$_SESSION['index_list_names'])) return ; // если новая инсталяция и списка локальных ролей нет - просто выходим

        $list_id=0 ;
        if (_sizeof(_IL('IL_roll')->recs))
        {  echo '<strong>Импорт локальных ролей</strong><br>' ;
           foreach(_IL('IL_roll')->recs as $rec_rol)
            {   $ext_info=unserialize($rec_rol['ext_info']) ;
                $data=array('clss'=>94,
                            'obj_name'=>$rec_rol['obj_name'],
                            'id'=>$rec_rol['id']+100,
                            'index_page'=>$ext_info['index_page'],
                            'use_auch_as_smena'=>($ext_info['use_auch_as_smena'])? 1:0,
                            'smena_monopole_mode'=>($ext_info['smena_monopole_mode'])? 1:0,
                            'report_template'=>$ext_info['report_template'],
                           ) ;
                adding_rec_to_table('roles',$data) ;
                echo 'Добавлена локальная роль <strong>'.$data['obj_name'].'</strong> ['.$data['id'].']<br>' ;
                $list_id=$rec_rol['parent'] ;
            }
        }
        // очистить локальный список ролей
        if ($list_id) execSQL_update('delete from obj_site_list where parent='.$list_id) ;
    }

    function mark_roles_for_remove()
       { execSQL_update('update roles set temp=1 where id<100') ;
       }

   function delete_marked_roles()
   {  if (_sizeof($this->arr_roles_ids)) execSQL_update('update roles set temp=0 where pkey in ('.implode(',',$this->arr_roles_ids).')') ;
      $recs=execSQL('select pkey,obj_name from roles where temp=1 and id<100') ;
      if (_sizeof($recs))
      {  echo 'Будет отменена регистрация отсутствующих ролей системы:' ;
         print_2x_arr($recs) ;
         execSQL_update('delete from roles where temp=1 and id<100') ;
      }
   }

       var $recs_roles ;
       var $arr_roles_ids ;
       function reg_rol($id,$name,$index_page='',$options=array())
         {  global $install_options ;
            if (_sizeof($install_options) and !$install_options['roles']) return ;
            //if ($id==1) execSQL_update('delete from roles',2) ;

            if (ESMO_STATUS=='SETUP_FIRST') $this->recs_roles=array() ; // при первой установке не проверяем существование записи по roles в БД
            elseif (!_sizeof($this->recs_roles)) $this->recs_roles=execSQL('select * from roles',array('use_fname_indx'=>'id')) ;
            $rec_rol=isset($this->recs_roles[$id])? $this->recs_roles[$id]:array();
            if (!$rec_rol['pkey'])
            {  $rec_rol=array('id'=>$id,'c_data'=>time(),'r_data'=>time(),'obj_name'=>$name,'index_page'=>$index_page,'clss'=>94,'parent'=>1,'enabled'=>1,'temp'=>0) ;
               $rec_rol['use_auch_as_smena']=($options['use_auch_as_smena'])? 1:0;
               $rec_rol['smena_monopole_mode']=($options['smena_monopole_mode'])? 1:0;
               $rec_rol['autologout']=(is_numeric($options['autologout']))? $options['autologout']:0;
               $rec_rol['report_template']=($options['report_template'])? $options['report_template']:'';
               $rec_rol['working']=($options['working'])? $options['working']:'';
               if (ESMO_STATUS=='SETUP_FIRST')  multiSQL_insert('roles')->append($rec_rol) ;
               else  adding_rec_to_table('roles',$rec_rol,array('debug'=>0)) ;
               echo 'Зарегистрирована роль <strong>'.$name.'</strong><br>' ;
               if (!$options['no_log'] and ESMO_STATUS!='SETUP_FIRST') LOGS()->reg_log('ROLES','Зарегистрирована роль "'.$name.'" ['.$id.']') ;
            }
            else
            {  echo 'Роль <strong>'.$name.'</strong>' ;
               $arr_changes=array() ;
               if ($options['allow_update_name'] and $name!=$rec_rol['obj_name']) $arr_changes['Наименование']=$rec_rol['obj_name'].' => '.$name ;
               if ($index_page!=$rec_rol['index_page']) $arr_changes['Стартовая страница']=$rec_rol['index_page'].' => '.$index_page ;
               if (isset($options['use_auch_as_smena']) and $options['use_auch_as_smena']!=$rec_rol['use_auch_as_smena']) $arr_changes['Начало смены по авторизации']=$rec_rol['use_auch_as_smena'].' => '.$options['use_auch_as_smena'] ;
               if (isset($options['smena_monopole_mode']) and $options['smena_monopole_mode']!=$rec_rol['smena_monopole_mode']) $arr_changes['Монопольная смена']=$rec_rol['smena_monopole_mode'].' => '.$options['smena_monopole_mode'] ;
               if (isset($options['autologout']) and is_numeric($options['autologout']) and $options['autologout']!=$rec_rol['autologout']) $arr_changes['Срок жизни сессии']=$rec_rol['autologout'].' => '.$options['autologout'] ;
               if (isset($options['report_template']) and $options['report_template']!=$rec_rol['report_template']) $arr_changes['Отчет по закрытию смены']=$rec_rol['report_template'].' => '.$options['report_template'] ;
               if (isset($options['working']) and $options['working']!=$rec_rol['working']) $arr_changes['Должность по умолчанию']=$rec_rol['working'].' => '.$options['working'] ;
               if (_sizeof($arr_changes))
               {  $data=array('temp'=>0) ;
                  if ($options['allow_update_name']) $data['obj_name']=$name;
                  if ($index_page) $data['index_page']=$index_page;
                  if (isset($options['use_auch_as_smena'])) $data['use_auch_as_smena']=($options['use_auch_as_smena'])? 1:0;
                  if (isset($options['smena_monopole_mode'])) $data['smena_monopole_mode']=($options['smena_monopole_mode'])? 1:0;
                  $data['autologout']=(is_numeric($options['autologout']))? $options['autologout']:0;
                  if (isset($options['report_template'])) $data['report_template']=($options['report_template'])? $options['report_template']:'';
                  if (isset($options['working'])) $data['working']=($options['working'])? $options['working']:'';
                  $result=update_rec_in_table('roles',$data,'pkey='.$rec_rol['pkey'],array('debug'=>0)) ;
                  if ($result['error']) echo '<div class="alert">'.$result['error'].'</div>' ;

                  LOGS()->reg_log('ROLES','Изменена роль "'.$rec_rol['obj_name'].' ['.$rec_rol['id'].']"',array('data'=>$arr_changes)) ;
                  echo ' - <span class="green">UPDATE</span> ['.print_r($arr_changes,true).']<br>' ;
               }
               else
               { echo ' - <span class="green">OK</span><br>' ;
                 $this->arr_roles_ids[]=$rec_rol['pkey'] ;  // позже temp будет сброшено во всех этих ID
               }
            }
         }


     function reg_menu_item($menu_name,$item_name,$item_url,$params=array(),$options=array())
     {   global $install_options ;
         if (_sizeof($install_options) and !$install_options['menu_config']) return ;

         include_once('Spyc.php');
         $menu_fname='menu_'.$menu_name.'.yaml' ;
         $menu = $this->load_ini_setting('/ini/'.$menu_fname) ;
         $params['title']=$item_name ;
         $menu[$item_url]=$params ;
         $this->save_ini_setting('/ini/'.$menu_fname,$menu) ;
         echo 'Регистрация пункта меню "<strong>'.$item_name.'</strong>" - <span class="green">OK</span><br>' ;
     }

     function reg_ext($dir,$title)
     {   global $install_options ;
         if (_sizeof($install_options) and !$install_options['reg_ext']) return ;
         $this->ext_array[$dir]=$title ;
         echo 'Регистрация директории "<strong>'.$dir.'</strong>" - <span class="green">OK</span><br>' ;
     }

     function save_reg_ext()
     {   //damp_array(ENGINE()->list_active_ext,1,-1); damp_array($this->ext_array,1,-1);
         $arr=array_merge(ENGINE()->list_active_ext,$this->ext_array) ;
         //damp_array($arr,1,-1);
         $this->save_ini_setting('/ini/ext.yaml',$arr) ;
     }

     function reg_class($descr_clss,$options=array())
     {   global $install_options ;
         if (_sizeof($install_options) and !$install_options['reg_clss']) return ;

         include_once('Spyc.php');
         $menu_fname='clss.yaml' ;
         $arr_desc_clss = $this->load_ini_setting('/ini/'.$menu_fname) ;



         if (_sizeof($descr_clss)) foreach($descr_clss as $clss_code=>$clss_info)
         { if (isset($_SESSION['descr_clss'][$clss_code]))
           {   if (_sizeof($clss_info)) foreach($clss_info as $finfo=>$fvalue)
               {  if (is_array($fvalue)) foreach($fvalue as $finfo2=>$fvalue2) $_SESSION['descr_clss'][$clss_code][$finfo][$finfo2]=$fvalue2 ;
                  else                                                         $_SESSION['descr_clss'][$clss_code][$finfo]=$fvalue ;
               }
               $arr_desc_clss[$clss_code]=$_SESSION['descr_clss'][$clss_code] ;

           }
           else $arr_desc_clss[$clss_code]=$clss_info ;
           echo 'Регистрация класса "<strong>'.$clss_info['name'].'</strong>" ['.$clss_code.'] - <span class="green">OK</span><br>' ;
         }
         ksort($arr_desc_clss) ;
         $this->save_ini_setting('/ini/'.$menu_fname,$arr_desc_clss) ;
         create_class_model() ;
     }

}

// используется тока в режиме инсталяции движка
function create_table_by_pattern($pattern)
{  $id=SETUP()->create_table_by_pattern($pattern) ;
   return($id) ;
}

function create_viewer($name,$sql_create)
{  SETUP()->create_viewer($name,$sql_create) ;
}


?>
