Skip to content

Commit d349a07

Browse files
committed
Entry type sorting
Fully resolves #9192 Resolves #11335
1 parent f54db11 commit d349a07

File tree

4 files changed

+42
-11
lines changed

4 files changed

+42
-11
lines changed

CHANGELOG-WIP.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
- Live Preview now always shows a “Refresh” button, regardless of whether the preview target has auto-refresh enabled. ([#11160](https://github.com/craftcms/cms/discussions/11160))
2020
- Entry Type condition rules now allow multiple selections. ([#11124](https://github.com/craftcms/cms/pull/11124))
2121
- Element index filters now only show condition rules for the custom fields that are used by the field layouts in the selected source, if a native source is selected. ([#11187](https://github.com/craftcms/cms/discussions/11187))
22+
- It’s now possible to sort entries by their type. ([#9192](https://github.com/craftcms/cms/discussions/9192), [#11335](https://github.com/craftcms/cms/discussions/11335))
2223
- Sites’ Language settings now display the locale IDs as option hints, rather than the languages’ native names. ([#11195](https://github.com/craftcms/cms/discussions/11195))
2324
- Selectize options can now specify searchable `keywords` that won’t be visible in the UI.
2425
- Selectize inputs will now include their options’ values as search keywords.
@@ -27,6 +28,7 @@
2728
- The control panel’s JavaScript queue is now paused when the browser tab isn’t visible. ([#10632](https://github.com/craftcms/cms/issues/10632))
2829
- The `users/create` command now asks whether the user should be activated when saved.
2930
- Deprecation messages are now consistently referred to as “deprecation warnings” in the control panel.
31+
- Callback functions returned by elements’ `sortOptions()`/`defineSortOptions()` methods are now passed a `yii\db\Connection` object as a second argument.
3032

3133
### Removed
3234
- Removed `craft\elements\conditions\entries\EntryTypeCondition::$sectionUid`.

src/base/Element.php

Lines changed: 22 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,7 @@
7373
use yii\base\InvalidConfigException;
7474
use yii\base\NotSupportedException;
7575
use yii\base\UnknownPropertyException;
76+
use yii\db\Connection;
7677
use yii\db\ExpressionInterface;
7778
use yii\validators\BooleanValidator;
7879
use yii\validators\NumberValidator;
@@ -939,6 +940,8 @@ public static function indexHtml(ElementQueryInterface $elementQuery, ?array $di
939940
'tableName' => static::pluralDisplayName(),
940941
];
941942

943+
$db = Craft::$app->getDb();
944+
942945
if (!empty($viewState['order'])) {
943946
// Special case for sorting by structure
944947
if (isset($viewState['order']) && $viewState['order'] === 'structure') {
@@ -958,12 +961,12 @@ public static function indexHtml(ElementQueryInterface $elementQuery, ?array $di
958961
} else {
959962
unset($viewState['order']);
960963
}
961-
} elseif ($orderBy = self::_indexOrderBy($sourceKey, $viewState['order'], $viewState['sort'] ?? 'asc')) {
964+
} elseif ($orderBy = self::_indexOrderBy($sourceKey, $viewState['order'], $viewState['sort'] ?? 'asc', $db)) {
962965
$elementQuery->orderBy($orderBy);
963966

964967
if ((!is_array($orderBy) || !isset($orderBy['score'])) && !empty($viewState['orderHistory'])) {
965968
foreach ($viewState['orderHistory'] as $order) {
966-
if ($order[0] && $orderBy = self::_indexOrderBy($sourceKey, $order[0], $order[1])) {
969+
if ($order[0] && $orderBy = self::_indexOrderBy($sourceKey, $order[0], $order[1], $db)) {
967970
$elementQuery->addOrderBy($orderBy);
968971
} else {
969972
break;
@@ -992,7 +995,7 @@ public static function indexHtml(ElementQueryInterface $elementQuery, ?array $di
992995
}
993996
}
994997

995-
$variables['elements'] = $elementQuery->cache()->all();
998+
$variables['elements'] = $elementQuery->cache()->all($db);
996999

9971000
$template = '_elements/' . $viewState['mode'] . 'view/' . ($includeContainer ? 'container' : 'elements');
9981001

@@ -1554,12 +1557,17 @@ public static function gqlScopesByContext(mixed $context): array
15541557
* @param string $sourceKey
15551558
* @param string $attribute
15561559
* @param string $dir `asc` or `desc`
1560+
* @param Connection $db
15571561
* @return array|ExpressionInterface|false
15581562
*/
1559-
private static function _indexOrderBy(string $sourceKey, string $attribute, string $dir): ExpressionInterface|array|false
1560-
{
1563+
private static function _indexOrderBy(
1564+
string $sourceKey,
1565+
string $attribute,
1566+
string $dir,
1567+
Connection $db,
1568+
): ExpressionInterface|array|false {
15611569
$dir = strcasecmp($dir, 'desc') === 0 ? SORT_DESC : SORT_ASC;
1562-
$columns = self::_indexOrderByColumns($sourceKey, $attribute, $dir);
1570+
$columns = self::_indexOrderByColumns($sourceKey, $attribute, $dir, $db);
15631571

15641572
if ($columns === false || $columns instanceof ExpressionInterface) {
15651573
return $columns;
@@ -1590,10 +1598,15 @@ private static function _indexOrderBy(string $sourceKey, string $attribute, stri
15901598
* @param string $sourceKey
15911599
* @param string $attribute
15921600
* @param int $dir
1601+
* @param Connection $db
15931602
* @return bool|string|array|ExpressionInterface
15941603
*/
1595-
private static function _indexOrderByColumns(string $sourceKey, string $attribute, int $dir): ExpressionInterface|bool|array|string
1596-
{
1604+
private static function _indexOrderByColumns(
1605+
string $sourceKey,
1606+
string $attribute,
1607+
int $dir,
1608+
Connection $db,
1609+
): ExpressionInterface|bool|array|string {
15971610
if (!$attribute) {
15981611
return false;
15991612
}
@@ -1607,7 +1620,7 @@ private static function _indexOrderByColumns(string $sourceKey, string $attribut
16071620
$a = $sortOption['attribute'] ?? $sortOption['orderBy'];
16081621
if ($a === $attribute) {
16091622
if (is_callable($sortOption['orderBy'])) {
1610-
return $sortOption['orderBy']($dir);
1623+
return $sortOption['orderBy']($dir, $db);
16111624
}
16121625
return $sortOption['orderBy'];
16131626
}

src/base/ElementInterface.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -394,8 +394,8 @@ public static function indexHtml(ElementQueryInterface $elementQuery, ?array $di
394394
*
395395
* - `label` – The sort option label
396396
* - `orderBy` – An array, comma-delimited string, or a callback function that defines the columns to order the query by. If set to a callback
397-
* function, the function will be passed a single argument, `$dir`, set to either `SORT_ASC` or `SORT_DESC`, and it should return an array of
398-
* column names or an [[\yii\db\ExpressionInterface]] object.
397+
* function, the function will be passed two arguments: `$dir` (either `SORT_ASC` or `SORT_DESC`) and `$db` (a [[\yii\db\Connection]] object),
398+
* and it should return an array of column names or an [[\yii\db\ExpressionInterface]] object.
399399
* - `attribute` _(optional)_ – The [[tableAttributes()|table attribute]] name that this option is associated
400400
* with (required if `orderBy` is an array or more than one column name)
401401
* - `defaultDir` _(optional)_ – The default sort direction that should be used when sorting by this option

src/elements/Entry.php

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
use craft\behaviors\DraftBehavior;
1515
use craft\behaviors\RevisionBehavior;
1616
use craft\controllers\ElementIndexesController;
17+
use craft\db\FixedOrderExpression;
1718
use craft\db\Table;
1819
use craft\elements\actions\Delete;
1920
use craft\elements\actions\DeleteForSite;
@@ -51,8 +52,10 @@
5152
use craft\validators\DateTimeValidator;
5253
use craft\web\CpScreenResponseBehavior;
5354
use DateTime;
55+
use Illuminate\Support\Collection;
5456
use yii\base\Exception;
5557
use yii\base\InvalidConfigException;
58+
use yii\db\Connection;
5659
use yii\db\Expression;
5760
use yii\web\Response;
5861

@@ -513,6 +516,19 @@ protected static function defineSortOptions(): array
513516
'title' => Craft::t('app', 'Title'),
514517
'slug' => Craft::t('app', 'Slug'),
515518
'uri' => Craft::t('app', 'URI'),
519+
[
520+
'label' => Craft::t('app', 'Entry Type'),
521+
'orderBy' => function(int $dir, Connection $db) {
522+
$entryTypeIds = Collection::make(Craft::$app->getSections()->getAllEntryTypes())
523+
->sort(fn(EntryType $a, EntryType $b) => $dir === SORT_ASC
524+
? $a->name <=> $b->name
525+
: $b->name <=> $a->name)
526+
->map(fn(EntryType $type) => $type->id)
527+
->all();
528+
return new FixedOrderExpression('entries.typeId', $entryTypeIds, $db);
529+
},
530+
'attribute' => 'type',
531+
],
516532
[
517533
'label' => Craft::t('app', 'Post Date'),
518534
'orderBy' => function(int $dir) {

0 commit comments

Comments
 (0)