Use WildcardMatch
Per suggestion from @MarkBaker. WildcardMatch did not handle double tilde correctly. It has been changed to do so and its logic simplified (and commented). Existing AutoFilter test covered this situation, but I added a test for MATCH as well.
This commit is contained in:
parent
d88af46ab5
commit
d0dd5b4594
|
|
@ -755,16 +755,6 @@ parameters:
|
||||||
count: 1
|
count: 1
|
||||||
path: src/PhpSpreadsheet/Calculation/Internal/MakeMatrix.php
|
path: src/PhpSpreadsheet/Calculation/Internal/MakeMatrix.php
|
||||||
|
|
||||||
-
|
|
||||||
message: "#^Method PhpOffice\\\\PhpSpreadsheet\\\\Calculation\\\\Internal\\\\WildcardMatch\\:\\:wildcard\\(\\) should return string but returns string\\|null\\.$#"
|
|
||||||
count: 1
|
|
||||||
path: src/PhpSpreadsheet/Calculation/Internal/WildcardMatch.php
|
|
||||||
|
|
||||||
-
|
|
||||||
message: "#^Method PhpOffice\\\\PhpSpreadsheet\\\\Calculation\\\\Internal\\\\WildcardMatch\\:\\:compare\\(\\) has parameter \\$value with no typehint specified\\.$#"
|
|
||||||
count: 1
|
|
||||||
path: src/PhpSpreadsheet/Calculation/Internal/WildcardMatch.php
|
|
||||||
|
|
||||||
-
|
-
|
||||||
message: "#^Call to function is_string\\(\\) with null will always evaluate to false\\.$#"
|
message: "#^Call to function is_string\\(\\) with null will always evaluate to false\\.$#"
|
||||||
count: 3
|
count: 3
|
||||||
|
|
|
||||||
|
|
@ -5,30 +5,30 @@ namespace PhpOffice\PhpSpreadsheet\Calculation\Internal;
|
||||||
class WildcardMatch
|
class WildcardMatch
|
||||||
{
|
{
|
||||||
private const SEARCH_SET = [
|
private const SEARCH_SET = [
|
||||||
'/(?<!~)\*/ui',
|
'~~', // convert double tilde to unprintable value
|
||||||
'/~\*/ui',
|
'~\\*', // convert tilde backslash asterisk to [*] (matches literal asterisk in regexp)
|
||||||
'/(?<!~)\?/ui',
|
'\\*', // convert backslash asterisk to .* (matches string of any length in regexp)
|
||||||
'/~\?/ui',
|
'~\\?', // convert tilde backslash question to [?] (matches literal question mark in regexp)
|
||||||
|
'\\?', // convert backslash question to . (matches one character in regexp)
|
||||||
|
"\x1c", // convert original double tilde to single tilde
|
||||||
];
|
];
|
||||||
|
|
||||||
private const REPLACEMENT_SET = [
|
private const REPLACEMENT_SET = [
|
||||||
'${1}.*',
|
"\x1c",
|
||||||
'\*',
|
'[*]',
|
||||||
'${1}.',
|
'.*',
|
||||||
'\?',
|
'[?]',
|
||||||
|
'.',
|
||||||
|
'~',
|
||||||
];
|
];
|
||||||
|
|
||||||
public static function wildcard(string $wildcard): string
|
public static function wildcard(string $wildcard): string
|
||||||
{
|
{
|
||||||
// Preg Escape the wildcard, but protecting the Excel * and ? search characters
|
// Preg Escape the wildcard, but protecting the Excel * and ? search characters
|
||||||
$wildcard = str_replace(['*', '?'], [0x1A, 0x1B], $wildcard);
|
return str_replace(self::SEARCH_SET, self::REPLACEMENT_SET, preg_quote($wildcard));
|
||||||
$wildcard = preg_quote($wildcard);
|
|
||||||
$wildcard = str_replace([0x1A, 0x1B], ['*', '?'], $wildcard);
|
|
||||||
|
|
||||||
return preg_replace(self::SEARCH_SET, self::REPLACEMENT_SET, $wildcard);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static function compare($value, string $wildcard): bool
|
public static function compare(string $value, string $wildcard): bool
|
||||||
{
|
{
|
||||||
if ($value === '') {
|
if ($value === '') {
|
||||||
return true;
|
return true;
|
||||||
|
|
|
||||||
|
|
@ -6,6 +6,7 @@ use DateTime;
|
||||||
use DateTimeZone;
|
use DateTimeZone;
|
||||||
use PhpOffice\PhpSpreadsheet\Calculation\Calculation;
|
use PhpOffice\PhpSpreadsheet\Calculation\Calculation;
|
||||||
use PhpOffice\PhpSpreadsheet\Calculation\Functions;
|
use PhpOffice\PhpSpreadsheet\Calculation\Functions;
|
||||||
|
use PhpOffice\PhpSpreadsheet\Calculation\Internal\WildcardMatch;
|
||||||
use PhpOffice\PhpSpreadsheet\Cell\Coordinate;
|
use PhpOffice\PhpSpreadsheet\Cell\Coordinate;
|
||||||
use PhpOffice\PhpSpreadsheet\Exception as PhpSpreadsheetException;
|
use PhpOffice\PhpSpreadsheet\Exception as PhpSpreadsheetException;
|
||||||
use PhpOffice\PhpSpreadsheet\Shared\Date;
|
use PhpOffice\PhpSpreadsheet\Shared\Date;
|
||||||
|
|
@ -452,13 +453,6 @@ class AutoFilter
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Search/Replace arrays to convert Excel wildcard syntax to a regexp syntax for preg_matching.
|
|
||||||
*/
|
|
||||||
private const FROM_REPLACE = ['~~', '~\\*', '\\*', '~\\?', '\\?', "\x1c"];
|
|
||||||
|
|
||||||
private const TO_REPLACE = ["\x1c", '[*]', '.*', '[?]', '.', '~'];
|
|
||||||
|
|
||||||
private static function makeDateObject(int $year, int $month, int $day, int $hour = 0, int $minute = 0, int $second = 0): DateTime
|
private static function makeDateObject(int $year, int $month, int $day, int $hour = 0, int $minute = 0, int $second = 0): DateTime
|
||||||
{
|
{
|
||||||
$baseDate = new DateTime();
|
$baseDate = new DateTime();
|
||||||
|
|
@ -853,8 +847,7 @@ class AutoFilter
|
||||||
$ruleValue = $rule->getValue();
|
$ruleValue = $rule->getValue();
|
||||||
if (!is_array($ruleValue) && !is_numeric($ruleValue)) {
|
if (!is_array($ruleValue) && !is_numeric($ruleValue)) {
|
||||||
// Convert to a regexp allowing for regexp reserved characters, wildcards and escaped wildcards
|
// Convert to a regexp allowing for regexp reserved characters, wildcards and escaped wildcards
|
||||||
$ruleValue = preg_quote("$ruleValue");
|
$ruleValue = WildcardMatch::wildcard($ruleValue);
|
||||||
$ruleValue = str_replace(self::FROM_REPLACE, self::TO_REPLACE, $ruleValue);
|
|
||||||
if (trim($ruleValue) == '') {
|
if (trim($ruleValue) == '') {
|
||||||
$customRuleForBlanks = true;
|
$customRuleForBlanks = true;
|
||||||
$ruleValue = trim($ruleValue);
|
$ruleValue = trim($ruleValue);
|
||||||
|
|
|
||||||
|
|
@ -346,4 +346,10 @@ return [
|
||||||
['Obtuse', 'Amuse', 'Obverse', 'Inverse', 'Assurance', 'Amplitude', 'Adverse', 'Apartment'],
|
['Obtuse', 'Amuse', 'Obverse', 'Inverse', 'Assurance', 'Amplitude', 'Adverse', 'Apartment'],
|
||||||
0,
|
0,
|
||||||
],
|
],
|
||||||
|
[
|
||||||
|
3, // Expected
|
||||||
|
'*~~*', // contains a tilde
|
||||||
|
['aAAAAA', 'a123456*c', 'abc~xyz', 'alembic'],
|
||||||
|
0,
|
||||||
|
],
|
||||||
];
|
];
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue