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 );
00194 if ($sProductId ) {
00195 $sCacheIdent .= "_".$sProductId;
00196 }
00197 if ( !isset( $this->_aCloudArray[$sCacheIdent] ) ) {
00198
00199 $myUtils = oxUtils::getInstance();
00200
00201
00202 $aCloudArray = ( !$sProductId ) ? $myUtils->fromFileCache( $sCacheIdent ) : null;
00203
00204
00205 if ( $aCloudArray === null ) {
00206 $aCloudArray = $this->getTags( $sProductId, $blExtended, $iLang );
00207
00208 if ( !$sProductId ) {
00209 $myUtils->toFileCache( $sCacheIdent, $aCloudArray );
00210 }
00211 }
00212
00213 $this->_aCloudArray[$sCacheIdent] = $aCloudArray;
00214 }
00215 return $this->_aCloudArray[$sCacheIdent];
00216 }
00217
00225 public function getTagLink( $sTag )
00226 {
00227 $oSeoEncoderTag = oxSeoEncoderTag::getInstance();
00228 $iLang = $this->getLanguageId();
00229
00230 $sUrl = false;
00231 if ( oxUtils::getInstance()->seoIsActive() ) {
00232 $sUrl = $oSeoEncoderTag->getTagUrl( $sTag, $iLang );
00233 }
00234 return $sUrl ? $sUrl : $this->getConfig()->getShopUrl() . $oSeoEncoderTag->getStdTagUri( $sTag ) . "&lang=" . $iLang;
00235 }
00236
00244 public function getTagTitle( $sTag )
00245 {
00246 return getStr()->htmlentities( $sTag );
00247 }
00248
00254 protected function _getMaxHit()
00255 {
00256 if ( $this->_iMaxHit === null ) {
00257 $this->_iMaxHit = max( $this->getCloudArray() );
00258 }
00259 return $this->_iMaxHit;
00260 }
00261
00269 public function getTagSize( $sTag )
00270 {
00271 $aCloudArray = $this->getCloudArray();
00272 $iCurrSize = $this->_getFontSize( $aCloudArray[ $sTag ], $this->_getMaxHit() );
00273
00274
00275 return floor( $iCurrSize / OXTAGCLOUD_MINFONT ) * OXTAGCLOUD_MINFONT;
00276 }
00277
00278
00288 public function getTags( $sArtId = null, $blExtended = false, $iLang = null )
00289 {
00290 $oDb = oxDb::getDb( oxDb::FETCH_MODE_ASSOC );
00291
00292 if ($blExtended) {
00293 $iAmount = OXTAGCLOUD_EXTENDEDCOUNT;
00294 } else {
00295 $iAmount = OXTAGCLOUD_STARTPAGECOUNT;
00296 }
00297
00298 $sArtView = getViewName( 'oxarticles', $iLang );
00299 $sViewName = getViewName( 'oxartextends', $iLang );
00300
00301
00302 $oArticle = oxNew( 'oxarticle' );
00303 $oArticle->setLanguage( $iLang );
00304 $sArtActive = $oArticle->getActiveCheckQuery(true);
00305
00306
00307 $sQ = "SELECT {$sViewName}.`oxtags` AS `oxtags`
00308 FROM {$sArtView} AS `oxarticles`
00309 LEFT JOIN {$sViewName} ON `oxarticles`.`oxid` = {$sViewName}.`oxid`
00310 WHERE `oxarticles`.`oxactive` = 1 AND $sArtActive";
00311
00312 if ( $sArtId ) {
00313 $sQ = "SELECT {$sViewName}.`oxtags` AS `oxtags` FROM {$sViewName} WHERE `oxid` = " . $oDb->quote( $sArtId );
00314 $iAmount = 0;
00315 }
00316
00317 $oDb->setFetchMode( oxDb::FETCH_MODE_ASSOC );
00318 $rs = $oDb->select( $sQ );
00319 $aTags = array();
00320 while ( $rs && $rs->recordCount() && !$rs->EOF ) {
00321 $sTags = $this->trimTags( $rs->fields['oxtags'] );
00322 $aArticleTags = explode( $this->_sSeparator, $sTags );
00323 foreach ( $aArticleTags as $sTag ) {
00324 if ( trim( $sTag ) ) {
00325 ++$aTags[$sTag];
00326 }
00327 }
00328 $rs->moveNext();
00329 }
00330
00331
00332 if ( $iAmount ) {
00333 arsort( $aTags );
00334 $aTags = array_slice( $aTags, 0, $iAmount, true );
00335 }
00336
00337 $aTags = $this->_sortTags( $aTags );
00338 return $aTags;
00339 }
00340
00349 protected function _sortTags( $aTags, $iLang = null )
00350 {
00351 if ( is_array( $aTags ) && count( $aTags ) ) {
00352 $oDb = oxDb::getDb( oxDb::FETCH_MODE_ASSOC );
00353 $sSubQ = '';
00354 foreach ( $aTags as $sKey => $sTag ) {
00355 if ( $sSubQ ) {
00356 $sSubQ .= ' union all ';
00357 }
00358 $sSubQ .= 'select '.$oDb->quote( $sKey ).' as _oxsort, '.$oDb->quote( $sTag ).' as _oxval';
00359 }
00360
00361 $sViewName = getViewName( "oxartextends", $iLang );
00362
00363
00364 $sSubQ = "select {$sViewName}.oxtags as _oxsort, 'ox_skip' as _oxval from {$sViewName} limit 1 union $sSubQ";
00365 $sQ = "select _oxtable._oxsort, _oxtable._oxval from ( {$sSubQ} ) as _oxtable order by _oxtable._oxsort desc";
00366
00367 $aTags = array();
00368 $oDb->setFetchMode( oxDb::FETCH_MODE_ASSOC );
00369 $oRs = $oDb->select( $sQ );
00370 while ( $oRs && $oRs->recordCount() && !$oRs->EOF ) {
00371 if ( $oRs->fields['_oxval'] != 'ox_skip' ) {
00372 $aTags[$oRs->fields['_oxsort']] = $oRs->fields['_oxval'];
00373 }
00374 $oRs->moveNext();
00375 }
00376 }
00377 return $aTags;
00378 }
00379
00388 protected function _getFontSize( $iHit, $iMaxHit )
00389 {
00390
00391 if ($iMaxHit <= OXTAGCLOUD_MINOCCURENCETOSHOW || !$iMaxHit) {
00392 return OXTAGCLOUD_MINFONT;
00393 }
00394
00395 $iFontDiff = OXTAGCLOUD_MAXFONT - OXTAGCLOUD_MINFONT;
00396 $iMaxHitDiff = $iMaxHit - OXTAGCLOUD_MINOCCURENCETOSHOW;
00397 $iHitDiff = $iHit - OXTAGCLOUD_MINOCCURENCETOSHOW;
00398
00399 if ($iHitDiff < 0) {
00400 $iHitDiff = 0;
00401 }
00402
00403 $iSize = round($iHitDiff * $iFontDiff / $iMaxHitDiff) + OXTAGCLOUD_MINFONT;
00404
00405 return $iSize;
00406 }
00407
00415 public function _fixTagLength( $sTag )
00416 {
00417 $oStr = getStr();
00418 $sTag = trim( $sTag );
00419 $iLen = $oStr->strlen( $sTag );
00420
00421 if ( $iLen < OXTAGCLOUD_MINTAGLENGTH ) {
00422 $sTag .= str_repeat( '_', OXTAGCLOUD_MINTAGLENGTH - $iLen );
00423 }
00424
00425 return $sTag;
00426 }
00427
00435 public function stripMetaChars( $sText )
00436 {
00437 $oStr = getStr();
00438
00439
00440 $sText = str_replace($this->_aMetaChars, ' ', $sText);
00441
00442
00443 $sText = $oStr->preg_replace( "/\s+/", " ", trim( $sText ) );
00444
00445 return $sText;
00446 }
00447
00457 public function prepareTags( $sTags )
00458 {
00459 $sTags = $this->stripMetaChars($sTags);
00460 $aTags = explode( $this->_sSeparator, $sTags );
00461 $aRes = array();
00462 $oStr = getStr();
00463
00464 foreach ( $aTags as $sTag ) {
00465 if ( ( $sTag = trim( $sTag ) ) ) {
00466 $sRes = '';
00467 $iLen = $oStr->strlen( $sTag );
00468 if ( $iLen > $this->_iTagMaxLength ) {
00469 $sTag = $oStr->substr($sTag, 0, $this->_iTagMaxLength);
00470 }
00471 $sTag = trim( $sTag );
00472 $aMatches = explode(' ', $sTag);
00473 foreach ( $aMatches as $iKey => $sMatch ) {
00474 $sRes .= $oStr->strtolower( $this->_fixTagLength($sMatch ) )." ";
00475 }
00476 $aRes[] = trim( $sRes );
00477 }
00478 }
00479
00480 return implode( $this->_sSeparator, $aRes );
00481 }
00482
00490 public function trimTags( $sTags )
00491 {
00492 $oStr = getStr();
00493 $sTags = $oStr->preg_replace( "/(\s*\,+\s*)+/", ",", trim( $sTags ) );
00494 $sRes = '';
00495
00496 if ( $oStr->preg_match_all( "/([\s\,\-]?)([^\s\,\-]+)([\s\,\-]?)/", $sTags, $aMatches ) ) {
00497 foreach ( $aMatches[0] as $iKey => $sMatch ) {
00498 $sProc = $aMatches[2][$iKey];
00499 if ( $oStr->strlen( $sProc ) <= OXTAGCLOUD_MINTAGLENGTH ) {
00500 $sProc = rtrim( $sProc, "_" );
00501
00502 }
00503 $sRes .= $aMatches[1][$iKey] . $sProc . $aMatches[3][$iKey];
00504 }
00505 }
00506
00507 return trim( $sRes, $this->_sSeparator );
00508 }
00509
00517 public function resetTagCache( $iLang = null )
00518 {
00519 $myUtils = oxUtils::getInstance();
00520
00521 $sCacheKey1 = $this->_getCacheKey( true, $iLang );
00522 $myUtils->toFileCache( $sCacheKey1, null );
00523
00524 $sCacheKey2 = $this->_getCacheKey( false, $iLang );
00525 $myUtils->toFileCache( $sCacheKey2, null );
00526 }
00527
00536 protected function _getCacheKey( $blExtended, $iLang = null )
00537 {
00538 return $this->_sCacheKey."_".$this->getConfig()->getShopId()."_".( ( $iLang !== null ) ? $iLang : oxLang::getInstance()->getBaseLanguage() ) ."_".($blExtended?1:0);
00539 }
00540
00548 public function canBeTagged( $sTagTitle )
00549 {
00550 $aProducts = oxSession::getVar("aTaggedProducts");
00551 if ( isset($aProducts) && $aTags = $aProducts[$this->getProductId()]) {
00552 if ( $aTags[$sTagTitle] == 1 ) {
00553 return false;
00554 }
00555 }
00556 return true;
00557 }
00558
00559 }