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 74 forks source link

Can't use status filter for Graphql #347

Closed thomas4Bitcraft closed 2 weeks ago

thomas4Bitcraft commented 2 weeks ago

Bug description

I have just recently switched to the eloquent driver. The problem is, that previously I fetched existing entries for my preview-page like this:

query page {
  entry(
    collection: "pages"
    id: "c2980164-0e9b-432b-9658-56d30775ca0d",
    , filter: {status: {regex: "(draft|published|scheduled)"}}
  ) {
    ... on Entry_Pages_Page {
      id
      status
    }
  }
}

But as I saw on this issue the status filter only accepts a filter like status: {equals: "draft"}, which means I would have to make 3 different requests to fetch a single page. Is there any other possibility to handle different status values for collections?

How to reproduce

Switch to eloquent-driver and use the grapqhl status filter

Logs

No response

Environment

Environment
Application Name: Website
Laravel Version: 10.48.20
PHP Version: 8.2.7
Composer Version: 2.7.7
Environment: local
Debug Mode: ENABLED
URL: /
Maintenance Mode: OFF

Cache
Config: NOT CACHED
Events: NOT CACHED
Routes: NOT CACHED
Views: CACHED

Drivers
Broadcasting: log
Cache: file
Database: mysql
Logs: stack / single
Mail: smtp
Queue: sync
Session: file

Sentry
Enabled: MISSING DSN
Environment: local
Laravel SDK Version: 3.8.2
PHP SDK Version: 3.22.1
Release: NOT SET
Sample Rate Errors: 100%
Sample Rate Performance Monitoring: 0%
Sample Rate Profiling: NOT SET
Send Default PII: DISABLED

Statamic
Addons: 5
Sites: 12 (de, it, en, and 9 more)
Stache Watcher: Disabled
Static Caching: Disabled
Version: 5.23.0 PRO

Statamic Addons
bitcraft/form-webhook: dev-production
bitcraft/page-generator: dev-production
bitcraft/simple-seo: dev-production
ndx/statamic-bard-color-picker: 2.0.0
statamic/eloquent-driver: 4.14.0

Statamic Eloquent Driver
Asset Containers: file
Assets: file
Blueprints: eloquent
Collection Trees: eloquent
Collections: eloquent
Entries: eloquent
Forms: eloquent
Global Sets: eloquent
Global Variables: eloquent
Navigation Trees: eloquent
Navigations: eloquent
Revisions: eloquent
Sites: eloquent
Taxonomies: eloquent
Terms: eloquent
Tokens: eloquent

Additional details

No response

ryanmitchell commented 2 weeks ago

Are you able to recreate this issue using flat files in Statamic 5? I don't think we handle status any differently to how core/cms does it.

thomas4Bitcraft commented 2 weeks ago

@ryanmitchell It worked before switching to eloquent-driver and it was already running with Statamic 5.

When switching back to flat files it works as well.

'entries' => [
        'driver' => 'file',
        'model' => \Statamic\Eloquent\Entries\UuidEntryModel::class,
        'entry' => \Statamic\Eloquent\Entries\Entry::class,
        'map_data_to_columns' => false,
    ],
ryanmitchell commented 2 weeks ago

I'd be inclined to say the fact its working in flat files is an oversight, as its still calling ->where('status') behind the scenes which is deprecated, it should be using whereStatus() to provide the correct logic in v5+.

I'll pick it up with the core team and let you know.

thomas4Bitcraft commented 2 weeks ago

Alright thank you very much for the quick clarification!

duncanmcclean commented 2 weeks ago

But as I saw on https://github.com/statamic/eloquent-driver/issues/289 the status filter only accepts a filter like status: {equals: "draft"}, which means I would have to make 3 different requests to fetch a single page. Is there any other possibility to handle different status values for collections?

That's correct.

As of Statamic 5, it's only possible to query a single status at a time. We included some notes about this in the v5 upgrade guide:

CleanShot 2024-08-30 at 13 30 07

Out of curiosity, what's your use case for needing published, draft and scheduled entries in one page?

It worked before switching to eloquent-driver and it was already running with Statamic 5.

This is only working with flat-files at the moment, in order to provide backwards compatibility, which'll be removed in Statamic 6.

thomas4Bitcraft commented 2 weeks ago

@duncanmcclean @ryanmitchell We're using Statamic as a Headless CMS with a preview site where all entries should be viewable, regardless of their status. This means we need to display content in draft, scheduled, or published states seamlessly. Unfortunately, the current live preview setup falls short, making it nearly unusable for our needs. Here’s why:

A content editor creates a page and wants to preview it before publishing -> They need a live preview in draft mode. The content editor publishes the page but sets the date for it to go live a week later -> They need a live preview in scheduled mode. A week later, the page should be accessible without any status filter -> They need a live preview with no status or in published mode. Without support for all three states (draft, scheduled, published), the preview functionality becomes frustrating for content editors, leading to bug reports on our end.

Previously, we handled this by calling entries for the preview page like this:

const {data, error} = await useAsyncData(
    `page-${region}-${locale}-${slug}`,
    async () => {
      const gqlInstance = useGql();
      let page = await gqlInstance('page', {slug: slug, site: `${region}-${locale}`, status: "published|draft|scheduled"});

      return { page };
    }
);

Now, we’re forced to do something like this:


const {data, error} = await useAsyncData(
    `page-${region}-${locale}-${slug}`,
    async () => {
      const gqlInstance = useGql();
      let page = await gqlInstance('page', {slug: slug, site: `${region}-${locale}`, status: "published"});

      if (!page.entry) {
        page = await gqlInstance('page', {slug: slug, site: `${region}-${locale}`, status: "draft"});
      }

      if (!page.entry) {
        page = await gqlInstance('page', {slug: slug, site: `${region}-${locale}`, status: "scheduled"});
      }

      return { page };
    }
);

This approach is not only cumbersome but also significantly slower. I can’t rely on the draft filter alone, as that would prevent me from accessing published or scheduled entries.

Why was this change implemented? It feels like a regression, and I doubt we're the only ones who were relying on this functionality. This modification seems to have removed features that were previously working perfectly.

jasonvarga commented 1 week ago

So what you really need is to just avoid querying by status at all?

It looks like you never really cared if the entries were "published or draft or scheduled" ... you just wanted them all, as if there was no status filter applied at all.

jasonvarga commented 1 week ago

Available in https://github.com/statamic/cms/pull/10752 via filter: {status:"any"}

thomas4Bitcraft commented 1 week ago

@jasonvarga Yes that's perfect 🙂 The only thing that should be considered is, that if {status:"any"} is set the retrieved entry should output the draft version of the model.