00001 <?php
00002
00003 if (!defined('OXTAGCLOUD_MINFONT')) {
00004 define('OXTAGCLOUD_MINFONT', 100);
00005 define('OXTAGCLOUD_MAXFONT', 400);
00006 define('OXTAGCLOUD_MINOCCURENCETOSHOW', 2);
00007
00008 define('OXTAGCLOUD_MINTAGLENGTH', 4);
00009 define('OXTAGCLOUD_STARTPAGECOUNT', 20);
00010 define('OXTAGCLOUD_EXTENDEDCOUNT', 200);
00011 }
00012
00017 class oxTagCloud extends oxSuperCfg
00018 {
00024 protected $_sCacheKey = "tagcloud_";
00025
00031 protected $_blExtended = false;
00032
00038 protected $_sProductId = null;
00039
00045 protected $_iLangId = null;
00046
00052 protected $_iMaxHit = null;
00053
00059 protected $_aCloudArray = null;
00060
00067 protected $_sSeparator = ' ';
00068
00075 protected $_aMetaChars = array('+','-','>','<','(',')','~','*','"','\'','\\');
00076
00081 public function __construct()
00082 {
00083 $sSeparator = $this->getConfig()->getConfigParam("sTagSeparator");
00084 if ($sSeparator)
00085 $this->_sSeparator = $sSeparator;
00086 }
00087
00095 public function setProductId( $sProductId )
00096 {
00097 $this->_sProductId = $sProductId;
00098 }
00099
00107 public function setLanguageId( $iLangId )
00108 {
00109 $this->_iLangId = $iLangId;
00110 }
00111
00119 public function setExtendedMode( $blExtended )
00120 {
00121 $this->_blExtended = $blExtended;
00122 }
00123
00129 public function getLanguageId()
00130 {
00131 if ( $this->_iLangId === null ) {
00132 $this->_iLangId = oxLang::getInstance()->getBaseLanguage();
00133 }
00134 return $this->_iLangId;
00135 }
00136
00142 public function getProductId()
00143 {
00144 return $this->_sProductId;
00145 }
00146
00152 public function isExtended()
00153 {
00154 return $this->_blExtended;
00155 }
00156
00166 public function getCloudArray( $sProductId = null, $blExtended = null, $iLang = null )
00167 {
00168
00169 $iLang = ( $iLang === null ) ? (int) $this->getLanguageId() : $iLang;
00170 $blExtended = ( $blExtended === null ) ? $this->isExtended() : $blExtended;
00171 $sProductId = ( $sProductId === null ) ? (string) $this->getProductId() : $sProductId;
00172
00173
00174 $sCacheIdent = $this->_getCacheKey( $blExtended, $iLang )."_".$sProductId;
00175 if ( !isset( $this->_aCloudArray[$sCacheIdent] ) ) {
00176
00177 $myUtils = oxUtils::getInstance();
00178
00179
00180 $aCloudArray = ( !$sProductId ) ? $myUtils->fromFileCache( $sCacheIdent ) : null;
00181
00182
00183 if ( $aCloudArray === null ) {
00184 $aCloudArray = $this->getTags( $sProductId, $blExtended, $iLang );
00185
00186 if ( !$sProductId ) {
00187 $myUtils->toFileCache( $sCacheIdent, $aCloudArray );
00188 }
00189 }
00190
00191 $this->_aCloudArray[$sCacheIdent] = $aCloudArray;
00192 }
00193 return $this->_aCloudArray[$sCacheIdent];
00194 }
00195
00203 public function getTagLink( $sTag )
00204 {
00205 $oSeoEncoderTag = oxSeoEncoderTag::getInstance();
00206 $iLang = $this->getLanguageId();
00207
00208 $sUrl = false;
00209 if ( oxUtils::getInstance()->seoIsActive() ) {
00210 $sUrl = $oSeoEncoderTag->getTagUrl( $sTag, $iLang );
00211 }
00212 return $sUrl ? $sUrl : $this->getConfig()->getShopUrl() . $oSeoEncoderTag->getStdTagUri( $sTag ) . "&lang=" . $iLang;
00213 }
00214
00222 public function getTagTitle( $sTag )
00223 {
00224 return getStr()->htmlentities( $sTag );
00225 }
00226
00232 protected function _getMaxHit()
00233 {
00234 if ( $this->_iMaxHit === null ) {
00235 $this->_iMaxHit = max( $this->getCloudArray() );
00236 }
00237 return $this->_iMaxHit;
00238 }
00239
00247 public function getTagSize( $sTag )
00248 {
00249 $aCloudArray = $this->getCloudArray();
00250 $iCurrSize = $this->_getFontSize( $aCloudArray[ $sTag ], $this->_getMaxHit() );
00251
00252
00253 return floor( $iCurrSize / OXTAGCLOUD_MINFONT ) * OXTAGCLOUD_MINFONT;
00254 }
00255
00256
00266 public function getTags( $sArtId = null, $blExtended = false, $iLang = null )
00267 {
00268 $oDb = oxDb::getDb(true);
00269 if ($blExtended) {
00270 $iAmount = OXTAGCLOUD_EXTENDEDCOUNT;
00271 } else {
00272 $iAmount = OXTAGCLOUD_STARTPAGECOUNT;
00273 }
00274
00275 $sArticleSelect = " 1 ";
00276 if ( $sArtId ) {
00277 $sArticleSelect = " oxarticles.oxid = ".$oDb->quote( $sArtId )." ";
00278 $iAmount = 0;
00279 }
00280
00281 $sField = "oxartextends.oxtags".oxLang::getInstance()->getLanguageTag( $iLang );
00282
00283 $sArtView = getViewName('oxarticles');
00284 $sQ = "select $sField as oxtags from $sArtView as oxarticles left join oxartextends on oxarticles.oxid=oxartextends.oxid where oxarticles.oxactive=1 AND $sArticleSelect";
00285
00286 $rs = $oDb->execute( $sQ );
00287 $aTags = array();
00288 while ( $rs && $rs->recordCount() && !$rs->EOF ) {
00289 $sTags = $this->trimTags( $rs->fields['oxtags'] );
00290 $aArticleTags = explode( $this->_sSeparator, $sTags );
00291 foreach ( $aArticleTags as $sTag ) {
00292 if ( trim( $sTag ) ) {
00293 ++$aTags[$sTag];
00294 }
00295 }
00296 $rs->moveNext();
00297 }
00298
00299
00300 if ( $iAmount ) {
00301 arsort( $aTags );
00302 $aTags = array_slice( $aTags, 0, $iAmount, true );
00303 }
00304
00305 $aTags = $this->_sortTags( $aTags );
00306 return $aTags;
00307 }
00308
00317 protected function _sortTags( $aTags, $iLang = null )
00318 {
00319 if ( is_array( $aTags ) && count( $aTags ) ) {
00320 $oDb = oxDb::getDb( true );
00321 $sSubQ = '';
00322 foreach ( $aTags as $sKey => $sTag ) {
00323 if ( $sSubQ ) {
00324 $sSubQ .= ' union all ';
00325 }
00326 $sSubQ .= 'select '.$oDb->quote( $sKey ).' as _oxsort, '.$oDb->quote( $sTag ).' as _oxval';
00327 }
00328
00329 $sField = "oxartextends.oxtags".oxLang::getInstance()->getLanguageTag( $iLang );
00330
00331
00332 $sSubQ = "select {$sField} as _oxsort, 'ox_skip' as _oxval from oxartextends limit 1 union $sSubQ";
00333
00334 $sQ = "select _oxtable._oxsort, _oxtable._oxval from ( {$sSubQ} ) as _oxtable order by _oxtable._oxsort desc";
00335
00336 $aTags = array();
00337 $oRs = $oDb->execute( $sQ );
00338 while ( $oRs && $oRs->recordCount() && !$oRs->EOF ) {
00339 if ( $oRs->fields['_oxval'] != 'ox_skip' ) {
00340 $aTags[$oRs->fields['_oxsort']] = $oRs->fields['_oxval'];
00341 }
00342 $oRs->moveNext();
00343 }
00344 }
00345 return $aTags;
00346 }
00347
00359 public function getTagCloud($sArtId = null, $blExtended = false, $iLang = null )
00360 {
00361 $myUtils = oxUtils::getInstance();
00362
00363 $sTagCloud = null;
00364 $sCacheKey = $this->_getCacheKey($blExtended, $iLang );
00365 if ( $this->_sCacheKey && !$sArtId ) {
00366 $sTagCloud = $myUtils->fromFileCache( $sCacheKey );
00367 }
00368
00369 if ( !is_null($sTagCloud) ) {
00370 return $sTagCloud;
00371 }
00372
00373 $aTags = $this->getTags($sArtId, $blExtended, $iLang);
00374 if (!count($aTags)) {
00375 if ($this->_sCacheKey && !$sArtId) {
00376 $sTagCloud = false;
00377 $myUtils->toFileCache($sCacheKey, $sTagCloud);
00378 }
00379 return $sTagCloud;
00380 }
00381
00382 $iMaxHit = max( $aTags);
00383 $blSeoIsActive = $myUtils->seoIsActive();
00384 $oSeoEncoderTag = oxSeoEncoderTag::getInstance();
00385
00386 $iLang = ( $iLang !== null ) ? $iLang : oxLang::getInstance()->getBaseLanguage();
00387 $sUrl = $this->getConfig()->getShopUrl();
00388 $oStr = getStr();
00389
00390 $sTagCloud = false;
00391 foreach ( $aTags as $sTag => $sRelevance ) {
00392 $sLink = false;
00393 if ( $blSeoIsActive ) {
00394 $sLink = $oSeoEncoderTag->getTagUrl( $sTag, $iLang );
00395 }
00396 $sLink = $sLink ? $sLink : $sUrl . $oSeoEncoderTag->getStdTagUri( $sTag ) . "&lang=" . $iLang;
00397 $iFontSize = $this->_getFontSize( $sRelevance, $iMaxHit );
00398 $sTagCloud .= "<a style='font-size:". $iFontSize ."%;' class='tagitem_". $iFontSize . "' href='$sLink'>".$oStr->htmlentities($sTag)."</a> ";
00399 }
00400
00401 if ( $this->_sCacheKey && !$sArtId ) {
00402 $myUtils->toFileCache( $sCacheKey, $sTagCloud );
00403 }
00404
00405 return $sTagCloud;
00406 }
00407
00416 protected function _getFontSize( $iHit, $iMaxHit )
00417 {
00418
00419 if ($iMaxHit <= OXTAGCLOUD_MINOCCURENCETOSHOW || !$iMaxHit) {
00420 return OXTAGCLOUD_MINFONT;
00421 }
00422
00423 $iFontDiff = OXTAGCLOUD_MAXFONT - OXTAGCLOUD_MINFONT;
00424 $iMaxHitDiff = $iMaxHit - OXTAGCLOUD_MINOCCURENCETOSHOW;
00425 $iHitDiff = $iHit - OXTAGCLOUD_MINOCCURENCETOSHOW;
00426
00427 if ($iHitDiff < 0) {
00428 $iHitDiff = 0;
00429 }
00430
00431 $iSize = round($iHitDiff * $iFontDiff / $iMaxHitDiff) + OXTAGCLOUD_MINFONT;
00432
00433 return $iSize;
00434 }
00435
00443 public function _fixTagLength( $sTag )
00444 {
00445 $oStr = getStr();
00446 $sTag = trim( $sTag );
00447 $iLen = $oStr->strlen( $sTag );
00448
00449 if ( $iLen < OXTAGCLOUD_MINTAGLENGTH ) {
00450 $sTag .= str_repeat( '_', OXTAGCLOUD_MINTAGLENGTH - $iLen );
00451 }
00452
00453 return $sTag;
00454 }
00455
00463 public function stripMetaChars( $sText )
00464 {
00465 $oStr = getStr();
00466
00467
00468 $sText = str_replace($this->_aMetaChars, ' ', $sText);
00469
00470
00471 $sText = $oStr->preg_replace( "/\s+/", " ", trim( $sText ) );
00472
00473 return $sText;
00474 }
00475
00484 public function prepareTags( $sTags )
00485 {
00486 $sTags = $this->stripMetaChars($sTags);
00487 $aTags = explode( $this->_sSeparator, $sTags );
00488 $aRes = array();
00489 $oStr = getStr();
00490
00491 foreach ( $aTags as $sTag ) {
00492 if ( ( $sTag = trim( $sTag ) ) ) {
00493 $sRes = '';
00494 $aMatches = explode(' ', $sTag);
00495 foreach ( $aMatches as $iKey => $sMatch ) {
00496 $sRes .= $oStr->strtolower( $this->_fixTagLength($sMatch ) )." ";
00497 }
00498 $aRes[] = trim( $sRes );
00499 }
00500 }
00501
00502 return implode( $this->_sSeparator, $aRes );
00503 }
00504
00512 public function trimTags( $sTags )
00513 {
00514 $oStr = getStr();
00515 $sTags = $oStr->preg_replace( "/(\s*\,+\s*)+/", ",", trim( $sTags ) );
00516 $sRes = '';
00517
00518 if ( $oStr->preg_match_all( "/([\s\,\-]?)([^\s\,\-]+)([\s\,\-]?)/", $sTags, $aMatches ) ) {
00519 foreach ( $aMatches[0] as $iKey => $sMatch ) {
00520 $sProc = $aMatches[2][$iKey];
00521 if ( $oStr->strlen( $sProc ) <= OXTAGCLOUD_MINTAGLENGTH ) {
00522 $sProc = rtrim( $sProc, "_" );
00523
00524 }
00525 $sRes .= $aMatches[1][$iKey] . $sProc . $aMatches[3][$iKey];
00526 }
00527 }
00528
00529 return trim( $sRes, $this->_sSeparator );
00530 }
00531
00539 public function resetTagCache( $iLang = null )
00540 {
00541 $myUtils = oxUtils::getInstance();
00542
00543 $sCacheKey1 = $this->_getCacheKey( true, $iLang );
00544 $myUtils->toFileCache( $sCacheKey1, null );
00545
00546 $sCacheKey2 = $this->_getCacheKey( false, $iLang );
00547 $myUtils->toFileCache( $sCacheKey2, null );
00548 }
00549
00558 protected function _getCacheKey( $blExtended, $iLang = null )
00559 {
00560 return $this->_sCacheKey."_".$this->getConfig()->getShopId()."_".( ( $iLang !== null ) ? $iLang : oxLang::getInstance()->getBaseLanguage() ) ."_".$blExtended;
00561 }
00562
00563 }