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 )."_".$sProductId;
00194         if ( !isset( $this->_aCloudArray[$sCacheIdent] ) ) {
00195 
00196             $myUtils = oxUtils::getInstance();
00197 
00198             // checking cache
00199             $aCloudArray = ( !$sProductId ) ? $myUtils->fromFileCache( $sCacheIdent ) : null;
00200 
00201             // loading cloud info
00202             if ( $aCloudArray === null ) {
00203                 $aCloudArray = $this->getTags( $sProductId, $blExtended, $iLang );
00204                 // updating cache
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 ) . "&amp;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         // calculating min size
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         // check if article is still active
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         //taking only top tags
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             // forcing collation
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         //handling special case
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         // Remove meta chars
00437         $sText = str_replace($this->_aMetaChars, ' ', $sText);
00438 
00439         // Replace multiple spaces with single space
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 }