<?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 <stanislav.shramko@gmail.com>
*/
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');
}
}
|