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 $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
00364 $aSql[] = $this->getAddFieldSql($sTable, $sField, $sNewFieldName, $sPrevField, $sTableSet);
00365
00366
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
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
00418 $this->_iCurrentMaxLangId = null;
00419
00420 $aTable = $this->getAllTables();
00421
00422 foreach ($aTable as $sTableName) {
00423 $this->addNewMultilangField($sTableName);
00424 }
00425
00426
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
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 }