After selecting related pages in pages field, update all those pages own related pages field

I have a ‘related’ pages field on a sidebar which is used in several blueprints:

  related:
    label: Related Updates
    type: pages
    query: page.siblings(false)

When in a page this field is populated with another or several pages, I would need to loop them and update their own related pages field with this one. So being in page A and selecting pages B and C as related, should result in pages B and C having A as related aswell.

I assume this would be a create/update hook which would filter by any of the blueprints that have such related pages field. Then… I assume I would get the contents of that just updated field, loop over the pages in there, and … how do I update the contents of the related pages field in those other pages ?

Thank you

Yes, that would work, but why do you want to do that?

But how do I update the pages field, do I have to convert the pages field and loop , then encode as yaml ? like for example here: Updating structure field in page.update:after hook ?

I want to do this because I am relating news items, they show as related in each other pages in frontend, but this information comes from this field, so if A is related to B , B should show as related to A.

Am I making sense?

Thank you

In my opinion, it would be enough to store the relation in one place.

Yes, you need to yaml::encode and decode.

That does make a lot of sense, to store the relations in a single place, but in this site it would make sense aswell to be able to read and modify this information from each of this pages.

What is there in kirby that can behave in such a way with as little ‘‘hacking’’ as possible?

Thanks again.

The only way to do that would be with hooks, but keep in mind that you would have to update the information in all other fields if the page IDs change, unless you use the AutoID plugin or a similar mechanism (but currently, that is not possible with a pages field) to store permanent references.

There might also be a certain risk if you update multiple pages from a hook while they are currently being edited.

It really makes things much more complicated the way you intend to do it.

Maybe storing the relations in a SQLite database would make more sense.

Hmm… the structure of this site is something like:

site
    project N
        update A
        update B
        ...
    ...

update pages are the ones that need to be related among them.

Could I perhaps store the relations somewhere hidden at project level and retrieve them from each update page using query lang?

Although It seems very problematic to store and retrieve this kind of matrix-like information without a proper tool, such as a db as you mention.

/edit
Related question, when is a query in a field updated? when I open the page in the panel ?
If the origin of the query changes meanwhile, would the field show the new values in any other situation than fully reloading or re-entering the page? on save perhaps?

You cannot update field information via blueprint query language, if that’s what you mean, you would have to update the parent via a hook as well but that seems to be less critical to do that updating lots of pages.

Again, I would really like to understand your reasoning behind storing these relations in all places.

Ok,
User enters panel and creates project A, fills info, saves etc.
Within project A user creates update 1 page, and a few days later update 2 page.
Even later user creates update 3 page, which is related to update 2. S/he then selects update 2 page from a type:pages field populated by siblings. In the frontend, visiting update 3 page shows a sidebar with a list of related updates, which reads from this pages field, and so update 2 is shown.

But if 2 and 3 related it just makes sense that when visiting 2, 3 also shows on the related sidebar, so it should be included in the panel page of this update, in its type:pages field.

This is where the original question comes from.

I could have the user set all this relations in a single field in project A’s panel page. But imo when user creates update 3 and wants to establish a relation with update 2, it makes sense s/he can do it right there right now, instead of going up one level to do it, every time.

I do not explicitly need to update all pages via hooks, tho, but a way to set and get all the relations from every page. It could be two fields in every update page, a disabled field which reads the relations for that page from a centralized source, and displays them, and another field that allows the user to set relations for that particular page.

I was asking about query lang, because I thought perhaps I can build a custom function that receives the page object and returns its relations by reading them from somewhere in project A .txt file. Then I could have , for example, a disabled multiselect field, which would call this function via query lang.

This would solve the ‘get’ or ‘display’ part of the problem, but not the ‘set’ part… that is why I was asking when does a field update its contents in a panel page. I mean, in the case of the multiselect field, if the source of the query changes while we are in the page, in which case would the field display these changes ? On page save for example ? Or only exiting and entering the page again ?

I could have a type:pages field populated via siblings, then user could select related siblings, and on save, a hook would store this siblings somewhere in project A and clean the field. But I would like to know if on save, the disabled multiselect will show the changes, or if I can make it show them via a hook.

thank you

What I was trying to suggest:

If user on update 3 adds a relation to update 2, you can still fetch all relations of update 2 by filtering all siblings by the pages field without having to enter this relation additionally in update 2.

Oh, but of course, that is true and very convenient!

But if I am understanding it right, tho, this allows me to show the list of pages that have this page in a certain field, call it ‘setter’.

But I still need this ‘setter’ field.

If I have something like this in every page (pseudo):

getter
  label: gets and displays all pages that show a relation to this page
  type: ??
  query: all siblings that have this page in their setter field

setter
  label: sets relations with other pages
  type: pages
  query: page.siblings(false)

…setter and getter should show the same pages… because if page C says it is related to this page, this page is related to C too.

Because I can only query the options right? not the actual selected pages.

Thanks

For the getter you would need the pagesdisplay section plugin. Otherwise, you would only get options to select.

But this getter is not really needed for the frontend functionality, but only if you want a way to show these pages to the user.

Thank you, and yes, it is not needed for the frontend functionality as you say.

Regarding syncing both setter and getter (even if getter was not shown) is there any way ? Again, is there any field or option that allows to set, not the options, but the selected items of a , say, pages or multiselect field?

Thank you

No, unless you create a custom field. Sorry, I’m not following you, but for what purpose? Wouldn’t it be enough to show the related pages in a pages display field rather then the selected option on some other field?

Sorry, perhaps I am not explaining myself well or not understanding.

The display field allows me to show, in page A, every sibling which has page A selected in another field.

Because this field just displays, does not allow to select, I still need to select related pages.

So I need two fields. One displays ( the 'getter ), the other selects, (the ‘setter’) right?

This is ok, to an extent. But it most probably will show something like:

in page A
setter: page B
getter: page C

…which means that in page A I set page B as related, and that in page C I set pace A as related. If this is what we were talking about this is imo a bit confusing. Ideally a single field would have both the pages selected in page A and the pages in which page A is selected such as:

page A
settergetter: page B (selected here), page C (because in page C, page A is selected)

Thanks

@pixelijn @texnixe (same person right?) Did I explained myself well in my last message? does it still make no sense? Can we confirm this is only possible via a custom field ?

And on that line, is it actually feasible to write a custom ‘pages’ field that would accept a query for selectable pages AND a query for pages that will show as already selected, and still allow the user to select their own pages?

pseudo:

Related
  label: Related 
  type: pages_custom
  query: pages that will show as selectable
  query_selected: pages that will show as already selected and that user will not be able to de-select

Thank you and sorry for bumping the post.

It’s DID.

I think someone else has to get in here, my brain doesn’t follow you.

All I can say (and after that I will shut my face): If it was my project, I would use a single pages field that stores my relations. On the frontend, I would then filter the siblings by that related pages field. That’s it. It doesn’t matter if someone creates relations both ways or not. Or you can even create a query that only queries those siblings that do not yet reference the current page (unnecessary, IMO). No hooks or other fancy stuff.Everything else is overkill in my opinion.

A post was merged into an existing topic: Programmatically change the content of the file field

It’s an old thread, but upon revisiting, I remembered I once had a K2 plugin for this. I’ve updated it for K3. The code is a bit messy, lacks a readme, but it functions well. Feel free to comment or submit pull requests.

Cheers!