protected function getQuerySortSelector(DatabaseQuerySelect $query, Selector $selector)
{
$field = is_array($selector->field) ? reset($selector->field) : $selector->field;
$values = is_array($selector->value) ? $selector->value : array($selector->value);
$fields = $this->fuel('fields');
$database = $this->wire('database');
$user = $this->wire('user');
$language = $this->wire('languages') && $user->language ? $user->language : null;
foreach ($values as $value) {
$fc = substr($value, 0, 1);
$lc = substr($value, -1);
$value = trim($value, "-+");
if (strpos($value, ".")) {
list($value, $subValue) = explode(".", $value);
// i.e. some_field.title
} else {
$subValue = '';
}
if ($value == 'random') {
$value = 'RAND()';
} else {
if ($value == 'num_children' || $value == 'numChildren' || $value == 'children' && $subValue == 'count') {
// sort by quantity of children
$value = $this->getQueryNumChildren($query, new SelectorGreaterThan('num_children', "-1"));
} else {
if ($value == 'parent') {
// sort by parent native field. does not work with non-native parent fields.
$subValue = $database->escapeCol($subValue);
$tableAlias = "_sort_parent" . ($subValue ? "_{$subValue}" : '');
$query->join("pages AS {$tableAlias} ON {$tableAlias}.id=pages.parent_id");
$value = "{$tableAlias}." . ($subValue ? $subValue : "name");
} else {
if ($value == 'template') {
// sort by template
$tableAlias = $database->escapeTable("_sort_templates" . ($subValue ? "_{$subValue}" : ''));
$query->join("templates AS {$tableAlias} ON {$tableAlias}.id=pages.templates_id");
$value = "{$tableAlias}." . ($subValue ? $database->escapeCol($subValue) : "name");
} else {
if ($fields->isNative($value)) {
// sort by a native field
if (!strpos($value, ".")) {
// native field with no subfield
if ($value == 'name' && $language && !$language->isDefault() && $this->wire('modules')->isInstalled('LanguageSupportPageNames')) {
// substitute language-specific name field when LanguageSupportPageNames is active and language is not default
$value = "if(pages.name{$language}!='', pages.name{$language}, pages.name)";
} else {
$value = "pages." . $database->escapeCol($value);
}
}
} else {
$field = $fields->get($value);
if (!$field) {
continue;
}
$fieldName = $database->escapeCol($field->name);
$subValue = $database->escapeCol($subValue);
$tableAlias = "_sort_{$fieldName}" . ($subValue ? "_{$subValue}" : '');
$table = $database->escapeTable($field->table);
if ($field->type instanceof FieldtypePage) {
$blankValue = new PageArray();
} else {
$blankValue = $field->type->getBlankValue(new NullPage(), $field);
}
$query->leftjoin("{$table} AS {$tableAlias} ON {$tableAlias}.pages_id=pages.id");
if ($subValue === 'count') {
// sort by quantity of items
$value = "COUNT({$tableAlias}.data)";
// } else if($field->type instanceof FieldtypePage) {
} else {
if (is_object($blankValue) && ($blankValue instanceof PageArray || $blankValue instanceof Page)) {
// If it's a FieldtypePage, then data isn't worth sorting on because it just contains an ID to the page
// so we also join the page and sort on it's name instead of the field's "data" field.
if (!$subValue) {
$subValue = 'name';
}
$tableAlias2 = "_sort_page_{$fieldName}" . ($subValue ? "_{$subValue}" : '');
if ($this->wire('fields')->isNative($subValue)) {
$query->leftjoin("pages AS {$tableAlias2} ON {$tableAlias}.data={$tableAlias2}.id");
$value = "{$tableAlias2}.{$subValue}";
if ($subValue == 'name' && $language && !$language->isDefault() && $this->wire('modules')->isInstalled('LanguageSupportPageNames')) {
// append language ID to 'name' when performing sorts within another language and LanguageSupportPageNames in place
$value = "if({$value}{$language}!='', {$value}{$language}, {$value})";
}
} else {
if ($subValueField = $this->wire('fields')->get($subValue)) {
$subValueTable = $database->escapeTable($subValueField->getTable());
$query->leftjoin("{$subValueTable} AS {$tableAlias2} ON {$tableAlias}.data={$tableAlias2}.pages_id");
$value = "{$tableAlias2}.data";
if ($language && !$language->isDefault() && $subValueField->type instanceof FieldtypeLanguageInterface) {
// append language id to data, i.e. "data1234"
$value .= $language;
}
} else {
// error: unknown field
}
}
} else {
if (!$subValue && $language && !$language->isDefault() && $field->type instanceof FieldtypeLanguageInterface) {
// multi-language field, sort by the language version
$value = "if({$tableAlias}.data{$language} != '', {$tableAlias}.data{$language}, {$tableAlias}.data)";
} else {
$value = "{$tableAlias}." . ($subValue ? $subValue : "data");
}
}
}
}
}
}
}
}
if ($fc == '-' || $lc == '-') {
$query->orderby("{$value} DESC", true);
} else {
$query->orderby("{$value}", true);
}
}
}