Jump to content

PushAlert notifications for ProcessWire


psy
 Share

Recommended Posts

This module enables you to send push notifications and receive information about sent notifications on your HTTPS ProcessWire website.

It enables you to:

  1. Create a field of type FieldtypePushAlert that you can add to a page template. This is a multi-input field widget that enables you to send notifications from your page in the admin Page Edit and monitor statistics - Attempted, Delivered, Clicked, etc
  2. Send notifications from a page template directly using the API, eg to PW users who have a specific role and have subscribed to notifications
  3. Capture subscriptions on your website front end

All kudos to the great support team at PushAlert and to all the ProcessWire developers who've helped me with this project.

Download from the Modules directory at: https://modules.processwire.com/modules/push-alert/

or from GitHub at: https://github.com/clipmagic/PushAlert

Full instructions for use are in the module README.md file.

Enjoy!

  • Like 15
Link to comment
Share on other sites

Great stuff!

Do you know if Pushalert only accepts the root of a site/domain? I have a test-site installed @ dev.domain.com/project-name/

When I enter the above URL, Pushalert just saves dev.domain.com/

That's probably why I don't see anything in the bottom right corner in my frontend:

Quote

Go to the front end and confirm you see a bell icon in the bottom right corner. This default icon and can be changed in your PushAlert Dashboard.

Edit: actually, it works - but only after I copy and pasted the JS myself in the HTML HEAD (module didn't insert anything).

Link to comment
Share on other sites

Sorry, I already have another question: Once I subscribe, I see the bell icon on every subsequent page. Is that intended? I would expect to see this icon just once. Wouldn't you expect to not see it again after you either click "yes, subscribe" or "no thanks"?

When I publish my page, I get the following error: 

Session: SQLSTATE[HY093]: Invalid parameter number: mixed named and positional parameters


Something weird is happening when I want to set "Schedule send time":
The field always stays @ 2019-02-21 15:02:00, although I set it to 2019-02-21 15:55:00
(no matter if I set it via Date/Timepicker, or manually). It jumps back to this time after saving.

Are any timezones hard-coded? The time is a couple of minutes in the future. If I set it to sometime in the next hour, the time saves correctly. o_O

When I click on the notification (which appeared twice, by the way, stacked on top of each other), I get redirected to mysite.com/pw-backend/page/edit - and of course I see the login-screen there. I don't get redirected to my page with template pushalert. 

Edited by dragan
added some more questions
Link to comment
Share on other sites

Hi @dragan

Thanks for the feedback.

I believe PushAlert only accepts the root domain. I will ask PushAlert support for clarification.

The icon is always visible. After you've subscribed, it changes to an unsubscribe button.

5 hours ago, dragan said:

Session: SQLSTATE[HY093]: Invalid parameter number: mixed named and positional parameters

Not sure but may be related to the date issue?

No timezones are hardcoded. It is a standard PW Date Time picker inputfield. It gets converted to a timestamp for submission to PushAlert and saved in the field json data. It gets reconverted to a string when the page edit is redisplayed by the date field.

The URL submitted to PushAlert should be the frontend URL (always has been in my testing?), called in the code with $page->httpUrl. 

Are you using ProCache and stripping optional tags? The script needs the closing </head> tag. I'll work on an alternative way to manually call the script in the template. When you use only the PushAlert code, you miss the custom onSuccess callback function. This function posts back to PW to save the subscriber ID and logged-in user ID in the database.

            <script>
                function callbackOnSuccess(result) {                    
                    let topw = {};
                    topw.subscriber_id = result.subscriber_id;
                    topw.alreadySubscribed = result.alreadySubscribed;            
                    var json = JSON.stringify(topw);
                    return fetch("https://mywebsite.com/pushalert-endpoint/", {
                        method: "POST",
                        headers: {
                            "Content-Type": "application/json",
                        },
                        body: json
                    });
                }
                </script>

The only time, very early on in the development cycle, I got double notifications was when I had both sw.js and the PWABuilder service worker installed and they clashed horribly. The existing service worker called the page as did PW for faster load times and so the notification went twice.

Are you using multi-language? Maybe that's having an effect?

Link to comment
Share on other sites

9 hours ago, dragan said:

I get redirected to mysite.com/pw-backend/page/edit

Oh dear, this wasn't happening before but have been able to reproduce the issue.

Will let you know when the fix is available

FIXED and updated in gitHub:

In PushAlert.module, change lines 160 and 161 to:

        $paUrl       = $widget->pa_message_url;
        if (empty($paUrl) || stripos($paUrl, '/page/edit/') !== false) {
            $paUrl= substr($this->wire('config')->urls->httpRoot, 0, -1) . $page->path;
        }

 

Edited by psy
Solved problem
Link to comment
Share on other sites

17 hours ago, dragan said:

Do you know if Pushalert only accepts the root of a site/domain? I have a test-site installed @ dev.domain.com/project-name/

When I enter the above URL, Pushalert just saves dev.domain.com/

@dragan spoke with Alex @ PushAlert and the short answer is it has to be in the root. Long answer is that there is alternate, unpublished code that allows integration in sub-directories. Alex will send me the code to review. Will keep you posted 

 

Update

Using PushAlert from PW site installed in a subdirectory is not difficult. It will require an additional field on the module config page and is on the roadmap for the next release.

  • Like 1
Link to comment
Share on other sites

  • 2 weeks later...

@psy very excited to see this, thank you!

I had a few problems, on install:

/processwire/setup/field/edit?id=146 SQLSTATE[42S02]: Base table or view not found: 1146 Table mydominaname_processwire.field_PushAlert' doesn't exist (in /site/modules/PushAlert/PushAlert.module line 347)
 

and on trying to uninstall:

/processwire/module/edit?name=PushAlert&collap…

Method WireFileTools::unlink does not exist or is not callable in this context (in /wire/core/Wire.php line 519)

I couldn't get any notification sent on publishing a page with a FieldtypePushAlert field on it, but alerts work from the PushAlert website.

Has anyone else tried & had any issues/got any pointers? I've checked modsecurity on the server & no errors & am running php 5.6.40.

Thanks

Nick.

 

Link to comment
Share on other sites

@dab

Thanks for the feedback. I'll investigate.

I spent more time on the install/uninstall process than the actual integration but that's development for you. I tested on PW 3.0.74+ and PHP 7.0. Not sure if the fact you're using PHP 5.6.40 is the cause.

From your post it seems that the database table field_PushAlert was not found. Is your field name PushAlert? Maybe there is a problem with capital letters for field names in the DB?

Your second issue is a puzzle too. The only place in the module where unlink is used is in __uninstall to remove the push_alert_endpoint.php template. Was this created?

Link to comment
Share on other sites

6 hours ago, psy said:

@dab

Thanks for the feedback. I'll investigate.

I spent more time on the install/uninstall process than the actual integration but that's development for you. I tested on PW 3.0.74+ and PHP 7.0. Not sure if the fact you're using PHP 5.6.40 is the cause.

From your post it seems that the database table field_PushAlert was not found. Is your field name PushAlert? Maybe there is a problem with capital letters for field names in the DB?

Your second issue is a puzzle too. The only place in the module where unlink is used is in __uninstall to remove the push_alert_endpoint.php template. Was this created?

@psy, thanks for getting back.

>field_PushAlert was not found

ah yes, resolved when i used lowercase for the Pushalert field name on a later try (hope I didn't miss this instruction - sorry).

>push_alert_endpoint.php template. Was this created?

Yes,  that was created OK.

I'm thinking the lack of alerts might be PHP version related. I'll await any feedback from other users.

Once again, huge thanks for all the work on the module - it's absolutely fab ?.

Link to comment
Share on other sites

@dab Thank you ☺️

The field creation bit is pure PW, not PushAlert related at all so not sure why this occurred but good to know about uppercase/lowercase in field names.

The deletion of the pushalert_endpoint.php template is also pure PW/PHP as per the docs: https://processwire.com/api/ref/wire-file-tools/unlink/

        // Delete the endpoint template file - should never be customised
        $templatePath = $this->wire('config')->paths->templates . "pushalert_endpoint.php";
        if (is_file($templatePath))
            $this->wire('files')->unlink($templatePath);

Could it be a permissions error?

 

Link to comment
Share on other sites

Just testing it, look great ?

 

I suggest a more verbose message when there is an error. I got the following message "There was a problem sending the notification" and I needed to put a bd($resultObj); on line 200 to know which error was triggered. In my case, was :

msgerror.png.fa7f8f83f7f6b6d14273f01f02c4ba7a.png

 

I also got a notice for an undefined variable when there are error with $resultObj , the variable should be affected to false just before the if($resultObj->success) condition to avoid this notice :

dbupdaterror.png.cecc4701e013421da3b129529564b97c.png

 

 

Thanks again for this useful module !

  • Like 1
Link to comment
Share on other sites

On ProcessWire 3.0.124, I can't get it working. There is a weird issue with headers. The module keep saying that the API Key is invalid, I then tried with cURL on a terminal and it worked as expected. 

So I put a Tracy call to the core WireHttp to dump the headers set in the object :

https://github.com/processwire/processwire/blob/dev/wire/core/WireHttp.php#L576-L578

[...]
	bd($key .' => '. $value);
[...]

and as a result, we can see a string ( "0 : " ) before the Authorization header :

The header is treated as an array, see the index '0' ($key dumped here) :

headererror.png.a46b86193a768462e2b6ade43885d383.png

 

It's strange and its explain why my PulsewayPush module stopped working suddenly since some weeks after an upgrade. 

 

I just upgraded the system to ProcessWire 3.0.127, same things happen..

Link to comment
Share on other sites

@flydev Thanks again for the detailed feedback. My development site runs PW 3.0.124 so I don't understand why the behaviour would be different? C'est la vie.

In version 3.0.124, Ryan introduced support for cURL in WireHttp https://processwire.com/blog/posts/pw-3.0.124-and-new-site/#wirehttp-updated-with-curl-support

In the PushAlert.module I tried to take advantage of this new feature, from Line 439:

        // Prepare and send the request
        $slug = "send";

        if($this->wire('config')->version('3.0.124')) {
            // ProcessWire version is 3.0.124 or newer
            $result = $this->_sendHttp($slug, $options);
        } else {
            $result = $this->_sendCurl($slug, $options);
        }
        return $result;
    }

    /**
     * @param $slug
     * @param $options
     * @return mixed
     */
    private function _sendHttp ($slug, $options) {
        $http = new WireHttp();
        $headers = Array();
        $headers[] = "Authorization: api_key=". $this->api_key;
        $http->setHeaders( $headers);
        $result = $http->send($this->api_url . $slug, $options);
        return $result;

    }

    /**
     * @param $slug
     * @param $options
     * @return bool|string
     */
    private function _sendCurl ($slug, $options) {
        $headers = Array();
        $headers[] = "Authorization: api_key=" . $this->api_key;

        $ch = curl_init();
        curl_setopt($ch, CURLOPT_URL, $this->api_url . $slug);
        curl_setopt($ch, CURLOPT_POST, true);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
        curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($options));
        curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
        $result = curl_exec($ch);
        return $result;
    }

 

Because I cannot recreate the issue, would you please try commenting out lines 458, 459 & 460 and replacing them with:

//        $headers = Array();
//        $headers[] = "Authorization: api_key=". $this->api_key;
//        $http->setHeaders( $headers);

        $http->setHeader("Authorization: api_key=". $this->api_key);

and let me know if this resolves the issue.

More:  I used Array() in WireHttp to keep it consistent with the cURL method. Happy to change in the module _sendHttp method if WireHttp headers array works differently. Still wondering why it worked on my PW 3.0.124 and not for you...

Edited by psy
more info
  • Like 1
Link to comment
Share on other sites

11 hours ago, psy said:

//        $headers = Array();
//        $headers[] = "Authorization: api_key=". $this->api_key;
//        $http->setHeaders( $headers);

        $http->setHeader("Authorization: api_key=". $this->api_key);

 

It works like that, just FYI this function take 2 arguments so it need to be called :  $http->setHeader("Authorization", api_key=". $this->api_key);

After that, the API key is reconized. So I tested the module with the field in the template and trought the API, worked like a charm ?

 

11 hours ago, psy said:

Still wondering why it worked on my PW 3.0.124 and not for you...

...

  • Thanks 1
Link to comment
Share on other sites

@flydev grateful for your patience with me on resolving this issue. Fixed in gitHub

Working code is:

$http->setHeader("Authorization", "api_key=". $this->api_key);

Also updated the _getHttp function with same fix in gitHub

Edited by psy
  • Like 2
Link to comment
Share on other sites

@psy, many thanks, with the latest update, I can see alerts are now being sent from Processwire to pushalert.co!  Thank you ??.

My next step is to find out why push deliveries back to the subscribers are shown as "attempted" & not yet "delivered".

Link to comment
Share on other sites

@dab Great it's now working for you. All credit to flydev for the fix ?

The reporting of "Attempted" rather than "Delivered" is a question for PushAlert support. Once PW sends the notification, it hands over to PushAlert and then catches the response to report the status. 

Link to comment
Share on other sites

@psy, all resolved.  Now working beautifully thank you @psy!

Make sure, if you recreate your website entry on the PushAlert site you download a FRESH copy of the manifest.json & sw.js (oh dear, I thought I had!).

The PushAlert support team were super fast & very friendly if you run in to any problems. Thank you PushAlert.

  • Like 1
Link to comment
Share on other sites

@dab, yes, the PushAlert support team are almost as helpful as the PW devs here ?

DON'T use the PushAlert sw.js file. It's the vanilla version and doesn't include the PW custom code to save subscriber ID's with PW user ID's. The module will automatically add sw.js + the custom function to the <head> for you. See my post to @dragan about this above.

Also see the IMPORTANT section of the README about manifest.json. If you're site already has one, just add the gcm_sender_id code line.

 

Link to comment
Share on other sites

  • 3 months 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

×
×
  • Create New...