1
0
mirror of https://github.com/processwire/processwire.git synced 2025-08-18 12:31:17 +02:00

Improvements to searchability of FieldtypeOptions fields, now enabling it to match either value or title.

This commit is contained in:
Ryan Cramer
2019-01-11 08:52:12 -05:00
parent 36c0f401e7
commit 703fa29c85
2 changed files with 45 additions and 20 deletions

View File

@@ -100,11 +100,11 @@ class FieldtypeOptions extends FieldtypeMulti implements Module {
$inputfield->addOption((int) $option->id, $option->getTitle()); $inputfield->addOption((int) $option->id, $option->getTitle());
} }
if($field->initValue) { if($field->get('initValue')) {
$value = $page->getUnformatted($field->name); $value = $page->getUnformatted($field->name);
if($field->required && !$field->requiredIf) { if($field->required && !$field->requiredIf) {
if(empty($value) || !wireCount($value)) { if(empty($value) || !wireCount($value)) {
$page->set($field->name, $field->initValue); $page->set($field->name, $field->get('initValue'));
} }
} else if($this->wire('process') != 'ProcessField' && !wireCount($value)) { } else if($this->wire('process') != 'ProcessField' && !wireCount($value)) {
$this->warning( $this->warning(
@@ -230,10 +230,10 @@ class FieldtypeOptions extends FieldtypeMulti implements Module {
$sleepValue = array(); $sleepValue = array();
if(empty($value) || !count($value)) { if(empty($value) || !count($value)) {
// value is empty // value is empty
if($field->required && $field->initValue) { if($field->required && $field->get('initValue')) {
// value is required, and an initial value is supplied // value is required, and an initial value is supplied
// so populate the initial value // so populate the initial value
$initValue = $field->initValue; $initValue = $field->get('initValue');
if(!is_array($initValue)) $initValue = array($initValue); if(!is_array($initValue)) $initValue = array($initValue);
foreach($initValue as $v) { foreach($initValue as $v) {
$sleepValue[] = (int) $v; $sleepValue[] = (int) $v;
@@ -306,19 +306,34 @@ class FieldtypeOptions extends FieldtypeMulti implements Module {
if($subfield == 'data' && (ctype_digit("$value") || empty($value))) { if($subfield == 'data' && (ctype_digit("$value") || empty($value))) {
// this is fine (presumed to be an option_id) // this is fine (presumed to be an option_id)
} else { } else {
// some other subfield // some other subfield, which needs to be mapped to either value or title
$options = array();
if(!$subfield || !SelectableOption::isProperty($subfield)) { if($subfield === 'data' && ($operator === '=' || $operator === '!=')) {
// if empty subfield or not a subfield we recognize, just assume title // subfield not specified: matching some string value, is it a value or a title? (allow for either)
$subfield = 'title'; $options = $this->manager->getOptions($query->field, array(
'value' => $value,
'title' => $value,
'or' => true
));
} }
$options = $this->manager->findOptionsByProperty($query->field, $subfield, $operator, $value);
if(!count($options)) {
if(!$subfield || !SelectableOption::isProperty($subfield)) {
// if empty subfield or not a subfield we recognize, just assume title
$subfield = 'title';
}
$options = $this->manager->findOptionsByProperty($query->field, $subfield, $operator, $value);
}
$option = $options->first(); $option = $options->first();
if($operator != '=' && $operator != '!=') { if($operator != '=' && $operator != '!=') {
// for fulltext operations... // for fulltext operations...
// since we are now just matching IDs of already found options // since we are now just matching IDs of already found options
$operator = '='; $operator = '=';
} }
$subfield = 'data'; $subfield = 'data';
$value = $option ? $option->id : null; $value = $option ? $option->id : null;
} }

View File

@@ -97,39 +97,49 @@ class SelectableOptionManager extends Wire {
'id' => array(), 'id' => array(),
'title' => array(), 'title' => array(),
'value' => array(), 'value' => array(),
'or' => false, // change conditions from AND to OR?
); );
$sortKey = true; $sortKey = true;
$sorted = array(); $sorted = array();
$filters = array_merge($defaults, $filters); $filters = array_merge($defaults, $filters);
$wheres = array();
// make sure that all filters are arrays // make sure that all filters are arrays
foreach($defaults as $key => $unused) { foreach($defaults as $key => $unused) {
if(!is_array($filters[$key])) $filters[$key] = array($filters[$key]); if(!is_array($filters[$key])) $filters[$key] = array($filters[$key]);
} }
$sql = 'SELECT * FROM ' . self::optionsTable . ' WHERE fields_id=:fields_id ';
if(count($filters['id'])) { if(count($filters['id'])) {
$sql .= 'AND option_id IN('; $s = 'option_id IN(';
foreach($filters['id'] as $id) { foreach($filters['id'] as $id) {
$id = (int) $id; $id = (int) $id;
$sql .= "$id,"; $s .= "$id,";
$sorted[$id] = ''; // placeholder $sorted[$id] = ''; // placeholder
} }
$sql = rtrim($sql, ',') . ')'; $s = rtrim($s, ',') . ')';
$sortKey = 'filters-id'; $sortKey = 'filters-id';
$wheres[] = $s;
} }
foreach(array('title', 'value') as $property) { foreach(array('title', 'value') as $property) {
if(!count($filters[$property])) continue; if(!count($filters[$property])) continue;
$sql .= "AND `$property` IN("; $s = "`$property` IN(";
foreach($filters[$property] as $val) { foreach($filters[$property] as $val) {
$sql .= $this->wire('database')->quote($val) . ','; $s .= $this->wire('database')->quote($val) . ',';
$sorted[$val] = ''; // placeholder $sorted[$val] = ''; // placeholder
} }
$sql = rtrim($sql, ',') . ')'; $s = rtrim($s, ',') . ')';
$sortKey = "filters-$property"; $sortKey = "filters-$property";
$wheres[] = $s;
}
$sql = 'SELECT * FROM ' . self::optionsTable . ' WHERE fields_id=:fields_id ';
if(count($wheres) > 1) {
$andOr = $filters['or'] ? ' OR ' : ' AND ';
$sql .= 'AND (' . implode($andOr, $wheres) . ') ';
} else if(count($wheres) === 1) {
$sql .= 'AND ' . reset($wheres);
} }
if($sortKey === true) $sql .= 'ORDER BY sort ASC'; if($sortKey === true) $sql .= 'ORDER BY sort ASC';
@@ -173,7 +183,7 @@ class SelectableOptionManager extends Wire {
* Perform a partial match on title of options * Perform a partial match on title of options
* *
* @param Field $field * @param Field $field
* @param string $property Either 'title' or 'value' * @param string $property Either 'title' or 'value'. May also be blank (to imply 'either') if operator is '=' or '!='
* @param string $operator * @param string $operator
* @param string $value Value to find * @param string $value Value to find
* @return SelectableOptionArray * @return SelectableOptionArray