Porting panel.page.update hook to Kirby 3 syntax

Hi There, I’m trying to update a couple of panel.page.update hooks for Kirby 3, I’ve only started on one now, but I’m encountering a weird inconsistency. The hook checks for the dates of the children of a page whenever a date is changed and updates the date span for the parent page (@texnixe you were super helpful in getting this running in 2!).

In the updated hook that i’ve gotten mostly working, the date on a child page has to be changed twice and the is a step behind. It’s very strange. So if a child starts as 2018, and I change it to 2017, nothing happens, but if I change it back to 2018, or to any other date, Then it changes the parent to 2017.

Here was the Kirby 2 hook:

<?php

kirby()->hook('panel.page.update', function($page) {

    if($page->parent()->template() == 'series_visual') {
        $parent = $page->parent();
        $firstSibling = $parent->children()->sortBy('date', 'desc')->first();    
        $lastSibling = $parent->children()->sortBy('date', 'asc')->first(); 
        $date = $firstSibling->date('Y-m-d');
        $year = $lastSibling->date('Y-m-d'); // use format you use in date field of other pages
        try {
            $parent->update([
            'date'  => $date,      
            'year'  => $year          
            ]);
        } catch(Exception $e) {

            echo $e->getMessage();
            
        }
        
    }
    
});

And here is what I have so far for Kirby 3:

<?php

Kirby::plugin('rgolightly/datehooks', [
    'hooks' => [
	    'page.update:after' => function ($page) {
	    
    	if($page->parent()->template() == 'series_visual') {
        	$parent = $page->parent();
        	$firstSibling = $parent->children()->sortBy('date', 'desc')->first();    
        	$lastSibling = $parent->children()->sortBy('date', 'asc')->first(); 
        	$date = $firstSibling->date()->toDate('Y-m-d');
        	$year = $lastSibling->date()->toDate('Y-m-d'); // use format you use in date field of other pages
        try {
            $parent->update([
            'date'  => $date,      
            'year'  => $year          
            ]);
        } catch(Exception $e) {

            echo $e->getMessage();
            
        		}
    		}
    	}
   	]
]);

I did some tests, and I could reproduce this issue. While it picks up the date all right if you just try to get the new date, it doesn’t work when trying to get the correct dates from the collection. Maybe a caching issue or something like that.

maybe similar to this old issue? https://github.com/getkirby/kirby/issues/747

Yes, it seems to be the same thing.

Thanks all for your help. Glad it’s not something on my end.

It’s probably working well enough for my uses for now with some notes in the blueprint it should be workable. Will keep my eye out for an eventual patch.

Thanks again!

Hi again Kirby folks.

I’m having some issues with this hook in the most recent update. Whenever I try to save a new page or save edits to a page I am given an error:

Exception: Error
Call to a member function parentModel() on null

Here is the current code of the hook:

<?php

Kirby::plugin('rgolightly/datehooks', [

	'hooks' => [
		'page.update:after' => function ($page) {

			if($page->parentModel()->template() == 'series_visual') {
			
				$parent = $page->parent();
				$firstSibling = $parent->children()->sortBy('date', 'desc')->first();    
				$lastSibling = $parent->children()->sortBy('date', 'asc')->first(); 
				$date = $firstSibling->date()->toDate('Y-m-d');
				$year = $lastSibling->date()->toDate('Y-m-d'); // use format you use in date field of other pages
				
			try {
				$parent->update([
					'date'  => $date,      
					'year'  => $year          
				]);
			} catch(Exception $e) {
				echo $e->getMessage();
				}
			}
		}
	]
	
]);

I tried the hook migration tool, and it gives me:

The page.update:after event does not provide the $page argument. Kirby versions before 3.4.0 have expected the argument $newPage in this position.

I switched $page in the first line for $newPage, $oldPage which got rid of the errors in the migration assistant, but not the problem with saving.

Many thanks for any advice in what might be happening here. This hook was working smoothly in previous iterations. I had been running 3.3.2 I believe before the 3.4 update.

The hook variable must be changed to $newPage. Then you have to use this variable inside the hook. The code above still uses $page both as argument and in the code inside.

Hook variables are now named, i.e. you have to call the arguments $newPage, $oldPage, while the order in which you pass these arguments to the function is irrelevant (and you don’t have to pass all arguments but only the ones you actually need).

So your code should look like this:

<?php

Kirby::plugin('rgolightly/datehooks', [

	'hooks' => [
		'page.update:after' => function ($newPage) {

			if($newPage->parent() && $page->parent()->template()->name() === 'series_visual') {
			
 				$parent       = $newPage->parent();
                $siblings     = $parent->children()->sortBy('date', 'desc');
				$firstSibling = $siblings->first();    
				$lastSibling  = $siblings->last()); 
				$date         = $firstSibling->date()->toDate('Y-m-d');
				$year         = $lastSibling->date()->toDate('Y-m-d'); // use format you use in date field of other pages
				
			try {
				$parent->update([
					'date'  => $date,      
					'year'  => $year          
				]);
			} catch(Exception $e) {
				echo $e->getMessage(); // you can't echo anything from a hook, if you want to show an error, use `throw new Exception()`
				}
			}
		}
	]
	
]);

Ah, that makes so much sense Sonja. Many thanks. I’ve changed all instances of $page to $newPage and it seems to be working perfectly now.

<?php

Kirby::plugin('rgolightly/datehooks', [

	'hooks' => [
		'page.update:after' => function ($newPage) {

			if($newPage->parent() && $newPage->parent()->template()->name() === 'series_visual') {
			
				$parent = $newPage->parent();
				$firstSibling = $parent->children()->sortBy('date', 'desc')->first();    
				$lastSibling = $parent->children()->sortBy('date', 'asc')->first(); 
				$date = $firstSibling->date()->toDate('Y-m-d');
				$year = $lastSibling->date()->toDate('Y-m-d'); // use format you use in date field of other pages
				
			try {
				$parent->update([
					'date'  => $date,      
					'year'  => $year          
				]);
			} catch(Exception $e) {
				throw new Exception ($e->getMessage());
				}
			}
		}
	]
	
]);

Thought I had this working fully, but I have another Hook that is giving me problems. Here when a ‘series_visual’ page is updated it looks for how many children it has. If it’s more than 6 it creates a new subpage that builds a gallery out of all of those children and lists it.

I am getting a

Call to a member function template() on null

error here when I try to create any new page. I’m fairly sure this has to do with the second part of this hook, the page.create:after. I’m wondering if I need to split this out somehow, or use a different variable here?

Many thanks

<?php

Kirby::plugin('rgolightly/galleryhook', [

	'hooks' => [
		'page.update:after' => function ($newPage) {

			if($newPage->template()->name() === 'series_visual' && $newPage->children()->count() >= '6' && $newPage->children()->filterBy('template', 'gallery_sub')->count() == '0') {
				
				try {
					$newPage->createChild([
						'slug'  => 'all',      
						'template'  => 'gallery_sub'
					]);
				} catch(Exception $e) {
					throw new Exception ($e->getMessage());
					}
				}
		},
		
		'page.create:after' => function ($newPage) {
		
			if($newPage->template()->name() === 'gallery_sub') {
			
			try {
					$newPage->changeStatus("listed");
					
				}	catch(Exception $e) {
					throw new Exception ($e->getMessage());
					}
			}
		}
		]
	
]);

The parameter you have to pass to the create:after hook is called $page not newPage… https://getkirby.com/docs/reference/plugins/hooks/page-create-after

Ah. I see. Thanks so much, that does it!