kernel2/QF2_vis.php
author foxel
Wed, 30 Dec 2009 16:25:48 +0600
changeset 34 0e05a7ed0206
parent 19 7b6c1826b462
child 37 c971c735661c
permissions -rw-r--r--
модификация процесса обработки redefined.vis
для корректного переопределения блоков из частей стиля, отличных от common
Для указания переопределяемой части нужно вставить строку "<<part '{имя части}'>>' перед блоками, фактически переопределяющими эту часть стиля
     1 <?php
     2 
     3 // -------------------------------------------------------------------------- \\
     4 // VIS Class that provides template working and HTML visualization            \\
     5 // -------------------------------------------------------------------------- \\
     6 
     7 // Simple InUSE Check
     8 if ( !defined('QF_STARTED') )
     9         die('Hacking attempt');
    10 
    11 
    12 if ( defined('QF_KERNEL_VIS_LOADED') )
    13         die('Scripting error');
    14 
    15 define('QF_KERNEL_VIS_LOADED', True);
    16 
    17 // Cache prefixes for module data
    18 define('QF_KERNEL_VIS_VPREFIX', 'VIS.');
    19 define('QF_KERNEL_VIS_CPREFIX', 'VIS_CSS.');
    20 define('QF_KERNEL_VIS_JPREFIX', 'VIS_JS.');
    21 define('QF_KERNEL_VIS_COMMON', 'common');
    22 define('QF_KERNEL_VIS_DEFSTYLE', 'qf_def');
    23 
    24 // data directories
    25 define('QF_STYLES_DIR', QF_DATA_ROOT.'styles/');
    26 //define('QF_STCNTS_DIR', QF_DATA_ROOT.'vis_consts/'); // not used for now - not needed
    27 define('QF_JSCRIPTS_DIR', QF_DATA_ROOT.'jscripts/');
    28 define('QF_STATICS_DIR', 'static');
    29 define('QF_IMAGES_DIR', QF_STATICS_DIR.'/images');
    30 define('QF_ST_IMGS_DIR', QF_IMAGES_DIR.'/styles/');
    31 
    32 // defining some usefull constants
    33 // VIS resource types
    34 define('QF_VIS_NORMAL',  0);
    35 define('QF_VIS_STATIC',  1);
    36 define('QF_VIS_DINAMIC', 2);
    37 // Breakline
    38 define('VIS_BR', "\r\n");
    39 
    40 // node flags
    41 define('QF_VISNODE_ARRAY', 1); // node is an array of sametype nodes
    42 
    43 
    44 class QF_Visual
    45 {
    46     var $templates  = Array();
    47 
    48     var $VCSS_data  = ''; // CSS loaded from visuals
    49     var $VJS_data   = ''; // JS loaded from visuals
    50     var $CSS_data   = '';
    51     var $JS_data    = '';
    52     var $Consts     = Array();
    53 
    54     var $node_type  = Array();
    55     var $node_vars  = Array();
    56     var $node_subs  = Array();
    57     var $node_flags = Array();
    58     var $named_node = Array();
    59     var $parsed     = Array();
    60 
    61     var $style_name = QF_KERNEL_VIS_DEFSTYLE;
    62     var $style_vari = QF_KERNEL_VIS_COMMON;
    63 
    64     var $VIS_loaded = Array();
    65     var $CSS_loaded = false;
    66     var $JS_loaded  = Array();
    67 
    68     var $lang_name  = null;
    69     var $lang       = null;     // linking lang vars
    70     var $LNG_loaded = null;     // linking lang vars
    71 
    72     var $force_append  = true;  // forces to append CSS
    73     var $force_compact = true;  // forces to compact CSS/JS data
    74     var $vis_consts = Array();
    75     var $func_parsers = Array();
    76 
    77     function QF_Visual()
    78     {
    79         global $QF;
    80 
    81         if (defined('QF_VASUAL_CREATED'))
    82             trigger_error('Duplicate visual manager creation!', E_USER_ERROR);
    83 
    84         define('QF_VASUAL_CREATED', true);
    85 
    86         $this->node_type  = Array(0 => 'MAIN_PAGE');
    87         $this->style_name = QF_KERNEL_VIS_DEFSTYLE;
    88         $this->node_vars  = Array(0 => Array());
    89         $this->node_subs  = Array(0 => Array());
    90         $this->node_flags = Array(0 => 0);
    91         $this->named_node = Array('PAGE' => 0, 'MAIN' => 0);
    92         $this->func_parsers = Array(
    93             'FULLURL' => 'qf_full_url',
    94             'HTMLQUOTE' => 'htmlspecialchars',
    95             'URLEN' => 'qf_url_encode_part',
    96             'JS_DEF' => 'qf_value_JS_definition',
    97             'FTIME' => Array(&$QF->LNG, 'Time_Format'),
    98             'FBYTES' => Array(&$QF->LNG, 'Size_Format'),
    99             );
   100         $this->vis_consts = Array(
   101             'TIME' => $QF->Timer->time,
   102             );
   103     }
   104 
   105     function _Start()
   106     {
   107         global $QF;
   108 
   109         $data = $QF->LNG->Get_Data_Links();
   110         $this->lang       =& $data['lang'];
   111         $this->lang_name  =& $data['lang_name'];
   112         $this->LNG_loaded =& $data['LNG_loaded'];
   113         $this->Configure(Array(), true);
   114     }
   115 
   116     // configuring and loading functions
   117     function Configure($params, $force_clear = false)
   118     {
   119         global $QF;
   120 
   121         if (is_array($params))
   122         {
   123             extract($params);
   124 
   125             if ($force_clear) // clear all settings
   126             {
   127                 $this->node_type  = Array(0 => 'MAIN_PAGE');
   128                 $this->style_name = QF_KERNEL_VIS_DEFSTYLE;
   129                 $this->style_vari = QF_KERNEL_VIS_COMMON;
   130                 $this->node_vars  = Array(0 => Array());
   131                 $this->node_subs  = Array(0 => Array());
   132                 $this->named_node = Array('PAGE' => 0);
   133                 $this->named_node = Array('MAIN' => 0);
   134                 $this->templates  = Array();
   135                 $this->VCSS_data  = '';
   136                 $this->VJS_data   = '';
   137                 $this->VIS_loaded = Array();
   138                 $this->CSS_data   = '';
   139                 $this->JS_data    = '';
   140                 $this->CSS_loaded = false;
   141                 $this->JS_loaded  = Array();
   142                 $this->force_append  = true;
   143                 $this->force_compact = true;
   144             }
   145 
   146             if (isset($lang))
   147                 $QF->LNG->Select($lang);
   148 
   149             if (isset($style))
   150             {
   151                 $this->style_name = preg_replace('#\W#', '_', $style);
   152                 if (count($this->VIS_loaded))
   153                 {
   154                     $parts = $this->VIS_loaded;
   155                     $this->templates = Array();
   156                     $this->VCSS_data = '';
   157                     $this->VJS_data  = '';
   158                     $this->VIS_loaded = Array();
   159                     if (!$force_clear)
   160                         foreach ($parts as $part)
   161                             $this->Load_Templates($part);
   162                 }
   163 
   164                 if (isset($CSS))
   165                     $this->style_vari = $CSS;
   166                 elseif($CSS = $this->CSS_loaded)
   167                     if (!$force_clear)
   168                         $this->Load_ECSS($CSS);
   169 
   170             }
   171             elseif (isset($CSS))
   172                 $this->style_vari = $CSS;
   173 
   174             if (isset($root_node))
   175                 $this->node_type[0] = $root_node;
   176 
   177             if (isset($force_append))
   178                 $this->force_append = (bool) $force_append;
   179             if (isset($force_compact))
   180                 $this->force_compact = (bool) $force_compact;
   181         }
   182     }
   183 
   184     function Set_VConsts($consts, $no_replace = false)
   185     {
   186         if (!is_array($consts))
   187             return false;
   188 
   189         if ($no_replace)
   190             $this->vis_consts = $this->vis_consts + $consts;
   191         else
   192             $this->vis_consts = $consts + $this->vis_consts;
   193 
   194         return true;
   195     }
   196 
   197     function Load_ECSS($variant = '')
   198     {
   199         Global $QF;
   200 
   201         if (!$variant)
   202             $variant = $this->style_vari;
   203         else
   204             $variant = strtolower(preg_replace('#\W#', '_', $variant));
   205 
   206         $cachename = QF_KERNEL_VIS_CPREFIX.$this->style_name.'.'.$this->lang_name.'.'.$variant;
   207 
   208         if ($Cdata = $QF->Cache->Get($cachename))
   209         {
   210             $this->CSS_data = $Cdata;
   211             $QF->Timer->Time_Log($this->style_name.'.'.$variant.' CSS file loaded (from global cache)');
   212         }
   213         else
   214         {
   215             $file = $variant.'.ecss';
   216             $style = $this->style_name;
   217             $cfile = QF_STYLES_DIR.$style.'/'.$file;
   218             $commons = QF_STYLES_DIR.$style.'/'.QF_KERNEL_VIS_COMMON.'.ecss';
   219 
   220             if (!file_exists($cfile))
   221             {
   222                 trigger_error('VIS: there is no '.$this->style_name.'.'.$variant.' ECSS file', E_USER_WARNING );
   223                 $cfile = $commons;
   224             }
   225 
   226             if ($indata = qf_file_get_contents($cfile))
   227             {
   228                 $consts = Array(
   229                     'IMGS' => qf_full_url(QF_IMAGES_DIR),
   230                     'ST_IMGS' => qf_full_url(QF_ST_IMGS_DIR.$style),
   231                     'STATICS' => qf_full_url(QF_STATICS_DIR),
   232                     );
   233 
   234                 if (($cfile != $commons) && strstr($indata, '{COMMON_ECSS}') && ($commons = qf_file_get_contents($commons)))
   235                     $indata = str_replace('{COMMON_ECSS}', $commons, $indata);
   236 
   237                 $Cdata = $this->Prepare_ECSS($indata, $consts);
   238 
   239                 $QF->Cache->Set($cachename, $Cdata);
   240                 $this->CSS_data = $Cdata;
   241                 $QF->Timer->Time_Log($this->style_name.'.'.$variant.' CSS file loaded (from ECSS file)');
   242 
   243             }
   244             else
   245                 trigger_error('VIS: error loading '.$this->style_name.'.'.$variant.' ECSS file', E_USER_WARNING );
   246         }
   247 
   248         $this->style_vari = $this->CSS_loaded = $variant;
   249         return true;
   250 
   251     }
   252 
   253     function Load_EJS($name = '')
   254     {
   255         Global $QF;
   256 
   257         if (!$name)
   258             $name = QF_KERNEL_VIS_COMMON;
   259         else
   260             $name = strtolower(preg_replace('#\W#', '_', $name));
   261 
   262         if (!in_array($name, $this->JS_loaded))
   263         {
   264             $cachename = QF_KERNEL_VIS_JPREFIX.$this->lang_name.'.'.$name;
   265 
   266             if ($JSData = $QF->Cache->Get($cachename))
   267             {
   268                 $this->JS_data.= VIS_BR.$JSData;
   269 
   270                 $QF->Timer->Time_Log('"'.$name.'" JScript loaded (from global cache)');
   271             }
   272             else
   273             {
   274                 if (!in_array($name, $this->LNG_loaded))
   275                     $QF->LNG->Load_Language($name);
   276 
   277                 $file = $name.'.ejs';
   278                 $cfile = QF_JSCRIPTS_DIR.$file;
   279 
   280                 if (!file_exists($cfile))
   281                 {
   282                     trigger_error('VIS: there is no '.$name.' EJS file', E_USER_WARNING );
   283                 }
   284                 elseif ($indata = qf_file_get_contents($cfile))
   285                 {
   286                     $style = $this->style_name;
   287                     $indata = str_replace('{ST_IMGS}', qf_full_url(QF_ST_IMGS_DIR.$style), $indata);
   288                     $indata = str_replace('{IMGS}', qf_full_url(QF_IMAGES_DIR), $indata);
   289                     $indata = str_replace('{STATICS}', qf_full_url(QF_STATICS_DIR), $indata);
   290 
   291                     $indata = preg_replace_callback('#\{(?>L_((?:\w+|\"[^\"]+\"|\|)+))\}#',Array(&$this, '_Templ_Lang_CB'),$indata);
   292                     $indata = preg_replace('#\{(?>CONST:([\w\|]+))\}#e','(isset(\$this->Templ_Consts("$1"))) ? \$this->Templ_Consts("$1") : ""',$indata);
   293 
   294                     $QF->Events->Call_Event_Ref('EJS_PreParse', $indata);
   295 
   296                     $JSData = $this->Prepare_EJS($indata);
   297                     $this->JS_data.= VIS_BR.$JSData;
   298 
   299                     $QF->Cache->Set($cachename, $JSData );
   300                     $QF->Timer->Time_Log('"'.$name.'" JScript loaded (from EJS file)');
   301                 }
   302                 else
   303                     trigger_error('VIS: error loading "'.$name.'" EJS file', E_USER_WARNING );
   304             }
   305 
   306             $this->JS_loaded[] = $name;
   307         }
   308         return true;
   309     }
   310 
   311     function Load_Templates($part = '', $force_style = false)
   312     {
   313         Global $QF;
   314 
   315         if (!$part)
   316             $part = QF_KERNEL_VIS_COMMON;
   317         else
   318             $part = strtolower(preg_replace('#\W#', '_', $part));
   319 
   320         if (!in_array($part, $this->VIS_loaded))
   321         {
   322             if (!in_array($part, $this->LNG_loaded))
   323                 $QF->LNG->Load_Language($part);
   324 
   325             $cachename = QF_KERNEL_VIS_VPREFIX.$this->style_name.'.'.$this->lang_name.'.'.$part;
   326 
   327             if (list($Tdata, $VCSS, $VJS) = $QF->Cache->Get($cachename))
   328             {
   329                 $this->templates += $Tdata;
   330                 $this->VCSS_data .= VIS_BR.$VCSS;
   331                 $this->VJS_data  .= VIS_BR.$VJS;
   332 
   333                 // not used for now - not needed
   334                 //if ($part == QF_KERNEL_VIS_COMMON && $add_Consts = qf_file_load_datafile(QF_STCNTS_DIR.QF_KERNEL_VIS_COMMON.'.cnt', true))
   335                 //    $this->Consts += $add_Consts;
   336 
   337                 $QF->Timer->Time_Log('"'.$part.'" visuals loaded (from global cache)');
   338             }
   339             else
   340             {
   341                 $file = $part.'.vis';
   342                 $style = ($force_style)
   343                     ? $force_style
   344                     : $this->style_name;
   345                 $cfile = QF_STYLES_DIR.$style.'/'.$file;
   346                 if (!file_exists($cfile))
   347                 {
   348                     $style = QF_KERNEL_VIS_DEFSTYLE;
   349                     $cfile = QF_STYLES_DIR.$style.'/'.$file;
   350                 }
   351 
   352                 if (!file_exists($cfile))
   353                 {
   354                     trigger_error('VIS: there is no '.$this->style_name.'.'.$part.' VIS file', E_USER_WARNING );
   355                 }
   356                 elseif ($indata = qf_file_get_contents($cfile))
   357                 {
   358                     // not used for now - not needed
   359                     //if ($add_Consts = qf_file_load_datafile(QF_STCNTS_DIR.$part.'.cnt', true))
   360                     //    $this->Consts += $add_Consts;
   361                     $QF->Events->Call_Event_Ref('VIS_RawParse', $indata, $style, $part);
   362 
   363                     $indata = str_replace('{ST_IMGS}', QF_ST_IMGS_DIR.$style, $indata);
   364                     $indata = str_replace('{IMGS}', QF_IMAGES_DIR, $indata);
   365                     $indata = str_replace('{STATICS}', qf_full_url(QF_STATICS_DIR), $indata);
   366 
   367                     $indata = preg_replace_callback('#\{(?>L_((?:\w+|\"[^\"]+\"|\|)+))\}#',Array(&$this, '_Templ_Lang_CB'),$indata);
   368                     $indata = preg_replace('#\{(?>CONST:([\w\|]+))\}#e','(isset(\$this->Templ_Consts("$1"))) ? \$this->Templ_Consts("$1") : ""',$indata);
   369 
   370                     $QF->Events->Call_Event_Ref('VIS_PreParse', $indata, $style, $part);
   371 
   372                     preg_match_all("#<<\+ '(?>(\w+))'>>(.*?)<<- '\\1'>>#s", $indata, $blocks);
   373 
   374                     if (is_array($blocks[1]))
   375                     {
   376                         $Tdata  = Array();
   377                         $VCSS   = '';
   378                         $VJS    = '';
   379                         foreach ($blocks[1] as $num => $name)
   380                         {
   381                             $templ = $blocks[2][$num];
   382 
   383                             if ($name == 'CSS')
   384                                 $VCSS.= $this->Prepare_ECSS($templ);
   385                             elseif ($name == 'JS')
   386                                 $VJS.= $templ; // EJS can contain {V_ links
   387                                                // so we need to store it first and parse after VIS loading
   388                             else // normal VIS
   389                                 $Tdata[$name] = $this->Prepare_VIS($templ);
   390                         }
   391 
   392                         $this->templates += $Tdata;
   393                         $this->VCSS_data .= VIS_BR.$VCSS;
   394                         $VJS = $this->Prepare_EJS($VJS);
   395                         $this->VJS_data  .= VIS_BR.$VJS;
   396 
   397                         $QF->Cache->Set($cachename, Array($Tdata, $VCSS, $VJS) );
   398                         $QF->Timer->Time_Log('"'.$part.'" visuals loaded (from VIS file)');
   399                     }
   400                     else
   401                         trigger_error('VIS: error parsing "'.$part.'" VIS file for style "'.$this->style_name.'"', E_USER_WARNING );
   402 
   403                 }
   404                 else
   405                     trigger_error('VIS: error loading "'.$part.'" VIS file for style "'.$this->style_name.'"', E_USER_WARNING );
   406             }
   407 
   408             $this->VIS_loaded[] = $part;
   409 
   410         }
   411         return true;
   412     }
   413 
   414     // parsing functions
   415     function Parse($node = 0)
   416     {
   417         if (!is_int($node))
   418             $node = $this->Find_Node($node);
   419 
   420         if (is_null($node))
   421             return false;
   422 
   423         if (isset($this->parsed[$node]))
   424             return $this->parsed[$node];
   425 
   426         if (!isset($this->node_type[$node]))
   427         {
   428             trigger_error('VIS: trying to parse a fake node', E_USER_WARNING);
   429             return false;
   430         }
   431 
   432         $type =& $this->node_type[$node];
   433         $vars =& $this->node_vars[$node];
   434         $subs =& $this->node_subs[$node];
   435         $flags =& $this->node_flags[$node];
   436         $data = Array();
   437         $text = '';
   438 
   439         if ($flags && QF_VISNODE_ARRAY)
   440         {
   441             $parts = Array();
   442             $delimiter = (isset($vars['_DELIM'])) ? $vars['_DELIM'] : '';
   443             foreach ($vars as $data)
   444                 if (is_array($data))
   445                     $parts[] = $this->Parse_VIS($type, $data);
   446             $text = implode($delimiter, $parts);
   447         }
   448         else
   449         {
   450             foreach ($subs as $var => $subnodes)
   451                 foreach ($subnodes as $subnode)
   452                     $vars[$var][] = $this->Parse($subnode);
   453 
   454             foreach ($vars as $var => $vals)
   455                 $data[$var] = implode(VIS_BR, $vals);
   456 
   457             $text = $this->Parse_VIS($type, $data);
   458         }
   459 
   460         if ($node>0)
   461         {
   462             unset($this->node_type[$node],
   463                 $this->node_vars[$node],
   464                 $this->node_subs[$node],
   465                 $this->node_flags[$node]);
   466 
   467             $this->parsed[$node] =& $text;
   468         }
   469 
   470         return $text;
   471     }
   472 
   473     function Make_HTML()
   474     {
   475         if ($this->force_append)
   476         {
   477             if (!$this->CSS_loaded)
   478                 $this->load_ECSS();
   479             if (!in_array(QF_KERNEL_VIS_COMMON, $this->JS_loaded))
   480                 $this->load_EJS();
   481         }
   482 
   483         if (!count($this->VIS_loaded))
   484             $this->Load_Templates();
   485 
   486         $type =& $this->node_type[0];
   487         $vars =& $this->node_vars[0];
   488         $subs =& $this->node_subs[0];
   489         $data = Array();
   490         $text = '';
   491         $vars['CSS'][] = trim($this->CSS_data.VIS_BR.$this->VCSS_data);
   492         $vars['JS'][]  = trim($this->JS_data.VIS_BR.$this->VJS_data);
   493 
   494         foreach ($subs as $var => $subnodes)
   495             foreach ($subnodes as $subnode)
   496                 $vars[$var][] = $this->Parse($subnode);
   497 
   498         foreach ($vars as $var => $vals)
   499             $data[$var] = implode(VIS_BR, $vals);
   500 
   501 
   502         $text = $this->Parse_VIS($type, $data);
   503 
   504         return $text;
   505     }
   506 
   507     function Make_CSS()
   508     {
   509         if (!$this->CSS_loaded)
   510             $this->load_ECSS();
   511         return trim($this->CSS_data);
   512     }
   513 
   514     function Make_JS()
   515     {
   516         if (!$this->JS_loaded)
   517             $this->load_EJS();
   518         return trim($this->JS_data);
   519     }
   520 
   521     // tree construction functions
   522     function Create_Node($template, $data_arr = false, $globname = null)
   523     {
   524         $template = (string) $template;
   525         if (!$template)
   526             return false;
   527 
   528         end($this->node_type);
   529         $id = key($this->node_type) + 1;
   530         $this->node_type[$id] = $template;
   531         $this->node_vars[$id] = Array();
   532         $this->node_subs[$id] = Array();
   533         $this->node_flags[$id] = 0;
   534 
   535         if (is_array($data_arr))
   536             foreach ($data_arr as $key => $var)
   537             {
   538                 $key = strtoupper($key);
   539                 if (is_array($var))
   540                     $var = implode(' ', $var);
   541                 $this->node_vars[$id][$key][] = $var;
   542             }
   543 
   544         if ($globname && !is_numeric($globname))
   545         {
   546             $globname = strtoupper($globname);
   547             $this->named_node[$globname] = $id;
   548         }
   549 
   550         return $id;
   551     }
   552 
   553     function Append_Node($node_id, $varname, $parent = 0)
   554     {
   555         if (!is_int($parent))
   556             $parent = $this->Find_Node($parent);
   557         if (!is_int($node_id))
   558             $node_id = $this->Find_Node($node_id);
   559 
   560         $varname  = strtoupper($varname);
   561 
   562         if (!$varname)
   563             return false;
   564 
   565         if (!isset($this->node_type[$parent]))
   566         {
   567             trigger_error('VIS: trying to append data to fake node', E_USER_WARNING);
   568             return false;
   569         }
   570         if (!isset($this->node_type[$node_id]))
   571         {
   572             trigger_error('VIS: trying to append a fake node', E_USER_WARNING);
   573             return false;
   574         }
   575 
   576         $this->node_subs[$parent][$varname][] = $node_id;
   577         return true;
   578     }
   579 
   580     function Add_Node($template, $varname, $parent = 0, $data_arr = false, $globname = null)
   581     {
   582         if (!is_int($parent))
   583             $parent = $this->Find_Node($parent);
   584 
   585         $varname  = strtoupper($varname);
   586 
   587         if (!$varname)
   588             return false;
   589 
   590         if (!isset($this->node_type[$parent]))
   591         {
   592             trigger_error('VIS: trying to append data to fake node', E_USER_WARNING);
   593             return false;
   594         }
   595 
   596         if ($id = $this->Create_Node($template, $data_arr, $globname))
   597         {
   598             $this->node_subs[$parent][$varname][] = $id;
   599             return $id;
   600         }
   601 
   602         return false;
   603     }
   604 
   605     // Adds arrayed node
   606     function Add_Node_Array($template, $varname, $parent = 0, $data_arr = false, $delimiter = false)
   607     {
   608         if (!is_int($parent))
   609             $parent = $this->Find_Node($parent);
   610 
   611         $varname  = strtoupper($varname);
   612 
   613         if (!$varname)
   614             return false;
   615 
   616         if (!isset($this->node_type[$parent]))
   617         {
   618             trigger_error('VIS: trying to append data to fake node', E_USER_WARNING);
   619             return false;
   620         }
   621 
   622         if ($id = $this->Create_Node($template))
   623         {
   624             $this->node_subs[$parent][$varname][] = $id;
   625             $this->node_flags[$id] = QF_VISNODE_ARRAY;
   626 
   627             if (is_array($data_arr) && count($data_arr))
   628             {
   629               $in = 0;
   630               foreach ($data_arr as $arr)
   631                 if (is_array($arr))
   632                 {
   633                   foreach ($arr as $key => $var)
   634                   {
   635                       $key = strtoupper($key);
   636                       if (is_array($var))
   637                           $var = implode(' ', $var);
   638                       $this->node_vars[$id][$in][$key] = $var;
   639                   }
   640 
   641                   $this->node_vars[$id][$in]['_POS'] = $in;
   642 
   643                   $in++;
   644                 }
   645 
   646                 $this->node_vars[$id][0]['_IS_FIRST'] = '1';
   647                 $this->node_vars[$id][$in-1]['_IS_LAST'] = '1';
   648             }
   649 
   650             if (strlen($delimiter))
   651                 $this->node_vars[$id]['_DELIM'] = (string) $delimiter;
   652             return $id;
   653         }
   654 
   655         return false;
   656     }
   657 
   658     function Add_Data($node, $varname, $data)
   659     {
   660         if (is_null($node))
   661             return false;
   662 
   663         $varname = strtoupper($varname);
   664 
   665         if (!$varname)
   666             return false;
   667 
   668         if (!isset($this->node_type[$node]) || ($this->node_flags[$node] && QF_VISNODE_ARRAY))
   669         {
   670             trigger_error('VIS: trying to append data to fake node', E_USER_WARNING);
   671             return false;
   672         }
   673 
   674         if (is_array($data))
   675             $data = implode(' ', $data);
   676         $this->node_vars[$node][$varname][] = $data;
   677 
   678         return true;
   679     }
   680 
   681     function Add_Data_Array($node, $arr)
   682     {
   683         if (is_null($node))
   684             return false;
   685 
   686         if (!isset($this->node_type[$node]) || ($this->node_flags[$node] && QF_VISNODE_ARRAY))
   687         {
   688             trigger_error('VIS: trying to append data to fake node', E_USER_WARNING);
   689             return false;
   690         }
   691 
   692         if (!is_array($arr))
   693             return false;
   694 
   695         foreach ($arr as $key => $var)
   696         {
   697             $key = strtoupper($key);
   698             if (is_array($var))
   699                 $var = implode(' ', $var);
   700             $this->node_vars[$node][$key][] = $var;
   701         }
   702 
   703         return true;
   704     }
   705 
   706     function Find_Node($to_find)
   707     {
   708         if (!$to_find)
   709             return 0;
   710 
   711         if (!is_numeric($to_find))
   712         {
   713             $to_find = strtoupper($to_find);
   714             if (isset($this->named_node[$to_find]))
   715                 $to_find = $this->named_node[$to_find];
   716             else
   717                 return null;
   718         }
   719 
   720         $to_find = (int) $to_find;
   721         return $to_find;
   722     }
   723 
   724 
   725     // Inner parsing functions
   726 
   727     // reparses {L_...} blocks in raw templates
   728     function _Templ_Lang_CB($matches)
   729     {
   730         $code = $matches[1];
   731         $code = explode('|', $code);
   732 
   733         if (!($lng = strtoupper($code[0])))
   734             return '';
   735         if (!isset($this->lang[$lng]))
   736             return '';
   737 
   738         $data = $this->lang[$lng];
   739         if (count($code)>1)
   740         {
   741             $params = array_slice($code, 1);
   742             foreach ($params as $id => $val)
   743                 $params[$id] = ($val{0} == '"') ? substr($val, 1, -1) : '{'.$val.'}';
   744 
   745             $data = qf_sprintf_arr($data, $params);
   746         }
   747 
   748         return $data;
   749     }
   750 
   751     function Templ_Consts($code)
   752     {
   753         $code = explode('|', $code);
   754 
   755         if (!($id = strtoupper($code[0])))
   756             return '#';
   757         if (!isset($this->Consts[$id]))
   758             return '#';
   759 
   760         $data = $this->Consts[$id];
   761         if (count($code)>1)
   762         {
   763             $params = array_slice($code, 1);
   764             foreach ($params as $id => $val)
   765                 $params[$id] = (is_numeric($val{0})) ? (int) $val : '{'.$val.'}';
   766             $data = qf_sprintf_arr($data, $params);
   767         }
   768 
   769         return $data;
   770     }
   771 
   772     function Prepare_VIS($text)
   773     {
   774         global $QF;
   775 
   776         static $consts = Array(
   777             'QF_MARK'  => 'Powered by<br />QuickFox 2<br />&copy; Foxel aka LION<br /> 2006 - 2009',
   778             'QF_INDEX' => QF_INDEX,
   779             );
   780 
   781         $consts['QF_ROOT'] = $QF->HTTP->RootUrl;
   782         $text = trim($text);
   783 
   784         if ($this->force_compact)
   785             $text = $this->VIS_compact($text);
   786 
   787         $text = preg_replace('#(?<=\})\n\s*?(?=\{\w)#', '', $text);
   788         preg_match_all('#\{(\!?)((?>\w+))(?:\:((?:(?>\w+)(?:[\!=\>\<]{1,2}(?:\w+|\"[^\"]*\"))?|\||)*))?\}|[^\{]+|\{#', $text, $struct, PREG_SET_ORDER);
   789 
   790         $writes_to = '$OUT';
   791         $text = $writes_to.' = <<<QFT'.VIS_BR;
   792         $vars = Array();
   793 
   794         $iflevel = 0;
   795         $outiflevel = 0;
   796         $in_for = false;
   797 
   798         $keys = array_keys($struct);
   799 
   800         foreach ($keys as $key)
   801         {
   802             $part =& $struct[$key];
   803 
   804             if (isset($part[2]) && ($tag = strtoupper($part[2])))
   805             {
   806                 $got_a = ($part[1]) ? true : false;
   807 
   808                 $params = Array();
   809                 if (isset($part[3]) && ($got = preg_match_all('#((?>\w+))(?:([\!=\>\<]{1,2})(\w+|\"[^\"]*\"))?#', $part[3], $params, PREG_PATTERN_ORDER)))
   810                     for ($i = 0; $i < $got; $i++)
   811                         $params[1][$i] = strtoupper($params[1][$i]);
   812 
   813                 if ($tag == 'WRITE')
   814                 {
   815                     if (isset($params[1]) && count($params[1]) && ($var = $params[1][0]) && !is_numeric($var{0}))
   816                         $var = '$'.$var;
   817                     else
   818                         $var = '$OUT';
   819                     if ($var != $writes_to)
   820                     {
   821                         $writes_to = $var;
   822                         $text.= VIS_BR.'QFT;'.VIS_BR.$writes_to.(($got_a) ? '' : '.').'= <<<QFT'.VIS_BR;
   823                     }
   824                 }
   825                 elseif (isset($this->func_parsers[$tag])) //parsing the variable with func
   826                 {
   827                     $func_parser = $this->func_parsers[$tag];
   828 
   829                     if (!isset($params[1]) || !count($params[1]))
   830                         continue;
   831                     $pars = count($params[1]);
   832                     $needFunc = false;
   833                     $realPars = Array();
   834                     $varPars = Array();
   835                     for ($i = 0; $i < $pars; $i++)
   836                     {
   837                         $val = $params[1][$i];
   838 
   839                         if (is_numeric($val{0}))
   840                             $text.= qf_heredoc_addslashes(qf_func_call($func_parser, intval($val)), 'QFT');
   841                         elseif ($val{0} == '"')
   842                             $text.= qf_heredoc_addslashes(qf_func_call($func_parser, substr($val, 1, -1)), 'QFT');
   843                         else
   844                         {
   845                             $val = strtoupper($val);
   846                             if (substr($val, 0, 2) == 'L_')
   847                                 $text.= qf_heredoc_addslashes(qf_func_call($func_parser, $this->_Templ_Lang_CB(Array(1 => substr($val, 2)))), 'QFT');
   848                             elseif (isset($consts[$val]))
   849                                 $text.= qf_heredoc_addslashes(qf_func_call($func_parser, $consts[$val]), 'QFT');
   850                             else
   851                             {
   852                                 $vars[$val] = '';
   853                                 $text.= VIS_BR.'QFT'.VIS_BR.'.$this->Do_Func(\''.$tag.'\', $'.$val.').<<<QFT'.VIS_BR;
   854                             }
   855                         }
   856                     }
   857                 }
   858                 elseif ($tag == 'SET')
   859                 {
   860                     if ($pars = count($params[1]))
   861                     {
   862                         $sets = '';
   863                         for($i = 0; $i < $pars; $i++)
   864                         {
   865                             $var = $params[1][$i];
   866                             if (is_numeric($var{0}) || !isset($params[3][$i]) && !strlen($params[3][$i]))
   867                                 continue;
   868                             $val = $params[3][$i];
   869                             $sets.= '$'.$var.' = ';
   870 
   871                             if (is_numeric($val{0}))
   872                                 $sets.= intval($val).';';
   873                             elseif ($val{0} == '"')
   874                                 $sets.= '<<<QFT'.VIS_BR.qf_heredoc_addslashes(substr($val, 1, -1), 'QFT').VIS_BR.'QFT'.VIS_BR.';';
   875                             else
   876                             {
   877                                 $val = strtoupper($val);
   878                                 if (substr($val, 0, 2) == 'L_')
   879                                     $sets.= '<<<QFT'.VIS_BR.qf_heredoc_addslashes($this->_Templ_Lang_CB(Array(1 => substr($val, 2))), 'QFT').VIS_BR.'QFT'.VIS_BR.';';
   880                                 elseif (isset($consts[$val]))
   881                                     $sets.= '<<<QFT'.VIS_BR.qf_heredoc_addslashes($consts[$val], 'QFT').VIS_BR.'QFT'.VIS_BR.';';
   882                                 else
   883                                 {
   884                                     $vars[$val] = '';
   885                                     $sets.= '$'.$val.';';
   886                                 }
   887                             }
   888                         }
   889 
   890                         if ($sets)
   891                             $text.= VIS_BR.'QFT;'.VIS_BR.$sets.VIS_BR.$writes_to.'.= <<<QFT'.VIS_BR;
   892                     }
   893                 }
   894                 elseif ($tag == 'FOR')
   895                 {
   896                     if (!isset($params[1]) || !count($params[1]))
   897                         continue;
   898                     $params = $params[1];
   899                     $p1 = array_shift($params);
   900                     $p2 = array_shift($params);
   901                     $p3 = array_shift($params);
   902 
   903                     $p1 = (is_numeric($p1{0})) ? intval($p1) : '(int) $'.$p1.($vars[$p1] = '');
   904                     if ($p2)
   905                         $p2 = (is_numeric($p2{0})) ? intval($p2) : '(int) $'.$p2.($vars[$p2] = '');
   906                     else
   907                     {
   908                         $p2 = $p1;
   909                         $p1 = '0';
   910                     }
   911                     if ($p3)
   912                         $p3 = (is_numeric($p3{0})) ? intval($p3) : '(int) $'.$p3.($vars[$p3] = '');
   913                     else
   914                         $p3 = '1';
   915 
   916                     $in_for = true;
   917                     $outiflevel = $iflevel;
   918                     $iflevel = 0;
   919                     $text.= VIS_BR.'QFT;'.VIS_BR.'for ($I = '.$p1.'; $I <= '.$p2.'; $I+= '.$p3.') {'.VIS_BR.$writes_to.'.= <<<QFT'.VIS_BR;
   920                 }
   921                 elseif ($tag == 'ENDFOR')
   922                 {
   923                     if ($in_for)
   924                     {
   925                         $text.= VIS_BR.'QFT;'.VIS_BR;
   926                         $in_for = false;
   927                         $text.= str_repeat('} ', $iflevel);
   928                         $text.= VIS_BR.'}'.VIS_BR.$writes_to.'.= <<<QFT'.VIS_BR;
   929                         $iflevel = $outiflevel;
   930                     }
   931                 }
   932                 elseif ($tag == 'VIS')
   933                 {
   934                     if (!isset($params[1]) || !count($params[1]))
   935                         continue;
   936                     $visname = $params[1][0];
   937                     $text.= VIS_BR.'QFT;'.VIS_BR.$writes_to.(($got_a) ? '' : '.').'= $this->Parse_VIS(\''.$visname.'\'';
   938                     if (count($params[1]) > 1)
   939                     {
   940                         $text.= ', Array(';
   941                         $pars = count($params[1]);
   942                         for($i = 1; $i < $pars; $i++)
   943                         {
   944                             $var = $params[1][$i];
   945                             $val = (isset($params[3][$i]) && strlen($params[3][$i])) ? $params[3][$i] : '1';
   946                             $text.= '\''.$var.'\' => ';
   947 
   948                             if (is_numeric($val{0}))
   949                                 $text.= intval($val).',';
   950                             elseif ($val{0} == '"')
   951                                 $text.= '<<<QFT'.VIS_BR.qf_heredoc_addslashes(substr($val, 1, -1), 'QFT').VIS_BR.'QFT'.VIS_BR.',';
   952                             else
   953                             {
   954                                 $val = strtoupper($val);
   955                                 if (substr($val, 0, 2) == 'L_')
   956                                     $text.= '<<<QFT'.VIS_BR.qf_heredoc_addslashes($this->_Templ_Lang_CB(Array(1 => substr($val, 2))), 'QFT').VIS_BR.'QFT'.VIS_BR.',';
   957                                 elseif (isset($consts[$val]))
   958                                     $text.= '<<<QFT'.VIS_BR.qf_heredoc_addslashes($consts[$val], 'QFT').VIS_BR.'QFT'.VIS_BR.',';
   959                                 else
   960                                 {
   961                                     $vars[$val] = '';
   962                                     $text.= '$'.$val.',';
   963                                 }
   964                             }
   965                         }
   966                         $text.= ') ';
   967                     }
   968                     $text.= ');'.VIS_BR.$writes_to.'.= <<<QFT'.VIS_BR;
   969                 }
   970                 elseif ($tag == 'IF' || $tag == 'ELSEIF')
   971                 {
   972                     if (!isset($params[1]) || !count($params[1]))
   973                         continue;
   974                     $varname = $params[1][0];
   975                     $vars[$varname] = '';
   976                     if (isset($params[3][0]) && strlen($params[3][0]))
   977                     {
   978                         $condvar = $params[3][0];
   979                         $condition = $params[2][0];
   980                         switch ($condition)
   981                         {
   982                             case '>':
   983                             case '<':
   984                             case '>=':
   985                             case '<=':
   986                             case '!=':
   987                                 $condition = ' '.$condition.' ';
   988                                 break;
   989                             default:
   990                                 $condition = ' == ';
   991 
   992                         }
   993 
   994                         if (is_numeric($condvar{0}))
   995                             $condition = '((int) $'.$varname.$condition.intval($condvar).')';
   996                         elseif ($condvar{0} == '"')
   997                         {
   998                             $condvar = substr($condvar, 1, -1);
   999                             $condition = '($'.$varname.$condition.'\''.strtr($condvar, Array('\'' => '\\\'', '\\' => '\\\\')).'\')';
  1000                         }
  1001                         else
  1002                             $condition = '($'.$varname.$condition.'(string) $'.$condvar.')';
  1003                     }
  1004                     else
  1005                         $condition = 'strlen($'.$varname.')';
  1006 
  1007                     if ($got_a)
  1008                         $condition = '!'.$condition;
  1009 
  1010                     if ($tag == 'IF')
  1011                     {
  1012                         $text.= VIS_BR.'QFT;'.VIS_BR.'if ('.$condition.') {'.VIS_BR.$writes_to.'.= <<<QFT'.VIS_BR;
  1013                         $iflevel++;
  1014                     }
  1015                     elseif ($iflevel)
  1016                         $text.= VIS_BR.'QFT;'.VIS_BR.'} elseif('.$condition.') {'.VIS_BR.$writes_to.'.= <<<QFT'.VIS_BR;
  1017                 }
  1018                 elseif ($tag == 'ELSE')
  1019                 {
  1020                     if ($iflevel)
  1021                         $text.= VIS_BR.'QFT;'.VIS_BR.'} elseif(true) {'.VIS_BR.$writes_to.'.= <<<QFT'.VIS_BR;
  1022                 }
  1023                 elseif ($tag == 'ENDIF')
  1024                 {
  1025                     if ($iflevel)
  1026                     {
  1027                         $text.= VIS_BR.'QFT;'.VIS_BR.'}'.VIS_BR.$writes_to.'.= <<<QFT'.VIS_BR;
  1028                         $iflevel--;
  1029                     }
  1030                 }
  1031                 else
  1032                 {
  1033                     $varname = $tag;
  1034                     if (isset($consts[$varname]))
  1035                         $text.= qf_heredoc_addslashes($consts[$varname], 'QFT');
  1036                     elseif (!is_numeric($varname{0}))
  1037                     {
  1038                         $vars[$varname] = '';
  1039                         if ($got_a)
  1040                             $text.= VIS_BR.'QFT'.VIS_BR.'.qf_smart_htmlschars($'.$varname.').<<<QFT'.VIS_BR;
  1041                         else
  1042                             $text.= '{$'.$varname.'}';
  1043                     }
  1044                 }
  1045             }
  1046             else
  1047             {
  1048                 $text.= qf_heredoc_addslashes($part[0], 'QFT');
  1049             }
  1050 
  1051             unset($struct[$key]);
  1052         }
  1053 
  1054         $text.= VIS_BR.'QFT;'.VIS_BR;
  1055 
  1056         $text.= str_repeat('} ', $iflevel);
  1057         if ($in_for)
  1058             $text.= str_repeat('} ', $outiflevel+1);
  1059 
  1060         $text = preg_replace('#\$\w+\.\=\s*\<\<\<QFT\s+QFT;#', '', $text);
  1061         return Array('T' => $text, 'V' => $vars);
  1062     }
  1063 
  1064     function ____PreReplace_VISes($VISes) //RAW VISes including... TODO
  1065     {
  1066         foreach ($VISes as $id => $text)
  1067         {
  1068             preg_match_all('#\{\!?VIS(?:\:((?:(?>\w+)(?:[\!=\>\<]{1,2}(?:\w+|\"[^\"]*\"))?|\||)*))?\}|[^\{]+|\{#', $text, $struct, PREG_SET_ORDER);
  1069 
  1070             $text = '';
  1071             $keys = array_keys($struct);
  1072 
  1073             foreach ($keys as $key)
  1074             {
  1075                 $part =& $struct[$key];
  1076 
  1077                 if (isset($part[2]) && ($tag = strtoupper($part[2])))
  1078                 {
  1079                     $got_a = ($part[1]) ? true : false;
  1080                     $params = Array();
  1081                     if (isset($part[3]) && ($got = preg_match_all('#((?>\w+))(?:([\!=\>\<]{1,2})(\w+|\"[^\"]*\"))?#', $part[3], $params, PREG_PATTERN_ORDER)))
  1082                         for ($i = 0; $i < $got; $i++)
  1083                             $params[1][$i] = strtoupper($params[1][$i]);
  1084                 }
  1085             }
  1086         }
  1087     }
  1088 
  1089     function Do_Func($func_name, $data) //parsing data with funcParser
  1090     {
  1091         if (!isset($this->func_parsers[$func_name]))
  1092             return $data;
  1093 
  1094         $func_parser = $this->func_parsers[$func_name];
  1095         return qf_func_call($func_parser, $data);
  1096     }
  1097 
  1098     function Parse_VIS($vis, $data = Array())
  1099     {
  1100         Static $__COUNTER=1;
  1101         Static $QF_SID;
  1102         if (!$QF_SID)
  1103         {
  1104             global $QF;
  1105             $QF_SID = $QF->Session->SID;
  1106             unset($QF);
  1107         }
  1108 
  1109         $COUNTER = $__COUNTER++;
  1110         $RANDOM = dechex(rand(0x1FFF, getrandmax()));
  1111 
  1112         if (!isset($this->templates[$vis]))
  1113             return implode(VIS_BR, $data);
  1114 
  1115         if (extract($this->templates[$vis]['V'], EXTR_SKIP))
  1116         {
  1117             extract($data, EXTR_OVERWRITE | EXTR_PREFIX_ALL, 'IN');
  1118             extract($this->vis_consts, EXTR_OVERWRITE | EXTR_PREFIX_ALL, 'C');
  1119         }
  1120 
  1121         $OUT = '';
  1122 
  1123         if (eval($this->templates[$vis]['T']) === false)
  1124             trigger_error('VIS: error running "'.$vis.'" template. CODE ['.$this->templates[$vis]['T'].']', E_USER_ERROR);
  1125 
  1126         return $OUT;
  1127     }
  1128 
  1129     function Prepare_ECSS($indata, $constants = null)
  1130     {
  1131         if (is_array($constants))
  1132             foreach ($constants as $name=>$val)
  1133                 $indata = str_replace('{'.$name.'}', $val, $indata);
  1134 
  1135         $vars_mask='#\{((?>[\w\-]+))\}\s*=(.*)#';
  1136         $vars_block='#\{VARS\}(.*?)\{/VARS\}#si';
  1137 
  1138         preg_match_all($vars_block, $indata, $blocks);
  1139         $blocks = implode(' ', $blocks[0]);
  1140 
  1141         preg_match_all($vars_mask, $blocks, $sets);
  1142         if (is_array($sets[1]))
  1143             foreach ($sets[1] as $num => $name)
  1144                 $CSSVars[strtoupper($name)] = trim($sets[2][$num]);
  1145 
  1146         $Cdata = preg_replace($vars_block, '', $indata);
  1147 
  1148         if ($this->force_compact)
  1149             $Cdata = $this->CSS_compact($Cdata);
  1150 
  1151         $Cdata = preg_replace('#\{(?>(\w+))\}#e', '(isset(\$CSSVars[strtoupper("\1")])) ? \$CSSVars[strtoupper("\1")] : ""', $Cdata);
  1152 
  1153         return $Cdata;
  1154     }
  1155 
  1156     function Prepare_EJS($Jdata, $constants = null)
  1157     {
  1158         if (is_array($constants))
  1159             foreach ($constants as $name=>$val)
  1160                 $Jdata = str_replace('{'.$name.'}', $val, $Jdata);
  1161         if ($this->force_compact)
  1162             $Jdata = $this->EJS_compact($Jdata);
  1163         return $Jdata;
  1164     }
  1165 
  1166     function EJS_compact($indata)
  1167     {
  1168         $indata = str_replace("\r", '', $indata);
  1169         $indata = preg_replace('#^//.*?$#m', '', $indata);
  1170         $indata = preg_replace('#(?<=\s)//.*?$#m', '', $indata);
  1171         $indata = preg_replace('#(\n\s*)+#', "\n", $indata);
  1172         $indata = preg_replace('#\n(.{1,5})$#m', ' \\1', $indata);
  1173         $indata = str_replace("\n", VIS_BR, $indata);
  1174         $indata = trim($indata);
  1175         return $indata;
  1176     }
  1177 
  1178     function CSS_compact($indata)
  1179     {
  1180         $indata = str_replace("\r", '', $indata);
  1181         $indata = preg_replace('#/\*.+\*/#sU', '', $indata);
  1182         $indata = preg_replace('#(\n\s*)+#', "\n", $indata);
  1183         $indata = preg_replace('#\n(.{1,5})$#m', ' \\1', $indata);
  1184         $indata = preg_replace('#\s*(,|:|;|\{)\s+#', '\\1 ', $indata);
  1185         $indata = preg_replace('#\s+\}\s+#', " }\n", $indata);
  1186         $indata = str_replace("\n", VIS_BR, $indata);
  1187         $indata = trim($indata);
  1188         return $indata;
  1189     }
  1190 
  1191     function VIS_compact($indata)
  1192     {
  1193         $indata = str_replace("\r", '', $indata);
  1194         $indata = preg_replace('#(\n\s*)+#', "\n", $indata);
  1195         $indata = preg_replace('#\n(.{1,5})$#m', ' \\1', $indata);
  1196         $indata = preg_replace('#\x20+#', ' ', $indata);
  1197         $indata = str_replace("\n", VIS_BR, $indata);
  1198         $indata = trim($indata);
  1199         return $indata;
  1200     }
  1201 }
  1202 
  1203 
  1204 ?>