oxdbmetadatahandler.php

Go to the documentation of this file.
00001 <?php
00002 
00007 class oxDbMetaDataHandler extends oxSuperCfg
00008 {
00009 
00014     protected $_aDbTablesFields = null;
00015 
00016 
00021     protected $_aTables = null;
00022 
00027     protected $_iCurrentMaxLangId;
00028 
00033     protected $_aSkipTablesOnReset = array("oxcountry");
00034 
00042     public function getFields($sTableName)
00043     {
00044         $aFields = array();
00045         $aRawFields = oxDb::getDb()->MetaColumns($sTableName);
00046         if (is_array($aRawFields)) {
00047             foreach ($aRawFields as $oField) {
00048                 $aFields[$oField->name] = "{$sTableName}.{$oField->name}";
00049             }
00050         }
00051 
00052         return $aFields;
00053     }
00054 
00062     public function tableExists($sTableName)
00063     {
00064         $oDb = oxDb::getDb();
00065         $aTables = $oDb->getAll("show tables like " . $oDb->quote($sTableName));
00066 
00067         return count($aTables) > 0;
00068     }
00069 
00078     public function fieldExists($sFieldName, $sTableName)
00079     {
00080         $aTableFields = $this->getFields($sTableName);
00081         $sTableName = strtoupper($sTableName);
00082         if (is_array($aTableFields)) {
00083             $sFieldName = strtoupper($sFieldName);
00084             $aTableFields = array_map('strtoupper', $aTableFields);
00085             if (in_array("{$sTableName}.{$sFieldName}", $aTableFields)) {
00086                 return true;
00087             }
00088         }
00089 
00090         return false;
00091     }
00092 
00093 
00100     public function getAllTables()
00101     {
00102         if (empty($this->_aTables)) {
00103 
00104             $aTables = oxDb::getDb()->getAll("show tables");
00105 
00106             foreach ($aTables as $aTableInfo) {
00107                 $sTableName = $aTableInfo[0];
00108 
00109                 $this->_aTables[] = $aTableInfo[0];
00110             }
00111         }
00112 
00113         return $this->_aTables;
00114     }
00115 
00123     public function getAllMultiTables($sTable)
00124     {
00125         $aMLTables = array();
00126         foreach (array_keys(oxRegistry::getLang()->getLanguageIds()) as $iLangId) {
00127             $sLangTableName = getLangTableName($sTable, $iLangId);
00128             if ($sTable != $sLangTableName && !in_array($sLangTableName, $aMLTables)) {
00129                 $aMLTables[] = $sLangTableName;
00130             }
00131         }
00132 
00133         return $aMLTables;
00134     }
00135 
00145     protected function _getCreateTableSetSql($sTable, $iLang)
00146     {
00147         $sTableSet = getLangTableName($sTable, $iLang);
00148 
00149         $aRes = oxDb::getDb()->getAll("show create table {$sTable}");
00150         $sSql = "CREATE TABLE `{$sTableSet}` (" .
00151                 "`OXID` char(32) COLLATE latin1_general_ci NOT NULL, " .
00152                 "PRIMARY KEY (`OXID`)" .
00153                 ") " . strstr($aRes[0][1], 'ENGINE=');
00154 
00155         return $sSql;
00156     }
00157 
00169     public function getAddFieldSql($sTable, $sField, $sNewField, $sPrevField, $sTableSet = null)
00170     {
00171         if (!$sTableSet) {
00172             $sTableSet = $sTable;
00173         }
00174         $aRes = oxDb::getDb()->getAll("show create table {$sTable}");
00175         $sTableSql = $aRes[0][1];
00176 
00177         // removing comments;
00178         $sTableSql = preg_replace('/COMMENT \\\'.*?\\\'/', '', $sTableSql);
00179         preg_match("/.*,\s+(['`]?" . preg_quote($sField, '/') . "['`]?\s+[^,]+),.*/", $sTableSql, $aMatch);
00180         $sFieldSql = $aMatch[1];
00181 
00182         $sSql = "";
00183         if (!empty($sFieldSql)) {
00184             $sFieldSql = preg_replace("/" . preg_quote($sField, '/') . "/", $sNewField, $sFieldSql);
00185             $sSql = "ALTER TABLE `$sTableSet` ADD " . $sFieldSql;
00186             if ($this->tableExists($sTableSet) && $this->fieldExists($sPrevField, $sTableSet)) {
00187                 $sSql .= " AFTER `$sPrevField`";
00188             }
00189         }
00190 
00191         return $sSql;
00192     }
00193 
00194 
00205     public function getAddFieldIndexSql($sTable, $sField, $sNewField, $sTableSet = null)
00206     {
00207         $aRes = oxDb::getDb()->getAll("show create table {$sTable}");
00208 
00209         $sTableSql = $aRes[0][1];
00210 
00211         preg_match_all("/([\w]+\s+)?\bKEY\s+(`[^`]+`)?\s*\([^)]+\)/iU", $sTableSql, $aMatch);
00212         $aIndex = $aMatch[0];
00213 
00214         $blUsingTableSet = $sTableSet ? true : false;
00215 
00216         if (!$sTableSet) {
00217             $sTableSet = $sTable;
00218         }
00219 
00220         $aIndexSql = array();
00221         $aSql = array();
00222         if (count($aIndex)) {
00223             foreach ($aIndex as $sIndexSql) {
00224                 if (preg_match("/\([^)]*\b" . $sField . "\b[^)]*\)/i", $sIndexSql)) {
00225 
00226                     //removing index name - new will be added automaticly
00227                     $sIndexSql = preg_replace("/(.*\bKEY\s+)`[^`]+`/", "$1", $sIndexSql);
00228 
00229                     if ($blUsingTableSet) {
00230                         // replacing multiple fields to one (#3269)
00231                         $sIndexSql = preg_replace("/\([^\)]+\)/", "(`$sNewField`)", $sIndexSql);
00232                     } else {
00233                         //replacing previous field name with new one
00234                         $sIndexSql = preg_replace("/\b" . $sField . "\b/", $sNewField, $sIndexSql);
00235                     }
00236 
00237                     $aIndexSql[] = "ADD " . $sIndexSql;
00238                 }
00239             }
00240             if (count($aIndexSql)) {
00241                 $aSql = array("ALTER TABLE `$sTableSet` " . implode(", ", $aIndexSql));
00242             }
00243         }
00244 
00245         return $aSql;
00246     }
00247 
00254     public function getCurrentMaxLangId()
00255     {
00256         if (isset($this->_iCurrentMaxLangId)) {
00257             return $this->_iCurrentMaxLangId;
00258         }
00259 
00260         $sTable = $sTableSet = "oxarticles";
00261         $sField = $sFieldSet = "oxtitle";
00262         $iLang = 0;
00263         while ($this->tableExists($sTableSet) && $this->fieldExists($sFieldSet, $sTableSet)) {
00264             $iLang++;
00265             $sTableSet = getLangTableName($sTable, $iLang);
00266             $sFieldSet = $sField . '_' . $iLang;
00267         }
00268 
00269         $this->_iCurrentMaxLangId = --$iLang;
00270 
00271         return $this->_iCurrentMaxLangId;
00272     }
00273 
00279     public function getNextLangId()
00280     {
00281         return $this->getCurrentMaxLangId() + 1;
00282     }
00283 
00291     public function getMultilangFields($sTable)
00292     {
00293         $aFields = $this->getFields($sTable);
00294         $aMultiLangFields = array();
00295 
00296         foreach ($aFields as $sField) {
00297             if (preg_match("/({$sTable}\.)?(?<field>.+)_1$/", $sField, $aMatches)) {
00298                 $aMultiLangFields[] = $aMatches['field'];
00299             }
00300         }
00301 
00302         return $aMultiLangFields;
00303     }
00304 
00313     public function getSinglelangFields($sTable, $iLang)
00314     {
00315         $sLangTable = getLangTableName($sTable, $iLang);
00316 
00317         $aBaseFields = $this->getFields($sTable);
00318         $aLangFields = $this->getFields($sLangTable);
00319         $aFields = array_merge($aLangFields, $aBaseFields);
00320         $aSingleLangFields = array();
00321 
00322         foreach ($aFields as $sFieldName => $sField) {
00323             if (preg_match("/(({$sTable}|{$sLangTable})\.)?(?<field>.+)_(?<lang>[0-9]+)$/", $sField, $aMatches)) {
00324                 if ($aMatches['lang'] == $iLang) {
00325                     $aSingleLangFields[$aMatches['field']] = $sField;
00326                 }
00327             } else {
00328                 $aSingleLangFields[$sFieldName] = $sField;
00329             }
00330         }
00331 
00332         return $aSingleLangFields;
00333     }
00334 
00341     public function addNewMultilangField($sTable)
00342     {
00343         $aSql = array();
00344         $aFields = $this->getMultilangFields($sTable);
00345         $iMaxLang = $this->getCurrentMaxLangId();
00346         $iNewLang = $this->getNextLangId();
00347 
00348         $sTableSet = getLangTableName($sTable, $iNewLang);
00349         if (!$this->tableExists($sTableSet)) {
00350             $aSql[] = $this->_getCreateTableSetSql($sTable, $iNewLang);
00351         }
00352 
00353         if (is_array($aFields) && count($aFields) > 0) {
00354             foreach ($aFields as $sField) {
00355                 $sNewFieldName = $sField . "_" . $iNewLang;
00356                 if ($iNewLang > 1) {
00357                     $iPrevLang = $iNewLang - 1;
00358                     $sPrevField = $sField . '_' . $iPrevLang;
00359                 } else {
00360                     $sPrevField = $sField;
00361                 }
00362 
00363                 if (!$this->tableExists($sTableSet) || !$this->fieldExists($sNewFieldName, $sTableSet)) {
00364 
00365                     //getting add field sql
00366                     $aSql[] = $this->getAddFieldSql($sTable, $sField, $sNewFieldName, $sPrevField, $sTableSet);
00367 
00368                     //getting add index sql on added field
00369                     $aSql = array_merge($aSql, (array) $this->getAddFieldIndexSql($sTable, $sField, $sNewFieldName, $sTableSet));
00370                 }
00371             }
00372         }
00373 
00374         $this->executeSql($aSql);
00375     }
00376 
00386     public function resetMultilangFields($iLangId, $sTableName)
00387     {
00388         $iLangId = (int) $iLangId;
00389 
00390         if ($iLangId === 0) {
00391             return;
00392         }
00393 
00394         $aSql = array();
00395 
00396         $aFields = $this->getMultilangFields($sTableName);
00397         if (is_array($aFields) && count($aFields) > 0) {
00398             foreach ($aFields as $sFieldName) {
00399                 $sFieldName = $sFieldName . "_" . $iLangId;
00400 
00401                 if ($this->fieldExists($sFieldName, $sTableName)) {
00402                     //resetting field value to default
00403                     $aSql[] = "UPDATE {$sTableName} SET {$sFieldName} = DEFAULT;";
00404                 }
00405             }
00406         }
00407 
00408         if (!empty($aSql)) {
00409             $this->executeSql($aSql);
00410         }
00411     }
00412 
00417     public function addNewLangToDb()
00418     {
00419         //reset max count
00420         $this->_iCurrentMaxLangId = null;
00421 
00422         $aTable = $this->getAllTables();
00423 
00424         foreach ($aTable as $sTableName) {
00425             $this->addNewMultilangField($sTableName);
00426         }
00427 
00428         //updating views
00429         $this->updateViews();
00430     }
00431 
00440     public function resetLanguage($iLangId)
00441     {
00442         if ((int) $iLangId === 0) {
00443             return;
00444         }
00445 
00446         $aTables = $this->getAllTables();
00447 
00448         // removing tables which does not requires reset
00449         foreach ($this->_aSkipTablesOnReset as $sSkipTable) {
00450 
00451             if (($iSkipId = array_search($sSkipTable, $aTables)) !== false) {
00452                 unset($aTables[$iSkipId]);
00453             }
00454         }
00455 
00456         foreach ($aTables as $sTableName) {
00457             $this->resetMultilangFields($iLangId, $sTableName);
00458         }
00459     }
00460 
00466     public function executeSql($aSql)
00467     {
00468         $oDb = oxDb::getDb();
00469 
00470         if (is_array($aSql) && !empty($aSql)) {
00471             foreach ($aSql as $sSql) {
00472                 $sSql = trim($sSql);
00473                 if (!empty($sSql)) {
00474                     $oDb->execute($sSql);
00475                 }
00476             }
00477         }
00478     }
00479 
00487     public function updateViews($aTables = null)
00488     {
00489         set_time_limit(0);
00490 
00491         $oDb = oxDb::getDb();
00492         $oConfig = oxRegistry::getConfig();
00493 
00494         $aShops = $oDb->getAll("select * from oxshops");
00495 
00496         $aTables = $aTables ? $aTables : $oConfig->getConfigParam('aMultiShopTables');
00497 
00498         $bSuccess = true;
00499         foreach ($aShops as $aShop) {
00500             $sShopId = $aShop[0];
00501             $oShop = oxNew('oxshop');
00502             $oShop->load($sShopId);
00503             $oShop->setMultiShopTables($aTables);
00504             $aMallInherit = array();
00505             foreach ($aTables as $sTable) {
00506                 $aMallInherit[$sTable] = $oConfig->getShopConfVar('blMallInherit_' . $sTable, $sShopId);
00507             }
00508             if (!$oShop->generateViews(false, $aMallInherit) && $bSuccess) {
00509                 $bSuccess = false;
00510             }
00511         }
00512 
00513         return $bSuccess;
00514     }
00515 }