/tagclouds.php
PHP | 870 lines | 394 code | 117 blank | 359 comment | 41 complexity | 48a85bdc8fa90e3fe78fcd10d67f836c MD5 | raw file
- <?php
- /**
- #########################################################################################################
- # Project: PHP Link Directory - Link exchange directory @ http://www.phplinkdirectory.com/
- # Module: phpLD Simple TagCloud
- # Homepage: http://www.frozenminds.com/phpld-tagclouds.html
- # Author: Constantin Bejenaru aKa Boby @ http://www.frozenminds.com/
- # Language: PHP + xHTML + CSS
- # License: GPL @ http://www.gnu.org/copyleft/gpl.html
- # Version: 1.3
- # Notice: Please maintain this section
- #########################################################################################################
- # Copyright (c) 2006-2009 Constantin Bejenaru - http://www.frozenminds.com/
- #
- # This program is free software; you can redistribute it and/or
- # modify it under the terms of the GNU General Public License
- # as published by the Free Software Foundation; either version 2
- # of the License, or (at your option) any later version.
- #
- # This program is distributed in the hope that it will be useful,
- # but WITHOUT ANY WARRANTY; without even the implied warranty of
- # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- # GNU General Public License for more details.
- #
- # You should have received a copy of the GNU General Public License
- # along with this program; if not, write to the Free Software
- # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- #########################################################################################################
- */
- class phpld_tagclouds
- {
- /**
- * Array with words and word count
- *
- * @var array
- */
- protected $_tags = array ();
- /**
- * String of words
- *
- * @var string
- */
- protected $_tags_string = '';
- /**
- * Maximum allowed words (most important selected, the rest is removed)
- *
- * @var integer (zero or NULL means infinite)
- */
- protected $_maxWordsCount = 20;
- /**
- * Minimum occurrences of a word to be displayed
- *
- * @var integer
- */
- protected $_minCountValue = 0;
- /**
- * Minimum length of word to be displayed
- *
- * @var integer
- */
- protected $_minWordLen = 2;
- /**
- * Maximum length of a word to be displayed
- *
- * @var integer
- */
- protected $_maxWordLen = 30;
- /**
- * Minimum font size of a tag to be displayed
- *
- * @var integer
- */
- protected $_minFontSize = 30;
- /**
- * Maximum font size of a tag to be displayed
- *
- * @var integer
- */
- protected $_maxFontSize = 400;
- /**
- * Maximum number of style class to use
- *
- * @var integer
- */
- protected $_styleclass = 5;
- /**
- * Sort method
- * (alphabetical, count, random)
- *
- * @var string
- */
- protected $_sort = 'alphabetical';
- /**
- * Filter numeric words
- *
- * @var boolean
- */
- protected $_filter_numeric = TRUE;
- /**
- * Normalize tag cloud
- *
- * @var boolean
- */
- protected $_normalize = TRUE;
- /**
- * Words to not be displayed
- *
- * @var array
- */
- protected $_exclude_words = array ();
- /**
- * Change search URL variable
- *
- * @var string
- */
- protected $_searchVariable = 'search';
- /**
- * Tagclouds title
- *
- * @var string
- */
- protected $_cloudsTitle = '';
- /**
- * Encoding
- *
- * @var string
- */
- protected $_encoding = 'UTF-8';
- /**
- * Full HTML output
- *
- * @var string
- */
- protected $output = '';
- /**
- * Build tags output and return it
- *
- * @return string
- */
- public function get_tagclouds ()
- {
- //Detect current encoding
- $this->_encoding = mb_strtoupper (mb_detect_encoding ($this->_tags_string, 'auto', TRUE));
- //Convert to UTF-8 if needed
- if ('UTF-8' !== $this->_encoding)
- {
- $this->_tags_string = $this->toUTF8 ($this->_tags_string);
- //Detect new encoding
- $this->_encoding = mb_strtoupper (mb_detect_encoding ($this->_tags_string, 'auto', TRUE));
- }
- //Clean string
- $this->_tags_string = $this->clean_tagstring ($this->_tags_string);
- //Build array of tags from string
- $this->build_tags_array ($this->_tags_string);
- //Build the output
- $this->build_output ();
- //Make output
- return $this->output;
- }
- /**
- * Define maximum number of allowed tags
- *
- * @param integer (zero or NULL mean infinite)
- */
- public function maxWordsCount ($val)
- {
- //Validate and save value
- if (empty ($val))
- {
- $this->_maxWordsCount = null;
- }
- $this->_maxWordsCount = is_numeric ($val) ? intval ($val) : $this->_minCountValue;
- }
- /**
- * Change minimum occurrences of a word to be displayed
- *
- * @param integer
- */
- public function mincount ($val)
- {
- //Validate and save value
- $this->_minCountValue = is_numeric ($val) ? intval ($val) : $this->_minCountValue;
- }
- /**
- * Change minimum length of a word to be displayed
- *
- * @param integer
- */
- public function minWordLength ($val)
- {
- //Validate and save value
- $this->_minWordLen = is_numeric ($val) ? intval ($val) : $this->_minWordLen;
- }
- /**
- * Change maximum length of a word to be displayed
- *
- * @param integer
- */
- public function maxWordLength ($val)
- {
- //Validate and save value
- $this->_maxWordLen = is_numeric ($val) ? intval ($val) : $this->_maxWordLen;
- }
- /**
- * Change minimum font size of a tag to be displayed
- *
- * @param integer
- */
- public function minfontsize ($val)
- {
- //Validate and save value
- $this->_minFontSize = is_numeric ($val) ? intval ($val) : $this->_minFontSize;
- }
- /**
- * Change maximum font size of a tag to be displayed
- *
- * @param integer
- */
- public function maxfontsize ($val)
- {
- //Validate and save value
- $this->_maxFontSize = is_numeric ($val) ? intval ($val) : $this->_maxFontSize;
- }
- /**
- * Define maximum nuber for element class (CSS styling)
- *
- * @param integer
- */
- public function styleclass ($val)
- {
- //Validate and save value
- $this->_styleclass = is_numeric ($val) ? intval ($val) : $this->_styleclass;
- }
- /**
- * Maximum number of style class to use
- *
- * @param integer
- */
- public function sortmethod ($val)
- {
- //Correct value
- $val = strtolower (trim ($val));
- //Define supported methods for sorting
- $allowedSortMethods = array (
- 'alphabetical' ,
- 'count' ,
- 'random'
- );
- //Validate and save value
- $this->_sort = in_array ($val, $allowedSortMethods) ? $val : 'alphabetical';
- }
- /**
- * Change search URL variable
- *
- * @param string
- */
- public function setsearchvariable ($variable = 'search')
- {
- //Save value
- $this->_searchVariable = trim ($variable);
- }
- /**
- * Filter numeric words
- *
- * @param boolean
- */
- public function filter_numeric ($filter = TRUE)
- {
- $this->_filter_numeric = (boolean) $filter;
- }
- /**
- * Normalize tag cloud
- *
- * @param boolean
- */
- public function normalize ($normalize = TRUE)
- {
- $this->_normalize = (boolean) $normalize;
- }
- /**
- * Change title for tagclouds
- *
- * @param string
- */
- public function title ($title = '')
- {
- //Save value
- $this->_cloudsTitle = trim ($title);
- }
- /**
- * Add more words to not be displayed
- *
- * @param mixed (Array or string)
- * @return boolean TRUE on success, FALSE on error
- */
- public function exclude ($exclude)
- {
- if (empty ($exclude))
- {
- //Nothing to do
- return FALSE;
- }
- else
- {
- if (is_array ($exclude)) //If passed variable is an array, process it as an array
- {
- //Merge with existing exclusion words array
- $this->_exclude_words = array_merge ($this->_exclude_words, $exclude);
- }
- elseif (is_string ($exclude)) //If passed variable is a string, process it as string
- {
- //Clean string
- $exclude = $this->strip_specialchars ($exclude);
- //Convert string to array
- $exclude = explode (' ', $exclude);
- //Merge with existing exclusion words array
- if (is_array ($exclude) && ! empty ($exclude))
- {
- $this->_exclude_words = array_merge ($this->_exclude_words, $exclude);
- }
- }
- }
- return TRUE;
- }
- /**
- * Process categories
- *
- * @param mixed (Array or string)
- * @return boolean TRUE on success, FALSE on error
- */
- public function add_categories ($categories)
- {
- if (empty ($categories))
- {
- //Nothing to do
- return FALSE;
- }
- else
- {
- //If passed variable is an array, process it as an array
- if (is_array ($categories))
- {
- //Process each category at a time
- foreach ($categories as $key => $categ)
- {
- //Add category title text
- if (! empty ($categ['TITLE']))
- {
- $this->_tags_string .= ' ' . $categ['TITLE'];
- }
- //Add category description text
- if (! empty ($categ['DESCRIPTION']))
- {
- $this->_tags_string .= ' ' . $categ['DESCRIPTION'];
- }
- //Process subdirectories if available
- if (isset ($categ['SUBCATS']) && is_array ($categ['SUBCATS']) && ! empty ($categ['SUBCATS']))
- {
- //Process each subcategory at a time
- foreach ($categ['SUBCATS'] as $subcateg)
- {
- //Add subcategory title text
- if (! empty ($subcateg['TITLE']))
- {
- $this->_tags_string .= ' ' . $subcateg['TITLE'];
- }
- //Add subcategory description text
- if (! empty ($subcateg['DESCRIPTION']))
- {
- $this->_tags_string .= ' ' . $subcateg['DESCRIPTION'];
- }
- //Free memory
- unset ($subcateg, $categ['SUBCATS'][$key]);
- }
- }
- //Free memory
- unset ($categ, $categories[$key]);
- }
- }
- elseif (is_string ($categories)) //If passed variable is a string, process it as string
- {
- //Add category text
- $this->_tags_string .= ' ' . $categories;
- }
- //Free memory
- unset ($categories);
- }
- return TRUE;
- }
- /**
- * Process links
- *
- * @param mixed (Array or string)
- * @return boolean TRUE on success, FALSE on error
- */
- public function add_links ($links)
- {
- if (empty ($links))
- {
- //Nothing to do
- return FALSE;
- }
- else
- {
- //If passed variable is an array, process it as an array
- if (is_array ($links))
- {
- //Process each link at a time
- foreach ($links as $key => $link)
- {
- //Add link title text
- if (! empty ($link['TITLE']))
- {
- $this->_tags_string .= ' ' . $link['TITLE'];
- }
- //Add link description text
- if (! empty ($link['DESCRIPTION']))
- {
- $this->_tags_string .= ' ' . $link['DESCRIPTION'];
- }
- //Free memory
- unset ($link, $links[$key]);
- }
- }
- elseif (is_string ($links)) //If passed variable is a string, process it as string
- {
- //Add link text
- $this->_tags_string .= ' ' . $links;
- }
- //Free memory
- unset ($links);
- }
- return TRUE;
- }
- /**
- * Process articles
- *
- * @param mixed (Array or string)
- * @return boolean TRUE on success, FALSE on error
- */
- function add_articles ($articles)
- {
- if (empty ($articles))
- {
- //Nothing to do
- return FALSE;
- }
- else
- {
- //If passed variable is an array, process it as an array
- if (is_array ($articles))
- {
- //Process each link at a time
- foreach ($articles as $key => $article)
- {
- //Add article title text
- if (! empty ($article['TITLE']))
- {
- $this->_tags_string .= ' ' . $article['TITLE'];
- }
- //Add article body text
- if (! empty ($article['ARTICLE']))
- {
- $this->_tags_string .= ' ' . $article['ARTICLE'];
- }
- //Add article description text
- if (! empty ($article['DESCRIPTION']))
- {
- $this->_tags_string .= ' ' . $article['DESCRIPTION'];
- }
- //Free memory
- unset ($article, $articles[$key]);
- }
- }
- elseif (is_string ($article)) //If passed variable is a string, process it as string
- {
- //Add link text
- $this->_tags_string .= ' ' . $article;
- }
- //Free memory
- unset ($article);
- }
- return TRUE;
- }
- /**
- * Clean tag string of unneeded characters
- * (This will also escape the string)
- *
- * @param string
- * @return string
- */
- protected function clean_tagstring ($string = '')
- {
- //Remove HTML and PHP tags
- $string = strip_tags ($string);
- //Strip whitespace
- $string = $this->strip_specialchars ($string);
- //Convert special characters to HTML entities
- $string = $this->escape ($string);
- //Make lowercase and trim
- $string = mb_strtolower ($string, $this->_encoding);
- return trim ($string);
- }
- /**
- * Clean string of whitespace and special characters
- *
- * @param string
- * @return string
- */
- protected function strip_specialchars ($string = '')
- {
- //Handle whitespace
- $string = str_replace (" ", " ", $string); //Windows
- $string = str_replace ("\r\n", " ", $string); //Windows
- $string = str_replace ("\r", " ", $string); //Mac
- $string = str_replace ("\n", " ", $string); //*NIX
- $string = str_replace ("\t", " ", $string); //TAB
- $string = str_replace ("\0", "", $string); //NULL BYTE
- $string = str_replace ("\x0B", "", $string); //Vertical TAB
- //Remove anything except word, digit characters and spaces, at the end remove multiple spaces
- $pattern = array (
- '#[\'"/\.,_\-()!?@\#$%^&*+:;=`<>\\\]#i' , //special chars
- '#[\s]{2,}#' //multiple white-spaces
- );
- $string = preg_replace ($pattern, ' ', $string);
- return trim ($string);
- }
- /**
- * Convert special characters to HTML entities
- *
- * @param string String to be escaped
- * @return string Escaped string
- */
- protected function escape ($string = '')
- {
- return htmlspecialchars ($string, ENT_COMPAT, $this->_encoding);
- }
- /**
- * Converts strings to UTF-8 via iconv. NB, the result may not by UTF-8 if the conversion failed.
- *
- * This file comes from Prado (BSD License)
- *
- * @param string $string string to convert to UTF-8
- * @param string $from current encoding
- * @return string UTF-8 encoded string, original string if iconv failed
- */
- protected function toUTF8 ($string, $from)
- {
- $from = mb_strtoupper ($from);
- if ($from !== 'UTF-8')
- {
- // to UTF-8
- $s = iconv ($from, 'UTF-8', $string);
- // it could return FALSE
- return $s !== FALSE ? $s : $string;
- }
- return $string;
- }
- /**
- * Normalizes a tag cloud, ie. changes a (tag => weight) array into a
- * (tag => normalized_weight) one.
- * Normalized weights range from -2 to 2.
- *
- * @copyright 2007 Xavier Lacot (sfPropelActAsTaggableBehaviorPlugin Plugin for Symfony project)
- * @copyright 2007 Michael Nolan (sfPropelActAsTaggableBehaviorPlugin Plugin for Symfony project)
- *
- * @deprecated
- *
- * @param array $tag_cloud
- * @return array
- */
- protected function normalize_tag_cloud ($tag_cloud)
- {
- //Make sure tag cloud array is an array
- $tag_cloud = (array) $tag_cloud;
- $tags = array ();
- $levels = 5;
- $power = 0.7;
- if (count ($tag_cloud) > 0)
- {
- $max_count = max ($tag_cloud);
- $min_count = min ($tag_cloud);
- $max = intval ($levels / 2);
- if ($max_count != 0)
- {
- foreach ($tag_cloud as $tag => $count)
- {
- $tag = (string) $tag;
- $count = (int) $count;
- $tags[$tag] = (int) round (.9999 * $levels * (pow ($count / $max_count, $power) - .5), 0);
- }
- }
- }
- return (array) $tags;
- }
- /**
- * Build array with tags
- *
- * @param string
- * @return boolean TRUE on success, FALSE on error (=empty tags string)
- */
- protected function build_tags_array ($string = '')
- {
- if (empty ($string))
- {
- return FALSE;
- }
- else
- {
- //Split string into array
- $array = explode (' ', $string);
- //Drop empty values
- $array = array_filter ($array);
- //Count words
- $array_content = array_count_values ($array);
- //Process each word at a time
- foreach ($array_content as $word => $count)
- {
- //Check if word is numeric
- if (TRUE === $this->_filter_numeric && is_numeric ($word))
- {
- continue;
- }
- //Check minimum count value
- if ($count < $this->_minCountValue)
- {
- continue;
- }
- //Check word length
- if (mb_strlen ($word) < $this->_minWordLen || mb_strlen ($word) > $this->_maxWordLen)
- {
- continue;
- }
- //Check if in exclude words
- if (in_array ($word, $this->_exclude_words))
- {
- continue;
- }
- //Word is OK, add to new array
- $this->_tags[$word] = $count;
- //Free memory
- unset ($count, $array_content[$word]);
- }
- //Check if we need to normalize tag cloud
- if (TRUE === $this->_normalize)
- {
- //Normalize
- //$this->_tags = $this->normalize_tag_cloud ($this->_tags);
- }
- //Sort in reverse order (highest counts first)
- //Sortmethod = count
- arsort ($this->_tags);
- if (! empty ($this->_maxWordsCount))
- {
- //Truncate array to maximum allowed words count
- $this->_tags = array_slice ($this->_tags, 0, $this->_maxWordsCount, TRUE);
- }
- switch ($this->_sort)
- {
- case 'alphabetical':
- //Sort words alphabetically
- ksort ($this->_tags, SORT_STRING);
- break;
- case 'random':
- //Shuffle arrray (random order)
- //Workaround to shuffle array because the "shuffle()" function
- //assigns new keys for the elements in array
- $keys = array_keys ($this->_tags);
- shuffle ($keys);
- $newTags = array ();
- foreach ($keys as $key)
- {
- $newTags[$key] = $this->_tags[$key];
- }
- $this->_tags = $newTags;
- unset ($newTags, $keys);
- break;
- default:
- //Nothing to do, array is already sorted by words count
- break;
- }
- }
- return TRUE;
- }
- /**
- * Build HTML output
- *
- * @param string
- * @return boolean TRUE on success ($output populated), FALSE on error (no tags/words available)
- */
- protected function build_output ()
- {
- if (! is_array ($this->_tags) || empty ($this->_tags))
- {
- //No tags/word, return empty output
- $this->output = '';
- return FALSE;
- }
- else
- {
- //Determine maximum occurrence value
- $maxHits = max ($this->_tags);
- //Determine minimum and maximum occurences
- $minOccurs = min ($this->_tags);
- $maxOccurs = max ($this->_tags);
- //Add module details (please keep this)
- $this->add_module_details ();
- //Add tagclouds box
- $this->output .= '<div class="tagclouds">';
- //Add a title if available
- if (! empty ($this->_cloudsTitle))
- {
- $this->output .= $this->_cloudsTitle;
- }
- //Add the tagclouds paragraph
- $this->output .= '<p>';
- //Process each tag
- foreach ($this->_tags as $word => $count)
- {
- //Calculate font-size for current tag
- $weight = (log ($count) - log ($minOccurs)) / (log ($maxOccurs) - log ($minOccurs));
- $fontSize = intval ($this->_minFontSize + round (($this->_maxFontSize - $this->_minFontSize) * $weight));
- //Calculate style class (usually for CSS colors)
- $styleClass = ceil (((($count - $this->_minCountValue) * 100) / ($maxHits - $this->_minCountValue)) / (100 / $this->_styleclass));
- //Add word to output
- $this->output .= '<a href="' . DOC_ROOT . '/index.php?' . $this->_searchVariable . '=' . $word . '" style="font-size:' . $fontSize . '%;" class="cloud-word cloud-style-' . $styleClass . '" title="' . $word . '">' . $word . '</a> ';
- //Free memory
- unset ($this->_tags[$word], $word, $count, $fontSize, $styleClass);
- }
- //Trim output (last char is a space)
- $this->output = trim ($this->output);
- //Close paragraph and box
- $this->output .= '</p></div>';
- }
- return TRUE;
- }
- /**
- * Build HTML module information output
- *
- * (!! please maintain this section !!)
- */
- public function add_module_details ()
- {
- $this->output = "\n<!--";
- $this->output .= "\n# Project: PHP Link Directory - Link exchange directory @ http://www.phplinkdirectory.com/";
- $this->output .= "\n# Module: phpLD Simple TagCloud";
- $this->output .= "\n# Homepage: http://www.frozenminds.com/phpld-tagclouds.html";
- $this->output .= "\n# Author: Constantin Bejenaru aKa Boby @ http://www.frozenminds.com/";
- $this->output .= "\n# Language: PHP + xHTML + CSS";
- $this->output .= "\n# License: GNU/GPL";
- $this->output .= "\n-->\n";
- }
- }