MkFramework
 All Data Structures Functions
sgbd_xml.php
1 <?php
2 /*
3 This file is part of Mkframework.
4 
5 Mkframework is free software: you can redistribute it and/or modify
6 it under the terms of the GNU Lesser General Public License as published by
7 the Free Software Foundation, either version 3 of the License.
8 
9 Mkframework is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU Lesser General Public License for more details.
13 
14 You should have received a copy of the GNU Lesser General Public License
15 along with Mkframework. If not, see <http://www.gnu.org/licenses/>.
16 
17 */
18 class sgbd_xml extends abstract_sgbd{
19 
20  public static function getInstance($sConfig){
21  return self::_getInstance(__CLASS__,$sConfig);
22  }
23 
24  public function findMany($tSql,$sClassRow){
25  $tRows=$this->query($this->bind($tSql),$sClassRow);
26 
27  if(!$tRows){
28  return null;
29  }
30 
31  return $tRows;
32  }
33  public function findManySimple($tSql,$sClassRow){
34  return $this->findMany($tSql,$sClassRow);
35  }
36  public function findOne($tSql,$sClassRow){
37  $tRs=$this->query($this->bind($tSql),$sClassRow);
38 
39  if(empty($tRs)){
40  return null;
41  }
42 
43  return $tRs[0];
44  }
45  public function findOneSimple($tSql,$sClassRow){
46  return $this->findOne($tSql,$sClassRow);
47  }
48  public function execute($tSql){
49  return $this->query($this->bind($tSql));
50  }
51 
52  public function update($sTable,$tProperty,$tWhere){
53  $iId=$this->getIdFromTab($tWhere);
54 
55  $sFile=$this->_tConfig[$this->_sConfig.'.database'].$sTable.'/'.$iId.'.xml';
56  $oXml=simplexml_load_file($sFile);
57  $tXml=(array) $oXml;
58 
59  //remove index
60  $this->removeRowFromAllIndex($sTable,$tXml);
61 
62 
63  foreach($tProperty as $sVar => $sVal){
64  $tXml[$sVar]=(string)$sVal;
65  }
66 
67  //add in index
68  $this->addRowInAllIndex($sTable,$tXml);
69 
70  $this->save($tXml,$sFile);
71  }
72  public function insert($sTable,$tProperty){
73  $iId=$this->getMaxId($sTable);
74 
75  $tMax=array('max'=>($iId+1));
76 
77  $tProperty['id']=$iId;
78 
79  $sFile=$this->_tConfig[$this->_sConfig.'.database'].$sTable.'/'.$iId.'.xml';
80  $this->save($tProperty,$sFile);
81  $sFileMax=$this->_tConfig[$this->_sConfig.'.database'].$sTable.'/max.xml';
82  $this->save($tMax,$sFileMax);
83 
84  $this->addRowInAllIndex($sTable,$tProperty);
85 
86  return $iId;
87  }
88  public function delete($sTable,$tWhere){
89  $iId=$this->getIdFromTab($tWhere);
90 
91  $sFile=$this->_tConfig[$this->_sConfig.'.database'].$sTable.'/'.$iId.'.xml';
92  $oXml=simplexml_load_file($sFile);
93  $tXml=(array) $oXml;
94 
95  //remove index
96  $this->removeRowFromAllIndex($sTable,$tXml);
97 
98  unlink($this->_tConfig[$this->_sConfig.'.database'].$sTable.'/'.$iId.'.xml');
99  }
100 
101  public function getListColumn($sTable){
102 
103  $sFile=$this->_tConfig[$this->_sConfig.'.database'].$sTable.'/structure.xml';
104  $oXml=simplexml_load_file($sFile);
105 
106  $tXml=(array)$oXml;
107  return $tXml['colonne'];
108 
109  }
110  public function getListTable(){
111  $oDir=new _dir( $this->_tConfig[$this->_sConfig.'.database']);
112  $tDir=$oDir->getList();
113  $tSDir=array();
114  foreach($tDir as $oDir){
115  $tSDir[]= $oDir->getName();
116  }
117  return $tSDir;
118  }
119 
120  private function query($sReq,$sClassRow){
121  //traitement de la requete $sReq
122  $sReq=trim($sReq);
123  $this->_sReq=$sReq;
124 
125  if(substr($sReq,0,6)== 'SELECT'){
126 
127  $tReq=$this->explainSql($sReq);
128 
129  //count
130  $bCount=false;
131  $iCount=0;
132  if(isset($tReq['select']) and preg_match('/COUNT\(/i',$tReq['select'])){
133  $bCount=true;
134  }
135 
136  $tCritere=$this->findListCritere($tReq);
137 
138  $sTable=trim($tReq['from']);
139 
140  //UTILISATION D UN INDEX
141  $tSqlFieldEqual=array_keys($tCritere);
142 
143  $sIndexToUse=$this->findIndexForTable($sTable,$tSqlFieldEqual);
144 
145  $tObj=array();
146  //UTILISATION D UN INDEX
147  if($sIndexToUse!=''){
148  $tObj=$this->findWithTableIndex($sClassRow,$sTable,$sIndexToUse,$tCritere);
149 
150  }elseif($tSqlFieldEqual==array('=id')){
151  $sFilename=$this->_tConfig[$this->_sConfig.'.database'];
152  $sFilename.=$sTable.'/'.(string)$tCritere['=id'].'.xml';
153 
154  $tRow=(array)simplexml_load_file($sFilename,null,LIBXML_NOCDATA);
155 
156  $oRow=new $sClassRow($tRow);
157  $tObj[]=$oRow;
158  }else{
159 
160  $tObj=$this->findInTableWithCritere($sClassRow,$sTable,$tCritere);
161 
162 
163  }
164  //count
165  if($bCount){
166  $iCount=count($tObj);
167  return array($iCount);
168  }else if(isset($tReq['order']) and $tObj!=null){
169  return $this->sortResult($tObj,$tReq);
170  }else{
171  return $tObj;
172  }
173  }
174 
175 
176 
177  }
178  private function explainSql($sReq){
179  if(
180  preg_match_all('/^SELECT(?<select>.*)FROM(?<from>.*)WHERE(?<where>.*)ORDER BY(?<order>.*)/i'
181  ,$sReq,$tResult,PREG_SET_ORDER)
182  or
183  preg_match_all('/^SELECT(?<select>.*)FROM(?<from>.*)ORDER BY(?<order>.*)/i',$sReq,$tResult,PREG_SET_ORDER)
184  or
185  preg_match_all('/^SELECT(?<select>.*)FROM(?<from>.*)WHERE(?<where>.*)/i',$sReq,$tResult,PREG_SET_ORDER)
186  or
187  preg_match_all('/^SELECT(?<select>.*)FROM(?<from>.*)/i',$sReq,$tResult,PREG_SET_ORDER)
188  ){
189  if(isset($tResult[0]['where']) and preg_match('/ or /i',$tResult[0]['where'])){
190  $this->erreur('Requete non supportee : '.$sReq.$msg);
191  }elseif(isset($tResult[0]['order']) and !preg_match('/\s[ASC|DESC]/i',trim($tResult[0]['order'])) ){
192  $this->erreur('Il faut definir un sens de tri: ASC ou DESC dans la requete'.$sReq.$msg);
193  }else{
194  return $tResult[0];
195  }
196  }else{
197  $msg="\n\n";
198  $msg.="Le driver xml gere les requetes de type : \n";
199  $msg.="- SELECT liste_des_champs FROM ma_table WHERE champ=valeur ORDER BY champ DESC/ASC \n";
200  $msg.="- SELECT liste_des_champs FROM ma_table ORDER BY champ DESC/ASC \n";
201  $msg.="- SELECT liste_des_champs FROM ma_table WHERE champ=valeur \n";
202  $msg.="- SELECT liste_des_champs FROM ma_table \n";
203  $msg.=" la clause where accepte uniquement champ=valeur, champ!=valeur et AND \n";
204 
205  $this->erreur('Requete non supportee : '.$sReq.$msg);
206  }
207  }
208  private function findListCritere($tReq){
209  $tCritere=array();
210 
211  if(isset($tReq['where'])){
212  if(preg_match('/ and /i',$tReq['where'])){
213  $tWhere=preg_split('/ AND /i',$tReq['where']);
214  foreach($tWhere as $sWhereVal){
215  if(preg_match('/!=/',$sWhereVal)){
216  list($sVar,$sVal)=preg_split('/!=/',$sWhereVal);
217  $tCritere[trim($sVar)]='!'.trim($sVal);
218  }elseif(preg_match('/=/',$sWhereVal)){
219  list($sVar,$sVal)=preg_split('/=/',$sWhereVal);
220  $tCritere[trim($sVar)]='='.trim($sVal);
221  }
222  }
223  }else{
224  if(preg_match('/!=/',$tReq['where'])){
225  list($sVar,$sVal)=preg_split('/!=/',$tReq['where']);
226  $tCritere[trim($sVar)]='!'.trim($sVal);
227  }elseif(preg_match('/=/',$tReq['where'])){
228  list($sVar,$sVal)=preg_split('/=/',$tReq['where']);
229  $tCritere[trim($sVar)]='='.trim($sVal);
230  }
231  }
232 
233  }
234  return $tCritere;
235  }
236  private function sortResult($tObj,$tReq){
237 
238  list($sChamp,$sSens)=preg_split('/ /',trim($tReq['order']));
239 
240  $tTri=array();
241  $tIdObj=array();
242  foreach($tObj as $i => $oObj){
243  $tIdObj[ $i ]=$oObj;
244  $tTri[ $i ]=(string)$oObj->$sChamp;
245  }
246 
247  if($sSens=='DESC'){
248  arsort($tTri);
249  }else{
250  asort($tTri);
251  }
252 
253  $tOrderedObj=array();
254  $tId= array_keys($tTri);
255  foreach($tId as $id){
256  $tOrderedObj[]=$tIdObj[$id];
257  }
258 
259  return $tOrderedObj;
260  }
261  private function findIndexForTable($sTable,$tSqlFieldEqual){
262  $oDirIndex=new _dir($this->_tConfig[$this->_sConfig.'.database'].$sTable.'/index');
263  if($oDirIndex->exist()){
264  $tFileIndex=$oDirIndex->getListDir();
265  foreach($tFileIndex as $oFileIndex){
266  $tFieldIndex=$this->getFieldsFromIndex($oFileIndex->getName());
267 
268  foreach($tSqlFieldEqual as $sSqlFieldEqual){
269  if(
270  $sSqlFieldEqual[0]=='=' and !in_array(substr($sSqlFieldEqual,1),$tFieldIndex)
271  or
272  $sSqlFieldEqual[0]=='!' and in_array(substr($sSqlFieldEqual,1),$tFieldIndex)
273  ){
274  continue 2;
275  }
276  }
277 
278  return $oFileIndex->getName();
279  }
280  }
281  return null;
282  }
283  private function findWithTableIndex($sClassRow,$sTable,$sIndexToUse,$tCritere){
284  $sDirIndex=$this->_tConfig[$this->_sConfig.'.database'].$sTable.'/index/'.$sIndexToUse;
285 
286  $tFieldIndex=preg_split('/\./',$sIndexToUse);
287 
288  $oDirIndex=new _dir($sDirIndex);
289  $tFileIndex=$oDirIndex->getListFile();
290 
291  $tObj=array();
292  foreach($tFileIndex as $oFileIndex){
293  $sFileIndex=trim($oFileIndex->getName());
294 
295  $tRow=$this->getRowValueFromIndex($sFileIndex,$tFieldIndex);
296 
297  foreach($tCritere as $sCritereField => $sCritereVal){
298 
299  if(!isset($tRow[$sCritereField]) or
300  (
301  ($sCritereVal[0]=='=' and (string)$sCritereVal!=(string)'='.$tRow[$sCritereField])
302 
303  or
304 
305  ($sCritereVal[0]=='!' and (string)$sCritereVal==(string)'!'.$tRow[$sCritereField])
306  )
307  ){
308  continue 2;
309  }
310  }
311 
312  $tMatchedFile=file( $sDirIndex.'/'.$sFileIndex );
313  foreach($tMatchedFile as $sMatchedFile){
314  $sMatchedFile=trim($sMatchedFile);
315  $sFilename=$this->_tConfig[$this->_sConfig.'.database'].$sTable.'/'.$sMatchedFile;
316  $tRow=(array)simplexml_load_file($sFilename,null,LIBXML_NOCDATA);
317 
318  $oRow=new $sClassRow($tRow);
319  $tObj[]=$oRow;
320  }
321 
322  }
323  return $tObj;
324  }
325  private function findInTableWithCritere($sClassRow,$sTable,$tCritere){
326  $oDir=new _dir($this->_tConfig[$this->_sConfig.'.database'].$sTable);
327  $tFile=$oDir->getListFile();
328 
329 
330  $tObj=array();
331  foreach($tFile as $oFile){
332  if( in_array($oFile->getName(),array('structure.xml','max.xml'))){ continue; }
333  $tRow=(array)simplexml_load_file($oFile->getAdresse(),null,LIBXML_NOCDATA);
334 
335 
336  foreach($tCritere as $sCritereField => $sCritereVal){
337 
338  if(!isset($tRow[$sCritereField]) or
339  (
340  ($sCritereVal[0]=='=' and (string)$sCritereVal!=(string)'='.$tRow[$sCritereField])
341 
342  or
343 
344  ($sCritereVal[0]=='!' and (string)$sCritereVal==(string)'!'.$tRow[$sCritereField])
345  )
346  ){
347  continue 2;
348  }
349  }
350 
351 
352  $oRow=new $sClassRow($tRow);
353  $tObj[]=$oRow;
354 
355  }
356 
357  return $tObj;
358 
359 
360  }
361 
362  public function quote($sVal){
363  return $sVal;
364  }
365  public function getWhereAll(){
366  return '1=1';
367  }
368 
369  private function getFieldsFromIndex($sIndex){
370  $tFields=preg_split('/\./',substr($sIndex,0,-6));//field.field.index
371  return $tFields;
372  }
373  private function getRowValueFromIndex($sFileIndex,$tFieldIndex){
374  $tValue=preg_split('/####/',substr($sFileIndex,0,-4) );
375  $tRow=array();
376  foreach($tFieldIndex as $i => $var){
377  $tRow[$var]=$tValue[$i];
378  }
379  return $tRow;
380  }
381  private function getFileIndexFromTab($sIndex,$tRow){
382  $tFields=$this->getFieldsFromIndex($sIndex);
383  $sFileIndex='';
384  foreach($tFields as $sField){
385  $sFileIndex.=$tRow[$sField];
386  $sFileIndex.='####';
387  }
388  return $sFileIndex.'.csv';
389  }
390  public function generateIndexForTable($sTable,$sIndex){
391  $tFields=$this->getFieldsFromIndex($sIndex);
392 
393  $oDir=new _dir($this->_tConfig[$this->_sConfig.'.database'].$sTable);
394  $tFile=$oDir->getListFile();
395 
396  $tIndexContent=array();
397 
398  foreach($tFile as $oFile){
399  if($oFile->getName() == 'structure.xml'){ continue;}
400  if($oFile->getName() == 'max.xml'){ continue;}
401 
402  $tRow=(array)simplexml_load_file($oFile->getAdresse(),null,LIBXML_NOCDATA);
403 
404 
405 
406  $sKey='';
407  foreach($tFields as $sField){
408  $sKey.=$tRow[$sField];
409  $sKey.='####';
410  }
411  $tIndexContent[$sKey][]=$tRow['id'].'.xml';
412 
413  }
414 
415  $oDir=new _dir($this->_tConfig[$this->_sConfig.'.database'].$sTable.'/index/'.$sIndex);
416  foreach($oDir->getListFile() as $oFile){
417  $oFile->delete();
418  }
419 
420  foreach($tIndexContent as $sKey => $tFile){
421  $oFile=new _file($this->_tConfig[$this->_sConfig.'.database'].$sTable.'/index/'.$sIndex.'/'.$sKey.'.csv');
422  $oFile->setContent(implode($tFile,"\n"));
423  $oFile->save();
424  }
425  }
426  private function addRowInAllIndex($sTable,$tProperty){
427 
428  $oDir=new _dir($this->_tConfig[$this->_sConfig.'.database'].$sTable.'/index');
429  if($oDir->exist()){
430  $tDirIndex=$oDir->getListDir();
431  foreach($tDirIndex as $oDirIndex){
432  $this->addRowInIndex($sTable,$tProperty,$oDirIndex->getName());
433  }
434  }
435  }
436  private function addRowInIndex($sTable,$tProperty,$sIndex){
437 
438  $sFileIndex=$this->getFileIndexFromTab($sIndex,$tProperty);
439 
440  $oFile=new _file($this->_tConfig[$this->_sConfig.'.database'].$sTable.'/index/'.$sIndex.'/'.$sFileIndex);
441  $oFile->addContent($tProperty['id'].'.xml');
442  $oFile->save('a');
443  }
444  private function removeRowFromAllIndex($sTable,$tProperty){
445 
446  $oDir=new _dir($this->_tConfig[$this->_sConfig.'.database'].$sTable.'/index');
447  if($oDir->exist()){
448  $tDirIndex=$oDir->getListDir();
449  foreach($tDirIndex as $oDirIndex){
450  $this->removeRowFromIndex($sTable,$tProperty,$oDirIndex->getName());
451  }
452  }
453  }
454  private function removeRowFromIndex($sTable,$tProperty,$sIndex){
455 
456  $sFileIndex=$this->getFileIndexFromTab($sIndex,$tProperty);
457 
458  if(!file_exists($this->_tConfig[$this->_sConfig.'.database'].$sTable.'/index/'.$sIndex.'/'.$sFileIndex)){
459  return;
460  }
461 
462  $tLine=file($this->_tConfig[$this->_sConfig.'.database'].$sTable.'/index/'.$sIndex.'/'.$sFileIndex);
463  $tContent=array();
464  foreach($tLine as $sLine){
465  $sLine=trim($sLine);
466  if($sLine==$tProperty['id'].'.xml'){
467  continue;
468  }
469  $tContent[]=$sLine;
470  }
471 
472  $oFile=new _file($this->_tConfig[$this->_sConfig.'.database'].$sTable.'/index/'.$sIndex.'/'.$sFileIndex);
473  $oFile->setContent(implode("\n",$tContent));
474  $oFile->save();
475  }
476 
477  private function getIdFromTab($tId){
478  if(is_array($tId)){
479  return current($tId);
480  }else{
481  return $tId;
482  }
483  }
484  private function save($tProperty,$sFichier){
485  $oFile=new _file($sFichier);
486  $sRet="\n";
487  $sXml='<?xml version="1.0" encoding="ISO-8859-1"?>'.$sRet;
488  $sXml.='<main>'.$sRet;
489  foreach($tProperty as $sVar => $sVal){
490  $sXml.='<'.$sVar.'><![CDATA['.$sVal.']]></'.$sVar.'>'.$sRet;
491  }
492  $sXml.='</main>'.$sRet;
493  $oFile->write($sXml);
494  }
495  private function getMaxId($sTable){
496  $oXml=simplexml_load_file($this->_tConfig[$this->_sConfig.'.database'].$sTable.'/max.xml');
497  return (int)$oXml->max;
498 
499  }
500 
501 
502 
503 }