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