Push your Drupal Site's Events to your Phone with Pushover

Originally published at: http://www.sitepoint.com/push-drupal-sites-events-phone-pushover/

In this article I am going to show you how you can integrate Pushover with your Drupal site. I will illustrate a couple of examples of how you can use Pushover to notify yourself as soon as something happens on your site.

The code I write in this article is also available in this repository so you can just clone that if you want to follow along.

What is Pushover?

Pushover is a web and mobile application that allows you to get real time notifications on your mobile device. The way it works is that you install an app on your Android or Apple device and using a handy API you can send that app notifications. The great thing about this is that it happens more or less in real time (depending on your internet connection) as Pushover uses the Google and Apple servers to send the notifications.

The price is also very affordable. At a rate of $4.99 USD per platform (Android, Apple or desktop) paid only once, you can use it on any number of devices under that platform. And you also get a 5 day trial period for free the moment you create your account.

What am I doing here?

In this article I am going to set up a Pushover application and use it from my Drupal site to notify my phone of various events. I will give you two example use cases that Pushover can be handy with:

  • Whenever an anonymous user posts a comment that awaits administrative approval, I’ll send a notification to my phone
  • Whenever the admin user 1 logs into the site, I’ll send an emergency notification to my phone (useful if you are the only user of that admin account).

Naturally, these are examples and you may not find them useful. But they only serve as illustration of the power you can have by using Pushover.

Continue reading this article on SitePoint

Sorry, but I think that your PHP code is terrible.

Please, compare your examples with my organized and classified code http://pastebin.com/sFiFWWmV

I think that you need to improve a lot of your PHP skills.

Anyway, regards :slight_smile:

Hey Lito,

First of all, I believe you need to learn some manners before you comment on any posts. Some basics are in order at least.

Second of all, you didn’t seem to get that this is an example for Drupal where you need to implement procedural functions to hook into existing functionality. I wrote a simple demo helper function just so I don’t reuse the boilerplate client instantiation code and didn’t write a class for it because it would have been an overkill.

Your commentInsert() and userLogin() methods are superfluous because you’d use them only one time: inside a hook_comment_insert() and hook_user_login() respectively. And with this approach, if you want to send a push notification in another hook, you’d create a different method on the same class just for that as well. If you don’t, the whole point of your classes no longer exists.

Other than that, you just wrapped the existing client code in another class which I guess makes you better: I am perfectly fine living in a world where you think (or are) much better than me.

So good luck with that.

1 Like

While I appreciate the time you took to write up an alternative solution, that’s not a nice way to leave feedback.

In the future, perhaps sending a PR (so we can also see a diff, not just a pastebin which needs to be manually compared) would be a more productive approach, as it could then also be discussed in the pull request’s issue, no?

Sorry, I thought that my code was clear, do you thing that a diff is needed to compare code differences?

I think that the problem isn’t the functions or de classes or if is a wrapper or not, is a protest by the bad code in this “article”. I think that haven’t enough effort or quality to be published here, regardless of what he wants to show.

Sorry for my previous bad feedback.

Drupal 7 is driven by procedural event mechanism known as hooks. The code supplied by the author is completely adequate given the environment. Drupal <8 is not really known for OOP. It is mostly procedural and any attempt to clean things up using OOP typically results in making things less cleaner. Though you would have to be familiar with system to understand that. Yes, you can use OOP but really there is a specific time and place for it in older versions of Drupal. Showing a concept in the simplest of forms is not really one them fyi. Not to mention the code you supplied as an alternative within the context of Drupal does absolutely nothing since it isn’t hooked into the event/hook system.

Ok, I know, but I haven’t talking about finger, but about the moon.

Nested ifs, globals, simple comparisons, code not clear, not spaces, etc…

Here my constructive contribution to this article, using same functions and idea about Drupal.

define('PUSHOVER_APP_TOKEN', 'aKH8Nwsdasdanl342jmsdaBWgoVe');
define('PUSHOVER_USER_TOKEN', 'uCpygdjfsndfi7233sdasdo33Yv');

function pushover_send($vars)
    if (!defined('PUSHOVER_APP_TOKEN') || !defined('PUSHOVER_USER_TOKEN')) {
        return false;

    $error = false;

    $push = new Pushover();

    if (array_key_exists('error', $vars)) {
        $error = $vars['error'];

    foreach ($vars as $key => $value) {
        if (method_exists($push, $key)) {
            call_user_func_array(array($push, 'set'.$key), array($value));

    if ($push->send()) {
        return true;

    if ($error) {
        watchdog('Pushover', $error, array(), WATCHDOG_ERROR, NULL);

    return false;

* Implements hook_comment_insert().
function pushover_comment_insert($comment) {
    if (($comment->status !== 0) || ($comment->is_anonymous !== true)) {
        return false;

    return pushover_send(array(
        'title' => 'New comment on ' . variable_get('site_name') . '!',
        'message' => 'Subject: ' . $comment->subject,
        'url' => url('/node/'.$comment->nid.'#comment-'.$comment->cid, array('absolute' => true)),
        'device' => 'Nexus',
        'error' => t('A comment has been created but there was an error pushing that over.')

* Implements hook_user_login().
function pushover_user_login($account) {
    if (($account->uid !== 1) || in_array(ip_address(), array(''))) {
        return false;

    return pushover_send(array(
        'title' => 'Admin user sign in',
        'message' => 'Admin user has logged into this site: '.variable_get('site_name').'!',
        'url' => url('/', array('absolute' => true)),
        'priority' => 2,
        'retry' => 30,
        'expire' => 60,
        'error' => t('An admin user has logged into the site but there was an error pushing this over.')

Do you think that this code is enough professional and clear?

Anyway, thanks for your article and sorry my lack of tact.

I agree that Drupal <8 promotes some terrible practices. That is why Drupal 8 was completely rebuilt from the ground up. When I’m using Drupal 7 I more often than not take the stance of if you can’t beat them join them.

A diff would make it immediately clearer for other people joining the discussion, allowing them to benefit from your changes faster, should they prove valid. Either way, thank you for taking the time to contribute - just be more tactful in the future, please. There are more constructive approaches to criticism, and everyone appreciates constructive criticism.

I’m sorry, I know. My english is not the best in the world and sometimes I can be too rude or direct with my expressions.

Sorry all my errors to try to explain some solutions more elegant than article.


Nice article and useful solution.

On the Drupal best practices side, you could improve one important part:
Drupal uses a couple of standardized ways to include files. inlude_once is never used.

Best best way:
Use the Libaries API contrib module.
The library is placed in the sites/libraries folder. This way, the module and library are not hard linked to each other.

The basic drupal way:
Include the file in your module info file:
files = lib/Pushover/Pushover.php

Hey there,

Thanks for the comment.

I agree that using require_once is not the best way to go. Hence I mentioned in the article that this is just for demonstration (brevity) purposes only. I also mentioned the Libraries module as the more recommended approach. I’m not sure if you didn’t miss that :slight_smile:


Ah my bad. Looked over it. The link is pretty obvious :flushed:

This topic was automatically closed 91 days after the last reply. New replies are no longer allowed.