oxdbmetadatahandler.php

Go to the documentation of this file.
00001 <?php
00002 
00007 class oxDbMetaDataHandler extends oxSuperCfg
00008 {
00013     protected $_aDbTablesFields = null;
00014 
00015 
00020     protected $_aTables = null;
00021 
00026     protected $_iCurrentMaxLangId;
00027 
00032     protected $_aSkipTablesOnReset = array( "oxcountry" );
00033 
00041     public function getFields( $sTableName )
00042     {
00043         $aFields    = array();
00044         $aRawFields = oxDb::getDb()->MetaColumns( $sTableName );
00045         if (is_array($aRawFields)) {
00046             foreach ( $aRawFields as $oField ) {
00047                 $aFields[] = $oField->name;
00048             }
00049         }
00050         return $aFields;
00051     }
00052 
00060     public function tableExists( $sTableName )
00061     {
00062         $oDb = oxDb::getDb();
00063         $aTables = $oDb->getAll("show tables like ". $oDb->quote($sTableName));
00064         return count($aTables) > 0;
00065     }
00066 
00075     public function fieldExists( $sFieldName, $sTableName )
00076     {
00077         $aTableFields = $this->getFields( $sTableName );
00078 
00079         if ( is_array($aTableFields) ) {
00080             $sFieldName = strtoupper( $sFieldName );
00081             $aTableFields = array_map('strtoupper', $aTableFields);
00082             if ( in_array( $sFieldName, $aTableFields ) ) {
00083                 return true;
00084             }
00085         }
00086 
00087         return false;
00088     }
00089 
00090 
00097     public function getAllTables()
00098     {
00099         if ( empty($this->_aTables) ) {
00100 
00101             $aTables = oxDb::getDb()->getAll("show tables");
00102 
00103             foreach ( $aTables as $aTableInfo) {
00104                 $sTableName = $aTableInfo[0];
00105 
00106                 $this->_aTables[] = $aTableInfo[0];
00107             }
00108         }
00109         return $this->_aTables;
00110     }
00111 
00119     public function getAllMultiTables($sTable)
00120     {
00121         $aMLTables = array();
00122         foreach (array_keys(oxRegistry::getLang()->getLanguageIds()) as $iLangId) {
00123             $sLangTableName = getLangTableName($sTable, $iLangId );
00124             if ($sTable != $sLangTableName && !in_array($sLangTableName, $aMLTables)) {
00125                 $aMLTables[] = $sLangTableName;
00126             }
00127         }
00128         return $aMLTables;
00129     }
00130 
00140     protected function _getCreateTableSetSql( $sTable, $iLang)
00141     {
00142         $sTableSet = getLangTableName($sTable, $iLang);
00143 
00144         $aRes = oxDb::getDb()->getAll( "show create table {$sTable}" );
00145         $sSql = "CREATE TABLE `{$sTableSet}` (".
00146                 "`OXID` char(32) COLLATE latin1_general_ci NOT NULL, ".
00147                 "PRIMARY KEY (`OXID`)".
00148                 ") ".strstr($aRes[0][1], 'ENGINE=');
00149         return $sSql;
00150     }
00151 
00163     public function getAddFieldSql( $sTable, $sField, $sNewField, $sPrevField, $sTableSet = null )
00164     {
00165         if (!$sTableSet) {
00166             $sTableSet = $sTable;
00167         }
00168         $aRes = oxDb::getDb()->getAll( "show create table {$sTable}" );
00169         $sTableSql = $aRes[0][1];
00170 
00171         preg_match( "/.*,\s+(['`]?".preg_quote($sField, '/')."['`]?\s+[^,]+),.*/", $sTableSql, $aMatch );
00172         $sFieldSql = $aMatch[1];
00173 
00174         $sSql = "";
00175         if ( !empty($sFieldSql) ) {
00176             $sFieldSql = preg_replace( "/".preg_quote($sField, '/')."/", $sNewField, $sFieldSql );
00177             $sSql = "ALTER TABLE `$sTableSet` ADD " . $sFieldSql;
00178             if ($this->tableExists($sTableSet) && $this->fieldExists($sPrevField, $sTableSet)) {
00179                 $sSql .= " AFTER `$sPrevField`";
00180             }
00181         }
00182         return $sSql;
00183     }
00184 
00185 
00186 
00197     public function getAddFieldIndexSql( $sTable, $sField, $sNewField, $sTableSet = null )
00198     {
00199         $aRes = oxDb::getDb()->getAll( "show create table {$sTable}" );
00200 
00201         $sTableSql = $aRes[0][1];
00202 
00203         preg_match_all("/([\w]+\s+)?\bKEY\s+(`[^`]+`)?\s*\([^)]+\)/iU", $sTableSql, $aMatch);
00204         $aIndex = $aMatch[0];
00205 
00206         $blUsingTableSet = $sTableSet ?  true : false;
00207 
00208         if (!$sTableSet) {
00209             $sTableSet = $sTable;
00210         }
00211 
00212         $aIndexSql = array();
00213         $aSql      = array();
00214         if ( count($aIndex) ) {
00215             foreach ( $aIndex as $sIndexSql ) {
00216                 if ( preg_match("/\([^)]*\b" . $sField . "\b[^)]*\)/i", $sIndexSql )  ) {
00217 
00218                     //removing index name - new will be added automaticly
00219                     $sIndexSql = preg_replace("/(.*\bKEY\s+)`[^`]+`/", "$1", $sIndexSql );
00220 
00221                     if ( $blUsingTableSet ) {
00222                         // replacing multiple fields to one (#3269)
00223                         $sIndexSql = preg_replace("/\([^\)]+\)/", "(`$sNewField`)", $sIndexSql );
00224                     } else {
00225                         //replacing previous field name with new one
00226                         $sIndexSql = preg_replace("/\b" . $sField . "\b/", $sNewField, $sIndexSql );
00227                     }
00228 
00229                     $aIndexSql[] =  "ADD ". $sIndexSql;
00230                 }
00231             }
00232             if ( count($aIndexSql) ) {
00233                 $aSql = array("ALTER TABLE `$sTableSet` ".implode(", ", $aIndexSql));
00234             }
00235         }
00236 
00237         return $aSql;
00238     }
00239 
00246     public function getCurrentMaxLangId()
00247     {
00248         if ( isset($this->_iCurrentMaxLangId) ) {
00249             return $this->_iCurrentMaxLangId;
00250         }
00251 
00252         $sTable = $sTableSet = "oxarticles";
00253         $sField = $sFieldSet = "oxtitle";
00254         $iLang  = 0;
00255         while ($this->tableExists($sTableSet) && $this->fieldExists($sFieldSet, $sTableSet)) {
00256             $iLang ++;
00257             $sTableSet = getLangTableName($sTable, $iLang);
00258             $sFieldSet = $sField.'_'.$iLang;
00259         }
00260 
00261         $this->_iCurrentMaxLangId = --$iLang;
00262         return $this->_iCurrentMaxLangId;
00263     }
00264 
00270     public function getNextLangId()
00271     {
00272         return $this->getCurrentMaxLangId() + 1;
00273     }
00274 
00282     public function getMultilangFields( $sTable )
00283     {
00284         $aFields = $this->getFields( $sTable );
00285         $aMultiLangFields = array();
00286 
00287         foreach ( $aFields as $sField ) {
00288             if ( preg_match("/(.+)_1$/", $sField, $aMatches) ) {
00289                 $aMultiLangFields[] = $aMatches[1];
00290             }
00291         }
00292 
00293         return $aMultiLangFields;
00294     }
00295 
00304     public function getSinglelangFields( $sTable, $iLang )
00305     {
00306         $aFields = array_merge($this->getFields( $sTable ), $this->getFields(getLangTableName($sTable, $iLang) ));
00307         $aSingleLangFields = array();
00308 
00309         foreach ( $aFields as $sField ) {
00310             if ( preg_match("/(.+)_([0-9]+)$/", $sField, $aMatches) ) {
00311                 if ($aMatches[2] == $iLang) {
00312                     $aSingleLangFields[$aMatches[1]] = $sField;
00313                 }
00314             } else {
00315                 $aSingleLangFields[$sField] = $sField;
00316             }
00317         }
00318 
00319         return $aSingleLangFields;
00320     }
00321 
00330     public function addNewMultilangField( $sTable )
00331     {
00332         $aSql = array();
00333         $aFields  = $this->getMultilangFields($sTable);
00334         $iMaxLang = $this->getCurrentMaxLangId();
00335         $iNewLang = $this->getNextLangId();
00336 
00337         $sTableSet = getLangTableName($sTable, $iNewLang);
00338         if (!$this->tableExists($sTableSet)) {
00339             $aSql[] = $this->_getCreateTableSetSql( $sTable, $iNewLang );
00340         }
00341 
00342         if ( is_array($aFields) && count($aFields) > 0 ) {
00343             foreach ( $aFields as $sField ) {
00344                 $sNewFieldName = $sField . "_" . $iNewLang;
00345                 if ($iNewLang>1) {
00346                     $iPrevLang = $iNewLang-1;
00347                     $sPrevField = $sField.'_'.$iPrevLang;
00348                 } else {
00349                     $sPrevField = $sField;
00350                 }
00351 
00352                 if ( !$this->tableExists($sTableSet) || !$this->fieldExists( $sNewFieldName, $sTableSet ) ) {
00353 
00354                     //getting add field sql
00355                     $aSql[] = $this->getAddFieldSql( $sTable, $sField, $sNewFieldName, $sPrevField, $sTableSet );
00356 
00357                     //getting add index sql on added field
00358                     $aSql = array_merge($aSql, (array) $this->getAddFieldIndexSql($sTable, $sField, $sNewFieldName, $sTableSet));
00359                 }
00360             }
00361         }
00362 
00363         $this->executeSql($aSql);
00364     }
00365 
00375     public function resetMultilangFields( $iLangId, $sTableName )
00376     {
00377         $iLangId = (int)$iLangId;
00378 
00379         if ( $iLangId === 0 ) {
00380             return;
00381         }
00382 
00383         $aSql = array();
00384 
00385         $aFields = $this->getMultilangFields( $sTableName );
00386         if ( is_array($aFields) && count($aFields) > 0 ) {
00387             foreach ( $aFields as $sFieldName ) {
00388                 $sFieldName = $sFieldName . "_" . $iLangId;
00389 
00390                 if ( $this->fieldExists( $sFieldName, $sTableName ) ) {
00391                     //reseting field value to default
00392                     $aSql[] = "UPDATE {$sTableName} SET {$sFieldName} = DEFAULT;";
00393                 }
00394             }
00395         }
00396 
00397         if ( !empty($aSql) ) {
00398             $this->executeSql( $aSql );
00399         }
00400     }
00401 
00408     public function addNewLangToDb()
00409     {
00410         //reset max count
00411         $this->_iCurrentMaxLangId = null;
00412 
00413         $aTable = $this->getAllTables();
00414 
00415         foreach ( $aTable as $sTableName ) {
00416             $this->addNewMultilangField( $sTableName );
00417         }
00418 
00419         //updating views
00420         $this->updateViews();
00421     }
00422 
00431     public function resetLanguage( $iLangId )
00432     {
00433         if ( (int)$iLangId === 0 ) {
00434             return;
00435         }
00436 
00437         $aTables = $this->getAllTables();
00438 
00439         // removing tables which does not requires reset
00440         foreach ( $this->_aSkipTablesOnReset as $sSkipTable ) {
00441 
00442             if ( ($iSkipId = array_search( $sSkipTable, $aTables )) !== false ) {
00443                 unset( $aTables[$iSkipId] );
00444             }
00445         }
00446 
00447         foreach ( $aTables as $sTableName ) {
00448             $this->resetMultilangFields( $iLangId, $sTableName );
00449         }
00450     }
00451 
00459     public function executeSql( $aSql )
00460     {
00461         $oDb = oxDb::getDb();
00462 
00463         if ( is_array($aSql) && !empty($aSql) ) {
00464             foreach ( $aSql as $sSql) {
00465                 $sSql = trim($sSql);
00466                 if (!empty($sSql)) {
00467                     $oDb->execute( $sSql );
00468                 }
00469             }
00470         }
00471     }
00472 
00480     public function updateViews( $aTables = null )
00481     {
00482         set_time_limit( 0 );
00483 
00484         $oDb = oxDb::getDb();
00485         $oConfig = oxRegistry::getConfig();
00486 
00487         $aShops = $oDb->getAll( "select * from oxshops" );
00488 
00489         $aTables = $aTables ? $aTables : $oConfig->getConfigParam( 'aMultiShopTables' );
00490 
00491         $bSuccess = true;
00492         foreach ( $aShops as $aShop ) {
00493             $sShopId = $aShop[0];
00494             $oShop = oxNew( 'oxshop' );
00495             $oShop->load( $sShopId );
00496             $oShop->setMultiShopTables( $aTables );
00497             $blMultishopInherit = $oConfig->getShopConfVar( 'blMultishopInherit_oxcategories', $sShopId );
00498             $aMallInherit = array();
00499             foreach ( $aTables as $sTable ) {
00500                 $aMallInherit[$sTable] = $oConfig->getShopConfVar( 'blMallInherit_' . $sTable, $sShopId );
00501             }
00502             if ( !$oShop->generateViews( $blMultishopInherit, $aMallInherit ) && $bSuccess ) {
00503                 $bSuccess = false;
00504             }
00505         }
00506 
00507         return $bSuccess;
00508     }
00509 }
00510