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 $aTables = oxDb::getDb()->getAll("show tables like ".oxDb::getDb()->quote($sTableName));
00063 return count($aTables) > 0;
00064 }
00065
00074 public function fieldExists( $sFieldName, $sTableName )
00075 {
00076 $aTableFields = $this->getFields( $sTableName );
00077
00078 if ( is_array($aTableFields) ) {
00079 $sFieldName = strtoupper( $sFieldName );
00080 if ( in_array( $sFieldName, $aTableFields ) ) {
00081 return true;
00082 }
00083 }
00084
00085 return false;
00086 }
00087
00088
00095 public function getAllTables()
00096 {
00097 if ( empty($this->_aTables) ) {
00098
00099 $aTables = oxDb::getDb()->getAll("show tables");
00100
00101 foreach ( $aTables as $aTableInfo) {
00102 $sTableName = $aTableInfo[0];
00103
00104 $this->_aTables[] = $aTableInfo[0];
00105 }
00106 }
00107 return $this->_aTables;
00108 }
00109
00117 public function getAllMultiTables($sTable)
00118 {
00119 $aMLTables = array();
00120 foreach (array_keys(oxLang::getInstance()->getLanguageIds()) as $iLangId) {
00121 $sLangTableName = getLangTableName($sTable, $iLangId );
00122 if ($sTable != $sLangTableName && !in_array($sLangTableName, $aMLTables)) {
00123 $aMLTables[] = $sLangTableName;
00124 }
00125 }
00126 return $aMLTables;
00127 }
00128
00138 protected function _getCreateTableSetSql( $sTable, $iLang)
00139 {
00140 $sTableSet = getLangTableName($sTable, $iLang);
00141
00142 $aRes = oxDb::getDb()->getAll("show create table {$sTable}");
00143 $sSql = "CREATE TABLE `{$sTableSet}` (".
00144 "`OXID` char(32) COLLATE latin1_general_ci NOT NULL, ".
00145 "PRIMARY KEY (`OXID`)".
00146 ") ".strstr($aRes[0][1], 'ENGINE=');
00147 return $sSql;
00148 }
00149
00159 protected function _getAddFieldSql( $sTable, $sField, $iLang )
00160 {
00161 $sTableSet = getLangTableName($sTable, $iLang);
00162 $sNewField = $sField.'_'.$iLang;
00163
00164 if ($iLang>1) {
00165 $iPrevLang = $iLang-1;
00166 $sPrevField = $sField.'_'.$iPrevLang;
00167 } else {
00168 $sPrevField = $sField;
00169 }
00170
00171 $aRes = oxDb::getDb()->getAll("show create table {$sTable}");
00172 $sTableSql = $aRes[0][1];
00173
00174 preg_match( "/.*,\s+(['`]?".preg_quote($sField, '/')."['`]?\s+[^,]+),.*/", $sTableSql, $aMatch );
00175 $sFieldSql = $aMatch[1];
00176
00177 $sSql = "";
00178 if ( !empty($sFieldSql) ) {
00179 $sFieldSql = preg_replace( "/".preg_quote($sField, '/')."/", $sNewField, $sFieldSql );
00180 $sSql = "ALTER TABLE `$sTableSet` ADD " . $sFieldSql;
00181 if ($this->tableExists($sTableSet) && $this->fieldExists($sPrevField, $sTableSet)) {
00182 $sSql .= " AFTER `$sPrevField`";
00183 }
00184 }
00185 return $sSql;
00186 }
00187
00188
00189
00199 protected function _getAddFieldIndexSql( $sTable, $sField, $iLang )
00200 {
00201 $sTableSet = getLangTableName($sTable, $iLang);
00202 $sNewField = $sField.'_'.$iLang;
00203
00204 $aRes = oxDb::getDb()->getAll("show create table {$sTable}");
00205 $sTableSql = $aRes[0][1];
00206
00207 preg_match_all("/([\w]+\s+)?\bKEY\s+(`[^`]+`)?\s*\([^)]+\)/iU", $sTableSql, $aMatch);
00208 $aIndex = $aMatch[0];
00209
00210 $aIndexSql = array();
00211 if ( count($aIndex) ) {
00212 foreach ( $aIndex as $sIndexSql ) {
00213 if ( preg_match("/\([^)]*\b" . $sField . "\b[^)]*\)/i", $sIndexSql ) ) {
00214
00215
00216 $sIndexSql = preg_replace("/(.*\bKEY\s+)`[^`]+`/", "$1", $sIndexSql );
00217
00218
00219 $sIndexSql = preg_replace("/\b" . $sField . "\b/", $sNewField, $sIndexSql );
00220
00221 $aIndexSql[] = "ALTER TABLE `$sTableSet` ADD ". $sIndexSql;
00222 }
00223 }
00224 }
00225
00226 return $aIndexSql;
00227 }
00228
00235 public function getCurrentMaxLangId()
00236 {
00237 if ( isset($this->_iCurrentMaxLangId) ) {
00238 return $this->_iCurrentMaxLangId;
00239 }
00240
00241 $sTable = $sTableSet = "oxarticles";
00242 $sField = $sFieldSet = "oxtitle";
00243 $iLang = 0;
00244 while ($this->tableExists($sTableSet) && $this->fieldExists($sFieldSet, $sTableSet)) {
00245 $iLang ++;
00246 $sTableSet = getLangTableName($sTable, $iLang);
00247 $sFieldSet = $sField.'_'.$iLang;
00248 }
00249
00250 $this->_iCurrentMaxLangId = --$iLang;
00251 return $this->_iCurrentMaxLangId;
00252 }
00253
00259 public function getNextLangId()
00260 {
00261 return $this->getCurrentMaxLangId() + 1;
00262 }
00263
00271 public function getMultilangFields( $sTable )
00272 {
00273 $aFields = $this->getFields( $sTable );
00274 $aMultiLangFields = array();
00275
00276 foreach ( $aFields as $sField ) {
00277 if ( preg_match("/(.+)_1$/", $sField, $aMatches) ) {
00278 $aMultiLangFields[] = $aMatches[1];
00279 }
00280 }
00281
00282 return $aMultiLangFields;
00283 }
00284
00293 public function getSinglelangFields( $sTable, $iLang )
00294 {
00295 $aFields = array_merge($this->getFields( $sTable ), $this->getFields(getLangTableName($sTable, $iLang) ));
00296 $aSingleLangFields = array();
00297
00298 foreach ( $aFields as $sField ) {
00299 if ( preg_match("/(.+)_([0-9]+)$/", $sField, $aMatches) ) {
00300 if ($aMatches[2] == $iLang) {
00301 $aSingleLangFields[$aMatches[1]] = $sField;
00302 }
00303 } else {
00304 $aSingleLangFields[$sField] = $sField;
00305 }
00306 }
00307
00308 return $aSingleLangFields;
00309 }
00310
00319 public function addNewMultilangField( $sTable )
00320 {
00321 $aSql = array();
00322 $aFields = $this->getMultilangFields($sTable);
00323 $iMaxLang = $this->getCurrentMaxLangId();
00324 $iNewLang = $this->getNextLangId();
00325
00326 $sTableSet = getLangTableName($sTable, $iNewLang);
00327 if (!$this->tableExists($sTableSet)) {
00328 $aSql[] = $this->_getCreateTableSetSql( $sTable, $iNewLang );
00329 }
00330
00331 if ( is_array($aFields) && count($aFields) > 0 ) {
00332 foreach ( $aFields as $sField ) {
00333 $sNewFieldName = $sField . "_" . $iNewLang;
00334 if ( !$this->tableExists($sTableSet) || !$this->fieldExists( $sNewFieldName, $sTableSet ) ) {
00335
00336
00337 $aSql[] = $this->_getAddFieldSql($sTable, $sField, $iNewLang);
00338
00339
00340 $aSql = array_merge($aSql, (array) $this->_getAddFieldIndexSql($sTable, $sField, $iNewLang));
00341 }
00342 }
00343 }
00344 $this->_executeSql($aSql);
00345 }
00346
00356 public function resetMultilangFields( $iLangId, $sTableName )
00357 {
00358 $iLangId = (int)$iLangId;
00359
00360 if ( $iLangId === 0 ) {
00361 return;
00362 }
00363
00364 $aSql = array();
00365
00366 $aFields = $this->getMultilangFields( $sTableName );
00367 if ( is_array($aFields) && count($aFields) > 0 ) {
00368 foreach ( $aFields as $sFieldName ) {
00369 $sFieldName = $sFieldName . "_" . $iLangId;
00370
00371 if ( $this->fieldExists( $sFieldName, $sTableName ) ) {
00372
00373 $aSql[] = "UPDATE {$sTableName} SET {$sFieldName} = DEFAULT;";
00374 }
00375 }
00376 }
00377
00378 if ( !empty($aSql) ) {
00379 $this->_executeSql( $aSql );
00380 }
00381 }
00382
00389 public function addNewLangToDb()
00390 {
00391
00392 $this->_iCurrentMaxLangId = null;
00393
00394 $aTable = $this->getAllTables();
00395
00396 foreach ( $aTable as $sTableName ) {
00397 $this->addNewMultilangField( $sTableName );
00398 }
00399
00400
00401 $this->updateViews();
00402 }
00403
00412 public function resetLanguage( $iLangId )
00413 {
00414 if ( (int)$iLangId === 0 ) {
00415 return;
00416 }
00417
00418 $aTables = $this->getAllTables();
00419
00420
00421 foreach ( $this->_aSkipTablesOnReset as $sSkipTable ) {
00422
00423 if ( ($iSkipId = array_search( $sSkipTable, $aTables )) !== false ) {
00424 unset( $aTables[$iSkipId] );
00425 }
00426 }
00427
00428 foreach ( $aTables as $sTableName ) {
00429 $this->resetMultilangFields( $iLangId, $sTableName );
00430 }
00431 }
00432
00440 protected function _executeSql( $aSql )
00441 {
00442 $oDb = oxDb::getDb();
00443
00444 if ( is_array($aSql) && !empty($aSql) ) {
00445 foreach ( $aSql as $sSql) {
00446 $sSql = trim($sSql);
00447 if (!empty($sSql)) {
00448 $oDb->execute( $sSql );
00449 }
00450 }
00451 }
00452 }
00453
00459 public function updateViews()
00460 {
00461 oxDb::getInstance()->updateViews();
00462 }
00463
00464 }
00465