===== Event Notification Handler ===== <<[[Ticket:56]]<< Believe it or not, I wrote this code before I found out about PageWatches but I think my approach is a little different. Basically, I wanted something that would email people in my office whenever somebody posted a comment on a page of interest. I thought I would make it a little more robust however. This should be a framework that will allow wikka to automatically react to a variety of page events (i.e. commenting a page, editing a page etc) and trigger some response (i.e. emailing a user, sending an http request to a server etc.) This isn't finished, yet it is currently running in my office, so I know it works. Steps: 1) Create new event watching table. 1) Create a handler to register an event for a page to watch. 1) Create a response function (i.e. email notification). 1) Add code to look for and process a page event. Then call a response function. 1) Make handler easily accessible for users. ===== 1.) Create Table ===== %%(sql) CREATE TABLE `wikka_watches` ( `page_tag` VARCHAR(75) NOT NULL, `watcher` VARCHAR(75) NOT NULL, `comment` ENUM('Y','N') DEFAULT 'N' NOT NULL, `edit` ENUM('Y','N') DEFAULT 'N' NOT NULL ) TYPE = myisam; ALTER TABLE `wikka_watches` ADD UNIQUE (`page_tag`,`watcher`) ALTER TABLE `wikka_watches` ADD INDEX (`page_tag`) ALTER TABLE `wikka_watches` ADD INDEX (`watcher`) %% This will create a table that will store a page_tag and watcher pair. The watcher isn't restricted to being a username. It could be the name of a wikipingserver or something like that. Each column after that corresponds to a particular page event with a simple indication of whether or not that event is being watched for. ===== 2.) Create 'addwatch' handler ===== Create a file called addwatch.php in your handlers directory. Add this code: %%(php) page) { $this->SetRedirectMessage("Found no page for this handler."); break; } if (!$this->GetUser()) { $this->SetRedirectMessage("You must be registered to add a watch."); break; } //TODO: get type of watch from a param //passed into the handler. // //get type of watch $type = "comment"; //check if watch type is valid $validity = $this->Query("SHOW COLUMNS FROM " . $this->config["table_prefix"] . "watches LIKE '" . $type . "'"); if (mysql_num_rows($validity) == 0) { $this->SetRedirectMessage("Watch type is invalid."); break; } //get page name $tag = $this->GetPageTag(); //TODO: optionally specify the id of the //watcher instead of assuming user name. // //get watcher $watcher = $this->GetUserName(); //register watch in database $existing = $this->Query( "SELECT * FROM " . $this->config["table_prefix"] . "watches " . "WHERE page_tag = '" . mysql_real_escape_string($tag) . "'" . "AND watcher = '" . mysql_real_escape_string($watcher) . "'"); if (mysql_num_rows($existing) == 0 ) { $this->Query( "INSERT INTO " . $this->config["table_prefix"] . "watches SET ". "page_tag = '" . mysql_real_escape_string($tag) . "', " . "watcher = '" . mysql_real_escape_string($watcher) . "', " . $type . " = 'Y'"); $this->SetRedirectMessage("You are now watching this page for " . $type . "s."); break; } if (mysql_result($existing, 0, $type) == 'Y') { $this->SetRedirectMessage("You are already watching this page for " . $type . "s."); } else { $this->Query( "UPDATE " . $this->config["table_prefix"] . "watches SET ". "page_tag = '" . mysql_real_escape_string($tag) . "', " . "watcher = '" . mysql_real_escape_string($watcher) . "', " . $type . " = 'Y'"); $this->SetRedirectMessage("You are now watching this page for " . $type . "s."); } mysql_free_result($existing); } while (0); $this->Redirect($this->Href()); ?> %% As it stands right now, when a registered user invokes this handler on a page, the wikka_watches table will be updated to indicate that this user wants to be notified whenever this page is commented on. ===== 3.) Create 'notify' base function ===== In wikka.php, I added this function at line 972 before MAINTENANCE %%(php) //COMMUNICATION function Notify($to = "", $subject = "", $body = "", $altbody = "") { } %% Obviously, how you send mail is dependent on your server setup. I don't use the default mail() function. Instead, I have phpmailer setup, and I use it on an SMTP configuration. If somebody wants to see what I wrote for this function that uses phpmailer, let me know. Also, it should probably be called '""NotifyOnEmail""' as there might be additional notify functions created that belong to this family. ===== 4.) Invoke Event Processing somewhere ===== Keeping in mind that I want people to be notified of comments made on pages, I decided to invoke the event processing in the 'addcomment.php' action. Firstly, I have no idea if this is the best place for it to go (as opposed to being added directly in the ""SaveComment()"" function). Secondly, there needs to be a generic event-processing-wrapper of some kind that takes a callback function (such as notify) as a parameter. I'm working on that. Add the following to 'addcomment.php', line 18, right after STORE NEW COMMENT %%(php) //trigger watches $watches_table = $this->config["table_prefix"] . "watches"; $users_table = $this->config["table_prefix"] . "users"; $watch_query = "SELECT " . $users_table . ".email " . "FROM " . $watches_table . "," . $users_table . " " . "WHERE " . $watches_table . ".page_tag = '" . $this->tag . "' " . "AND " . $watches_table . ".watcher = " . $users_table . ".name"; $watches = $this->LoadAll($watch_query); foreach ($watches as $email) { if ($email["email"] == '') { continue; } $this->Notify($email["email"], $this->tag . " commented by " . $this->GetUserName(), $body); } %% ===== 5.) Make handler visible ===== Obviously, I want to make it easy for my users to add watches, so I just hacked the following. It adds a link to the footer. Add the following to footer.php, line 5 after the 'Edit Page' %%(php) echo $this->GetUser() ? "href("addwatch")."\" title=\"Click to watch this page\">Watch page ::\n" : ""; %% Now I don't really want to hack footer directly, plus, I want to be able to support adding watches of different types, so I need to eventually construct a separate menu altogether. ~& How about a ""{{watch}}"" action instead? --NilsLindenberg ===== Conclusion ===== Whenever a user in my wiki comes across a particular page of interest, he or she can click on the "Watch page" link at the bottom, and it will record the request to be notified. Thereafter, whenever somebody leaves a comment on that page, the user will receive an email containing the comment in the body of the message. ===== TODO: ===== - Create an "removewatch" handler. - Create a form in the user settings page that will allow people to manage their watches and add/remove/edit at will. Comments/feedback highly desired. Thank you. :) ---- CategoryUserContributions