diff --git a/backport-changelog/6.9/9299.md b/backport-changelog/6.9/9299.md
new file mode 100644
index 00000000000000..033dd6d234ee72
--- /dev/null
+++ b/backport-changelog/6.9/9299.md
@@ -0,0 +1,3 @@
+https://github.com/WordPress/wordpress-develop/pull/9299
+
+* https://github.com/WordPress/gutenberg/pull/70585
\ No newline at end of file
diff --git a/docs/reference-guides/core-blocks.md b/docs/reference-guides/core-blocks.md
index 259e40e859aaf3..630bcdd574e9a0 100644
--- a/docs/reference-guides/core-blocks.md
+++ b/docs/reference-guides/core-blocks.md
@@ -624,7 +624,7 @@ Display the publish date for an entry such as a post or page. ([Source](https://
- **Name:** core/post-date
- **Category:** theme
- **Supports:** color (background, gradients, link, text), interactivity (clientNavigation), spacing (margin, padding), typography (fontSize, lineHeight), ~~html~~
-- **Attributes:** displayType, format, isLink, textAlign
+- **Attributes:** datetime, format, isLink, textAlign
## Excerpt
diff --git a/lib/compat/wordpress-6.9/post-data-block-bindings.php b/lib/compat/wordpress-6.9/post-data-block-bindings.php
new file mode 100644
index 00000000000000..d86af59289ad28
--- /dev/null
+++ b/lib/compat/wordpress-6.9/post-data-block-bindings.php
@@ -0,0 +1,73 @@
+ "foo" ).
+ * @param WP_Block $block_instance The block instance.
+ * @return mixed The value computed for the source.
+ */
+function gutenberg_block_bindings_post_data_get_value( array $source_args, $block_instance ) {
+ if ( empty( $source_args['key'] ) ) {
+ return null;
+ }
+
+ if ( empty( $block_instance->context['postId'] ) ) {
+ return null;
+ }
+ $post_id = $block_instance->context['postId'];
+
+ // If a post isn't public, we need to prevent unauthorized users from accessing the post data.
+ $post = get_post( $post_id );
+ if ( ( ! is_post_publicly_viewable( $post ) && ! current_user_can( 'read_post', $post_id ) ) || post_password_required( $post ) ) {
+ return null;
+ }
+
+ if ( 'date' === $source_args['key'] ) {
+ return esc_attr( get_the_date( 'c', $post_id ) );
+ }
+
+ if ( 'modified' === $source_args['key'] ) {
+ // Only return the modified date if it is later than the publishing date.
+ if ( get_the_modified_date( 'Ymdhi', $post_id ) > get_the_date( 'Ymdhi', $post_id ) ) {
+ return esc_attr( get_the_modified_date( 'c', $post_id ) );
+ } else {
+ return '';
+ }
+ }
+}
+
+/**
+ * Registers Post Data source in the block bindings registry.
+ *
+ * @since 6.9.0
+ * @access private
+ */
+function gutenberg_register_block_bindings_post_data_source() {
+ if ( get_block_bindings_source( 'core/post-data' ) ) {
+ // The source is already registered.
+ return;
+ }
+
+ register_block_bindings_source(
+ 'core/post-data',
+ array(
+ 'label' => _x( 'Post Data', 'block bindings source' ),
+ 'get_value_callback' => 'gutenberg_block_bindings_post_data_get_value',
+ 'uses_context' => array( 'postId' ),
+ )
+ );
+}
+
+add_action( 'init', 'gutenberg_register_block_bindings_post_data_source' );
diff --git a/lib/load.php b/lib/load.php
index fe896202319b24..535cef389cc15e 100644
--- a/lib/load.php
+++ b/lib/load.php
@@ -39,6 +39,7 @@ function gutenberg_is_experiment_enabled( $name ) {
require __DIR__ . '/compat/wordpress-6.8/rest-api.php';
// WordPress 6.9 compat.
+ require __DIR__ . '/compat/wordpress-6.9/post-data-block-bindings.php';
require __DIR__ . '/compat/wordpress-6.9/rest-api.php';
require __DIR__ . '/compat/wordpress-6.9/class-gutenberg-hierarchical-sort.php';
diff --git a/packages/block-editor/src/components/publish-date-time-picker/README.md b/packages/block-editor/src/components/publish-date-time-picker/README.md
index a7d92250c7cb0f..3acd340b557705 100644
--- a/packages/block-editor/src/components/publish-date-time-picker/README.md
+++ b/packages/block-editor/src/components/publish-date-time-picker/README.md
@@ -32,6 +32,7 @@ const MyDateTimePicker = () => {
currentDate={ date }
onChange={ ( newDate ) => setDate( newDate ) }
onClose={ onClose }
+ title={ __( 'Select post date' ) }
/>
) }
/>
@@ -44,6 +45,14 @@ const MyDateTimePicker = () => {
`PublishDateTimePicker` supports all of the props that
[`DateTimePicker`](/packages/components/src/date-time#Props) supports, plus:
+### title
+
+The title displayed in the header of the popover that contains the `DateTimePicker`.
+
+- Type: `String`
+- Required: No
+- Default: `Publish`
+
### onClose
Called when the user presses the close button.
diff --git a/packages/block-editor/src/components/publish-date-time-picker/index.js b/packages/block-editor/src/components/publish-date-time-picker/index.js
index eeaa5b2daad6fa..d18901f2ef8636 100644
--- a/packages/block-editor/src/components/publish-date-time-picker/index.js
+++ b/packages/block-editor/src/components/publish-date-time-picker/index.js
@@ -18,6 +18,7 @@ export function PublishDateTimePicker(
showPopoverHeaderActions,
isCompact,
currentDate,
+ title,
...additionalProps
},
ref
@@ -33,7 +34,7 @@ export function PublishDateTimePicker(
return (
{
+ if ( datetime === undefined ) {
+ __unstableMarkNextChangeAsNotPersistent();
+ setAttributes( { datetime: new Date() } );
+ }
+ }, [ datetime ] );
+
const isDescendentOfQueryLoop = Number.isFinite( queryId );
const dateSettings = getDateSettings();
const [ siteFormat = dateSettings.formats.date ] = useEntityProp(
@@ -73,12 +90,6 @@ export default function PostDateEdit( {
'site',
'time_format'
);
- const [ date, setDate ] = useEntityProp(
- 'postType',
- postTypeSlug,
- displayType,
- postId
- );
const postType = useSelect(
( select ) =>
@@ -88,20 +99,15 @@ export default function PostDateEdit( {
[ postTypeSlug ]
);
- const dateLabel =
- displayType === 'date' ? __( 'Post Date' ) : __( 'Post Modified Date' );
-
- let postDate = date ? (
-
\ No newline at end of file
diff --git a/test/e2e/specs/editor/various/__snapshots__/Inserting-blocks-firefox-webkit-inserts-p-59603-ragging-and-dropping-from-the-global-inserter-1-webkit.txt b/test/e2e/specs/editor/various/__snapshots__/Inserting-blocks-firefox-webkit-inserts-p-59603-ragging-and-dropping-from-the-global-inserter-1-webkit.txt
index 753c30a0926707..4a3299dafa57c1 100644
--- a/test/e2e/specs/editor/various/__snapshots__/Inserting-blocks-firefox-webkit-inserts-p-59603-ragging-and-dropping-from-the-global-inserter-1-webkit.txt
+++ b/test/e2e/specs/editor/various/__snapshots__/Inserting-blocks-firefox-webkit-inserts-p-59603-ragging-and-dropping-from-the-global-inserter-1-webkit.txt
@@ -14,6 +14,6 @@
-
+
\ No newline at end of file
diff --git a/test/integration/fixtures/blocks/core__post-date.json b/test/integration/fixtures/blocks/core__post-date.json
index ec8dc784b3403b..d6ad7d5a101d39 100644
--- a/test/integration/fixtures/blocks/core__post-date.json
+++ b/test/integration/fixtures/blocks/core__post-date.json
@@ -4,7 +4,16 @@
"isValid": true,
"attributes": {
"isLink": false,
- "displayType": "date"
+ "metadata": {
+ "bindings": {
+ "datetime": {
+ "source": "core/post-data",
+ "args": {
+ "key": "date"
+ }
+ }
+ }
+ }
},
"innerBlocks": []
}
diff --git a/test/integration/fixtures/blocks/core__post-date.serialized.html b/test/integration/fixtures/blocks/core__post-date.serialized.html
index 56357e03f49902..8c2f8584aa5c46 100644
--- a/test/integration/fixtures/blocks/core__post-date.serialized.html
+++ b/test/integration/fixtures/blocks/core__post-date.serialized.html
@@ -1 +1 @@
-
+
diff --git a/test/integration/fixtures/blocks/core__post-date__deprecated-v2.html b/test/integration/fixtures/blocks/core__post-date__deprecated-v2.html
new file mode 100644
index 00000000000000..fe543b26ed7d96
--- /dev/null
+++ b/test/integration/fixtures/blocks/core__post-date__deprecated-v2.html
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/test/integration/fixtures/blocks/core__post-date__deprecated-v2.json b/test/integration/fixtures/blocks/core__post-date__deprecated-v2.json
new file mode 100644
index 00000000000000..e2489548853d64
--- /dev/null
+++ b/test/integration/fixtures/blocks/core__post-date__deprecated-v2.json
@@ -0,0 +1,21 @@
+[
+ {
+ "name": "core/post-date",
+ "isValid": true,
+ "attributes": {
+ "isLink": false,
+ "className": "wp-block-post-date__modified-date",
+ "metadata": {
+ "bindings": {
+ "datetime": {
+ "source": "core/post-data",
+ "args": {
+ "key": "modified"
+ }
+ }
+ }
+ }
+ },
+ "innerBlocks": []
+ }
+]
diff --git a/test/integration/fixtures/blocks/core__post-date__deprecated-v2.parsed.json b/test/integration/fixtures/blocks/core__post-date__deprecated-v2.parsed.json
new file mode 100644
index 00000000000000..5ff0a9ea999ef1
--- /dev/null
+++ b/test/integration/fixtures/blocks/core__post-date__deprecated-v2.parsed.json
@@ -0,0 +1,11 @@
+[
+ {
+ "blockName": "core/post-date",
+ "attrs": {
+ "displayType": "modified"
+ },
+ "innerBlocks": [],
+ "innerHTML": "",
+ "innerContent": []
+ }
+]
diff --git a/test/integration/fixtures/blocks/core__post-date__deprecated-v2.serialized.html b/test/integration/fixtures/blocks/core__post-date__deprecated-v2.serialized.html
new file mode 100644
index 00000000000000..8244aa86f5ea01
--- /dev/null
+++ b/test/integration/fixtures/blocks/core__post-date__deprecated-v2.serialized.html
@@ -0,0 +1 @@
+
diff --git a/test/integration/fixtures/blocks/core__query__deprecated-3.json b/test/integration/fixtures/blocks/core__query__deprecated-3.json
index d41ce2c5c826b7..d3ed27ec4fac33 100644
--- a/test/integration/fixtures/blocks/core__query__deprecated-3.json
+++ b/test/integration/fixtures/blocks/core__query__deprecated-3.json
@@ -68,7 +68,16 @@
"isValid": true,
"attributes": {
"isLink": false,
- "displayType": "date"
+ "metadata": {
+ "bindings": {
+ "datetime": {
+ "source": "core/post-data",
+ "args": {
+ "key": "date"
+ }
+ }
+ }
+ }
},
"innerBlocks": []
},
diff --git a/test/integration/fixtures/blocks/core__query__deprecated-3.serialized.html b/test/integration/fixtures/blocks/core__query__deprecated-3.serialized.html
index 86c87dde71c3bd..e6346c144a66ff 100644
--- a/test/integration/fixtures/blocks/core__query__deprecated-3.serialized.html
+++ b/test/integration/fixtures/blocks/core__query__deprecated-3.serialized.html
@@ -3,7 +3,7 @@
-
+