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 return $this->_getUniqueSeoUrl( $blExclude ? $sSeoUrl : $this->addLanguageParam( $sSeoUrl, $iLang ), $sObjectId, $iLang );
00136 }
00137
00143 public function resetCache()
00144 {
00145 $this->_aSeoCache = array();
00146 }
00147
00151 public function __construct()
00152 {
00153 $myConfig = $this->getConfig();
00154 if (!self::$_sSeparator) {
00155 $this->setSeparator( $myConfig->getConfigParam( 'sSEOSeparator' ) );
00156 }
00157 if (!self::$_sPrefix) {
00158 $this->setPrefix( $myConfig->getConfigParam( 'sSEOuprefix' ) );
00159 }
00160 $this->setReservedWords( $myConfig->getConfigParam( 'aSEOReservedWords' ) );
00161 }
00162
00174 protected function _copyToHistory( $sId, $iShopId, $iLang, $sType = null, $sNewId = null )
00175 {
00176 $oDb = oxDb::getDb();
00177 $sObjectid = $sNewId?$oDb->quote( $sNewId ):'oxobjectid';
00178 $sType = $sType?"oxtype =".$oDb->quote( $sType )." and":'';
00179 $iLang = (int) $iLang;
00180
00181
00182 $sSub = "select $sObjectid, MD5( LOWER( oxseourl ) ), oxshopid, oxlang, now() from oxseo
00183 where {$sType} oxobjectid = ".$oDb->quote( $sId )." and oxshopid = ".$oDb->quote( $iShopId )." and
00184 oxlang = {$iLang} and oxexpired = '1'";
00185 $sQ = "replace oxseohistory ( oxobjectid, oxident, oxshopid, oxlang, oxinsert ) {$sSub}";
00186 $oDb->execute( $sQ );
00187 }
00188
00197 protected function _getAddParams()
00198 {
00199
00200 if ( $this->_sAddParams === null ) {
00201 $this->_sAddParams = $this->_getAddParamsFnc( oxConfig::getParameter('currency'), $this->getConfig()->getShopId() );
00202 }
00203 return $this->_sAddParams;
00204 }
00205
00217 protected function _getAddParamsFnc( $iCur, $iActShop )
00218 {
00219 $sParams = '';
00220 if ( count( $aParams = oxUtilsUrl::getInstance()->getAddUrlParams() ) ) {
00221 foreach ( $aParams as $sName => $sValue ) {
00222 if ( $sValue ) {
00223 if ( $sParams ) {
00224 $sParams .= "&";
00225 }
00226 $sParams .= $sName . "=" . $sValue;
00227 }
00228 }
00229 if ( $sParams ) {
00230 $sParams = '?'.$sParams;
00231 }
00232 }
00233 return $sParams;
00234 }
00235
00246 protected function _getDynamicObjectId( $iShopId, $sStdUrl )
00247 {
00248 return $this->getDynamicObjectId( $iShopId, $sStdUrl );
00249 }
00250
00259 public function getDynamicObjectId( $iShopId, $sStdUrl )
00260 {
00261 return $this->_getStaticObjectId( $iShopId, $sStdUrl );
00262 }
00263
00273 protected function _getDynamicUri( $sStdUrl, $sSeoUrl, $iLang )
00274 {
00275 $iShopId = $this->getConfig()->getShopId();
00276
00277 $sStdUrl = $this->_trimUrl( $sStdUrl );
00278 $sObjectId = $this->getDynamicObjectId( $iShopId, $sStdUrl );
00279 $sSeoUrl = $this->_prepareUri( $sSeoUrl );
00280
00281
00282 $sOldSeoUrl = $this->_loadFromDb( 'dynamic', $sObjectId, $iLang );
00283 if ( $sOldSeoUrl === $sSeoUrl ) {
00284 $sSeoUrl = $sOldSeoUrl;
00285 } else {
00286
00287 if ( $sOldSeoUrl ) {
00288
00289 $this->_copyToHistory( $sObjectId, $iShopId, $iLang, 'dynamic' );
00290 }
00291
00292
00293 $sSeoUrl = $this->_processSeoUrl( $sSeoUrl, $sObjectId, $iLang );
00294
00295
00296 $this->_saveToDb( 'dynamic', $sObjectId, $sStdUrl, $sSeoUrl, $iLang, $iShopId );
00297 }
00298
00299 return $sSeoUrl;
00300 }
00301
00311 protected function _getFullUrl( $sSeoUrl, $iLang = null, $blSsl = false )
00312 {
00313 $sProcessedUrl = false;
00314 if ( $sSeoUrl ) {
00315 $sFullUrl = ( $blSsl ? $this->getConfig()->getSslShopUrl( $iLang ) : $this->getConfig()->getShopUrl( $iLang ) ) . $sSeoUrl;
00316 $sProcessedUrl = oxUtilsUrl::getInstance()->processSeoUrl( $sFullUrl );
00317 }
00318 return $sProcessedUrl;
00319 }
00320
00331 protected function _getSeoIdent( $sSeoUrl, $iLang = null )
00332 {
00333 return md5( strtolower( $sSeoUrl ) );
00334 }
00335
00345 protected function _getStaticUri( $sStdUrl, $iShopId, $iLang )
00346 {
00347 $sStdUrl = $this->_trimUrl( $sStdUrl, $iLang );
00348 return $this->_loadFromDb( 'static', $this->_getStaticObjectId( $iShopId, $sStdUrl ), $iLang );
00349 }
00350
00356 protected function _getUrlExtension()
00357 {
00358 return;
00359 }
00360
00373 protected function _getUniqueSeoUrl( $sSeoUrl, $sObjectId = null, $iObjectLang = null )
00374 {
00375 $oStr = getStr();
00376 $sConstEnd = $this->_getUrlExtension();
00377 if ($sConstEnd === null) {
00378 $aMatched = array();
00379 if ( $oStr->preg_match( '/\.html?$/i', $sSeoUrl, $aMatched ) ) {
00380 $sConstEnd = $aMatched[0];
00381 } else {
00382 if ($sSeoUrl{$oStr->strlen($sSeoUrl)-1} != '/') {
00383 $sSeoUrl .= '/';
00384 }
00385 $sConstEnd = '/';
00386 }
00387 }
00388
00389
00390 $sAdd = ' ';
00391 if ('/' != self::$_sSeparator) {
00392 $sAdd = self::$_sSeparator . self::$_sPrefix;
00393 } else {
00394 $sAdd = '_' . self::$_sPrefix;
00395 }
00396 $sSeoUrl = $oStr->preg_replace( "#^(/*)(".implode('|', $this->_getReservedEntryKeys()).")/#i", "\$1\$2$sAdd/", $sSeoUrl );
00397
00398 $sBaseSeoUrl = $sSeoUrl;
00399 if ( $sConstEnd && $oStr->substr( $sSeoUrl, 0 - $oStr->strlen( $sConstEnd ) ) == $sConstEnd ) {
00400 $sBaseSeoUrl = $oStr->substr( $sSeoUrl, 0, $oStr->strlen( $sSeoUrl ) - $oStr->strlen( $sConstEnd ) );
00401 }
00402
00403 $oDb = oxDb::getDb();
00404 $iShopId = $this->getConfig()->getShopId();
00405 $iCnt = 0;
00406 $sCheckSeoUrl = $this->_trimUrl( $sSeoUrl );
00407 $sQ = "select 1 from oxseo where oxshopid = '{$iShopId}'";
00408
00409
00410 if ( $sObjectId && isset($iObjectLang) ) {
00411 $iObjectLang = (int) $iObjectLang;
00412 $sQ .= " and not (oxobjectid = " . $oDb->quote( $sObjectId ) . " and oxlang = $iObjectLang)";
00413 }
00414
00415 while ( $oDb->getOne( $sQ ." and oxident= " . $oDb->quote( $this->_getSeoIdent( $sCheckSeoUrl ) ) ) ) {
00416 $sAdd = '';
00417 if ( self::$_sPrefix ) {
00418 $sAdd = self::$_sSeparator . self::$_sPrefix;
00419 }
00420 if ( $iCnt ) {
00421 $sAdd .= self::$_sSeparator . $iCnt;
00422 }
00423 ++$iCnt;
00424
00425 $sSeoUrl = $sBaseSeoUrl . $sAdd . $sConstEnd;
00426 $sCheckSeoUrl = $this->_trimUrl( $sSeoUrl );
00427 }
00428 return $sSeoUrl;
00429 }
00430
00445 protected function _isFixed( $sType, $sId, $iLang, $iShopId = null, $sParams = null, $blStrictParamsCheck = true)
00446 {
00447 if ( $iShopId === null ) {
00448 $iShopId = $this->getConfig()->getShopId();
00449 }
00450 $iLang = (int) $iLang;
00451
00452 if ( !isset( $this->_aFixedCache[$sType][$sShopId][$sId][$iLang] ) ) {
00453 $oDb = oxDb::getDb( true );
00454
00455 $sQ = "select oxfixed from oxseo where oxtype = ".$oDb->quote( $sType )."
00456 and oxobjectid = ".$oDb->quote( $sId ) ." and oxshopid = ".$oDb->quote( $iShopId )." and oxlang = '{$iLang}'";
00457
00458 $sParams = $sParams ? $oDb->quote( $sParams ) : "''";
00459 if ( $sParams && $blStrictParamsCheck ) {
00460 $sQ .= " and oxparams = {$sParams}";
00461 } else {
00462 $sQ .= " order by oxparams = {$sParams} desc";
00463 }
00464 $sQ .= " limit 1";
00465
00466 $this->_aFixedCache[$sType][$sShopId][$sId][$iLang] = (bool) $oDb->getOne( $sQ );
00467 }
00468 return $this->_aFixedCache[$sType][$sShopId][$sId][$iLang];
00469 }
00470
00486 protected function _loadFromDb( $sType, $sId, $iLang, $iShopId = null, $sParams = null, $blStrictParamsCheck = true)
00487 {
00488 $oDb = oxDb::getDb( true );
00489 if ( $iShopId === null ) {
00490 $iShopId = $this->getConfig()->getShopId();
00491 }
00492
00493 $iLang = (int) $iLang;
00494
00495 $sQ = "select oxfixed, oxseourl, oxexpired, oxtype from oxseo where oxtype = ".$oDb->quote( $sType )."
00496 and oxobjectid = ".$oDb->quote( $sId ) ." and oxshopid = ".$oDb->quote( $iShopId )." and oxlang = '{$iLang}'";
00497
00498 $sParams = $sParams ? $sParams : '';
00499 if ( $sParams && $blStrictParamsCheck ) {
00500 $sQ .= " and oxparams = '{$sParams}'";
00501 } else {
00502 $sQ .= " order by oxparams = '{$sParams}' desc";
00503 }
00504 $sQ .= " limit 1";
00505
00506
00507 $sIdent = md5($sQ);
00508 if ( isset( $this->_aSeoCache[$sIdent] ) ) {
00509 return $this->_aSeoCache[$sIdent];
00510 }
00511
00512 $sSeoUrl = false;
00513 $oRs = $oDb->execute( $sQ );
00514 if ( $oRs && $oRs->recordCount() > 0 && !$oRs->EOF ) {
00515
00516 if ( $oRs->fields['oxexpired'] && ( $oRs->fields['oxtype'] == 'static' || $oRs->fields['oxtype'] == 'dynamic' ) ) {
00517
00518 $this->_copyToHistory( $sId, $iShopId, $iLang );
00519 $oDb->execute( "update oxseo set oxexpired = 0 where oxobjectid = ".$oDb->quote( $sId )." and oxlang = '{$iLang}'" );
00520 $sSeoUrl = $oRs->fields['oxseourl'];
00521 } elseif ( !$oRs->fields['oxexpired'] || $oRs->fields['oxfixed'] ) {
00522
00523 $sSeoUrl = $oRs->fields['oxseourl'];
00524 }
00525
00526
00527 $this->_aSeoCache[$sIdent] = $sSeoUrl;
00528 }
00529 return $sSeoUrl;
00530 }
00531
00538 protected function _getReservedEntryKeys()
00539 {
00540 if ( !isset( self::$_aReservedEntryKeys ) && !is_array( self::$_aReservedEntryKeys ) ) {
00541 $sDir = getShopBasePath();
00542 self::$_aReservedEntryKeys = array();
00543 $oStr = getStr();
00544 foreach ( glob( "$sDir/*" ) as $sFile ) {
00545 if ( $oStr->preg_match( '/^(.+)\.php[0-9]*$/i', basename( $sFile ), $aMatches ) ) {
00546 self::$_aReservedEntryKeys[] = preg_quote( $aMatches[0] );
00547 self::$_aReservedEntryKeys[] = preg_quote( $aMatches[1] );
00548 } elseif ( is_dir( $sFile ) ) {
00549 self::$_aReservedEntryKeys[] = preg_quote( basename( $sFile ) );
00550 }
00551 }
00552 }
00553 return self::$_aReservedEntryKeys;
00554 }
00555
00563 protected function _prepareUri( $sUri )
00564 {
00565
00566 $sUri = $this->encodeString( $sUri );
00567
00568
00569 $sUri = strip_tags( $sUri );
00570 $oStr = getStr();
00571
00572 $sSeparator = self::$_sSeparator;
00573 $sPrefix = self::$_sPrefix;
00574
00575 foreach ( self::$_aReservedWords as $sWord ) {
00576 $sWord = preg_quote( $sWord );
00577 $sUri = $oStr->preg_replace( array( "/(\s{$sWord})$/i", "/^({$sWord}\s)/i", "/(\s{$sWord}\s)/i", "/^({$sWord})$/i",
00578 "/(\/{$sWord})$/i", "/^({$sWord}\/)/i", "/(\/{$sWord}\/)/i"),
00579 " \$1{$sSeparator}{$sPrefix}{$sSeparator} ", $sUri );
00580 }
00581
00582
00583 $sExt = '';
00584 $oStr = getStr();
00585 $aMatched = array();
00586 if ( $oStr->preg_match( '/\.html?$/i', $sUri, $aMatched ) ) {
00587 $sExt = $oStr->substr( $sUri, 0 - $oStr->strlen( $aMatched[0] ) );
00588 $sUri = $oStr->substr( $sUri, 0, $oStr->strlen( $sUri ) - $oStr->strlen( $aMatched[0] ) );
00589 }
00590
00591
00592 $sRegExp = '/[^A-Za-z0-9'.preg_quote( self::$_sSeparator, '/').preg_quote( self::$_sPrefix, '/').'\/]+/';
00593 $sUri = trim( $oStr->preg_replace( array( "/\W*\/\W*/", $sRegExp ), array( "/", self::$_sSeparator ), $sUri ), self::$_sSeparator );
00594
00595
00596 if ( !$sUri ) {
00597 $sUri = $this->_prepareUri( self::$_sPrefix );
00598 }
00599
00600
00601 $sUri .= $sExt;
00602
00603
00604 return $oStr->preg_replace( array( '|//+|', '/' . preg_quote( self::$_sSeparator . self::$_sSeparator, '/' ) .'+/' ),
00605 array( '/', self::$_sSeparator ), $sUri );
00606 }
00607
00616 protected function _prepareTitle( $sTitle, $blSkipTruncate = false )
00617 {
00618 $sTitle = $this->_prepareUri( str_replace( "/", self::$_sSeparator, $sTitle ) );
00619
00620 $oStr = getStr();
00621
00622 if ( !$blSkipTruncate && $oStr->strlen( $sTitle ) > $this->_iIdLength ) {
00623 if ( ( $iFirstSpace = $oStr->strstr( $oStr->substr( $sTitle, $this->_iIdLength ), self::$_sSeparator ) !== false ) ) {
00624 $sTitle = trim( $oStr->substr( $sTitle, 0, $this->_iIdLength + $iFirstSpace ), self::$_sSeparator );
00625 }
00626 }
00627
00628
00629 return $sTitle;
00630 }
00631
00632
00649 protected function _saveToDb( $sType, $sObjectId, $sStdUrl, $sSeoUrl, $iLang, $iShopId = null, $blFixed = null, $sParams = null )
00650 {
00651 $oDb = oxDb::getDb( true );
00652 if ( $iShopId === null ) {
00653 $iShopId = $this->getConfig()->getShopId();
00654 }
00655
00656 $iLang = (int) $iLang;
00657
00658 $sStdUrl = $this->_trimUrl( $sStdUrl );
00659 $sSeoUrl = $this->_trimUrl( $sSeoUrl );
00660 $sIdent = $this->_getSeoIdent( $sSeoUrl );
00661
00662
00663 $sQtedObjectId = $oDb->quote( $sObjectId );
00664 $iQtedShopId = $oDb->quote( $iShopId );
00665 $sQtedType = $oDb->quote( $sType );
00666 $sQtedSeoUrl = $oDb->quote( $sSeoUrl );
00667 $sQtedStdUrl = $oDb->quote( $sStdUrl );
00668 $sQtedParams = $oDb->quote( $sParams );
00669 $sQtedIdent = $oDb->quote( $sIdent );
00670
00671
00672 $sQ = "select oxfixed, oxexpired, ( oxstdurl like {$sQtedStdUrl} ) as samestdurl,
00673 oxseourl like {$sQtedSeoUrl} as sameseourl from oxseo where oxtype = {$sQtedType} and
00674 oxobjectid = {$sQtedObjectId} and oxshopid = {$iQtedShopId} and oxlang = {$iLang} ";
00675
00676 $sQ .= $sParams ? " and oxparams = {$sQtedParams} " : '';
00677
00678 $sQ .= "limit 1";
00679
00680 $oRs = $oDb->execute( $sQ );
00681 if ( $oRs && $oRs->recordCount() > 0 && !$oRs->EOF ) {
00682 if ( $oRs->fields['samestdurl'] && $oRs->fields['sameseourl'] && $oRs->fields['oxexpired'] ) {
00683
00684 $sFixed = isset( $blFixed ) ? ", oxfixed = " . ( (int) $blFixed ) . " " : '';
00685
00686 $sSql = "update oxseo set oxexpired = 0 {$sFixed} where oxtype = {$sQtedType} and
00687 oxobjectid = {$sQtedObjectId} and oxshopid = {$iQtedShopId} and oxlang = {$iLang} ";
00688 $sSql .= $sParams ? " and oxparams = {$sQtedParams} " : '';
00689 $sSql .= " limit 1";
00690
00691 return $oDb->execute( $sSql );
00692 } elseif ( $oRs->fields['oxexpired'] ) {
00693
00694 $this->_copyToHistory( $sObjectId, $iShopId, $iLang, $sType );
00695 }
00696 }
00697
00698
00699 $sParams = $sParams ? $oDb->quote( $sParams ) :'""';
00700 $blFixed = (int) $blFixed;
00701
00702 $sQ = "insert into oxseo
00703 (oxobjectid, oxident, oxshopid, oxlang, oxstdurl, oxseourl, oxtype, oxfixed, oxexpired, oxparams)
00704 values
00705 ( {$sQtedObjectId}, {$sQtedIdent}, {$iQtedShopId}, {$iLang}, {$sQtedStdUrl}, {$sQtedSeoUrl}, {$sQtedType}, '$blFixed', '0', {$sParams} )
00706 on duplicate key update
00707 oxident = {$sQtedIdent}, oxstdurl = {$sQtedStdUrl}, oxseourl = {$sQtedSeoUrl}, oxfixed = '$blFixed', oxexpired = '0'";
00708
00709 return $oDb->execute( $sQ );
00710 }
00711
00722 protected function _trimUrl( $sUrl, $iLang = null )
00723 {
00724 $myConfig = $this->getConfig();
00725 $oStr = getStr();
00726 $sUrl = str_replace( array( $myConfig->getShopUrl( $iLang ), $myConfig->getSslShopUrl( $iLang ) ), '', $sUrl );
00727 $sUrl = $oStr->preg_replace( '/(\?|&(amp;)?)(force_)?(admin_)?sid=[a-z0-9\.]+&?(amp;)?/i', '\1', $sUrl );
00728 $sUrl = $oStr->preg_replace( '/(\?|&(amp;)?)shp=[0-9]+&?(amp;)?/i', '\1', $sUrl );
00729 $sUrl = $oStr->preg_replace( '/(\?|&(amp;)?)lang=[0-9]+&?(amp;)?/i', '\1', $sUrl );
00730 $sUrl = $oStr->preg_replace( '/(\?|&(amp;)?)&(amp;)?/i', '\1', $sUrl );
00731 $sUrl = $oStr->preg_replace( '/(\?|&(amp;)?)+$/i', '', $sUrl );
00732 return $sUrl;
00733 }
00734
00743 public function encodeString( $sString, $blReplaceChars = true )
00744 {
00745
00746 $sString = getStr()->html_entity_decode( $sString );
00747
00748 if ( $blReplaceChars ) {
00749 $aReplaceChars = $this->getConfig()->getConfigParam( 'aSeoReplaceChars' );
00750 $sString = str_replace( array_keys( $aReplaceChars ), array_values( $aReplaceChars ), $sString );
00751 }
00752
00753
00754 $aReplaceWhat = array( '&', '"', ''', '<', '>' );
00755 return str_replace( $aReplaceWhat, '', $sString );
00756 }
00757
00765 public function setSeparator( $sSeparator = null )
00766 {
00767 self::$_sSeparator = $sSeparator;
00768 if ( !self::$_sSeparator ) {
00769 self::$_sSeparator = '-';
00770 }
00771 }
00772
00780 public function setPrefix( $sPrefix )
00781 {
00782 if ($sPrefix) {
00783 self::$_sPrefix = $sPrefix;
00784 } else {
00785 self::$_sPrefix = 'oxid';
00786 }
00787 }
00788
00796 public function setIdLength( $iIdlength = null )
00797 {
00798 if ( isset( $iIdlength ) ) {
00799 $this->_iIdLength = $iIdlength;
00800 }
00801 }
00802
00810 public function setReservedWords( $aReservedWords )
00811 {
00812 self::$_aReservedWords = array_merge( self::$_aReservedWords, $aReservedWords );
00813 }
00814
00815
00827 public function markAsExpired( $sId, $iShopId = null, $iExpStat = 1, $iLang = null, $sParams = null )
00828 {
00829 $oDb = oxDb::getDb();
00830 $sWhere = $sId ? "where oxobjectid = " . $oDb->quote( $sId ) : '';
00831 $sWhere .= isset( $iShopId ) ? ( $sWhere ? " and oxshopid = ". $oDb->quote( $iShopId ) : "where oxshopid = ". $oDb->quote( $iShopId ) ) : '';
00832 $sWhere .= $iLang ? ( $sWhere ? " and oxlang = '{$iLang}'" : "where oxlang = '{$iLang}'" ) : '';
00833 $sWhere .= $sParams ? ( $sWhere ? " and {$sParams}" : "where {$sParams}" ) : '';
00834
00835 $sQ = "update oxseo set oxexpired = " . $oDb->quote( $iExpStat ) . " $sWhere ";
00836 $oDb->execute( $sQ );
00837 }
00838
00852 protected function _getPageUri( $oObject, $sType, $sStdUrl, $sSeoUrl, $sParams, $iLang = null, $blFixed = false )
00853 {
00854 if ( !isset( $iLang ) ) {
00855 $iLang = $oObject->getLanguage();
00856 }
00857 $iShopId = $this->getConfig()->getShopId();
00858
00859
00860 $sOldSeoUrl = $this->_loadFromDb( $sType, $oObject->getId(), $iLang, $iShopId, $sParams );
00861 if ( !$sOldSeoUrl ) {
00862
00863 $sSeoUrl = $this->_processSeoUrl( $sSeoUrl, $oObject->getId(), $iLang );
00864 $this->_saveToDb( $sType, $oObject->getId(), $sStdUrl, $sSeoUrl, $iLang, $iShopId, (int) $blFixed, $sParams );
00865 } else {
00866
00867 $sSeoUrl = $sOldSeoUrl;
00868 }
00869 return $sSeoUrl;
00870 }
00871
00880 protected function _getStaticObjectId( $iShopId, $sStdUrl )
00881 {
00882 return md5( strtolower ( $iShopId . $this->_trimUrl( $sStdUrl ) ) );
00883 }
00884
00894 public function encodeStaticUrls( $aStaticUrl, $iShopId, $iLang )
00895 {
00896 $oDb = oxDb::getDb();
00897 $sValues = '';
00898 $sOldObjectId = null;
00899
00900
00901 $sStdUrl = $this->_trimUrl( trim( $aStaticUrl['oxseo__oxstdurl'] ) );
00902 $sObjectId = $aStaticUrl['oxseo__oxobjectid'];
00903
00904 if ( !$sObjectId || $sObjectId == '-1' ) {
00905 $sObjectId = $this->_getStaticObjectId( $iShopId, $sStdUrl );
00906 } else {
00907
00908 $sOldObjectId = $sObjectId;
00909
00910
00911 if ( $this->_getStaticObjectId( $iShopId, $sStdUrl ) != $sObjectId ) {
00912 $sObjectId = $this->_getStaticObjectId( $iShopId, $sStdUrl );
00913 }
00914 }
00915
00916 foreach ( $aStaticUrl['oxseo__oxseourl'] as $iLang => $sSeoUrl ) {
00917
00918 $iLang = (int) $iLang;
00919
00920
00921 if ( ( $sSeoUrl = trim( $sSeoUrl ) ) ) {
00922 $sSeoUrl = $this->_prepareUri( $this->_trimUrl( $sSeoUrl ) );
00923 $sSeoUrl = $this->_processSeoUrl( $sSeoUrl, $sObjectId, $iLang );
00924 }
00925
00926
00927 if ( $sOldObjectId ) {
00928
00929 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}' " ) ) {
00930 $this->_copyToHistory( $sOldObjectId, $iShopId, $iLang, 'static', $sObjectId );
00931 }
00932 }
00933
00934 if ( !$sSeoUrl || !$sStdUrl ) {
00935 continue;
00936 }
00937
00938 $sIdent = $this->_getSeoIdent( $sSeoUrl );
00939
00940 if ( $sValues ) {
00941 $sValues .= ', ';
00942 }
00943
00944 $sValues .= "( " . $oDb->quote( $sObjectId ) . ", " . $oDb->quote( $sIdent ) . ", " . $oDb->quote( $iShopId ).", '{$iLang}', " . $oDb->quote( $sStdUrl ) . ", " . $oDb->quote( $sSeoUrl ) . ", 'static' )";
00945 }
00946
00947
00948 if ( $sOldObjectId ) {
00949 $oDb->execute( "delete from oxseo where oxobjectid in ( " . $oDb->quote( $sOldObjectId ) . ", " . $oDb->quote( $sObjectId ) . " )" );
00950 }
00951
00952
00953 if ( $sValues ) {
00954
00955 $sQ = "insert into oxseo ( oxobjectid, oxident, oxshopid, oxlang, oxstdurl, oxseourl, oxtype ) values {$sValues} ";
00956 $oDb->execute( $sQ );
00957 }
00958
00959 return $sObjectId;
00960 }
00961
00969 public function copyStaticUrls( $iShopId )
00970 {
00971 $iBaseShopId = $this->getConfig()->getBaseShopId();
00972 if ( $iShopId != $iBaseShopId ) {
00973 $oDb = oxDb::getDb();
00974 foreach (array_keys(oxLang::getInstance()->getLanguageIds()) as $iLang) {
00975 $sQ = "insert into oxseo ( oxobjectid, oxident, oxshopid, oxlang, oxstdurl, oxseourl, oxtype )
00976 select MD5( LOWER( CONCAT( " . $oDb->quote( $iShopId ) . ", oxstdurl ) ) ), MD5( LOWER( oxseourl ) ),
00977 " . $oDb->quote( $iShopId ) . ", oxlang, oxstdurl, oxseourl, oxtype from oxseo where oxshopid = '{$iBaseShopId}' and oxtype = 'static' and oxlang='$iLang' ";
00978 $oDb->execute( $sQ );
00979 }
00980 }
00981 }
00982
00992 public function getStaticUrl( $sStdUrl, $iLang = null, $iShopId = null )
00993 {
00994 if (!isset($iShopId)) {
00995 $iShopId = $this->getConfig()->getShopId();
00996 }
00997 if (!isset($iLang)) {
00998 $iLang = oxLang::getInstance()->getEditLanguage();
00999 }
01000
01001 if ( isset($this->_aStaticUrlCache[$sStdUrl][$iLang][$iShopId])) {
01002 return $this->_aStaticUrlCache[$sStdUrl][$iLang][$iShopId];
01003 }
01004
01005 $sFullUrl = '';
01006 if ( ( $sSeoUrl = $this->_getStaticUri( $sStdUrl, $iShopId, $iLang ) ) ) {
01007 $sFullUrl = $this->_getFullUrl( $sSeoUrl, $iLang, strpos( $sStdUrl, "https:" ) === 0 );
01008 }
01009
01010
01011 $this->_aStaticUrlCache[$sStdUrl][$iLang][$iShopId] = $sFullUrl;
01012
01013 return $sFullUrl;
01014 }
01015
01034 public function addSeoEntry( $sObjectId, $iShopId, $iLang, $sStdUrl, $sSeoUrl, $sType, $blFixed = 1, $sKeywords = '', $sDescription = '', $sParams = '', $blExclude = false, $sAltObjectId = null )
01035 {
01036 $sSeoUrl = $this->_processSeoUrl( $this->_prepareUri( $this->_trimUrl( $sSeoUrl ? $sSeoUrl : $this->_getAltUri( $sAltObjectId ? $sAltObjectId : $sObjectId, $iLang ) ) ), $sObjectId, $iLang, $blExclude );
01037 if ( $this->_saveToDb( $sType, $sObjectId, $sStdUrl, $sSeoUrl, $iLang, $iShopId, $blFixed, $sParams ) ) {
01038
01039 $oDb = oxDb::getDb( true );
01040
01041
01042 $sQtedObjectId = $oDb->quote( $sAltObjectId ? $sAltObjectId : $sObjectId );
01043 $iQtedShopId = $oDb->quote( $iShopId );
01044
01045 $oStr = getStr();
01046 if ( $sKeywords !== false ) {
01047 $sKeywords = $oDb->quote( $oStr->htmlspecialchars( $this->encodeString( strip_tags( $sKeywords ), false ) ) );
01048 }
01049
01050 if ( $sDescription !== false ) {
01051 $sDescription = $oDb->quote( $oStr->htmlspecialchars( strip_tags( $sDescription ) ) );
01052 }
01053
01054 $sQ = "insert into oxobject2seodata
01055 ( oxobjectid, oxshopid, oxlang, oxkeywords, oxdescription )
01056 values
01057 ( {$sQtedObjectId}, {$iQtedShopId}, {$iLang}, ".( $sKeywords ? $sKeywords : "''" ).", ".( $sDescription ? $sDescription : "''" )." )
01058 on duplicate key update
01059 oxkeywords = ".( $sKeywords ? $sKeywords : "oxkeywords" ).", oxdescription = ".( $sDescription ? $sDescription : "oxdescription" );
01060 $oDb->execute( $sQ );
01061 }
01062 }
01063
01072 protected function _getAltUri( $sObjectId, $iLang )
01073 {
01074 }
01075
01086 public function deleteSeoEntry( $sObjectId, $iShopId, $iLang, $sType )
01087 {
01088 $oDb = oxDb::getDb();
01089 $sQ = "delete from oxseo where oxobjectid = " . $oDb->quote( $sObjectId ) . " and oxshopid = " . $oDb->quote( $iShopId ) . " and oxlang = " . $oDb->quote( $iLang ) . " and oxtype = " . $oDb->quote( $sType ) . " ";
01090 oxDb::getDb()->execute( $sQ );
01091 }
01092
01103 public function getMetaData( $sObjectId, $sMetaType, $iShopId = null, $iLang = null )
01104 {
01105 $oDb = oxDb::getDb();
01106
01107 $iShopId = ( !isset( $iShopId ) ) ? $this->getConfig()->getShopId():$iShopId;
01108 $iLang = ( !isset( $iLang ) ) ? oxLang::getInstance()->getObjectTplLanguage():((int) $iLang);
01109 return $oDb->getOne( "select {$sMetaType} from oxobject2seodata where oxobjectid = " . $oDb->quote( $sObjectId ) . " and oxshopid = " . $oDb->quote( $iShopId )." and oxlang = '{$iLang}'" );
01110 }
01111
01125 public function getDynamicUrl( $sStdUrl, $sSeoUrl, $iLang )
01126 {
01127 startProfile("getDynamicUrl");
01128 $sDynUrl = $this->_getFullUrl( $this->_getDynamicUri( $sStdUrl, $sSeoUrl, $iLang ), strpos( $sStdUrl, "https:" ) === 0 );
01129 stopProfile("getDynamicUrl");
01130 return $sDynUrl;
01131 }
01132
01141 public function fetchSeoUrl( $sStdUrl, $iLanguage = null )
01142 {
01143 $oDb = oxDb::getDb( true );
01144 $iLanguage = isset( $iLanguage ) ? ( (int) $iLanguage ) : oxLang::getInstance()->getBaseLanguage();
01145 $sSeoUrl = false;
01146
01147 $sShopId = $this->getConfig()->getShopId();
01148
01149 $sQ = "select oxseourl, oxlang from oxseo where oxstdurl = ".$oDb->quote( $sStdUrl )." and oxlang = '$iLanguage' and oxshopid = '$sShopId' limit 1";
01150 $oRs = $oDb->execute( $sQ );
01151 if ( !$oRs->EOF ) {
01152 $sSeoUrl = $oRs->fields['oxseourl'];
01153 }
01154
01155 return $sSeoUrl;
01156 }
01157 }