+ MPDF 6.1

This commit is contained in:
2020-08-11 18:04:59 +06:00
parent 11d3f0fc7a
commit c2e133debe
714 changed files with 120510 additions and 93145 deletions

View File

@ -1,518 +1,2 @@
<?php
/**
* Обвернуть строку в кавычки в соответствии с типом.
* @param String $t Тип
* @param String $v Значение
* @return String Строка
*/
function getSQLValue($t,$v)
{
if($t=='object' && gettype($v)=='string') $t='string'; //Если id шники uuid
if($t=='object')
{ if (($v=='-1')||($v=='')) $v='NULL';
}else
if($t=='i4' || $t=='integer')
{ if($v=='') $v='NULL';
}else
if($t=='f8')
{ if($v=='')$v='NULL';
$v=str_replace(',','.',$v); //Разделитель целой и дробной части точка
}else
if($t=='b')
{ if($v=='') $v='NULL'; else
if($v=='1') $v='true'; else
if($v=='0') $v='false';
}else
if($t=='string' || $t=='dateTime' || $t=='date')
{ if($v=='')
{ $v='NULL';
}else
{ $v=str_replace('\'','\\\'',$v); //так как в SQL строку вставляется
$v='\''.$v.'\'';
}
}else
$v='\''.$v.'\'';
return $v;
}
/** Перенести параметры из родительского в sql строку дочернего элемента
* @param object $nParent
* @param object $nChild
* @result Строка
*/
function getSQL($nParent,$nChild)
{
if($nChild==null) return '';
$nPs=findNode($nParent, 'columns');
$nFs=findNode($nChild, 'filter');
//Переносим значения в фильтр
if($nFs!=null)
{
if($nPs!=null) $nP=$nPs->firstChild; else $nP=null;
while ($nP != null)
{
if ($nP->nodeName=='param')
{
$val=getCdata($nP)->nodeValue;
$nF=findNodeOnAttribute($nFs, 'column', 'pn', $nP->getAttribute("n"));
if($nF!=null) getCdata($nF)->nodeValue=$val;
}
$nP = $nP->nextSibling;
}
}
//Переносим значения в SQL запрос из фильтра
$sql=getCdataValue(findNode($nChild,'sql-query'));
$nFs=findNode($nChild, 'filter');
if($nFs!=null)
{ $nF=$nFs->firstChild;
while($nF != null)
{
if($nF->nodeName=='column')
{
$sql=str_replace('${'.$nF->getAttribute("n").'}',getSQLValue($nF->getAttribute("vt"),getCdata($nF)->nodeValue),$sql);
}
$nF=$nF->nextSibling;
}
}
return $sql;
}
//Функция по заданному пути выдаёт все под пути в виде асоциативного массива (тоесть + 1 уровень дерева)
//$db - PDO соединение с базой данных
//$path - путь "id дерева из XML; id записи из базы; id дерева из XML; id записи из базы;"
//$nParent - родительский узел нужен для рекурсии по умолчанию ставить null
function GetSubNodes($path,$nParent,&$title)
{
global $v_db;
if($nParent==null) return array();
$dt=''; //Разделитель для заголовка смотри ниже по тексту "->"
//По заданному пути спускаемся к нужному узлу дерева
$mas=split(';',$path);
for($i=0;$i<(count($mas)-1)/2;$i++)
{
$nChild=findNodeOnAttribute($nParent, 'type', 'id', $mas[$i*2]); //Ищем нужную ветку XML дерева
$sql=getSQL($nParent,$nChild); //Выбираем параметры из родительского в дочерний потом из текущего в sql запрос
//Выполняем и ищем запись с нужным id
$res = $v_db->query($sql);
while ($row = $res->fetch(PDO::FETCH_ASSOC))// $row - ассоциативный массив значений, ключи - названия столбцов
{
if($row[$nChild->getAttribute('ObjectID')]==$mas[$i*2+1])
{
$title.=$dt.$row[$nChild->getAttribute('c')]; //Чтоб отобразить заголовок в виде пути
$dt='->';
//Записываем параметры из текущей записи в параметры для передачи в в следующую итерацию
$nPs=findNode($nChild,'columns');
$nP=$nPs->firstChild;
while ($nP != null)
{
if ($nP->nodeName=='param')
getCdata($nP)->nodeValue=$row[$nP->getAttribute("n")];
$nP = $nP->nextSibling;
}
$nParent=$nChild;
break;
}
}
}
//Добрались до самого последнего элемента пути теперь выбераем из всех дочерних узлов
$result=array();
$nChild=$nParent->firstChild;
while ($nChild != null)
{
if($nChild->nodeName=='goto')
{
$nType=findFirstNodeOnAttribute($nChild->ownerDocument->documentElement,"type","id",$nChild->getAttribute("id"));
if($nType==null) { $nChild = $nChild->nextSibling; continue; }
}else $nType=$nChild;
if ($nType->nodeName=='type')
{
$sql=getSQL($nParent,$nType);//Получаем SQL запрос перенося параметры из родительского в дочерний а потом в SQL дочернего
$res = $v_db->query($sql);
while ($row = $res->fetch(PDO::FETCH_ASSOC))// $row - ассоциативный массив значений, ключи - названия столбцов
{
$cnt=count($result);
$result[$cnt]['name']=$row[$nType->getAttribute('c')];
$result[$cnt]['path']=$path.$nType->getAttribute('id').';'.$row[$nChild->getAttribute('ObjectID')].';';
}
}
$nChild = $nChild->nextSibling;
}
return $result;
}
//Из пути получить асоциативный массив заголовков + путь
//$path - путь "id дерева из XML; id записи из базы; id дерева из XML; id записи из базы;"
//$nParent - XML узел с которого будет начинаться поиск
//$db - База данных PDO
function getTXTPath($path,$nParent,$db)
{
$result=array(); $pos=0;
$mas=explode(';',$path);
for($i=0;$i<(count($mas)-1)/2;$i++)
{
$nChild=findNodeOnAttribute($nParent, 'type', 'id', $mas[$i*2]); //Ищем нужную ветку XML дерева
if($nChild==null) $nChild=findFirstNodeOnAttribute($nParent->ownerDocument->documentElement, 'type', 'id', $mas[$i*2]);
if($nChild==null) continue;
//print $nParent->ownerDocument->saveXML($nParent).'<br>';
$sql=getSQL($nParent,$nChild); //Выбираем параметры из родительского в дочерний потом из текущего в sql запрос
if(gettype($_SESSION['USER_ID'])=='string')
$sql=str_replace('${user_id}',$_SESSION['USER_ID']=='' ? 'null' : '\''.$_SESSION['USER_ID'].'\'',$sql);
else
$sql=str_replace('${user_id}',$_SESSION['USER_ID']=='' ? 'null' : $_SESSION['USER_ID'],$sql);
//print $sql.'<br>';
//Выполняем и ищем запись с нужным id
$res = $db->query($sql);
while ($row = $res->fetch(PDO::FETCH_ASSOC))// $row - ассоциативный массив значений, ключи - названия столбцов
{
if($row[$nChild->getAttribute('ObjectID')]==$mas[$i*2+1])
{
$result[$pos]['name']=$row[$nChild->getAttribute('c')];
$result[$pos]['path']=$mas[$i*2].';'.$mas[$i*2+1].';';
//Записываем параметры из текущей записи в параметры для передачи в в следующую итерацию
$nP=findNode($nChild, 'columns');
if($nP!=null) $nP=$nP->firstChild;
while ($nP != null)
{
if ($nP->nodeName=='param')
{
if(isset($row[$nP->getAttribute("n")]))
getCdata($nP)->nodeValue=$row[$nP->getAttribute("n")];
if(isset($row[$nP->getAttribute("n")]))
$result[$pos][$nP->getAttribute("n")]=$row[$nP->getAttribute("n")];
//getCdata($nP)->nodeValue=$row[$nP->getAttribute("n")];
//$result[$pos][$nP->getAttribute("n")]=$row[$nP->getAttribute("n")];
}
$nP = $nP->nextSibling;
}
$nParent=$nChild;
$pos++;
break;
}
}
}
return $result;
}
//получить путь по id дерева и по id записи в виде строки (поднимается вверх по дереву)
// $tid - id дерева
// $fid - id записи
// $nParent - родительский XML узел
// $db - Открытая база данных
function getPathOnId($tid,$fid,$nParent,$db)
{
if($nParent==null || $db==null) return '';
$str='';
$nChild=findFirstNodeOnAttribute($nParent, 'type', 'id', $tid);
if($nChild==null) return '';
//Пробуем найти родительский id по переданому
$nFs=findNode($nChild, 'filter');
$sql=findNode($nChild,'sql-query');
if($sql==null) return '';
$sql=getCdata($sql)->nodeValue;
if($nFs!=null)
{ $nF=$nFs->firstChild;
while($nF != null)
{
if($nF->nodeName=='column')
{
if($nF->getAttribute('n')==$nChild->getAttribute('ObjectID'))
getCdata($nF)->nodeValue=$fid;
else getCdata($nF)->nodeValue=''; //Очищаем фильтр
$sql=str_replace('${'.$nF->getAttribute("n").'}',getSQLValue($nF->getAttribute("vt"),getCdata($nF)->nodeValue),$sql);
}
$nF=$nF->nextSibling;
}
}
$res = $db->query($sql);
if($res->rowCount()>1) return ''; //В результ сете может быть только 1 запись так как фильтруем по id
while ($row = $res->fetch(PDO::FETCH_ASSOC))// $row - ассоциативный массив значений, ключи - названия столбцов
{
$fid=$row[$nChild->getAttribute('ParentID')];
//Мы не знаем id шник какого родителя ведь есть goto! (Для них должно выполняться условие их родитель всегда должен быть не пустым те. быть не на первом уровне вложенности)
$nGoto=findFirstNodeOnAttribute($nParent, 'goto', 'id', $tid);
if($nGoto!=null) $nGoto=$nGoto->parentNode;
if($nGoto!=null && $nGoto->nodeName=='type')
{
$sTmp=getPathOnId($nGoto->getAttribute('id'),$fid,$nParent,$db);
if($sTmp!='') //Не тупик ли
{
$str=$nChild->getAttribute('id').';'.$fid.';'.$str;
$str=$sTmp.$str;
break;
}
}
//Для случаяв если по goto не удалось пройтись
$nChild=$nChild->parentNode;
if($nChild!=null && $nChild->nodeName=='type' && $nChild->getAttribute('id')!='-1')
{
$str=$fid.';'.$str;
$str=$nChild->getAttribute('id').';'.$str;
$str=getPathOnId($nChild->getAttribute('id'),$fid,$nParent,$db).$str;
}
}
return $str;
}
//Получить XML дерево в виде строки (рекурсией в массив с заданным уровнем вложенности)
// $nParent - родительский XML узел
// $nParams - Первоначальные параметры фильтра (и для рекурсии)
// $db - соединение с базой данных
// $first - как вызванно через рекурсию или нет
// $path - путь к нужному узлу в виде "id node tree;id data;id node tree;id data;..."
function getTreeArray($nParent,$nParams,$db,$first,$path)
{
if($nParent==null || $db==null) return null;
$result='';
if($first) $result.='<?xml version="1.0" encoding="utf-8"?><metadata fn="2" htmlid="0">'."\n";
//Если параметры переданны как объект то парсим их в DOM дерево
if(gettype($nParams)=='string')
{
$doc = new DOMDocument();
try
{ $doc->loadXML('<metadata>'.$nParams.'</metadata>');
} catch (Exception $e)
{ $nParams=null;
}
$nParams = $doc->documentElement;
}
$mpath = explode(';', $path); //Путь к заветному узлу в виде массива
//перебераем все дочерние элементы и для каждого выполняем запрос c фильтрацией
$currNode = $nParent->firstChild; //из tree.xml
while ($currNode != null)
{
$tmpNode=$currNode; //если узел goto
if($tmpNode->nodeName=="goto") //если встретилась "зацикливалка"
{
$treeid=$tmpNode->getAttribute("id");
$tmpNode=findFirstNodeOnAttribute($tmpNode->ownerDocument->documentElement,"type","id",$treeid);
if($tmpNode==null) { $currNode = $currNode->nextSibling; continue; }
}
if($tmpNode->nodeName=="type" && $tmpNode->getAttribute("hide") != '1')
{
$treeid=$tmpNode->getAttribute("id"); //Идентификатор XML узла
//Пропускаем узлы которые не в заданном пути
if(!(count($mpath)>=3 && $mpath[0]!=$treeid))
{
$caption=$tmpNode->getAttribute("c"); //Название поля для заголовка
//$sql=getSQL($nParent,$tmpNode);
$sql=getSQL($nParams,$tmpNode);
if(gettype($_SESSION['USER_ID'])=='string')
$sql=str_replace('${user_id}',$_SESSION['USER_ID']=='' ? 'null' : '\''.$_SESSION['USER_ID'].'\'',$sql);
else
$sql=str_replace('${user_id}',$_SESSION['USER_ID']=='' ? 'null' : $_SESSION['USER_ID'],$sql);
$res=null;
try
{ $res=$db->query($sql);
} catch (Exception $e)
{ return null;
}
while ($row = $res->fetch(PDO::FETCH_ASSOC))
{
if(array_key_exists('id', $row)) $fid=$row['id']; else $fid=''; //id записи
if(count($mpath)>=3 && $mpath[1]!=$fid) continue; //Пропускаем записи которые не в пути
if(array_key_exists('icon_id', $row)) $iid=$row['icon_id']; else $iid=''; //id значка
if(array_key_exists($caption, $row)) $val=$row[$caption]; else $val=''; //Заголовок
$visible='';
if($tmpNode->getAttribute("visible")=="0") $visible=' visible="0" ';
//Для проверки есть ли дети составляем XML запрос и отправляем в вункцию как будто он пришел от клиента
//c - Есть ли под узлы по умолчанию есть
//fid - id записи
//iid - id иконки
//treeid - id ветки дерева
//ObjectID - название поля с уникальным идентификатором записи
//сохраняем параметры фильтра для дочерних элементов с текщим состоянием
//перебираем фильтры которые должны быть заполненны для каждого узла даные для фильтра беруться из результ сета
$rСol='<columns>'."\n";
//считываем название поля и находим данные в результсете
$nColumn = findFirstNode($tmpNode, 'columns'); //tree.xml
if($nColumn!=null) $nColumn=$nColumn->firstChild;
while ($nColumn != null)
{
if($nColumn->nodeName=="param")
{
$fname=$nColumn->getAttribute("n");
if(array_key_exists($fname, $row)) //Если поле есть в результсете
{ //getCdata($nColumn)->nodeValue=$row[$fname]; //Заполняем парамерт значением для рекурсии при следующей итерации затрётся
$fval=$row[$fname];
}else $fval=getCdataValue($nColumn);
$rСol.='<param n="'.$fname.'"><![CDATA['.$fval.']]></param>'."\n";
}
$nColumn = $nColumn->nextSibling;
}
$rСol.='</columns>'."\n";
$path='';
for($i=1;$i<(count($mpath)-1)/2;$i++) $path.=$mpath[i].';'.$mpath[i].';'; //Оставшийся путь минус текущий
// !!! Рекурсия !!!
$rSub=getTreeArray($tmpNode,$rСol,$db,false,$path);
$result.='<tree c="'.($rSub == '' ? '0' : '1').'" fid="'.$fid.'" iid="'.$iid.'" treeid="'.$treeid.'" t="'.$tmpNode->getAttribute("n").'" ObjectID="'.$tmpNode->getAttribute("ObjectID").'"'.$visible.'>'."\n";
$result.='<![CDATA['.$val.']]>'."\n";
$result.=$rСol;
$result.=$rSub;
$result.='</tree>'."\n";
$rSub='';
}
$res->closeCursor();
}
}
$currNode = $currNode->nextSibling;
}
if($first) $result.='</metadata>';
return $result; //XML строка
}
//Похожее на верхнее только получаем XML карту сайта
// $nParent - родительский XML узел
// $nParams - Первоначальные параметры фильтра (и для рекурсии)
// $db - соединение с базой данных
// $first - как вызванно через рекурсию или нет
function getSiteMap($nParent,$nParams,$db,$first,$path)
{
if($nParent==null || $db==null) return null;
$result='';
if($first) $result.='<?xml version="1.0" encoding="utf-8"?><urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">'."\n";
//Если параметры переданны как объект то парсим их в DOM дерево
if(gettype($nParams)=='string')
{
$doc = new DOMDocument();
try
{ $doc->loadXML('<metadata>'.$nParams.'</metadata>');
} catch (Exception $e)
{ $nParams=null;
}
$nParams = $doc->documentElement;
}
//перебераем все дочерние элементы и для каждого выполняем запрос c фильтрацией
$currNode = $nParent->firstChild; //из tree.xml
while ($currNode != null)
{
$tmpNode=$currNode; //если узел goto
if($tmpNode->nodeName=="goto") //если встретилась "зацикливалка"
{
$treeid=$tmpNode->getAttribute("id");
$tmpNode=findFirstNodeOnAttribute($tmpNode->ownerDocument->documentElement,"type","id",$treeid);
if($tmpNode==null) { $currNode = $currNode->nextSibling; continue; }
}
if($tmpNode->nodeName=="type")
{
$treeid=$tmpNode->getAttribute("id"); //Идентификатор XML узла
$sql=getSQL($nParams,$tmpNode);
if(isset($_SESSION['USER_ID']))
{
if(gettype($_SESSION['USER_ID'])=='string')
$sql=str_replace('${user_id}',$_SESSION['USER_ID']=='' ? 'null' : '\''.$_SESSION['USER_ID'].'\'',$sql);
else
$sql=str_replace('${user_id}',$_SESSION['USER_ID']=='' ? 'null' : $_SESSION['USER_ID'],$sql);
}
$res=null;
try
{ $res=$db->query($sql);
} catch (Exception $e)
{ return null;
}
while ($row = $res->fetch(PDO::FETCH_ASSOC))
{
if(array_key_exists('id', $row)) { $fid=$row['id']; } else { $fid=''; } //id записи
if(array_key_exists('seq', $row)) { $date=date('Y-m-d',946620000+$row['seq']); } else { $date=date('Y-m-d'); } //Дата модификации страницы
if(array_key_exists('url', $row)) { $url=$row['url']; } else { $url=''; } //id записи
//сохраняем параметры фильтра для дочерних элементов с текщим состоянием
//перебираем фильтры которые должны быть заполненны для каждого узла даные для фильтра беруться из результ сета
$rСol='<columns>'."\n";
//считываем название поля и находим данные в результсете
$nColumn = findFirstNode($tmpNode, 'columns'); //tree.xml
if($nColumn!=null) $nColumn=$nColumn->firstChild;
while ($nColumn != null)
{
if($nColumn->nodeName=="param")
{
$fname=$nColumn->getAttribute("n");
if(array_key_exists($fname, $row)) //Если поле есть в результсете
{ //getCdata($nColumn)->nodeValue=$row[$fname]; //Заполняем парамерт значением для рекурсии при следующей итерации затрётся
$fval=$row[$fname];
}else
{ $fval=getCdataValue($nColumn);
}
$rСol.='<param n="'.$fname.'"><![CDATA['.$fval.']]></param>'."\n";
}
$nColumn = $nColumn->nextSibling;
}
$rСol.='</columns>'."\n";
if($url=='')
{ $url=getHashFromPath($path.$treeid.';'.$fid.';');
}
$result.=' <url>'."\n";
$result.=' <loc>http://'.$_SERVER["SERVER_NAME"].'/shop/'.$url.'.html</loc>'."\n";
$result.=' <lastmod>'.$date.'</lastmod>'."\n";
$result.=' <changefreq>daily</changefreq>'."\n";
$result.=' </url>'."\n";
// !!! Рекурсия !!!
$result.=getSiteMap($tmpNode,$rСol,$db,false,$path.$treeid.';'.$fid.';');
}
$res->closeCursor();
}
$currNode = $currNode->nextSibling;
}
if($first) $result.='</urlset>';
return $result; //XML строка
}

View File

@ -149,17 +149,20 @@ function TMenu(v_obj,v_scr,v_treepath) //Горизонтальное меню
xmlHttpRequest.responseXML=CreateXMLDOC(xmlHttpRequest.responseText);
//загрузился xml документ начинаем его разбирать (по id функции в документе)
var xmldoc = xmlHttpRequest.responseXML;
if(xmldoc==null) alert(_('Wrong_XML_document')+"!\n"+xmlHttpRequest.responseText);
var node = xmldoc.documentElement;
//alert("Данные=\n"+xmlHttpRequest.responseText);
if((node==null)||(node.getAttribute("fn")==null)) alert(_('Error')+"\n"+_('No_data')+"!\n"+xmlHttpRequest.responseText);
let xmldoc = xmlHttpRequest.responseXML;
if(xmldoc==null){
alert2(_('Alert'),_('Wrong_XML_document')+"!\n"+xmlHttpRequest.responseText);
return;
}
let node = xmldoc.documentElement;
//alert2(_('Alert'),"Данные=\n"+xmlHttpRequest.responseText);
if((node==null)||(node.getAttribute("fn")==null)) alert2(_('Alert'),_('Error')+"\n"+_('No_data')+"!\n"+xmlHttpRequest.responseText);
else
{
var fn = node.getAttribute("fn");
if (fn=='0')
{
alert(findFirstNode(node,"#cdata-section").nodeValue);
alert2(_('Alert'),findFirstNode(node,"#cdata-section").nodeValue);
}else if (fn=='1')
{
var tn=this.findNode(node.getAttribute("htmlid")); //Родительский узел
@ -180,11 +183,11 @@ function TMenu(v_obj,v_scr,v_treepath) //Горизонтальное меню
var cnt=document.getElementById(this.m_pr+tn.htmlid+'tb');
if(cnt!=null) this.createList(tn.htmlid); //Создать HTML кнопки
}else
alert("Unknown function! fn=\""+fn+"\"" );
alert2(_('Alert'),"Unknown function! fn=\""+fn+"\"" );
}
}else
{
alert(_('Failed_to_get_data')+"\n URL: "+url+"\n" + xmlHttpRequest.statusText);
alert2(_('Alert'),_('Failed_to_get_data')+"\n URL: "+url+"\n" + xmlHttpRequest.statusText);
}
}
};
@ -546,7 +549,7 @@ function TMenu(v_obj,v_scr,v_treepath) //Горизонтальное меню
//Добавить слушателя нажатия на кнопку
this.addListener=function(listener)
{ if(listener.OnClickNode==null) alert('У объекта нет функции "OnClickNode()"!');
{ if(listener.OnClickNode==null) alert2(_('Alert'),'У объекта нет функции "OnClickNode()"!');
this.m_ls[this.m_ls.length]=listener;
};
//Удалить слушателя
@ -646,27 +649,30 @@ function TTree(v_obj,v_pr,v_scr,v_pth,v_imgsize) //Дерево
xmlHttpRequest.responseXML=CreateXMLDOC(xmlHttpRequest.responseText);
//загрузился xml документ начинаем его разбирать (по id функции в документе)
var xmldoc = xmlHttpRequest.responseXML;
if(xmldoc==null) alert(_('Wrong_XML_document')+"!\n"+xmlHttpRequest.responseText);
var node = xmldoc.documentElement;
if((node==null)||(node.getAttribute("fn")==null)) alert(_('Error')+"\n"+_('No_data')+"!\n"+xmlHttpRequest.responseText);
let xmldoc = xmlHttpRequest.responseXML;
if(xmldoc==null){
alert2(_('Alert'),_('Wrong_XML_document')+"!\n"+xmlHttpRequest.responseText);
return;
}
let node = xmldoc.documentElement;
if((node==null)||(node.getAttribute("fn")==null)) alert2(_('Alert'),_('Error')+"\n"+_('No_data')+"!\n"+xmlHttpRequest.responseText);
else
{
var fn = node.getAttribute("fn");
if (fn==0)
{
alert(findFirstNode(node,"#cdata-section").nodeValue);
alert2(_('Alert'),findFirstNode(node,"#cdata-section").nodeValue);
}else
if (fn==1)
{
this.addNode(node);
this.OpenTreeOnPath(this.m_path);
}else
alert("Unknown function! fn=\""+fn+"\"" );
alert2(_('Alert'),"Unknown function! fn=\""+fn+"\"" );
}
}else
{
alert(_('Failed_to_get_data')+"\n URL: "+url+"\n" + xmlHttpRequest.statusText);
alert2(_('Alert'),_('Failed_to_get_data')+"\n URL: "+url+"\n" + xmlHttpRequest.statusText);
}
}
};
@ -899,7 +905,7 @@ function TTree(v_obj,v_pr,v_scr,v_pth,v_imgsize) //Дерево
//Добавить слушателя
this.addListener=function(listener)
{ if(listener.OnClickNode==null) alert('У объекта нет функции "OnClickNode()"!');
{ if(listener.OnClickNode==null) alert2(_('Alert'),'У объекта нет функции "OnClickNode()"!');
this.m_ls[this.m_ls.length]=listener;
};
//Удалить слушателя
@ -911,7 +917,7 @@ function TTree(v_obj,v_pr,v_scr,v_pth,v_imgsize) //Дерево
};
//Добавить слушателя
this.addListenerLoad=function(listener)
{ if(listener.OnLoadNode==null) alert('У объекта нет функции "OnLoadNode(node)"!');
{ if(listener.OnLoadNode==null) alert2(_('Alert'),'У объекта нет функции "OnLoadNode(node)"!');
this.m_lsl[this.m_lsl.length]=listener;
};
//Удалить слушателя

View File

@ -12,7 +12,7 @@
//sleep(1); //Тестирование с задержкой
//require_once("../../config.php"); Должно быть обьявлено во внешнем файле
require_once("tools.php");
require_once("treetools.php");
/**
* Отправить клиенту информацию о ошибке
@ -34,7 +34,7 @@
*/
function fnGetData($treeNode,$currNode)
{
$sql=getSQL($treeNode,$currNode);
$sql=getSQLFromP($treeNode,$currNode);
if(gettype($_SESSION['USER_ID'])=='string')
$sql=str_replace('${_user_id}',$_SESSION['USER_ID']=='' ? 'null' : '\''.$_SESSION['USER_ID'].'\'',$sql);

526
metadata/tree/treetools.php Normal file
View File

@ -0,0 +1,526 @@
<?php
function getSQLFromP0(){
echo '+++wwwwwwwww++++++';
}
/**
* Обвернуть строку в кавычки в соответствии с типом.
* @param String $t Тип
* @param String $v Значение
* @return String Строка
*/
function getSQLValue($t,$v)
{
if($t=='object' && gettype($v)=='string') $t='string'; //Если id шники uuid
if($t=='object')
{ if (($v=='-1')||($v=='')) $v='NULL';
}else
if($t=='i4' || $t=='integer')
{ if($v=='') $v='NULL';
}else
if($t=='f8')
{ if($v=='')$v='NULL';
$v=str_replace(',','.',$v); //Разделитель целой и дробной части точка
}else
if($t=='b')
{ if($v=='') $v='NULL'; else
if($v=='1') $v='true'; else
if($v=='0') $v='false';
}else
if($t=='string' || $t=='dateTime' || $t=='date')
{ if($v=='')
{ $v='NULL';
}else
{ $v=str_replace('\'','\\\'',$v); //так как в SQL строку вставляется
$v='\''.$v.'\'';
}
}else
$v='\''.$v.'\'';
return $v;
}
/** Перенести параметры из родительского в sql строку дочернего элемента
* @param object $nParent Родительский узел
* @param object $nChild Дочерний узел
* @return string
*/
function getSQLFromP($nParent,$nChild)
{
if($nChild==null) return '';
$nPs=findNode($nParent, 'columns');
$nFs=findNode($nChild, 'filter');
//Переносим значения в фильтр
if($nFs!=null)
{
if($nPs!=null) $nP=$nPs->firstChild; else $nP=null;
while ($nP != null)
{
if ($nP->nodeName=='param')
{
$val=getCdata($nP)->nodeValue;
$nF=findNodeOnAttribute($nFs, 'column', 'pn', $nP->getAttribute("n"));
if($nF!=null) getCdata($nF)->nodeValue=$val;
}
$nP = $nP->nextSibling;
}
}
//Переносим значения в SQL запрос из фильтра
$sql=getCdataValue(findNode($nChild,'sql-query'));
$nFs=findNode($nChild, 'filter');
if($nFs!=null)
{ $nF=$nFs->firstChild;
while($nF != null)
{
if($nF->nodeName=='column')
{
$sql=str_replace('${'.$nF->getAttribute("n").'}',getSQLValue($nF->getAttribute("vt"),getCdata($nF)->nodeValue),$sql);
}
$nF=$nF->nextSibling;
}
}
return $sql;
}
//Функция по заданному пути выдаёт все под пути в виде асоциативного массива (тоесть + 1 уровень дерева)
//$db - PDO соединение с базой данных
//$path - путь "id дерева из XML; id записи из базы; id дерева из XML; id записи из базы;"
//$nParent - родительский узел нужен для рекурсии по умолчанию ставить null
function GetSubNodes($path,$nParent,&$title)
{
global $v_db;
if($nParent==null) return array();
$dt=''; //Разделитель для заголовка смотри ниже по тексту "->"
//По заданному пути спускаемся к нужному узлу дерева
$mas=split(';',$path);
for($i=0;$i<(count($mas)-1)/2;$i++)
{
$nChild=findNodeOnAttribute($nParent, 'type', 'id', $mas[$i*2]); //Ищем нужную ветку XML дерева
$sql=getSQLFromP($nParent,$nChild); //Выбираем параметры из родительского в дочерний потом из текущего в sql запрос
//Выполняем и ищем запись с нужным id
$res = $v_db->query($sql);
while ($row = $res->fetch(PDO::FETCH_ASSOC))// $row - ассоциативный массив значений, ключи - названия столбцов
{
if($row[$nChild->getAttribute('ObjectID')]==$mas[$i*2+1])
{
$title.=$dt.$row[$nChild->getAttribute('c')]; //Чтоб отобразить заголовок в виде пути
$dt='->';
//Записываем параметры из текущей записи в параметры для передачи в в следующую итерацию
$nPs=findNode($nChild,'columns');
$nP=$nPs->firstChild;
while ($nP != null)
{
if ($nP->nodeName=='param')
getCdata($nP)->nodeValue=$row[$nP->getAttribute("n")];
$nP = $nP->nextSibling;
}
$nParent=$nChild;
break;
}
}
}
//Добрались до самого последнего элемента пути теперь выбераем из всех дочерних узлов
$result=array();
$nChild=$nParent->firstChild;
while ($nChild != null)
{
if($nChild->nodeName=='goto')
{
$nType=findFirstNodeOnAttribute($nChild->ownerDocument->documentElement,"type","id",$nChild->getAttribute("id"));
if($nType==null) { $nChild = $nChild->nextSibling; continue; }
}else $nType=$nChild;
if ($nType->nodeName=='type')
{
$sql=getSQLFromP($nParent,$nType);//Получаем SQL запрос перенося параметры из родительского в дочерний а потом в SQL дочернего
$res = $v_db->query($sql);
while ($row = $res->fetch(PDO::FETCH_ASSOC))// $row - ассоциативный массив значений, ключи - названия столбцов
{
$cnt=count($result);
$result[$cnt]['name']=$row[$nType->getAttribute('c')];
$result[$cnt]['path']=$path.$nType->getAttribute('id').';'.$row[$nChild->getAttribute('ObjectID')].';';
}
}
$nChild = $nChild->nextSibling;
}
return $result;
}
//Из пути получить асоциативный массив заголовков + путь
//$path - путь "id дерева из XML; id записи из базы; id дерева из XML; id записи из базы;"
//$nParent - XML узел с которого будет начинаться поиск
//$db - База данных PDO
function getTXTPath($path,$nParent,$db)
{
$result=array(); $pos=0;
$mas=explode(';',$path);
for($i=0;$i<(count($mas)-1)/2;$i++)
{
$nChild=findNodeOnAttribute($nParent, 'type', 'id', $mas[$i*2]); //Ищем нужную ветку XML дерева
if($nChild==null) $nChild=findFirstNodeOnAttribute($nParent->ownerDocument->documentElement, 'type', 'id', $mas[$i*2]);
if($nChild==null) continue;
//print $nParent->ownerDocument->saveXML($nParent).'<br>';
$sql=getSQLFromP($nParent,$nChild); //Выбираем параметры из родительского в дочерний потом из текущего в sql запрос
if(gettype($_SESSION['USER_ID'])=='string')
$sql=str_replace('${user_id}',$_SESSION['USER_ID']=='' ? 'null' : '\''.$_SESSION['USER_ID'].'\'',$sql);
else
$sql=str_replace('${user_id}',$_SESSION['USER_ID']=='' ? 'null' : $_SESSION['USER_ID'],$sql);
//print $sql.'<br>';
//Выполняем и ищем запись с нужным id
$res = $db->query($sql);
while ($row = $res->fetch(PDO::FETCH_ASSOC))// $row - ассоциативный массив значений, ключи - названия столбцов
{
if($row[$nChild->getAttribute('ObjectID')]==$mas[$i*2+1])
{
$result[$pos]['name']=$row[$nChild->getAttribute('c')];
$result[$pos]['path']=$mas[$i*2].';'.$mas[$i*2+1].';';
//Записываем параметры из текущей записи в параметры для передачи в в следующую итерацию
$nP=findNode($nChild, 'columns');
if($nP!=null) $nP=$nP->firstChild;
while ($nP != null)
{
if ($nP->nodeName=='param')
{
if(isset($row[$nP->getAttribute("n")]))
getCdata($nP)->nodeValue=$row[$nP->getAttribute("n")];
if(isset($row[$nP->getAttribute("n")]))
$result[$pos][$nP->getAttribute("n")]=$row[$nP->getAttribute("n")];
//getCdata($nP)->nodeValue=$row[$nP->getAttribute("n")];
//$result[$pos][$nP->getAttribute("n")]=$row[$nP->getAttribute("n")];
}
$nP = $nP->nextSibling;
}
$nParent=$nChild;
$pos++;
break;
}
}
}
return $result;
}
//получить путь по id дерева и по id записи в виде строки (поднимается вверх по дереву)
// $tid - id дерева
// $fid - id записи
// $nParent - родительский XML узел
// $db - Открытая база данных
function getPathOnId($tid,$fid,$nParent,$db)
{
if($nParent==null || $db==null) return '';
$str='';
$nChild=findFirstNodeOnAttribute($nParent, 'type', 'id', $tid);
if($nChild==null) return '';
//Пробуем найти родительский id по переданому
$nFs=findNode($nChild, 'filter');
$sql=findNode($nChild,'sql-query');
if($sql==null) return '';
$sql=getCdata($sql)->nodeValue;
if($nFs!=null)
{ $nF=$nFs->firstChild;
while($nF != null)
{
if($nF->nodeName=='column')
{
if($nF->getAttribute('n')==$nChild->getAttribute('ObjectID'))
getCdata($nF)->nodeValue=$fid;
else getCdata($nF)->nodeValue=''; //Очищаем фильтр
$sql=str_replace('${'.$nF->getAttribute("n").'}',getSQLValue($nF->getAttribute("vt"),getCdata($nF)->nodeValue),$sql);
}
$nF=$nF->nextSibling;
}
}
$res = $db->query($sql);
if($res->rowCount()>1) return ''; //В результ сете может быть только 1 запись так как фильтруем по id
while ($row = $res->fetch(PDO::FETCH_ASSOC))// $row - ассоциативный массив значений, ключи - названия столбцов
{
$fid=$row[$nChild->getAttribute('ParentID')];
//Мы не знаем id шник какого родителя ведь есть goto! (Для них должно выполняться условие их родитель всегда должен быть не пустым те. быть не на первом уровне вложенности)
$nGoto=findFirstNodeOnAttribute($nParent, 'goto', 'id', $tid);
if($nGoto!=null) $nGoto=$nGoto->parentNode;
if($nGoto!=null && $nGoto->nodeName=='type')
{
$sTmp=getPathOnId($nGoto->getAttribute('id'),$fid,$nParent,$db);
if($sTmp!='') //Не тупик ли
{
$str=$nChild->getAttribute('id').';'.$fid.';'.$str;
$str=$sTmp.$str;
break;
}
}
//Для случаяв если по goto не удалось пройтись
$nChild=$nChild->parentNode;
if($nChild!=null && $nChild->nodeName=='type' && $nChild->getAttribute('id')!='-1')
{
$str=$fid.';'.$str;
$str=$nChild->getAttribute('id').';'.$str;
$str=getPathOnId($nChild->getAttribute('id'),$fid,$nParent,$db).$str;
}
}
return $str;
}
//Получить XML дерево в виде строки (рекурсией в массив с заданным уровнем вложенности)
// $nParent - родительский XML узел
// $nParams - Первоначальные параметры фильтра (и для рекурсии)
// $db - соединение с базой данных
// $first - как вызванно через рекурсию или нет
// $path - путь к нужному узлу в виде "id node tree;id data;id node tree;id data;..."
function getTreeArray($nParent,$nParams,$db,$first,$path)
{
if($nParent==null || $db==null) return null;
$result='';
if($first) $result.='<?xml version="1.0" encoding="utf-8"?><metadata fn="2" htmlid="0">'."\n";
//Если параметры переданны как объект то парсим их в DOM дерево
if(gettype($nParams)=='string')
{
$doc = new DOMDocument();
try
{ $doc->loadXML('<metadata>'.$nParams.'</metadata>');
} catch (Exception $e)
{ $nParams=null;
}
$nParams = $doc->documentElement;
}
$mpath = explode(';', $path); //Путь к заветному узлу в виде массива
//перебераем все дочерние элементы и для каждого выполняем запрос c фильтрацией
$currNode = $nParent->firstChild; //из tree.xml
while ($currNode != null)
{
$tmpNode=$currNode; //если узел goto
if($tmpNode->nodeName=="goto") //если встретилась "зацикливалка"
{
$treeid=$tmpNode->getAttribute("id");
$tmpNode=findFirstNodeOnAttribute($tmpNode->ownerDocument->documentElement,"type","id",$treeid);
if($tmpNode==null) { $currNode = $currNode->nextSibling; continue; }
}
if($tmpNode->nodeName=="type" && $tmpNode->getAttribute("hide") != '1')
{
$treeid=$tmpNode->getAttribute("id"); //Идентификатор XML узла
//Пропускаем узлы которые не в заданном пути
if(!(count($mpath)>=3 && $mpath[0]!=$treeid))
{
$caption=$tmpNode->getAttribute("c"); //Название поля для заголовка
//$sql=getSQLFromP($nParent,$tmpNode);
$sql=getSQLFromP($nParams,$tmpNode);
if(gettype($_SESSION['USER_ID'])=='string')
$sql=str_replace('${user_id}',$_SESSION['USER_ID']=='' ? 'null' : '\''.$_SESSION['USER_ID'].'\'',$sql);
else
$sql=str_replace('${user_id}',$_SESSION['USER_ID']=='' ? 'null' : $_SESSION['USER_ID'],$sql);
$res=null;
try
{ $res=$db->query($sql);
} catch (Exception $e)
{ return null;
}
while ($row = $res->fetch(PDO::FETCH_ASSOC))
{
if(array_key_exists('id', $row)) $fid=$row['id']; else $fid=''; //id записи
if(count($mpath)>=3 && $mpath[1]!=$fid) continue; //Пропускаем записи которые не в пути
if(array_key_exists('icon_id', $row)) $iid=$row['icon_id']; else $iid=''; //id значка
if(array_key_exists($caption, $row)) $val=$row[$caption]; else $val=''; //Заголовок
$visible='';
if($tmpNode->getAttribute("visible")=="0") $visible=' visible="0" ';
//Для проверки есть ли дети составляем XML запрос и отправляем в вункцию как будто он пришел от клиента
//c - Есть ли под узлы по умолчанию есть
//fid - id записи
//iid - id иконки
//treeid - id ветки дерева
//ObjectID - название поля с уникальным идентификатором записи
//сохраняем параметры фильтра для дочерних элементов с текщим состоянием
//перебираем фильтры которые должны быть заполненны для каждого узла даные для фильтра беруться из результ сета
$rСol='<columns>'."\n";
//считываем название поля и находим данные в результсете
$nColumn = findFirstNode($tmpNode, 'columns'); //tree.xml
if($nColumn!=null) $nColumn=$nColumn->firstChild;
while ($nColumn != null)
{
if($nColumn->nodeName=="param")
{
$fname=$nColumn->getAttribute("n");
if(array_key_exists($fname, $row)) //Если поле есть в результсете
{ //getCdata($nColumn)->nodeValue=$row[$fname]; //Заполняем парамерт значением для рекурсии при следующей итерации затрётся
$fval=$row[$fname];
}else $fval=getCdataValue($nColumn);
$rСol.='<param n="'.$fname.'"><![CDATA['.$fval.']]></param>'."\n";
}
$nColumn = $nColumn->nextSibling;
}
$rСol.='</columns>'."\n";
$path='';
for($i=1;$i<(count($mpath)-1)/2;$i++) $path.=$mpath[i].';'.$mpath[i].';'; //Оставшийся путь минус текущий
// !!! Рекурсия !!!
$rSub=getTreeArray($tmpNode,$rСol,$db,false,$path);
$result.='<tree c="'.($rSub == '' ? '0' : '1').'" fid="'.$fid.'" iid="'.$iid.'" treeid="'.$treeid.'" t="'.$tmpNode->getAttribute("n").'" ObjectID="'.$tmpNode->getAttribute("ObjectID").'"'.$visible.'>'."\n";
$result.='<![CDATA['.$val.']]>'."\n";
$result.=$rСol;
$result.=$rSub;
$result.='</tree>'."\n";
$rSub='';
}
$res->closeCursor();
}
}
$currNode = $currNode->nextSibling;
}
if($first) $result.='</metadata>';
return $result; //XML строка
}
//Похожее на верхнее только получаем XML карту сайта
// $nParent - родительский XML узел
// $nParams - Первоначальные параметры фильтра (и для рекурсии)
// $db - соединение с базой данных
// $first - как вызванно через рекурсию или нет
function getSiteMap($nParent,$nParams,$db,$first,$path)
{
if($nParent==null || $db==null) return null;
$result='';
if($first) $result.='<?xml version="1.0" encoding="utf-8"?><urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">'."\n";
//Если параметры переданны как объект то парсим их в DOM дерево
if(gettype($nParams)=='string')
{
$doc = new DOMDocument();
try
{ $doc->loadXML('<metadata>'.$nParams.'</metadata>');
} catch (Exception $e)
{ $nParams=null;
}
$nParams = $doc->documentElement;
}
//перебераем все дочерние элементы и для каждого выполняем запрос c фильтрацией
$currNode = $nParent->firstChild; //из tree.xml
while ($currNode != null)
{
$tmpNode=$currNode; //если узел goto
if($tmpNode->nodeName=="goto") //если встретилась "зацикливалка"
{
$treeid=$tmpNode->getAttribute("id");
$tmpNode=findFirstNodeOnAttribute($tmpNode->ownerDocument->documentElement,"type","id",$treeid);
if($tmpNode==null) { $currNode = $currNode->nextSibling; continue; }
}
if($tmpNode->nodeName=="type")
{
$treeid=$tmpNode->getAttribute("id"); //Идентификатор XML узла
$sql=getSQLFromP($nParams,$tmpNode);
if(isset($_SESSION['USER_ID']))
{
if(gettype($_SESSION['USER_ID'])=='string')
$sql=str_replace('${user_id}',$_SESSION['USER_ID']=='' ? 'null' : '\''.$_SESSION['USER_ID'].'\'',$sql);
else
$sql=str_replace('${user_id}',$_SESSION['USER_ID']=='' ? 'null' : $_SESSION['USER_ID'],$sql);
}
$res=null;
try
{ $res=$db->query($sql);
} catch (Exception $e)
{ return null;
}
while ($row = $res->fetch(PDO::FETCH_ASSOC))
{
if(array_key_exists('id', $row)) { $fid=$row['id']; } else { $fid=''; } //id записи
if(array_key_exists('seq', $row)) { $date=date('Y-m-d',946620000+$row['seq']); } else { $date=date('Y-m-d'); } //Дата модификации страницы
if(array_key_exists('url', $row)) { $url=$row['url']; } else { $url=''; } //id записи
//сохраняем параметры фильтра для дочерних элементов с текщим состоянием
//перебираем фильтры которые должны быть заполненны для каждого узла даные для фильтра беруться из результ сета
$rСol='<columns>'."\n";
//считываем название поля и находим данные в результсете
$nColumn = findFirstNode($tmpNode, 'columns'); //tree.xml
if($nColumn!=null) $nColumn=$nColumn->firstChild;
while ($nColumn != null)
{
if($nColumn->nodeName=="param")
{
$fname=$nColumn->getAttribute("n");
if(array_key_exists($fname, $row)) //Если поле есть в результсете
{ //getCdata($nColumn)->nodeValue=$row[$fname]; //Заполняем парамерт значением для рекурсии при следующей итерации затрётся
$fval=$row[$fname];
}else
{ $fval=getCdataValue($nColumn);
}
$rСol.='<param n="'.$fname.'"><![CDATA['.$fval.']]></param>'."\n";
}
$nColumn = $nColumn->nextSibling;
}
$rСol.='</columns>'."\n";
if($url=='')
{ $url=getHashFromPath($path.$treeid.';'.$fid.';');
}
$result.=' <url>'."\n";
$result.=' <loc>http://'.$_SERVER["SERVER_NAME"].'/shop/'.$url.'.html</loc>'."\n";
$result.=' <lastmod>'.$date.'</lastmod>'."\n";
$result.=' <changefreq>daily</changefreq>'."\n";
$result.=' </url>'."\n";
// !!! Рекурсия !!!
$result.=getSiteMap($tmpNode,$rСol,$db,false,$path.$treeid.';'.$fid.';');
}
$res->closeCursor();
}
$currNode = $currNode->nextSibling;
}
if($first) $result.='</urlset>';
return $result; //XML строка
}