Header injection

How would I inject YAML into the header before it gets processed? I thought I could go into the onBuildPagesInitialized event, but that appears to be too early. I want to use Grav\Common\Page\Header to set new values before it gets rendered. Is onPageInitialized too late? I’ve tried both but I can’t find the right event key or method to get me the page object. Any guidance appreciated!

onPageProcessed might be the earliest, but the taxonomy hasn’t been loaded yet, and that’s something I’d need access to. Hrm.

I recognize that there are lots of headers I can’t meaningfully change at these event points (I see plugins are already processed), but I’m thinking of injecting metadata keys so Grav can output the correct tags.

The filesource plugin hooks onto the onPageContentRawevent and gets the Page object via $event['page'], but that’s not working at those other event points.

I’m an idiot. I’d delete this whole thread if I could. I did this already in another plugin I did. The answer is $page = $this->grav['page']; /sighs/

So while I can now access the headers, when I inject new ‘metadata’ subkeys and values, they don’t get rendered in the final HTML. I’m currently hooked into onPageInitialized.

I tried hooking to onPageProcessed but that appears to be too early. All I managed to do was force a 404. I want to inject tags (and possibly other header content as well) based on taxonomy.

You need to set the modified header back on the page object with:

$page->header($header);

However, if you wan this to persist to cache rather than doing this on every page requests for this page, then you need to use a onPageContentRaw() or onPageContentProcessed

That’s what I do:

$page = $this->grav['page'];
$header = $page->header();
$header = new \Grav\Common\Page\Header((array) $header);
$header->set('metadata.some.nested', 'value');
$page->header($header->items);

But still no gets outputted.

Thanks for the life cycle tips. I thought it might be too late by those points. I’ll try those.

That’s the last line of code in that function, though. Not sure if there’s something else I need to do to finalize it.

Yeah, moving to onPageContentProcessed didn’t change anything either. I dumped the $header at the top and $page->header() at the very end, and the changes make it, but no meta tags are outputted.

I did some more testing. If I stick to onPageInitialized, then it turns out I can activate plugins (e.g., setting the header pubmed.active: true). I assume that the expanded shortcode still gets cached.

Actually I have you the wrong event, should be onPageProcessed

Now I just get weird 404s. Where in the life cycle exactly are the metadata keys and values pulled from the header and rendered to HTML (https://learn.getgrav.org/content/headers#meta-page-headers)?

Well, they are processed when pages are built with Page::init(). After each page is processed onPageProcessed is called passing that page via the event. this is the best place to manipulate anything related the headers.

This init() method calls Page::metadata() where the metadata is pulled from headers, merged with site-level config, and stored in Page::$metadata - https://github.com/getgrav/grav/blob/develop/system/src/Grav/Common/Page/Page.php#L1328-L1386

So, you need to get the $page->metadata() do your work on it an set it back via $page->metadata($metadata) from the onPageProcessed() event. That should fix everything :slight_smile:

Thanks. I will see what I can do.

The trick, though, is that I want the core Grav metadata code to do the work. If the user wants to inject Twitter cards or a refresh value, the Grav code already detects and handles that. I don’t want to duplicate that function and it’s supporting hashes. Ideally I’d nullify the existing metadata and just retrigger the metadata() method. But I can’t do that because Page::metadata is protected, and Page::metadata() doesn’t have a facility for nullifying the data once it’s initialized.

I don’t have any skin in this game. It was a plugin idea I saw and so decided to tinker with. It seems to work for activating plugins, and I need to test if it’s also working for custom twig variables, but it’s the tags that are not working. If there’s no easy fix on the Grav side of things, I understand it’s not a priority and I’ll just scrap the plugin for now. If there is a way to accommodate, then let me know and I’ll go from there. For now I’ll leave this one and look at webmentions.

Thanks!

Well I think you can do whatever you need by getting the pre-processed metadata with Page::metadata() this gets a simple array. Then you can null things, or set new things, or modify existing things directly on this array, then set the ‘modified’ array back with Page::metadata($metadata).

But the core code detects things like http_equiv, and that’s reflected in the returned array. So the plugin would have to also detect those things and adjust the array correctly (basically copy/paste the Page::metadata() function). Ideally, I’d let the Grav code do that by it just reparsing the modified header.

For now, because everything else is working as expected, I’m going to copy/paste the Grav code and just publish. If a workaround becomes available, then great.