<?php

/**
 * <pre>
 * Invision Power Services
 * IP.Board v3.2.3
 * Tagging: Cloud class - is it bird? is it a cloud? No it's a.. nope, it's a cloud. Sorry for that.
 * Matt Mecham
 * Last Updated: $Date: 2011-08-08 04:56:34 -0400 (Mon, 08 Aug 2011) $
 * </pre>
 *
 * @author 		$Author: mmecham $
 * @copyright	(c) 2001 - 2011 Invision Power Services, Inc.
 * @license		http://www.invisionpower.com/community/board/license.html
 * @package		IP.Board
 * @link		http://www.invisionpower.com
 * @since		24 Feb 2011
 * @version		$Revision: 9375 $
 *
 */

if ( ! defined( 'IN_IPB' ) )
{
	print "<h1>Incorrect access</h1>You cannot access this file directly. If you have recently upgraded, make sure you upgraded all the relevant files.";
	exit();
}

class classes_tags_cloud
{
	/**#@+
	 * Registry objects
	 *
	 * @access	protected
	 * @var		object
	 */	
	protected $registry;
	protected $DB;
	protected $settings;
	protected $request;
	protected $lang;
	protected $member;
	protected $memberData;
	protected $cache;
	protected $caches;
	/**#@-*/
	
	protected $app  = '';
	protected $area = '';
	protected $errorMsg = '';
	protected $relId    = 0;
	protected $parentId = 0;
	protected $skinGroup    = 'global_other';
	protected $skinTemplate = 'tagCloud';
	
	/**
	 * @return the $errorMsg
	 */
	public function getErrorMsg()
	{
		return $this->errorMsg;
	}

	/**
	 * @param field_type $errorMsg
	 */
	public function setErrorMsg( $errorMsg )
	{
		$this->errorMsg = $errorMsg;
	}

	/**
	 * @return the $app
	 */
	public function getApp()
	{
		return $this->app;
	}

	/**
	 * @return the $area
	 */
	public function getArea()
	{
		return $this->area;
	}

	/**
	 * @param field_type $app
	 */
	public function setApp( $app )
	{
		$this->app = $app;
	}

	/**
	 * @param field_type $area
	 */
	public function setArea( $area )
	{
		$this->area = $area;
	}
	
	
	/**
	 * @return the $relId
	 */
	public function getRelId()
	{
		return $this->relId;
	}

	/**
	 * @param field_type $relId
	 */
	public function setRelId( $relId )
	{
		$this->relId = intval( $relId );
	}

	/**
	 * @return the $parentId
	 */
	public function getParentId()
	{
		return $this->parentId;
	}

	/**
	 * @param field_type $parentId
	 */
	public function setParentId( $parentId )
	{
		$this->parentId = intval( $parentId );
	}

	/**
	 * @return the $skinGroup
	 */
	public function getSkinGroup()
	{
		return $this->skinGroup;
	}

	/**
	 * @param field_type $skinGroup
	 */
	public function setSkinGroup( $skinGroup )
	{
		$this->skinGroup = $skinGroup;
	}

	/**
	 * @return the $skinTemplate
	 */
	public function getSkinTemplate()
	{
		return $this->skinTemplate;
	}

	/**
	 * @param field_type $skinTemplate
	 */
	public function setSkinTemplate( $skinTemplate )
	{
		$this->skinTemplate = $skinTemplate;
	}

	/**
	 * Is tagging enabled?
	 * 
	 * @return 	Booyaleean
	 */
	protected function _isEnabled()
	{
		return ( $this->settings['tags_enabled'] ) ? true : false;	
	}
	
	/**
	 * Setup registry classes
	 *
	 * @return	@e void
	 */
	public function __construct()
	{
		/* Make registry objects */
		$this->registry   =  ipsRegistry::instance();
		$this->DB         =  $this->registry->DB();
		$this->settings   =& $this->registry->fetchSettings();
		$this->request    =& $this->registry->fetchRequest();
		$this->lang       =  $this->registry->getClass('class_localization');
		$this->member     =  $this->registry->member();
		$this->memberData =& $this->registry->member()->fetchMemberData();
		$this->cache      =  $this->registry->cache();
		$this->caches     =& $this->registry->cache()->fetchCaches();
		
		/* Clean member perm array */
		foreach( $this->member->perm_id_array as $k => $v )
		{
			if ( empty( $v ) )
			{
				unset( $this->member->perm_id_array[ $k ] );
			}
		}
	}
	
	/**
	 * Render the cloud
	 * @param array $data returned from getCloudData
	 */
	public function render( array $data )
	{
		$group = $this->getSkinGroup();
		$templ = $this->getSkinTemplate();
	
		/* Some basic formatt-ing */
		foreach( $data['tags'] as $id => $val )
		{
			$data['tags'][ $id ]['className']  = $this->_weightToClassName( $val['weight'] );
			$data['tags'][ $id ]['tagWithUrl'] = $this->registry->output->getTemplate('global_other')->tagEntry( $val['tag'], true );
		}
		
		return $this->registry->output->getTemplate( $group )->$templ( $data );
	}
	
	protected function _weightToClassName( $weight )
	{
		$className = 'ipsTagWeight_1';
		
		if ( $weight < 0.9 )
		{
			$className = 'ipsTagWeight_2';
		}
		
		if ( $weight < 0.8 )
		{
			$className = 'ipsTagWeight_3';
		}
		
		if ( $weight < 0.7 )
		{
			$className = 'ipsTagWeight_4';
		}
	
		if ( $weight < 0.6 )
		{
			$className = 'ipsTagWeight_5';
		}
	
		if ( $weight < 0.5 )
		{
			$className = 'ipsTagWeight_6';
		}
	
		if ( $weight < 0.4 )
		{
			$className = 'ipsTagWeight_7';
		}
	
		if ( $weight < 0.3 )
		{
			$className = 'ipsTagWeight_8';
		}
		
		return $className;
	}
	
	/**
	 * getCloudData
	 * 
	 * Filters:
	 * limit		Limit the number of tags returned
	 * visible		The number of visible tags
	 * noCache		Bypass any caching and always fetch fresh
	 * 
	 * @param	array	Filters (limit, visible)
	 */
	public function getCloudData( $filters=array() )
	{
		/* INIT */
		$where = array();
		$data  = array();
		$raw   = array();
		$nums  = array( 'min' => 0, 'max' => 0, 'count' => 0 );
		$final = array( 'tags' => array(), 'nums' => array() );
		
		/* Clean up filters */
		$filters['limit']   = intval( $filters['limit'] );
		$filters['offset']  = intval( $filters['offset'] );
		
		$filters['visible'] = ( ! isset( $filters['visible'] ) ) ? 1 : intval( $filters['visible'] );
		
		if ( $this->getApp() && $this->getArea() && $this->getRelId() )
		{
			$where[] = "t.tag_aai_lookup='" . $this->_getKey( array( 'meta_id' => $this->getRelId() ) ) . "'";
		}
		else if ( $this->getApp() && $this->getArea() && $this->getParentId() )
		{
			$where[] = "t.tag_aap_lookup='" . $this->_getKey( array( 'meta_parent_id' => $this->getParentId() ) ) . "'";
		}
		
		if ( $this->getApp() )
		{
			$where[] = "t.tag_meta_app='" . $this->DB->addSlashes( $this->getApp() ) . "'";
		}
		
		if ( $this->getArea() )
		{
			$where[] = "t.tag_meta_area='" . $this->DB->addSlashes( $this->getArea() ) . "'";
		}
		
		/* Test against cache class */
		if ( empty( $filters['noCache'] ) )
		{
			$cacheKey = 'tagCloud-' . md5( implode( '&', $where ) );
			$cached   = $this->registry->getClass('cacheSimple')->get( $cacheKey );
			
			if ( $cached !== null && is_array( $cached['data'] ) )
			{
				$cached['data']['cached'] = $cached['time'];
				
				return $cached['data'];
			}
		}
		
		/* Still here? Fetch from the database */
		$this->DB->allow_sub_select = true;
		$this->DB->loadCacheFile( IPSLib::getAppDir('core') . '/sql/' . ips_DBRegistry::getDriverType() . '_tag_queries.php', 'public_tag_sql_queries' );
		$this->DB->buildFromCache( 'getCloudData', array( 'where' => $where, 'limit' => array( $filters['offset'], $filters['limit'] ) ), 'public_tag_sql_queries' );
		$o = $this->DB->execute();
		
		while( $tag = $this->DB->fetch() )
		{
			$raw[ $tag['times'] . '.' . md5( $tag['tag_text'] ) ] = $tag;
			
			if ( empty( $nums['min'] ) OR $nums['min'] > $tag['times'] )
			{
				$nums['min'] = $tag['times'];
			}
			
			if ( $nums['max'] < $tag['times'] )
			{
				$nums['max'] = $tag['times'];
			}
			
			$nums['count'] += $tag['times'];
		}
		
		/* Sort it */
		krsort( $raw );
		
		/* Now give out some useful data */
		foreach( $raw as $key => $data )
		{
			/* Work out a percentage */
			$percent = sprintf( '%.2F', $data['times'] / $nums['max'] * 100 );
			
			$final['tags'][] = array( 'tag'     => $data['tag_text'],
							  		  'count'   => $data['times'],
							  	  	  'percent' => $percent,
									  'weight'  => sprintf( '%.2F', $percent / 100 ) );
		}
		
		$final['nums'] = $nums;
		
		/* Cache */
		$this->registry->getClass('cacheSimple')->set( $cacheKey, $final );
		
		return $final;
	}
	
	/**
	 * Build a key
	 */
	private function _getKey( $where )
	{		
		if ( isset( $where['meta_id'] ) )
		{
			return md5( $this->getApp() . ';' . $this->getArea() . ';' . intval( $where['meta_id'] ) );
		}
		else if ( isset( $where['meta_parent_id'] ) )
		{
			return md5( $this->getApp() . ':' . $this->getArea() . ':' . intval( $where['meta_parent_id'] ) );
		}
	}
	
	
}