Code Coverage |
||||||||||
Classes and Traits |
Functions and Methods |
Lines |
||||||||
| Total | |
0.00% |
0 / 1 |
|
54.84% |
17 / 31 |
CRAP | |
60.66% |
185 / 305 |
| sgbd_xml | |
0.00% |
0 / 1 |
|
54.84% |
17 / 31 |
749.13 | |
60.66% |
185 / 305 |
| getInstance | |
100.00% |
1 / 1 |
1 | |
100.00% |
1 / 1 |
|||
| findMany | |
100.00% |
1 / 1 |
2 | |
100.00% |
4 / 4 |
|||
| findManySimple | |
100.00% |
1 / 1 |
1 | |
100.00% |
1 / 1 |
|||
| findOne | |
100.00% |
1 / 1 |
2 | |
100.00% |
4 / 4 |
|||
| findOneSimple | |
100.00% |
1 / 1 |
1 | |
100.00% |
1 / 1 |
|||
| execute | |
100.00% |
1 / 1 |
1 | |
100.00% |
1 / 1 |
|||
| update | |
100.00% |
1 / 1 |
2 | |
100.00% |
11 / 11 |
|||
| insert | |
100.00% |
1 / 1 |
1 | |
100.00% |
9 / 9 |
|||
| delete | |
100.00% |
1 / 1 |
1 | |
100.00% |
7 / 7 |
|||
| getListColumn | |
100.00% |
1 / 1 |
1 | |
100.00% |
4 / 4 |
|||
| getListTable | |
100.00% |
1 / 1 |
2 | |
100.00% |
7 / 7 |
|||
| query | |
0.00% |
0 / 1 |
11.03 | |
93.94% |
31 / 33 |
|||
| explainSql | |
0.00% |
0 / 1 |
9.37 | |
83.33% |
20 / 24 |
|||
| findListCritere | |
100.00% |
1 / 1 |
8 | |
100.00% |
23 / 23 |
|||
| sortResult | |
100.00% |
1 / 1 |
4 | |
100.00% |
17 / 17 |
|||
| findIndexForTable | |
0.00% |
0 / 1 |
42.33 | |
18.75% |
3 / 16 |
|||
| findWithTableIndex | |
0.00% |
0 / 1 |
90 | |
0.00% |
0 / 27 |
|||
| findInTableWithCritere | |
0.00% |
0 / 1 |
9 | |
95.00% |
19 / 20 |
|||
| quote | |
100.00% |
1 / 1 |
1 | |
100.00% |
1 / 1 |
|||
| getWhereAll | |
100.00% |
1 / 1 |
1 | |
100.00% |
1 / 1 |
|||
| getFieldsFromIndex | |
0.00% |
0 / 1 |
2 | |
0.00% |
0 / 2 |
|||
| getRowValueFromIndex | |
0.00% |
0 / 1 |
6 | |
0.00% |
0 / 6 |
|||
| getFileIndexFromTab | |
0.00% |
0 / 1 |
6 | |
0.00% |
0 / 7 |
|||
| generateIndexForTable | |
0.00% |
0 / 1 |
56 | |
0.00% |
0 / 27 |
|||
| addRowInAllIndex | |
0.00% |
0 / 1 |
5.20 | |
37.50% |
3 / 8 |
|||
| addRowInIndex | |
0.00% |
0 / 1 |
2 | |
0.00% |
0 / 5 |
|||
| removeRowFromAllIndex | |
0.00% |
0 / 1 |
5.20 | |
37.50% |
3 / 8 |
|||
| removeRowFromIndex | |
0.00% |
0 / 1 |
20 | |
0.00% |
0 / 15 |
|||
| getIdFromTab | |
0.00% |
0 / 1 |
2.15 | |
66.67% |
2 / 3 |
|||
| save | |
100.00% |
1 / 1 |
2 | |
100.00% |
10 / 10 |
|||
| getMaxId | |
100.00% |
1 / 1 |
1 | |
100.00% |
2 / 2 |
|||
| <?php | |
| /* | |
| This file is part of Mkframework. | |
| Mkframework is free software: you can redistribute it and/or modify | |
| it under the terms of the GNU Lesser General Public License as published by | |
| the Free Software Foundation, either version 3 of the License. | |
| Mkframework is distributed in the hope that it will be useful, | |
| but WITHOUT ANY WARRANTY; without even the implied warranty of | |
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
| GNU Lesser General Public License for more details. | |
| You should have received a copy of the GNU Lesser General Public License | |
| along with Mkframework. If not, see <http://www.gnu.org/licenses/>. | |
| */ | |
| class sgbd_xml extends abstract_sgbd | |
| { | |
| public static function getInstance($sConfig) | |
| { | |
| return self::_getInstance(__CLASS__, $sConfig); | |
| } | |
| public function findMany($tSql, $sClassRow) | |
| { | |
| $tRows=$this->query($this->bind($tSql), $sClassRow); | |
| if (!$tRows) { | |
| return null; | |
| } | |
| return $tRows; | |
| } | |
| public function findManySimple($tSql, $sClassRow) | |
| { | |
| return $this->findMany($tSql, $sClassRow); | |
| } | |
| public function findOne($tSql, $sClassRow) | |
| { | |
| $tRs=$this->query($this->bind($tSql), $sClassRow); | |
| if (empty($tRs)) { | |
| return null; | |
| } | |
| return $tRs[0]; | |
| } | |
| public function findOneSimple($tSql, $sClassRow) | |
| { | |
| return $this->findOne($tSql, $sClassRow); | |
| } | |
| public function execute($tSql) | |
| { | |
| throw new Exception('method execute not available for this driver'); | |
| } | |
| public function update($sTable, $tProperty, $tWhere) | |
| { | |
| $iId=$this->getIdFromTab($tWhere); | |
| $sFile=$this->_tConfig[$this->_sConfig.'.database'].$sTable.'/'.$iId.'.xml'; | |
| $oXml=simplexml_load_file($sFile); | |
| $tXml=(array) $oXml; | |
| //remove index | |
| $this->removeRowFromAllIndex($sTable, $tXml); | |
| foreach ($tProperty as $sVar => $sVal) { | |
| $tXml[$sVar]=(string)$sVal; | |
| } | |
| //add in index | |
| $this->addRowInAllIndex($sTable, $tXml); | |
| $this->save($tXml, $sFile); | |
| } | |
| public function insert($sTable, $tProperty) | |
| { | |
| $iId=$this->getMaxId($sTable); | |
| $tMax=array('max'=>($iId+1)); | |
| $tProperty['id']=$iId; | |
| $sFile=$this->_tConfig[$this->_sConfig.'.database'].$sTable.'/'.$iId.'.xml'; | |
| $this->save($tProperty, $sFile); | |
| $sFileMax=$this->_tConfig[$this->_sConfig.'.database'].$sTable.'/max.xml'; | |
| $this->save($tMax, $sFileMax); | |
| $this->addRowInAllIndex($sTable, $tProperty); | |
| return $iId; | |
| } | |
| public function delete($sTable, $tWhere) | |
| { | |
| $iId=$this->getIdFromTab($tWhere); | |
| $sFile=$this->_tConfig[$this->_sConfig.'.database'].$sTable.'/'.$iId.'.xml'; | |
| $oXml=simplexml_load_file($sFile); | |
| $tXml=(array) $oXml; | |
| //remove index | |
| $this->removeRowFromAllIndex($sTable, $tXml); | |
| unlink($this->_tConfig[$this->_sConfig.'.database'].$sTable.'/'.$iId.'.xml'); | |
| } | |
| public function getListColumn($sTable) | |
| { | |
| $sFile=$this->_tConfig[$this->_sConfig.'.database'].$sTable.'/structure.xml'; | |
| $oXml=simplexml_load_file($sFile); | |
| $tXml=(array)$oXml; | |
| return $tXml['colonne']; | |
| } | |
| public function getListTable() | |
| { | |
| $oDir=new _dir($this->_tConfig[$this->_sConfig.'.database']); | |
| $tDir=$oDir->getList(); | |
| $tSDir=array(); | |
| foreach ($tDir as $oDir) { | |
| $tSDir[]= $oDir->getName(); | |
| } | |
| return $tSDir; | |
| } | |
| private function query($sReq, $sClassRow) | |
| { | |
| //traitement de la requete $sReq | |
| $sReq=trim($sReq); | |
| $this->_sReq=$sReq; | |
| if (substr($sReq, 0, 6)== 'SELECT') { | |
| $tReq=$this->explainSql($sReq); | |
| //count | |
| $bCount=false; | |
| $iCount=0; | |
| if (isset($tReq['select']) and preg_match('/COUNT\(/i', $tReq['select'])) { | |
| $bCount=true; | |
| } | |
| $tCritere=$this->findListCritere($tReq); | |
| $sTable=trim($tReq['from']); | |
| //UTILISATION D UN INDEX | |
| $tSqlFieldEqual=array_keys($tCritere); | |
| $sIndexToUse=$this->findIndexForTable($sTable, $tSqlFieldEqual); | |
| $tObj=array(); | |
| //UTILISATION D UN INDEX | |
| if ($sIndexToUse!='') { | |
| $tObj=$this->findWithTableIndex($sClassRow, $sTable, $sIndexToUse, $tCritere); | |
| } elseif ($tSqlFieldEqual==array('id') and substr((string)$tCritere['id'],0,1)=='=') { | |
| $sFilename=$this->_tConfig[$this->_sConfig.'.database']; | |
| $sFilename.=$sTable.'/'.substr((string)$tCritere['id'],1).'.xml'; | |
| if(file_exists($sFilename)){ | |
| $tRow=(array)simplexml_load_file($sFilename, null, LIBXML_NOCDATA); | |
| $oRow=new $sClassRow($tRow); | |
| $tObj[]=$oRow; | |
| } | |
| } else { | |
| $tObj=$this->findInTableWithCritere($sClassRow, $sTable, $tCritere); | |
| } | |
| //count | |
| if ($bCount) { | |
| $iCount=count($tObj); | |
| return array($iCount); | |
| } elseif (isset($tReq['order']) and $tObj!=null) { | |
| return $this->sortResult($tObj, $tReq); | |
| } else { | |
| return $tObj; | |
| } | |
| } | |
| } | |
| private function explainSql($sReq) | |
| { | |
| if ( | |
| preg_match_all('/^SELECT(?<select>.*)FROM(?<from>.*)WHERE(?<where>.*)ORDER BY(?<order>.*)/i', $sReq, $tResult, PREG_SET_ORDER) | |
| or | |
| preg_match_all('/^SELECT(?<select>.*)FROM(?<from>.*)ORDER BY(?<order>.*)/i', $sReq, $tResult, PREG_SET_ORDER) | |
| or | |
| preg_match_all('/^SELECT(?<select>.*)FROM(?<from>.*)WHERE(?<where>.*)/i', $sReq, $tResult, PREG_SET_ORDER) | |
| or | |
| preg_match_all('/^SELECT(?<select>.*)FROM(?<from>.*)/i', $sReq, $tResult, PREG_SET_ORDER) | |
| ) { | |
| if (isset($tResult[0]['where']) and preg_match('/ or /i', $tResult[0]['where'])) { | |
| $this->erreur('Requete non supportee : '.$sReq); | |
| } elseif (isset($tResult[0]['order']) and !preg_match('/\s[ASC|DESC]/i', trim($tResult[0]['order']))) { | |
| $this->erreur('Il faut definir un sens de tri: ASC ou DESC dans la requete'.$sReq); | |
| } else { | |
| return $tResult[0]; | |
| } | |
| } else { | |
| $msg="\n\n"; | |
| $msg.="Le driver xml gere les requetes de type : \n"; | |
| $msg.="- SELECT liste_des_champs FROM ma_table WHERE champ=valeur ORDER BY champ DESC/ASC \n"; | |
| $msg.="- SELECT liste_des_champs FROM ma_table ORDER BY champ DESC/ASC \n"; | |
| $msg.="- SELECT liste_des_champs FROM ma_table WHERE champ=valeur \n"; | |
| $msg.="- SELECT liste_des_champs FROM ma_table \n"; | |
| $msg.=" la clause where accepte uniquement champ=valeur, champ!=valeur et AND \n"; | |
| $this->erreur('Requete non supportee : '.$sReq.$msg); | |
| } | |
| } | |
| private function findListCritere($tReq) | |
| { | |
| $tCritere=array(); | |
| if (isset($tReq['where'])) { | |
| if (preg_match('/ and /i', $tReq['where'])) { | |
| $tWhere=preg_split('/ AND /i', $tReq['where']); | |
| foreach ($tWhere as $sWhereVal) { | |
| if (preg_match('/!=/', $sWhereVal)) { | |
| list($sVar, $sVal)=preg_split('/!=/', $sWhereVal); | |
| $tCritere[trim($sVar)]='!'.trim($sVal); | |
| } elseif (preg_match('/=/', $sWhereVal)) { | |
| list($sVar, $sVal)=preg_split('/=/', $sWhereVal); | |
| $tCritere[trim($sVar)]='='.trim($sVal); | |
| } | |
| } | |
| } else { | |
| if (preg_match('/!=/', $tReq['where'])) { | |
| list($sVar, $sVal)=preg_split('/!=/', $tReq['where']); | |
| $tCritere[trim($sVar)]='!'.trim($sVal); | |
| } elseif (preg_match('/=/', $tReq['where'])) { | |
| list($sVar, $sVal)=preg_split('/=/', $tReq['where']); | |
| $tCritere[trim($sVar)]='='.trim($sVal); | |
| } | |
| } | |
| } | |
| return $tCritere; | |
| } | |
| private function sortResult($tObj, $tReq) | |
| { | |
| list($sChamp, $sSens)=preg_split('/ /', trim($tReq['order'])); | |
| $tTri=array(); | |
| $tIdObj=array(); | |
| foreach ($tObj as $i => $oObj) { | |
| $tIdObj[ $i ]=$oObj; | |
| $tTri[ $i ]=(string)$oObj->$sChamp; | |
| } | |
| if ($sSens=='DESC') { | |
| arsort($tTri); | |
| } else { | |
| asort($tTri); | |
| } | |
| $tOrderedObj=array(); | |
| $tId= array_keys($tTri); | |
| foreach ($tId as $id) { | |
| $tOrderedObj[]=$tIdObj[$id]; | |
| } | |
| return $tOrderedObj; | |
| } | |
| private function findIndexForTable($sTable, $tSqlFieldEqual) | |
| { | |
| $oDirIndex=new _dir($this->_tConfig[$this->_sConfig.'.database'].$sTable.'/index'); | |
| if ($oDirIndex->exist()) { | |
| $tFileIndex=$oDirIndex->getListDir(); | |
| foreach ($tFileIndex as $oFileIndex) { | |
| $tFieldIndex=$this->getFieldsFromIndex($oFileIndex->getName()); | |
| foreach ($tSqlFieldEqual as $sSqlFieldEqual) { | |
| if ( | |
| $sSqlFieldEqual[0]=='=' and !in_array(substr($sSqlFieldEqual, 1), $tFieldIndex) | |
| or | |
| $sSqlFieldEqual[0]=='!' and in_array(substr($sSqlFieldEqual, 1), $tFieldIndex) | |
| ) { | |
| continue 2; | |
| } | |
| } | |
| return $oFileIndex->getName(); | |
| } | |
| } | |
| return null; | |
| } | |
| private function findWithTableIndex($sClassRow, $sTable, $sIndexToUse, $tCritere) | |
| { | |
| $sDirIndex=$this->_tConfig[$this->_sConfig.'.database'].$sTable.'/index/'.$sIndexToUse; | |
| $tFieldIndex=preg_split('/\./', $sIndexToUse); | |
| $oDirIndex=new _dir($sDirIndex); | |
| $tFileIndex=$oDirIndex->getListFile(); | |
| $tObj=array(); | |
| foreach ($tFileIndex as $oFileIndex) { | |
| $sFileIndex=trim($oFileIndex->getName()); | |
| $tRow=$this->getRowValueFromIndex($sFileIndex, $tFieldIndex); | |
| foreach ($tCritere as $sCritereField => $sCritereVal) { | |
| if (!isset($tRow[$sCritereField]) or | |
| ( | |
| ($sCritereVal[0]=='=' and (string)$sCritereVal!=(string)'='.$tRow[$sCritereField]) | |
| or | |
| ($sCritereVal[0]=='!' and (string)$sCritereVal==(string)'!'.$tRow[$sCritereField]) | |
| ) | |
| ) { | |
| continue 2; | |
| } | |
| } | |
| $tMatchedFile=file($sDirIndex.'/'.$sFileIndex); | |
| foreach ($tMatchedFile as $sMatchedFile) { | |
| $sMatchedFile=trim($sMatchedFile); | |
| $sFilename=$this->_tConfig[$this->_sConfig.'.database'].$sTable.'/'.$sMatchedFile; | |
| $tRow=(array)simplexml_load_file($sFilename, null, LIBXML_NOCDATA); | |
| $oRow=new $sClassRow($tRow); | |
| $tObj[]=$oRow; | |
| } | |
| } | |
| return $tObj; | |
| } | |
| private function findInTableWithCritere($sClassRow, $sTable, $tCritere) | |
| { | |
| $oDir=new _dir($this->_tConfig[$this->_sConfig.'.database'].$sTable); | |
| $tFile=$oDir->getListFile(); | |
| $tObj=array(); | |
| foreach ($tFile as $oFile) { | |
| if (in_array($oFile->getName(), array('structure.xml','max.xml'))) { | |
| continue; | |
| } | |
| $tRow=(array)simplexml_load_file($oFile->getAdresse(), null, LIBXML_NOCDATA); | |
| foreach ($tCritere as $sCritereField => $sCritereVal) { | |
| if (!isset($tRow[$sCritereField]) or | |
| ( | |
| ($sCritereVal[0]=='=' and (string)$sCritereVal!=(string)'='.$tRow[$sCritereField]) | |
| or | |
| ($sCritereVal[0]=='!' and (string)$sCritereVal==(string)'!'.$tRow[$sCritereField]) | |
| ) | |
| ) { | |
| continue 2; | |
| } | |
| } | |
| $oRow=new $sClassRow($tRow); | |
| $tObj[]=$oRow; | |
| } | |
| return $tObj; | |
| } | |
| public function quote($sVal) | |
| { | |
| return $sVal; | |
| } | |
| public function getWhereAll() | |
| { | |
| return '1=1'; | |
| } | |
| private function getFieldsFromIndex($sIndex) | |
| { | |
| $tFields=preg_split('/\./', substr($sIndex, 0, -6));//field.field.index | |
| return $tFields; | |
| } | |
| private function getRowValueFromIndex($sFileIndex, $tFieldIndex) | |
| { | |
| $tValue=preg_split('/####/', substr($sFileIndex, 0, -4)); | |
| $tRow=array(); | |
| foreach ($tFieldIndex as $i => $var) { | |
| $tRow[$var]=$tValue[$i]; | |
| } | |
| return $tRow; | |
| } | |
| private function getFileIndexFromTab($sIndex, $tRow) | |
| { | |
| $tFields=$this->getFieldsFromIndex($sIndex); | |
| $sFileIndex=''; | |
| foreach ($tFields as $sField) { | |
| $sFileIndex.=$tRow[$sField]; | |
| $sFileIndex.='####'; | |
| } | |
| return $sFileIndex.'.csv'; | |
| } | |
| public function generateIndexForTable($sTable, $sIndex) | |
| { | |
| $tFields=$this->getFieldsFromIndex($sIndex); | |
| $oDir=new _dir($this->_tConfig[$this->_sConfig.'.database'].$sTable); | |
| $tFile=$oDir->getListFile(); | |
| $tIndexContent=array(); | |
| foreach ($tFile as $oFile) { | |
| if ($oFile->getName() == 'structure.xml') { | |
| continue; | |
| } | |
| if ($oFile->getName() == 'max.xml') { | |
| continue; | |
| } | |
| $tRow=(array)simplexml_load_file($oFile->getAdresse(), null, LIBXML_NOCDATA); | |
| $sKey=''; | |
| foreach ($tFields as $sField) { | |
| $sKey.=$tRow[$sField]; | |
| $sKey.='####'; | |
| } | |
| $tIndexContent[$sKey][]=$tRow['id'].'.xml'; | |
| } | |
| $oDir=new _dir($this->_tConfig[$this->_sConfig.'.database'].$sTable.'/index/'.$sIndex); | |
| foreach ($oDir->getListFile() as $oFile) { | |
| $oFile->delete(); | |
| } | |
| foreach ($tIndexContent as $sKey => $tFile) { | |
| $oFile=new _file($this->_tConfig[$this->_sConfig.'.database'].$sTable.'/index/'.$sIndex.'/'.$sKey.'.csv'); | |
| $oFile->setContent(implode($tFile, "\n")); | |
| $oFile->save(); | |
| } | |
| } | |
| private function addRowInAllIndex($sTable, $tProperty) | |
| { | |
| $oDir=new _dir($this->_tConfig[$this->_sConfig.'.database'].$sTable.'/index'); | |
| if ($oDir->exist()) { | |
| $tDirIndex=$oDir->getListDir(); | |
| foreach ($tDirIndex as $oDirIndex) { | |
| $this->addRowInIndex($sTable, $tProperty, $oDirIndex->getName()); | |
| } | |
| } | |
| } | |
| private function addRowInIndex($sTable, $tProperty, $sIndex) | |
| { | |
| $sFileIndex=$this->getFileIndexFromTab($sIndex, $tProperty); | |
| $oFile=new _file($this->_tConfig[$this->_sConfig.'.database'].$sTable.'/index/'.$sIndex.'/'.$sFileIndex); | |
| $oFile->addContent($tProperty['id'].'.xml'); | |
| $oFile->save('a'); | |
| } | |
| private function removeRowFromAllIndex($sTable, $tProperty) | |
| { | |
| $oDir=new _dir($this->_tConfig[$this->_sConfig.'.database'].$sTable.'/index'); | |
| if ($oDir->exist()) { | |
| $tDirIndex=$oDir->getListDir(); | |
| foreach ($tDirIndex as $oDirIndex) { | |
| $this->removeRowFromIndex($sTable, $tProperty, $oDirIndex->getName()); | |
| } | |
| } | |
| } | |
| private function removeRowFromIndex($sTable, $tProperty, $sIndex) | |
| { | |
| $sFileIndex=$this->getFileIndexFromTab($sIndex, $tProperty); | |
| if (!file_exists($this->_tConfig[$this->_sConfig.'.database'].$sTable.'/index/'.$sIndex.'/'.$sFileIndex)) { | |
| return; | |
| } | |
| $tLine=file($this->_tConfig[$this->_sConfig.'.database'].$sTable.'/index/'.$sIndex.'/'.$sFileIndex); | |
| $tContent=array(); | |
| foreach ($tLine as $sLine) { | |
| $sLine=trim($sLine); | |
| if ($sLine==$tProperty['id'].'.xml') { | |
| continue; | |
| } | |
| $tContent[]=$sLine; | |
| } | |
| $oFile=new _file($this->_tConfig[$this->_sConfig.'.database'].$sTable.'/index/'.$sIndex.'/'.$sFileIndex); | |
| $oFile->setContent(implode("\n", $tContent)); | |
| $oFile->save(); | |
| } | |
| private function getIdFromTab($tId) | |
| { | |
| if (is_array($tId)) { | |
| return current($tId); | |
| } else { | |
| return $tId; | |
| } | |
| } | |
| private function save($tProperty, $sFichier) | |
| { | |
| $oFile=new _file($sFichier); | |
| $sRet="\n"; | |
| $sXml='<?xml version="1.0" encoding="ISO-8859-1"?>'.$sRet; | |
| $sXml.='<main>'.$sRet; | |
| foreach ($tProperty as $sVar => $sVal) { | |
| $sXml.='<'.$sVar.'><![CDATA['.$sVal.']]></'.$sVar.'>'.$sRet; | |
| } | |
| $sXml.='</main>'.$sRet; | |
| $oFile->write($sXml); | |
| } | |
| private function getMaxId($sTable) | |
| { | |
| $oXml=simplexml_load_file($this->_tConfig[$this->_sConfig.'.database'].$sTable.'/max.xml'); | |
| return (int)$oXml->max; | |
| } | |
| } |