Jump to content

Weekly update – 19 February 2021


ryan
 Share

Recommended Posts

This week I've been developing a client site, but also working through some of the feature requests. I'm going through them in order of "thumbs-up" on GitHub and trying to focus more on those that I can get through reasonably quickly. For a summary of what's been added, be sure to see the dev branch commit log. There's still a few more I'd like to add before bumping the version to 3.0.173, so will save that for next week. 

One of the requests was for the ability to add custom after-save actions in the Page editor. These are the "Save + Exit", "Save + Add New", etc., dropdown actions that you see on the Save button in the page editor. This is something that's already supported, but not formally documented. So I wanted to quickly go through a couple examples of how to do that here, as it is kind of useful and fun.

Let's start with a "hello world" example to keep it simple, then we'll move on to a more practical example. Say we want a "Save + Say Hello" dropdown action in our page editor Save button. We need one hook to add the action, and another to process it. These hooks could go in your /site/ready.php file or your /site/templates/admin.php file, or in a module. 

First we'll want to hook ProcessPageEdit::getSubmitActions() to add our custom "hello" action: 

$wire->addHookAfter('ProcessPageEdit::getSubmitActions', function($event) {
  $actions = $event->return; // array of actions indexed by name
  $page = $event->object->getPage(); // page being edited

  // add a new action that says hello after saving page
  $actions['hello'] = [ 
    'value' => 'hello', // value for action that you will check 
    'icon' => 'hand-spock-o', // icon to show in action, excluding the 'fa-' part
    'label' => '%s + Say Hello', // the '%' is replaced with 'Save' or 'Publish'
    'class' => '', // optional class if you need different styling for button/link
  ]; 

  $event->return = $actions;
}); 

To process our action, we'll need to add a hook to ProcessPageEdit::processSubmitAction():

$wire->addHookAfter('ProcessPageEdit::processSubmitAction', function($event) {
  $action = $event->arguments(0); // action name, i.e. 'hello'
  $page = $process->getPage(); // Page that was edited/saved
  
  if($action === 'hello') { 
    $notice = new NoticeWarning("Hello! You edited page $page->path");
    $notice->icon = 'hand-spock-o';
    $event->notices->add($notice);
  } 
});

That's all there is to it. 

That part where I created the $notice above could just as easily been $this->warning("Hello!..."); but I wanted to add a custom icon to it, which is why I created the Notice manually. 

Many of the built-in after-save actions perform a redirect to another location, such as adding another page, exiting back to the page list, viewing the page on the front-end, etc. If you have a need to perform a redirect after the save, use the $event->object->setRedirectUrl($url); method. This is preferable to calling $session->redirect(); yourself, as it is handled by the page editor after it has finished everything it needs to do.

What if you just want to remove one of the existing actions? For instance, maybe you want to remove the "Save + Add New" action. That action has the name "add", so we can remove it like this:

$wire->addHookAfter('ProcessPageEdit::getSubmitActions', function($event) {
  $actions = $event->return; // array of actions, indexed by name
  unset($actions['add']); 
  $event->return = $actions;
}); 

If there's another you'd like to remove, I'd recommend using TracyDebugger and bd($actions); so you can see and identify all the actions that are present from your hook.

Now let's get to a more practical example. Let's say that you are using ProCache and you want to add a save action to automatically prime the cache after performing the save. By "prime the cache" I mean have it perform a page-view on the front-end that makes it save a new cache file for the page. Here's how you could do that:

$wire->addHookAfter('ProcessPageEdit::getSubmitActions', function($event) {
  $actions = $event->return; // array
  $page = $event->object->getPage(); // page being edited
  $procache = $event->wire('procache'); 

  if(!$procache) return; // if procache not installed, do not add action
  if(!$page->isPublic()) return; // page not public is also not cacheable
  if(!$page->viewable()) return; // page not viewable has no template file
  if(!$procache->isPageCacheable($page)) return; // page not setup for cacheing

  $actions['cache'] = [
    'value' => 'cache', 
    'icon' => 'fighter-jet', 
    'label' => '%s + Cache', // Save + Cache
    'class' => '', 
  ];

  $event->return = $actions;
}); 

…and our hook to process the action:

$wire->addHookAfter('ProcessPageEdit::processSubmitAction', function($event) {
  $action = $event->arguments(0); // action name, i.e. 'cache'
  $page = $process->getPage(); // Page that was edited/saved
 
  if($action === 'cache') { 
    $http = new WireHttp();
    $response = $http->get($page->httpUrl);
    if($response) {
      $size = wireBytesStr(strlen($response)); 
      $event->message("Cache primed for page $page->path ($size)", "nogroup");
    } else {
      $this->warning("Error caching page: " . $http->getError());
    }
  } 
});

Note that we don't have to clear the cache file here because that's something that ProCache has already done prior to our hook above being called. Thanks for reading and have a great weekend! 
 

  • Like 28
  • Thanks 1
Link to comment
Share on other sites

@thetuningspoon After save actions don't participate in a delete action. But I can add a hook for that purpose: ProcessPageEdit::redirectAfterDelete(). I'll have it in there in 3.0.173 and you can hook before that method to perform your own redirect before the page editor does. 

  • Like 3
Link to comment
Share on other sites

Thanks Ryan. This is something I had to deal with for a client a couple of years ago adding custom save buttons that then used lazyCron to publish the page later–this however is a much neater solution so i'll refactor at some point.

Link to comment
Share on other sites

  • 1 year later...
On 2/19/2021 at 9:51 PM, ryan said:
$page = $process->getPage(); // Page that was edited/saved

Note: the variable $process is undefined in my case, running PW 3.0.201. I used this instead:

$page = $event->object->getPage(); // Page that was edited/saved
Edited by szabesz
false information was removed
  • Like 2
Link to comment
Share on other sites

  • 1 year later...

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
 Share

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...