mirror of
https://github.com/processwire/processwire.git
synced 2025-08-16 11:44:42 +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());
|
||||
}
|
||||
|
||||
if($field->initValue) {
|
||||
if($field->get('initValue')) {
|
||||
$value = $page->getUnformatted($field->name);
|
||||
if($field->required && !$field->requiredIf) {
|
||||
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)) {
|
||||
$this->warning(
|
||||
@@ -230,10 +230,10 @@ class FieldtypeOptions extends FieldtypeMulti implements Module {
|
||||
$sleepValue = array();
|
||||
if(empty($value) || !count($value)) {
|
||||
// value is empty
|
||||
if($field->required && $field->initValue) {
|
||||
if($field->required && $field->get('initValue')) {
|
||||
// value is required, and an initial value is supplied
|
||||
// so populate the initial value
|
||||
$initValue = $field->initValue;
|
||||
$initValue = $field->get('initValue');
|
||||
if(!is_array($initValue)) $initValue = array($initValue);
|
||||
foreach($initValue as $v) {
|
||||
$sleepValue[] = (int) $v;
|
||||
@@ -306,19 +306,34 @@ class FieldtypeOptions extends FieldtypeMulti implements Module {
|
||||
if($subfield == 'data' && (ctype_digit("$value") || empty($value))) {
|
||||
// this is fine (presumed to be an option_id)
|
||||
} 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 empty subfield or not a subfield we recognize, just assume title
|
||||
$subfield = 'title';
|
||||
if($subfield === 'data' && ($operator === '=' || $operator === '!=')) {
|
||||
// subfield not specified: matching some string value, is it a value or a title? (allow for either)
|
||||
$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();
|
||||
|
||||
if($operator != '=' && $operator != '!=') {
|
||||
// for fulltext operations...
|
||||
// since we are now just matching IDs of already found options
|
||||
$operator = '=';
|
||||
}
|
||||
|
||||
$subfield = 'data';
|
||||
$value = $option ? $option->id : null;
|
||||
}
|
||||
|
@@ -97,41 +97,51 @@ class SelectableOptionManager extends Wire {
|
||||
'id' => array(),
|
||||
'title' => array(),
|
||||
'value' => array(),
|
||||
'or' => false, // change conditions from AND to OR?
|
||||
);
|
||||
|
||||
$sortKey = true;
|
||||
$sorted = array();
|
||||
$filters = array_merge($defaults, $filters);
|
||||
$wheres = array();
|
||||
|
||||
// make sure that all filters are arrays
|
||||
foreach($defaults as $key => $unused) {
|
||||
if(!is_array($filters[$key])) $filters[$key] = array($filters[$key]);
|
||||
}
|
||||
|
||||
$sql = 'SELECT * FROM ' . self::optionsTable . ' WHERE fields_id=:fields_id ';
|
||||
|
||||
if(count($filters['id'])) {
|
||||
$sql .= 'AND option_id IN(';
|
||||
$s = 'option_id IN(';
|
||||
foreach($filters['id'] as $id) {
|
||||
$id = (int) $id;
|
||||
$sql .= "$id,";
|
||||
$s .= "$id,";
|
||||
$sorted[$id] = ''; // placeholder
|
||||
}
|
||||
$sql = rtrim($sql, ',') . ')';
|
||||
$s = rtrim($s, ',') . ')';
|
||||
$sortKey = 'filters-id';
|
||||
$wheres[] = $s;
|
||||
}
|
||||
|
||||
|
||||
foreach(array('title', 'value') as $property) {
|
||||
if(!count($filters[$property])) continue;
|
||||
$sql .= "AND `$property` IN(";
|
||||
$s = "`$property` IN(";
|
||||
foreach($filters[$property] as $val) {
|
||||
$sql .= $this->wire('database')->quote($val) . ',';
|
||||
$s .= $this->wire('database')->quote($val) . ',';
|
||||
$sorted[$val] = ''; // placeholder
|
||||
}
|
||||
$sql = rtrim($sql, ',') . ')';
|
||||
$s = rtrim($s, ',') . ')';
|
||||
$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';
|
||||
|
||||
$query = $this->wire('database')->prepare($sql);
|
||||
@@ -173,7 +183,7 @@ class SelectableOptionManager extends Wire {
|
||||
* Perform a partial match on title of options
|
||||
*
|
||||
* @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 $value Value to find
|
||||
* @return SelectableOptionArray
|
||||
|
Reference in New Issue
Block a user