Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Custom Preview Links not fully filterable #13998

Closed
yoadsn opened this issue Feb 21, 2019 · 34 comments
Closed

Custom Preview Links not fully filterable #13998

yoadsn opened this issue Feb 21, 2019 · 34 comments
Labels
[Feature] Document Settings Document settings experience [Feature] Extensibility The ability to extend blocks or the editing experience REST API Interaction Related to REST API [Type] Bug An existing feature does not function as intended

Comments

@yoadsn
Copy link

yoadsn commented Feb 21, 2019

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.

@corywebb
Copy link

corywebb commented Mar 7, 2019

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.

@draganescu
Copy link
Contributor

Hi there, I'll close this and reopen #4555 and we can continue the discussion there.

@draganescu
Copy link
Contributor

Reopened the issue for @danielbachhuber and @yoadsn, see #4555

@yoadsn
Copy link
Author

yoadsn commented Mar 16, 2019

@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.

  1. WP admin is accessed and used from domain A

  2. 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)

  3. Using Gutenberg for a draft post.

  4. After an autosave - the autosave endpoint return a preview_url as you have mentioned above.
    The reducer here would take the preview_link as is and use that for the preview button.
    As you have shown on the screenshots of the PR Move editorMediaUpload to the editor module #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 the get_preview_post_link which makes the preview link filterable.

  5. 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 the get_permalink function.
    The permalink is filterable but in my scenario preview link need to work on site_url and not the home_url - permalinks should always be on home_url. (for the preview to work, all admin auth is against site_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?

@swissspidy swissspidy added [Feature] Document Settings Document settings experience [Feature] Extensibility The ability to extend blocks or the editing experience REST API Interaction Related to REST API labels Mar 17, 2019
@Guibod
Copy link

Guibod commented Mar 28, 2019

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.

@danielbachhuber danielbachhuber added the [Type] Bug An existing feature does not function as intended label Apr 16, 2019
@danielbachhuber
Copy link
Member

@yoadsn Sorry for the late reply here. Your analysis seems reasonable although I'm not quite sure what the fix should be.

@yoadsn
Copy link
Author

yoadsn commented Apr 17, 2019

@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.

@danielbachhuber
Copy link
Member

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.

@yoadsn
Copy link
Author

yoadsn commented Apr 17, 2019

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.

@aduth
Copy link
Member

aduth commented Apr 29, 2019

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:

case 'REQUEST_POST_UPDATE_SUCCESS':
if ( action.post.preview_link ) {
return action.post.preview_link;
} else if ( action.post.link ) {
return addQueryArgs( action.post.link, { preview: true } );
}
return state;

@kyleramirez
Copy link

kyleramirez commented Jun 30, 2019

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?

@ocean90
Copy link
Member

ocean90 commented Jul 1, 2019

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.

@martinszeltins
Copy link

There's still no filter to change the Preview link that is on the right side of Gutenberg.

@Jamiewarb
Copy link

Is there any news on this at all? :)

@tvanro
Copy link

tvanro commented Dec 24, 2019

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 as get_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

@ciprianimike
Copy link

any news on this issue?

@carlotrimarchi
Copy link

carlotrimarchi commented Feb 25, 2020

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.

@pixelprogrammer
Copy link

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);
			});
		}
	}
});

nickcernis added a commit to wpengine/faustjs that referenced this issue Feb 10, 2021
* feat: add support for previewing drafts in @wpengine/headless

* feat: add support for previewing drafts from WP (note: Gutenberg not yet supported)

WordPress/gutenberg#4555
WordPress/gutenberg#13998

* fix: improve reliability of post preview link replacement for published content

* feat: add NextPreviewContext so we can better know if previewMode is active in hooks

* test: update preview link WP test

Co-authored-by: Nick Cernis <nick@cern.is>
@MoOx
Copy link

MoOx commented Apr 30, 2021

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.

@ntsim
Copy link

ntsim commented Jun 17, 2021

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.

wjohnsto added a commit to wpengine/faustjs that referenced this issue Jul 1, 2021
* feat: change fallback mode to 'blocking' allow passing overrides in initializeNextStaticPaths()

* feat: Add getting started sidebar box to plugin settings page (#76)

* feature: Add getting started box

* design: Style getting started box

* chore: Move install script to external script

This also removes the WPGraphQL notification bar.
We've replaced this with a button so the bar is
no longer needed.

* chore: PHP standards

* chore: Remove unused class

* refactor: Add error handling for WPGraphQL install

* chore: Use consistent plugin name and quotes

* style: Improve label alignment and accessibility

* docs: Update README with more information about the framework

* docs: Improve secret key field description (#78)

- Makes link text more accessible.
- Adds missing `__()` translation function call.

* fix: Replaced wpe_headless_domain_replacement_enabled() in rewrite callbacks with wpe_headless_is_rewrites_enabled() to correct link rewrites. (#77)

* fix: Undefined index: preview_id

* fix: phpcs

* Docs rework to use absolute URL paths (#83)

* testing absolute links

* chore: adding semantic commit

Co-authored-by: William Johnston <will@wwj.dev>

* docs: Add deployment steps for wpe-headless plugin (#79)

* test: Added tests for content replacement functions and callbacks

* test: Moved duplicate wp_insert_post calls to setUp()

* fix: Added optional operator to src attribute within EnqueuedStylesheet when filtering for gutenburg styling (#84)

* docs: Adjust “disable theme” label (#85)

To make it clear that the plugin option disables
admin pages, not full theme functionality.

* fix: change Next to start on port 8080 (#82)

Since the WP Atlas hosting/deployment service expects the service to run on port 8080, we should update the example so it's ready to work with the deployment service.

* feat: Updated for WordPress plugin release. (#88)

* Update README.md (#89)

* feat: add graphql-code-gen

Types are now generated using the WP GraphQL schema

* feat: migrate types over to generated types from WP GraphQL

* style: lint fixes

* fix(BH-816): make redirect in initializeNextStaticProps dynamic

* build: add lint script in @wpengine/headless

* style: lint fixes

* docs: add templating/README.md

* docs: add getting-started/README.md

* docs: Update README with links to guides

* Add callback for content src= replacement (#90)

* feat: Add callback for content src= replacement

* Match full domain path in src attr

* feat: Add content modeling plugin skeleton

* Add phpunit config

* Feat/filter media src (#97)

* feat: Add callback for content src= replacement

* Match full domain path in src attr

* feat: Add conent image srcset filter

* Add admin checkbox for image source rewrite

* style: whitespace lint issue

* test: Add test for when image filter not enabled

* Update media source toggle string

* fix: Added WP_CLI check before redirecting user on WordPress plugin activate. (#101)

* chore: bump Next.js to ^10.0.5 in preview example

* fix: use <div /> instead of <p /> for excerpt/content in example

<p>'s cannot be inside <p>'s and without this, there is an error during rehydration

* fix(BH-809): use Apollo hooks, extract GraphQL queries

* fix: do not export resolveTemplate in /utils to reduce chance of Webpack errors

This should prevent errors if the 'theme' directory is not present in a non-Next.js project

* chore: bump @wpengine/headless to 0.4.0

* refactor: generate wpgraphql.d.ts instead of wpgraphql.ts

The primary advantage to this is a smaller bundle size and not needing to import WPGraphQL all over the place

* ci: refactor plugin jobs and add content-model plugin (#102)

* refactor: existing wpe-headless jobs to paramaterized

* ci: add content-model plugin to circleci

* Add content model readme file

* remove composer-setup.php after lint

* test: End to end testing integration (#104)

* Added @wordpress/env package to create a WordPress testing/development environment

* Added wp-env commands for wpe-headless plugin.

* Added wp-env config file to wpe-headless plugin

* Added cypress and wp-env npm packages

* Added cypress files

* Corrected failing test

* Turned videos off by default

* Reworked .gitignore

* Moved end-2-end testing to project root

* fix: resolve regressions with previews not working without client-side requests

* fix: run getContentNode if using front page to properly hydrate Apollo cache

This fixes usePost() not returning anything if using a frontpage and client-side queries are disabled. Also, extracted out query into nextFetchFromWP()

* feat: add page.tsx template to preview example

* fix: update heading levels in preview example templates

* docs: Added documentation for end-2-end testing. (#107)

* Added documentation for end-2-end testing

* Update docs/DEVELOPMENT.md

Co-authored-by: Nick Cernis <nick@cern.is>

Co-authored-by: Nick Cernis <nick@cern.is>

* Cookies will only be persistent for a single request (#108)

* putting apollo client on context

* feat: cookie now initialized whenever accessed

* feat: cookies are persistent only for a single request

* chore: fixing lint issues

* fix: add ctx prop to <HeadlessProvider /> in example

Co-authored-by: William Johnston <will@wwj.dev>
Co-authored-by: Clay Griffiths <clay@claygriffiths.com>

* chore: bump @wpengine/headless to 0.4.1

* feat: Added initial structure for registering custom content types and fields.

test: Updated phpcs config.

* feat: Adjust domain replacement logic to remove header / query parameter requirement.

BREAKING CHANGE:

Previously the plugin required enabling the "Enable Post and Category URL rewrites" setting
and also passing either the `replace-domain` parameter to the WPGraphQL endpoint
or sending `HTTP_X_WP_HEADLESS` in the header.

Now it only requires enabling the plugin option. No other request parameters
are required.

* fix: Use 302 redirects for public URLs (#113)

Turning off “Enable public route redirects” will
no longer continue to cause redirects due to
aggressive browser caching of 301 redirects.

* style: Style and structure the example project (#109)

* chore: Add normalize.css and sass to starter theme

* chore: Add a main Sass file for global CSS

* chore: Load normalize.css and the main CSS file

* chore: Add fonts and font-face declarations

* design: Add base styling

* feat: Add simple stateless components and styles

* chore: Add image for homepage hero background

* feat: Add front page content and styles

* refactor: Use Next Link for site title

* refactor: Make Posts intro prop optional

* feat: Add Header and Footer to all page templates

* style: Add padding around page content

* style: Add breakpoint Sass variables

* docs: Mention the components scoped CSS styles

* feat: Give Hero component an ID prop

So that styling can be overridden on a per-page
basis.

The page using the Hero component can pass the
id prop and then override default Hero styling
in its [page-name].module.scss file.

* style: Give posts a scoped 'single' class

To help with responsive styling.

* style: Adjust styling at smaller widths

* chore: Pass heading levels in a type-safe way

Some hoop-jumping to satisfy TypeScript's type
checker. Fixes the type error that @mindctrl
kindly reported:

Type '{ children: string; className: string; }'
is not assignable to type 'IntrinsicAttributes'.

* refactor: Rename sass folder to scss

* chore: Fix import order

* refactor: Use Google Fonts instead of local fonts

Addresses feedback from @trevanhetzel at
https://github.com/wpengine/headless-framework/pull/109#discussion_r568136700.

* chore: Annotate function return types

* docs: Update font info on the front page.

To mention Google Fonts in place of locally hosted
fonts.

* fix: Incorrect nesting of Post heading and link

This was causing a console error for the Posts
component:

“Function components cannot be given refs.”

* chore: Suppress no-spreading warning

* chore: Suppress unneeded eslint rules

* fix: Load front-page.tsx if showing latest posts

If Settings → Reading is set to display latest
posts on the homepage (the default), this ensures
that the latest-posts template loads to display
the welcome content.

Before, users would have to set a static page
as the homepage in WP before they saw the default
homepage, which is a worse setup experience.

* chore: Remove unused file

* chore: Inline Post type

The WPGraphQL types do not appear to be exposed,
so attempting to import { WPGraphQL } from
'@wpengine/headless' results in:

Type error: Module '"../node_modules/@wpengine/headless/dist"'
has no exported member 'WPGraphQL'.

* fix: return '404' as possible template if there's a 404

* feat: add 404.tsx template to examples/preview

* fix: force $wp_query->parse_query() to run when getting templates

* fix: Remove front page template loader from index

Clay's fix in https://github.com/wpengine/headless-framework/pull/109/commits/9e996a96be95d042a48df69063d3e2aebb84aebf
ensures the front-page template loads for “latest
posts” homepages now, so front-page.tsx
will load automatically as expected. 🎉

* docs: change “theme” to “project” in welcome text

To address Trevan's copy edits:
- https://github.com/wpengine/headless-framework/pull/109#discussion_r568981682
- https://github.com/wpengine/headless-framework/pull/109#discussion_r568982025

Co-authored-by: Clay Griffiths <clay@claygriffiths.com>

* Ci: package headless build (#111)

* ci: Add npm build and test jobs

* npm install in test job

* Disable npm package test run until failing test can be fixed in another ticket

* ci: enable npm package test

* ci: use circleci/node orb commands

* test: remove menu component test. needs attention

* test: pass with no tests found

* chore: remove 404 page template (#114)

Removes pages/404.tsx, because 404s will now
result in loading theme/404.tsx.

This ensures that:
- Devs don't have two conflicting 404 templates to
choose from.
- example.com/404 loads the theme 404 template
instead of the page/404.tsx template.

* fix: Change the way GraphQL auth callback checks HTTP_AUTHORIZATION (#116)

* chore: bump wpe-headless plugin to 0.4.1

* feat: clone preview as getting-started (#117)

* refactor: clone preview folder as getting-started

We plan to then simplify the preview example in
a future PR.

getting-started will serve as the full framework
demo from this point on.

* chore: remove dev-lerna script for preview example

We only want packages/headless and
examples/getting-started to build when doing
`npm run dev` from the project root.

Otherwise Next spins examples/preview and
examples/getting-started up and there's a port
collision on 3000.

An alternative is to spin up examples on different
ports, but this seems excessive, particularly if
the examples folder grows.

* docs: update install steps to use getting-started

* docs: update getting-started example readme (#118)

I cloned this from the preview example but forgot
to update the readme.

* Ci/add e2e test (#119)

* ci: Add npm build and test jobs

* npm install in test job

* Disable npm package test run until failing test can be fixed in another ticket

* ci: enable npm package test

* ci: use circleci/node orb commands

* test: remove menu component test. needs attention

* test: pass with no tests found

* ci: add e2e

* ci attach project

* ci add run cypress tests

* ci: move e2e to own workflow

* build: include src/types/wpgraphql.d.ts in published package

* chore: bump version to 0.4.3

* chore: update @wpengine/headless in preview example

* docs: Fixed link to post previews doc

Closes #121.

* feat: Add "npm run clean" command (#125)

* feat: Add "npm run clean" command

Clears next folders and node_modules for the
example projects.

Intended to be run from the project root after
switching branches and encountering unexpected
behavior.

Follow with `npm run bootstrap` to start over.

* docs: mention 'npm run clean' command

Props @markkelnar.

* refactor: use WPGraphQL types in Posts component (#124)

* refactor: pass templates to TemplateLoader and Data Fetchers rather than auto loading from theme dir

* feat: make <TemplateLoader /> generic, add <NextTemplateLoader />

* refactor: update examples/preview to use wp-templates dir

* fix: return null in <TemplateLoader /> if page info is not provided

* fix: make templates param in Data Fetcher optional

* docs: update docs to reflect <TemplateLoader /> changes

* docs: Document the WPHead component (#128)

* docs: add WPHead readme

* docs: complete WPHead readme

* docs: update examples to point to wp-templates/ instead of theme/

* fix: ensure WP stylesheets start with WP URL (#115)

Passes the WP URL from WPGraphQL instead of
depending on process.env, which isn't available
to the WPHead component.

* fix: remove hash when querying GetUriInfo in useUriInfo()

* chore: bump @wpengine/headless to 0.5.0

* feat(BH-863): add support for previewing drafts (#122)

* feat: add support for previewing drafts in @wpengine/headless

* feat: add support for previewing drafts from WP (note: Gutenberg not yet supported)

https://github.com/WordPress/gutenberg/issues/4555
https://github.com/WordPress/gutenberg/issues/13998

* fix: improve reliability of post preview link replacement for published content

* feat: add NextPreviewContext so we can better know if previewMode is active in hooks

* test: update preview link WP test

Co-authored-by: Nick Cernis <nick@cern.is>

* fix: prevent 500 error on archives (#131)

* chore: extend GET_URI_INFO query with conditionals

So that `nextFetchFromWP` can better alter
requests based on the page type.

* chore: add conditionals to getUriInfo service

Exposes isSingular and isArchive in the response.

* chore: update UriInfo type with new conditionals

* chore: update GetUriInfoQuery type

Handled automatically with this command from
packages/headless:

npm run generate-graphql

* refactor: only run getContentNode on singulars

Calling getContentNode on an archive was causing
the 500 error.

* fix: update package-locks

Attempting to clear CI errors.

* revert: remove package locks

* fix: check pageInfo is not void before using

Resolves the compilation error:

Property 'isSingular' does not exist on
type 'void'.

* refactor: improve front page variable name

* refactor: improve inline comment

* refactor: remove unneeded path check

isFrontPage and isPostsPage are all we need.

* fix: WPE_HEADLESS_SECRET to WP_HEADLESS_SECRET (#134)

The WPE_ prefix is reserved for env vars on the
WP Engine hosting platform, so users will not
be able to create vars with this name.

* docs (BH-829): Generate headless package docs with typedoc (#132)

* docs: generate docs with typedoc

* chore: update package-lock

* chore: configure typedoc

* docs: add initial generated docs

* docs: correct typo

* Custom queries (#133)

* feat: adding post and page data fragments

* feat: setting up gql queries with fragments

* adding page information and allowing list post options

* feat: allowing extensible args for list posts

* chore: fragments are explicit, variables on gql calls are optional

* feat: enabling variables and fragments to be passed to gql services

* chore: adjusting example to use new hook interfaces

* feat: conditionally calling server-side services, usePost will only make request if necessary

* chore: lint fix

* removing console log

* refactor: initializeApollo -> getApolloClient

* chore: decoupling next

* refactor: adjusting exports to be consistent and not use default, lint fix

* feat: allowing customizable queries on the backend and allowing you to cache them as well

* moving react dependencies into sub-folder

* refactor: using higher-level component imports

* refactor: moving WPHead to be a next-only component

* refactor: removing unused docs, adding documentation for theme components

* adding docs for queries

* fix: correcting doc imports

Co-authored-by: Will Johnston <will@wwj.dev>

* chore: prep headless plugin 0.5 and package 0.6 (#136)

* chore: bump headless package to 0.6.0 in examples (#137)

* chore: correcting image link to be absolute (#138)

Co-authored-by: William Johnston <will@wwj.dev>

* docs: fix typo breaking a link in README (#140)

* docs: fix post preview link (#143)

* fix: Rewrite href nodes with the frontend URL (#99)

* fix: Replace href keys in WPGraphQL responses

So that URL replacement works in the updated menu
component.

* ci: npm publish job (#141)

* feat (BH-864): Add a category template to the getting-started example (#145)

* feat: Add category template

* feat: Add PostsArchive component

Same as Posts but attempts to amend the default
query.

* refactor: Remove PostsArchive component

Just use Posts instead.

* fix: Load a named category in category.tsx

* fix: Fetch category slug from path

Assumes a category prefix of 'category'.

* chore: Remove to-dos and unused code

Co-authored-by:  John Parris <john.parris@wpengine.com>

* fix: only returning revalidate for SSG (#142)

* fix: only returning revalidate for SSG

* ensuring pageProps is an object

* fix: lint

Co-authored-by: William Johnston <will@wwj.dev>

* fix (BH-897): Fetch six posts for the front page template (#147)

* fix: Fetch six posts for the front page template

Fixes #144 so the front page template displays
posts even if Settings → Reading is using a
static page instead of “latest posts”.

* docs: remove where clause to get all posts

* Adjusting previews doc to work with latest framework features (#148)

* chore: correcting image link to be absolute

* doc: adjusting previews doc to work with latest framework features

Co-authored-by: William Johnston <will@wwj.dev>

* feat: Add wp-admin index page for content modeling.

* test: Add test for content model wp-admin page

* feat: Generate labels for custom post type registration.

Given a singular and plural name, generate the labels necessary
for registering custom post types.

* test: Add tests for generating custom post type labels.

* test: Update labels in example test data.

* ci: Update phpcs configuration.

* feat: Pagination component (BH-856) and getting-started example (#154)

* feat: Add a Pagination component to display links

This depends on Next and WPGraphQL. It assumes the
cursor-based pagination strategy described at
https://www.wpgraphql.com/2020/03/26/forward-and-backward-pagination-with-wpgraphql/.

Custom queries must be handled separately by the
page template displaying the posts. See an example
in headless-framework/examples/getting-started/wp-templates/category.tsx.

* chore: Do not pass pagination info to WPGraphQL

When the path is
/category/uncategorized/after/abc123, we want to
only send /category/uncategorized to GraphQL for
the purpose of determining the correct template
for the current page.

So strip the `/after/abc123` portion, leaving
/category/uncategorized.

This assumes we want to paginate post archives
using URLs in the format:

/category/uncategorized/[before|after]/[abc123].

Where abc123 is the ID of the last or first post
on the current page.

This is different to the WP-native /page/1 format
but more closely matches the more efficient
cursor-based pagination strategy at
https://www.wpgraphql.com/2020/03/26/forward-and-backward-pagination-with-wpgraphql/

It also allows pages to be fetched on the server
(and cached) without using client-side requests
to fetch additional content. This means a user
does not have to fill in NEXT_PUBLIC_WORDPRESS_URL
to get paginated content.

* feat: Add pagination to getting-started template

To demonstrate a paginated archive. Will show
next and previous page links on category
archives such as category/uncategorized.

* style: Add basic styles for the pagination links

* refactor: extract category option logic

Puts category option logic in the framework
instead of in the page template.

As suggested by @trevanhetzel in
https://github.com/wpengine/headless-framework/pull/154.

* docs: improve getStaticProps info

* chore: lint

* refactor: 'keyword' to 'direction'

Keyword sounds like it relates to search terms.

Thanks to @mindctrl for the feedback.

* fix: #152, exporting types from non-core modules (#153)

Co-authored-by: William Johnston <will@wwj.dev>

* ci: Install WPGraphQL plugin for phpunit tests.

* feat: Register custom post types and fields with the WPGraphQL API

* ci: Update PHP_CodeSniffer config to remove snake case requirement.

* chore: Remove debug code

* test: Add test case for number/float field type.

* fix: Do not replace URLs in generalSettings query

So that a query like this:

query GeneralSettings {
  generalSettings {
    title
    description
    url
  }
}

Gives the expected WP URL instead of the frontend
site URL if “Enable Post and Category URL
rewrites” is enabled at Settings → Headless.

* Added to quickstart to populate front end url (#161)

* fix: improvements to the Posts getting-started component (#160)

* fix: Wrap read more anchor in Next Link component

* refactor: remove count prop from Posts

No longer required because we can now limit posts
via custom queries, as in front-page.tsx.

* chore: remove unneeded href attribute

Next Links only need this on the Link wrapper:
https://nextjs.org/docs/api-reference/next/link

* chore: remove unneeded space

Co-authored-by: John Parris <john.parris@wpengine.com>

Co-authored-by: John Parris <john.parris@wpengine.com>

* feat: Point getting-started to a live demo URL for a faster new user experience (BH-895) (#155)

* feat: Use a demo WORDPRESS_URL by default

Makes a missing WORDPRESS_URL or .env.local a
warning instead of an exception.

Shows content from a live demo site instead of
failing to build.

* feat: Warn if WP_HEADLESS_SECRET is not set

Instead of throwing an exception and failing to
continue, warn the user if WP_HEADLESS_SECRET is
unset.

That way they can continue without env vars and
still see demo content. (Previews will not work
until they act on the warning.)

* feat: Add a posts link to the hard-coded menu

Swap out for a dynamic menu in another PR.

* docs: Redo quick start docs

To create the frontend app first, then repoint
to a WordPress instance.

* docs: Redo getting started docs

To create the frontend app first, then repoint
to a WordPress instance.

* docs: frontend to front-end for consistency

* docs: Prompt to set the front-end site URL

* chore: prep WP Engine Headless 0.5.1 and @wpengine/headless 0.6.1 for release (#162)

* chore: bump @wpengine/headless package to 0.6.1

* chore: bump WP Engine Headless plugin to 0.5.1

* docs: note stable tag in readme when releasing

* docs: add package changelog and compatibility note

* docs: fix plugin name

* chore: set examples to use @wpengine/headless 0.6.1 (#164)

* chore: bump examples to use latest package version

* chore: update lockfiles

* chore: Remove content model plugin and Circle CI config

* docs: Describe automated package release process (#169)

* Update format for preview links (#167)

* fix: Rewrite post preview links to the following format:

host/preview/post-slug?p=xx&preview=true

* test: Adjust preview link test to check for updated link format.

* refactor: client-side preview handling

* feat: Gutenberg preview link replacement

* feat: fixing gutenberg bug where preview link filter is not honored. TemplateLoader works for promises or components. Removing preview handler, since only auth handler is needed

* doc: adjusting NEXT_PUBLIC_WORDPRESS_URL to be default

* doc: adjusting previews doc to use new preview route

* fix: lint errors

* fix: lint errors

* refactor: JS is old-browser friendly

* fix: fixing WP gutenberg links, adding XXX

* fix: not opening new window for preview links

* fix: composeUrlPath will only warn if uriPath is not a string

* fix: changed displatch for gutenberg editor to autosave instead of savePost

* fix: pagination is working with a default implementation

* doc: fixing typo

* doc: simplifying previews component

* docs: Amend getting started steps to copy env file

The hard-coded fallback URL was removed in
https://github.com/wpengine/headless-framework/pull/167/files#diff-d1f942ac42801cdbd70e98a5a4105d8c354af691b37b65f1706f5323898af1e7L23.

So we now need to prompt the user to copy the
env file before they run the dev server.

Without this every page 404s.

Co-authored-by: William Johnston <will@wwj.dev>
Co-authored-by: Matt Landers <matt@platypi.io>
Co-authored-by: Matt Landers <matt.landers@wpengine.com>
Co-authored-by: Nick Cernis <nick@cern.is>

* chore: prep WP Engine Headless 0.5.2 and @wpengine/headless 0.6.2 for release (#171)

* chore: Prep WPE Headless plugin 0.5.2 for release

* chore: Prep headless package 0.6.2 for release

* chore: Use @wpengine/headless 0.6.2 in examples (#172)

* Preview links work with configured site URL path (#173)

* fix: Rewrite post preview links to the following format:

host/preview/post-slug?p=xx&preview=true

* test: Adjust preview link test to check for updated link format.

* refactor: client-side preview handling

* feat: Gutenberg preview link replacement

* feat: fixing gutenberg bug where preview link filter is not honored. TemplateLoader works for promises or components. Removing preview handler, since only auth handler is needed

* doc: adjusting NEXT_PUBLIC_WORDPRESS_URL to be default

* doc: adjusting previews doc to use new preview route

* fix: lint errors

* fix: lint errors

* refactor: JS is old-browser friendly

* fix: fixing WP gutenberg links, adding XXX

* fix: not opening new window for preview links

* fix: composeUrlPath will only warn if uriPath is not a string

* fix: changed displatch for gutenberg editor to autosave instead of savePost

* fix: pagination is working with a default implementation

* doc: fixing typo

* doc: simplifying previews component

* fix: preview links working for frontend site URLs with path

* lint: fix

* lint: fix 2

* fix: using skip parameter for useQuery to avoid conditional hook calls

* refactor: using skip for useQuery for every skippable hook

Co-authored-by: John Parris <john.parris@wpengine.com>
Co-authored-by: William Johnston <will@wwj.dev>
Co-authored-by: Matt Landers <matt@platypi.io>
Co-authored-by: Matt Landers <matt.landers@wpengine.com>

* Prep WP Engine Headless 0.5.3 and @wpengine/headless 0.6.3 for release (#175)

* chore: bump WPE Headless plugin to 0.5.3

* chore: bump @wpengine/headless package to 0.6.3

* test: Codeception end-2-end integration (#159)

* Integrated Codeception.
* Added end-2-end tests for settings.
* Added end-2-end tests for post previews.

Co-authored-by: Nick Cernis <nick@cern.is>

* chore: use @wpengine/headless 0.6.3 in examples (#176)

* DOCS: Initial Framework grammar and tone edits (#181)

* DOCS: Initial Framework grammar and tone edits

* Update docs/getting-started/README.md

Co-authored-by: Nick Cernis <nick@cern.is>

* Update docs/getting-started/README.md

Co-authored-by: Nick Cernis <nick@cern.is>

* Update docs/getting-started/README.md

Co-authored-by: Nick Cernis <nick@cern.is>

* Update docs/templating/README.md

Co-authored-by: Nick Cernis <nick@cern.is>

* Update docs/queries/README.md

Co-authored-by: Nick Cernis <nick@cern.is>

* Update docs/templating/README.md

Co-authored-by: Nick Cernis <nick@cern.is>

* Remove "it" from sentence.

* Update README.md

* Update docs/templating/README.md

Co-authored-by: Nick Cernis <nick@cern.is>

Co-authored-by: Nick Cernis <nick@cern.is>
Co-authored-by: Will Johnston <wjohnsto@users.noreply.github.com>

* doc: adding space between of[Node] (#182)

* adding space between of[Node]

* doc: semantic commit

* doc: reverting semantic commit

Co-authored-by: William Johnston <will@wwj.dev>

* test: Add phpunit tests for settings functions

* build(deps): bump elliptic in /examples/getting-started (#180)

Bumps [elliptic](https://github.com/indutny/elliptic) from 6.5.3 to 6.5.4.
- [Release notes](https://github.com/indutny/elliptic/releases)
- [Commits](https://github.com/indutny/elliptic/compare/v6.5.3...v6.5.4)

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>

* build(deps): bump elliptic from 6.5.3 to 6.5.4 in /examples/preview (#179)

Bumps [elliptic](https://github.com/indutny/elliptic) from 6.5.3 to 6.5.4.
- [Release notes](https://github.com/indutny/elliptic/releases)
- [Commits](https://github.com/indutny/elliptic/compare/v6.5.3...v6.5.4)

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>

* build(deps): bump elliptic from 6.5.3 to 6.5.4 in /packages/headless (#178)

Bumps [elliptic](https://github.com/indutny/elliptic) from 6.5.3 to 6.5.4.
- [Release notes](https://github.com/indutny/elliptic/releases)
- [Commits](https://github.com/indutny/elliptic/compare/v6.5.3...v6.5.4)

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>

* chore: bump next to 10.0.9 (#184)

Removes a transitive dependency (cacache) that
depended on a vulnerable version of ssri (6.0.1)
triggering dependabot alerts.

* chore: bump lerna to 4.0.0 (#185)

To ensures that the `ssri` transitive dependency is
using the security patch from v8.0.1.

* chore: bump @wordpress/env to prevent mysql error

Error during npm run wp:start was:
mysqlcheck: Got error: 1045: Access denied for user

Caused by changes to the WP Docker image:

https://github.com/WordPress/gutenberg/issues/29829

* fix: prevent errors for JWT authenticated requests (#190)

Removes the graphql_authentication_errors filter
and callback, which cause an error for JWT
authenticated requests.

Authentication already happens in
wpe_headless_rest_determine_current_user, which
is hooked to determine_current_user and runs
during GraphQL, REST and regular requests.

Fixes #189.

* chore: prepare release of WPE Headless 0.5.4 (#192)

* Update CODEOWNERS to include developer-relations.

* Removing Cypress (#196)

* updating composer doc to specify codeception version

* refactor: removing Cypress (#195)

* refactor: removing test-end-2-end which only references cypress tests

Co-authored-by: William Johnston <will@wwj.dev>

* build(deps): bump node-notifier in /packages/headless (#197)

Bumps [node-notifier](https://github.com/mikaelbr/node-notifier) from 8.0.0 to 8.0.2.
- [Release notes](https://github.com/mikaelbr/node-notifier/releases)
- [Changelog](https://github.com/mikaelbr/node-notifier/blob/master/CHANGELOG.md)
- [Commits](https://github.com/mikaelbr/node-notifier/compare/v8.0.0...v8.0.2)

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>

* build(deps): bump rmccue/requests in /plugins/wpe-headless (#193)

Bumps rmccue/requests from 1.7.0 to 1.8.0.

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>

* docs[repo](#201): adding basic contribution guidelines (#202)

* docs[repo](#201): adding basic contribution guidelines

* docs[repo]: adding semantic commits workflow

* docs[repo]: configuring semantic commits

* docs: configuring semantic commits

Co-authored-by: William Johnston <will@wwj.dev>

* build(deps): bump ua-parser-js in /packages/headless (#204)

Bumps [ua-parser-js](https://github.com/faisalman/ua-parser-js) from 0.7.23 to 0.7.28.
- [Release notes](https://github.com/faisalman/ua-parser-js/releases)
- [Commits](https://github.com/faisalman/ua-parser-js/compare/0.7.23...0.7.28)

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>

* build(deps): bump handlebars from 4.7.6 to 4.7.7 in /packages/headless (#205)

Bumps [handlebars](https://github.com/wycats/handlebars.js) from 4.7.6 to 4.7.7.
- [Release notes](https://github.com/wycats/handlebars.js/releases)
- [Changelog](https://github.com/handlebars-lang/handlebars.js/blob/master/release-notes.md)
- [Commits](https://github.com/wycats/handlebars.js/compare/v4.7.6...v4.7.7)

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>

* build(deps): bump url-parse from 1.4.7 to 1.5.1 in /packages/headless (#206)

Bumps [url-parse](https://github.com/unshiftio/url-parse) from 1.4.7 to 1.5.1.
- [Release notes](https://github.com/unshiftio/url-parse/releases)
- [Commits](https://github.com/unshiftio/url-parse/compare/1.4.7...1.5.1)

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>

* Contribution guidelines (#203)

* docs[repo](#201): adding basic contribution guidelines

* docs[repo]: adding semantic commits workflow

* docs[repo]: configuring semantic commits

* docs: configuring semantic commits

* fix: fixing broken links

Co-authored-by: William Johnston <will@wwj.dev>

* build(deps): bump lodash in /examples/getting-started (#207)

Bumps [lodash](https://github.com/lodash/lodash) from 4.17.20 to 4.17.21.
- [Release notes](https://github.com/lodash/lodash/releases)
- [Commits](https://github.com/lodash/lodash/compare/4.17.20...4.17.21)

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>

* build(deps): bump lodash from 4.17.20 to 4.17.21 in /examples/preview (#208)

Bumps [lodash](https://github.com/lodash/lodash) from 4.17.20 to 4.17.21.
- [Release notes](https://github.com/lodash/lodash/releases)
- [Commits](https://github.com/lodash/lodash/compare/4.17.20...4.17.21)

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>

* build(deps): bump lodash from 4.17.20 to 4.17.21 (#213)

Bumps [lodash](https://github.com/lodash/lodash) from 4.17.20 to 4.17.21.
- [Release notes](https://github.com/lodash/lodash/releases)
- [Commits](https://github.com/lodash/lodash/compare/4.17.20...4.17.21)

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>

* build(deps): bump lodash from 4.17.20 to 4.17.21 in /packages/headless (#212)

Bumps [lodash](https://github.com/lodash/lodash) from 4.17.20 to 4.17.21.
- [Release notes](https://github.com/lodash/lodash/releases)
- [Commits](https://github.com/lodash/lodash/compare/4.17.20...4.17.21)

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>

* build(deps): bump hosted-git-info in /examples/getting-started (#211)

Bumps [hosted-git-info](https://github.com/npm/hosted-git-info) from 2.8.8 to 2.8.9.
- [Release notes](https://github.com/npm/hosted-git-info/releases)
- [Changelog](https://github.com/npm/hosted-git-info/blob/v2.8.9/CHANGELOG.md)
- [Commits](https://github.com/npm/hosted-git-info/compare/v2.8.8...v2.8.9)

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>

* build(deps): bump hosted-git-info in /examples/preview (#210)

Bumps [hosted-git-info](https://github.com/npm/hosted-git-info) from 2.8.8 to 2.8.9.
- [Release notes](https://github.com/npm/hosted-git-info/releases)
- [Changelog](https://github.com/npm/hosted-git-info/blob/v2.8.9/CHANGELOG.md)
- [Commits](https://github.com/npm/hosted-git-info/compare/v2.8.8...v2.8.9)

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>

* build(deps): bump hosted-git-info in /packages/headless (#209)

Bumps [hosted-git-info](https://github.com/npm/hosted-git-info) from 2.8.8 to 2.8.9.
- [Release notes](https://github.com/npm/hosted-git-info/releases)
- [Changelog](https://github.com/npm/hosted-git-info/blob/v2.8.9/CHANGELOG.md)
- [Commits](https://github.com/npm/hosted-git-info/compare/v2.8.8...v2.8.9)

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>

* fix: lint fixes (#216)

* fix: lint fixes

* fix: updating packages and running lint:fix

Co-authored-by: William Johnston <will@wwj.dev>

* `core` broken out (#215)

* feat: setting up core package, removing references to react, next. Adjusting environment variables to be configuration variables

* test[core]:(#198) Adding config tests

* test[core]:(#198) moving config test file to mimic folder structure in src

* test[core]:(#198) finishing config tests

* fix: linting issues

* fix[core]: fixing lint warnings

Co-authored-by: William Johnston <will@wwj.dev>

* feat: break out `react` package (#217)

* feat: setting up core package, removing references to react, next. Adjusting environment variables to be configuration variables

* feat[react](#199): Begin scaffolding for decoupled React package

* fix[react]:(#199) Use new paths for imports and remove old deps from package

* fix[react]:(#199) Remove react components

* fix[react]:(#199) Remove components export from index and Add Todos

* make: use @wpengine/headless-core naming for now

* fix: Update import paths to headless-core

* fix: wildcard export of queries for react pck

* chore: bump @apollo/client to 3.3.17

* fix: add back `QueryResult` types in services

Adding back the `ApolloQueryResult` type as the `useQuery` hook in `@apollo/client` still returns `QueryResult` instead of `ApolloQueryResult`

* fix: when running dev-lerna don't clean before tsc

run `npm run bootstrap` prior to `npm run dev` to built packages for dev.

Removed the `clean` script from `dev-lerna` since we now have sibling packages relying on each other

* chore: remove old react submodule

* fix: set headless-core version to 0.6.3

* fix: package versions and names

* refactor: remove ununsed types

* fix: Match ApolloClient shape from core

* fix[core]:(#199) adjusting ApolloQueryResult | QueryResult to be more specific to support core and react modules. Adjusting package.json to list apollo and graphql as dependencies

Co-authored-by: William Johnston <will@wwj.dev>

* feat: break out `next` package (#219)

* feat: setup scaffolding for next package

* fix: Add @wpengine/headless-react dep

* fix: sibling dependency imports

* fix: export HeadlessProvider for headless-next

* fix: include nextConfig

* fix: export authorizeHandler

* fix: remove next as dependency

* fix: add wpgraphql definition

* fix: include reference to wpgraphql definition

* refactor: include core utils under submodule

* fix: include next definition reference

* refactor: remove WPHead

* Publish `core`, `react`, and `next` (#226)

* chore: incrementing package versions

* chore: setting package urls

* chore: #223 updating react to use canary core

* chore: #223 updating next to use canary core and canary react

Co-authored-by: William Johnston <will@wwj.dev>

* ci: setting up linting automation (#222)

* ci: setting up linting automation

* fix: removing graphql devDependency

* fix: #221 lint fixes and package increment

* fix: #221 lint fixes and package increment for react

* fix: #221 lint fixes and package increment for core

Co-authored-by: William Johnston <will@wwj.dev>

* build(deps): bump wp-cli/wp-cli in /plugins/wpe-headless (#231)

Bumps wp-cli/wp-cli from 2.4.1 to 2.5.0.

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>

* docs: Next.js getting started example with decoupled packages (#237)

* Next getting started example

* fix: Use released headless packages on NPM

* feat: Add pagination, SSG for archive pages

* refactor: document the permalink category base

* refactor: category URL in archive getStaticProps

* make: lerna dev scripts

* fix: site titles and scss home page styles

* fix: revert next package changes

* refactor: remove re-exports from higher-level headless libs (#229)

* refactor: remove re-exports from higher-level headless libs

* fix: typescript-eslint and prettier rule conflict

* fix: lint scripts for ci

* fix: remove prettier/@typescript-eslint

* Revert "fix: lint scripts for ci"

This reverts commit f6c86ec120194a87a5efa3ccef80249c953a6c42.

* fix: Use core linting scripts

* fix: ESlint warnings

* style: Use src directory in examples/next/getting-started (#242)

* style: use src dir for components, pages, & scss

* chore: remove old styles

* refactor: remove custom next.config.js implementation

* style: update tsconfig baseUrl for src dir

* refactor: (#239) removing unused code and using baseUrl for imports

* fix: npm audit

Co-authored-by: William Johnston <will@wwj.dev>

* refactor: remove nextConfig.js (#243)

* refactor: remove custom nextConfig implementation

* fix: npm audit

* docs: update changelogs for 0.6.4-0.6.5 (#245)

* Tests: Create tests for Next package (#247)

* refactor: specify modules for export

* test: add tests for stringifyQueries

* test: getStaticPaths default and overridabale tests

* test: suites for utils

* Create tests for `core` package (#248)

* test[core]: (#246) adjusting config exports to allow for granular testing, making config params immutable, adding tests for mutability

* test[core]: (#246) adding assert tests

* test[core]: (#246) adding assert tests

* test[core]: (#246) adding cookie tests where possible

* test[core]: (#246) adding assert tests

* test[core]: (#246) adding assert tests

* test[core]: (#246) adding auth middleware tests

* test[core]: (#246) adding auth/authorize tests

* removing hanging fetch

Co-authored-by: William Johnston <will@wwj.dev>

* headless-plugin: do not rewrite post links in GraphQL response (#250)

To prevent an issue where post uris are returned
with a localhost prefix but page uris are
returned with just the path.

Both post and page uris will now be only the path.

* chore: prep Headless Plugin 0.5.5 for release (#251)

* Tests: Create test for React package (#249)

* fix: jest config for react package

* refactor: only export what is necessary

* test: create useGeneralSettings custom hook test

* test: useUriInfo test

* fix: use version 1 lockfile

* fix: eslint issue

* fix: middleware conflict

* fix: update lint script to use ts parser

* chore: npm audit

* fix: remove unused imports

* Add root-level scripts for linting and testing (#253)

* chore: (#252) adding linting and testing scripts

* chore: (#252) modifying eslint action to use root script

* chore: (#252) modifying eslint action to install the right dependencies

* chore: (#252) adding testing github action

* chore: (#252) adding testing github action as separate file

* chore: (#252) fixing tsconfig files in react and next packages to allow for better monorepo intellisense

* chore: (#252) adding react and react-dom devDependencies to next package

* chore: (#252) renaming action tasks

* chore: (#252) renaming action tasks

Co-authored-by: William Johnston <will@wwj.dev>

* chore: (#254) removing lerna, adding root scripts for bootstrapping (#256)

Co-authored-by: William Johnston <will@wwj.dev>

* Add ESLint Ignore Patterns for IDE ESLint plugins (#257)

* chore: (#255) add ESLint ignore patterns

* Revert "chore: (#255) add ESLint ignore patterns"

This reverts commit dff565bb7a877e92cc85dd29e4d614ee146e75c4.

* chore: (#255) revert and fix formatting

* chore: fixing refresh script to not install with a prefix (#258)

Co-authored-by: William Johnston <will@wwj.dev>

* fix: (#259) ESLint scripts on MacOS (#260)

* Removing apollo and adding gqless (#264)

* chore: (#262) removing apollo and adding gqless

* feat: (#262) adding ability to intercept request context and apply headers, adding client-side auth header

* feat: (#262) incrementing versions

* feat: (#262) add gqless to React package (#265)

* chore: (#262) removing apollo and adding gqless

* feat: (#262) adding ability to intercept request context and apply headers, adding client-side auth header

* feat: (#262) incrementing versions

* feat: (#262) create client

* refactor: (#262) remove apollo

* refactor: (#262) headless provider

* feat (#262): create hooks using gqless

* feat: (#262) provide client creation options ability

Co-authored-by: William Johnston <will@wwj.dev>

* fix: (#266) fix headlessConfig() setter (#267)

* feat: resolve/infer URL from Next context (#263)

* feat: utils to determine url from context

* test: getUrlFromContext and other utils

* fix: add react as dev dependency for test

* chore: npm audit

* fix: getCurrentUrlPath uses getUrlFromContext + tests

* fix: Add jest types for monorepo development

* fix: eslint issues

* refactor: reorganize getUrlFromContext

* fix: add @apollo/client dep

* feat: infer pagination archive urls

* Gqless next implementation (#268)

* chore: incrementing package versions

* feat: (#262) adding next gqless support, adjusting react typings to test merging

* feat: adding is404, exporting core client on react and next clients (#269)

* feat: (#278) create react example (#282)

* feat: react example

* feat: design/styles for react example

* fix: navigation

* fix: preview route

* feat: enable previews in React example

* feat: ability to specify the api URL

* feat: env template

* feat: finalize home page and add titles

* feat: start server script

* refactor: bootstrap

* fix: react helment titles

* refactor: use canary packages

* refactor: use the default client

* refactor: add local types

* chore: adjusting typings to avoid having to cast, adding linking scripts

* fix: requested changes

Co-authored-by: William Johnston <will@wwj.dev>

* fix: (#284) preview example alerts (#285)

* Getting started migration (#283)

* exporting next client

* doc: (#273) adding post list and single post pages using canary framework

* doc: (#272) adding pageUri page

* fix: correct router provider for getNextStaticProps

* fix: example is using new getNextStaticProps interface

* chore: adding next lint and fixing lint error

* fix: is404 will always refetch the entity

* feat: (#274) migrate categories

* chore: setting up workspaces

* chore: fixing actions to install and run correct scripts

* chore: actions use node 14

* chore: correcting action

* chore: correcting action

* chore: correcting test action to not run npm test

* chore: removing node version matrix from action

* chore: testing version action

* chore: testing version action

* chore: using node 15 to get npm 7

* chore: actions are building before running test or lint

* chore: actions should be working now with correct npm version

* doc: (#276) pagination working for posts

* doc: (#276) using pagination component for post pagination

* chore: removing unused code

* doc: (#276) pagination component using const and exporting props interface

* feat: (#272) demonstrate custom page use

* doc: adding 404 functionality to posts, adding featured category page and header link to blog

* feat: adding optional logger for queries

* feat: (#277) category pagination

* fix: lodash linting error

* fix: Add 404 checks to pages/categories

* fix: (#281,#271) previews working in next example

* fix: adding preview file

* fix: useHydrateCache always restores cache, logger is direct import

* chore: incrementing versions

* fix: removing console log

* chore: removing unused code

* refactor: prepare for demo

* feat: Add custom 404 page

* fix: display featured image on post/page if exists

* refactor: remove unused deps from example

* chore: incrementing package versions

* doc: (#271) adding page and post previews to a single page

* chore: using next package versions

* chore: updating dependencies

* fix: lint issue

Co-authored-by: Blake Wilson <blake.wilson@wpengine.com>

* fix: (#284) glob-parent, normalize-url (#286)

* doc: (#287) using core types for pagination and posts (#288)

* Dependabot fix (#291)

* fix: (#290) removing old package-lock.json

* fix: (#290) removing old headless/package-lock.json

* fix: (#290) updating headless packages

* ci: removing packages/headless build from CI since it is deprecated

* ci: removing packages-headless build from CI since it is deprecated

* Custom client functionality (#295)

* doc: (#279) adding project with custom client

* feat: (#279) enabling custom clients as well as server-side clients, adding custom client to getting-started

* feat: (#279) enabling ssr for authenticated client requests

* fix: (#290) Replace node-sass with sass (#294)

* fix: node-sass -> sass, remove react example from workspaces

* fix: minor/patch scripts

* refactor: remove old codegen tools

* chore: (#296) incrementing package versions (#297)

* Migrate react example 0.7 (#299)

* refactor: use new 0.7 client

* fix: use plain WP schema

* refactor: use ReactClient interface

* refactor: use schema types

* make: fix trim-newlines dependabot alert (#300)

* Setting @faustjs as framework name (#319)

* feat: (#317) setting @faustjs as framework name

* fix: lint issues

* docs: Initial docs setup for FaustJs (#320)

* feat: docusaurus setup

* chore: clean up docusaurus config

* docs: start data fetching in next

* docs: usePage next hook

* docs: useGeneralSettings hook in next

* docs: WIP params, ssg, ssr, data fetching

* docs: next client generation

* docs: data fetching hooks, custom client usage

* docs: usePages hook

* docs: ssr/ssg

* docs: (#306) create CPT guide

* fix: custom post types guide title

* docs: (#306) clean up CPT guide (#322)

* Reference doc for SSR and SSG (#323)

* doc: (#310) finishing ssr and ssg doc, moving is404 to new file, adding HeadlessProvider information

* doc: adding files and updating packages

* doc: (#307) completing doc for hooks and fetching data (#328)

* doc: (#309) finishing 404 doc (#325)

* Refactor React Hooks (#330)

* refactor: (#327) remove react hooks from client and example

* refactor: (#327) remove `useGeneralSettings` and `usePages` from next client

* Refactor `getNext...` and `is404` config  (#329)

* feat: (#321) Support revalidate config option

* feat: (#321) support `redirect` and `notFound`

* refactor: (#321) destructure revalidate

* test: (#321) create tests for getNextServerSideProps and getNextStaticProps

* refactor: (#324) Update is404 param structure

* docs: (#324) update is404 docs

* refactor: (#324) use `notFound` config key for is404

Co-authored-by: Clay Griffiths <clay@claygriffiths.com>
Co-authored-by: Nick Cernis <nick@cern.is>
Co-authored-by: Trevan Hetzel <trevan@hetzelcreative.com>
Co-authored-by: Ryan Meier <ryan.meier@wpengine.com>
Co-authored-by: John Parris <john.parris@wpengine.com>
Co-authored-by: Ben Greeley <bengreeley@users.noreply.github.com>
Co-authored-by: Mark Kelnar <markkelnar@gmail.com>
Co-authored-by: Clay Griffiths <clay.griffiths@wpengine.com>
Co-authored-by: Mateusz Czapliński <mateusz.czaplinski@wpengine.com>
Co-authored-by: Ajit Bohra <ajit@lubus.in>
Co-authored-by: Matt Landers <matt-landers@users.noreply.github.com>
Co-authored-by: Matt Landers <matt@platypi.io>
Co-authored-by: Matt Landers <matt.landers@wpengine.com>
Co-authored-by: Nate Archer <12628964+DonNateR@users.noreply.github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Brandon DuRette <bdurette@users.noreply.github.com>
Co-authored-by: Blake Wilson <blake@blake.id>
Co-authored-by: Blake Wilson <blake.wilson@wpengine.com>
@amjadgoldev
Copy link

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);
                });
            }
        }
    });

@dextorlobo
Copy link

dextorlobo commented Aug 10, 2021

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.

@benknight
Copy link

benknight commented Aug 24, 2021

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);
	}
});

blakewilson added a commit to wpengine/faustjs that referenced this issue Sep 3, 2021
Work around for using the correct preview links in draft posts in the Gutenberg editor as described in WordPress/gutenberg#13998
wjohnsto pushed a commit to wpengine/faustjs that referenced this issue Sep 3, 2021
* Create withFaust next config helper

* Use preview post/page revision if it exists

* Use `wp_localize_script` to add the correct post preview link to the page

* Testing for nextConfig/withFaust

* Add `post_type` to preview URL

* Remove post type from preview URLs

* Fix preview replacement test

* Use get_preview_post_link for Gutenberg preview links

Work around for using the correct preview links in draft posts in the Gutenberg editor as described in WordPress/gutenberg#13998

* Fix linting errors

* Fix enqueue_block_editor_assets add action test

* Clean up

* Merge redirects if they exist in next config

* Fix tests

* Do not use permanent preview redirects

* fix: preview redirect source
@emanuellopes
Copy link

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;
    }
}

pcraig3 added a commit to cds-snc/gc-articles that referenced this issue Feb 11, 2022
pcraig3 added a commit to cds-snc/gc-articles that referenced this issue Feb 14, 2022
pcraig3 added a commit to cds-snc/gc-articles that referenced this issue Feb 14, 2022
* Add JS to make the preview link work

Source:
- WordPress/gutenberg#13998 (comment)

* All good in the hood
pcraig3 added a commit to cds-snc/gc-articles that referenced this issue Feb 14, 2022
pcraig3 added a commit to cds-snc/gc-articles that referenced this issue Feb 17, 2022
* Add JS to make the preview link work

Source:
- WordPress/gutenberg#13998 (comment)

* All good in the hood

* cypress fixes? maybe? unclear

* Try skipping site settings

* unskip 1 test

* Log out pls

* Move the code

* add a then, see what happens

* move redirector test to the end

* Rename some files

* make it work

* save the screenshots

* Add most of the specs back

* Green-light alert

* Skip alert test only

* try new alert test

* Add the notify tests

* unskip alert tests

* track login panel tests

* unskip them all

* Return gitignore files

* Don't save screenshots

* unskip
roles tests

* Update cypress

* Revert changes to alert block

I re-wrote the test to try and get it working, but it didn't help,
so reverting to the original one.
gilzow added a commit to gilzow/wordpress-nextjs-test that referenced this issue May 23, 2022
@oseisaac
Copy link

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

@ltroya-as
Copy link

ltroya-as commented Jul 28, 2022

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

@emanuellopes
Copy link

$_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.

@emanuellopes
Copy link

you can put this code on funtions.php like this

new App\Routes\PreviewArticle();

don't forget to use composer to autoload the file

@bph
Copy link
Contributor

bph commented Jul 16, 2024

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.

@bph bph closed this as not planned Won't fix, can't repro, duplicate, stale Jul 16, 2024
@rodrigo-arias
Copy link

There are indeed workarounds to achieve this, but in my opinion, it's not an edge case. Most headless implementations require this functionality.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
[Feature] Document Settings Document settings experience [Feature] Extensibility The ability to extend blocks or the editing experience REST API Interaction Related to REST API [Type] Bug An existing feature does not function as intended
Projects
Development

No branches or pull requests