statamic / eloquent-driver

Provides support for storing your Statamic data in a database, rather than flat files.
https://statamic.dev/tips/storing-content-in-a-database
MIT License
104 stars 73 forks source link

An orderable dated collection can't be custom sorted #139

Closed robdekort closed 1 year ago

robdekort commented 1 year ago

When you have a dated orderable collection you can't custom sort it. Well you can in the UI but the order won't persist.

Was talking about this on Discord and it turns out @ryanmitchell already made a PR.

robdekort commented 1 year ago

An update on this. It turns out Ryan fixed a bug that is a bug but not this one.

I'm storing my collection info in flat files but my entries in the database. This seems to be a bad combo.

ryanmitchell commented 1 year ago

So this is an interesting problem to solve.

Rob's collection is flat file, which means his collection tree is also stored flat file and saved by ReorderEntriesController.

His entries are stored in the database, so are reading the order column to get the entry order instead of the tree order, which isnt' being updated as ReorderEntriesController doesn't save the entry.

It feels like we'd need to do something a bit hacky in EntryQueryBuilder like adding the following to handle ordering by a fixed list of ids:

    public function orderBy($column, $direction = 'asc')
    {
        $column = $this->column($column);

        if ($column === 'order') {
            $wheres = collect($this->builder->getQuery()->wheres);
            if ($collection = $wheres->firstWhere('column', 'collection')) {
                $collection = Collection::find($collection['value']);

                if ($collection) {
                    $site = $wheres->firstWhere('column', 'site');
                    $site = $site ? $site['value'] : $collection->sites()->first();
                    $ids = $collection->structure()->in($site)->flattenedPages()->map->id()->map(function($value) { return '"'.$value.'"'; })->join(',');

                    $this->builder->orderByRaw("FIELD(id, {$ids})");
                    return $this;
                }
            }
        }

        return parent::orderBy($column, $direction);
    }

Can you think of a better way @jasonvarga ?

jasonvarga commented 1 year ago

When saving the tree, there's an event listener that is supposed to update the order values for any entries that were moved.

It seems to be working fine, but I haven't tried the flat file / eloquent combo like Rob. I don't see why it wouldn't be doing it, though.

jasonvarga commented 1 year ago

Ok yeah it's a little more obvious now that I've tried it.

It ends up calling CollectionRepository::updateEntryOrder() - but since the collection is in the Stache, it does the Stache specific stuff.

A similar thing would happen if you stored collections in the db but entries in files (but you wouldn't because that's weird).

ryanmitchell commented 1 year ago

Yeah rob causes all sorts of problems. Do we need to move that call to the facade somehow?

robdekort commented 1 year ago

Hey Mitchell! I’m out camping. Stop blaming me! I didn’t even bring my computer.