Created
October 3, 2016 13:46
-
-
Save ch0c01d/77438ab28b5aae5f2d74d9cace76d06e to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
/** | |
* Underscore.php v1.0 | |
* Copyright (c) 2013 Jonathan Aquino | |
* | |
* This is a fork of Brian Haveri's Underscore.php. I have removed the | |
* object-oriented way of calling the functions, and changed all functions to | |
* static. This eliminates the E_STRICT warnings under PHP >=5.4. | |
* | |
* Underscore.php is licensed under the MIT license | |
* Underscore.php was inspired by and borrowed from Underscore.js | |
* For docs, license, tests, and downloads, see: https://github.com/JonathanAquino/Underscore.php | |
*/ | |
// Underscore.php | |
class __ { | |
// Invoke the iterator on each item in the collection | |
public static function each($collection=null, $iterator=null) { | |
if(is_null($collection)) return null; | |
$collection = (array) self::_collection($collection); | |
if(count($collection) === 0) return null; | |
foreach($collection as $k=>$v) { | |
call_user_func($iterator, $v, $k, $collection); | |
} | |
return null; | |
} | |
// Return an array of values by mapping each item through the iterator | |
// map alias: collect | |
public static function collect($collection=null, $iterator=null) { return self::map($collection, $iterator); } | |
public static function map($collection=null, $iterator=null) { | |
if(is_null($collection)) return array(); | |
$collection = (array) self::_collection($collection); | |
if(count($collection) === 0) array(); | |
$return = array(); | |
foreach($collection as $k=>$v) { | |
$return[] = call_user_func($iterator, $v, $k, $collection); | |
} | |
return $return; | |
} | |
// Reduce a collection to a single value | |
// reduce aliases: foldl, inject | |
public static function foldl($collection=null, $iterator=null, $memo=null) { return self::reduce($collection, $iterator, $memo); } | |
public static function inject($collection=null, $iterator=null, $memo=null) { return self::reduce($collection, $iterator, $memo); } | |
public static function reduce($collection=null, $iterator=null, $memo=null) { | |
if(!is_object($collection) && !is_array($collection)) { | |
if(is_null($memo)) throw new Exception('Invalid object'); | |
else return $memo; | |
} | |
return array_reduce($collection, $iterator, $memo); | |
} | |
// Right-associative version of reduce | |
// reduceRight alias: foldr | |
public static function foldr($collection=null, $iterator=null, $memo=null) { return self::reduceRight($collection, $iterator, $memo); } | |
public static function reduceRight($collection=null, $iterator=null, $memo=null) { | |
if(!is_object($collection) && !is_array($collection)) { | |
if(is_null($memo)) throw new Exception('Invalid object'); | |
else return $memo; | |
} | |
krsort($collection); | |
$__ = new self; | |
return $__->reduce($collection, $iterator, $memo); | |
} | |
// Extract an array of values for a given property | |
public static function pluck($collection=null, $key=null) { | |
$collection = (array) self::_collection($collection); | |
$return = array(); | |
foreach($collection as $item) { | |
foreach($item as $k=>$v) { | |
if($k === $key) $return[] = $v; | |
} | |
} | |
return $return; | |
} | |
// Does the collection contain this value? | |
// includ alias: contains | |
public static function contains($collection=null, $val=null) { return self::includ($collection, $val); } | |
public static function includ($collection=null, $val=null) { | |
$collection = (array) self::_collection($collection); | |
return (array_search($val, $collection, true) !== false); | |
} | |
// Invoke the named function over each item in the collection, optionally passing arguments to the function | |
public static function invoke($collection=null, $function_name=null, $arguments=null) { | |
$args = func_get_args(); | |
$__ = new self; | |
list($collection, $function_name) = $__->first($args, 2); | |
$arguments = $__->rest(func_get_args(), 2); | |
// If passed an array or string, return an array | |
// If passed an object, return an object | |
$is_obj = is_object($collection); | |
$result = (empty($arguments)) ? array_map($function_name, (array) $collection) : array_map($function_name, (array) $collection, $arguments); | |
if($is_obj) $result = (object) $result; | |
return $result; | |
} | |
// Does any values in the collection meet the iterator's truth test? | |
// any alias: some | |
public static function some($collection=null, $iterator=null) { return self::any($collection, $iterator); } | |
public static function any($collection=null, $iterator=null) { | |
$collection = self::_collection($collection); | |
$__ = new self; | |
if(!is_null($iterator)) $collection = $__->map($collection, $iterator); | |
if(count($collection) === 0) return false; | |
return is_int(array_search(true, $collection, false)); | |
} | |
// Do all values in the collection meet the iterator's truth test? | |
// all alias: every | |
public static function every($collection=null, $iterator=null) { return self::all($collection, $iterator); } | |
public static function all($collection=null, $iterator=null) { | |
$collection = self::_collection($collection); | |
$__ = new self; | |
if(!is_null($iterator)) $collection = $__->map($collection, $iterator); | |
$collection = (array) $collection; | |
if(count($collection) === 0) return true; | |
return is_bool(array_search(false, $collection, false)); | |
} | |
// Return an array of values that pass the truth iterator test | |
// filter alias: select | |
public static function select($collection=null, $iterator=null) { return self::filter($collection, $iterator); } | |
public static function filter($collection=null, $iterator=null) { | |
$collection = self::_collection($collection); | |
$return = array(); | |
foreach($collection as $val) { | |
if(call_user_func($iterator, $val)) $return[] = $val; | |
} | |
return $return; | |
} | |
// Return an array where the items failing the truth test are removed | |
public static function reject($collection=null, $iterator=null) { | |
$collection = self::_collection($collection); | |
$return = array(); | |
foreach($collection as $val) { | |
if(!call_user_func($iterator, $val)) $return[] = $val; | |
} | |
return $return; | |
} | |
// Return the value of the first item passing the truth iterator test | |
// find alias: detect | |
public static function detect($collection=null, $iterator=null) { return self::find($collection, $iterator); } | |
public static function find($collection=null, $iterator=null) { | |
$collection = self::_collection($collection); | |
foreach($collection as $val) { | |
if(call_user_func($iterator, $val)) return $val; | |
} | |
return false; | |
} | |
// How many items are in this collection? | |
public static function size($collection=null) { | |
$collection = self::_collection($collection); | |
return count((array) $collection); | |
} | |
// Get the first element of an array. Passing n returns the first n elements. | |
// first alias: head | |
public static function head($collection=null, $n=null) { return self::first($collection, $n); } | |
public static function first($collection=null, $n=null) { | |
$collection = self::_collection($collection); | |
if($n === 0) return array(); | |
if(is_null($n)) return current(array_splice($collection, 0, 1, true)); | |
return array_splice($collection, 0, $n, true); | |
} | |
// Get the rest of the array elements. Passing n returns from that index onward. | |
public static function tail($collection=null, $index=null) { return self::rest($collection, $index); } | |
public static function rest($collection=null, $index=null) { | |
if(is_null($index)) $index = 1; | |
$collection = self::_collection($collection); | |
return array_splice($collection, $index); | |
} | |
// Return everything but the last array element. Passing n excludes the last n elements. | |
public static function initial($collection=null, $n=null) { | |
$collection = (array) self::_collection($collection); | |
if(is_null($n)) $n = 1; | |
$first_index = count($collection) - $n; | |
$__ = new self; | |
return $__->first($collection, $first_index); | |
} | |
// Get the last element from an array. Passing n returns the last n elements. | |
public static function last($collection=null, $n=null) { | |
$collection = self::_collection($collection); | |
if($n === 0) $result = array(); | |
elseif($n === 1 || is_null($n)) $result = array_pop($collection); | |
else { | |
$__ = new self; | |
$result = $__->rest($collection, -$n); | |
} | |
return $result; | |
} | |
// Return a copy of the array with falsy values removed | |
public static function compact($collection=null) { | |
$collection = self::_collection($collection); | |
$__ = new self; | |
return $__->select($collection, function($val) { | |
return (bool) $val; | |
}); | |
} | |
// Flattens a multidimensional array | |
public static function flatten($collection=null, $shallow=null) { | |
$collection = self::_collection($collection); | |
$return = array(); | |
if(count($collection) > 0) { | |
foreach($collection as $item) { | |
if(is_array($item)) { | |
$__ = new self; | |
$return = array_merge($return, ($shallow) ? $item : $__->flatten($item)); | |
} | |
else $return[] = $item; | |
} | |
} | |
return $return; | |
} | |
// Returns a copy of the array with all instances of val removed | |
public static function without($collection=null, $val=null) { | |
$args = func_get_args(); | |
$collection = $args[0]; | |
$collection = self::_collection($collection); | |
$num_args = count($args); | |
if($num_args === 1) return $collection; | |
if(count($collection) === 0) return $collection; | |
$__ = new self; | |
$removes = $__->rest($args); | |
foreach($removes as $remove) { | |
$remove_keys = array_keys($collection, $remove, true); | |
if(count($remove_keys) > 0) { | |
foreach($remove_keys as $key) { | |
unset($collection[$key]); | |
} | |
} | |
} | |
return $collection; | |
} | |
// Return an array of the unique values | |
// uniq alias: unique | |
public static function unique($collection=null, $is_sorted=null, $iterator=null) { return self::uniq($collection, $is_sorted, $iterator); } | |
public static function uniq($collection=null, $is_sorted=null, $iterator=null) { | |
$collection = self::_collection($collection); | |
$return = array(); | |
if(count($collection) === 0) return $return; | |
$calculated = array(); | |
foreach($collection as $item) { | |
$val = (!is_null($iterator)) ? $iterator($item) : $item; | |
if(is_bool(array_search($val, $calculated, true))) { | |
$calculated[] = $val; | |
$return[] = $item; | |
} | |
} | |
return $return; | |
} | |
// Returns an array containing the intersection of all the arrays | |
public static function intersection($array=null) { | |
$arrays = func_get_args(); | |
if(count($arrays) === 1) return $array; | |
$__ = new self; | |
$return = $__->first($arrays); | |
foreach($__->rest($arrays) as $next) { | |
if(!$__->isArray($next)) $next = str_split((string) $next); | |
$return = array_intersect($return, $next); | |
} | |
return array_values($return); | |
} | |
// Merge together multiple arrays | |
public static function union($array=null) { | |
$arrays = func_get_args(); | |
$__ = new self; | |
return $__->flatten(array_values(array_unique(call_user_func_array('array_merge', $arrays), SORT_REGULAR))); | |
} | |
// Get the difference between two arrays | |
public static function difference($array_one=null, $array_two=null) { | |
$arrays = func_get_args(); | |
return array_values(call_user_func_array('array_diff', $arrays)); | |
} | |
// Get the index of the first match | |
public static function indexOf($collection=null, $item=null) { | |
$collection = self::_collection($collection); | |
$key = array_search($item, $collection, true); | |
return (is_bool($key)) ? -1 : $key; | |
} | |
// Get the index of the last match | |
public static function lastIndexOf($collection=null, $item=null) { | |
$collection = self::_collection($collection); | |
krsort($collection); | |
$__ = new self; | |
return $__->indexOf($collection, $item); | |
} | |
// Returns an array of integers from start to stop (exclusive) by step | |
public static function range($stop=null) { | |
$args = func_get_args(); | |
$__ = new self; | |
$args = $__->reject($args, function($val) { | |
return is_null($val); | |
}); | |
$num_args = count($args); | |
switch($num_args) { | |
case 1: | |
list($start, $stop, $step) = array(0, $args[0], 1); | |
break; | |
case 2: | |
list($start, $stop, $step) = array($args[0], $args[1], 1); | |
if($stop < $start) return array(); | |
break; | |
default: | |
list($start, $stop, $step) = array($args[0], $args[1], $args[2]); | |
if($step > 0 && $step > $stop) return array($start); | |
} | |
$results = range($start, $stop, $step); | |
// Switch inclusive to exclusive | |
if($step > 0 && $__->last($results) >= $stop) array_pop($results); | |
elseif($step < 0 && $__->last($results) <= $stop) array_pop($results); | |
return $results; | |
} | |
// Merges arrays | |
public static function zip($array=null) { | |
$arrays = func_get_args(); | |
$num_arrays = count($arrays); | |
if($num_arrays === 1) return $array; | |
$__ = new self; | |
$num_return_arrays = $__->max($__->map($arrays, function($array) { | |
return count($array); | |
})); | |
$return_arrays = $__->range($num_return_arrays); | |
foreach($return_arrays as $k=>$v) { | |
if(!is_array($return_arrays[$k])) $return_arrays[$k] = array(); | |
foreach($arrays as $a=>$array) { | |
$return_arrays[$k][$a] = array_key_exists($k, $array) ? $array[$k] : null; | |
} | |
} | |
return $return_arrays; | |
} | |
// Get the max value in the collection | |
public static function max($collection=null, $iterator=null) { | |
if(is_null($iterator)) return max($collection); | |
$results = array(); | |
foreach($collection as $k=>$item) { | |
$results[$k] = $iterator($item); | |
} | |
arsort($results); | |
$__ = new self; | |
$first_key = $__->first(array_keys($results)); | |
return $collection[$first_key]; | |
} | |
// Get the min value in the collection | |
public static function min($collection=null, $iterator=null) { | |
if(is_null($iterator)) return min($collection); | |
$results = array(); | |
foreach($collection as $k=>$item) { | |
$results[$k] = $iterator($item); | |
} | |
asort($results); | |
$__ = new self; | |
$first_key = $__->first(array_keys($results)); | |
return $collection[$first_key]; | |
} | |
// Sort the collection by return values from the iterator | |
public static function sortBy($collection=null, $iterator=null) { | |
$results = array(); | |
foreach($collection as $k=>$item) { | |
$results[$k] = $iterator($item); | |
} | |
asort($results); | |
foreach($results as $k=>$v) { | |
$results[$k] = $collection[$k]; | |
} | |
return array_values($results); | |
} | |
// Group the collection by return values from the iterator | |
public static function groupBy($collection=null, $iterator=null) { | |
$result = array(); | |
$collection = (array) $collection; | |
foreach($collection as $k=>$v) { | |
$key = (is_callable($iterator)) ? $iterator($v, $k) : $v[$iterator]; | |
if(!array_key_exists($key, $result)) $result[$key] = array(); | |
$result[$key][] = $v; | |
} | |
return $result; | |
} | |
// Returns the index at which the value should be inserted into the sorted collection | |
public static function sortedIndex($collection=null, $value=null, $iterator=null) { | |
$collection = (array) self::_collection($collection); | |
$__ = new self; | |
$calculated_value = (!is_null($iterator)) ? $iterator($value) : $value; | |
while(count($collection) > 1) { | |
$midpoint = floor(count($collection) / 2); | |
$midpoint_values = array_slice($collection, $midpoint, 1); | |
$midpoint_value = $midpoint_values[0]; | |
$midpoint_calculated_value = (!is_null($iterator)) ? $iterator($midpoint_value) : $midpoint_value; | |
$collection = ($calculated_value < $midpoint_calculated_value) ? array_slice($collection, 0, $midpoint, true) : array_slice($collection, $midpoint, null, true); | |
} | |
$keys = array_keys($collection); | |
return current($keys) + 1; | |
} | |
// Shuffle the array | |
public static function shuffle($collection=null) { | |
$collection = (array) self::_collection($collection); | |
shuffle($collection); | |
return $collection; | |
} | |
// Return the collection as an array | |
public static function toArray($collection=null) { | |
return (array) $collection; | |
} | |
// Get the collection's keys | |
public static function keys($collection=null) { | |
if(!is_object($collection) && !is_array($collection)) throw new Exception('Invalid object'); | |
return array_keys((array) $collection); | |
} | |
// Get the collection's values | |
public static function values($collection=null) { | |
return array_values((array) $collection); | |
} | |
// Copy all properties from the source objects into the destination object | |
public static function extend($object=null) { | |
$args = func_get_args(); | |
$num_args = func_num_args(); | |
if($num_args === 1) return $object; | |
$is_object = is_object($object); | |
$array = (array) $object; | |
$__ = new self; | |
$extensions = $__->rest(func_get_args()); | |
foreach($extensions as $extension) { | |
$extension = (array) $extension; | |
$array = array_merge($array, $extension); | |
} | |
return ($is_object) ? (object) $array : $array; | |
} | |
// Returns the object with any missing values filled in using the defaults. | |
public static function defaults($object=null) { | |
$args = func_get_args(); | |
list($object) = $args; | |
$num_args = count($args); | |
if($num_args === 1) return $object; | |
$is_object = is_object($object); | |
$array = (array) $object; | |
$__ = new self; | |
$extensions = $__->rest($args); | |
foreach($extensions as $extension) { | |
$extension = (array) $extension; | |
$array = array_merge($extension, $array); | |
} | |
return ($is_object) ? (object) $array : $array; | |
} | |
// Get the names of functions available to the object | |
// functions alias: methods | |
public static function methods($object=null) { return self::functions($object); } | |
public static function functions($object=null) { | |
return get_class_methods(get_class($object)); | |
} | |
// Returns a shallow copy of the object | |
public static function clon(&$object=null) { | |
$clone = null; | |
if(is_array($object)) $clone = (array) clone (object) $object; | |
elseif(!is_object($object)) $clone = $object; | |
elseif(!$clone) $clone = clone $object; | |
// shallow copy object | |
if(is_object($clone) && count($clone) > 0) { | |
foreach($clone as $k=>$v) { | |
if(is_array($v) || is_object($v)) $clone->$k =& $object->$k; | |
} | |
} | |
// shallow copy array | |
elseif(is_array($clone) && count($clone) > 0) { | |
foreach($clone as $k=>$v) { | |
if(is_array($v) || is_object($v)) $clone[$k] =& $object[$k]; | |
} | |
} | |
return $clone; | |
} | |
// Invokes the interceptor on the object, then returns the object | |
public static function tap($object=null, $interceptor=null) { | |
$interceptor($object); | |
return $object; | |
} | |
// Does the given key exist? | |
public static function has($collection=null, $key=null) { | |
$collection = (array) self::_collection($collection); | |
return array_key_exists($key, $collection); | |
} | |
// Are these items equal? | |
public static function isEqual($a=null, $b=null) { | |
if($a === $b) return true; | |
if(gettype($a) !== gettype($b)) return false; | |
if(is_callable($a) !== is_callable($b)) return false; | |
if($a == $b) return true; | |
// Objects and arrays compared by values | |
if(is_object($a) || is_array($a)) { | |
// Do either implement isEqual()? | |
if(is_object($a) && isset($a->isEqual)) return $a->isEqual($b); | |
if(is_object($b) && isset($b->isEqual)) return $b->isEqual($a); | |
if(is_array($a) && array_key_exists('isEqual', $a)) return $a['isEqual']($b); | |
if(is_array($b) && array_key_exists('isEqual', $b)) return $b['isEqual']($a); | |
if(count($a) !== count($b)) return false; | |
$__ = new self; | |
$keys_equal = $__->isEqual($__->keys($a), $__->keys($b)); | |
$values_equal = $__->isEqual($__->values($a), $__->values($b)); | |
return $keys_equal && $values_equal; | |
} | |
return false; | |
} | |
// Is this item empty? | |
public static function isEmpty($item=null) { | |
return is_array($item) || is_object($item) ? !((bool) count((array) $item)) : (!(bool) $item); | |
} | |
// Is this item an object? | |
public static function isObject($item=null) { | |
return is_object($item); | |
} | |
// Is this item an array? | |
public static function isArray($item=null) { | |
return is_array($item); | |
} | |
// Is this item a string? | |
public static function isString($item=null) { | |
return is_string($item); | |
} | |
// Is this item a number? | |
public static function isNumber($item=null) { | |
return (is_int($item) || is_float($item) && !is_nan($item) && !is_infinite($item)); | |
} | |
// Is this item a bool? | |
public static function isBoolean($item=null) { | |
return is_bool($item); | |
} | |
// Is this item a function (by type, not by name)? | |
public static function isFunction($item=null) { | |
return is_object($item) && is_callable($item); | |
} | |
// Is this item an instance of DateTime? | |
public static function isDate($item=null) { | |
return is_object($item) && get_class($item) === 'DateTime'; | |
} | |
// Is this item a NaN value? | |
public static function isNaN($item=null) { | |
return is_nan($item); | |
} | |
// Returns the same value passed as the argument | |
public static function identity() { | |
$args = func_get_args(); | |
if(count($args) > 0) return $args[0]; | |
return function($x) { | |
return $x; | |
}; | |
} | |
// Generate a globally unique id, optionally prefixed | |
public static $_uniqueId = -1; | |
public static function uniqueId($prefix=null) { | |
self::$_uniqueId++; | |
return (is_null($prefix)) ? self::$_uniqueId : $prefix . self::$_uniqueId; | |
} | |
// Invokes the iterator n times | |
public static function times($n=null, $iterator=null) { | |
if(is_null($n)) $n = 0; | |
for($i=0; $i<$n; $i++) $iterator($i); | |
return null; | |
} | |
// Temporary PHP open and close tags used within templates | |
// Allows for normal processing of templates even when | |
// the developer uses PHP open or close tags for interpolation or evaluation | |
const TEMPLATE_OPEN_TAG = '760e7dab2836853c63805033e514668301fa9c47'; | |
const TEMPLATE_CLOSE_TAG= 'd228a8fa36bd7db108b01eddfb03a30899987a2b'; | |
const TEMPLATE_DEFAULT_EVALUATE = '/<%([\s\S]+?)%>/'; | |
const TEMPLATE_DEFAULT_INTERPOLATE= '/<%=([\s\S]+?)%>/'; | |
const TEMPLATE_DEFAULT_ESCAPE = '/<%-([\s\S]+?)%>/'; | |
public static $_template_settings = array( | |
'evaluate' => self::TEMPLATE_DEFAULT_EVALUATE, | |
'interpolate' => self::TEMPLATE_DEFAULT_INTERPOLATE, | |
'escape' => self::TEMPLATE_DEFAULT_ESCAPE | |
); | |
// Set template settings | |
public static function templateSettings($settings=null) { | |
$_template_settings =& self::$_template_settings; | |
if(is_null($settings)) { | |
$_template_settings = array( | |
'evaluate' => self::TEMPLATE_DEFAULT_EVALUATE, | |
'interpolate' => self::TEMPLATE_DEFAULT_INTERPOLATE, | |
'escape' => self::TEMPLATE_DEFAULT_ESCAPE | |
); | |
return true; | |
} | |
foreach($settings as $k=>$v) { | |
if(!array_key_exists($k, $_template_settings)) continue; | |
$_template_settings[$k] = $v; | |
} | |
return true; | |
} | |
// Compile templates into functions that can be evaluated for rendering | |
public static function template($code=null, $context=null) { | |
$class_name = __CLASS__; | |
$return = function($context=null) use ($code, $class_name) { | |
$ts = $class_name::$_template_settings; | |
// Wrap escaped, interpolated, and evaluated blocks inside PHP tags | |
extract((array) $context); | |
preg_match_all($ts['escape'], $code, $vars, PREG_SET_ORDER); | |
if(count($vars) > 0) { | |
foreach($vars as $var) { | |
$echo = $class_name::TEMPLATE_OPEN_TAG . ' echo htmlentities(' . trim($var[1]) . '); ' . $class_name::TEMPLATE_CLOSE_TAG; | |
$code = str_replace($var[0], $echo, $code); | |
} | |
} | |
preg_match_all($ts['interpolate'], $code, $vars, PREG_SET_ORDER); | |
if(count($vars) > 0) { | |
foreach($vars as $var) { | |
$echo = $class_name::TEMPLATE_OPEN_TAG . ' echo ' . trim($var[1]) . '; ' . $class_name::TEMPLATE_CLOSE_TAG; | |
$code = str_replace($var[0], $echo, $code); | |
} | |
} | |
preg_match_all($ts['evaluate'], $code, $vars, PREG_SET_ORDER); | |
if(count($vars) > 0) { | |
foreach($vars as $var) { | |
$echo = $class_name::TEMPLATE_OPEN_TAG . trim($var[1]) . $class_name::TEMPLATE_CLOSE_TAG; | |
$code = str_replace($var[0], $echo, $code); | |
} | |
} | |
$code = str_replace($class_name::TEMPLATE_OPEN_TAG, '<?php ', $code); | |
$code = str_replace($class_name::TEMPLATE_CLOSE_TAG, '?>', $code); | |
// Use the output buffer to grab the return value | |
$code = 'ob_start(); extract($context); ?>' . $code . '<?php return ob_get_clean();'; | |
$func = create_function('$context', $code); | |
return $func((array) $context); | |
}; | |
// Return function or call function depending on context | |
return ((isset($this) && isset($this->_wrapped) && $this->_wrapped) || !is_null($context) ? $return($context) : $return); | |
} | |
// Escape | |
public static function escape($item=null) { | |
return htmlentities($item); | |
} | |
// Memoizes a function by caching the computed result. | |
public static $_memoized = array(); | |
public static function memoize($function=null, $hashFunction=null) { | |
$class_name = __CLASS__; | |
return function() use ($function, $class_name, $hashFunction) { | |
// Generate a key based on hashFunction | |
$args = func_get_args(); | |
if(is_null($hashFunction)) $hashFunction = function($function, $args) { | |
// Try using var_export to identify the function | |
return md5(join('_', array( | |
var_export($function, true), | |
var_export($args, true) | |
))); | |
}; | |
$key = $hashFunction($function, $args); | |
if(!array_key_exists($key, $class_name::$_memoized)) { | |
$class_name::$_memoized[$key] = call_user_func_array($function, $args); | |
} | |
return $class_name::$_memoized[$key]; | |
}; | |
} | |
// Throttles a function so that it can only be called once every wait milliseconds | |
public static $_throttled = array(); | |
public static function throttle($function=null, $wait=null) { | |
$class_name = __CLASS__; | |
return function() use ($function, $wait, $class_name) { | |
// Try using var_export to identify the function | |
$key = md5(join('', array( | |
var_export($function, true), | |
$wait | |
))); | |
$microtime = microtime(true); | |
$ready_to_call = (!array_key_exists($key, $class_name::$_throttled) || $microtime >= $class_name::$_throttled[$key]); | |
if($ready_to_call) { | |
$next_callable_time = $microtime + ($wait / 1000); | |
$class_name::$_throttled[$key] = $next_callable_time; | |
return call_user_func_array($function, func_get_args()); | |
} | |
}; | |
} | |
// Creates a version of the function that can only be called once | |
public static $_onced = array(); | |
public static function once($function=null) { | |
$class_name = __CLASS__; | |
return function() use ($function, $class_name) { | |
// Try using var_export to identify the function | |
$key = md5(var_export($function, true)); | |
if(!array_key_exists($key, $class_name::$_onced)) { | |
$class_name::$_onced[$key] = call_user_func_array($function, func_get_args()); | |
} | |
return $class_name::$_onced[$key]; | |
}; | |
} | |
// Wraps the function inside the wrapper function, passing it as the first argument | |
public static function wrap($function=null, $wrapper=null) { | |
return function() use ($wrapper, $function) { | |
$args = array_merge(array($function), func_get_args()); | |
return call_user_func_array($wrapper, $args); | |
}; | |
} | |
// Returns the composition of the functions | |
public static function compose() { | |
$functions = func_get_args(); | |
return function() use ($functions) { | |
$args = func_get_args(); | |
foreach($functions as $function) { | |
$args[0] = call_user_func_array($function, $args); | |
} | |
return $args[0]; | |
}; | |
} | |
// Creates a version of the function that will only run after being called count times | |
public static $_aftered = array(); | |
public static function after($count=null, $function=null) { | |
$class_name = __CLASS__; | |
$key = md5(mt_rand()); | |
$func = function() use ($function, $class_name, $count, $key) { | |
if(!array_key_exists($key, $class_name::$_aftered)) $class_name::$_aftered[$key] = 0; | |
$class_name::$_aftered[$key] += 1; | |
if($class_name::$_aftered[$key] >= $count) return call_user_func_array($function, func_get_args()); | |
}; | |
return ($count) ? $func : $func(); | |
} | |
// Get a collection in a way that supports strings | |
private static function _collection($collection) { | |
return (!is_array($collection) && !is_object($collection)) ? str_split((string) $collection) : $collection; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment