Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 6 additions & 2 deletions docusaurus/docs/cms/api/document-service.md
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,7 @@ Syntax: `findOne(parameters: Params) => Document`
| `documentId` | Document id | | `ID` |
| [`locale`](/cms/api/document-service/locale#find-one)| Locale of the document to find. | Default locale | String or `undefined` |
| [`status`](/cms/api/document-service/status#find-one) | _If [Draft & Publish](/cms/features/draft-and-publish) is enabled for the content-type_:<br/>Publication status, can be: <ul><li>`'published'` to find only published documents</li><li>`'draft'` to find only draft documents</li></ul> | `'draft'` | `'published'` or `'draft'` |
| [`hasPublishedVersion`](/cms/api/document-service/status#has-published-version) | _If [Draft & Publish](/cms/features/draft-and-publish) is enabled for the content-type_:<br/>Filter by whether the document has a published version. Ignored when not set. | `undefined` | Boolean |
| [`fields`](/cms/api/document-service/fields#findone) | [Select fields](/cms/api/document-service/fields#findone) to return | All fields<br/>(except those not populated by default) | Object |
| [`populate`](/cms/api/document-service/populate) | [Populate](/cms/api/document-service/populate) results with additional fields. | `null` | Object |

Expand Down Expand Up @@ -135,6 +136,7 @@ Syntax: `findFirst(parameters: Params) => Document`
|-----------|-------------|---------|------|
| [`locale`](/cms/api/document-service/locale#find-first) | Locale of the documents to find. | Default locale | String or `undefined` |
| [`status`](/cms/api/document-service/status#find-first) | _If [Draft & Publish](/cms/features/draft-and-publish) is enabled for the content-type_:<br/>Publication status, can be: <ul><li>`'published'` to find only published documents</li><li>`'draft'` to find only draft documents</li></ul> | `'draft'` | `'published'` or `'draft'` |
| [`hasPublishedVersion`](/cms/api/document-service/status#has-published-version) | _If [Draft & Publish](/cms/features/draft-and-publish) is enabled for the content-type_:<br/>Filter by whether the document has a published version. Ignored when not set. | `undefined` | Boolean |
| [`filters`](/cms/api/document-service/filters) | [Filters](/cms/api/document-service/filters) to use | `null` | Object |
| [`fields`](/cms/api/document-service/fields#findfirst) | [Select fields](/cms/api/document-service/fields#findfirst) to return | All fields<br/>(except those not populate by default) | Object |
| [`populate`](/cms/api/document-service/populate) | [Populate](/cms/api/document-service/populate) results with additional fields. | `null` | Object |
Expand Down Expand Up @@ -225,6 +227,7 @@ Syntax: `findMany(parameters: Params) => Document[]`
|-----------|-------------|---------|------|
| [`locale`](/cms/api/document-service/locale#find-many) | Locale of the documents to find. | Default locale | String or `undefined` |
| [`status`](/cms/api/document-service/status#find-many) | _If [Draft & Publish](/cms/features/draft-and-publish) is enabled for the content-type_:<br/>Publication status, can be: <ul><li>`'published'` to find only published documents</li><li>`'draft'` to find only draft documents</li></ul> | `'draft'` | `'published'` or `'draft'` |
| [`hasPublishedVersion`](/cms/api/document-service/status#has-published-version) | _If [Draft & Publish](/cms/features/draft-and-publish) is enabled for the content-type_:<br/>Filter by whether the document has a published version. Ignored when not set. | `undefined` | Boolean |
| [`filters`](/cms/api/document-service/filters) | [Filters](/cms/api/document-service/filters) to use | `null` | Object |
| [`fields`](/cms/api/document-service/fields#findmany) | [Select fields](/cms/api/document-service/fields#findmany) to return | All fields<br/>(except those not populate by default) | Object |
| [`populate`](/cms/api/document-service/populate) | [Populate](/cms/api/document-service/populate) results with additional fields. | `null` | Object |
Expand Down Expand Up @@ -732,12 +735,13 @@ Syntax: `count(parameters: Params) => number`
|-----------|-------------|---------|------|
| [`locale`](/cms/api/document-service/locale#count) | Locale of the documents to count | Default locale | String or `null` |
| [`status`](/cms/api/document-service/status#count) | _If [Draft & Publish](/cms/features/draft-and-publish) is enabled for the content-type_:<br/>Publication status, can be: <ul><li>`'published'` to find only published documents </li><li>`'draft'` to find draft documents (will return all documents)</li></ul> | `'draft'` | `'published'` or `'draft'` |
| [`hasPublishedVersion`](/cms/api/document-service/status#has-published-version) | _If [Draft & Publish](/cms/features/draft-and-publish) is enabled for the content-type_:<br/>Filter by whether the document has a published version. Ignored when not set. | `undefined` | Boolean |
| [`filters`](/cms/api/document-service/filters) | [Filters](/cms/api/document-service/filters) to use | `null` | Object |

:::note
Since published documents necessarily also have a draft counterpart, a published document is still counted as having a draft version.

This means that counting with the `status: 'draft'` parameter still returns the total number of documents matching other parameters, even if some documents have already been published and are not displayed as "draft" or "modified" in the Content Manager anymore. There currently is no way to prevent already published documents from being counted.
This means that counting with the `status: 'draft'` parameter still returns the total number of documents matching other parameters, even if some documents have already been published and are not displayed as "draft" or "modified" in the Content Manager anymore. To count only documents that have never been published, use the [`hasPublishedVersion`](/cms/api/document-service/status#has-published-version) parameter.
:::

#### Examples
Expand All @@ -746,7 +750,7 @@ This means that counting with the `status: 'draft'` parameter still returns the

##### Generic example

If no parameter is passed, the `count()` method the total number of documents for the default locale:
If no parameter is passed, the `count()` method returns the total number of documents for the default locale:
<ApiCall>

<Request>
Expand Down
142 changes: 137 additions & 5 deletions docusaurus/docs/cms/api/document-service/status.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
---
title: Using Draft & Publish with the Document Service API
description: Use Strapi's Document Service API to return either the draft or the published version of a document
description: Use Strapi's Document Service API to return draft or published versions of a document and filter by publication history with hasPublishedVersion.
displayed_sidebar: cmsSidebar
sidebar_label: Status
tags:
Expand All @@ -12,18 +12,20 @@ tags:
- findOne()
- findMany()
- findFirst()
- hasPublishedVersion
- published version
- status

---

# Document Service API: Usage with Draft & Publish

By default the [Document Service API](/cms/api/document-service) returns the draft version of a document when the [Draft & Publish](/cms/features/draft-and-publish) feature is enabled. This page describes how to use the `status` parameter to:
By default the [Document Service API](/cms/api/document-service) returns the draft version of a document when the [Draft & Publish](/cms/features/draft-and-publish) feature is enabled. This page describes how to use the `status` and `hasPublishedVersion` parameters to:

- return the published version of a document,
- count documents depending on their status,
- and directly publish a document while creating it or updating it.
- filter documents by whether they have ever been published,
- count documents depending on their status,
- directly publish a document while creating it or updating it.

:::note
Passing `{ status: 'draft' }` to a Document Service API query returns the same results as not passing any `status` parameter.
Expand Down Expand Up @@ -152,7 +154,7 @@ const publishedCount = await strapi.documents("api::restaurant.restaurant").coun
:::note
Since published documents necessarily also have a draft counterpart, a published document is still counted as having a draft version.

This means that counting with the `status: 'draft'` parameter still returns the total number of documents matching other parameters, even if some documents have already been published and are not displayed as "draft" or "modified" in the Content Manager anymore. There currently is no way to prevent already published documents from being counted.
This means that counting with the `status: 'draft'` parameter still returns the total number of documents matching other parameters, even if some documents have already been published and are not displayed as "draft" or "modified" in the Content Manager anymore. To count only documents that have never been published, use the [`hasPublishedVersion`](#has-published-version) parameter.
:::

## Create a draft and publish it {#create}
Expand Down Expand Up @@ -224,3 +226,133 @@ await strapi.documents('api::restaurant.restaurant').update({
</Response>
</ApiCall>

## Filter by publication history with `hasPublishedVersion` <NewBadge /> {#has-published-version}

The `hasPublishedVersion` parameter filters documents by whether a published version exists. Use `hasPublishedVersion` with `status: 'draft'` to distinguish documents that have never been published from drafts of already-published documents.

The parameter accepts a boolean (`true` or `false`) and works with `findOne()`, `findFirst()`, `findMany()`, and `count()`.

### Find never-published documents

Pass `hasPublishedVersion: false` with `status: 'draft'` to return only documents that have never been published:

<ApiCall noSideBySide>
<Request title="Example request">

```js
const documents = await strapi.documents("api::restaurant.restaurant").findMany({
status: 'draft',
hasPublishedVersion: false,
});
```

</Request>

<Response title="Example response">

```js
[
{
documentId: "ln1gkzs6ojl9d707xn6v86mw",
name: "Restaurant B",
publishedAt: null, // never published
locale: "en",
// …
},
// … other never-published documents
]
```

</Response>
</ApiCall>

### Find drafts of published documents

Pass `hasPublishedVersion: true` with `status: 'draft'` to return only drafts of documents that have been published at least once:

<ApiCall noSideBySide>
<Request title="Example request">

```js
const documents = await strapi.documents("api::restaurant.restaurant").findMany({
status: 'draft',
hasPublishedVersion: true,
});
```

</Request>

<Response title="Example response">

```js
[
{
documentId: "a1b2c3d4e5f6g7h8i9j0klm",
name: "Biscotte Restaurant",
publishedAt: null, // draft version is returned, but a published version exists
locale: "en",
// …
},
// …
]
```

</Response>
</ApiCall>

:::note
Because the draft version is returned, `publishedAt` is `null` even when a published version exists.
:::

### Count never-published documents

Combine `hasPublishedVersion: false` with `count()` to count documents that have never been published:

```js
const neverPublishedCount = await strapi.documents("api::restaurant.restaurant").count({
status: 'draft',
hasPublishedVersion: false,
});
```

### Combine with other parameters

`hasPublishedVersion` can be combined with [`locale`](/cms/api/document-service/locale), [`filters`](/cms/api/document-service/filters), and [`populate`](/cms/api/document-service/populate):

<ApiCall noSideBySide>
<Request title="Example request">

```js
const documents = await strapi.documents("api::restaurant.restaurant").findMany({
status: 'draft',
hasPublishedVersion: false,
locale: 'en',
filters: {
name: { $startsWith: 'Pizzeria' },
},
});
```

</Request>

<Response title="Example response">

```js
[
{
documentId: "j9k8l7m6n5o4p3q2r1s0tuv",
name: "Pizzeria Napoli",
publishedAt: null,
locale: "en",
// …
},
]
```

</Response>
</ApiCall>

:::tip
When `hasPublishedVersion` is used with [`populate`](/cms/api/document-service/populate), the filter also applies to populated relations. Each related document is filtered based on whether a published version exists for it.
:::

46 changes: 46 additions & 0 deletions docusaurus/docs/cms/api/graphql.md
Original file line number Diff line number Diff line change
Expand Up @@ -425,6 +425,52 @@ query Query($status: PublicationStatus) {
}
```

### Filter by publication history with `hasPublishedVersion` <NewBadge /> {#haspublishedversion}

If the [Draft & Publish](/cms/features/draft-and-publish) feature is enabled for the content-type, you can add a `hasPublishedVersion` parameter to queries to filter documents based on whether they have a published version.

Use `hasPublishedVersion` with `status: DRAFT` to distinguish between documents that have never been published and drafts of already-published documents:

```graphql title="Example: Fetch only never-published drafts"
{
restaurants(status: DRAFT, hasPublishedVersion: false) {
documentId
name
publishedAt
}
}
```

```graphql title="Example: Fetch drafts of already-published documents"
{
restaurants(status: DRAFT, hasPublishedVersion: true) {
documentId
name
publishedAt
}
}
```

`hasPublishedVersion` also works with Relay-style connection queries:

```graphql title="Example: Count never-published drafts with Relay-style query"
{
restaurants_connection(status: DRAFT, hasPublishedVersion: false) {
nodes {
documentId
name
}
pageInfo {
total
}
}
}
```

:::tip
When `hasPublishedVersion` is used with queries that include relations, the filter also applies to related documents. Each related document is filtered based on whether a published version exists for it.
:::

## Aggregations

Aggregations can be used to compute metrics such as counts, sums, or grouped totals without fetching every document individually. Aggregations are exposed through <ExternalLink to="https://www.apollographql.com/docs/technotes/TN0029-relay-style-connections/" text="Relay-style"/> connection queries: every collection type includes an `aggregate` field under its `<plural>_connection` query.
Expand Down
1 change: 1 addition & 0 deletions docusaurus/docs/cms/api/rest/parameters.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ The following API parameters are available:
| `filters` | Object | [Filter the response](/cms/api/rest/filters) |
| `locale` | String | [Select a locale](/cms/api/rest/locale) |
| `status` | String | [Select the Draft & Publish status](/cms/api/rest/status) |
| `hasPublishedVersion` | Boolean | [Filter by whether the document has a published version](/cms/api/rest/status#haspublishedversion-) |
| `populate` | String or Object | [Populate relations, components, or dynamic zones](/cms/api/rest/populate-select#population) |
| `fields` | Array | [Select only specific fields to display](/cms/api/rest/populate-select#field-selection) |
| `sort` | String or Array | [Sort the response](/cms/api/rest/sort-pagination.md#sorting) |
Expand Down
Loading
Loading