Location: PHPKode > projects > Open Power Template > lib/Opt/Function.php
<?php
/*
 *  OPEN POWER LIBS <http://www.invenzzia.org>
 *
 * This file is subject to the new BSD license that is bundled
 * with this package in the file LICENSE. It is also available through
 * WWW at this URL: <http://www.invenzzia.org/license/new-bsd>
 *
 * Copyright (c) Invenzzia Group <http://www.invenzzia.org>
 * and other contributors. See website for details.
 *
 */

	/**
	 * A generic container for the template functions created for
	 * the autoloader purporses only.
	 */
	class Opt_Function
	{
		/**
		 * The cycle iterator for cycle() function.
		 * @static
		 * @var int
		 */
		static private $_cycleIterator = 0;

		/**
		 * The method allows to create aggregate functions that operate
		 * on container. It calls the specified function for all the
		 * container elements provided in the first function call
		 * argument.
		 *
		 * @static
		 * @param Callback $callback A valid function callback
		 * @param Array $args The list of function arguments.
		 * @return Container Processed container
		 */
		static public function processContainer($callback, $args)
		{			
			$result = array();
			foreach($args[0] as $idx => $value)
			{
				$args[0] = $value;
				$result[$idx] = call_user_func_array($callback, $args);
			}
			
			return $result;
		} // end processContainer();

		/**
		 * Returns true, if the specified value is a valid OPT container.
		 *
		 * @static
		 * @param Mixed $value The value to test.
		 * @return Boolean True, if the value is really a container
		 */
		static public function isContainer($value)
		{
			return is_array($value) || (is_object($value) && ($value instanceof Iterator || $value instanceof IteratorAggregate));
		} // end isContainer();

		/**
		 * Returns the first non-empty argument.
		 *
		 * @static
		 * @param mixed ... The arguments.
		 * @return mixed The first non-empty argument
		 */
		static public function firstof()
		{
			$args = func_get_args();
			$cnt = sizeof($args);
			for($i = 0; $i < $cnt; $i++)
			{
				if(!empty($args[$i]))
				{
					return $args[$i];
				}
			}
		} // end firstof();

		/**
		 * Returns true, if the container contains the specified value.
		 *
		 * @static
		 * @param string $item The container
		 * @param mixed $value The value
		 * @return True, if the value exists in the container.
		 */
		static public function contains($item, $value)
		{
			if(is_array($item))
			{
				return in_array($value, $item);
			}
			elseif($item instanceof ArrayAccess && $item instanceof Traversable)
			{
				foreach($item as $r)
				{
					if($r === $value)
					{
						return true;
					}
				}
			}
			return false;
		} // end contains();

		/**
		 * Returns true, if the container contains the specified key.
		 *
		 * @static
		 * @param string $item The container
		 * @param mixed $key The key
		 * @return True, if the key exists in the container.
		 */
		static public function containsKey($item, $key)
		{
			if(is_array($item) || $item instanceof ArrayAccess)
			{
				return isset($item[$key]);
			}
			return false;
		} // end containsKey();

		/**
		 * Puts the specified string $delim between every two characters of $string.
		 * By default, it puts spaces between the $string characters.
		 *
		 * @static
		 * @param String|Container $string The string to be processed.
		 * @param String $delim = ' ' Character delimiter.
		 * @return String|Container The modified text.
		 */
		static public function spacify($string, $delim = ' ')
		{
			if(self::isContainer($string))
			{
				return self::processContainer(array('Opt_Function', 'spacify'), array($string, $delim));
			}
		
			$ns = '';
			$len = strlen($string);
			$tpl = Opl_Registry::get('opt');

			for($i = 0; $i < $len; $i++)
			{
				if($tpl->charset == 'utf-8' && ord($string[$i]) > 127)
				{
					break;
				}
				$ns .= $string[$i];
				if($i + 1 < $len)
				{
					$ns .= $delim;
				}
			}
			return $ns;
		} // end spacify();

		/**
		 * Makes an indentation to the specified string.
		 *
		 * @static
		 * @param String|Container $string The source string or the container
		 * @param Int $num The length of the indentation
		 * @param String $with = ' ' The indent character
		 * @return String|Container The modified string
		 */
		static public function indent($string, $num, $with = ' ')
		{
			if(self::isContainer($string))
			{
				return self::processContainer(array('Opt_Function', 'indent'), array($string, $num, $with));
			}
		
			return preg_replace('/([\\r\\n]{1,2})/', '$1'.str_repeat($with, $num), $string);
		} // end indent();

		/**
		 * Strips the groups of white characters in $string into a single space.
		 *
		 * @static
		 * @param String|Container $string The source string or the container.
		 * @return String|Container The modified string.
		 */
		static public function strip($string)
		{
			if(self::isContainer($string))
			{
				return self::processContainer(array('Opt_Function', 'strip'), array($string));
			}

			return trim(preg_replace('/\s+/', ' ', $string));
		} // end strip();

		/**
		 * Pads the string or a container.
		 *
		 * @static
		 * @param string|container $string The string to pad.
		 * @param int $length The pad length
		 * @param string $padString The string used for padding.
		 * @param string $type The padding type.
		 * @return string|container The modified string.
		 */
		static public function pad($string, $length, $padString = ' ', $type = 'right')
		{
			if(!is_scalar($padString))
			{
				$padString = ' ';
			}
			switch((string)$type)
			{
				case 'left':
					$type = STR_PAD_LEFT;
					break;
				case 'both':
					$type = STR_PAD_BOTH;
					break;
				default:
					$type = STR_PAD_RIGHT;
			}
			if(self::isContainer($string))
			{
				$list = array();
				foreach($string as $idx => $str)
				{
					if(is_scalar($str))
					{
						$list[$idx] = str_pad((string)$str, (int)$length, (string)$padString, $type);
					}
				}
				return $list;
			}

			return str_pad((string)$string, (int)$length, (string)$padString, $type);
		} // end pad();

		/**
		 * Counts the occurences of substring in another string.
		 *
		 * @static
		 * @param String|Container $string The source string or the container.
		 * @param string $searched The searched string
		 * @return String|Container The modified string.
		 */
		static public function countSubstring($string, $searched)
		{
			if(self::isContainer($string))
			{
				$i = 0;
				foreach($string as $item)
				{
					if(is_string($item))
					{
						$i += substr_count($item, $searched);
					}
				}
				return $i;
			}

			return substr_count($string, $searched);
		} // end countSubstring();

		/**
		 * Truncates the string or the container of strings to the specified length.
		 * If the string was really shortened, appends the $etc to the end of it.
		 * By default, the function can truncate a string in the middle of a word.
		 * If you want to round the truncation to the whole words, change the default
		 * value of the last argument to false.
		 *
		 * @static
		 * @param String|Container $string The source string or the container of strings.
		 * @param Int $length Truncate to the specified length.
		 * @param String $etc = '' The extra string appended to the result, if it was really truncated.
		 * @param Boolean $break = true Do we allow to break the words?
		 * @return String|Container The modified string.
		 */
		static public function truncate($string, $length, $etc = '', $break = true)
		{
			if(self::isContainer($string))
			{
				return self::processContainer(array('Opt_Function', 'truncate'), array($string, $length, $etc, $break));
			}

			if($length == 0)
			{
				return '';
			}
			$strlen = strlen($string);
			if($strlen > $length)
			{
				if(!$break)
				{
					$string = preg_replace('/\s+?(\S+)?$/', '', substr($string, 0, $length));
				}
				return substr($string, 0, $length).$etc;
			}
			return $string;
		} // end truncate();

		/**
		 * Tries to break the string every specified number of characters.
		 *
		 * @param String $string The input string
		 * @param Integer $width The width of a line
		 * @param String $break The break string
		 * @param Boolean $cut Whether to cut too long words
		 * @return String
		 */
		static public function wordwrap($string, $width, $break = '<br />', $cut = null)
		{
			if(!is_null($break))
			{
				$break = str_replace(array('\\n', '\\r', '\\t', '\\\\'), array("\n", "\r", "\t", '\\'), $break);
			}
			return wordwrap($string, $width, $break, $cut);
		} // end wordwrap();

		/**
		 * Formats the input number to be a valid money amount string. The function is not available on
		 * systems without strfmon capabilities (i.e. Microsoft Windows).
		 *
		 * @param Number $number The input number
		 * @param String $format The format (if not specified, using locale settings)
		 * @return String
		 */
		static public function money($number, $format = null)
		{
			if(self::isContainer($number))
			{
				return self::processContainer(array('Opt_Function', 'money'), array($number, $format));
			}
			$opt = Opl_Registry::get('opt');
			$format = (is_null($format) ? $opt->moneyFormat : $format);
			return money_format($format, $number);
		} // end money();

		/**
		 * Formats the input number to look nice in the text. If the extra arguments
		 * are not present, they are taken from OPT configuration.
		 *
		 * @param Number $number The input number
		 * @param Integer $d1 The number of decimals
		 * @param String $d2 The decimal separator
		 * @param String $d3 The thousand separator
		 * @return String
		 */
		static public function number($number, $d1 = null, $d2 = null, $d3 = null)
		{
			if(self::isContainer($number))
			{
				return self::processContainer(array('Opt_Function', 'number'), array($number, $d1, $d2, $d3));
			}
			$opt = Opl_Registry::get('opt');
			$d1 = ($d1 === null ? $opt->numberDecimals : $d1);
			$d2 = ($d2 === null ? $opt->numberDecPoint : $d2);
			$d3 = ($d3 === null ? $opt->numberThousandSep : $d3);
			return number_format($number, $d1, $d2, $d3);
		} // end number();

		/**
		 * Returns the absolute value of a number.
		 *
		 * @param Number|Container $items The input number of container of numbers
		 * @return Number|Container
		 */
		static public function absolute($items)
		{
			if(self::isContainer($items))
			{
				return self::processContainer('abs', array($items));
			}
			
			return abs($items);
		} // end absolute();

		/**
		 * Sums all the numbers in the specified container.
		 *
		 * @param Container $items The container of numbers.
		 * @return Number
		 */
		static public function sum($items)
		{
			if(self::isContainer($items))
			{				
				$sum = 0;
				foreach($items as $item)
				{
					if(!self::isContainer($item))
					{
						$sum += $item;
					}
				}
				return $sum;
			}
			return null;
		} // end sum();

		/**
		 * Returns the average value of the numbers in a container.
		 *
		 * @param Container $items The container of numbers
		 * @return Number
		 */
		static public function average($items)
		{
			if(self::isContainer($items))
			{				
				$sum = 0;
				$cnt = 0;
				foreach($items as $item)
				{
					if(!self::isContainer($item) && !is_null($item))
					{
						$sum += $item;
						$cnt++;
					}
				}
				if($cnt > 0)
				{
					return $sum / $cnt;
				}
			}
			return null;
		} // end average();

		/**
		 * Returns the standard deviation of the numbers in a container.
		 *
		 * @param Container $items The container of numbers.
		 * @return Number
		 */
		static public function stddev($items)
		{
			$average = self::average($items);
			
			if(is_null($average))
			{
				return null;
			}
			
			$sum = 0;
			$cnt = 0;
			foreach($items as $item)
			{
				if(!self::isContainer($item) && !is_null($item))
				{
					$sum += pow($item - $average, 2);
					$cnt++;
				}
			}
			return sqrt(($sum / ($cnt - 1)));
		} // end stddev();

		/**
		 * Replaces the lowercase characters in $item with the uppercase.
		 *
		 * @static
		 * @param String|Container $item The string or the container.
		 * @return String|Container The modified string
		 */
		static public function upper($item)
		{
			if(self::isContainer($item))
			{
				return self::processContainer(array('Opt_Function', 'upper'), array($item));
			}
			
			return strtoupper($item);
		} // end upper();

		/**
		 * Replaces the uppercase characters in $item with the lowercase.
		 *
		 * @static
		 * @param String|Container $item The string or the container.
		 * @return String|Container The modified string
		 */
		static public function lower($item)
		{
			if(self::isContainer($item))
			{
				return self::processContainer(array('Opt_Function', 'lower'), array($item));
			}
			
			return strtolower($item);
		} // end lower();

		/**
		 * Capitalizes the first character of $item.
		 *
		 * @static
		 * @param String|Container $item The string or the container.
		 * @return String|Container The modified string
		 */
		static public function capitalize($item)
		{
			if(self::isContainer($item))
			{
				return self::processContainer(array('Opt_Function', 'capitalize'), array($item));
			}
			
			return ucfirst($item);
		} // end capitalize();

		/**
		 * Changes the newline characters to the BR tag.
		 *
		 * @static
		 * @param String|Container $item The string or the container.
		 * @return String|Container The modified string
		 */
		static public function nl2br($item)
		{
			if(self::isContainer($item))
			{
				return self::processContainer(array('Opt_Function', 'nl2br'), array($item));
			}
			
			return nl2br($item);
		} // end nl2br();

		/**
		 * Removes the HTML tags from $item.
		 *
		 * @static
		 * @param String|Container $item The string or the container.
		 * @param String $what The list of allowable tags that must not be removed.
		 * @return String|Container The modified string
		 */
		static public function stripTags($item, $what = '')
		{
			if(self::isContainer($item))
			{
				return self::processContainer(array('Opt_Function', 'stripTags'), array($item, $what));
			}
			
			return strip_tags($item, $what);
		} // end stripTags();

		/**
		 * Helps displaying a nice range between two numbers, if they are
		 * not equal, i.e.: "5 - 10" or the number itself, if they are
		 * equal. By default, the second number is evaluated as the current
		 * year, which allows to create a range of years for the Copyright foot
		 * at the bottom of the website.
		 *
		 * @static
		 * @param Int $number1 Starting number
		 * @param Int $number2=null Ending number
		 * @return String The result string
		 */
		static public function range($number1, $number2 = null)
		{
			if($number2 === null)
			{
				$number2 = date('Y');
			}
			if($number2 == $number1)
			{
				return $number1;
			}
			return $number1.' - '.$number2;			
		} // end range();

		/**
		 * Returns true, if the specified string is a valid URL.
		 *
		 * @static
		 * @param String $address The string to test.
		 * @return Boolean True, if the specified string is a valid URL.
		 */
		static public function isUrl($address)
		{
			return filter_var($address, FILTER_VALIDATE_URL) !== false;
		} // end isUrl();

		/**
		 * Returns true, if the specified URL or file path points to the
		 * image file. The recognition bases on the file extension and
		 * currently recognizes JPG, PNG, GIF, SVG and BMP.
		 *
		 * @static
		 * @param String $address The URL or filesystem path to test.
		 * @return Boolean True, if the specified address points to an image.
		 */
		static public function isImage($address)
		{
			$result = @parse_url($address);
			if(is_array($result))
			{
				if(isset($result['path']))
				{
					// Try to obtain the file extension
					if(($id = strrpos($result['path'], '.')) !== false)
					{
						if(in_array(substr($result['path'], $id+1, 3), array('jpg', 'png', 'gif', 'svg', 'bmp')) || in_array(substr($result['path'], $id+1, 4), array('jpeg')))
						{
							return true;
						}
					}
				}
			}
			return false;
		} // end isImage();

		/**
		 * Returns the next element of the specified list of items.
		 *
		 * @return Mixed
		 */
		static public function cycle()
		{
			$items = func_get_args();
			if(is_array($items[0]))
			{
				$items = $items[0];
			}

			return ($items[(self::$_cycleIterator++) % sizeof($items) ]);
		} // end cycle();

		/**
		 * Creates an entity for the specified string. If used with the 'u:' modifier,
		 * it allows to display the entities in the output document.
		 *
		 * @static
		 * @param String $name A valid entity name.
		 * @return String
		 */
		static public function entity($name)
		{
			if(!preg_match('/^(([a-zA-Z\_\:]{1}[a-zA-Z0-9\_\:\-\.]*)|(\#((x[a-fA-F0-9]+)|([0-9]+))))$/', $name))
			{
				throw new Opt_InvalidEntityName_Exception($name);
			}
			return '&'.$name.';';
		} // end entity();

		/**
		 * Attempts to generate a plural form of the specified string according
		 * to the language rules and the specified number.
		 *
		 * @static
		 * @throws Opt_Pluralize_Exception
		 * @param int $number The number to determine the plural form.
		 * @param string $singularForm The base singular form.
		 * @param string ... The plural forms (if we do not use the translation interface)
		 * @return string The grammar form for the specified number
		 */
		static public function pluralize($number, $singularForm)
		{
			$args = func_get_args();
			$opt = Opl_Registry::get('opt');
			if(sizeof($args) == 0)
			{
				// Use the translation interface.
				
				$tf = $opt->getTranslationInterface();

				if($tf === null || !method_exists($tf, 'pluralize'))
				{
					throw new Opt_Pluralize_Exception('the translation interface does not support pluralization.');
				}

				return $tf->pluralize($number, $singularForm);
			}
			else
			{
				// Translate on the fly.

				$argument = null;
				if(is_object($opt->pluralForms) && is_callable($opt->pluralForms))
				{
					$closure = $opt->pluralForms;
					$argument = $closure($number);
				}
				else
				{
					$last = sizeof($args) - 1;
					$i = 0;
					$arg = null;
					foreach($opt->pluralForms as $expression => $argument)
					{
						$arg = $argument;
						if($i != $last)
						{
							eval('$__result = ('.str_replace('%d', $number, $expression).');');
							if($__result === true)
							{
								break;
							}
						}
					}
				}
				if(!isset($args[$argument+1]))
				{
					throw new Opt_Pluralize_Exception('unknown grammar form number: '.$argument.'.');
				}
				return $args[$argument+1];
			}
		} // end pluralize();

		/**
		 * Turns URL-s into clickable links.
		 *
		 * @static
		 * @param string $text The text to parse.
		 * @param string $class The optional CSS class.
		 * @param string $target The target.
		 * @return string The parsed text.
		 */
		static public function autoLink($text, $class = null, $target = '_blank')
		{
			$extra = '';
			if($class !== null)
			{
				$extra .= ' class="'.(string)htmlspecialchars($class).'"';
			}
			if($target !== null)
			{
				$extra .= ' target="'.(string)htmlspecialchars($target).'"';
			}
			return str_replace(array('<a href="www.', '<a href="ftp.'),
				array('<a href="http://www.', '<a href="ftp://ftp.'),
				preg_replace('/(((http|https|ftp|ftps|gopher)\:\/\/)|(www\.)|(ftp\.))([a-zA-Z0-9\_\-]+\@)?(([0-9a-fA-F\:]{6,39})|(([a-zA-Z0-9\-\_]+\.)*[a-zA-Z0-9\-\_]+(\:[0-9]{1,5})?)|(\[[0-9a-fA-F\:]{6,39}\]\:[0-9]{1,5}))(\/[a-zA-Z0-9\_\-\&\;\?\/\.\=\+\#]*)?/is',
				'<a href="$0"'.$extra.'>$0</a>', htmlspecialchars($text)));
		} // end autoLink();

		/**
		 * Builds XML attributes from an array. The function allows to specify the
		 * ignore list in either text- or array format.
		 *
		 * @param Array $attributes The list of attributes.
		 * @param Mixed $ignoreList The list of ignored items.
		 * @param String $prepend The string prepended to the attribute list.
		 */
		static public function buildAttributes($attributes, $ignoreList = array(), $prepend = '')
		{
			if(is_string($ignoreList))
			{
				$ignoreList = explode(',', $ignoreList);
				array_walk($ignoreList, 'trim');
			}

			foreach($attributes as $name => $value)
			{
				if(!in_array($name, $ignoreList))
				{
					// Do not accept null values.
					if($value === null)
					{
						continue;
					}
					// If the name is correct...
					if(preg_match('/^([a-zA-Z0-9\.\_\-]+\:)?([a-zA-Z0-9\.\_\-]+)$/', $name))
					{
						$prepend .= ''.$name.'="'.htmlspecialchars($value).'" ';
					}
				}
			}
			return rtrim($prepend);
		} // end buildAttributes();
	} // end Opt_Function;
Return current item: Open Power Template