Jump to content

Need to send email notification after a page has been published


Lars282
 Share

Recommended Posts

Hey.

I have got a question on how to get a module to do the following:

Registered users can use a form to add pages to my website, but they are added as unpublished until a moderator can review them and then publish them through the admin.

What I want to add now is that the user who originally added the page receives a notification email once the page has been published.

How can I hook in after 'publishing' the page?

Thanks,

Lars

Link to comment
Share on other sites

I don't have a simple solution to this one, but will do more thinking about how I could have ProcessWire provide a hook like Pages::statusChanged or something like that. But until we have something like that, here are a couple ways you could do it:

Option 1

Add a hook to Pages::saveReady and have your hook function do something like this:

Pages::saveReady hook

$page = $event->arguments[0];
if($page->id && $page->isChanged('status') && !$page->is(Page::statusUnpublished)) {
 $result = $this->db->query("SELECT status FROM pages WHERE id={$page->id}"); 
 list($status) = $result->fetch_row();
 if($status & Page::statusUnpublished) {
   // page is about to be published
   // send your email 
 }
}

Option 2

The other option would be to change your workflow such that user submitted pages went into a different parent than the live ones. For instance, user-submissions might go into parent /pending/ and published submissions would live in /live/. Then you could have your hook monitor for when a page is moving from /pending/ to /live/. If you wanted to, you could also have it take care of the publishing automatically:

Pages::saveReady hook

$page = $event->arguments[0];
if(!$page->parentPrevious) return; // if page is not being moved then stop now
if($page->parent->name == 'live' && $page->parentPrevious->name == 'pending') {
 $page->removeStatus(Page::statusUnpublished);
 // send your email
}
  • Like 5
Link to comment
Share on other sites

I think I prefer option 1 but am not sure whether I understand what the if statements are checking for.

if($page->id && $page->isChanged('status') && !$page->is(Page::statusUnpublished))

Why is the $page->id needed? $page->isChanged('status') simply checks if the status has changed? !$page->is(Page::statusUnpublished) checks for whether the page is published now, after saving?

Having checked this, it is known that the page is published now and had a different status. So now we need to check that the previous status was Unpublished? So why is the query to the DB needed and why isn't if(Page::statusUnpublished) enough?

Also, how do I hook to Pages::saveReady? And where am I hooking to? Before the new values have been written into the DB but after the $page holds the new values?

Sorry for so many question, this is the first time I am actually trying to use hooks myself.

Link to comment
Share on other sites

I think I prefer option 1 but am not sure whether I understand what the if statements are checking for.

if($page->id && $page->isChanged('status') && !$page->is(Page::statusUnpublished))

Why is the $page->id needed? $page->isChanged('status') simply checks if the status has changed? !$page->is(Page::statusUnpublished) checks for whether the page is published now, after saving?

Yes, this is for the page current in memory I think. It's not yet saved to db hence the saveReady().

Checking for ID makes sure it's a page that has an id.

Having checked this, it is known that the page is published now and had a different status. So now we need to check that the previous status was Unpublished? So why is the query to the DB needed and why isn't if(Page::statusUnpublished) enough?

See previous. I think you need to query DB to really check if the page was unpublished before as the current in memory Page is already status "published".

Also, how do I hook to Pages::saveReady? And where am I hooking to? Before the new values have been written into the DB but after the $page holds the new values?

I think this goes into init() and would be

public function init() {
 $this->addHookAfter('Page::saveReady', $this, 'sendMailOnPublish');
}

The last param is the function name in your module that will get called.

public function sendMailOnPublish(HookEvent $event) {
 // Ryans ... code
}

Maybe also wanna read http://wiki.processw...essWire_Modules

Edited by Soma
hard work making post with code and edit them..
Link to comment
Share on other sites

@Lars282 Soma and Slkwrm have it right. Keep in mind that saveReady is called after it's been confirmed the save() will definitely occur, and right before the save actually occurs. So this is the ideal hook for you to use in your case.

I think you need to query DB to really check if the page was unpublished before as the current in memory Page is already status "published".

This is correct. We don't yet have a property $page->statusPrevious property like we do for parent or template. So there's no way for you to know what the previous status was short of loading another copy of the page, or just querying the database like in the example. But now you've got me thinking I may need to add a statusPrevious property in a future version.

For your hook attachment code, I would suggest this:

public function ready() {
 $this->pages->addHook('saveReady', $this, 'sendMailOnPublish'); 
}

…basically the same as what Soma suggested, except that I would add it to $this->pages directly since there is only ever 1 instance of $pages, making it slightly more efficient to do this way. Your actual hook function will be in the same class as your ready() function, and would resemble the one Soma posted.

I think that if($page->id) checks here that the page isn't a new/just created one.

This is correct. If there was no $page->id, it would be a new/unsaved page, and you wouldn't want to go querying the DB for it as we know it wouldn't be there. So that's what the $page->id check is for.

  • Like 3
Link to comment
Share on other sites

  • 9 years later...

Hello!

I tried to make my own module using the code above.
But unfortunately no mail is been sent.
If i delete the if statement that starts with "if($page->template ..." it works. But then a mail is sent after every page modification.

Here is my module code. Do you see any error?

<?php

class MailNotificator extends WireData implements Module {

    public static function getModuleInfo() {

        return array(
            'title' => 'MailNotificator', 
            'version' => 1, 
            'summary' => 'Hook the saving of pages to add own processes.',
            'singular' => true, // Limit the module to a single instance
            'autoload' => true, // Load the module with every call to ProcessWire 
            );
    }
    
    public function ready() {
     $this->pages->addHook('saveReady', $this, 'afterSaveReady'); 
    }

    public function afterSaveReady(HookEvent $event) {
        $page = $event->arguments[0]; 
         if($page->template =="mytemplate" && $page->id && $page->isChanged('status') && !$page->is(Page::statusUnpublished)) {

            $result = $this->db->query("SELECT status FROM pages WHERE id={$page->id}"); 
            list($status) = $result->fetch_row();
            
            if($status & Page::statusUnpublished) {
                 $to = "your@email.com";
                 $from = "my@email.com";
                 $subject = "New page: ".$page->title;
                 $body = $page->text;
                 $bodyhtml = "<html><body><p>".$page->text."</p></body></html>";

                $numSent = $this->mail->subject($subject)
              ->to($to)
              ->from($from)
              ->body($body)
              ->bodyHTML($bodyhtml)
              ->send();
             }
          }  

    }

}

Thanks and good night!

Link to comment
Share on other sites

Try to change the trigger from "saveReady to "save"?


// Before
public function ready() {
     $this->pages->addHook('saveReady', $this, 'afterSaveReady'); 
    }

// After
public function ready() {
     $this->pages->addHookAfter('save', $this, 'afterSaveReady'); 
    }

    

 

  • Like 1
Link to comment
Share on other sites

Thanks for your answer!

I tried it without success.

It seems that this line is responisble for the error.
If i delete the if statemant the mail is sent (twice and after every change of the page).

if($page->template =="mytemplate" && $page->id && $page->isChanged('status') && !$page->is(Page::statusUnpublished)) {

 

Link to comment
Share on other sites

We have a hook for that by now: https://processwire.com/api/ref/pages/published/

<?php
$wire->addHookAfter("Pages::published(template=yourpagetemplate)", function(HookEvent $event) {
  $page = $event->arguments(0);

  $mail = new WireMail();
  $mail->subject("Page {$page->title} has been published...");
  ...
  $mail->send();
});

Not sure if that is really what you want though... Maybe you want to send an email when the page is created? Then Pages::added is for you: https://processwire.com/api/ref/pages/added/

  • Like 5
Link to comment
Share on other sites

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...