<?php
	
class WordCloud
{
	var $version = '2.0';
	var $wordsArray = array();
	var $limitAmount = 0;
	
	/*
	 * PHP 5 Constructor
	 *
	 * @param array $words
	 * 		 
	 * @return void
	 */
	
	function __construct($words = false)
	{
		// If we are trying to parse some works, in any format / type
		if ( $words !== false ) {
			// If we have a string
			if (is_string($words)) {
				$this->addString($words);
			} elseif (count($words)) {
				foreach ($words as $key => $value) {
					$this->addWord($value);
				}
			}
		}
		return;
	}
	
	/*
	 * PHP 4 Constructor
	 *
	 * @param array $words
	 * 		 
	 * @return void
	 */
	
	function wordCloud($words = false)
	{
		return $this->__construct($words);
	}
	
	/*
	 * Convert a string into a cloud
	 *
	 * @param string $string
	 * @return void
	 */
	
	function addString($string)
	{
		// remove all other chars apart from a-z
		$string = preg_replace('[^a-z]', '', strip_tags(strtolower($string)));
		$words = array();
		$words = explode(' ', $string);
		if (count($words)) {
			foreach ($words as $key => $value) {
				$this->addWord($value);
			}
		}
	}
	
	/*
	 * Display user friendly message, for debugging mainly
	 *
	 * @param string $string
	 * @param array $value
*
	 * @return bool
	 */
	
	function notify($string, $value)
	{
		echo '<pre>';
		print_r($string);
		print_r($value);
		echo '</pre>';
		return false;
	}
	
	/*
	 * Assign word to array
	 *
	 * @param string $word
	 * 		 
	 * @return string
	 */
	
	function addWord($wordAttributes = array())
	{
		if (is_string($wordAttributes)) {
			$wordAttributes = array('word' => $wordAttributes);
		}
		if (!array_key_exists('size', $wordAttributes)) {
			$wordAttributes = array_merge($wordAttributes, array('size' => 1));
		}
		if (!array_key_exists('word', $wordAttributes)) {
			return $this->notify('no word attribute', print_r($wordAttributes, true));
		}
		$word = strtolower($wordAttributes['word']);
		if (empty($this->wordsArray[$word])) {
			$this->wordsArray[$word] = array();
		}
		if (!empty($this->wordsArray[$word]['size']) && !empty($wordAttributes['size'])) {
			$wordAttributes['size'] = ($this->wordsArray[$word]['size'] + $wordAttributes['size']);
		} elseif (!empty($this->wordsArray[$word]['size'])) {
			$wordAttributes['size'] = $this->wordsArray[$word]['size'];
		}
		$this->wordsArray[$word] = $wordAttributes;
		return $this->wordsArray[$word];
	}
	
	/*
	 * Shuffle associated names in array
	 *
	 * @return array $this->wordsArray
	 */
	
	function shuffleCloud ()
	{
		$keys = array_keys($this->wordsArray);
		shuffle($keys);
		if (count($keys) && is_array($keys)) {
			$tmpArray = $this->wordsArray;
			$this->wordsArray = array();
			foreach ($keys as $key => $value)
				$this->wordsArray[$value] = $tmpArray[$value];
		}
		return $this->wordsArray;
	}
	
	/*
	 * Get the class range using a percentage
	 *
	 * @returns int $class
	 */
	
	function getClassFromPercent($percent)
	{
		if ($percent >= 99)
			$class = 9;
		elseif ($percent >= 70)
			$class = 8;
		elseif ($percent >= 60)
			$class = 7;
		elseif ($percent >= 50)
			$class = 6;
		elseif ($percent >= 40)
			$class = 5;
		elseif ($percent >= 30)
			$class = 4;
		elseif ($percent >= 20)
			$class = 3;
		elseif ($percent >= 10)
			$class = 2;
		elseif ($percent >= 5)
			$class = 1;
		else
			$class = 0;
		return $class;
	}
	
	/*
	 * Sets a limit for the amount of clouds
	 *
	 * @param string $limit		 
	 *		 
	 * @returns string $this->limitAmount
	 */
	
	function setLimit ( $limit = FALSE )
	{
		if ( $limit != FALSE ) {
			$this->limitAmount = $limit;
		}
	}
	
	/*
	 * Gets the limited amount of clouds
	 *
	 * @returns string $wordCloud
	 */
	
	function limitCloud ()
	{
		if ( $this->limitAmount > 0 ) {
			$i = 1;
			foreach ( $this->wordsArray as $key => $value ) {
				if ( $this->limitAmount >= $i ) {
					$wordsArray [ $value [ 'word' ] ] = $value;				
				}
				$i++;			
			}
			$this->wordsArray = array();
			$this->wordsArray = $wordsArray;
			return $this->wordsArray;
		}
	}
	
	/*
	 * Finds the maximum value of an array
	 *
	 * @param string $word		 
	 *		 
	 * @returns void
	 */
	
	function removeWord ( $word )
	{
		$this->removeWords[] = strtolower($word);
	}
	
	/*
	 * Removes tags from the whole array
	 *
	 * @returns array $this->wordsArray
	 */
	
	function removeWords()
	{
		foreach ($this->wordsArray as $key => $value) {
			if (!in_array($value['word'], $this->removeWords)) {
				$wordsArray[$value['word']] = $value;
			}
		}
		$this->wordsArray = array();
		$this->wordsArray = $wordsArray;
		return $this->wordsArray;
	}
	
	/*
	 * Assign the order field and order direction of the cloud
	 *
	 * @param array $field
	 * @param string $sortway
	 *     		 
	 * @returns void
	 */
	
	function orderBy($field, $direction = 'ASC')
	{
		return $this->orderBy = array ( 'field' => $field, 'direction' => $direction );
	}
	
	/*
	 * Orders the cloud by a specific field
	 *
	 * @param array $unsortedArray
	 * @param string $sortField
	 * @param string $sortWay
	 *     		 
	 * @returns array $unsortedArray
	 */
	
	function orderCloud ( $unsortedArray, $sortField, $sortWay = 'SORT_ASC' )
	{
	 	$sortedArray = array();
		foreach ( $unsortedArray as $uniqid => $row ) {
			foreach ( $row as $key => $value )
			{
				$sortedArray [ $key ] [ $uniqid ] = strtolower ( $value );
			}
		}
		if ( $sortWay ) {
			array_multisort ( $sortedArray [ $sortField ], constant ( $sortWay ), $unsortedArray );
		}
		return $unsortedArray;
	}
	
	/*
	 * Finds the maximum value of an array
	 *
	 * @returns string $max
	 */
	
	function getMax ()
	{
		$max = 0;
		if ( ! empty ( $this->wordsArray ) ) {
			$p_size = 0;
			foreach ( $this->wordsArray as $cKey => $cVal )
			{
				$c_size = $cVal [ 'size' ];
				if ( $c_size > $p_size )
					$max = $c_size;
				$p_size = $c_size;
			}
		}
		return $max;
	}
	
	/*
	 * Create the HTML code for each word and apply font size.
	 *
	 * @returns string/array $return
	 */
	
	function showCloud ( $returnType = 'html' )
	{
		if ( empty ( $this->orderBy ) ) {
			$this->shuffleCloud ();
		}
		else {
			$orderDirection = strtolower ( $this->orderBy [ 'direction' ] ) == 'desc' ? 'SORT_DESC' : 'SORT_ASC';
			$this->wordsArray = $this->orderCloud ( $this->wordsArray, $this->orderBy [ 'field' ], $orderDirection );
		}
		if ( ! empty ( $this->limitAmount ) ) {
			$this->limitCloud ();
		}
		if ( ! empty ( $this->removeWords ) ) {
			$this->removeWords ();
		}
		$this->max = $this->getMax ();
		if ( is_array ( $this->wordsArray ) ) {
			$return = ( $returnType == 'html' ? '' : ( $returnType == 'array' ? array () : '' ) );
			foreach ( $this->wordsArray as $word => $arrayInfo ) 
			{
				$sizeRange = $this->getClassFromPercent ( ( $arrayInfo [ 'size' ] / $this->max ) * 100 );
				$arrayInfo [ 'range' ] = $sizeRange;
				if ( $returnType == 'array' ) {
					$return [ $word ] = $arrayInfo;
				}
				elseif ( $returnType == 'html' ) {
					$return .= "		<span class='word size{$sizeRange}'> &nbsp; {$arrayInfo['word']} &nbsp; </span>\n";
				}
			}
			return $return;
		}
	}
}
//END