]>
Commit | Line | Data |
---|---|---|
493c2f88 | 1 | <?php |
93e79595 | 2 | class GoogleReaderImport extends Plugin { |
493c2f88 AD |
3 | |
4 | ||
5 | private $link; | |
6 | private $host; | |
7 | ||
8 | function about() { | |
9 | return array(1.0, | |
7c93962d | 10 | "Import starred/shared items from Google Reader takeout", |
493c2f88 AD |
11 | "fox", |
12 | false, | |
13 | ""); | |
14 | } | |
15 | ||
16 | function init($host) { | |
17 | $this->link = $host->get_link(); | |
18 | $this->host = $host; | |
19 | ||
4cf0f9a9 AD |
20 | $host->add_command("greader-import", |
21 | "import data in Google Reader JSON format", | |
22 | $this, ":", "FILE"); | |
23 | ||
493c2f88 AD |
24 | $host->add_hook($host::HOOK_PREFS_TAB, $this); |
25 | } | |
26 | ||
4cf0f9a9 AD |
27 | function greader_import($args) { |
28 | $file = $args['greader_import']; | |
29 | ||
30 | if (!file_exists($file)) { | |
31 | _debug("file not found: $file"); | |
32 | return; | |
33 | } | |
34 | ||
35 | _debug("please enter your username:"); | |
36 | ||
37 | $username = db_escape_string($this->link, trim(read_stdin())); | |
38 | ||
39 | _debug("looking up user: $username..."); | |
40 | ||
41 | $result = db_query($this->link, "SELECT id FROM ttrss_users | |
42 | WHERE login = '$username'"); | |
43 | ||
44 | if (db_num_rows($result) == 0) { | |
45 | _debug("user not found."); | |
46 | return; | |
47 | } | |
48 | ||
49 | $owner_uid = db_fetch_result($result, 0, "id"); | |
50 | ||
51 | _debug("processing: $file (owner_uid: $owner_uid)"); | |
52 | ||
53 | $this->import($file, $owner_uid); | |
54 | } | |
55 | ||
493c2f88 AD |
56 | function get_prefs_js() { |
57 | return file_get_contents(dirname(__FILE__) . "/init.js"); | |
58 | } | |
59 | ||
4cf0f9a9 | 60 | function import($file = false, $owner_uid = 0) { |
493c2f88 | 61 | |
749da11b AD |
62 | purge_orphans($this->link); |
63 | ||
4cf0f9a9 AD |
64 | if (!$file) { |
65 | header("Content-Type: text/html"); | |
493c2f88 | 66 | |
93e79595 AD |
67 | $owner_uid = $_SESSION["uid"]; |
68 | ||
3306daec AD |
69 | if ($_FILES['starred_file']['error'] != 0) { |
70 | print_error(T_sprintf("Upload failed with error code %d", | |
71 | $_FILES['starred_file']['error'])); | |
72 | return; | |
73 | } | |
74 | ||
75 | $tmp_file = false; | |
76 | ||
77 | if (is_uploaded_file($_FILES['starred_file']['tmp_name'])) { | |
78 | $tmp_file = tempnam(CACHE_DIR . '/upload', 'starred'); | |
79 | ||
80 | $result = move_uploaded_file($_FILES['starred_file']['tmp_name'], | |
81 | $tmp_file); | |
82 | ||
83 | if (!$result) { | |
84 | print_error(__("Unable to move uploaded file.")); | |
85 | return; | |
86 | } | |
87 | } else { | |
88 | print_error(__('Error: please upload OPML file.')); | |
89 | return; | |
90 | } | |
91 | ||
92 | if (is_file($tmp_file)) { | |
93 | $doc = json_decode(file_get_contents($tmp_file), true); | |
94 | unlink($tmp_file); | |
4cf0f9a9 AD |
95 | } else { |
96 | print_error(__('No file uploaded.')); | |
97 | return; | |
98 | } | |
493c2f88 | 99 | } else { |
4cf0f9a9 | 100 | $doc = json_decode(file_get_contents($file), true); |
493c2f88 AD |
101 | } |
102 | ||
4cf0f9a9 AD |
103 | if ($file) { |
104 | $sql_set_marked = strtolower(basename($file)) == 'starred.json' ? 'true' : 'false'; | |
105 | _debug("will set articles as starred: $sql_set_marked"); | |
106 | ||
107 | } else { | |
108 | $sql_set_marked = strtolower($_FILES['starred_file']['name']) == 'starred.json' ? 'true' : 'false'; | |
109 | } | |
4c92878f | 110 | |
493c2f88 AD |
111 | if ($doc) { |
112 | if (isset($doc['items'])) { | |
113 | $processed = 0; | |
114 | ||
115 | foreach ($doc['items'] as $item) { | |
116 | // print_r($item); | |
117 | ||
05e1e0ff | 118 | $guid = db_escape_string($this->link, mb_substr($item['id'], 0, 250)); |
493c2f88 AD |
119 | $title = db_escape_string($this->link, $item['title']); |
120 | $updated = date('Y-m-d h:i:s', $item['updated']); | |
121 | $link = ''; | |
122 | $content = ''; | |
123 | $author = db_escape_string($this->link, $item['author']); | |
4188225c | 124 | $tags = array(); |
749da11b | 125 | $orig_feed_data = array(); |
493c2f88 AD |
126 | |
127 | if (is_array($item['alternate'])) { | |
128 | foreach ($item['alternate'] as $alt) { | |
129 | if (isset($alt['type']) && $alt['type'] == 'text/html') { | |
130 | $link = db_escape_string($this->link, $alt['href']); | |
131 | } | |
132 | } | |
133 | } | |
134 | ||
b87bd8ed AD |
135 | if (is_array($item['summary'])) { |
136 | $content = db_escape_string($this->link, | |
137 | $item['summary']['content'], false); | |
138 | } | |
139 | ||
493c2f88 AD |
140 | if (is_array($item['content'])) { |
141 | $content = db_escape_string($this->link, | |
142 | $item['content']['content'], false); | |
143 | } | |
144 | ||
4188225c AD |
145 | if (is_array($item['categories'])) { |
146 | foreach ($item['categories'] as $cat) { | |
147 | if (strstr($cat, "com.google/") === FALSE) { | |
148 | array_push($tags, sanitize_tag($cat)); | |
149 | } | |
150 | } | |
151 | } | |
152 | ||
749da11b AD |
153 | if (is_array($item['origin'])) { |
154 | if (strpos($item['origin']['streamId'], 'feed/') === 0) { | |
155 | ||
156 | $orig_feed_data['feed_url'] = db_escape_string($this->link, | |
61096207 AD |
157 | mb_substr(preg_replace("/^feed\//", |
158 | "", $item['origin']['streamId']), 0, 200)); | |
749da11b AD |
159 | |
160 | $orig_feed_data['title'] = db_escape_string($this->link, | |
61096207 | 161 | mb_substr($item['origin']['title'], 0, 200)); |
749da11b AD |
162 | |
163 | $orig_feed_data['site_url'] = db_escape_string($this->link, | |
61096207 | 164 | mb_substr($item['origin']['htmlUrl'], 0, 200)); |
749da11b AD |
165 | } |
166 | } | |
167 | ||
493c2f88 AD |
168 | $processed++; |
169 | ||
4cf0f9a9 | 170 | $imported += (int) $this->create_article($owner_uid, $guid, $title, |
749da11b AD |
171 | $updated, $link, $content, $author, $sql_set_marked, $tags, |
172 | $orig_feed_data); | |
b9fc62a7 AD |
173 | |
174 | if ($file && $processed % 25 == 0) { | |
175 | _debug("processed $processed articles..."); | |
176 | } | |
493c2f88 AD |
177 | } |
178 | ||
4cf0f9a9 AD |
179 | if ($file) { |
180 | _debug(sprintf("All done. %d of %d articles imported.", $imported, $processed)); | |
181 | } else { | |
182 | print "<p style='text-align : center'>" . T_sprintf("All done. %d out of %d articles imported.", $imported, $processed) . "</p>"; | |
183 | } | |
493c2f88 AD |
184 | |
185 | } else { | |
186 | print_error(__('The document has incorrect format.')); | |
187 | } | |
188 | ||
189 | } else { | |
190 | print_error(__('Error while parsing document.')); | |
191 | } | |
192 | ||
4cf0f9a9 AD |
193 | if (!$file) { |
194 | print "<div align='center'>"; | |
195 | print "<button dojoType=\"dijit.form.Button\" | |
196 | onclick=\"dijit.byId('starredImportDlg').execute()\">". | |
197 | __('Close this window')."</button>"; | |
198 | print "</div>"; | |
199 | } | |
493c2f88 AD |
200 | } |
201 | ||
202 | // expects ESCAPED data | |
749da11b | 203 | private function create_article($owner_uid, $guid, $title, $updated, $link, $content, $author, $marked, $tags, $orig_feed_data) { |
493c2f88 AD |
204 | |
205 | if (!$guid) $guid = sha1($link); | |
206 | ||
b9fc62a7 | 207 | $create_archived_feeds = true; |
fc5cd158 | 208 | |
493c2f88 AD |
209 | $guid = "$owner_uid,$guid"; |
210 | ||
211 | $content_hash = sha1($content); | |
212 | ||
213 | if (filter_var($link, FILTER_VALIDATE_URL) === FALSE) return false; | |
214 | ||
215 | db_query($this->link, "BEGIN"); | |
216 | ||
749da11b AD |
217 | $feed_id = 'NULL'; |
218 | ||
219 | // let's check for archived feed entry | |
220 | ||
221 | $feed_inserted = false; | |
222 | ||
223 | // before dealing with archived feeds we must check ttrss_feeds to maintain id consistency | |
224 | ||
fc5cd158 | 225 | if ($orig_feed_data['feed_url'] && $create_archived_feeds) { |
749da11b AD |
226 | $result = db_query($this->link, |
227 | "SELECT id FROM ttrss_feeds WHERE feed_url = '".$orig_feed_data['feed_url']."' | |
228 | AND owner_uid = $owner_uid"); | |
229 | ||
230 | if (db_num_rows($result) != 0) { | |
231 | $feed_id = db_fetch_result($result, 0, "id"); | |
232 | } else { | |
233 | // let's insert it | |
234 | ||
235 | if (!$orig_feed_data['title']) $orig_feed_data['title'] = '[Unknown]'; | |
236 | ||
237 | $result = db_query($this->link, | |
238 | "INSERT INTO ttrss_feeds | |
239 | (owner_uid,feed_url,site_url,title,cat_id,auth_login,auth_pass,update_method) | |
240 | VALUES ($owner_uid, | |
241 | '".$orig_feed_data['feed_url']."', | |
242 | '".$orig_feed_data['site_url']."', | |
243 | '".$orig_feed_data['title']."', | |
244 | NULL, '', '', 0)"); | |
245 | ||
246 | $result = db_query($this->link, | |
247 | "SELECT id FROM ttrss_feeds WHERE feed_url = '".$orig_feed_data['feed_url']."' | |
248 | AND owner_uid = $owner_uid"); | |
249 | ||
250 | if (db_num_rows($result) != 0) { | |
251 | $feed_id = db_fetch_result($result, 0, "id"); | |
252 | $feed_inserted = true; | |
253 | } | |
254 | } | |
255 | } | |
256 | ||
61096207 | 257 | if ($feed_id && $feed_id != 'NULL') { |
749da11b AD |
258 | // locate archived entry to file entries in, we don't want to file them in actual feeds because of purging |
259 | // maybe file marked in real feeds because eh | |
260 | ||
261 | $result = db_query($this->link, "SELECT id FROM ttrss_archived_feeds WHERE | |
262 | feed_url = '".$orig_feed_data['feed_url']."' AND owner_uid = $owner_uid"); | |
263 | ||
264 | if (db_num_rows($result) != 0) { | |
265 | $orig_feed_id = db_fetch_result($result, 0, "id"); | |
266 | } else { | |
267 | db_query($this->link, "INSERT INTO ttrss_archived_feeds | |
268 | (id, owner_uid, title, feed_url, site_url) | |
269 | SELECT id, owner_uid, title, feed_url, site_url from ttrss_feeds | |
270 | WHERE id = '$feed_id'"); | |
271 | ||
272 | $result = db_query($this->link, "SELECT id FROM ttrss_archived_feeds WHERE | |
273 | feed_url = '".$orig_feed_data['feed_url']."' AND owner_uid = $owner_uid"); | |
274 | ||
275 | if (db_num_rows($result) != 0) { | |
276 | $orig_feed_id = db_fetch_result($result, 0, "id"); | |
749da11b AD |
277 | } |
278 | } | |
279 | } | |
280 | ||
b9fc62a7 AD |
281 | // delete temporarily inserted feed |
282 | if ($feed_id && $feed_inserted) { | |
283 | db_query($this->link, "DELETE FROM ttrss_feeds WHERE id = $feed_id"); | |
284 | } | |
285 | ||
61096207 AD |
286 | if (!$orig_feed_id) $orig_feed_id = 'NULL'; |
287 | ||
493c2f88 AD |
288 | $result = db_query($this->link, "SELECT id FROM ttrss_entries, ttrss_user_entries WHERE |
289 | guid = '$guid' AND ref_id = id AND owner_uid = '$owner_uid' LIMIT 1"); | |
290 | ||
291 | if (db_num_rows($result) == 0) { | |
292 | $result = db_query($this->link, "INSERT INTO ttrss_entries | |
293 | (title, guid, link, updated, content, content_hash, date_entered, date_updated, author) | |
294 | VALUES | |
295 | ('$title', '$guid', '$link', '$updated', '$content', '$content_hash', NOW(), NOW(), '$author')"); | |
296 | ||
297 | $result = db_query($this->link, "SELECT id FROM ttrss_entries WHERE guid = '$guid'"); | |
298 | ||
299 | if (db_num_rows($result) != 0) { | |
300 | $ref_id = db_fetch_result($result, 0, "id"); | |
301 | ||
302 | db_query($this->link, "INSERT INTO ttrss_user_entries | |
303 | (ref_id, uuid, feed_id, orig_feed_id, owner_uid, marked, tag_cache, label_cache, | |
304 | last_read, note, unread, last_marked) | |
305 | VALUES | |
b9fc62a7 | 306 | ('$ref_id', '', NULL, $orig_feed_id, $owner_uid, $marked, '', '', NOW(), '', false, NOW())"); |
493c2f88 | 307 | |
4188225c AD |
308 | $result = db_query($this->link, "SELECT int_id FROM ttrss_user_entries, ttrss_entries |
309 | WHERE owner_uid = $owner_uid AND ref_id = id AND ref_id = $ref_id"); | |
310 | ||
311 | if (db_num_rows($result) != 0 && is_array($tags)) { | |
312 | ||
313 | $entry_int_id = db_fetch_result($result, 0, "int_id"); | |
314 | $tags_to_cache = array(); | |
315 | ||
316 | foreach ($tags as $tag) { | |
317 | ||
318 | $tag = db_escape_string($this->link, sanitize_tag($tag)); | |
319 | ||
320 | if (!tag_is_valid($tag)) continue; | |
321 | ||
322 | $result = db_query($this->link, "SELECT id FROM ttrss_tags | |
323 | WHERE tag_name = '$tag' AND post_int_id = '$entry_int_id' AND | |
324 | owner_uid = '$owner_uid' LIMIT 1"); | |
325 | ||
326 | if ($result && db_num_rows($result) == 0) { | |
327 | db_query($this->link, "INSERT INTO ttrss_tags | |
328 | (owner_uid,tag_name,post_int_id) | |
329 | VALUES ('$owner_uid','$tag', '$entry_int_id')"); | |
330 | } | |
331 | ||
332 | array_push($tags_to_cache, $tag); | |
493c2f88 | 333 | } |
4188225c AD |
334 | |
335 | /* update the cache */ | |
336 | ||
337 | $tags_to_cache = array_unique($tags_to_cache); | |
338 | $tags_str = db_escape_string($this->link, join(",", $tags_to_cache)); | |
339 | ||
340 | db_query($this->link, "UPDATE ttrss_user_entries | |
341 | SET tag_cache = '$tags_str' WHERE ref_id = '$ref_id' | |
342 | AND owner_uid = $owner_uid"); | |
493c2f88 AD |
343 | } |
344 | ||
345 | $rc = true; | |
346 | } | |
347 | } | |
348 | ||
1b1db717 | 349 | db_query($this->link, "COMMIT"); |
493c2f88 AD |
350 | |
351 | return $rc; | |
352 | } | |
353 | ||
354 | function hook_prefs_tab($args) { | |
355 | if ($args != "prefFeeds") return; | |
356 | ||
4c92878f | 357 | print "<div dojoType=\"dijit.layout.AccordionPane\" title=\"".__("Import starred or shared items from Google Reader")."\">"; |
493c2f88 | 358 | |
4c92878f | 359 | print_notice("Your imported articles will appear in Starred (in file is named starred.json) and Archived feeds."); |
493c2f88 | 360 | |
4c92878f | 361 | print "<p>".__("Paste your starred.json or shared.json into the form below."). "</p>"; |
493c2f88 AD |
362 | |
363 | print "<iframe id=\"starred_upload_iframe\" | |
364 | name=\"starred_upload_iframe\" onload=\"starredImportComplete(this)\" | |
365 | style=\"width: 400px; height: 100px; display: none;\"></iframe>"; | |
366 | ||
367 | print "<form name=\"starred_form\" style='display : block' target=\"starred_upload_iframe\" | |
368 | enctype=\"multipart/form-data\" method=\"POST\" | |
369 | action=\"backend.php\"> | |
370 | <input id=\"starred_file\" name=\"starred_file\" type=\"file\"> | |
371 | <input type=\"hidden\" name=\"op\" value=\"pluginhandler\"> | |
372 | <input type=\"hidden\" name=\"method\" value=\"import\"> | |
93e79595 | 373 | <input type=\"hidden\" name=\"plugin\" value=\"googlereaderimport\"> |
493c2f88 AD |
374 | <button dojoType=\"dijit.form.Button\" onclick=\"return starredImport();\" type=\"submit\">" . |
375 | __('Import my Starred items') . "</button>"; | |
376 | ||
b229a184 | 377 | print "</form>"; |
493c2f88 AD |
378 | |
379 | print "</div>"; #pane | |
380 | } | |
381 | } | |
382 | ?> |