webhook support
authorChristian Weiske <cweiske@cweiske.de>
Tue, 17 Sep 2013 14:58:09 +0000 (16:58 +0200)
committerChristian Weiske <cweiske@cweiske.de>
Tue, 17 Sep 2013 14:58:47 +0000 (16:58 +0200)
ChangeLog
README.rst
data/config.default.php
src/phorkie/Forker.php
src/phorkie/Notificator.php [new file with mode: 0644]
src/phorkie/Repository.php
src/phorkie/Repository/Post.php

index 35a521895cab7798186150a82e3d1c3732a6d0c6..3109e7f72157ef7079dc3604df37ddab47753a9d 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,7 @@
+2013-09-17  Christian Weiske  <cweiske@cweiske.de>
+
+       * Add webhook support
+
 2013-09-16  Elan Ruusamäe  <glen@pld-linux.org>
 
        * Disable editor on commit with --no-edit
index 0e8cadf90f2192effb7ef725de70178e8b6c72b5..8f4366719fba8383fb354966ab72eae7c66ff68d 100644 (file)
@@ -36,6 +36,7 @@ Features
 - search across pastes: description, file names and file content
 
   - options: quoting, logical and, or, not, partial words
+- webhook support - get notified when pastes are created, edited or deleted
 
 
 ============
@@ -208,6 +209,37 @@ It is possible to get this information for each single commit::
     http://cweiske.de/
 
 
+Notifications via webhooks
+==========================
+Depending on how you use phorkie, it might be nice to notify some other service
+when pastes are added or updated.
+Phorkie contains a simply mechanism to post data to a given URL which
+you can then use as needed.
+
+The data are json-encoded POSTed to the URLs contained in the
+``$GLOBALS['phorkie']['cfg']['webhooks']`` setting array, with
+a MIME type of ``application/vnd.phorkie.webhook+json``::
+
+  {
+      'event': 'create',
+      'author': {
+          'name':'Anonymous',
+          'email': 'anonymous@phorkie',
+      },
+      'repository': {
+          'name': 'webhooktest',
+          'url': 'http://example.org/33',
+          'description': 'webhooktest',
+          'owner': {
+              'name': 'Anonymous',
+              'email': 'anonymous@phorkie',
+          }
+      }
+  }
+
+The event may be ``create``, ``edit`` or ``delete``.
+
+
 =================
 Technical details
 =================
index b4c7d551cf1344956e3382f61a16913e2a0435c4..070070ddd0e972a49c70f4207e11ca0df598d82e 100644 (file)
@@ -14,6 +14,10 @@ $GLOBALS['phorkie']['cfg'] = array(
     'geshi'         => 'MediaWiki/geshi/geshi/geshi.php',
     'index'         => 'new',//"new" or "list"
     'perPage'       => 10,
+    'webhooks'      => array(
+        /* array of urls that get called when
+           a paste is created, edited or deleted */
+    )
 );
 $GLOBALS['phorkie']['auth'] = array(
     // 0 = public, no authentication, 1 = protect adds/edits/deletes,
index 157cb5e3e435a6a78da4bb087469fb3de9fa2f2f..f4e1295794b790fbed1022cb55d1d86e127cf60c 100644 (file)
@@ -8,6 +8,10 @@ class Forker
         $new = $this->fork($repo->gitDir);
         \copy($repo->gitDir . '/description', $new->gitDir . '/description');
         $this->index($new);
+
+        $not = new Notificator();
+        $not->create($new);
+
         return $new;
     }
 
@@ -19,6 +23,10 @@ class Forker
             'Fork of ' . $originalUrl
         );
         $this->index($new);
+
+        $not = new Notificator();
+        $not->create($new);
+
         return $new;
     }
 
diff --git a/src/phorkie/Notificator.php b/src/phorkie/Notificator.php
new file mode 100644 (file)
index 0000000..3ef5c81
--- /dev/null
@@ -0,0 +1,71 @@
+<?php
+namespace phorkie;
+
+/**
+ * Send out webhook callbacks when something happens
+ */
+class Notificator
+{
+    /**
+     * A repository has been created
+     */
+    public function create(Repository $repo)
+    {
+        $this->send('create', $repo);
+    }
+
+    /**
+     * A repository has been modified
+     */
+    public function edit(Repository $repo)
+    {
+        $this->send('edit', $repo);
+    }
+
+    /**
+     * A repository has been deleted
+     */
+    public function delete(Repository $repo)
+    {
+        $this->send('delete', $repo);
+    }
+
+    /**
+     * Call webhook URLs with our payload
+     */
+    protected function send($event, Repository $repo)
+    {
+        if (count($GLOBALS['phorkie']['cfg']['webhooks']) == 0) {
+            return;
+        }
+        
+        /* slightly inspired by
+           https://help.github.com/articles/post-receive-hooks */
+        $payload = (object) array(
+            'event'  => $event,
+            'author' => array(
+                'name'  => $_SESSION['name'],
+                'email' => $_SESSION['email']
+            ),
+            'repository' => array(
+                'name'        => $repo->getTitle(),
+                'url'         => $repo->getLink('display', null, true),
+                'description' => $repo->getDescription(),
+                'owner'       => $repo->getOwner()
+            )
+        );
+        foreach ($GLOBALS['phorkie']['cfg']['webhooks'] as $url) {
+            $req = new \HTTP_Request2($url);
+            $req->setMethod(\HTTP_Request2::METHOD_POST)
+                ->setHeader('Content-Type: application/vnd.phorkie.webhook+json')
+                ->setBody(json_encode($payload));
+            try {
+                $response = $req->send();
+                //FIXME log response codes != 200
+            } catch (HTTP_Request2_Exception $e) {
+                //FIXME log exceptions
+            }
+        }
+    }
+}
+?>
index 815ef5e4e56ac6a73ba440a86f85947dcb470377..f45c76f72a7e8317ed15f23ba5e48d9a99cfbbf0 100644 (file)
@@ -208,8 +208,13 @@ class Repository
         $db = new Database();
         $db->getIndexer()->deleteRepo($this);
 
-        return Tools::recursiveDelete($this->workDir)
+        $bOk = Tools::recursiveDelete($this->workDir)
             && Tools::recursiveDelete($this->gitDir);
+
+        $not = new Notificator();
+        $not->delete($this);
+
+        return $bOk;
     }
 
     public function getTitle()
index e2e4e9197fd8c4c3b6b8bc95d49b5df3523a0854..0860cad631b665fb50f047fab80a35163a790760 100644 (file)
@@ -154,8 +154,10 @@ class Repository_Post
             //FIXME: index changed files only
             //also handle file deletions
             $db = new Database();
+            $not = new Notificator();
             if ($bNew) {
                 $db->getIndexer()->addRepo($this->repo);
+                $not->create($this->repo);
             } else {
                 $commits = $this->repo->getHistory();
                 $db->getIndexer()->updateRepo(
@@ -163,6 +165,7 @@ class Repository_Post
                     $commits[count($commits)-1]->committerTime,
                     $commits[0]->committerTime
                 );
+                $not->edit($this->repo);
             }
         }