diff --git a/src/PerrysLambda/ArrayBase.php b/src/PerrysLambda/ArrayBase.php index 089c0b2..46d6a5f 100644 --- a/src/PerrysLambda/ArrayBase.php +++ b/src/PerrysLambda/ArrayBase.php @@ -552,8 +552,8 @@ public function removeKey($field) if($this->exists($field)) { unset($this->__data[$field]); + $this->invalidateKeycache(); } - $this->invalidateKeycache(); return $this; } @@ -612,11 +612,12 @@ abstract public function getIsValidValue($value); /** * filter by condition - * @param callable $where + * @param callable|array $where * @return \PerrysLambda\ArrayList */ - public function where(callable $where) + public function where($where) { + $where = LambdaUtils::toConditionCallable($where); $collection = $this->newInstance(); foreach($this as $record) { @@ -630,12 +631,13 @@ public function where(callable $where) /** * Get first item matching to callable - * @param callable $where + * @param callable|array $where * @return mixed * @throws \OutOfBoundsException */ - public function whereFirst(callable $where) + public function whereFirst($where) { + $where = LambdaUtils::toConditionCallable($where); foreach($this as $record) { if(call_user_func($where, $record)) @@ -648,12 +650,13 @@ public function whereFirst(callable $where) /** * Get first item matching to callable or default - * @param callable $where + * @param callable|array $where * @param mixed $default * @return mixed */ - public function whereFirstOrDefault(callable $where, $default=null) + public function whereFirstOrDefault($where, $default=null) { + $where = LambdaUtils::toConditionCallable($where); foreach($this as $record) { if(call_user_func($where, $record)) @@ -671,7 +674,7 @@ public function whereFirstOrDefault(callable $where, $default=null) */ public function groupBy($group=null) { - $group = LambdaUtils::toCallable($group); + $group = LambdaUtils::toSelectCallable($group); $result = new ObjectArray(array()); if($this instanceof ObjectArray) @@ -703,7 +706,7 @@ public function groupBy($group=null) */ public function distinct($distinct=null) { - $distinct = LambdaUtils::toCallable($distinct); + $distinct = LambdaUtils::toSelectCallable($distinct); $keys = array(); $collection = $this->newInstance(); @@ -759,11 +762,12 @@ public function except(ArrayBase $comparedata) /** * Check for any field by condition - * @param callable $where + * @param callable|array $where * @return bool */ - public function any(callable $where) + public function any($where) { + $where = LambdaUtils::toConditionCallable($where); foreach($this as $record) { if(call_user_func($where, $record)) @@ -776,11 +780,12 @@ public function any(callable $where) /** * Check for all fields by condition - * @param callable $where + * @param callable|array $where * @return bool */ - public function all(callable $where) + public function all($where) { + $where = LambdaUtils::toConditionCallable($where); foreach($this as $record) { if(!call_user_func($where, $record)) @@ -798,7 +803,7 @@ public function all(callable $where) */ public function select($select=null) { - $select = LambdaUtils::toCallable($select); + $select = LambdaUtils::toSelectCallable($select); $result = array(); foreach($this as $key => $record) @@ -815,7 +820,7 @@ public function select($select=null) */ public function selectMany($select=null) { - $select = LambdaUtils::toCallable($select); + $select = LambdaUtils::toSelectCallable($select); $result = array(); foreach($this as $key => $record) @@ -858,7 +863,7 @@ public function each(callable $each) */ public function sum($sum=null) { - $sum = LambdaUtils::toCallable($sum); + $sum = LambdaUtils::toSelectCallable($sum); $temp = $this->select($sum)->toArray(); return array_sum($temp); } @@ -870,7 +875,7 @@ public function sum($sum=null) */ public function min($min=null) { - $min = LambdaUtils::toCallable($min); + $min = LambdaUtils::toSelectCallable($min); $temp = $this->select($min)->toArray(); return min($temp); } @@ -882,7 +887,7 @@ public function min($min=null) */ public function max($max=null) { - $max = LambdaUtils::toCallable($max); + $max = LambdaUtils::toSelectCallable($max); $temp = $this->select($max)->toArray(); return max($temp); } @@ -894,7 +899,7 @@ public function max($max=null) */ public function avg($avg=null) { - $avg = LambdaUtils::toCallable($avg); + $avg = LambdaUtils::toSelectCallable($avg); return ($this->sum($avg)/$this->length()); } @@ -906,7 +911,7 @@ public function avg($avg=null) */ public function joinString($join=null, $glue=", ") { - $join = LambdaUtils::toCallable($join); + $join = LambdaUtils::toSelectCallable($join); $temp = $this->select($join)->toArray(); return implode($glue, $temp); } @@ -1061,7 +1066,7 @@ public function skip($offset) */ public function order($order) { - $order = LambdaUtils::toCallable($order); + $order = LambdaUtils::toSelectCallable($order); return Sortable::startOrder($this, $order); } @@ -1072,7 +1077,7 @@ public function order($order) */ public function orderDesc($order) { - $order = LambdaUtils::toCallable($order); + $order = LambdaUtils::toSelectCallable($order); return Sortable::startOrderDesc($this, $order); } diff --git a/src/PerrysLambda/LambdaUtils.php b/src/PerrysLambda/LambdaUtils.php index c0d71e9..bc279c8 100644 --- a/src/PerrysLambda/LambdaUtils.php +++ b/src/PerrysLambda/LambdaUtils.php @@ -14,7 +14,7 @@ class LambdaUtils * @return callable * @throws \PerrysLambda\Exception\InvalidException */ - public static function toCallable($mixed=null) + public static function toSelectCallable($mixed=null) { // callable if(is_callable($mixed)) @@ -48,5 +48,53 @@ public static function toCallable($mixed=null) throw new InvalidException("Could not convert expression of type ".gettype($mixed)." into a lambda callable"); } + + + /** + * Convert strings, numbers, booleans and arrays into a callable + * @param type $mixed + * @return type + * @throws InvalidException + */ + public static function toConditionCallable($mixed=null) + { + // callable + if(is_callable($mixed)) + { + return $mixed; + } + // is bool + elseif(is_bool($mixed) || is_string($mixed) || is_numeric($mixed)) + { + return function($v) use($mixed) { return $v===$mixed; }; + } + // conditions from array + elseif(is_array($mixed) && count($mixed)>0) + { + return function($v) use($mixed) + { + foreach($mixed as $field => $expression) + { + if(is_callable($expression)) + { + if($expression($v[$field])!==true) + { + return false; + } + } + else + { + if($v[$field]!==$expression) + { + return false; + } + } + } + return true; + }; + } + + throw new InvalidException("Could not convert expression of type ".gettype($mixed)." into a lambda callable"); + } } diff --git a/src/PerrysLambda/Sortable.php b/src/PerrysLambda/Sortable.php index 63e0a5b..5a361a6 100644 --- a/src/PerrysLambda/Sortable.php +++ b/src/PerrysLambda/Sortable.php @@ -20,7 +20,7 @@ class Sortable */ public static function startOrder(ArrayList $list, $order) { - $order = LambdaUtils::toCallable($order); + $order = LambdaUtils::toSelectCallable($order); $temp = new static($list, $order, self::ORDER_ASC); $temp->thenBy($order); return $temp; @@ -34,7 +34,7 @@ public static function startOrder(ArrayList $list, $order) */ public static function startOrderDesc(ArrayList $list, $order) { - $order = LambdaUtils::toCallable($order); + $order = LambdaUtils::toSelectCallable($order); $temp = new static($list, $order, self::ORDER_DESC); $temp->thenByDesc($order); return $temp; @@ -54,7 +54,7 @@ protected function __construct(ArrayList $list) */ public function thenBy($order) { - $order = LambdaUtils::toCallable($order); + $order = LambdaUtils::toSelectCallable($order); $this->orders[] = array("property" => $order, "direction" => self::ORDER_ASC); return $this; } @@ -66,7 +66,7 @@ public function thenBy($order) */ public function thenByDesc($order) { - $order = LambdaUtils::toCallable($order); + $order = LambdaUtils::toSelectCallable($order); $this->orders[] = array("property" => $order, "direction" => self::ORDER_DESC); return $this; } diff --git a/test/ExceptionTest.php b/test/ExceptionTest.php index 2574db0..fbb25d2 100644 --- a/test/ExceptionTest.php +++ b/test/ExceptionTest.php @@ -114,7 +114,7 @@ public function testSkipOutOfBounds() */ public function testCallableBoolean() { - \PerrysLambda\LambdaUtils::toCallable(true); + \PerrysLambda\LambdaUtils::toSelectCallable(true); } /** diff --git a/test/LambdaTest.php b/test/LambdaTest.php index a4da49b..02090bb 100644 --- a/test/LambdaTest.php +++ b/test/LambdaTest.php @@ -185,10 +185,15 @@ public function testLambda() // any / all $this->assertSame(true, $basic->any(function($v) { return $v===1; })); + $this->assertSame(true, $basic->any(1)); $this->assertSame(false, $basic->all(function($v) { return $v===1; })); + $this->assertSame(false, $basic->all(1)); $this->assertSame(true, $all->all(function($v) { return $v===1; })); + $this->assertSame(true, $all->all(1)); $this->assertSame(true, $all->any(function($v) { return $v===1; })); + $this->assertSame(true, $all->any(1)); $this->assertSame(false, $all->any(function($v) { return $v===2; })); + $this->assertSame(false, $all->any(2)); // wherefirst $this->assertSame(5, $basic->whereFirst(function($v) { return $v>4; })); @@ -248,6 +253,11 @@ public function testLambdaByString() ); $list = ArrayList::asObjectArray($testdata); + + $this->assertSame(3, $list->where(array('b'=>'bar'))->first()->a); + $this->assertSame(3, $list->whereFirst(array('b'=>'bar'))->a); + $this->assertSame(3, $list->whereFirstOrDefault(array('b'=>'bar'))->a); + $this->assertSame(null, $list->whereFirstOrDefault(array('b'=>'asdf'))); $this->assertSame(14, $list->sum('a')); $this->assertSame(2, $list->min('a'));