00001 <?php
00002
00007 class oxSeoEncoder extends oxSuperCfg
00008 {
00015 protected static $_aReservedWords = array( 'admin' );
00016
00022 protected static $_aReservedEntryKeys = null;
00023
00029 protected static $_sSeparator = null;
00030
00036 protected $_iIdLength = 255;
00037
00043 protected static $_sPrefix = null;
00044
00050 protected $_sAddParams = null;
00051
00057 protected static $_instance = null;
00058
00064 protected $_aSeoCache = array();
00065
00071 protected $_aFixedCache = array();
00072
00078 public static function getInstance()
00079 {
00080 if ( defined( 'OXID_PHP_UNIT' ) ) {
00081 self::$_instance = modInstances::getMod( __CLASS__ );
00082 }
00083
00084 if (!self::$_instance) {
00085 self::$_instance = oxNew("oxSeoEncoder");
00086 if ( defined( 'OXID_PHP_UNIT' ) ) {
00087 modInstances::addMod( __CLASS__, self::$_instance);
00088 }
00089 }
00090
00091 if ( defined( 'OXID_PHP_UNIT' ) ) {
00092
00093 self::$_instance->_aSeoCache = array();
00094 }
00095
00096 return self::$_instance;
00097
00098 }
00099
00108 public function addLanguageParam( $sSeoUrl, $iLang )
00109 {
00110 $iLang = (int) $iLang;
00111 $iDefLang = (int) $this->getConfig()->getConfigParam( 'iDefSeoLang' );
00112 $aLangIds = oxLang::getInstance()->getLanguageIds();
00113
00114 if ( $iLang != $iDefLang && isset( $aLangIds[$iLang] ) && getStr()->strpos( $sSeoUrl, $aLangIds[$iLang] . '/' ) !== 0 ) {
00115 $sSeoUrl = $aLangIds[$iLang] . '/'.$sSeoUrl;
00116 }
00117
00118 return $sSeoUrl;
00119 }
00120
00133 protected function _processSeoUrl( $sSeoUrl, $sObjectId = null, $iLang = null, $blExclude = false )
00134 {
00135 if (!$blExclude) {
00136 $sSeoUrl = $this->addLanguageParam( $sSeoUrl, $iLang );
00137 }
00138 return $this->_getUniqueSeoUrl( $sSeoUrl, $sObjectId, $iLang );
00139 }
00140
00146 public function resetCache()
00147 {
00148 $this->_aSeoCache = array();
00149 }
00150
00154 public function __construct()
00155 {
00156 $myConfig = $this->getConfig();
00157 if (!self::$_sSeparator) {
00158 $this->setSeparator( $myConfig->getConfigParam( 'sSEOSeparator' ) );
00159 }
00160 if (!self::$_sPrefix) {
00161 $this->setPrefix( $myConfig->getConfigParam( 'sSEOuprefix' ) );
00162 }
00163 $this->setReservedWords( $myConfig->getConfigParam( 'aSEOReservedWords' ) );
00164 }
00165
00177 protected function _copyToHistory( $sId, $iShopId, $iLang, $sType = null, $sNewId = null )
00178 {
00179 $oDb = oxDb::getDb();
00180 $sObjectid = $sNewId?$oDb->quote( $sNewId ):'oxobjectid';
00181 $sType = $sType?"oxtype =".$oDb->quote( $sType )." and":'';
00182 $iLang = (int) $iLang;
00183
00184
00185 $sSub = "select $sObjectid, MD5( LOWER( oxseourl ) ), oxshopid, oxlang, now() from oxseo
00186 where {$sType} oxobjectid = ".$oDb->quote( $sId )." and oxshopid = ".$oDb->quote( $iShopId )." and
00187 oxlang = {$iLang} and oxexpired = '1'";
00188 $sQ = "replace oxseohistory ( oxobjectid, oxident, oxshopid, oxlang, oxinsert ) {$sSub}";
00189 $oDb->execute( $sQ );
00190 }
00191
00200 public function getDynamicObjectId( $iShopId, $sStdUrl )
00201 {
00202 return $this->_getStaticObjectId( $iShopId, $sStdUrl );
00203 }
00204
00214 protected function _getDynamicUri( $sStdUrl, $sSeoUrl, $iLang )
00215 {
00216 $iShopId = $this->getConfig()->getShopId();
00217
00218 $sStdUrl = $this->_trimUrl( $sStdUrl );
00219 $sObjectId = $this->getDynamicObjectId( $iShopId, $sStdUrl );
00220 $sSeoUrl = $this->_prepareUri( $sSeoUrl );
00221
00222
00223 $sOldSeoUrl = $this->_loadFromDb( 'dynamic', $sObjectId, $iLang );
00224 if ( $sOldSeoUrl === $sSeoUrl ) {
00225 $sSeoUrl = $sOldSeoUrl;
00226 } else {
00227
00228 if ( $sOldSeoUrl ) {
00229
00230 $this->_copyToHistory( $sObjectId, $iShopId, $iLang, 'dynamic' );
00231 }
00232
00233
00234 $sSeoUrl = $this->_processSeoUrl( $sSeoUrl, $sObjectId, $iLang );
00235
00236
00237 $this->_saveToDb( 'dynamic', $sObjectId, $sStdUrl, $sSeoUrl, $iLang, $iShopId );
00238 }
00239
00240 return $sSeoUrl;
00241 }
00242
00252 protected function _getFullUrl( $sSeoUrl, $iLang = null, $blSsl = false )
00253 {
00254 if ( $sSeoUrl ) {
00255 $sFullUrl = ( $blSsl ? $this->getConfig()->getSslShopUrl( $iLang ) : $this->getConfig()->getShopUrl( $iLang ) ) . $sSeoUrl;
00256 return oxUtilsUrl::getInstance()->processSeoUrl( $sFullUrl );
00257 }
00258 return false;
00259 }
00260
00270 protected function _getSeoIdent( $sSeoUrl )
00271 {
00272 return md5( strtolower( $sSeoUrl ) );
00273 }
00274
00284 protected function _getStaticUri( $sStdUrl, $iShopId, $iLang )
00285 {
00286 $sStdUrl = $this->_trimUrl( $sStdUrl, $iLang );
00287 return $this->_loadFromDb( 'static', $this->_getStaticObjectId( $iShopId, $sStdUrl ), $iLang );
00288 }
00289
00295 protected function _getUrlExtension()
00296 {
00297 return;
00298 }
00299
00312 protected function _getUniqueSeoUrl( $sSeoUrl, $sObjectId = null, $iObjectLang = null )
00313 {
00314 $sSeoUrl = $this->_prepareUri( $sSeoUrl );
00315 $oStr = getStr();
00316 $sExt = '';
00317 if ( $oStr->preg_match( '/(\.html?|\/)$/i', $sSeoUrl, $aMatched ) ) {
00318 $sExt = $aMatched[0];
00319 }
00320 $sBaseSeoUrl = $sSeoUrl;
00321 if ( $sExt && $oStr->substr( $sSeoUrl, 0 - $oStr->strlen( $sExt ) ) == $sExt ) {
00322 $sBaseSeoUrl = $oStr->substr( $sSeoUrl, 0, $oStr->strlen( $sSeoUrl ) - $oStr->strlen( $sExt ) );
00323 }
00324
00325 $oDb = oxDb::getDb();
00326 $iShopId = $this->getConfig()->getShopId();
00327 $iCnt = 0;
00328 $sCheckSeoUrl = $this->_trimUrl( $sSeoUrl );
00329 $sQ = "select 1 from oxseo where oxshopid = '{$iShopId}'";
00330
00331
00332 if ( $sObjectId && isset($iObjectLang) ) {
00333 $iObjectLang = (int) $iObjectLang;
00334 $sQ .= " and not (oxobjectid = " . $oDb->quote( $sObjectId ) . " and oxlang = $iObjectLang)";
00335 }
00336
00337 while ( $oDb->getOne( $sQ ." and oxident= " . $oDb->quote( $this->_getSeoIdent( $sCheckSeoUrl ) ) ) ) {
00338 $sAdd = '';
00339 if ( self::$_sPrefix ) {
00340 $sAdd = self::$_sSeparator . self::$_sPrefix;
00341 }
00342 if ( $iCnt ) {
00343 $sAdd .= self::$_sSeparator . $iCnt;
00344 }
00345 ++$iCnt;
00346
00347 $sSeoUrl = $sBaseSeoUrl . $sAdd . $sExt;
00348 $sCheckSeoUrl = $this->_trimUrl( $sSeoUrl );
00349 }
00350 return $sSeoUrl;
00351 }
00352
00367 protected function _isFixed( $sType, $sId, $iLang, $iShopId = null, $sParams = null, $blStrictParamsCheck = true)
00368 {
00369 if ( $iShopId === null ) {
00370 $iShopId = $this->getConfig()->getShopId();
00371 }
00372 $iLang = (int) $iLang;
00373
00374 if ( !isset( $this->_aFixedCache[$sType][$sShopId][$sId][$iLang] ) ) {
00375 $oDb = oxDb::getDb( true );
00376
00377 $sQ = "select oxfixed from oxseo where oxtype = ".$oDb->quote( $sType )."
00378 and oxobjectid = ".$oDb->quote( $sId ) ." and oxshopid = ".$oDb->quote( $iShopId )." and oxlang = '{$iLang}'";
00379
00380 $sParams = $sParams ? $oDb->quote( $sParams ) : "''";
00381 if ( $sParams && $blStrictParamsCheck ) {
00382 $sQ .= " and oxparams = {$sParams}";
00383 } else {
00384 $sQ .= " order by oxparams = {$sParams} desc";
00385 }
00386 $sQ .= " limit 1";
00387
00388 $this->_aFixedCache[$sType][$sShopId][$sId][$iLang] = (bool) $oDb->getOne( $sQ );
00389 }
00390 return $this->_aFixedCache[$sType][$sShopId][$sId][$iLang];
00391 }
00392
00408 protected function _loadFromDb( $sType, $sId, $iLang, $iShopId = null, $sParams = null, $blStrictParamsCheck = true)
00409 {
00410 $oDb = oxDb::getDb( true );
00411 if ( $iShopId === null ) {
00412 $iShopId = $this->getConfig()->getShopId();
00413 }
00414
00415 $iLang = (int) $iLang;
00416
00417 $sQ = "select oxfixed, oxseourl, oxexpired, oxtype from oxseo where oxtype = ".$oDb->quote( $sType )."
00418 and oxobjectid = ".$oDb->quote( $sId ) ." and oxshopid = ".$oDb->quote( $iShopId )." and oxlang = '{$iLang}'";
00419
00420 $sParams = $sParams ? $sParams : '';
00421 if ( $sParams && $blStrictParamsCheck ) {
00422 $sQ .= " and oxparams = '{$sParams}'";
00423 } else {
00424 $sQ .= " order by oxparams = '{$sParams}' desc";
00425 }
00426 $sQ .= " limit 1";
00427
00428
00429 $sIdent = md5($sQ);
00430 if ( isset( $this->_aSeoCache[$sIdent] ) ) {
00431 return $this->_aSeoCache[$sIdent];
00432 }
00433
00434 $sSeoUrl = false;
00435 $oRs = $oDb->execute( $sQ );
00436 if ( $oRs && $oRs->recordCount() > 0 && !$oRs->EOF ) {
00437
00438 if ( $oRs->fields['oxexpired'] && ( $oRs->fields['oxtype'] == 'static' || $oRs->fields['oxtype'] == 'dynamic' ) ) {
00439
00440 $this->_copyToHistory( $sId, $iShopId, $iLang );
00441 $oDb->execute( "update oxseo set oxexpired = 0 where oxobjectid = ".$oDb->quote( $sId )." and oxlang = '{$iLang}'" );
00442 $sSeoUrl = $oRs->fields['oxseourl'];
00443 } elseif ( !$oRs->fields['oxexpired'] || $oRs->fields['oxfixed'] ) {
00444
00445 $sSeoUrl = $oRs->fields['oxseourl'];
00446 }
00447
00448
00449 $this->_aSeoCache[$sIdent] = $sSeoUrl;
00450 }
00451 return $sSeoUrl;
00452 }
00453
00460 protected function _getReservedEntryKeys()
00461 {
00462 if ( !isset( self::$_aReservedEntryKeys ) || !is_array( self::$_aReservedEntryKeys ) ) {
00463 $sDir = getShopBasePath();
00464 self::$_aReservedEntryKeys = array_map('preg_quote', self::$_aReservedWords, array('#'));
00465 $oStr = getStr();
00466 foreach ( glob( "$sDir/*" ) as $sFile ) {
00467 if ( $oStr->preg_match( '/^(.+)\.php[0-9]*$/i', basename( $sFile ), $aMatches ) ) {
00468 self::$_aReservedEntryKeys[] = preg_quote( $aMatches[0], '#' );
00469 self::$_aReservedEntryKeys[] = preg_quote( $aMatches[1], '#' );
00470 } elseif ( is_dir( $sFile ) ) {
00471 self::$_aReservedEntryKeys[] = preg_quote( basename( $sFile ), '#' );
00472 }
00473 }
00474 self::$_aReservedEntryKeys = array_unique(self::$_aReservedEntryKeys);
00475 }
00476 return self::$_aReservedEntryKeys;
00477 }
00478
00486 protected function _prepareUri( $sUri )
00487 {
00488
00489 $sUri = $this->encodeString( $sUri );
00490
00491
00492 $sUri = strip_tags( $sUri );
00493 $oStr = getStr();
00494
00495
00496
00497 $oStr = getStr();
00498 $sExt = $this->_getUrlExtension();
00499 if ($sExt === null) {
00500 $aMatched = array();
00501 if ( $oStr->preg_match( '/(\.html?|\/)$/i', $sUri, $aMatched ) ) {
00502 $sExt = $aMatched[0];
00503 } else {
00504 $sExt = '/';
00505 }
00506 }
00507 if ( $sExt && $oStr->substr( $sUri, 0 - $oStr->strlen( $sExt ) ) == $sExt ) {
00508 $sUri = $oStr->substr( $sUri, 0, $oStr->strlen( $sUri ) - $oStr->strlen( $sExt ) );
00509 }
00510
00511
00512 $sRegExp = '/[^A-Za-z0-9'.preg_quote( self::$_sSeparator, '/').preg_quote( self::$_sPrefix, '/').'\/]+/';
00513 $sUri = $oStr->preg_replace( array( "/\W*\/\W*/", $sRegExp ), array( "/", self::$_sSeparator ), $sUri );
00514
00515
00516 if ( !$sUri && self::$_sPrefix ) {
00517 $sUri = $this->_prepareUri( self::$_sPrefix );
00518 }
00519
00520 $sAdd = '';
00521 if ('/' != self::$_sSeparator) {
00522 $sAdd = self::$_sSeparator . self::$_sPrefix;
00523 $sUri = trim($sUri, self::$_sSeparator);
00524 } else {
00525 $sAdd = '_' . self::$_sPrefix;
00526 }
00527
00528
00529 $sUri .= $sExt;
00530
00531
00532 $sUri = $oStr->preg_replace( "#^(/*)(".implode('|', $this->_getReservedEntryKeys()).")(/|$)#i", "\$1\$2$sAdd\$3", $sUri );
00533
00534
00535 return $oStr->preg_replace( array( '|//+|', '/' . preg_quote( self::$_sSeparator . self::$_sSeparator, '/' ) .'+/' ),
00536 array( '/', self::$_sSeparator ), $sUri );
00537 }
00538
00539
00548 protected function _prepareTitle( $sTitle, $blSkipTruncate = false )
00549 {
00550 $sTitle = $this->encodeString( $sTitle );
00551 $sSep = self::$_sSeparator;
00552 if (!$sSep || ('/' == $sSep)) {
00553 $sSep = '_';
00554 }
00555
00556 $sRegExp = '/[^A-Za-z0-9\/'.preg_quote( self::$_sPrefix, '/').preg_quote($sSep, '/').']+/';
00557 $sTitle = preg_replace( array("#/+#", $sRegExp, "# +#", "#(".preg_quote($sSep, '/').")+#"), $sSep, $sTitle );
00558
00559 $oStr = getStr();
00560
00561 if ( !$blSkipTruncate && $oStr->strlen( $sTitle ) > $this->_iIdLength ) {
00562 $iFirstSpace = $oStr->strpos( $sTitle, $sSep, $this->_iIdLength);
00563 if ( $iFirstSpace !== false ) {
00564 $sTitle = $oStr->substr( $sTitle, 0, $iFirstSpace );
00565 }
00566 }
00567
00568 $sTitle = trim( $sTitle, $sSep );
00569
00570 if (!$sTitle) {
00571 return self::$_sPrefix;
00572 }
00573
00574 return $sTitle;
00575 }
00576
00577
00594 protected function _saveToDb( $sType, $sObjectId, $sStdUrl, $sSeoUrl, $iLang, $iShopId = null, $blFixed = null, $sParams = null )
00595 {
00596 $oDb = oxDb::getDb( true );
00597 if ( $iShopId === null ) {
00598 $iShopId = $this->getConfig()->getShopId();
00599 }
00600
00601 $iLang = (int) $iLang;
00602
00603 $sStdUrl = $this->_trimUrl( $sStdUrl );
00604 $sSeoUrl = $this->_trimUrl( $sSeoUrl );
00605 $sIdent = $this->_getSeoIdent( $sSeoUrl );
00606
00607
00608 $sQtedObjectId = $oDb->quote( $sObjectId );
00609 $iQtedShopId = $oDb->quote( $iShopId );
00610 $sQtedType = $oDb->quote( $sType );
00611 $sQtedSeoUrl = $oDb->quote( $sSeoUrl );
00612 $sQtedStdUrl = $oDb->quote( $sStdUrl );
00613 $sQtedParams = $oDb->quote( $sParams );
00614 $sQtedIdent = $oDb->quote( $sIdent );
00615
00616
00617 $sQ = "select oxfixed, oxexpired, ( oxstdurl like {$sQtedStdUrl} ) as samestdurl,
00618 oxseourl like {$sQtedSeoUrl} as sameseourl from oxseo where oxtype = {$sQtedType} and
00619 oxobjectid = {$sQtedObjectId} and oxshopid = {$iQtedShopId} and oxlang = {$iLang} ";
00620
00621 $sQ .= $sParams ? " and oxparams = {$sQtedParams} " : '';
00622
00623 $sQ .= "limit 1";
00624
00625 $oRs = $oDb->execute( $sQ );
00626 if ( $oRs && $oRs->recordCount() > 0 && !$oRs->EOF ) {
00627 if ( $oRs->fields['samestdurl'] && $oRs->fields['sameseourl'] && $oRs->fields['oxexpired'] ) {
00628
00629 $sFixed = isset( $blFixed ) ? ", oxfixed = " . ( (int) $blFixed ) . " " : '';
00630
00631 $sSql = "update oxseo set oxexpired = 0 {$sFixed} where oxtype = {$sQtedType} and
00632 oxobjectid = {$sQtedObjectId} and oxshopid = {$iQtedShopId} and oxlang = {$iLang} ";
00633 $sSql .= $sParams ? " and oxparams = {$sQtedParams} " : '';
00634 $sSql .= " limit 1";
00635
00636 return $oDb->execute( $sSql );
00637 } elseif ( $oRs->fields['oxexpired'] ) {
00638
00639 $this->_copyToHistory( $sObjectId, $iShopId, $iLang, $sType );
00640 }
00641 }
00642
00643
00644 $sParams = $sParams ? $oDb->quote( $sParams ) :'""';
00645 $blFixed = (int) $blFixed;
00646
00647 $sQ = "insert into oxseo
00648 (oxobjectid, oxident, oxshopid, oxlang, oxstdurl, oxseourl, oxtype, oxfixed, oxexpired, oxparams)
00649 values
00650 ( {$sQtedObjectId}, {$sQtedIdent}, {$iQtedShopId}, {$iLang}, {$sQtedStdUrl}, {$sQtedSeoUrl}, {$sQtedType}, '$blFixed', '0', {$sParams} )
00651 on duplicate key update
00652 oxident = {$sQtedIdent}, oxstdurl = {$sQtedStdUrl}, oxseourl = {$sQtedSeoUrl}, oxfixed = '$blFixed', oxexpired = '0'";
00653
00654 return $oDb->execute( $sQ );
00655 }
00656
00667 protected function _trimUrl( $sUrl, $iLang = null )
00668 {
00669 $myConfig = $this->getConfig();
00670 $oStr = getStr();
00671 $sUrl = str_replace( array( $myConfig->getShopUrl( $iLang ), $myConfig->getSslShopUrl( $iLang ) ), '', $sUrl );
00672 $sUrl = $oStr->preg_replace( '/(\?|&(amp;)?)(force_)?(admin_)?sid=[a-z0-9\.]+&?(amp;)?/i', '\1', $sUrl );
00673 $sUrl = $oStr->preg_replace( '/(\?|&(amp;)?)shp=[0-9]+&?(amp;)?/i', '\1', $sUrl );
00674 $sUrl = $oStr->preg_replace( '/(\?|&(amp;)?)lang=[0-9]+&?(amp;)?/i', '\1', $sUrl );
00675 $sUrl = $oStr->preg_replace( '/(\?|&(amp;)?)cur=[0-9]+&?(amp;)?/i', '\1', $sUrl );
00676 $sUrl = $oStr->preg_replace( '/(\?|&(amp;)?)stoken=[a-z0-9]+&?(amp;)?/i', '\1', $sUrl );
00677 $sUrl = $oStr->preg_replace( '/(\?|&(amp;)?)&(amp;)?/i', '\1', $sUrl );
00678 $sUrl = $oStr->preg_replace( '/(\?|&(amp;)?)+$/i', '', $sUrl );
00679 return trim($sUrl);
00680 }
00681
00690 public function encodeString( $sString, $blReplaceChars = true )
00691 {
00692
00693 $sString = getStr()->html_entity_decode( $sString );
00694
00695 if ( $blReplaceChars ) {
00696 $aReplaceChars = $this->getConfig()->getConfigParam( 'aSeoReplaceChars' );
00697 $sString = str_replace( array_keys( $aReplaceChars ), array_values( $aReplaceChars ), $sString );
00698 }
00699
00700
00701 $aReplaceWhat = array( '&', '"', ''', '<', '>' );
00702 return str_replace( $aReplaceWhat, '', $sString );
00703 }
00704
00712 public function setSeparator( $sSeparator = null )
00713 {
00714 self::$_sSeparator = $sSeparator;
00715 if ( !self::$_sSeparator ) {
00716 self::$_sSeparator = '-';
00717 }
00718 }
00719
00727 public function setPrefix( $sPrefix )
00728 {
00729 if ($sPrefix) {
00730 self::$_sPrefix = $sPrefix;
00731 } else {
00732 self::$_sPrefix = 'oxid';
00733 }
00734 }
00735
00743 public function setIdLength( $iIdlength = null )
00744 {
00745 if ( isset( $iIdlength ) ) {
00746 $this->_iIdLength = $iIdlength;
00747 }
00748 }
00749
00758 public function setReservedWords( $aReservedWords )
00759 {
00760 self::$_aReservedWords = array_merge( self::$_aReservedWords, $aReservedWords );
00761 }
00762
00763
00775 public function markAsExpired( $sId, $iShopId = null, $iExpStat = 1, $iLang = null, $sParams = null )
00776 {
00777 $oDb = oxDb::getDb();
00778 $sWhere = $sId ? "where oxobjectid = " . $oDb->quote( $sId ) : '';
00779 $sWhere .= isset( $iShopId ) ? ( $sWhere ? " and oxshopid = ". $oDb->quote( $iShopId ) : "where oxshopid = ". $oDb->quote( $iShopId ) ) : '';
00780 $sWhere .= $iLang ? ( $sWhere ? " and oxlang = '{$iLang}'" : "where oxlang = '{$iLang}'" ) : '';
00781 $sWhere .= $sParams ? ( $sWhere ? " and {$sParams}" : "where {$sParams}" ) : '';
00782
00783 $sQ = "update oxseo set oxexpired = " . $oDb->quote( $iExpStat ) . " $sWhere ";
00784 $oDb->execute( $sQ );
00785 }
00786
00800 protected function _getPageUri( $oObject, $sType, $sStdUrl, $sSeoUrl, $sParams, $iLang = null, $blFixed = false )
00801 {
00802 if ( !isset( $iLang ) ) {
00803 $iLang = $oObject->getLanguage();
00804 }
00805 $iShopId = $this->getConfig()->getShopId();
00806
00807
00808 $sOldSeoUrl = $this->_loadFromDb( $sType, $oObject->getId(), $iLang, $iShopId, $sParams );
00809 if ( !$sOldSeoUrl ) {
00810
00811 $sSeoUrl = $this->_processSeoUrl( $sSeoUrl, $oObject->getId(), $iLang );
00812 $this->_saveToDb( $sType, $oObject->getId(), $sStdUrl, $sSeoUrl, $iLang, $iShopId, (int) $blFixed, $sParams );
00813 } else {
00814
00815 $sSeoUrl = $sOldSeoUrl;
00816 }
00817 return $sSeoUrl;
00818 }
00819
00828 protected function _getStaticObjectId( $iShopId, $sStdUrl )
00829 {
00830 return md5( strtolower ( $iShopId . $this->_trimUrl( $sStdUrl ) ) );
00831 }
00832
00842 public function encodeStaticUrls( $aStaticUrl, $iShopId, $iLang )
00843 {
00844 $oDb = oxDb::getDb();
00845 $sValues = '';
00846 $sOldObjectId = null;
00847
00848
00849 $sStdUrl = $this->_trimUrl( trim( $aStaticUrl['oxseo__oxstdurl'] ) );
00850 $sObjectId = $aStaticUrl['oxseo__oxobjectid'];
00851
00852 if ( !$sObjectId || $sObjectId == '-1' ) {
00853 $sObjectId = $this->_getStaticObjectId( $iShopId, $sStdUrl );
00854 } else {
00855
00856 $sOldObjectId = $sObjectId;
00857
00858
00859 if ( $this->_getStaticObjectId( $iShopId, $sStdUrl ) != $sObjectId ) {
00860 $sObjectId = $this->_getStaticObjectId( $iShopId, $sStdUrl );
00861 }
00862 }
00863
00864 foreach ( $aStaticUrl['oxseo__oxseourl'] as $iLang => $sSeoUrl ) {
00865
00866 $iLang = (int) $iLang;
00867
00868
00869 $sSeoUrl = $this->_trimUrl( $sSeoUrl );
00870 if ( $sSeoUrl ) {
00871 $sSeoUrl = $this->_processSeoUrl( $sSeoUrl, $sObjectId, $iLang );
00872 }
00873
00874
00875 if ( $sOldObjectId ) {
00876
00877 if ( !$oDb->getOne( "select (" . $oDb->quote( $sSeoUrl ) . " like oxseourl) & (" . $oDb->quote( $sStdUrl ) . " like oxstdurl) from oxseo where oxobjectid = ".$oDb->quote( $sOldObjectId )." and oxshopid = '{$iShopId}' and oxlang = '{$iLang}' " ) ) {
00878 $this->_copyToHistory( $sOldObjectId, $iShopId, $iLang, 'static', $sObjectId );
00879 }
00880 }
00881
00882 if ( !$sSeoUrl || !$sStdUrl ) {
00883 continue;
00884 }
00885
00886 $sIdent = $this->_getSeoIdent( $sSeoUrl );
00887
00888 if ( $sValues ) {
00889 $sValues .= ', ';
00890 }
00891
00892 $sValues .= "( " . $oDb->quote( $sObjectId ) . ", " . $oDb->quote( $sIdent ) . ", " . $oDb->quote( $iShopId ).", '{$iLang}', " . $oDb->quote( $sStdUrl ) . ", " . $oDb->quote( $sSeoUrl ) . ", 'static' )";
00893 }
00894
00895
00896 if ( $sOldObjectId ) {
00897 $oDb->execute( "delete from oxseo where oxobjectid in ( " . $oDb->quote( $sOldObjectId ) . ", " . $oDb->quote( $sObjectId ) . " )" );
00898 }
00899
00900
00901 if ( $sValues ) {
00902
00903 $sQ = "insert into oxseo ( oxobjectid, oxident, oxshopid, oxlang, oxstdurl, oxseourl, oxtype ) values {$sValues} ";
00904 $oDb->execute( $sQ );
00905 }
00906
00907 return $sObjectId;
00908 }
00909
00917 public function copyStaticUrls( $iShopId )
00918 {
00919 $iBaseShopId = $this->getConfig()->getBaseShopId();
00920 if ( $iShopId != $iBaseShopId ) {
00921 $oDb = oxDb::getDb();
00922 foreach (array_keys(oxLang::getInstance()->getLanguageIds()) as $iLang) {
00923 $sQ = "insert into oxseo ( oxobjectid, oxident, oxshopid, oxlang, oxstdurl, oxseourl, oxtype )
00924 select MD5( LOWER( CONCAT( " . $oDb->quote( $iShopId ) . ", oxstdurl ) ) ), MD5( LOWER( oxseourl ) ),
00925 " . $oDb->quote( $iShopId ) . ", oxlang, oxstdurl, oxseourl, oxtype from oxseo where oxshopid = '{$iBaseShopId}' and oxtype = 'static' and oxlang='$iLang' ";
00926 $oDb->execute( $sQ );
00927 }
00928 }
00929 }
00930
00940 public function getStaticUrl( $sStdUrl, $iLang = null, $iShopId = null )
00941 {
00942 if (!isset($iShopId)) {
00943 $iShopId = $this->getConfig()->getShopId();
00944 }
00945 if (!isset($iLang)) {
00946 $iLang = oxLang::getInstance()->getEditLanguage();
00947 }
00948
00949 if ( isset($this->_aStaticUrlCache[$sStdUrl][$iLang][$iShopId])) {
00950 return $this->_aStaticUrlCache[$sStdUrl][$iLang][$iShopId];
00951 }
00952
00953 $sFullUrl = '';
00954 if ( ( $sSeoUrl = $this->_getStaticUri( $sStdUrl, $iShopId, $iLang ) ) ) {
00955 $sFullUrl = $this->_getFullUrl( $sSeoUrl, $iLang, strpos( $sStdUrl, "https:" ) === 0 );
00956 }
00957
00958
00959 $this->_aStaticUrlCache[$sStdUrl][$iLang][$iShopId] = $sFullUrl;
00960
00961 return $sFullUrl;
00962 }
00963
00982 public function addSeoEntry( $sObjectId, $iShopId, $iLang, $sStdUrl, $sSeoUrl, $sType, $blFixed = 1, $sKeywords = '', $sDescription = '', $sParams = '', $blExclude = false, $sAltObjectId = null )
00983 {
00984 $sSeoUrl = $this->_processSeoUrl( $this->_trimUrl( $sSeoUrl ? $sSeoUrl : $this->_getAltUri( $sAltObjectId ? $sAltObjectId : $sObjectId, $iLang ) ), $sObjectId, $iLang, $blExclude );
00985 if ( $this->_saveToDb( $sType, $sObjectId, $sStdUrl, $sSeoUrl, $iLang, $iShopId, $blFixed, $sParams ) ) {
00986
00987 $oDb = oxDb::getDb( true );
00988
00989
00990 $sQtedObjectId = $oDb->quote( $sAltObjectId ? $sAltObjectId : $sObjectId );
00991 $iQtedShopId = $oDb->quote( $iShopId );
00992
00993 $oStr = getStr();
00994 if ( $sKeywords !== false ) {
00995 $sKeywords = $oDb->quote( $oStr->htmlspecialchars( $this->encodeString( strip_tags( $sKeywords ), false ) ) );
00996 }
00997
00998 if ( $sDescription !== false ) {
00999 $sDescription = $oDb->quote( $oStr->htmlspecialchars( strip_tags( $sDescription ) ) );
01000 }
01001
01002 $sQ = "insert into oxobject2seodata
01003 ( oxobjectid, oxshopid, oxlang, oxkeywords, oxdescription )
01004 values
01005 ( {$sQtedObjectId}, {$iQtedShopId}, {$iLang}, ".( $sKeywords ? $sKeywords : "''" ).", ".( $sDescription ? $sDescription : "''" )." )
01006 on duplicate key update
01007 oxkeywords = ".( $sKeywords ? $sKeywords : "oxkeywords" ).", oxdescription = ".( $sDescription ? $sDescription : "oxdescription" );
01008 $oDb->execute( $sQ );
01009 }
01010 }
01011
01020 protected function _getAltUri( $sObjectId, $iLang )
01021 {
01022 }
01023
01034 public function deleteSeoEntry( $sObjectId, $iShopId, $iLang, $sType )
01035 {
01036 $oDb = oxDb::getDb();
01037 $sQ = "delete from oxseo where oxobjectid = " . $oDb->quote( $sObjectId ) . " and oxshopid = " . $oDb->quote( $iShopId ) . " and oxlang = " . $oDb->quote( $iLang ) . " and oxtype = " . $oDb->quote( $sType ) . " ";
01038 oxDb::getDb()->execute( $sQ );
01039 }
01040
01051 public function getMetaData( $sObjectId, $sMetaType, $iShopId = null, $iLang = null )
01052 {
01053 $oDb = oxDb::getDb();
01054
01055 $iShopId = ( !isset( $iShopId ) ) ? $this->getConfig()->getShopId():$iShopId;
01056 $iLang = ( !isset( $iLang ) ) ? oxLang::getInstance()->getObjectTplLanguage():((int) $iLang);
01057 return $oDb->getOne( "select {$sMetaType} from oxobject2seodata where oxobjectid = " . $oDb->quote( $sObjectId ) . " and oxshopid = " . $oDb->quote( $iShopId )." and oxlang = '{$iLang}'" );
01058 }
01059
01073 public function getDynamicUrl( $sStdUrl, $sSeoUrl, $iLang )
01074 {
01075 startProfile("getDynamicUrl");
01076 $sDynUrl = $this->_getFullUrl( $this->_getDynamicUri( $sStdUrl, $sSeoUrl, $iLang ), strpos( $sStdUrl, "https:" ) === 0 );
01077 stopProfile("getDynamicUrl");
01078 return $sDynUrl;
01079 }
01080
01089 public function fetchSeoUrl( $sStdUrl, $iLanguage = null )
01090 {
01091 $oDb = oxDb::getDb( true );
01092 $iLanguage = isset( $iLanguage ) ? ( (int) $iLanguage ) : oxLang::getInstance()->getBaseLanguage();
01093 $sSeoUrl = false;
01094
01095 $sShopId = $this->getConfig()->getShopId();
01096
01097 $sQ = "select oxseourl, oxlang from oxseo where oxstdurl = ".$oDb->quote( $sStdUrl )." and oxlang = '$iLanguage' and oxshopid = '$sShopId' limit 1";
01098 $oRs = $oDb->execute( $sQ );
01099 if ( !$oRs->EOF ) {
01100 $sSeoUrl = $oRs->fields['oxseourl'];
01101 }
01102
01103 return $sSeoUrl;
01104 }
01105 }