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         $aFields = array_merge($this->getFields($sTable), $this->getFields($sLangTable));
00318         $aSingleLangFields = array();
00319 
00320         foreach ($aFields as $sFieldName => $sField) {
00321             if (preg_match("/(({$sTable}|{$sLangTable})\.)?(?<field>.+)_(?<lang>[0-9]+)$/", $sField, $aMatches)) {
00322                 if ($aMatches['lang'] == $iLang) {
00323                     $aSingleLangFields[$aMatches['field']] = $sField;
00324                 }
00325             } else {
00326                 $aSingleLangFields[$sFieldName] = $sField;
00327             }
00328         }
00329 
00330         return $aSingleLangFields;
00331     }
00332 
00339     public function addNewMultilangField($sTable)
00340     {
00341         $aSql = array();
00342         $aFields = $this->getMultilangFields($sTable);
00343         $iMaxLang = $this->getCurrentMaxLangId();
00344         $iNewLang = $this->getNextLangId();
00345 
00346         $sTableSet = getLangTableName($sTable, $iNewLang);
00347         if (!$this->tableExists($sTableSet)) {
00348             $aSql[] = $this->_getCreateTableSetSql($sTable, $iNewLang);
00349         }
00350 
00351         if (is_array($aFields) && count($aFields) > 0) {
00352             foreach ($aFields as $sField) {
00353                 $sNewFieldName = $sField . "_" . $iNewLang;
00354                 if ($iNewLang > 1) {
00355                     $iPrevLang = $iNewLang - 1;
00356                     $sPrevField = $sField . '_' . $iPrevLang;
00357                 } else {
00358                     $sPrevField = $sField;
00359                 }
00360 
00361                 if (!$this->tableExists($sTableSet) || !$this->fieldExists($sNewFieldName, $sTableSet)) {
00362 
00363                     //getting add field sql
00364                     $aSql[] = $this->getAddFieldSql($sTable, $sField, $sNewFieldName, $sPrevField, $sTableSet);
00365 
00366                     //getting add index sql on added field
00367                     $aSql = array_merge($aSql, (array) $this->getAddFieldIndexSql($sTable, $sField, $sNewFieldName, $sTableSet));
00368                 }
00369             }
00370         }
00371 
00372         $this->executeSql($aSql);
00373     }
00374 
00384     public function resetMultilangFields($iLangId, $sTableName)
00385     {
00386         $iLangId = (int) $iLangId;
00387 
00388         if ($iLangId === 0) {
00389             return;
00390         }
00391 
00392         $aSql = array();
00393 
00394         $aFields = $this->getMultilangFields($sTableName);
00395         if (is_array($aFields) && count($aFields) > 0) {
00396             foreach ($aFields as $sFieldName) {
00397                 $sFieldName = $sFieldName . "_" . $iLangId;
00398 
00399                 if ($this->fieldExists($sFieldName, $sTableName)) {
00400                     //resetting field value to default
00401                     $aSql[] = "UPDATE {$sTableName} SET {$sFieldName} = DEFAULT;";
00402                 }
00403             }
00404         }
00405 
00406         if (!empty($aSql)) {
00407             $this->executeSql($aSql);
00408         }
00409     }
00410 
00415     public function addNewLangToDb()
00416     {
00417         //reset max count
00418         $this->_iCurrentMaxLangId = null;
00419 
00420         $aTable = $this->getAllTables();
00421 
00422         foreach ($aTable as $sTableName) {
00423             $this->addNewMultilangField($sTableName);
00424         }
00425 
00426         //updating views
00427         $this->updateViews();
00428     }
00429 
00438     public function resetLanguage($iLangId)
00439     {
00440         if ((int) $iLangId === 0) {
00441             return;
00442         }
00443 
00444         $aTables = $this->getAllTables();
00445 
00446         // removing tables which does not requires reset
00447         foreach ($this->_aSkipTablesOnReset as $sSkipTable) {
00448 
00449             if (($iSkipId = array_search($sSkipTable, $aTables)) !== false) {
00450                 unset($aTables[$iSkipId]);
00451             }
00452         }
00453 
00454         foreach ($aTables as $sTableName) {
00455             $this->resetMultilangFields($iLangId, $sTableName);
00456         }
00457     }
00458 
00464     public function executeSql($aSql)
00465     {
00466         $oDb = oxDb::getDb();
00467 
00468         if (is_array($aSql) && !empty($aSql)) {
00469             foreach ($aSql as $sSql) {
00470                 $sSql = trim($sSql);
00471                 if (!empty($sSql)) {
00472                     $oDb->execute($sSql);
00473                 }
00474             }
00475         }
00476     }
00477 
00485     public function updateViews($aTables = null)
00486     {
00487         set_time_limit(0);
00488 
00489         $oDb = oxDb::getDb();
00490         $oConfig = oxRegistry::getConfig();
00491 
00492         $aShops = $oDb->getAll("select * from oxshops");
00493 
00494         $aTables = $aTables ? $aTables : $oConfig->getConfigParam('aMultiShopTables');
00495 
00496         $bSuccess = true;
00497         foreach ($aShops as $aShop) {
00498             $sShopId = $aShop[0];
00499             $oShop = oxNew('oxshop');
00500             $oShop->load($sShopId);
00501             $oShop->setMultiShopTables($aTables);
00502             $aMallInherit = array();
00503             foreach ($aTables as $sTable) {
00504                 $aMallInherit[$sTable] = $oConfig->getShopConfVar('blMallInherit_' . $sTable, $sShopId);
00505             }
00506             if (!$oShop->generateViews(false, $aMallInherit) && $bSuccess) {
00507                 $bSuccess = false;
00508             }
00509         }
00510 
00511         return $bSuccess;
00512     }
00513 }