Custom Preview Links not fully filterable
yoadsn opened this issue · 34 comments
I am opening this to point at #4555.
I believe the problem is not solved and should be reopened.
All details are in my last comment on that thread.
Completely agree. The preview links should be fully filterable with the preview_post_link
filter. I'm not sure why that went away, or why the "autosaves" solution was considered sufficient.
Hi there, I'll close this and reopen #4555 and we can continue the discussion there.
Reopened the issue for @danielbachhuber and @yoadsn, see #4555
@danielbachhuber Recap of the problem analysis as described on #4555.
As noted - preview_post_link
is useful and should be backward compatible using Gutenberg.
I believe the fix in https://core.trac.wordpress.org/ticket/44180 is not complete.
Here is the scenario I am facing and my analysis.
-
WP admin is accessed and used from domain A
-
WP frontend is on domain B using reverse proxy - this is very common when wanting to host WP on a sub folder of a TLD
(But this senario I believe applies also to any case where home_url !== site_url or in fact anytime the preview url needs to be filterable) -
Using Gutenberg for a draft post.
-
After an autosave - the autosave endpoint return a
preview_url
as you have mentioned above.
The reducer here would take thepreview_link
as is and use that for the preview button.
As you have shown on the screenshots of the PR #6682 - hovering over the "preview" button at this point would show the url as it was returned from the autosave endpoint.
This URL was generated here and using theget_preview_post_link
which makes the preview link filterable. -
If now the "preview" button is clicked or the "save" link is clicked. The clien would hit the posts controller and get the payload which includes the post's
link
.
This link is generated here and is using theget_permalink
function.
The permalink is filterable but in my scenario preview link need to work onsite_url
and not thehome_url
- permalinks should always be onhome_url
. (for the preview to work, all admin auth is againstsite_url
).
The reason this works is that the reducer mentioned above applies the{ preview: true }
query param on the client.
This means there is an inconsistent behaviour between the way preview links are generated form the autosave controller and on the client.
Anyway - hovering over the button would now show a different URL (assuming site_url
!== home_url
).
I hope I analyzed the situation correctly - I'm jst a user of WP so first time looking at the source codes.
I might be able to work around this problem if I will filter the permalink and somehow know that it is going to be used on the "editor" and not on the frontend - but this is not possible since the posts controller does not identify itself to the call in anyway.
Thoughts?
That's a really painful bug, and suffer from a similar use case described by @yoadsn .
We use a reverse proxy to serve our legacy app and wordpress on the same domain. We need a specific url starting with a prefix that can be used by AWS Cloudfront to select the proper backend.
I'm really looking forward a solution.
@yoadsn Sorry for the late reply here. Your analysis seems reasonable although I'm not quite sure what the fix should be.
@danielbachhuber Of course I may be talking none-sense here but I would keep the preview link generation logic on the backend as much as possible and ensure it uses standard filterable generation methods like get_preview_post_link
.
So, when hitting the "posts" controller - perhaps there will be a way to also ask for the "preview link" on top of the "link" (=permalink). This way, the client reducer can use that returned value instead of generating a preview link indirectly from the permalink.
I know the request can contain a fields
parameter but I'm unsure how easy it is to extend the schema for a post to include such optional field.
So in the controller - similar to this field data prep:
if ( in_array( 'link', $fields, true ) ) {
$data['link'] = get_permalink( $post->ID );
}
There will be: (Excuse my lack of source knowledge here - waving hands)
if ( in_array( 'preview_link', $fields, true ) ) {
$parent_id = wp_is_post_autosave( $post );
$preview_post_id = false === $parent_id ? $post->ID : $parent_id;
$preview_query_args = array();
if ( false !== $parent_id ) {
$preview_query_args['preview_id'] = $parent_id;
$preview_query_args['preview_nonce'] = wp_create_nonce( 'post_preview_' . $parent_id );
}
$data['preview_link'] = get_preview_post_link( $preview_post_id , $preview_query_args );
}
Quite similar to how the autosaves controller does it.
Hopefully this makes sense - reimplementing the link filtering on the client just sounds crazy to me and a bad call in terms of business logic encapsulation.
I would keep the preview link generation logic on the backend as much as possible and ensure it uses standard filterable generation methods like
get_preview_post_link
.
I agree with this.
So, when hitting the "posts" controller - perhaps there will be a way to also ask for the "preview link" on top of the "link" (=permalink). This way, the client reducer can use that returned value instead of generating a preview link indirectly from the permalink.
Right. The challenge is that I'm not sure, conceptually, how well this fits with the Posts Controller. Currently, the preview_link
is the responsibility of the Autosaves Controller, which makes more conceptual sense — you're previewing a work-in-progress version of the post. At first glance, it doesn't seem like this fits cleanly with the Posts Controller.
But, maybe the simplest thing to do is simply add preview_link
to the Posts Controller and be done with it.
@aduth or @azaozz have spent a ton more time in this area and might have other thoughts.
Makes sense.
My 2 cents - Conceptually this API divides responsibility between "AutoSave" and "Save".
Although differences do exist, the use case is the same - modifying post state.
So if I would think this through I think I arrive at a conclusion that "Auto" is in fact a client concern and not a server concern. The Server API should have never indicate any difference between the two but rather facilitate either state mutations (Before publish and after publish) regardless of "auto" having . any meaning.
Given this is how the API is architected - Probably best to extend the post controller then overload the "autosave" controller with generic "saving" and "loading" of documents in any state.
As a bonus, the server can decide a "preview link" to a published version is just "the link" without the client caring.
There's a fair bit more context to the decision of creating a separate autosaves endpoint at:
https://core.trac.wordpress.org/ticket/43316#comment:62
...including considerations around revisions and the capabilities of the server in handling fields therein.
In Gutenberg, it doesn't really make much a difference whether it be one or separate endpoints, as long as we could communicate intent of the nature of the save as being of this more transient sort (i.e. not necessarily needing a full revision history).
Related: #9151 (comment)
As far as actionability: It seems there's not much reluctance about including preview_link
in the return response of a "full" post save (i.e. on the posts controller). If I recall correctly, this had also been the behavior in earlier implementations (#6882). May I suggest a next step be to propose this for consideration in an upcoming REST API meeting and/or create a Trac ticket to introduce this new field?
As far as I can tell, there would actually be no change required in Gutenberg for this to start being leveraged, since the current behavior is to use preview_link
from a response when and if it's available:
gutenberg/packages/editor/src/store/reducer.js
Lines 762 to 769 in 5b3b3ab
Hello,
I'm reading this thread and not sure what the next steps are. I rewrite preview links from: /?p=8792&preview=true
to /previews/?p=8792&preview=true
. For draft posts, this works from the posts index, but while editing, my hook for preview_post_link
never gets called. Is there a way to do this?
To add the preview_link
to the REST response you can use this snippet:
/**
* Includes preview link in post data for a response.
*
* @param \WP_REST_Response $response The response object.
* @param \WP_Post $post Post object.
* @return \WP_REST_Response The response object.
*/
function my_include_preview_link_in_rest_response( $response, $post ) {
if ( 'draft' === $post->post_status ) {
$response->data['preview_link'] = get_preview_post_link( $post );
}
return $response;
}
add_filter( 'rest_prepare_post', 'my_include_preview_link_in_rest_response', 10, 2 );
add_filter( 'rest_prepare_page', 'my_include_preview_link_in_rest_response', 10, 2 );
See also https://core.trac.wordpress.org/ticket/44180 for a similar version.
As far as I can tell, there would actually be no change required in Gutenberg for this to start being leveraged, since the current behavior is to use
preview_link
from a response when and if it's available:
@aduth You're correct. The only thing is that REQUEST_POST_UPDATE_SUCCESS
isn't called for the initial editor load when the data is preloaded. Wondering if we should change that.
There's still no filter to change the Preview link that is on the right side of Gutenberg.
Is there any news on this at all? :)
I'm having the same problem and """solved""" it with a workaround (notice the triple double quotes). Maybe it could help some people until there's an official solution. Feel free to use and/or improve this workaround.
Add this in your theme's functions.php
// workaround script until there's an official solution for https://github.com/WordPress/gutenberg/issues/13998
function fix_preview_link_on_draft() {
echo '<script type="text/javascript">
jQuery(document).ready(function () {
const checkPreviewInterval = setInterval(checkPreview, 1000);
function checkPreview() {
const editorPreviewButton = jQuery(".editor-post-preview");
const editorPostSaveDraft = jQuery(".editor-post-save-draft");
if (editorPostSaveDraft.length && editorPreviewButton.length && editorPreviewButton.attr("href") !== "' . get_preview_post_link() . '" ) {
editorPreviewButton.attr("href", "' . get_preview_post_link() . '");
editorPreviewButton.off();
editorPreviewButton.click(false);
editorPreviewButton.on("click", function() {
editorPostSaveDraft.click();
setTimeout(function() {
const win = window.open("' . get_preview_post_link() . '", "_blank");
if (win) {
win.focus();
}
}, 1000);
});
}
}
});
</script>';
}
add_action('admin_footer', 'fix_preview_link_on_draft');
The script is running every second as Gutenberg also updates the preview URL on certain actions. Each interval it will execute the following logic:
- Check if we have
.editor-post-preview
and.editor-post-save-draft
and that the href is not the same asget_preview_post_link()
- If yes -> continue with the next steps || if no -> finish
- Update href with the correct
get_preview_post_link()
- Remove the listener events added by Gutenberg from the button
- Add our listener event that will save the draft and then open
get_preview_post_link()
in a new tab on click
Use at your own risk! It might break on future Gutenberg versions
Tested on Wordpress 5.3.2
any news on this issue?
function fix_preview_link_on_draft() { echo '<script type="text/javascript"> jQuery(document).ready(function () { const checkPreviewInterval = setInterval(checkPreview, 1000); function checkPreview() { const editorPreviewButton = jQuery(".editor-post-preview"); const editorPostSaveDraft = jQuery(".editor-post-save-draft"); if (editorPostSaveDraft.length && editorPreviewButton.length && editorPreviewButton.attr("href") !== "' . get_preview_post_link() . '" ) { editorPreviewButton.attr("href", "' . get_preview_post_link() . '"); editorPreviewButton.off(); editorPreviewButton.click(false); editorPreviewButton.on("click", function() { editorPostSaveDraft.click(); setTimeout(function() { const win = window.open("' . get_preview_post_link() . '", "_blank"); if (win) { win.focus(); } }, 1000); }); } } }); </script>'; } add_action('admin_footer', 'fix_preview_link_on_draft');
Use at your own risk! It might break on future Gutenberg versions
Tested on Wordpress 5.3.2
thanks @tvanro , your solution is the only one that has worked for me so far.
Thanks @tvanro that got me out of a pickle
I updated the code so it works with new posts and set an interval when clicked so that the window opens when the post is saved. I also moved the check for the draft button inside the click function because it may not exist on first visit with no updates. So this gives the user the ability to click preview when first visiting the edit screen for the post.
jQuery(document).ready(function () {
const checkPreviewInterval = setInterval(checkPreview, 1000);
function checkPreview() {
const editorPreviewButton = jQuery(".editor-post-preview");
if (editorPreviewButton.length && editorPreviewButton.attr("href") !== "' . get_preview_post_link() . '" ) {
editorPreviewButton.attr("href", "' . get_preview_post_link() . '");
editorPreviewButton.off();
editorPreviewButton.click(false);
editorPreviewButton.on("click", function(e) {
const editorPostSaveDraft = jQuery(".editor-post-save-draft");
if(editorPostSaveDraft.length > 0) {
editorPostSaveDraft.click();
}
const intervalId = setInterval(function() {
// find out when the post is saved
let saved = document.querySelector(".is-saved");
if(saved) {
clearInterval(intervalId);
const win = window.open("' . get_preview_post_link() . '", "_blank");
if (win) {
win.focus();
}
}
}, 50);
});
}
}
});
Thanks @tvanro. Save me a lot of time.
We are still waiting for native solution of the isue..
I'm having the same problem and """solved""" it with a workaround (notice the triple double quotes). Maybe it could help some people until there's an official solution. Feel free to use and/or improve this workaround.
Add this in your theme's functions.php
// workaround script until there's an official solution for https://github.com/WordPress/gutenberg/issues/13998 function fix_preview_link_on_draft() { echo '<script type="text/javascript"> jQuery(document).ready(function () { const checkPreviewInterval = setInterval(checkPreview, 1000); function checkPreview() { const editorPreviewButton = jQuery(".editor-post-preview"); const editorPostSaveDraft = jQuery(".editor-post-save-draft"); if (editorPostSaveDraft.length && editorPreviewButton.length && editorPreviewButton.attr("href") !== "' . get_preview_post_link() . '" ) { editorPreviewButton.attr("href", "' . get_preview_post_link() . '"); editorPreviewButton.off(); editorPreviewButton.click(false); editorPreviewButton.on("click", function() { editorPostSaveDraft.click(); setTimeout(function() { const win = window.open("' . get_preview_post_link() . '", "_blank"); if (win) { win.focus(); } }, 1000); }); } } }); </script>'; } add_action('admin_footer', 'fix_preview_link_on_draft');
The script is running every second as Gutenberg also updates the preview URL on certain actions. Each interval it will execute the following logic:
- Check if we have
.editor-post-preview
and.editor-post-save-draft
and that the href is not the same asget_preview_post_link()
- If yes -> continue with the next steps || if no -> finish
- Update href with the correct
get_preview_post_link()
- Remove the listener events added by Gutenberg from the button
- Add our listener event that will save the draft and then open
get_preview_post_link()
in a new tab on clickUse at your own risk! It might break on future Gutenberg versions
Tested on Wordpress 5.3.2
Modified this function so each preview click doesn't open the new tab 👍
setTimeout(function() {
const win = window.open("' . get_preview_post_link() . '", editorPreviewButton.attr("target"));
if (typeof win.name === "undefined") win.name = editorPreviewButton.attr("target");
if (win) {
win.focus();
}
}, 1500);
I'm having the same problem and """solved""" it with a workaround (notice the triple double quotes). Maybe it could help some people until there's an official solution. Feel free to use and/or improve this workaround.
Add this in your theme's functions.php// workaround script until there's an official solution for https://github.com/WordPress/gutenberg/issues/13998 function fix_preview_link_on_draft() { echo '<script type="text/javascript"> jQuery(document).ready(function () { const checkPreviewInterval = setInterval(checkPreview, 1000); function checkPreview() { const editorPreviewButton = jQuery(".editor-post-preview"); const editorPostSaveDraft = jQuery(".editor-post-save-draft"); if (editorPostSaveDraft.length && editorPreviewButton.length && editorPreviewButton.attr("href") !== "' . get_preview_post_link() . '" ) { editorPreviewButton.attr("href", "' . get_preview_post_link() . '"); editorPreviewButton.off(); editorPreviewButton.click(false); editorPreviewButton.on("click", function() { editorPostSaveDraft.click(); setTimeout(function() { const win = window.open("' . get_preview_post_link() . '", "_blank"); if (win) { win.focus(); } }, 1000); }); } } }); </script>'; } add_action('admin_footer', 'fix_preview_link_on_draft');
The script is running every second as Gutenberg also updates the preview URL on certain actions. Each interval it will execute the following logic:
- Check if we have
.editor-post-preview
and.editor-post-save-draft
and that the href is not the same asget_preview_post_link()
- If yes -> continue with the next steps || if no -> finish
- Update href with the correct
get_preview_post_link()
- Remove the listener events added by Gutenberg from the button
- Add our listener event that will save the draft and then open
get_preview_post_link()
in a new tab on clickUse at your own risk! It might break on future Gutenberg versions
Tested on Wordpress 5.3.2Modified this function so each preview click doesn't open the new tab 👍
setTimeout(function() { const win = window.open("' . get_preview_post_link() . '", editorPreviewButton.attr("target")); if (typeof win.name === "undefined") win.name = editorPreviewButton.attr("target"); if (win) { win.focus(); } }, 1500);
Well, in order to not spread this all over the backend pages, I've used these hooks/actions instead:
add_action( 'admin_footer-edit.php', 'fix_preview_link_on_draft' ); // Fired on the page with the posts table
add_action( 'admin_footer-post.php', 'fix_preview_link_on_draft' ); // Fired on post edit page
add_action( 'admin_footer-post-new.php', 'fix_preview_link_on_draft' ); // Fired on add new post page
from here.
Instead of waiting to change this preview links and since this bug doesn't trigger enough traction despite being an issue for several years, my approach is the dumbest I could find, but it work for all kind of preview (unpublished or not)!
In my function.php
I brutally catch all preview links to show an iframe from the frontend (and I inject and authToken so my author doesn't have to make any login from the frontend etc).
if (!is_admin() && isset($_GET["preview"]) && $_GET["preview"]==true) {
$auth = new \WPGraphQL\JWT_Authentication\Auth;
$authToken = $auth->get_token(wp_get_current_user());
$url = add_query_arg([
'id' => isset($_GET["p"]) ? $_GET["p"] : $_GET["preview_id"],
'secret' => "cestsecretvoilàtout",
'authToken' => $authToken
], FRONTEND_URL . '/api/preview');
echo '<iframe src="' . $url . '" style="width:100%; height: 100%;">';
exit(1);
}
Note: My setup is next.js + apollo / wpgraphql on the frontend.
Instead of waiting to change this preview links and since this bug doesn't trigger enough traction despite being an issue for several years, my approach is the dumbest I could find, but it work for all kind of preview (unpublished or not)!
In my
function.php
I brutally catch all preview links to show an iframe from the frontend (and I inject and authToken so my author doesn't have to make any login from the frontend etc).if (!is_admin() && isset($_GET["preview"]) && $_GET["preview"]==true) { $auth = new \WPGraphQL\JWT_Authentication\Auth; $authToken = $auth->get_token(wp_get_current_user()); $url = add_query_arg([ 'id' => isset($_GET["p"]) ? $_GET["p"] : $_GET["preview_id"], 'secret' => "cestsecretvoilàtout", 'authToken' => $authToken ], FRONTEND_URL . '/api/preview'); echo '<iframe src="' . $url . '" style="width:100%; height: 100%;">'; exit(1); }
Note: My setup is next.js + apollo / wpgraphql on the frontend.
This is actually genius, thank you for this! This works a lot better than other solutions I've seen around previewing 😬
I would just add that rather than doing this in functions.php
, you can do it in the singular.php
template. Think it ends up being a bit cleaner as you can also call wp_head
and wp_footer
which gives you the WordPress admin bar, making it a lot more like the native admin experience.
for wp Version 5.7.2
jQuery(document).ready(function () {
const checkPreviewInterval = setTimeout(checkPreview, 1000);
//checkPreview();
function checkPreview() {
const ToggleButton = jQuery(".block-editor-post-preview__button-toggle");
const editorPreviewButton = jQuery(".editor-post-preview");
ToggleButton.hide();
editorPreviewButton.show();
if (editorPreviewButton.length && editorPreviewButton.attr("href") !== "' . get_preview_post_link() . '" ) {
editorPreviewButton.attr("href", "' . get_preview_post_link() . '");
editorPreviewButton.off();
editorPreviewButton.click(false);
editorPreviewButton.on("click", function() {
setTimeout(function() {
const win = window.open("' . get_preview_post_link() . '", "_blank");
if (win) {
win.focus();
}
}, 1000);
});
}
}
});
Instead of waiting to change this preview links and since this bug doesn't trigger enough traction despite being an issue for several years, my approach is the dumbest I could find, but it work for all kind of preview (unpublished or not)!
In my
function.php
I brutally catch all preview links to show an iframe from the frontend (and I inject and authToken so my author doesn't have to make any login from the frontend etc).if (!is_admin() && isset($_GET["preview"]) && $_GET["preview"]==true) { $auth = new \WPGraphQL\JWT_Authentication\Auth; $authToken = $auth->get_token(wp_get_current_user()); $url = add_query_arg([ 'id' => isset($_GET["p"]) ? $_GET["p"] : $_GET["preview_id"], 'secret' => "cestsecretvoilàtout", 'authToken' => $authToken ], FRONTEND_URL . '/api/preview'); echo '<iframe src="' . $url . '" style="width:100%; height: 100%;">'; exit(1); }
Note: My setup is next.js + apollo / wpgraphql on the frontend.
This solution works fine for me. But I have done some modifications to get the latest revision ID of the custom post type (article). This work is for the draft and published posts. I am not sure, it might need some changes but it works for me.
/**
* Redirect preview link of the post to front-end domain.
*/
add_action(
'init',
function() {
if (
! is_admin() &&
isset( $_GET['preview'] ) &&
true == $_GET['preview']
) {
if ( isset( $_GET['p'] ) ) {
$post_id = intval( $_GET['p'] ); // Newly created post with draft status.
}
if ( isset( $_GET['preview_id'] ) ) {
$post_id = intval( $_GET['preview_id'] ); // Published post.
}
$post = get_post( $post_id );
if ( 'article' !== $post->post_type ) {
return;
}
$revisions = wp_get_post_revisions( $post_id );
$revision = reset( $revisions );
$preview_url = get_front_end_domain() . 'preview/' . $post_id . '/version/' . $revision->ID;
wp_redirect( $preview_url );
exit();
}
}
);
I have to get the different domains for each environment (local, develop, staging, production). So I have created the get_front_end_domain()
method to fetch the current environment domain.
My own version of @MoOx's fix. It's better to avoid using a fullscreen iframe and just do a redirect:
// Redirect preview page to Next preview
add_action("template_redirect", function () {
if (!is_admin() && isset($_GET["preview"]) && $_GET["preview"] == true) {
$redirect = add_query_arg(
[
"redirect" => urlencode("/post?p=" . $_GET["p"]),
"secret" => "abcdef123456",
],
"https://www.example.com/api/preview"
);
wp_redirect($redirect);
}
});
I've used the old approach adding a .js file on code.
This time I've tried another solution, I think this is better than use the .js script.
<?php
namespace App\Routes;
class PreviewArticle
{
public function __construct()
{
$this->preview_post();
}
/**
* Add filter to modify the link for preview post
*/
private function preview_post()
{
add_filter('preview_post_link', array($this, 'preview_post_link_filter'), 1, 2);
add_filter('rest_prepare_post', array($this, 'hack_fix_preview_link'), 10, 2);
}
/**
* Callback function that changes the preview link for post
*
* @param $preview_link
* @param $post
*
* @return string
*/
public function preview_post_link_filter($preview_link, $post): string
{
$postID = ($post) ? $post->ID : 0;
try {
$token = createJWTToken($postID);
} catch (UserException $exception) {
Logger::info("Error Creating JWT token for Preview Page");
return $preview_link;
}
return sprintf('%s/preview/%s?token=%s', home_url(), $post->ID, $token);
}
/**
* Hack Function that changes the preview link for draft articles,
* this must be removed when wordpress do the properly fix https://github.com/WordPress/gutenberg/issues/13998
*
* @param $response
* @param $post
*
* @return mixed
*/
function hack_fix_preview_link($response, $post)
{
if ('draft' === $post->post_status) {
$response->data['link'] = get_preview_post_link($post);
}
return $response;
}
}
Instead of waiting to change this preview links and since this bug doesn't trigger enough traction despite being an issue for several years, my approach is the dumbest I could find, but it work for all kind of preview (unpublished or not)!
In my
function.php
I brutally catch all preview links to show an iframe from the frontend (and I inject and authToken so my author doesn't have to make any login from the frontend etc).if (!is_admin() && isset($_GET["preview"]) && $_GET["preview"]==true) { $auth = new \WPGraphQL\JWT_Authentication\Auth; $authToken = $auth->get_token(wp_get_current_user()); $url = add_query_arg([ 'id' => isset($_GET["p"]) ? $_GET["p"] : $_GET["preview_id"], 'secret' => "cestsecretvoilàtout", 'authToken' => $authToken ], FRONTEND_URL . '/api/preview'); echo '<iframe src="' . $url . '" style="width:100%; height: 100%;">'; exit(1); }
Note: My setup is next.js + apollo / wpgraphql on the frontend.
Where do I add this code to make it work
I've used the old approach adding a .js file on code.
This time I've tried another solution, I think this is better than use the .js script.
<?php namespace App\Routes; class PreviewArticle { public function __construct() { $this->preview_post(); } /** * Add filter to modify the link for preview post */ private function preview_post() { add_filter('preview_post_link', array($this, 'preview_post_link_filter'), 1, 2); add_filter('rest_prepare_post', array($this, 'hack_fix_preview_link'), 10, 2); } /** * Callback function that changes the preview link for post * * @param $preview_link * @param $post * * @return string */ public function preview_post_link_filter($preview_link, $post): string { $postID = ($post) ? $post->ID : 0; try { $token = createJWTToken($postID); } catch (UserException $exception) { Logger::info("Error Creating JWT token for Preview Page"); return $preview_link; } return sprintf('%s/preview/%s?token=%s', home_url(), $post->ID, $token); } /** * Hack Function that changes the preview link for draft articles, * this must be removed when wordpress do the properly fix https://github.com/WordPress/gutenberg/issues/13998 * * @param $response * @param $post * * @return mixed */ function hack_fix_preview_link($response, $post) { if ('draft' === $post->post_status) { $response->data['link'] = get_preview_post_link($post); } return $response; } }
Where do you put this code? @emanuellopes
$_GET["p"]
Where do you put this code? @emanuellopes
Can you be more specific?
Don't use $_GET variables directly!! You must filter the variables.
you can put this code on funtions.php like this
new App\Routes\PreviewArticle();
don't forget to use composer to autoload the file
This seems to be an edge case only applicable to headless implementation. Developers provided a few work around code examples. The issue hasn't seen any additional comments for the last 1 1/2 years. Let's close it.
There are indeed workarounds to achieve this, but in my opinion, it's not an edge case. Most headless implementations require this functionality.