1
0
mirror of https://github.com/processwire/processwire.git synced 2025-08-16 03:34:33 +02:00

Add new SelectorContainsAnyWordsExpand operator (~|+=) and update the getDescription() methods for most Selector classes to bring greater consistency and less translation.

This commit is contained in:
Ryan Cramer
2020-07-03 15:48:30 -04:00
parent 803e5c26d3
commit 70f1a7cc8b
2 changed files with 171 additions and 120 deletions

View File

@@ -132,6 +132,12 @@ abstract class Selector extends WireData {
*/ */
const compareTypeDatabase = 128; const compareTypeDatabase = 128;
/**
* Comparison type: Fulltext index required when used with database queries
*
*/
const compareTypeFulltext = 256;
/** /**
* Given a field name and value, construct the Selector. * Given a field name and value, construct the Selector.
* *
@@ -658,6 +664,7 @@ abstract class Selector extends WireData {
'ContainsAnyWords', 'ContainsAnyWords',
'ContainsAnyWordsPartial', 'ContainsAnyWordsPartial',
'ContainsAnyWordsLike', 'ContainsAnyWordsLike',
'ContainsAnyWordsExpand',
'ContainsExpand', 'ContainsExpand',
'ContainsMatch', 'ContainsMatch',
'ContainsMatchExpand', 'ContainsMatchExpand',
@@ -686,9 +693,7 @@ class SelectorEqual extends Selector {
public static function getOperator() { return '='; } public static function getOperator() { return '='; }
public static function getCompareType() { return Selector::compareTypeExact; } public static function getCompareType() { return Selector::compareTypeExact; }
public static function getLabel() { return __('Equals', __FILE__); } public static function getLabel() { return __('Equals', __FILE__); }
public static function getDescription() { public static function getDescription() { return __('Given value is the same as value compared to.', __FILE__); }
return __('Given value is exactly the same as value compared to.', __FILE__);
}
protected function match($value1, $value2) { return $this->evaluate($value1 == $value2); } protected function match($value1, $value2) { return $this->evaluate($value1 == $value2); }
} }
@@ -700,9 +705,7 @@ class SelectorNotEqual extends Selector {
public static function getOperator() { return '!='; } public static function getOperator() { return '!='; }
public static function getCompareType() { return Selector::compareTypeExact; } public static function getCompareType() { return Selector::compareTypeExact; }
public static function getLabel() { return __('Not equals', __FILE__); } public static function getLabel() { return __('Not equals', __FILE__); }
public static function getDescription() { public static function getDescription() { return __('Given value is not the same as value compared to.', __FILE__); }
return __('Given value is not exactly the same as value compared to.', __FILE__);
}
protected function match($value1, $value2) { return $this->evaluate($value1 != $value2); } protected function match($value1, $value2) { return $this->evaluate($value1 != $value2); }
} }
@@ -714,9 +717,7 @@ class SelectorGreaterThan extends Selector {
public static function getOperator() { return '>'; } public static function getOperator() { return '>'; }
public static function getCompareType() { return Selector::compareTypeSort; } public static function getCompareType() { return Selector::compareTypeSort; }
public static function getLabel() { return __('Greater than', __FILE__); } public static function getLabel() { return __('Greater than', __FILE__); }
public static function getDescription() { public static function getDescription() { return __('Compared value is greater than given value.', __FILE__); }
return __('Given value is greater than compared value.', __FILE__);
}
protected function match($value1, $value2) { return $this->evaluate($value1 > $value2); } protected function match($value1, $value2) { return $this->evaluate($value1 > $value2); }
} }
@@ -728,9 +729,7 @@ class SelectorLessThan extends Selector {
public static function getOperator() { return '<'; } public static function getOperator() { return '<'; }
public static function getCompareType() { return Selector::compareTypeSort; } public static function getCompareType() { return Selector::compareTypeSort; }
public static function getLabel() { return __('Less than', __FILE__); } public static function getLabel() { return __('Less than', __FILE__); }
public static function getDescription() { public static function getDescription() { return __('Compared value is less than given value.', __FILE__); }
return __('Given value is less than compared value.', __FILE__);
}
protected function match($value1, $value2) { return $this->evaluate($value1 < $value2); } protected function match($value1, $value2) { return $this->evaluate($value1 < $value2); }
} }
@@ -742,9 +741,7 @@ class SelectorGreaterThanEqual extends Selector {
public static function getOperator() { return '>='; } public static function getOperator() { return '>='; }
public static function getCompareType() { return Selector::compareTypeSort; } public static function getCompareType() { return Selector::compareTypeSort; }
public static function getLabel() { return __('Greater than or equal', __FILE__); } public static function getLabel() { return __('Greater than or equal', __FILE__); }
public static function getDescription() { public static function getDescription() { return __('Compared value is greater than or equal to given value.', __FILE__); }
return __('Given value is greater than or equal to compared value.', __FILE__);
}
protected function match($value1, $value2) { return $this->evaluate($value1 >= $value2); } protected function match($value1, $value2) { return $this->evaluate($value1 >= $value2); }
} }
@@ -756,9 +753,7 @@ class SelectorLessThanEqual extends Selector {
public static function getOperator() { return '<='; } public static function getOperator() { return '<='; }
public static function getCompareType() { return Selector::compareTypeSort; } public static function getCompareType() { return Selector::compareTypeSort; }
public static function getLabel() { return __('Less than or equal', __FILE__); } public static function getLabel() { return __('Less than or equal', __FILE__); }
public static function getDescription() { public static function getDescription() { return __('Compared value is less than or equal to given value.', __FILE__); }
return __('Given value is less than or equal to compared value.', __FILE__);
}
protected function match($value1, $value2) { return $this->evaluate($value1 <= $value2); } protected function match($value1, $value2) { return $this->evaluate($value1 <= $value2); }
} }
@@ -768,15 +763,47 @@ class SelectorLessThanEqual extends Selector {
*/ */
class SelectorContains extends Selector { class SelectorContains extends Selector {
public static function getOperator() { return '*='; } public static function getOperator() { return '*='; }
public static function getCompareType() { return Selector::compareTypeFind; } public static function getCompareType() { return Selector::compareTypeFind | Selector::compareTypeFulltext; }
public static function getLabel() { return __('Contains phrase', __FILE__); } public static function getLabel() { return __('Contains phrase', __FILE__); }
public static function getDescription() { public static function getDescription() { return SelectorContains::buildDescription('phrase fulltext'); }
return __('Given phrase or word appears in value compared to.', __FILE__);
}
protected function match($value1, $value2) { protected function match($value1, $value2) {
$matches = stripos($value1, $value2) !== false && preg_match('/\b' . preg_quote($value2) . '/i', $value1); $matches = stripos($value1, $value2) !== false && preg_match('/\b' . preg_quote($value2) . '/i', $value1);
return $this->evaluate($matches); return $this->evaluate($matches);
} }
/**
* Build description from predefined keys for SelectorContains* classes
*
* @param array|string $keys
* @return string
*
*/
public static function buildDescription($keys) {
$a = array();
if(!is_array($keys)) $keys = explode(' ', $keys);
foreach($keys as $key) {
switch($key) {
case 'text': $a[] = __('Given text appears in value compared to.', __FILE__); break;
case 'phrase': $a[] = __('Given phrase or word appears in value compared to.', __FILE__); break;
case 'phrase-start': $a[] = __('Given word or phrase appears at beginning of compared value.', __FILE__); break;
case 'phrase-end': $a[] = __('Given word or phrase appears at end of compared value.', __FILE__); break;
case 'expand': $a[] = __('Expand to include potentially related terms and word variations.', __FILE__); break;
case 'words-all': $a[] = __('All given words appear in compared value, in any order.', __FILE__); break;
case 'words-any': $a[] = __('Any given words appear in compared value, in any order.', __FILE__); break;
case 'words-match': $a[] = __('Any given words match against compared value.', __FILE__); break;
case 'words-whole': $a[] = __('Matches whole words.', __FILE__); break;
case 'words-partial': $a[] = __('Matches whole or partial words.', __FILE__); break;
case 'words-partial-any': $a[] = __('Partial matches anywhere within words.', __FILE__); break;
case 'words-partial-begin': $a[] = __('Partial matches from beginning of words.', __FILE__); break;
case 'words-partial-last': $a[] = __('Partial matches last word in given value.', __FILE__); break;
case 'fulltext': $a[] = __('Uses “fulltext” index.', __FILE__); break;
case 'like': $a[] = __('Matches using “like”.', __FILE__); break;
case 'like-words': $a[] = __('Matches without regard to word boundaries (using “like”).', __FILE__); break;
default: $a[] = "UNKNOWN:$key";
}
}
return implode(' ', $a);
}
} }
/** /**
@@ -785,11 +812,9 @@ class SelectorContains extends Selector {
*/ */
class SelectorContainsExpand extends SelectorContains { class SelectorContainsExpand extends SelectorContains {
public static function getOperator() { return '*+='; } public static function getOperator() { return '*+='; }
public static function getCompareType() { return Selector::compareTypeFind | Selector::compareTypeExpand | Selector::compareTypeDatabase; } public static function getCompareType() { return Selector::compareTypeFind | Selector::compareTypeExpand | Selector::compareTypeDatabase | Selector::compareTypeFulltext; }
public static function getLabel() { return __('Contains phrase + expand', __FILE__); } public static function getLabel() { return __('Contains phrase expand', __FILE__); }
public static function getDescription() { public static function getDescription() { return SelectorContains::buildDescription('phrase expand fulltext'); }
return __('Given phrase, word or related terms appear in value compared to.', __FILE__);
}
} }
/** /**
@@ -800,9 +825,7 @@ class SelectorContainsLike extends SelectorContains {
public static function getOperator() { return '%='; } public static function getOperator() { return '%='; }
public static function getCompareType() { return Selector::compareTypeFind | Selector::compareTypeLike; } public static function getCompareType() { return Selector::compareTypeFind | Selector::compareTypeLike; }
public static function getLabel() { return __('Contains text like', __FILE__); } public static function getLabel() { return __('Contains text like', __FILE__); }
public static function getDescription() { public static function getDescription() { return SelectorContains::buildDescription('phrase like'); }
return __('Given text appears in compared value, without regard to word boundaries.', __FILE__);
}
protected function match($value1, $value2) { return $this->evaluate(stripos($value1, $value2) !== false); } protected function match($value1, $value2) { return $this->evaluate(stripos($value1, $value2) !== false); }
} }
@@ -812,11 +835,9 @@ class SelectorContainsLike extends SelectorContains {
*/ */
class SelectorContainsWords extends Selector { class SelectorContainsWords extends Selector {
public static function getOperator() { return '~='; } public static function getOperator() { return '~='; }
public static function getCompareType() { return Selector::compareTypeFind; } public static function getCompareType() { return Selector::compareTypeFind | Selector::compareTypeFulltext; }
public static function getLabel() { return __('Contains entire words', __FILE__); } public static function getLabel() { return __('Contains all words', __FILE__); }
public static function getDescription() { public static function getDescription() { return SelectorContains::buildDescription('words-all words-whole fulltext'); }
return __('All given whole words appear in compared value, in any order.', __FILE__);
}
protected function match($value1, $value2) { protected function match($value1, $value2) {
$hasAll = true; $hasAll = true;
$words = $this->wire()->sanitizer->wordsArray($value2); $words = $this->wire()->sanitizer->wordsArray($value2);
@@ -834,11 +855,9 @@ class SelectorContainsWords extends Selector {
*/ */
class SelectorContainsWordsPartial extends Selector { class SelectorContainsWordsPartial extends Selector {
public static function getOperator() { return '~*='; } public static function getOperator() { return '~*='; }
public static function getCompareType() { return Selector::compareTypeFind; } public static function getCompareType() { return Selector::compareTypeFind | Selector::compareTypeFulltext; }
public static function getLabel() { return __('Contains words partial', __FILE__); } public static function getLabel() { return __('Contains all partial words', __FILE__); }
public static function getDescription() { public static function getDescription() { return SelectorContains::buildDescription('words-all words-partial words-partial-begin fulltext'); }
return __('All given partial and whole words appear in compared value, in any order. Partial matches from beginning of words.', __FILE__);
}
protected function match($value1, $value2) { protected function match($value1, $value2) {
$hasAll = true; $hasAll = true;
$words = $this->wire()->sanitizer->wordsArray($value2); $words = $this->wire()->sanitizer->wordsArray($value2);
@@ -852,6 +871,28 @@ class SelectorContainsWordsPartial extends Selector {
} }
} }
/**
* Selector that matches partial words at either beginning or ending
*
*/
class SelectorContainsWordsLike extends Selector {
public static function getOperator() { return '~%='; }
public static function getCompareType() { return Selector::compareTypeFind | Selector::compareTypeLike; }
public static function getLabel() { return __('Contains all words like', __FILE__); }
public static function getDescription() { return SelectorContains::buildDescription('words-all words-partial words-partial-any like'); }
protected function match($value1, $value2) {
$hasAll = true;
$words = $this->wire()->sanitizer->wordsArray($value2);
foreach($words as $key => $word) {
if(stripos($value1, $word) === false) {
$hasAll = false;
break;
}
}
return $this->evaluate($hasAll);
}
}
/** /**
* Selector that matches entire words except for last word, which must start with * Selector that matches entire words except for last word, which must start with
* *
@@ -860,11 +901,9 @@ class SelectorContainsWordsPartial extends Selector {
*/ */
class SelectorContainsWordsLive extends Selector { class SelectorContainsWordsLive extends Selector {
public static function getOperator() { return '~~='; } public static function getOperator() { return '~~='; }
public static function getCompareType() { return Selector::compareTypeFind; } public static function getCompareType() { return Selector::compareTypeFind | Selector::compareTypeFulltext; }
public static function getLabel() { return __('Contains words live', __FILE__); } public static function getLabel() { return __('Contains all words live', __FILE__); }
public static function getDescription() { public static function getDescription() { return SelectorContains::buildDescription('words-all words-partial-last fulltext'); }
return __('All given whole words—and at least partial last word—appear in compared value, in any order.', __FILE__);
}
protected function match($value1, $value2) { protected function match($value1, $value2) {
$hasAll = true; $hasAll = true;
$words = $this->wire()->sanitizer->wordsArray($value2); $words = $this->wire()->sanitizer->wordsArray($value2);
@@ -882,41 +921,15 @@ class SelectorContainsWordsLive extends Selector {
} }
} }
/**
* Selector that matches partial words at either beginning or ending
*
*/
class SelectorContainsWordsLike extends Selector {
public static function getOperator() { return '~%='; }
public static function getCompareType() { return Selector::compareTypeFind | Selector::compareTypeLike; }
public static function getLabel() { return __('Contains words like', __FILE__); }
public static function getDescription() {
return __('All given partial or whole words appear in compared value (in any order) without regard to word boundaries.', __FILE__);
}
protected function match($value1, $value2) {
$hasAll = true;
$words = $this->wire()->sanitizer->wordsArray($value2);
foreach($words as $key => $word) {
if(stripos($value1, $word) === false) {
$hasAll = false;
break;
}
}
return $this->evaluate($hasAll);
}
}
/** /**
* Selector that matches all words with query expansion * Selector that matches all words with query expansion
* *
*/ */
class SelectorContainsWordsExpand extends SelectorContainsWords { class SelectorContainsWordsExpand extends SelectorContainsWords {
public static function getOperator() { return '~+='; } public static function getOperator() { return '~+='; }
public static function getCompareType() { return Selector::compareTypeFind | Selector::compareTypeExpand; } public static function getCompareType() { return Selector::compareTypeFind | Selector::compareTypeExpand | Selector::compareTypeFulltext; }
public static function getLabel() { return __('Contains words + expand', __FILE__); } public static function getLabel() { return __('Contains all words expand', __FILE__); }
public static function getDescription() { public static function getDescription() { return SelectorContains::buildDescription('words-all words-whole expand fulltext'); }
return __('All given whole words appear in compared value (in any order) and expand to match related values.', __FILE__);
}
} }
/** /**
@@ -925,8 +938,9 @@ class SelectorContainsWordsExpand extends SelectorContainsWords {
*/ */
class SelectorContainsAnyWords extends Selector { class SelectorContainsAnyWords extends Selector {
public static function getOperator() { return '~|='; } public static function getOperator() { return '~|='; }
public static function getCompareType() { return Selector::compareTypeFind; } public static function getCompareType() { return Selector::compareTypeFind | Selector::compareTypeFulltext; }
public static function getLabel() { return __('Contains any words', __FILE__); } public static function getLabel() { return __('Contains any words', __FILE__); }
public static function getDescription() { return SelectorContains::buildDescription('words-any words-whole fulltext'); }
protected function match($value1, $value2) { protected function match($value1, $value2) {
$hasAny = false; $hasAny = false;
$words = $this->wire()->sanitizer->wordsArray($value2); $words = $this->wire()->sanitizer->wordsArray($value2);
@@ -940,9 +954,6 @@ class SelectorContainsAnyWords extends Selector {
} }
return $this->evaluate($hasAny); return $this->evaluate($hasAny);
} }
public static function getDescription() {
return __('Any of the given whole words appear in compared value.', __FILE__);
}
} }
/** /**
@@ -951,8 +962,9 @@ class SelectorContainsAnyWords extends Selector {
*/ */
class SelectorContainsAnyWordsPartial extends Selector { class SelectorContainsAnyWordsPartial extends Selector {
public static function getOperator() { return '~|*='; } public static function getOperator() { return '~|*='; }
public static function getCompareType() { return Selector::compareTypeFind; } public static function getCompareType() { return Selector::compareTypeFind | Selector::compareTypeFulltext; }
public static function getLabel() { return __('Contains any partial words', __FILE__); } public static function getLabel() { return __('Contains any partial words', __FILE__); }
public static function getDescription() { return SelectorContains::buildDescription('words-any words-partial words-partial-begin fulltext'); }
protected function match($value1, $value2) { protected function match($value1, $value2) {
$hasAny = false; $hasAny = false;
$words = $this->wire()->sanitizer->wordsArray($value2); $words = $this->wire()->sanitizer->wordsArray($value2);
@@ -966,9 +978,6 @@ class SelectorContainsAnyWordsPartial extends Selector {
} }
return $this->evaluate($hasAny); return $this->evaluate($hasAny);
} }
public static function getDescription() {
return __('Any of the given partial or whole words appear in compared value. Partial matches from beginning of words.', __FILE__);
}
} }
/** /**
@@ -976,13 +985,10 @@ class SelectorContainsAnyWordsPartial extends Selector {
* *
*/ */
class SelectorContainsAnyWordsLike extends Selector { class SelectorContainsAnyWordsLike extends Selector {
// public static function getOperator() { return '%|='; }
public static function getOperator() { return '~|%='; } public static function getOperator() { return '~|%='; }
public static function getCompareType() { return Selector::compareTypeFind | Selector::compareTypeLike; } public static function getCompareType() { return Selector::compareTypeFind | Selector::compareTypeLike; }
public static function getLabel() { return __('Contains any words like', __FILE__); } public static function getLabel() { return __('Contains any words like', __FILE__); }
public static function getDescription() { public static function getDescription() { return SelectorContains::buildDescription('words-any words-partial words-partial-any like'); }
return __('Any of the given partial or whole words appear in compared value, without regard to word boundaries.', __FILE__);
}
protected function match($value1, $value2) { protected function match($value1, $value2) {
$hasAny = false; $hasAny = false;
$words = $this->wire()->sanitizer->wordsArray($value2); $words = $this->wire()->sanitizer->wordsArray($value2);
@@ -996,6 +1002,43 @@ class SelectorContainsAnyWordsLike extends Selector {
} }
} }
/**
* Selector that matches any words with query expansion
*
*/
class SelectorContainsAnyWordsExpand extends SelectorContainsAnyWords {
public static function getOperator() { return '~|+='; }
public static function getCompareType() { return Selector::compareTypeFind | Selector::compareTypeExpand | Selector::compareTypeFulltext; }
public static function getLabel() { return __('Contains any words expand', __FILE__); }
public static function getDescription() { return SelectorContains::buildDescription('words-any expand fulltext'); }
protected function match($value1, $value2) {
$hasAny = false;
$textTools = $this->wire()->sanitizer->getTextTools();
$words = $this->wire()->sanitizer->wordsArray($value2);
foreach($words as $word) {
if(stripos($value1, $word) !== false && preg_match('/\b' . preg_quote($word) . '\b/i', $value1)) {
$hasAny = true;
break;
}
$stem = $textTools->getWordStem($word);
if($stem && stripos($value1, $stem) !== false && preg_match('/\b' . preg_quote($stem) . '/i', $value1)) {
$hasAny = true;
break;
}
$alternates = $textTools->getWordAlternates($word);
foreach($alternates as $alternate) {
if(stripos($value1, $alternate) && preg_match('/\b' . preg_quote($alternate) . '\b/i', $value1)) {
$hasAny = true;
break;
}
}
if($hasAny) break;
}
return $this->evaluate($hasAny);
}
}
/** /**
* Selector that uses standard MySQL MATCH/AGAINST behavior with implied DB-score sorting * Selector that uses standard MySQL MATCH/AGAINST behavior with implied DB-score sorting
* *
@@ -1004,11 +1047,9 @@ class SelectorContainsAnyWordsLike extends Selector {
*/ */
class SelectorContainsMatch extends SelectorContainsAnyWords { class SelectorContainsMatch extends SelectorContainsAnyWords {
public static function getOperator() { return '**='; } public static function getOperator() { return '**='; }
public static function getCompareType() { return Selector::compareTypeFind | Selector::compareTypeDatabase; } public static function getCompareType() { return Selector::compareTypeFind | Selector::compareTypeDatabase | Selector::compareTypeFulltext; }
public static function getLabel() { return __('Contains match', __FILE__); } public static function getLabel() { return __('Contains match', __FILE__); }
public static function getDescription() { public static function getDescription() { return SelectorContains::buildDescription('words-match words-whole fulltext'); }
return __('Any or all of the given words match compared value using default database logic and score.', __FILE__);
}
} }
/** /**
@@ -1019,11 +1060,9 @@ class SelectorContainsMatch extends SelectorContainsAnyWords {
*/ */
class SelectorContainsMatchExpand extends SelectorContainsMatch { class SelectorContainsMatchExpand extends SelectorContainsMatch {
public static function getOperator() { return '**+='; } public static function getOperator() { return '**+='; }
public static function getCompareType() { return Selector::compareTypeFind | Selector::compareTypeExpand | Selector::compareTypeDatabase; } public static function getCompareType() { return Selector::compareTypeFind | Selector::compareTypeExpand | Selector::compareTypeDatabase | Selector::compareTypeFulltext; }
public static function getLabel() { return __('Contains match + expand', __FILE__); } public static function getLabel() { return __('Contains match expand', __FILE__); }
public static function getDescription() { public static function getDescription() { return SelectorContains::buildDescription('words-match words-whole expand fulltext'); }
return SelectorContainsMatch::getDescription() . ' ' . __('Plus, expands to include potentially related results.', __FILE__);
}
} }
/** /**
@@ -1043,7 +1082,7 @@ class SelectorContainsMatchExpand extends SelectorContainsMatch {
*/ */
class SelectorContainsAdvanced extends SelectorContains { class SelectorContainsAdvanced extends SelectorContains {
public static function getOperator() { return '#='; } public static function getOperator() { return '#='; }
public static function getCompareType() { return Selector::compareTypeFind | Selector::compareTypeCommand; } public static function getCompareType() { return Selector::compareTypeFind | Selector::compareTypeCommand | Selector::compareTypeFulltext; }
public static function getLabel() { return __('Advanced text search', __FILE__); } public static function getLabel() { return __('Advanced text search', __FILE__); }
public static function getDescription() { public static function getDescription() {
return return
@@ -1132,11 +1171,9 @@ class SelectorContainsAdvanced extends SelectorContains {
*/ */
class SelectorStarts extends Selector { class SelectorStarts extends Selector {
public static function getOperator() { return '^='; } public static function getOperator() { return '^='; }
public static function getCompareType() { return Selector::compareTypeFind; } public static function getCompareType() { return Selector::compareTypeFind | Selector::compareTypeFulltext; }
public static function getLabel() { return __('Starts with', __FILE__); } public static function getLabel() { return __('Starts with', __FILE__); }
public static function getDescription() { public static function getDescription() { return SelectorContains::buildDescription('phrase-start fulltext'); }
return __('Given word or phrase appears at beginning of compared value.', __FILE__);
}
protected function match($value1, $value2) { protected function match($value1, $value2) {
return $this->evaluate(stripos(trim($value1), $value2) === 0); return $this->evaluate(stripos(trim($value1), $value2) === 0);
} }
@@ -1150,9 +1187,7 @@ class SelectorStartsLike extends SelectorStarts {
public static function getOperator() { return '%^='; } public static function getOperator() { return '%^='; }
public static function getCompareType() { return Selector::compareTypeFind | Selector::compareTypeLike; } public static function getCompareType() { return Selector::compareTypeFind | Selector::compareTypeLike; }
public static function getLabel() { return __('Starts like', __FILE__); } public static function getLabel() { return __('Starts like', __FILE__); }
public static function getDescription() { public static function getDescription() { return SelectorContains::buildDescription('phrase-start like'); }
return __('Given text appears at beginning of compared value, without regard for word boundaries.', __FILE__);
}
} }
/** /**
@@ -1161,11 +1196,9 @@ class SelectorStartsLike extends SelectorStarts {
*/ */
class SelectorEnds extends Selector { class SelectorEnds extends Selector {
public static function getOperator() { return '$='; } public static function getOperator() { return '$='; }
public static function getCompareType() { return Selector::compareTypeFind; } public static function getCompareType() { return Selector::compareTypeFind | Selector::compareTypeFulltext; }
public static function getLabel() { return __('Ends with', __FILE__); } public static function getLabel() { return __('Ends with', __FILE__); }
public static function getDescription() { public static function getDescription() { return SelectorContains::buildDescription('phrase-end fulltext'); }
return __('Given word or phrase appears at end of compared value.', __FILE__);
}
protected function match($value1, $value2) { protected function match($value1, $value2) {
$value2 = trim($value2); $value2 = trim($value2);
$value1 = substr($value1, -1 * strlen($value2)); $value1 = substr($value1, -1 * strlen($value2));
@@ -1181,9 +1214,7 @@ class SelectorEndsLike extends SelectorEnds {
public static function getOperator() { return '%$='; } public static function getOperator() { return '%$='; }
public static function getCompareType() { return Selector::compareTypeFind | Selector::compareTypeLike; } public static function getCompareType() { return Selector::compareTypeFind | Selector::compareTypeLike; }
public static function getLabel() { return __('Ends like', __FILE__); } public static function getLabel() { return __('Ends like', __FILE__); }
public static function getDescription() { public static function getDescription() { return SelectorContains::buildDescription('phrase-end like'); }
return __('Given text appears at end of compared value, without regard for word boundaries.', __FILE__);
}
} }
/** /**

View File

@@ -383,9 +383,17 @@ class Selectors extends WireArray {
} }
if($operator && !isset($operators[$lastOperator])) { if($operator && !isset($operators[$lastOperator])) {
if(self::isOperator($operator)) { $fail = true;
$operators[$operator] = $operator; if(!count($operators)) {
} else { // check if operator has a typo we can fix
$op = self::isOperator($operator, true);
if($op) {
$operators[$op] = $op;
$str = substr($str, $n);
$fail = false;
}
}
if($fail) {
throw new WireException("Unrecognized operator: $operator"); throw new WireException("Unrecognized operator: $operator");
} }
} }
@@ -1235,7 +1243,7 @@ class Selectors extends WireArray {
* @param array $options * @param array $options
* - `operator` (string): Return info for only this operator. When specified, only value is returned (default=''). * - `operator` (string): Return info for only this operator. When specified, only value is returned (default='').
* - `compareType` (int): Return only operators matching given `Selector::compareType*` constant (default=0). * - `compareType` (int): Return only operators matching given `Selector::compareType*` constant (default=0).
* - `getIndexType` (string): Index type to use in returned array: 'operator', 'className' or 'class' (default='class') * - `getIndexType` (string): Index type to use in returned array: 'operator', 'className', 'class', or 'none' (default='class')
* - `getValueType` (string): Value type to use in returned array: 'operator', 'class', 'className', 'label', 'description', 'compareType', 'verbose' (default='operator'). * - `getValueType` (string): Value type to use in returned array: 'operator', 'class', 'className', 'label', 'description', 'compareType', 'verbose' (default='operator').
* If 'verbose' option used then assoc array returned for each operator containing 'class', 'className', 'operator', 'compareType', 'label', 'description'. * If 'verbose' option used then assoc array returned for each operator containing 'class', 'className', 'operator', 'compareType', 'label', 'description'.
* @return array|string|int Returned array where both keys and values are operators (or values are requested 'valueType' option) * @return array|string|int Returned array where both keys and values are operators (or values are requested 'valueType' option)
@@ -1291,14 +1299,20 @@ class Selectors extends WireArray {
} else { } else {
$value = $operator; $value = $operator;
} }
if($indexType === 'class') { if($indexType === 'none') {
$key = '';
} else if($indexType === 'class') {
$key = $typeName; $key = $typeName;
} else if($indexType === 'className') { } else if($indexType === 'className') {
$key = $className; $key = $className;
} else { } else {
$key = $operator; $key = $operator;
} }
$operators[$key] = $value; if($key === '') {
$operators[] = $value;
} else {
$operators[$key] = $value;
}
} }
if(!empty($options['operator'])) return reset($operators); if(!empty($options['operator'])) return reset($operators);
@@ -1400,12 +1414,18 @@ class Selectors extends WireArray {
* #pw-group-static-helpers * #pw-group-static-helpers
* *
* @param string $operator * @param string $operator
* @return bool * @param bool $returnOperator Return the operator rather than bool? When true, corrects minor typos, like mixed up
* order, returning correct found operator string if possible, false otherwise. Added 3.0.162. (default=false)
* @return bool|string
* @since 3.0.108 * @since 3.0.108
* *
*/ */
static public function isOperator($operator) { static public function isOperator($operator, $returnOperator = false) {
return self::getOperatorType($operator, true); $is = self::getOperatorType($operator, true);
if(!$returnOperator || strlen($operator) < 3) return $is;
if($is) return $operator;
$op = strrev(trim($operator, '=')) . '=';
return self::getOperatorType($op, true) ? $op : false;
} }
/** /**