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
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
00227 $sIndexSql = preg_replace("/(.*\bKEY\s+)`[^`]+`/", "$1", $sIndexSql);
00228
00229 if ($blUsingTableSet) {
00230
00231 $sIndexSql = preg_replace("/\([^\)]+\)/", "(`$sNewField`)", $sIndexSql);
00232 } else {
00233
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
00366 $aSql[] = $this->getAddFieldSql($sTable, $sField, $sNewFieldName, $sPrevField, $sTableSet);
00367
00368
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
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
00420 $this->_iCurrentMaxLangId = null;
00421
00422 $aTable = $this->getAllTables();
00423
00424 foreach ($aTable as $sTableName) {
00425 $this->addNewMultilangField($sTableName);
00426 }
00427
00428
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
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 }