oxtagcloud.php

Go to the documentation of this file.
00001 <?php
00002 
00003 if (!defined('OXTAGCLOUD_MINFONT')) {
00004     define('OXTAGCLOUD_MINFONT', 100);
00005     define('OXTAGCLOUD_MAXFONT', 400);
00006     define('OXTAGCLOUD_MINOCCURENCETOSHOW', 2);
00007     //depends on mysql server configuration
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         // collecting cloud info
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         // checking if current data is allready loaded
00174         $sCacheIdent = $this->_getCacheKey( $blExtended, $iLang )."_".$sProductId;
00175         if ( !isset( $this->_aCloudArray[$sCacheIdent] ) ) {
00176 
00177             $myUtils = oxUtils::getInstance();
00178 
00179             // checking cache
00180             $aCloudArray = ( !$sProductId ) ? $myUtils->fromFileCache( $sCacheIdent ) : null;
00181 
00182             // loading cloud info
00183             if ( $aCloudArray === null ) {
00184                 $aCloudArray = $this->getTags( $sProductId, $blExtended, $iLang );
00185                 // updating cache
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 ) . "&amp;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         // calculating min size
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         //$sQ = "select $sField from oxartextends where $sArticleSelect";
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         //taking only top tags
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             // forcing collation
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 ) . "&amp;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         //handling special case
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         // Remove meta chars
00468         $sText = str_replace($this->_aMetaChars, ' ', $sText);
00469 
00470         // Replace multiple spaces with single space
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 }