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).'
'; $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.'
'; //Выполняем и ищем запись с нужным 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.=''."\n"; //Если параметры переданны как объект то парсим их в DOM дерево if(gettype($nParams)=='string') { $doc = new DOMDocument(); try { $doc->loadXML(''.$nParams.''); } 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=''."\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.=''."\n"; } $nColumn = $nColumn->nextSibling; } $rСol.=''."\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.=''."\n"; $result.=''."\n"; $result.=$rСol; $result.=$rSub; $result.=''."\n"; $rSub=''; } $res->closeCursor(); } } $currNode = $currNode->nextSibling; } if($first) $result.=''; 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.=''."\n"; //Если параметры переданны как объект то парсим их в DOM дерево if(gettype($nParams)=='string') { $doc = new DOMDocument(); try { $doc->loadXML(''.$nParams.''); } 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=''."\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.=''."\n"; } $nColumn = $nColumn->nextSibling; } $rСol.=''."\n"; if($url=='') { $url=getHashFromPath($path.$treeid.';'.$fid.';'); } $result.=' '."\n"; $result.=' http://'.$_SERVER["SERVER_NAME"].'/shop/'.$url.'.html'."\n"; $result.=' '.$date.''."\n"; $result.=' daily'."\n"; $result.=' '."\n"; // !!! Рекурсия !!! $result.=getSiteMap($tmpNode,$rСol,$db,false,$path.$treeid.';'.$fid.';'); } $res->closeCursor(); } $currNode = $currNode->nextSibling; } if($first) $result.=''; return $result; //XML строка }