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 $_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         // collecting cloud info
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         // checking if current data is allready loaded
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             // checking cache
00202             $aCloudArray = ( !$sProductId ) ? $myUtils->fromFileCache( $sCacheIdent ) : null;
00203 
00204             // loading cloud info
00205             if ( $aCloudArray === null ) {
00206                 $aCloudArray = $this->getTags( $sProductId, $blExtended, $iLang );
00207                 // updating cache
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 ) . "&amp;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         // calculating min size
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         // check if article is still active
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         //taking only top tags
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             // forcing collation
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         //handling special case
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         // Remove meta chars
00440         $sText = str_replace($this->_aMetaChars, ' ', $sText);
00441 
00442         // Replace multiple spaces with single space
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 }