Commit 907bca22 by mushishixian

安装数组搜索包

parent ee659885
...@@ -9,13 +9,14 @@ ...@@ -9,13 +9,14 @@
"license": "MIT", "license": "MIT",
"require": { "require": {
"php": "^7.2.5|^8.0", "php": "^7.2.5|^8.0",
"ext-json": "*",
"fideloper/proxy": "^4.4", "fideloper/proxy": "^4.4",
"fruitcake/laravel-cors": "^2.0", "fruitcake/laravel-cors": "^2.0",
"guzzlehttp/guzzle": "^6.3.1|^7.0.1", "guzzlehttp/guzzle": "^6.3.1|^7.0.1",
"laravel/framework": "^7.29", "laravel/framework": "^7.29",
"laravel/tinker": "^2.5", "laravel/tinker": "^2.5",
"laravel/ui": "2.*", "laravel/ui": "2.*",
"ext-json": "*" "loilo/fuse": "^3.6"
}, },
"require-dev": { "require-dev": {
"facade/ignition": "^2.0", "facade/ignition": "^2.0",
......
...@@ -4,7 +4,7 @@ ...@@ -4,7 +4,7 @@
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
"This file is @generated automatically" "This file is @generated automatically"
], ],
"content-hash": "e779bf3771ba1e840253b4dd58e565f6", "content-hash": "06606c565321db2d0262ec1f551221d5",
"packages": [ "packages": [
{ {
"name": "asm89/stack-cors", "name": "asm89/stack-cors",
...@@ -1509,6 +1509,65 @@ ...@@ -1509,6 +1509,65 @@
"time": "2022-04-17T13:12:02+00:00" "time": "2022-04-17T13:12:02+00:00"
}, },
{ {
"name": "loilo/fuse",
"version": "3.6.1",
"source": {
"type": "git",
"url": "https://github.com/loilo/Fuse.git",
"reference": "ead0f50addaee3d9bbed3aae1f0b8ed22b0f573f"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/loilo/Fuse/zipball/ead0f50addaee3d9bbed3aae1f0b8ed22b0f573f",
"reference": "ead0f50addaee3d9bbed3aae1f0b8ed22b0f573f",
"shasum": "",
"mirrors": [
{
"url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%",
"preferred": true
}
]
},
"require": {
"php": "^5.6 || ^7.0"
},
"require-dev": {
"phpunit/phpunit": "^5.0 || ^6.0 || ^7.0"
},
"type": "library",
"autoload": {
"files": [
"src/Bitap/matched_indices.php",
"src/Bitap/pattern_alphabet.php",
"src/Bitap/regex_search.php",
"src/Bitap/score.php",
"src/Bitap/search.php",
"src/Helpers/deep_value.php",
"src/Helpers/get.php",
"src/Helpers/is_list.php"
],
"psr-4": {
"Fuse\\": "src/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"Apache-2.0"
],
"authors": [
{
"name": "Florian Reuschel",
"email": "florian@loilo.de"
}
],
"description": "Fuzzy search for PHP based on Bitap algorithm",
"support": {
"issues": "https://github.com/loilo/Fuse/issues",
"source": "https://github.com/loilo/Fuse/tree/v3.6.1"
},
"time": "2020-03-10T10:18:12+00:00"
},
{
"name": "monolog/monolog", "name": "monolog/monolog",
"version": "2.8.0", "version": "2.8.0",
"source": { "source": {
...@@ -7473,7 +7532,8 @@ ...@@ -7473,7 +7532,8 @@
"prefer-stable": true, "prefer-stable": true,
"prefer-lowest": false, "prefer-lowest": false,
"platform": { "platform": {
"php": "^7.2.5|^8.0" "php": "^7.2.5|^8.0",
"ext-json": "*"
}, },
"platform-dev": [], "platform-dev": [],
"plugin-api-version": "2.1.0" "plugin-api-version": "2.1.0"
......
...@@ -24,21 +24,8 @@ use Composer\Semver\VersionParser; ...@@ -24,21 +24,8 @@ use Composer\Semver\VersionParser;
*/ */
class InstalledVersions class InstalledVersions
{ {
/**
* @var mixed[]|null
* @psalm-var array{root: array{name: string, version: string, reference: string, pretty_version: string, aliases: string[], dev: bool, install_path: string, type: string}, versions: array<string, array{dev_requirement: bool, pretty_version?: string, version?: string, aliases?: string[], reference?: string, replaced?: string[], provided?: string[], install_path?: string, type?: string}>}|array{}|null
*/
private static $installed; private static $installed;
/**
* @var bool|null
*/
private static $canGetVendors; private static $canGetVendors;
/**
* @var array[]
* @psalm-var array<string, array{root: array{name: string, version: string, reference: string, pretty_version: string, aliases: string[], dev: bool, install_path: string, type: string}, versions: array<string, array{dev_requirement: bool, pretty_version?: string, version?: string, aliases?: string[], reference?: string, replaced?: string[], provided?: string[], install_path?: string, type?: string}>}>
*/
private static $installedByVendor = array(); private static $installedByVendor = array();
/** /**
......
...@@ -32,5 +32,13 @@ return array( ...@@ -32,5 +32,13 @@ return array(
'ed962a97bd972bc82007176b647d4e36' => $vendorDir . '/facade/ignition/src/helpers.php', 'ed962a97bd972bc82007176b647d4e36' => $vendorDir . '/facade/ignition/src/helpers.php',
'6124b4c8570aa390c21fafd04a26c69f' => $vendorDir . '/myclabs/deep-copy/src/DeepCopy/deep_copy.php', '6124b4c8570aa390c21fafd04a26c69f' => $vendorDir . '/myclabs/deep-copy/src/DeepCopy/deep_copy.php',
'b6b991a57620e2fb6b2f66f03fe9ddc2' => $vendorDir . '/symfony/string/Resources/functions.php', 'b6b991a57620e2fb6b2f66f03fe9ddc2' => $vendorDir . '/symfony/string/Resources/functions.php',
'5a6c01c6b890a6f9e22f6a75f33535c3' => $vendorDir . '/loilo/fuse/src/Bitap/matched_indices.php',
'cb0217d87bec02191ba2d2597c16f1a7' => $vendorDir . '/loilo/fuse/src/Bitap/pattern_alphabet.php',
'07e8a1a5effbc28d6b452bec2948bb65' => $vendorDir . '/loilo/fuse/src/Bitap/regex_search.php',
'd28900056f66e13fa4e269caa8a4cd1c' => $vendorDir . '/loilo/fuse/src/Bitap/score.php',
'7679d68ce06dec48d343f560108145d2' => $vendorDir . '/loilo/fuse/src/Bitap/search.php',
'ae18f0d7f1399203de0fc444e860fdd9' => $vendorDir . '/loilo/fuse/src/Helpers/deep_value.php',
'ea2171ac7e455f713fa8445ea3919da7' => $vendorDir . '/loilo/fuse/src/Helpers/get.php',
'59ff57762b50378bb54688b7561c609b' => $vendorDir . '/loilo/fuse/src/Helpers/is_list.php',
'b4e3f29b106af37a2bb239f73cdf68c7' => $baseDir . '/app/helpers.php', 'b4e3f29b106af37a2bb239f73cdf68c7' => $baseDir . '/app/helpers.php',
); );
...@@ -59,6 +59,7 @@ return array( ...@@ -59,6 +59,7 @@ return array(
'GuzzleHttp\\Psr7\\' => array($vendorDir . '/guzzlehttp/psr7/src'), 'GuzzleHttp\\Psr7\\' => array($vendorDir . '/guzzlehttp/psr7/src'),
'GuzzleHttp\\Promise\\' => array($vendorDir . '/guzzlehttp/promises/src'), 'GuzzleHttp\\Promise\\' => array($vendorDir . '/guzzlehttp/promises/src'),
'GuzzleHttp\\' => array($vendorDir . '/guzzlehttp/guzzle/src'), 'GuzzleHttp\\' => array($vendorDir . '/guzzlehttp/guzzle/src'),
'Fuse\\' => array($vendorDir . '/loilo/fuse/src'),
'Fruitcake\\Cors\\' => array($vendorDir . '/fruitcake/laravel-cors/src'), 'Fruitcake\\Cors\\' => array($vendorDir . '/fruitcake/laravel-cors/src'),
'Fideloper\\Proxy\\' => array($vendorDir . '/fideloper/proxy/src'), 'Fideloper\\Proxy\\' => array($vendorDir . '/fideloper/proxy/src'),
'Faker\\' => array($vendorDir . '/fakerphp/faker/src/Faker'), 'Faker\\' => array($vendorDir . '/fakerphp/faker/src/Faker'),
......
...@@ -2072,6 +2072,68 @@ ...@@ -2072,6 +2072,68 @@
"install-path": "../league/mime-type-detection" "install-path": "../league/mime-type-detection"
}, },
{ {
"name": "loilo/fuse",
"version": "3.6.1",
"version_normalized": "3.6.1.0",
"source": {
"type": "git",
"url": "https://github.com/loilo/Fuse.git",
"reference": "ead0f50addaee3d9bbed3aae1f0b8ed22b0f573f"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/loilo/Fuse/zipball/ead0f50addaee3d9bbed3aae1f0b8ed22b0f573f",
"reference": "ead0f50addaee3d9bbed3aae1f0b8ed22b0f573f",
"shasum": "",
"mirrors": [
{
"url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%",
"preferred": true
}
]
},
"require": {
"php": "^5.6 || ^7.0"
},
"require-dev": {
"phpunit/phpunit": "^5.0 || ^6.0 || ^7.0"
},
"time": "2020-03-10T10:18:12+00:00",
"type": "library",
"installation-source": "dist",
"autoload": {
"files": [
"src/Bitap/matched_indices.php",
"src/Bitap/pattern_alphabet.php",
"src/Bitap/regex_search.php",
"src/Bitap/score.php",
"src/Bitap/search.php",
"src/Helpers/deep_value.php",
"src/Helpers/get.php",
"src/Helpers/is_list.php"
],
"psr-4": {
"Fuse\\": "src/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"Apache-2.0"
],
"authors": [
{
"name": "Florian Reuschel",
"email": "florian@loilo.de"
}
],
"description": "Fuzzy search for PHP based on Bitap algorithm",
"support": {
"issues": "https://github.com/loilo/Fuse/issues",
"source": "https://github.com/loilo/Fuse/tree/v3.6.1"
},
"install-path": "../loilo/fuse"
},
{
"name": "mockery/mockery", "name": "mockery/mockery",
"version": "1.3.6", "version": "1.3.6",
"version_normalized": "1.3.6.0", "version_normalized": "1.3.6.0",
......
...@@ -5,7 +5,7 @@ ...@@ -5,7 +5,7 @@
'type' => 'project', 'type' => 'project',
'install_path' => __DIR__ . '/../../', 'install_path' => __DIR__ . '/../../',
'aliases' => array(), 'aliases' => array(),
'reference' => 'eea4a370d6b9ebe69099f9050e8a33f641a4328c', 'reference' => 'ee659885dc607f44661a077e009c3db918b3dbc3',
'name' => 'laravel/laravel', 'name' => 'laravel/laravel',
'dev' => true, 'dev' => true,
), ),
...@@ -379,7 +379,7 @@ ...@@ -379,7 +379,7 @@
'type' => 'project', 'type' => 'project',
'install_path' => __DIR__ . '/../../', 'install_path' => __DIR__ . '/../../',
'aliases' => array(), 'aliases' => array(),
'reference' => 'eea4a370d6b9ebe69099f9050e8a33f641a4328c', 'reference' => 'ee659885dc607f44661a077e009c3db918b3dbc3',
'dev_requirement' => false, 'dev_requirement' => false,
), ),
'laravel/tinker' => array( 'laravel/tinker' => array(
...@@ -427,6 +427,15 @@ ...@@ -427,6 +427,15 @@
'reference' => 'ff6248ea87a9f116e78edd6002e39e5128a0d4dd', 'reference' => 'ff6248ea87a9f116e78edd6002e39e5128a0d4dd',
'dev_requirement' => false, 'dev_requirement' => false,
), ),
'loilo/fuse' => array(
'pretty_version' => '3.6.1',
'version' => '3.6.1.0',
'type' => 'library',
'install_path' => __DIR__ . '/../loilo/fuse',
'aliases' => array(),
'reference' => 'ead0f50addaee3d9bbed3aae1f0b8ed22b0f573f',
'dev_requirement' => false,
),
'mockery/mockery' => array( 'mockery/mockery' => array(
'pretty_version' => '1.3.6', 'pretty_version' => '1.3.6',
'version' => '1.3.6.0', 'version' => '1.3.6.0',
......
{
"name": "loilo/fuse",
"description": "Fuzzy search for PHP based on Bitap algorithm",
"type": "library",
"version": "3.6.1",
"license": "Apache-2.0",
"authors": [
{
"name": "Florian Reuschel",
"email": "florian@loilo.de"
}
],
"require": {
"php": "^5.6 || ^7.0"
},
"require-dev": {
"phpunit/phpunit": "^5.0 || ^6.0 || ^7.0"
},
"autoload": {
"psr-4": {
"Fuse\\": "src/"
},
"files": [
"src/Bitap/matched_indices.php",
"src/Bitap/pattern_alphabet.php",
"src/Bitap/regex_search.php",
"src/Bitap/score.php",
"src/Bitap/search.php",
"src/Helpers/deep_value.php",
"src/Helpers/get.php",
"src/Helpers/is_list.php"
]
}
}
<?php namespace Fuse\Bitap;
class Bitap
{
// Public properties to preserve compatibility with Fuse.js
public $options;
public $pattern;
public $patternAlphabet;
public function __construct($pattern, $options = [])
{
$this->options = array_merge([
// Approximately where in the text is the pattern expected to be found?
'location' => 0,
// Determines how close the match must be to the fuzzy location (specified above).
// An exact letter match which is 'distance' characters away from the fuzzy location
// would score as a complete mismatch. A distance of '0' requires the match be at
// the exact location specified, a threshold of '1000' would require a perfect match
// to be within 800 characters of the fuzzy location to be found using a 0.8 threshold.
'distance' => 100,
// At what point does the match algorithm give up. A threshold of '0.0' requires a perfect match
// (of both letters and location), a threshold of '1.0' would match anything.
'threshold' => 0.6,
// Machine word size
'maxPatternLength' => 32,
// Indicates whether comparisons should be case sensitive.
'isCaseSensitive' => false,
// Regex used to separate words when searching. Only applicable when `tokenize` is `true`.
'tokenSeparator' => '/ +/',
// When true, the algorithm continues searching to the end of the input even if a perfect
// match is found before the end of the same input.
'findAllMatches' => false,
// Minimum number of characters that must be matched before a result is considered a match
'minMatchCharLength' => 1,
'includeMatches' => false
], $options);
$this->pattern = $this->options['isCaseSensitive']
? $pattern
: mb_strtolower($pattern);
if (mb_strlen($this->pattern) <= $this->options['maxPatternLength']) {
$this->patternAlphabet = pattern_alphabet($this->pattern);
}
}
public function search($text)
{
if (!$this->options['isCaseSensitive']) {
$text = mb_strtolower($text);
}
// Exact match
if ($this->pattern === $text) {
$result = [
'isMatch' => true,
'score' => 0,
];
if ($this->options['includeMatches']) {
$result['matchedIndices'] = [[0, mb_strlen($text) - 1]];
}
return $result;
}
// When pattern length is greater than the machine word length, just do a regex comparison
if (mb_strlen($this->pattern) > $this->options['maxPatternLength']) {
return regex_search($text, $this->pattern, $this->options['tokenSeparator']);
}
// Otherwise, use Bitap algorithm
return search($text, $this->pattern, $this->patternAlphabet, [
'location' => $this->options['location'],
'distance' => $this->options['distance'],
'threshold' => $this->options['threshold'],
'findAllMatches' => $this->options['findAllMatches'],
'minMatchCharLength' => $this->options['minMatchCharLength'],
'includeMatches' => $this->options['includeMatches']
]);
}
}
<?php namespace Fuse\Bitap;
function matched_indices($matchmask = [], $minMatchCharLength = 1)
{
$matchedIndices = [];
$start = -1;
$end = -1;
$i = 0;
for ($len = sizeof($matchmask); $i < $len; $i++) {
$match = $matchmask[$i];
if ($match && $start === -1) {
$start = $i;
} elseif (!$match && $start !== -1) {
$end = $i - 1;
if (($end - $start) + 1 >= $minMatchCharLength) {
$matchedIndices[] = [ $start, $end ];
}
$start = -1;
}
}
// (i-1 - start) + 1 => i - start
if (isset($matchmask[$i - 1]) && $matchmask[$i - 1] && ($i - $start) >= $minMatchCharLength) {
$matchedIndices[] = [ $start, $i - 1 ];
}
return $matchedIndices;
}
<?php namespace Fuse\Bitap;
function pattern_alphabet($pattern)
{
$mask = [];
$len = mb_strlen($pattern);
for ($i = 0; $i < $len; $i++) {
$mask[mb_substr($pattern, $i, 1)] = 0;
}
for ($i = 0; $i < $len; $i++) {
$mask[mb_substr($pattern, $i, 1)] |= 1 << ($len - $i - 1);
}
return $mask;
}
<?php namespace Fuse\Bitap;
function regex_search($text, $pattern, $tokenSeparator = ' +')
{
$regex = '/' . preg_replace('/' . str_replace('/', '\\/', $tokenSeparator) . '/', '|', str_replace('/', '\\/', preg_quote($pattern))) . '/';
$isMatch = (bool) preg_match($regex, $text, $matches);
$matchedIndices = [];
if ($isMatch) {
for ($i = 0, $matchesLen = sizeof($matches); $i < $matchesLen; $i++) {
$match = $matches[$i];
$matchedIndices[] = [ mb_strpos($text, $match), mb_strlen($match) - 1 ];
}
}
return [
'score' => $isMatch ? 0.5 : 1,
'isMatch' => $isMatch,
'matchedIndices' => $matchedIndices
];
}
<?php namespace Fuse\Bitap;
function score($pattern, $options = [])
{
$options = array_merge([
'errors' => 0,
'currentLocation' => 0,
'expectedLocation' => 0,
'distance' => 100
], $options);
$accuracy = $options['errors'] / mb_strlen($pattern);
$proximity = abs($options['expectedLocation'] - $options['currentLocation']);
if (!$options['distance']) {
// Dodge divide by zero error.
return $proximity ? 1.0 : $accuracy;
}
return $accuracy + ($proximity / $options['distance']);
}
<?php namespace Fuse\Bitap;
function search($text, $pattern, $patternAlphabet, $options = [])
{
$options = array_merge([
'location' => 0,
'distance' => 100,
'threshold' => 0.6,
'findAllMatches' => false,
'minMatchCharLength' => 1,
'includeMatches' => false
], $options);
$expectedLocation = $options['location'];
// Set starting location at beginning text and initialize the alphabet.
$textLen = mb_strlen($text);
// Highest score beyond which we give up.
$currentThreshold = $options['threshold'];
// Is there a nearby exact match? (speedup)
$bestLocation = mb_strpos($text, $pattern, $expectedLocation);
$patternLen = mb_strlen($pattern);
// a mask of the matches
$matchMask = [];
for ($i = 0; $i < $textLen; $i++) {
$matchMask[$i] = 0;
}
if ($bestLocation !== false) {
$score = score($pattern, [
'errors' => 0,
'currentLocation' => $bestLocation,
'expectedLocation' => $expectedLocation,
'distance' => $options['distance']
]);
$currentThreshold = min($score, $currentThreshold);
// What about in the other direction? (speed up)
$bestLocation = mb_strrpos($text, $pattern, $expectedLocation + $patternLen);
if ($bestLocation !== false) {
$score = score($pattern, [
'errors' => 0,
'currentLocation' => $bestLocation,
'expectedLocation' => $expectedLocation,
'distance' => $options['distance']
]);
$currentThreshold = min($score, $currentThreshold);
}
}
// Reset the best location
$bestLocation = -1;
$lastBitArr = [];
$finalScore = 1;
$binMax = $patternLen + $textLen;
$mask = 1 << min($patternLen - 1, 30);
for ($i = 0; $i < $patternLen; $i++) {
// Scan for the best match; each iteration allows for one more error.
// Run a binary search to determine how far from the match location we can stray
// at this error level.
$binMin = 0;
$binMid = $binMax;
while ($binMin < $binMid) {
$score = score($pattern, [
'errors' => $i,
'currentLocation' => $expectedLocation + $binMid,
'expectedLocation' => $expectedLocation,
'distance' => $options['distance']
]);
if ($score <= $currentThreshold) {
$binMin = $binMid;
} else {
$binMax = $binMid;
}
$binMid = floor(($binMax - $binMin) / 2 + $binMin);
}
// Use the result from this iteration as the maximum for the next.
$binMax = $binMid;
$start = max(1, $expectedLocation - $binMid + 1);
$finish = $options['findAllMatches']
? $textLen
: min($expectedLocation + $binMid, $textLen) + $patternLen;
// Initialize the bit array
$bitArr = [];
$bitArr[$finish + 1] = (1 << $i) - 1;
for ($j = $finish; $j >= $start; $j -= 1) {
$currentLocation = $j - 1;
$offset = mb_substr($text, $currentLocation, 1);
$charMatch = isset($patternAlphabet[$offset])
? $patternAlphabet[$offset]
: null;
if ($charMatch) {
$matchMask[$currentLocation] = 1;
}
// First pass: exact match
$bitArr[$j] = (($bitArr[$j + 1] << 1) | 1) & $charMatch;
// Subsequent passes: fuzzy match
if ($i !== 0) {
$bitArr[$j] |= ((($lastBitArr[$j + 1] | $lastBitArr[$j]) << 1) | 1) | $lastBitArr[$j + 1];
}
if ($bitArr[$j] & $mask) {
$finalScore = score($pattern, [
'errors' => $i,
'currentLocation' => $currentLocation,
'expectedLocation' => $expectedLocation,
'distance' => $options['distance']
]);
// This match will almost certainly be better than any existing match.
// But check anyway.
if ($finalScore <= $currentThreshold) {
// Indeed it is
$currentThreshold = $finalScore;
$bestLocation = $currentLocation;
// Already passed `loc`, downhill from here on in.
if ($bestLocation <= $expectedLocation) {
break;
}
// When passing `bestLocation`, don't exceed our current distance from `expectedLocation`.
$start = max(1, 2 * $expectedLocation - $bestLocation);
}
}
}
// No hope for a (better) match at greater error levels.
$score = score($pattern, [
'errors' => $i + 1,
'currentLocation' => $expectedLocation,
'expectedLocation' => $expectedLocation,
'distance' => $options['distance']
]);
if ($score > $currentThreshold) {
break;
}
$lastBitArr = $bitArr;
}
// Count exact matches (those with a score of 0) to be "almost" exact
$result = [
'isMatch' => $bestLocation >= 0,
'score' => $finalScore == 0 ? 0.001 : $finalScore
];
if ($options['includeMatches']) {
$result['matchedIndices'] = matched_indices($matchMask, $options['minMatchCharLength']);
}
return $result;
}
<?php namespace Fuse\Helpers;
function deep_value($assoc, $path, &$list = [])
{
if (!$path) {
// If there's no path left, we've gotten to the object we care about.
$list[] = $assoc;
} else {
$dotIndex = mb_strpos($path, '.');
$firstSegment = $path;
$remaining = null;
if ($dotIndex !== false) {
$firstSegment = mb_substr($path, 0, $dotIndex);
$remaining = mb_substr($path, $dotIndex + 1);
}
$value = isset($assoc[$firstSegment])
? $assoc[$firstSegment]
: null;
if (!is_null($value)) {
if (!$remaining && (is_string($value) || is_int($value) || is_float($value))) {
$list[] = (string) $value;
} elseif (is_list($value)) {
// Search each item in the array.
for ($i = 0, $len = sizeof($value); $i < $len; $i++) {
deep_value($value[$i], $remaining, $list);
}
} elseif ($remaining) {
// An associative array. Recurse further.
deep_value($value, $remaining, $list);
}
}
}
return $list;
}
<?php namespace Fuse\Helpers;
function get($obj, $path)
{
$list = [];
$get = function ($obj, $path) use (&$list, &$get) {
if (!$path) {
// If there's no $path left, we've gotten to the $object we care about.
$list[] = $obj;
} else {
$dotIndex = strpos($path, '.');
$key = $path;
$remaining = null;
if ($dotIndex !== false) {
$key = substr($path, 0, $dotIndex);
$remaining = substr($path, $dotIndex + 1);
}
$value = isset($obj[$key]) ? $obj[$key] : null;
if (!is_null($value)) {
if (!$remaining && (is_string($value) || is_float($value) || is_int($value))) {
$list[] = (string) ($value);
} elseif (is_list($value)) {
// Search each item in the array.
foreach ($value as $item) {
$get($item, $remaining);
}
} elseif ($remaining) {
// An $object. Recurse further.
$get($value, $remaining);
}
}
}
};
$get($obj, $path);
return $list;
}
\ No newline at end of file
<?php namespace Fuse\Helpers;
function is_list($var)
{
return is_array($var) && !array_diff_key($var, array_keys(array_keys($var)));
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or sign in to comment