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
00066 protected $_sSeparator = ',';
00067
00074 protected $_iTagMaxLength = 60;
00075
00083 protected $_aMetaChars = array('+','-','>','<','(',')','~','*','"','\'','\\','[',']','{','}',';',':','.','/','|','!','@','#','$','%','^','&','?','=','`');
00084
00089 public function __construct()
00090 {
00091 $sSeparator = $this->getConfig()->getConfigParam("sTagSeparator");
00092 if ($sSeparator)
00093 $this->_sSeparator = $sSeparator;
00094 }
00095
00103 public function setProductId( $sProductId )
00104 {
00105 $this->_sProductId = $sProductId;
00106 }
00107
00115 public function setLanguageId( $iLangId )
00116 {
00117 $this->_iLangId = $iLangId;
00118 }
00119
00127 public function setExtendedMode( $blExtended )
00128 {
00129 $this->_blExtended = $blExtended;
00130 }
00131
00137 public function getLanguageId()
00138 {
00139 if ( $this->_iLangId === null ) {
00140 $this->_iLangId = oxRegistry::getLang()->getBaseLanguage();
00141 }
00142 return $this->_iLangId;
00143 }
00144
00150 public function getProductId()
00151 {
00152 return $this->_sProductId;
00153 }
00154
00160 public function getTagMaxLength()
00161 {
00162 return $this->_iTagMaxLength;
00163 }
00164
00170 public function isExtended()
00171 {
00172 return $this->_blExtended;
00173 }
00174
00184 public function getCloudArray( $sProductId = null, $blExtended = null, $iLang = null )
00185 {
00186
00187 $iLang = ( $iLang === null ) ? (int) $this->getLanguageId() : $iLang;
00188 $blExtended = ( $blExtended === null ) ? $this->isExtended() : $blExtended;
00189 $sProductId = ( $sProductId === null ) ? (string) $this->getProductId() : $sProductId;
00190
00191
00192 $sCacheIdent = $this->_getCacheKey( $blExtended, $iLang )."_".$sProductId;
00193 if ( !isset( $this->_aCloudArray[$sCacheIdent] ) ) {
00194
00195 $myUtils = oxRegistry::getUtils();
00196
00197
00198 $aCloudArray = ( !$sProductId ) ? $myUtils->fromFileCache( $sCacheIdent ) : null;
00199
00200
00201 if ( $aCloudArray === null ) {
00202 $aCloudArray = $this->getTags( $sProductId, $blExtended, $iLang );
00203
00204 if ( !$sProductId ) {
00205 $myUtils->toFileCache( $sCacheIdent, $aCloudArray );
00206 }
00207 }
00208
00209 $this->_aCloudArray[$sCacheIdent] = $aCloudArray;
00210 }
00211 return $this->_aCloudArray[$sCacheIdent];
00212 }
00213
00221 public function getTagLink( $sTag )
00222 {
00223 $oSeoEncoderTag = oxRegistry::get("oxSeoEncoderTag");
00224 $iLang = $this->getLanguageId();
00225
00226 $sUrl = false;
00227 if ( oxRegistry::getUtils()->seoIsActive() ) {
00228 $sUrl = $oSeoEncoderTag->getTagUrl( $sTag, $iLang );
00229 }
00230 return $sUrl ? $sUrl : $this->getConfig()->getShopUrl() . $oSeoEncoderTag->getStdTagUri( $sTag ) . "&lang=" . $iLang;
00231 }
00232
00240 public function getTagTitle( $sTag )
00241 {
00242 return getStr()->htmlentities( $sTag );
00243 }
00244
00250 protected function _getMaxHit()
00251 {
00252 if ( $this->_iMaxHit === null ) {
00253 $this->_iMaxHit = max( $this->getCloudArray() );
00254 }
00255 return $this->_iMaxHit;
00256 }
00257
00265 public function getTagSize( $sTag )
00266 {
00267 $aCloudArray = $this->getCloudArray();
00268 $iCurrSize = $this->_getFontSize( $aCloudArray[ $sTag ], $this->_getMaxHit() );
00269
00270
00271 return floor( $iCurrSize / OXTAGCLOUD_MINFONT ) * OXTAGCLOUD_MINFONT;
00272 }
00273
00274
00284 public function getTags( $sArtId = null, $blExtended = false, $iLang = null )
00285 {
00286 $oDb = oxDb::getDb( oxDb::FETCH_MODE_ASSOC );
00287
00288 if ($blExtended) {
00289 $iAmount = OXTAGCLOUD_EXTENDEDCOUNT;
00290 } else {
00291 $iAmount = OXTAGCLOUD_STARTPAGECOUNT;
00292 }
00293
00294 $sArtView = getViewName( 'oxarticles', $iLang );
00295 $sViewName = getViewName( 'oxartextends', $iLang );
00296
00297
00298 $oArticle = oxNew( 'oxarticle' );
00299 $oArticle->setLanguage( $iLang );
00300 $sArtActive = $oArticle->getActiveCheckQuery(true);
00301
00302
00303 $sQ = "SELECT {$sViewName}.`oxtags` AS `oxtags`
00304 FROM {$sArtView} AS `oxarticles`
00305 LEFT JOIN {$sViewName} ON `oxarticles`.`oxid` = {$sViewName}.`oxid`
00306 WHERE `oxarticles`.`oxactive` = 1 AND $sArtActive";
00307
00308 if ( $sArtId ) {
00309 $sQ = "SELECT {$sViewName}.`oxtags` AS `oxtags` FROM {$sViewName} WHERE `oxid` = " . $oDb->quote( $sArtId );
00310 $iAmount = 0;
00311 }
00312
00313 $oDb->setFetchMode( oxDb::FETCH_MODE_ASSOC );
00314 $rs = $oDb->select( $sQ );
00315 $aTags = array();
00316 while ( $rs && $rs->recordCount() && !$rs->EOF ) {
00317 $sTags = $this->trimTags( $rs->fields['oxtags'] );
00318 $aArticleTags = explode( $this->_sSeparator, $sTags );
00319 foreach ( $aArticleTags as $sTag ) {
00320 if ( trim( $sTag ) ) {
00321 ++$aTags[$sTag];
00322 }
00323 }
00324 $rs->moveNext();
00325 }
00326
00327
00328 if ( $iAmount ) {
00329 arsort( $aTags );
00330 $aTags = array_slice( $aTags, 0, $iAmount, true );
00331 }
00332
00333 $aTags = $this->_sortTags( $aTags );
00334 return $aTags;
00335 }
00336
00345 protected function _sortTags( $aTags, $iLang = null )
00346 {
00347 if ( is_array( $aTags ) && count( $aTags ) ) {
00348 $oDb = oxDb::getDb( oxDb::FETCH_MODE_ASSOC );
00349 $sSubQ = '';
00350 foreach ( $aTags as $sKey => $sTag ) {
00351 if ( $sSubQ ) {
00352 $sSubQ .= ' union all ';
00353 }
00354 $sSubQ .= 'select '.$oDb->quote( $sKey ).' as _oxsort, '.$oDb->quote( $sTag ).' as _oxval';
00355 }
00356
00357 $sViewName = getViewName( "oxartextends", $iLang );
00358
00359
00360 $sSubQ = "select {$sViewName}.oxtags as _oxsort, 'ox_skip' as _oxval from {$sViewName} limit 1 union $sSubQ";
00361 $sQ = "select _oxtable._oxsort, _oxtable._oxval from ( {$sSubQ} ) as _oxtable order by _oxtable._oxsort desc";
00362
00363 $aTags = array();
00364 $oDb->setFetchMode( oxDb::FETCH_MODE_ASSOC );
00365 $oRs = $oDb->select( $sQ );
00366 while ( $oRs && $oRs->recordCount() && !$oRs->EOF ) {
00367 if ( $oRs->fields['_oxval'] != 'ox_skip' ) {
00368 $aTags[$oRs->fields['_oxsort']] = $oRs->fields['_oxval'];
00369 }
00370 $oRs->moveNext();
00371 }
00372 }
00373 return $aTags;
00374 }
00375
00384 protected function _getFontSize( $iHit, $iMaxHit )
00385 {
00386
00387 if ($iMaxHit <= OXTAGCLOUD_MINOCCURENCETOSHOW || !$iMaxHit) {
00388 return OXTAGCLOUD_MINFONT;
00389 }
00390
00391 $iFontDiff = OXTAGCLOUD_MAXFONT - OXTAGCLOUD_MINFONT;
00392 $iMaxHitDiff = $iMaxHit - OXTAGCLOUD_MINOCCURENCETOSHOW;
00393 $iHitDiff = $iHit - OXTAGCLOUD_MINOCCURENCETOSHOW;
00394
00395 if ($iHitDiff < 0) {
00396 $iHitDiff = 0;
00397 }
00398
00399 $iSize = round($iHitDiff * $iFontDiff / $iMaxHitDiff) + OXTAGCLOUD_MINFONT;
00400
00401 return $iSize;
00402 }
00403
00411 public function _fixTagLength( $sTag )
00412 {
00413 $oStr = getStr();
00414 $sTag = trim( $sTag );
00415 $iLen = $oStr->strlen( $sTag );
00416
00417 if ( $iLen < OXTAGCLOUD_MINTAGLENGTH ) {
00418 $sTag .= str_repeat( '_', OXTAGCLOUD_MINTAGLENGTH - $iLen );
00419 }
00420
00421 return $sTag;
00422 }
00423
00431 public function stripMetaChars( $sText )
00432 {
00433 $oStr = getStr();
00434
00435
00436 $sText = str_replace($this->_aMetaChars, ' ', $sText);
00437
00438
00439 $sText = $oStr->preg_replace( "/\s+/", " ", trim( $sText ) );
00440
00441 return $sText;
00442 }
00443
00453 public function prepareTags( $sTags )
00454 {
00455 $sTags = $this->stripMetaChars($sTags);
00456 $aTags = explode( $this->_sSeparator, $sTags );
00457 $aRes = array();
00458 $oStr = getStr();
00459
00460 foreach ( $aTags as $sTag ) {
00461 if ( ( $sTag = trim( $sTag ) ) ) {
00462 $sRes = '';
00463 $iLen = $oStr->strlen( $sTag );
00464 if ( $iLen > $this->_iTagMaxLength ) {
00465 $sTag = $oStr->substr($sTag, 0, $this->_iTagMaxLength);
00466 }
00467 $sTag = trim( $sTag );
00468 $aMatches = explode(' ', $sTag);
00469 foreach ( $aMatches as $iKey => $sMatch ) {
00470 $sRes .= $oStr->strtolower( $this->_fixTagLength($sMatch ) )." ";
00471 }
00472 $aRes[] = trim( $sRes );
00473 }
00474 }
00475
00476 return implode( $this->_sSeparator, $aRes );
00477 }
00478
00486 public function trimTags( $sTags )
00487 {
00488 $oStr = getStr();
00489 $sTags = $oStr->preg_replace( "/(\s*\,+\s*)+/", ",", trim( $sTags ) );
00490 $sRes = '';
00491
00492 if ( $oStr->preg_match_all( "/([\s\,\-]?)([^\s\,\-]+)([\s\,\-]?)/", $sTags, $aMatches ) ) {
00493 foreach ( $aMatches[0] as $iKey => $sMatch ) {
00494 $sProc = $aMatches[2][$iKey];
00495 if ( $oStr->strlen( $sProc ) <= OXTAGCLOUD_MINTAGLENGTH ) {
00496 $sProc = rtrim( $sProc, "_" );
00497
00498 }
00499 $sRes .= $aMatches[1][$iKey] . $sProc . $aMatches[3][$iKey];
00500 }
00501 }
00502
00503 return trim( $sRes, $this->_sSeparator );
00504 }
00505
00513 public function resetTagCache( $iLang = null )
00514 {
00515 $myUtils = oxRegistry::getUtils();
00516
00517 $sCacheKey1 = $this->_getCacheKey( true, $iLang );
00518 $myUtils->toFileCache( $sCacheKey1, null );
00519
00520 $sCacheKey2 = $this->_getCacheKey( false, $iLang );
00521 $myUtils->toFileCache( $sCacheKey2, null );
00522 }
00523
00532 protected function _getCacheKey( $blExtended, $iLang = null )
00533 {
00534 return $this->_sCacheKey."_".$this->getConfig()->getShopId()."_".( ( $iLang !== null ) ? $iLang : oxRegistry::getLang()->getBaseLanguage() ) ."_".$blExtended;
00535 }
00536
00544 public function canBeTagged( $sTagTitle )
00545 {
00546 $aProducts = oxSession::getVar("aTaggedProducts");
00547 if ( isset($aProducts) && $aTags = $aProducts[$this->getProductId()]) {
00548 if ( $aTags[$sTagTitle] == 1 ) {
00549 return false;
00550 }
00551 }
00552 return true;
00553 }
00554
00555 }