8 generate random verification token
10 sends a sub request to the hub...
13 hub sends confirmation back to us via GET
14 We verify the request, then echo back the challenge.
15 On our end, we save the time we subscribed and the lease expiration
18 hub sends us updates via POST
23 class FeedDBException extends FeedSubException
27 function __construct($obj)
29 parent::__construct('Database insert failure');
34 class Feedinfo extends Plugin_DataObject
36 public $__table = 'feedinfo';
45 // PuSH subscription data
54 public /*static*/ function staticGet($k, $v=null)
56 return parent::staticGet(__CLASS__, $k, $v);
61 class_exists('Schema'); // autoload hack
62 // warning: the autoincrement doesn't seem to set.
63 // alter table feedinfo change column id id int(11) not null auto_increment;
64 return new TableDef($this->__table,
65 array(new ColumnDef('id', 'integer',
66 null, false, 'PRI', '0', null, true),
67 new ColumnDef('profile_id', 'integer',
69 new ColumnDef('feeduri', 'varchar',
71 new ColumnDef('homeuri', 'varchar',
73 new ColumnDef('huburi', 'varchar',
75 new ColumnDef('verify_token', 'varchar',
77 new ColumnDef('sub_start', 'datetime',
79 new ColumnDef('sub_end', 'datetime',
81 new ColumnDef('created', 'datetime',
83 new ColumnDef('lastupdate', 'datetime',
87 public function getProfile()
89 return Profile::staticGet('id', $this->profile_id);
93 * @param FeedMunger $munger
96 public static function ensureProfile($munger)
98 $feedinfo = $munger->feedinfo();
100 $current = self::staticGet('feeduri', $feedinfo->feeduri);
102 // @fixme we should probably update info as necessary
106 $feedinfo->query('BEGIN');
109 $profile = $munger->profile();
110 $result = $profile->insert();
111 if (empty($result)) {
112 throw new FeedDBException($profile);
115 $feedinfo->profile_id = $profile->id;
116 $result = $feedinfo->insert();
117 if (empty($result)) {
118 throw new FeedDBException($feedinfo);
121 $feedinfo->query('COMMIT');
122 } catch (FeedDBException $e) {
123 common_log_db_error($e->obj, 'INSERT', __FILE__);
124 $feedinfo->query('ROLLBACK');
131 * Send a subscription request to the hub for this feed.
132 * The hub will later send us a confirmation POST to /feedsub/callback.
134 * @return bool true on success, false on failure
136 public function subscribe()
138 // @fixme use the verification token
139 #$token = md5(mt_rand() . ':' . $this->feeduri);
140 #$this->verify_token = $token;
141 #$this->update(); // @fixme
144 $callback = common_local_url('feedsubcallback', array('feed' => $this->id));
145 $headers = array('Content-Type: application/x-www-form-urlencoded');
146 $post = array('hub.mode' => 'subscribe',
147 'hub.callback' => $callback,
148 'hub.verify' => 'async',
149 //'hub.verify_token' => $token,
150 //'hub.lease_seconds' => 0,
151 'hub.topic' => $this->feeduri);
152 $client = new HTTPClient();
153 $response = $client->post($this->huburi, $headers, $post);
154 if ($response->getStatus() >= 200 && $response->getStatus() < 300) {
155 common_log(LOG_INFO, __METHOD__ . ': sub req ok');
158 common_log(LOG_INFO, __METHOD__ . ': sub req failed');
161 } catch (Exception $e) {
163 common_log(LOG_ERR, __METHOD__ . ": error \"{$e->getMessage()}\" hitting hub $this->huburi subscribing to $this->feeduri");
169 * Read and post notices for updates from the feed.
170 * Currently assumes that all items in the feed are new,
171 * coming from a PuSH hub.
173 * @param string $xml source of Atom or RSS feed
175 public function postUpdates($xml)
177 common_log(LOG_INFO, __METHOD__ . ": packet for \"$this->feeduri\"! $xml");
178 require_once "XML/Feed/Parser.php";
179 $feed = new XML_Feed_Parser($xml, false, false, true);
180 $munger = new FeedMunger($feed);
183 foreach ($feed as $index => $entry) {
184 // @fixme this might sort in wrong order if we get multiple updates
186 $notice = $munger->notice($index);
187 $notice->profile_id = $this->profile_id;
189 // Double-check for oldies
190 // @fixme this could explode horribly for multiple feeds on a blog. sigh
191 $dupe = new Notice();
192 $dupe->uri = $notice->uri;
194 if ($dupe->fetch()) {
195 common_log(LOG_WARNING, __METHOD__ . ": tried to save dupe notice for entry {$notice->uri} of feed {$this->feeduri}");
199 if (Event::handle('StartNoticeSave', array(&$notice))) {
200 $id = $notice->insert();
201 Event::handle('EndNoticeSave', array($notice));
203 $notice->addToInboxes();
205 common_log(LOG_INFO, __METHOD__ . ": saved notice {$notice->id} for entry $index of update to \"{$this->feeduri}\"");
209 common_log(LOG_INFO, __METHOD__ . ": no updates in packet for \"$this->feeduri\"! $xml");