mirror of
https://github.com/processwire/processwire.git
synced 2025-08-17 20:11:46 +02:00
Improvements to searchability of FieldtypeOptions fields, now enabling it to match either value or title.
This commit is contained in:
@@ -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;
|
||||||
}
|
}
|
||||||
|
@@ -97,41 +97,51 @@ 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';
|
||||||
|
|
||||||
$query = $this->wire('database')->prepare($sql);
|
$query = $this->wire('database')->prepare($sql);
|
||||||
@@ -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
|
||||||
|
Reference in New Issue
Block a user