websub subcriptions work
[phinde.git] / src / phinde / Subscriptions.php
1 <?php
2 namespace phinde;
3
4 /**
5  * Database table containing information about Pubsubhubbub subscriptions
6  */
7 class Subscriptions
8 {
9     protected $db;
10
11     public function __construct()
12     {
13         $this->db = new \PDO(
14             $GLOBALS['phinde']['db_dsn'],
15             $GLOBALS['phinde']['db_user'],
16             $GLOBALS['phinde']['db_pass']
17         );
18         $this->db->setAttribute(\PDO::ATTR_ERRMODE, \PDO::ERRMODE_EXCEPTION); 
19     }
20
21     /**
22      * Fetch a topic
23      *
24      * @param string $topic Topic URL
25      *
26      * @return false|object False if the row does not exist
27      */
28     public function get($topic)
29     {
30         $stmt = $this->db->prepare(
31             'SELECT * FROM subscriptions'
32             . ' WHERE sub_topic = :topic'
33         );
34         $stmt->execute([':topic' => $topic]);
35
36         //fetchObject() itself returns FALSE on failure
37         return $stmt->fetchObject();
38     }
39
40     /**
41      * Create a new subscription entry in database.
42      * Automatically generates secret, capkey and lease seconds.
43      *
44      * This method does NOT:
45      * - check for duplicates (do it yourself)
46      * - return the object (fetch it yourself)
47      * - send subscription requests to the hub
48      *
49      * @param string $topic URL to subscribe to
50      *
51      * @return void
52      */
53     public function create($topic)
54     {
55         $stmt = $this->db->prepare(
56             'INSERT INTO subscriptions'
57             . ' (sub_topic, sub_status, sub_lease_seconds, sub_expires'
58             . ', sub_secret, sub_capkey, sub_created, sub_updated'
59             . ', sub_pings, sub_lastping, sub_statusmessage)'
60             . ' VALUES '
61             . ' (:topic, "subscribing", :lease_seconds, "0000-00-00 00:00:00"'
62             . ', :secret, :capkey, NOW(), NOW()'
63             . ', 0, "0000-00-00 00:00:00", "")'
64         );
65         $stmt->execute(
66             [
67                 ':topic'         => $topic,
68                 ':lease_seconds' => 86400 * 30,
69                 ':secret'        => bin2hex(openssl_random_pseudo_bytes(16)),
70                 ':capkey'        => bin2hex(openssl_random_pseudo_bytes(16)),
71             ]
72         );
73     }
74
75     /**
76      * A subscription has been confirmed by the hub - mark it as active.
77      *
78      * @param integer $subId        Subscription ID
79      * @param integer $leaseSeconds Number of seconds until subscription expires
80      *
81      * @return void
82      */
83     public function subscribed($subId, $leaseSeconds)
84     {
85         $this->db->prepare(
86             'UPDATE subscriptions'
87             . ' SET sub_status        = "active"'
88             . '   , sub_lease_seconds = :leaseSeconds'
89             . '   , sub_expires       = :expires'
90             . '   , sub_updated       = NOW()'
91             . ' WHERE sub_id = :id'
92         )->execute(
93             [
94                 ':leaseSeconds' => $leaseSeconds,
95                 ':expires' => gmdate('Y-m-d H:i:s', time() + $leaseSeconds),
96                 ':id' => $subId,
97             ]
98         );
99     }
100
101     /**
102      * Mark a subscription as "unsubscribed"
103      *
104      * @param integer $subId Subscription ID
105      *
106      * @return void
107      */
108     public function unsubscribed($subId)
109     {
110         $this->db->prepare(
111             'UPDATE subscriptions'
112             . ' SET sub_status = "unsubscribed"'
113             . '   , sub_updated = NOW()'
114             . ' WHERE sub_id = :id'
115         )->execute([':id' => $subId]);
116     }
117
118     public function denied($subId, $reason)
119     {
120         $this->db->prepare(
121             'UPDATE subscriptions'
122             . ' SET sub_status = "denied"'
123             . '   , sub_statusmessage = :reason'
124             . '   , sub_updated = NOW()'
125             . ' WHERE sub_id = :id'
126         )->execute([':id' => $subId, ':reason' => $reason]);
127     }
128
129     public function pinged($subId)
130     {
131         $this->db->prepare(
132             'UPDATE subscriptions'
133             . ' SET sub_pings    = sub_pings + 1'
134             . '   , sub_lastping = NOW()'
135             . '   , sub_updated  = NOW()'
136             . ' WHERE sub_id = :id'
137         )->execute([':id' => $subId]);
138     }
139
140     /**
141      * Detect the hub for the given topic URL
142      *
143      * @param string $url Topic URL
144      *
145      * @return array Topic URL and hub URL. Hub URL is NULL if there is none.
146      */
147     public function detectHub($url)
148     {
149         $hue = new HubUrlExtractor();
150         $hue->setRequestTemplate(new HttpRequest());
151         $urls = $hue->getUrls($url);
152         //we violate the spec by not requiring a self URL
153         $topicUrl = isset($urls['self']) ? $urls['self'] : $url;
154         $hubUrl   = isset($urls['hub'])  ? $urls['hub'] : null;
155
156         return array($topicUrl, $hubUrl);
157     }
158 }
159 ?>