Handlers for non-URL data

@SantosGuillamot has started a PR for the first non-URL handler: comments!

Hi, this is my first comment. I’m in investigation frontity for my project, and from my perspective this is great thing. Currently, I’m trying to implement menu, but I can’t understand location for code above.

1 Like

Hey @nihad.obralic, welcome to the community :slight_smile:

This is still a work in progress. I recommend you to stick to a simpler menu, probably stored in the frontity.settings.js file (like the one in mars-theme) for now.

When we finish this work we’ll announce support for WP menus, edited in the dashboard.

Thank you.

I’m using wp-rest-api-v2-menus/ plugin for now. I’m able to get all necessary data, but there are also plenty of redundant data. Imho it would be great to us “Wordpress Frontity Menu Rest” plugin. Which could return tailor-made data for Frontity needs.

I’ve also played a bit with WP-API/menus-endpoints mostly with widget part. And so far widget part is totally useless.

I was trying to get widgets for particular sidebar:
http://example.com/wp-json/wp/v2/widgets?sidebar=default
and this is what I’ve got:

[
  {
    "id": "custom_html-2",
    "type": "custom_html"
  },
  {
    "id": "media_gallery-2",
    "type": "media_gallery"
  },
  {
    "id": "links-2",
    "type": "links"
  },
  {
    "id": "recent-posts-2",
    "type": "recent-posts",
    "title": "recent posts",
    "number": 5,
    "show_date": false
  }
]

I expected totally different data. I thougt this endpoint will return let’s say html for every single widget.
I finished with custom rest endpoint. I’m not a PHP developer, but friend of mine prepared this code for me:

<?php
function get_sidebar($data) {
	$id = urldecode($data['id']);
	ob_start();
	dynamic_sidebar($id);
	$sidebar = ob_get_contents();
	ob_end_clean();
	return array('id'=>$id, 'content'=>$sidebar);
}

function get_sidebars() {
	$results = array();
	foreach ( $GLOBALS['wp_registered_sidebars'] as $sidebar ) {
		$results[] = sbc_get_sidebar(array('id'=>$sidebar['id']));
	}
	return $results;
}

add_action( 'rest_api_init', function () {
	register_rest_route( 'wp/v2', '/sidebars', array(
		'methods' => 'GET',
		'callback' => 'get_sidebars',
	));
	register_rest_route( 'wp/v2', '/sidebars/(?P<id>[%a-zA-Z0-9_-]+)', array(
		'methods' => 'GET',
		'callback' => 'get_sidebar',
		'args' => array(
			'id' => array()	
		)
	));
});
?>

I think the best solution for all those problems could be a set of wordpress plugins dedicated for Frontity:

  • Yoast Meta Frontity,
  • Menu Rest Frontity,
  • Sidebars Rest Frontity.
    and so on.
1 Like

Hi @LiamMcKoy, we are about to release the Yoast Plugin in the next days. It will be a more general plugin because it will expose all tags in <head> and will work with other SEO plugins, so we are considering to change its name to something like REST API Head Tags.

About the others, we have already in mind to create a bunch of plugins to help WordPress integrate with Frontity, so thanks for your suggestions! :blush:

1 Like

An update about the menus endpoint on WordPress. It looks like it will probably get merged in the WordPress core in the 5.4 version:

1 Like

Hi there! :wave:

We’re planning to start working on the comments package in the coming weeks, but first we have to take a decision about handlers for non-URL data. Here we have a quick summary so we can continue the discussion:

  • Our initial idea was to use the same API than the URL data, but doing minor changes like not using the initial slash or adding any character before:
actions.source.fetch("comments/123") //without slash
actions.source.fetch("!comments/123")

It would be and standard, nothing constrained.

  • We have to populate the state the same way everything is stored in Frontity. For example, the comments should be stored in state.source.comments[commentId].

Any thoughts? Anything to discuss about?

I think that it’s going to be more obvious that this is not a URL if we use a distinctive character.

We can modify actions.router.set so it throws when the link passed doesn’t start with "/".

If we do that, we can use any character we want, reserved or unreserved:

// Throws because it's not a valid URL.
actions.router.set("comments/123");
// Throws because it's not a valid URL.
actions.router.set("@comments/123");

// Doesn't throw, this could be a valid URL:
actions.router.set("/comments/123");
// Doesn't throw, this could be a valid URL:
actions.router.set("/@comments/123");

From the list of possible characters:

reserved = ";" | "/" | "?" | ":" | "@" | "&" | "=" | "+" | "$" | ","
unreserved = "-" | "_" | "." | "!" | "~" | "*" | "'" | "(" | ")"

I like actions.source.fetch("@comments/123") the most.


We also need to make a decision about this :point_up_2:

But maybe it’s better to open a feature topic for the comments handler to start discussing about this @SantosGuillamot? :slight_smile:

I like the approach of using a special character, I agree is more obvious and we can throw errors if it doesn’t start with "/" as you said.

Regarding which character, maybe we should try to use one that is not commonly used for other “code” purposes, so it isn’t confusing. For example, I’m aware that the "$" character could be used inside regex or template strings right? Or the "!" could be confused with the logical “not” operator. Not sure if these would be confusing or not, you’ll know better about this.

Btw, I think "@" is not confusing at all, so we can go with it.

Sure, I’m planning to add two new topics for both the menu and the comments. I wanted to keep this topic just for the handlers for non-URL data. I’ll reference them here once they are open.

Awesome! :clap:

By the way, should we open a feature topic for the comment handler and a feature topic for the comment package or only one for the comment package that contains a user story for the comment handler? What do you think?

I thought about that some time ago, and I think it makes sense to split it, although I’m not 100% convinced :grin: .

Right now, Frontity is handling all the WordPress default content like posts, CPT, taxonomies, authors… and populating the `state, and the themes decide how to consume this data. I think WordPress works in a similar way: you can get all the comments with a PHP function, but the theme decides how to show them.

So I feel it could be a good approach to create a handler that populates the state in an easy way to consume, and add an example of how to consume it in mars-theme.

In the future, if we see this is not enough, we can work on the feature of building a comments component.

Btw, I think is something that will happen again, for example with the menus.

I see. Well, one problem is fetching the comments (handled by wp-source via actions.source.fetch("@comments/1232") but another is creating new comments. I don’t think themes should have to implement the logic of creating a new comment…

The @frontity/wp-comments could expose:

  • Comments: a component that shows both the comments and the form to create a new one.
  • CommentForm a component to create a new comment.
  • actions.comments.create(...): an action for those themes that want to create the form themselves, but don’t want to implement the logic.

Apart from that, we need to investigate a way to pass down styles to an external component:

I think this works, but I’m not 100% sure:

const commentsStyles = css`
  margin: 0;

  .commentItem {
    color: red;
  }
`;

const Post = ({ ... }) => {
  return (
    <>
      ...
      <Comments className={commentsStyles} />
    </>
  );
}

Okay, I like the approach you suggest. I’ve opened a new topic in order to keep talking about this. Let’s keep this one for the handlers for non-URL data.

Hi there! Just wanted to say (in case you are not aware of it) that currently when I use a @something pattern, the data object still gets populated with link and query and those things. I think this doesn’t make much sense. Is this something you already thought about?

Hey @orballo :wave: Yes, I’m working on updating the wp-comments package to use the REST API in https://github.com/frontity/frontity/pull/542/ and I’ve just realized the same problem.

I think that we’ll have to update the source.libraries.populate(), the CommentData source type and the comments handler to account for that (and possibly something else).

My bad, it’s actually unrelated

However, I think it’s quite harmless to populate those. Since we populate every link with entity with link, route, query & page here

I’m guessing that we just could add a simple check to not add a query & link or route if the link starts with @:

// This is state.source.get

get: ({ state }) => (link) => {
	// ...
	if (normalizedLink.startsWith("@")) {
	  return { page, isFetching: false, isReady: false }
	} else { 
	    return {
	      link: normalize(normalizedLink),
	      route,
	      query,
	      page,
	      isFetching: false,
	      isReady: false,
	    };
	}
}

Any reasons against it?

@orballo Update: This will be updated according to how I mentioned previously. The query, route and link will be removed from non-URL entities in the data object like:

if (normalizedLink.startsWith("@")) {
  return { page, isFetching: false, isReady: false }
} else { 
   return {
      link: normalize(normalizedLink),
      route,
      query,
      page,
      isFetching: false,
      isReady: false,
   };
}
1 Like

Have these plugins been released yet?

Im currently using a plugin called WP REST API Sidebars, https://en-gb.wordpress.org/plugins/wp-rest-api-sidebars/, to expose and get my sidebars. However, all of the links point back to the original WordPress site. For example when I click on a post in the Recent Posts widget im directed back to the original WordPress site.

Do you have any suggestions on how best to fix this?

Any help would be appreciated.

Hi @leogardner12!

Right now we only have the REST API - Head Tags plugin and we are working on a plugin for the embedded mode.

Regarding this, I would recommend you a couple of things:

  • Redirect your WordPress urls to Frontity urls, excludings the ones for the admiin, the REST API…
  • Use our link processor to handle the routing, and use html2react for the widgets you mention. You can see more information at this other Feature Discussion that has already been released.

Putting this down for people searching for the reason why their translations/multisites aren’t working properly, and how this topic is the solution.
Additionally I hope that the solutions implemented won’t break any workaround, like the one described below.

While working on a multilingual website in Frontity I noticed that custom handlers break on subdirectories (eg. https://example.com/nl/) because the handler route was being “redirected”.

For example retrieving the menu on the main website worked without a problem, but didn’t even reach the menuHandler (like menu-handler.js).

After a lot of debugging I fixed it by simply adding an @ in front of the route of the handler(s), so they wouldn’t be redirected and therefor return nothing.

2 Likes