| 
<?php/**
 * Allows to use FP-like features for arrays, strings, SPL iterators and even results
 * returned from callbacks
 *
 * This class adds a lot of syntax sugar to your recordset processing routines or other
 * similar tasks when you don't want to write a loop construct. You will never see the
 * calls of FuncUtility methods in the Frontier's core. It uses call_user_func(),
 * which is slow. But I hope, it's performance will be improved someday though.
 *
 * @author Stanis Shramko <[email protected]>
 */
 class FuncUtility
 {
 
 /**
 * Filters all elements of $set using the $callback
 *
 * @return array
 * @throws InvalidArgumentException
 */
 public static function filter($callback, $set)
 {
 if (!is_callable($callback))
 {
 throw new InvalidArgumentException(
 'The first argument is not callable');
 }
 $values = array();
 if (is_callable($set))
 {
 while ($value = call_user_func($set))
 {
 if (call_user_func($callback, $value))
 {
 $values[] = $value;
 }
 }
 }
 else
 {
 foreach (($set = self::prepareIterable($set)) as $value)
 {
 if (call_user_func($callback, $value))
 $values[] = $value;
 }
 }
 return $values;
 }
 
 /**
 * Applies the $callback to all elements of $set
 *
 * @return void
 * @throws InvalidArgumentException
 */
 public static function each($callback, $set)
 {
 if (!is_callable($callback))
 {
 throw new InvalidArgumentException(
 'The first argument is not callable');
 }
 if (is_callable($set))
 {
 while ($value = call_user_func($set))
 {
 call_user_func($callback, $value);
 }
 }
 else
 {
 foreach (($set = self::prepareIterable($set)) as $value)
 {
 call_user_func($callback, $value);
 }
 }
 }
 
 /**
 * Applies the $callback to all elements of $set
 *
 * @return array
 * @throws InvalidArgumentException
 */
 public static function map($callback, $set)
 {
 if (!is_callable($callback))
 {
 throw new InvalidArgumentException(
 'The first argument is not callable');
 }
 $values = array();
 if (is_callable($set))
 {
 while ($value = call_user_func($set))
 {
 $values[] = call_user_func($callback, $value);
 }
 }
 else
 {
 foreach (($set = self::prepareIterable($set)) as $value)
 {
 $values[] = call_user_func($callback, $value);
 }
 }
 return $values;
 }
 
 /**
 * Reduces the $set using $result
 *
 * @return array
 * @throws InvalidArgumentException
 */
 public static function reduce($callback, $set)
 {
 if (!is_callable($callback))
 {
 throw new InvalidArgumentException(
 'The first argument is not callable');
 }
 if (is_callable($set))
 {
 $result = call_user_func($set);
 while ($value = call_user_func($set))
 {
 $result = call_user_func($callback, $result, $value);
 }
 }
 else
 {
 $first = true;
 foreach (($set = self::prepareIterable($set)) as $value)
 {
 if (!$first)
 {
 $result = call_user_func($callback, $result,
 $value);
 }
 else
 {
 $result = $value;
 $first = false;
 }
 }
 }
 return $result;
 }
 
 /**
 * Prepares "something iterable"
 *
 * @param mixed $set
 * @return mixed array or Iterator
 */
 protected static function prepareIterable($set)
 {
 if (is_array($set) || $set instanceof Iterator)
 {
 return $set;
 }
 if (is_string($set))
 {
 return str_split($set);
 }
 throw new InvalidArgumentException('The second argument is not iterable');
 }
 
 }
 
 |