/** * Filters an array of arrays based on whether or not * @param array $collection A collection of arrays. Any values that are not arrays will be automatically filtered * out. * @param array $property_list An array of properties that must match for the item to be included in the final * list. Comparison is run using ArrayUtility::dotRead Can also be provided as an array of arrays. If passed in * this format, each array is treated as part of an "OR" test i.e. if any individual array would pass the * filter test if submitted on its own, the item is considered valid. * @param string $match_type Any of the available MATCH_TYPE_* constants or null to use default. Affects whether * value comparisons are performed on exact data types. Default is "loose" which does not perform a type check * @param bool $force_key_preservation Keys are preserved for assoc arrays only by default. Set to true to ALWAYS * preserve keys * @return array An array of only the matching items. Keys are preserved for associative arrays only. */ public static function filterWhere(array $collection, array $property_list, $match_type = self::MATCH_TYPE_LOOSE, $force_key_preservation = false) { if (is_null($match_type)) { $match_type = self::MATCH_TYPE_LOOSE; } if (!in_array($match_type, [self::MATCH_TYPE_LOOSE, self::MATCH_TYPE_STRICT, self::MATCH_TYPE_CASE_INSENSITIVE])) { throw new \InvalidArgumentException("'{$match_type}' is not a valid match type. Must be one of loose, strict."); } //Turn property lists in to array $property_lists = !is_array(current($property_list)) ? [$property_list] : $property_list; $property_lists = array_map([ArrayUtility::class, "flatten"], $property_lists); //Determine if keys should be preserved $preserve_keys = $force_key_preservation || ArrayUtility::isAssoc($collection); $result = array_filter($collection, function ($entry) use($property_lists, $match_type) { if (!is_array($entry) || !$entry) { return false; } //test all keys and return false if any of them don't match foreach ($property_lists as $property_list) { $matches = true; foreach ($property_list as $key => $expected_value) { //Ensure every value matches switch ($match_type) { case self::MATCH_TYPE_CASE_INSENSITIVE: if (strtolower(ArrayUtility::dotRead($entry, $key)) != strtolower($expected_value)) { $matches = false; } break; case self::MATCH_TYPE_LOOSE: if (ArrayUtility::dotRead($entry, $key) != $expected_value) { $matches = false; } break; default: if (ArrayUtility::dotRead($entry, $key) !== $expected_value) { $matches = false; } break; } } if ($matches) { return true; } } return false; }); if (!$preserve_keys) { return array_values($result); } return $result; }