]> git.wh0rd.org - tt-rss.git/blame - classes/pref_feeds.php
initial work on nested categories
[tt-rss.git] / classes / pref_feeds.php
CommitLineData
afcfe6ca 1<?php
46da73c2 2class Pref_Feeds extends Protected_Handler {
8484ce22
AD
3
4 function csrf_ignore($method) {
f6cd767b 5 $csrf_ignored = array("index", "getfeedtree", "add", "editcats", "editfeed",
35b9844b 6 "savefeedorder", "uploadicon");
8484ce22
AD
7
8 return array_search($method, $csrf_ignored) !== false;
9 }
10
afcfe6ca
AD
11 function batch_edit_cbox($elem, $label = false) {
12 print "<input type=\"checkbox\" title=\"".__("Check to enable field")."\"
13 onchange=\"dijit.byId('feedEditDlg').toggleField(this, '$elem', '$label')\">";
14 }
15
16 function renamecat() {
17 $title = db_escape_string($_REQUEST['title']);
18 $id = db_escape_string($_REQUEST['id']);
19
20 if ($title) {
21 db_query($this->link, "UPDATE ttrss_feed_categories SET
22 title = '$title' WHERE id = '$id' AND owner_uid = " . $_SESSION["uid"]);
23 }
24 return;
25 }
26
27 function remtwitterinfo() {
28
29 db_query($this->link, "UPDATE ttrss_users SET twitter_oauth = NULL
30 WHERE id = " . $_SESSION['uid']);
31
32 return;
33 }
34
2a060a94
AD
35 private function get_category_items($cat_id) {
36
37 $items = array();
38
39 $result = db_query($this->link, "SELECT id, title FROM ttrss_feed_categories
40 WHERE owner_uid = " . $_SESSION["uid"] . " AND parent_cat = '$cat_id' ORDER BY order_id, title");
41
42 while ($line = db_fetch_assoc($result)) {
43
44 $cat = array();
45 $cat['id'] = 'CAT:' . $line['id'];
46 $cat['bare_id'] = $feed_id;
47 $cat['name'] = $line['title'];
48 $cat['items'] = array();
49 $cat['checkbox'] = false;
50 $cat['type'] = 'category';
51
52 $cat['items'] = $this->get_category_items($line['id']);
53
54 $cat['param'] = T_sprintf('(%d feeds)', count($cat['items']));
55
56 if (count($cat['items']) > 0 || $show_empty_cats)
57 array_push($items, $cat);
58
59 }
60
61 $feed_result = db_query($this->link, "SELECT id, title, last_error,
62 ".SUBSTRING_FOR_DATE."(last_updated,1,19) AS last_updated
63 FROM ttrss_feeds
64 WHERE cat_id = '$cat_id' AND owner_uid = ".$_SESSION["uid"].
65 "$search_qpart ORDER BY order_id, title");
66
67 while ($feed_line = db_fetch_assoc($feed_result)) {
68 $feed = array();
69 $feed['id'] = 'FEED:' . $feed_line['id'];
70 $feed['bare_id'] = $feed_line['id'];
71 $feed['name'] = $feed_line['title'];
72 $feed['checkbox'] = false;
73 $feed['error'] = $feed_line['last_error'];
74 $feed['icon'] = getFeedIcon($feed_line['id']);
75 $feed['param'] = make_local_datetime($this->link,
76 $feed_line['last_updated'], true);
77
78 array_push($items, $feed);
79 }
80
81 return $items;
82 }
83
afcfe6ca
AD
84 function getfeedtree() {
85
86 $search = $_SESSION["prefs_feed_search"];
87
88 if ($search) $search_qpart = " AND LOWER(title) LIKE LOWER('%$search%')";
89
90 $root = array();
91 $root['id'] = 'root';
92 $root['name'] = __('Feeds');
93 $root['items'] = array();
94 $root['type'] = 'category';
95
96 if (get_pref($this->link, 'ENABLE_FEED_CATS')) {
5b7bd238 97 $show_empty_cats = get_pref($this->link, '_PREFS_SHOW_EMPTY_CATS');
afcfe6ca
AD
98
99 $result = db_query($this->link, "SELECT id, title FROM ttrss_feed_categories
2a060a94 100 WHERE owner_uid = " . $_SESSION["uid"] . " AND parent_cat IS NULL ORDER BY order_id, title");
afcfe6ca
AD
101
102 while ($line = db_fetch_assoc($result)) {
103 $cat = array();
104 $cat['id'] = 'CAT:' . $line['id'];
105 $cat['bare_id'] = $feed_id;
106 $cat['name'] = $line['title'];
107 $cat['items'] = array();
108 $cat['checkbox'] = false;
109 $cat['type'] = 'category';
110
2a060a94 111 $cat['items'] = $this->get_category_items($line['id']);
afcfe6ca
AD
112
113 $cat['param'] = T_sprintf('(%d feeds)', count($cat['items']));
114
5b7bd238 115 if (count($cat['items']) > 0 || $show_empty_cats)
afcfe6ca
AD
116 array_push($root['items'], $cat);
117
118 $root['param'] += count($cat['items']);
119 }
120
121 /* Uncategorized is a special case */
122
123 $cat = array();
124 $cat['id'] = 'CAT:0';
125 $cat['bare_id'] = 0;
126 $cat['name'] = __("Uncategorized");
127 $cat['items'] = array();
128 $cat['type'] = 'category';
129 $cat['checkbox'] = false;
130
131 $feed_result = db_query($this->link, "SELECT id, title,last_error,
132 ".SUBSTRING_FOR_DATE."(last_updated,1,19) AS last_updated
133 FROM ttrss_feeds
134 WHERE cat_id IS NULL AND owner_uid = ".$_SESSION["uid"].
135 "$search_qpart ORDER BY order_id, title");
136
137 while ($feed_line = db_fetch_assoc($feed_result)) {
138 $feed = array();
139 $feed['id'] = 'FEED:' . $feed_line['id'];
140 $feed['bare_id'] = $feed_line['id'];
141 $feed['name'] = $feed_line['title'];
142 $feed['checkbox'] = false;
143 $feed['error'] = $feed_line['last_error'];
144 $feed['icon'] = getFeedIcon($feed_line['id']);
145 $feed['param'] = make_local_datetime($this->link,
146 $feed_line['last_updated'], true);
147
148 array_push($cat['items'], $feed);
149 }
150
151 $cat['param'] = T_sprintf('(%d feeds)', count($cat['items']));
152
5b7bd238 153 if (count($cat['items']) > 0 || $show_empty_cats)
afcfe6ca
AD
154 array_push($root['items'], $cat);
155
156 $root['param'] += count($cat['items']);
157 $root['param'] = T_sprintf('(%d feeds)', $root['param']);
158
159 } else {
160 $feed_result = db_query($this->link, "SELECT id, title, last_error,
161 ".SUBSTRING_FOR_DATE."(last_updated,1,19) AS last_updated
162 FROM ttrss_feeds
163 WHERE owner_uid = ".$_SESSION["uid"].
164 "$search_qpart ORDER BY order_id, title");
165
166 while ($feed_line = db_fetch_assoc($feed_result)) {
167 $feed = array();
168 $feed['id'] = 'FEED:' . $feed_line['id'];
169 $feed['bare_id'] = $feed_line['id'];
170 $feed['name'] = $feed_line['title'];
171 $feed['checkbox'] = false;
172 $feed['error'] = $feed_line['last_error'];
173 $feed['icon'] = getFeedIcon($feed_line['id']);
174 $feed['param'] = make_local_datetime($this->link,
175 $feed_line['last_updated'], true);
176
177 array_push($root['items'], $feed);
178 }
179
180 $root['param'] = T_sprintf('(%d feeds)', count($root['items']));
181
182 }
183
184 $fl = array();
185 $fl['identifier'] = 'id';
186 $fl['label'] = 'name';
187 $fl['items'] = array($root);
188
189 print json_encode($fl);
190 return;
191 }
192
193 function catsortreset() {
194 db_query($this->link, "UPDATE ttrss_feed_categories
195 SET order_id = 0 WHERE owner_uid = " . $_SESSION["uid"]);
196 return;
197 }
198
199 function feedsortreset() {
200 db_query($this->link, "UPDATE ttrss_feeds
201 SET order_id = 0 WHERE owner_uid = " . $_SESSION["uid"]);
202 return;
203 }
204
5b7bd238
AD
205 function togglehiddenfeedcats() {
206 set_pref($this->link, '_PREFS_SHOW_EMPTY_CATS',
207 (get_pref($this->link, '_PREFS_SHOW_EMPTY_CATS') ? 'false' : 'true'));
208 }
209
2a060a94
AD
210 private function process_category_order($data_map, $item_id, $parent_id = false) {
211# print "C: $item_id P: $parent_id\n";
212 $bare_id = substr($item_id, strpos($item_id, ':')+1);
213
214 if ($item_id != 'root') {
215 if ($parent_id && $parent_id != 'root') {
216 $parent_bare_id = substr($parent_id, strpos($parent_id, ':')+1);
217 $parent_qpart = db_escape_string($parent_bare_id);
218 } else {
219 $parent_qpart = 'NULL';
220 }
221
222 db_query($this->link, "UPDATE ttrss_feed_categories
223 SET parent_cat = $parent_qpart WHERE id = '$bare_id' AND
224 owner_uid = " . $_SESSION["uid"]);
225 }
226
227 $order_id = 0;
228
229 $cat = $data_map[$item_id];
230
231 if ($cat && is_array($cat)) {
232 foreach ($cat as $item) {
233 $id = $item['_reference'];
234 $bare_id = substr($id, strpos($id, ':')+1);
235
236# print "[$order_id] $id/$bare_id\n";
237
238 if ($item['_reference']) {
239
240 if (strpos($id, "FEED") === 0) {
241
242 db_query($this->link, "UPDATE ttrss_feeds
243 SET order_id = '$order_id' WHERE id = '$bare_id' AND
244 owner_uid = " . $_SESSION["uid"]);
245
246 } else if (strpos($id, "CAT:") === 0) {
247 $this->process_category_order(&$data_map, $item['_reference'], $item_id);
248
249 if ($item_id != 'root') {
250 $parent_qpart = db_escape_string($bare_id);
251 } else {
252 $parent_qpart = 'NULL';
253 }
254
255 db_query($this->link, "UPDATE ttrss_feed_categories
256 SET order_id = '$order_id' WHERE id = '$bare_id' AND
257 owner_uid = " . $_SESSION["uid"]);
258 }
259 }
260
261 ++$order_id;
262 }
263 }
264 }
265
afcfe6ca
AD
266 function savefeedorder() {
267 $data = json_decode($_POST['payload'], true);
268
2a060a94
AD
269 #file_put_contents("/tmp/saveorder.json", $_POST['payload']);
270 #$data = json_decode(file_get_contents("/tmp/saveorder.json"), true);
271
afcfe6ca
AD
272 if (is_array($data) && is_array($data['items'])) {
273 $cat_order_id = 0;
274
275 $data_map = array();
2a060a94 276 $root_item = false;
afcfe6ca
AD
277
278 foreach ($data['items'] as $item) {
279
2a060a94 280# if ($item['id'] != 'root') {
afcfe6ca
AD
281 if (is_array($item['items'])) {
282 if (isset($item['items']['_reference'])) {
283 $data_map[$item['id']] = array($item['items']);
284 } else {
285 $data_map[$item['id']] =& $item['items'];
286 }
287 }
2a060a94
AD
288 if ($item['id'] == 'root') {
289 $root_item = $item['id'];
afcfe6ca
AD
290 }
291 }
292
2a060a94
AD
293 $this->process_category_order(&$data_map, $root_item);
294
295 /* foreach ($data['items'][0]['items'] as $item) {
afcfe6ca
AD
296 $id = $item['_reference'];
297 $bare_id = substr($id, strpos($id, ':')+1);
298
299 ++$cat_order_id;
300
301 if ($bare_id > 0) {
302 db_query($this->link, "UPDATE ttrss_feed_categories
303 SET order_id = '$cat_order_id' WHERE id = '$bare_id' AND
304 owner_uid = " . $_SESSION["uid"]);
305 }
306
307 $feed_order_id = 0;
308
309 if (is_array($data_map[$id])) {
310 foreach ($data_map[$id] as $feed) {
311 $id = $feed['_reference'];
312 $feed_id = substr($id, strpos($id, ':')+1);
313
314 if ($bare_id != 0)
315 $cat_query = "cat_id = '$bare_id'";
316 else
317 $cat_query = "cat_id = NULL";
318
319 db_query($this->link, "UPDATE ttrss_feeds
320 SET order_id = '$feed_order_id',
321 $cat_query
322 WHERE id = '$feed_id' AND
323 owner_uid = " . $_SESSION["uid"]);
324
325 ++$feed_order_id;
326 }
327 }
2a060a94 328 } */
afcfe6ca
AD
329 }
330
331 return;
332 }
333
334 function removeicon() {
335 $feed_id = db_escape_string($_REQUEST["feed_id"]);
336
337 $result = db_query($this->link, "SELECT id FROM ttrss_feeds
338 WHERE id = '$feed_id' AND owner_uid = ". $_SESSION["uid"]);
339
340 if (db_num_rows($result) != 0) {
341 unlink(ICONS_DIR . "/$feed_id.ico");
342 }
343
344 return;
345 }
346
347 function uploadicon() {
348 $icon_file = $_FILES['icon_file']['tmp_name'];
349 $feed_id = db_escape_string($_REQUEST["feed_id"]);
350
351 if (is_file($icon_file) && $feed_id) {
352 if (filesize($icon_file) < 20000) {
353
354 $result = db_query($this->link, "SELECT id FROM ttrss_feeds
355 WHERE id = '$feed_id' AND owner_uid = ". $_SESSION["uid"]);
356
357 if (db_num_rows($result) != 0) {
358 unlink(ICONS_DIR . "/$feed_id.ico");
359 move_uploaded_file($icon_file, ICONS_DIR . "/$feed_id.ico");
360 $rc = 0;
361 } else {
362 $rc = 2;
363 }
364 } else {
365 $rc = 1;
366 }
367 } else {
368 $rc = 2;
369 }
370
371 print "<script type=\"text/javascript\">";
372 print "parent.uploadIconHandler($rc);";
373 print "</script>";
374 return;
375 }
376
377 function editfeed() {
378 global $purge_intervals;
379 global $update_intervals;
380 global $update_methods;
381
382 $feed_id = db_escape_string($_REQUEST["id"]);
383
384 $result = db_query($this->link,
385 "SELECT * FROM ttrss_feeds WHERE id = '$feed_id' AND
386 owner_uid = " . $_SESSION["uid"]);
387
388 $title = htmlspecialchars(db_fetch_result($result,
389 0, "title"));
390
391 print "<input dojoType=\"dijit.form.TextBox\" style=\"display : none\" name=\"id\" value=\"$feed_id\">";
392 print "<input dojoType=\"dijit.form.TextBox\" style=\"display : none\" name=\"op\" value=\"pref-feeds\">";
393 print "<input dojoType=\"dijit.form.TextBox\" style=\"display : none\" name=\"method\" value=\"editSave\">";
394
395 print "<div class=\"dlgSec\">".__("Feed")."</div>";
396 print "<div class=\"dlgSecCont\">";
397
398 /* Title */
399
400 print "<input dojoType=\"dijit.form.ValidationTextBox\" required=\"1\"
401 placeHolder=\"".__("Feed Title")."\"
402 style=\"font-size : 16px; width: 20em\" name=\"title\" value=\"$title\">";
403
404 /* Feed URL */
405
406 $feed_url = db_fetch_result($result, 0, "feed_url");
407 $feed_url = htmlspecialchars(db_fetch_result($result,
408 0, "feed_url"));
409
410 print "<hr/>";
411
412 print __('URL:') . " ";
413 print "<input dojoType=\"dijit.form.ValidationTextBox\" required=\"1\"
414 placeHolder=\"".__("Feed URL")."\"
415 regExp='^(http|https)://.*' style=\"width : 20em\"
416 name=\"feed_url\" value=\"$feed_url\">";
417
418 $last_error = db_fetch_result($result, 0, "last_error");
419
420 if ($last_error) {
421 print "&nbsp;<span title=\"".htmlspecialchars($last_error)."\"
422 class=\"feed_error\">(error)</span>";
423
424 }
425
426 /* Category */
427
428 if (get_pref($this->link, 'ENABLE_FEED_CATS')) {
429
430 $cat_id = db_fetch_result($result, 0, "cat_id");
431
432 print "<hr/>";
433
434 print __('Place in category:') . " ";
435
436 print_feed_cat_select($this->link, "cat_id", $cat_id,
437 'dojoType="dijit.form.Select"');
438 }
439
440 print "</div>";
441
442 print "<div class=\"dlgSec\">".__("Update")."</div>";
443 print "<div class=\"dlgSecCont\">";
444
445 /* Update Interval */
446
447 $update_interval = db_fetch_result($result, 0, "update_interval");
448
449 print_select_hash("update_interval", $update_interval, $update_intervals,
450 'dojoType="dijit.form.Select"');
451
452 /* Update method */
453
454 $update_method = db_fetch_result($result, 0, "update_method",
455 'dojoType="dijit.form.Select"');
456
457 print " " . __('using') . " ";
458 print_select_hash("update_method", $update_method, $update_methods,
459 'dojoType="dijit.form.Select"');
460
461 $purge_interval = db_fetch_result($result, 0, "purge_interval");
462
463
464 /* Purge intl */
465
466 print "<hr/>";
467 print __('Article purging:') . " ";
468
469 print_select_hash("purge_interval", $purge_interval, $purge_intervals,
470 'dojoType="dijit.form.Select" ' .
471 ((FORCE_ARTICLE_PURGE == 0) ? "" : 'disabled="1"'));
472
473 print "</div>";
474 print "<div class=\"dlgSec\">".__("Authentication")."</div>";
475 print "<div class=\"dlgSecCont\">";
476
477 $auth_login = htmlspecialchars(db_fetch_result($result, 0, "auth_login"));
478
479 print "<input dojoType=\"dijit.form.TextBox\" id=\"feedEditDlg_login\"
480 placeHolder=\"".__("Login")."\"
481 name=\"auth_login\" value=\"$auth_login\"><hr/>";
482
483 $auth_pass = htmlspecialchars(db_fetch_result($result, 0, "auth_pass"));
484
485 print "<input dojoType=\"dijit.form.TextBox\" type=\"password\" name=\"auth_pass\"
486 placeHolder=\"".__("Password")."\"
487 value=\"$auth_pass\">";
488
489 print "<div dojoType=\"dijit.Tooltip\" connectId=\"feedEditDlg_login\" position=\"below\">
490 ".__('<b>Hint:</b> you need to fill in your login information if your feed requires authentication, except for Twitter feeds.')."
491 </div>";
492
493 print "</div>";
494 print "<div class=\"dlgSec\">".__("Options")."</div>";
495 print "<div class=\"dlgSecCont\">";
496
497 $private = sql_bool_to_bool(db_fetch_result($result, 0, "private"));
498
499 if ($private) {
500 $checked = "checked=\"1\"";
501 } else {
502 $checked = "";
503 }
504
505 print "<input dojoType=\"dijit.form.CheckBox\" type=\"checkbox\" name=\"private\" id=\"private\"
506 $checked>&nbsp;<label for=\"private\">".__('Hide from Popular feeds')."</label>";
507
508 $rtl_content = sql_bool_to_bool(db_fetch_result($result, 0, "rtl_content"));
509
510 if ($rtl_content) {
511 $checked = "checked=\"1\"";
512 } else {
513 $checked = "";
514 }
515
516 print "<hr/><input dojoType=\"dijit.form.CheckBox\" type=\"checkbox\" id=\"rtl_content\" name=\"rtl_content\"
517 $checked>&nbsp;<label for=\"rtl_content\">".__('Right-to-left content')."</label>";
518
519 $include_in_digest = sql_bool_to_bool(db_fetch_result($result, 0, "include_in_digest"));
520
521 if ($include_in_digest) {
522 $checked = "checked=\"1\"";
523 } else {
524 $checked = "";
525 }
526
527 print "<hr/><input dojoType=\"dijit.form.CheckBox\" type=\"checkbox\" id=\"include_in_digest\"
528 name=\"include_in_digest\"
529 $checked>&nbsp;<label for=\"include_in_digest\">".__('Include in e-mail digest')."</label>";
530
531
532 $always_display_enclosures = sql_bool_to_bool(db_fetch_result($result, 0, "always_display_enclosures"));
533
534 if ($always_display_enclosures) {
535 $checked = "checked";
536 } else {
537 $checked = "";
538 }
539
540 print "<hr/><input dojoType=\"dijit.form.CheckBox\" type=\"checkbox\" id=\"always_display_enclosures\"
541 name=\"always_display_enclosures\"
542 $checked>&nbsp;<label for=\"always_display_enclosures\">".__('Always display image attachments')."</label>";
543
544
545 $cache_images = sql_bool_to_bool(db_fetch_result($result, 0, "cache_images"));
546
547 if ($cache_images) {
548 $checked = "checked=\"1\"";
549 } else {
550 $checked = "";
551 }
552
3c696512
AD
553 print "<hr/><input dojoType=\"dijit.form.CheckBox\" type=\"checkbox\" id=\"cache_images\"
554 name=\"cache_images\"
afcfe6ca 555 $checked>&nbsp;<label for=\"cache_images\">".
3c696512 556 __('Cache images locally')."</label>";
afcfe6ca
AD
557
558 $mark_unread_on_update = sql_bool_to_bool(db_fetch_result($result, 0, "mark_unread_on_update"));
559
560 if ($mark_unread_on_update) {
561 $checked = "checked";
562 } else {
563 $checked = "";
564 }
565
566 print "<hr/><input dojoType=\"dijit.form.CheckBox\" type=\"checkbox\" id=\"mark_unread_on_update\"
567 name=\"mark_unread_on_update\"
568 $checked>&nbsp;<label for=\"mark_unread_on_update\">".__('Mark updated articles as unread')."</label>";
569
570 $update_on_checksum_change = sql_bool_to_bool(db_fetch_result($result, 0, "update_on_checksum_change"));
571
572 if ($update_on_checksum_change) {
573 $checked = "checked";
574 } else {
575 $checked = "";
576 }
577
578 print "<hr/><input dojoType=\"dijit.form.CheckBox\" type=\"checkbox\" id=\"update_on_checksum_change\"
579 name=\"update_on_checksum_change\"
580 $checked>&nbsp;<label for=\"update_on_checksum_change\">".__('Mark posts as updated on content change')."</label>";
581
582 print "</div>";
583
584 /* Icon */
585
586 print "<div class=\"dlgSec\">".__("Icon")."</div>";
587 print "<div class=\"dlgSecCont\">";
588
589 print "<iframe name=\"icon_upload_iframe\"
590 style=\"width: 400px; height: 100px; display: none;\"></iframe>";
591
592 print "<form style='display : block' target=\"icon_upload_iframe\"
593 enctype=\"multipart/form-data\" method=\"POST\"
594 action=\"backend.php\">
595 <input id=\"icon_file\" size=\"10\" name=\"icon_file\" type=\"file\">
596 <input type=\"hidden\" name=\"op\" value=\"pref-feeds\">
597 <input type=\"hidden\" name=\"feed_id\" value=\"$feed_id\">
598 <input type=\"hidden\" name=\"method\" value=\"uploadicon\">
599 <button dojoType=\"dijit.form.Button\" onclick=\"return uploadFeedIcon();\"
600 type=\"submit\">".__('Replace')."</button>
601 <button dojoType=\"dijit.form.Button\" onclick=\"return removeFeedIcon($feed_id);\"
602 type=\"submit\">".__('Remove')."</button>
603 </form>";
604
605 print "</div>";
606
607 $title = htmlspecialchars($title, ENT_QUOTES);
608
609 print "<div class='dlgButtons'>
610 <div style=\"float : left\">
611 <button dojoType=\"dijit.form.Button\" onclick='return unsubscribeFeed($feed_id, \"$title\")'>".
612 __('Unsubscribe')."</button>";
613
614 if (PUBSUBHUBBUB_ENABLED) {
615 $pubsub_state = db_fetch_result($result, 0, "pubsub_state");
616 $pubsub_btn_disabled = ($pubsub_state == 2) ? "" : "disabled=\"1\"";
617
618 print "<button dojoType=\"dijit.form.Button\" id=\"pubsubReset_Btn\" $pubsub_btn_disabled
619 onclick='return resetPubSub($feed_id, \"$title\")'>".__('Resubscribe to push updates').
620 "</button>";
621 }
622
623 print "</div>";
624
625 print "<div dojoType=\"dijit.Tooltip\" connectId=\"pubsubReset_Btn\" position=\"below\">".
626 __('Resets PubSubHubbub subscription status for push-enabled feeds.')."</div>";
627
628 print "<button dojoType=\"dijit.form.Button\" onclick=\"return dijit.byId('feedEditDlg').execute()\">".__('Save')."</button>
629 <button dojoType=\"dijit.form.Button\" onclick=\"return dijit.byId('feedEditDlg').hide()\">".__('Cancel')."</button>
630 </div>";
631
632 return;
633 }
634
635 function editfeeds() {
636 global $purge_intervals;
637 global $update_intervals;
638 global $update_methods;
46da73c2 639
afcfe6ca
AD
640 $feed_ids = db_escape_string($_REQUEST["ids"]);
641
ca6a0741
AD
642 print "<div class=\"dialogNotice\">" . __("Enable the options you wish to apply using checkboxes on the right:") . "</div>";
643
afcfe6ca
AD
644 print "<input dojoType=\"dijit.form.TextBox\" style=\"display : none\" name=\"ids\" value=\"$feed_ids\">";
645 print "<input dojoType=\"dijit.form.TextBox\" style=\"display : none\" name=\"op\" value=\"pref-feeds\">";
646 print "<input dojoType=\"dijit.form.TextBox\" style=\"display : none\" name=\"method\" value=\"batchEditSave\">";
647
648 print "<div class=\"dlgSec\">".__("Feed")."</div>";
649 print "<div class=\"dlgSecCont\">";
650
651 /* Title */
652
653 print "<input dojoType=\"dijit.form.ValidationTextBox\"
654 disabled=\"1\" style=\"font-size : 16px; width : 20em;\" required=\"1\"
655 name=\"title\" value=\"$title\">";
656
657 $this->batch_edit_cbox("title");
658
659 /* Feed URL */
660
661 print "<br/>";
662
663 print __('URL:') . " ";
664 print "<input dojoType=\"dijit.form.ValidationTextBox\" disabled=\"1\"
665 required=\"1\" regExp='^(http|https)://.*' style=\"width : 20em\"
666 name=\"feed_url\" value=\"$feed_url\">";
667
668 $this->batch_edit_cbox("feed_url");
669
670 /* Category */
671
672 if (get_pref($this->link, 'ENABLE_FEED_CATS')) {
673
674 print "<br/>";
675
676 print __('Place in category:') . " ";
677
678 print_feed_cat_select($this->link, "cat_id", $cat_id,
679 'disabled="1" dojoType="dijit.form.Select"');
680
681 $this->batch_edit_cbox("cat_id");
682
683 }
684
685 print "</div>";
686
687 print "<div class=\"dlgSec\">".__("Update")."</div>";
688 print "<div class=\"dlgSecCont\">";
689
690 /* Update Interval */
691
692 print_select_hash("update_interval", $update_interval, $update_intervals,
693 'disabled="1" dojoType="dijit.form.Select"');
694
695 $this->batch_edit_cbox("update_interval");
696
697 /* Update method */
698
699 print " " . __('using') . " ";
700 print_select_hash("update_method", $update_method, $update_methods,
701 'disabled="1" dojoType="dijit.form.Select"');
702 $this->batch_edit_cbox("update_method");
703
704 /* Purge intl */
705
706 if (FORCE_ARTICLE_PURGE == 0) {
707
708 print "<br/>";
709
710 print __('Article purging:') . " ";
711
712 print_select_hash("purge_interval", $purge_interval, $purge_intervals,
713 'disabled="1" dojoType="dijit.form.Select"');
714
715 $this->batch_edit_cbox("purge_interval");
716 }
717
718 print "</div>";
719 print "<div class=\"dlgSec\">".__("Authentication")."</div>";
720 print "<div class=\"dlgSecCont\">";
721
722 print "<input dojoType=\"dijit.form.TextBox\"
723 placeHolder=\"".__("Login")."\" disabled=\"1\"
724 name=\"auth_login\" value=\"$auth_login\">";
725
726 $this->batch_edit_cbox("auth_login");
727
728 print "<br/><input dojoType=\"dijit.form.TextBox\" type=\"password\" name=\"auth_pass\"
729 placeHolder=\"".__("Password")."\" disabled=\"1\"
730 value=\"$auth_pass\">";
731
732 $this->batch_edit_cbox("auth_pass");
733
734 print "</div>";
735 print "<div class=\"dlgSec\">".__("Options")."</div>";
736 print "<div class=\"dlgSecCont\">";
737
738 print "<input disabled=\"1\" type=\"checkbox\" name=\"private\" id=\"private\"
739 dojoType=\"dijit.form.CheckBox\">&nbsp;<label id=\"private_l\" class='insensitive' for=\"private\">".__('Hide from Popular feeds')."</label>";
740
741 print "&nbsp;"; $this->batch_edit_cbox("private", "private_l");
742
743 print "<br/><input disabled=\"1\" type=\"checkbox\" id=\"rtl_content\" name=\"rtl_content\"
744 dojoType=\"dijit.form.CheckBox\">&nbsp;<label class='insensitive' id=\"rtl_content_l\" for=\"rtl_content\">".__('Right-to-left content')."</label>";
745
746 print "&nbsp;"; $this->batch_edit_cbox("rtl_content", "rtl_content_l");
747
748 print "<br/><input disabled=\"1\" type=\"checkbox\" id=\"include_in_digest\"
749 name=\"include_in_digest\"
750 dojoType=\"dijit.form.CheckBox\">&nbsp;<label id=\"include_in_digest_l\" class='insensitive' for=\"include_in_digest\">".__('Include in e-mail digest')."</label>";
751
752 print "&nbsp;"; $this->batch_edit_cbox("include_in_digest", "include_in_digest_l");
753
754 print "<br/><input disabled=\"1\" type=\"checkbox\" id=\"always_display_enclosures\"
755 name=\"always_display_enclosures\"
756 dojoType=\"dijit.form.CheckBox\">&nbsp;<label id=\"always_display_enclosures_l\" class='insensitive' for=\"always_display_enclosures\">".__('Always display image attachments')."</label>";
757
758 print "&nbsp;"; $this->batch_edit_cbox("always_display_enclosures", "always_display_enclosures_l");
759
3c696512
AD
760 print "<br/><input disabled=\"1\" type=\"checkbox\" id=\"cache_images\"
761 name=\"cache_images\"
762 dojoType=\"dijit.form.CheckBox\">&nbsp;<label class='insensitive' id=\"cache_images_l\"
763 for=\"cache_images\">".
764 __('Cache images locally')."</label>";
afcfe6ca 765
3c696512 766 print "&nbsp;"; $this->batch_edit_cbox("cache_images", "cache_images_l");
afcfe6ca
AD
767
768 print "<br/><input disabled=\"1\" type=\"checkbox\" id=\"mark_unread_on_update\"
769 name=\"mark_unread_on_update\"
770 dojoType=\"dijit.form.CheckBox\">&nbsp;<label id=\"mark_unread_on_update_l\" class='insensitive' for=\"mark_unread_on_update\">".__('Mark updated articles as unread')."</label>";
771
772 print "&nbsp;"; $this->batch_edit_cbox("mark_unread_on_update", "mark_unread_on_update_l");
773
774 print "<br/><input disabled=\"1\" type=\"checkbox\" id=\"update_on_checksum_change\"
775 name=\"update_on_checksum_change\"
776 dojoType=\"dijit.form.CheckBox\">&nbsp;<label id=\"update_on_checksum_change_l\" class='insensitive' for=\"update_on_checksum_change\">".__('Mark posts as updated on content change')."</label>";
777
778 print "&nbsp;"; $this->batch_edit_cbox("update_on_checksum_change", "update_on_checksum_change_l");
779
780 print "</div>";
781
782 print "<div class='dlgButtons'>
783 <button dojoType=\"dijit.form.Button\"
784 onclick=\"return dijit.byId('feedEditDlg').execute()\">".
785 __('Save')."</button>
786 <button dojoType=\"dijit.form.Button\"
787 onclick=\"return dijit.byId('feedEditDlg').hide()\">".
788 __('Cancel')."</button>
789 </div>";
790
791 return;
792 }
793
794 function batchEditSave() {
3a76e2a2 795 return $this->editsaveops(true);
afcfe6ca 796 }
46da73c2 797
afcfe6ca 798 function editSave() {
3a76e2a2 799 return $this->editsaveops(false);
afcfe6ca 800 }
46da73c2
AD
801
802 function editsaveops($batch) {
803
afcfe6ca
AD
804 $feed_title = db_escape_string(trim($_POST["title"]));
805 $feed_link = db_escape_string(trim($_POST["feed_url"]));
806 $upd_intl = (int) db_escape_string($_POST["update_interval"]);
807 $purge_intl = (int) db_escape_string($_POST["purge_interval"]);
808 $feed_id = (int) db_escape_string($_POST["id"]); /* editSave */
809 $feed_ids = db_escape_string($_POST["ids"]); /* batchEditSave */
810 $cat_id = (int) db_escape_string($_POST["cat_id"]);
811 $auth_login = db_escape_string(trim($_POST["auth_login"]));
812 $auth_pass = db_escape_string(trim($_POST["auth_pass"]));
813 $private = checkbox_to_sql_bool(db_escape_string($_POST["private"]));
814 $rtl_content = checkbox_to_sql_bool(db_escape_string($_POST["rtl_content"]));
815 $include_in_digest = checkbox_to_sql_bool(
816 db_escape_string($_POST["include_in_digest"]));
817 $cache_images = checkbox_to_sql_bool(
818 db_escape_string($_POST["cache_images"]));
819 $update_method = (int) db_escape_string($_POST["update_method"]);
820
821 $always_display_enclosures = checkbox_to_sql_bool(
822 db_escape_string($_POST["always_display_enclosures"]));
823
824 $mark_unread_on_update = checkbox_to_sql_bool(
825 db_escape_string($_POST["mark_unread_on_update"]));
826
827 $update_on_checksum_change = checkbox_to_sql_bool(
828 db_escape_string($_POST["update_on_checksum_change"]));
829
830 if (get_pref($this->link, 'ENABLE_FEED_CATS')) {
831 if ($cat_id && $cat_id != 0) {
832 $category_qpart = "cat_id = '$cat_id',";
833 $category_qpart_nocomma = "cat_id = '$cat_id'";
834 } else {
835 $category_qpart = 'cat_id = NULL,';
836 $category_qpart_nocomma = 'cat_id = NULL';
837 }
838 } else {
839 $category_qpart = "";
840 $category_qpart_nocomma = "";
841 }
842
3c696512 843 $cache_images_qpart = "cache_images = $cache_images,";
afcfe6ca 844
3a76e2a2 845 if (!$batch) {
afcfe6ca
AD
846
847 $result = db_query($this->link, "UPDATE ttrss_feeds SET
848 $category_qpart
849 title = '$feed_title', feed_url = '$feed_link',
850 update_interval = '$upd_intl',
851 purge_interval = '$purge_intl',
852 auth_login = '$auth_login',
853 auth_pass = '$auth_pass',
854 private = $private,
855 rtl_content = $rtl_content,
856 $cache_images_qpart
857 include_in_digest = $include_in_digest,
858 always_display_enclosures = $always_display_enclosures,
859 mark_unread_on_update = $mark_unread_on_update,
860 update_on_checksum_change = $update_on_checksum_change,
861 update_method = '$update_method'
862 WHERE id = '$feed_id' AND owner_uid = " . $_SESSION["uid"]);
863
3a76e2a2 864 } else {
afcfe6ca
AD
865 $feed_data = array();
866
867 foreach (array_keys($_POST) as $k) {
868 if ($k != "op" && $k != "method" && $k != "ids") {
869 $feed_data[$k] = $_POST[$k];
870 }
871 }
872
873 db_query($this->link, "BEGIN");
874
875 foreach (array_keys($feed_data) as $k) {
876
877 $qpart = "";
878
879 switch ($k) {
880 case "title":
881 $qpart = "title = '$feed_title'";
882 break;
883
884 case "feed_url":
885 $qpart = "feed_url = '$feed_link'";
886 break;
887
888 case "update_interval":
889 $qpart = "update_interval = '$upd_intl'";
890 break;
891
892 case "purge_interval":
893 $qpart = "purge_interval = '$purge_intl'";
894 break;
895
896 case "auth_login":
897 $qpart = "auth_login = '$auth_login'";
898 break;
899
900 case "auth_pass":
901 $qpart = "auth_pass = '$auth_pass'";
902 break;
903
904 case "private":
a498d18b 905 $qpart = "private = $private";
afcfe6ca
AD
906 break;
907
908 case "include_in_digest":
a498d18b 909 $qpart = "include_in_digest = $include_in_digest";
afcfe6ca
AD
910 break;
911
912 case "always_display_enclosures":
a498d18b 913 $qpart = "always_display_enclosures = $always_display_enclosures";
afcfe6ca
AD
914 break;
915
916 case "mark_unread_on_update":
a498d18b 917 $qpart = "mark_unread_on_update = $mark_unread_on_update";
afcfe6ca
AD
918 break;
919
920 case "update_on_checksum_change":
a498d18b 921 $qpart = "update_on_checksum_change = $update_on_checksum_change";
afcfe6ca
AD
922 break;
923
924 case "cache_images":
a498d18b 925 $qpart = "cache_images = $cache_images";
afcfe6ca
AD
926 break;
927
928 case "rtl_content":
a498d18b 929 $qpart = "rtl_content = $rtl_content";
afcfe6ca
AD
930 break;
931
932 case "update_method":
933 $qpart = "update_method = '$update_method'";
934 break;
935
936 case "cat_id":
937 $qpart = $category_qpart_nocomma;
938 break;
939
940 }
941
942 if ($qpart) {
943 db_query($this->link,
944 "UPDATE ttrss_feeds SET $qpart WHERE id IN ($feed_ids)
945 AND owner_uid = " . $_SESSION["uid"]);
946 print "<br/>";
947 }
948 }
949
950 db_query($this->link, "COMMIT");
951 }
952 return;
953 }
954
955 function resetPubSub() {
956
957 $ids = db_escape_string($_REQUEST["ids"]);
958
959 db_query($this->link, "UPDATE ttrss_feeds SET pubsub_state = 0 WHERE id IN ($ids)
960 AND owner_uid = " . $_SESSION["uid"]);
961
962 return;
963 }
964
965 function remove() {
966
967 $ids = split(",", db_escape_string($_REQUEST["ids"]));
968
969 foreach ($ids as $id) {
970 remove_feed($this->link, $id, $_SESSION["uid"]);
971 }
972
973 return;
974 }
975
976 function clear() {
977 $id = db_escape_string($_REQUEST["id"]);
978 clear_feed_articles($this->link, $id);
979 }
980
981 function rescore() {
982 $ids = split(",", db_escape_string($_REQUEST["ids"]));
983
984 foreach ($ids as $id) {
985
986 $filters = load_filters($this->link, $id, $_SESSION["uid"], 6);
987
988 $result = db_query($this->link, "SELECT
989 title, content, link, ref_id, author,".
990 SUBSTRING_FOR_DATE."(updated, 1, 19) AS updated
991 FROM
992 ttrss_user_entries, ttrss_entries
993 WHERE ref_id = id AND feed_id = '$id' AND
994 owner_uid = " .$_SESSION['uid']."
995 ");
996
997 $scores = array();
998
999 while ($line = db_fetch_assoc($result)) {
1000
1001 $tags = get_article_tags($this->link, $line["ref_id"]);
1002
1003 $article_filters = get_article_filters($filters, $line['title'],
1004 $line['content'], $line['link'], strtotime($line['updated']),
1005 $line['author'], $tags);
1006
1007 $new_score = calculate_article_score($article_filters);
1008
1009 if (!$scores[$new_score]) $scores[$new_score] = array();
1010
1011 array_push($scores[$new_score], $line['ref_id']);
1012 }
1013
1014 foreach (array_keys($scores) as $s) {
1015 if ($s > 1000) {
1016 db_query($this->link, "UPDATE ttrss_user_entries SET score = '$s',
1017 marked = true WHERE
1018 ref_id IN (" . join(',', $scores[$s]) . ")");
1019 } else if ($s < -500) {
1020 db_query($this->link, "UPDATE ttrss_user_entries SET score = '$s',
1021 unread = false WHERE
1022 ref_id IN (" . join(',', $scores[$s]) . ")");
1023 } else {
1024 db_query($this->link, "UPDATE ttrss_user_entries SET score = '$s' WHERE
1025 ref_id IN (" . join(',', $scores[$s]) . ")");
1026 }
1027 }
1028 }
1029
1030 print __("All done.");
1031
1032 }
1033
1034 function rescoreAll() {
1035
1036 $result = db_query($this->link,
1037 "SELECT id FROM ttrss_feeds WHERE owner_uid = " . $_SESSION['uid']);
1038
1039 while ($feed_line = db_fetch_assoc($result)) {
1040
1041 $id = $feed_line["id"];
1042
1043 $filters = load_filters($this->link, $id, $_SESSION["uid"], 6);
1044
1045 $tmp_result = db_query($this->link, "SELECT
1046 title, content, link, ref_id, author,".
1047 SUBSTRING_FOR_DATE."(updated, 1, 19) AS updated
1048 FROM
1049 ttrss_user_entries, ttrss_entries
1050 WHERE ref_id = id AND feed_id = '$id' AND
1051 owner_uid = " .$_SESSION['uid']."
1052 ");
1053
1054 $scores = array();
1055
1056 while ($line = db_fetch_assoc($tmp_result)) {
1057
1058 $tags = get_article_tags($this->link, $line["ref_id"]);
1059
1060 $article_filters = get_article_filters($filters, $line['title'],
1061 $line['content'], $line['link'], strtotime($line['updated']),
1062 $line['author'], $tags);
1063
1064 $new_score = calculate_article_score($article_filters);
1065
1066 if (!$scores[$new_score]) $scores[$new_score] = array();
1067
1068 array_push($scores[$new_score], $line['ref_id']);
1069 }
1070
1071 foreach (array_keys($scores) as $s) {
1072 if ($s > 1000) {
1073 db_query($this->link, "UPDATE ttrss_user_entries SET score = '$s',
1074 marked = true WHERE
1075 ref_id IN (" . join(',', $scores[$s]) . ")");
1076 } else {
1077 db_query($this->link, "UPDATE ttrss_user_entries SET score = '$s' WHERE
1078 ref_id IN (" . join(',', $scores[$s]) . ")");
1079 }
1080 }
1081 }
1082
1083 print __("All done.");
1084
1085 }
1086
1087 function add() {
1088 $feed_url = db_escape_string(trim($_REQUEST["feed_url"]));
1089 $cat_id = db_escape_string($_REQUEST["cat_id"]);
1090 $p_from = db_escape_string($_REQUEST["from"]);
1091
1092 /* only read authentication information from POST */
1093
1094 $auth_login = db_escape_string(trim($_POST["auth_login"]));
1095 $auth_pass = db_escape_string(trim($_POST["auth_pass"]));
1096
1097 if ($p_from != 'tt-rss') {
f4ce1d64 1098 header('Content-Type: text/html; charset=utf-8');
afcfe6ca
AD
1099 print "<html>
1100 <head>
1101 <title>Tiny Tiny RSS</title>
1102 <link rel=\"stylesheet\" type=\"text/css\" href=\"utility.css\">
f4ce1d64 1103 <meta http-equiv=\"Content-Type\" content=\"text/html; charset=utf-8\"/>
afcfe6ca
AD
1104 </head>
1105 <body>
093fae5e 1106 <img class=\"floatingLogo\" src=\"images/logo_wide.png\"
afcfe6ca
AD
1107 alt=\"Tiny Tiny RSS\"/>
1108 <h1>Subscribe to feed...</h1>";
1109 }
1110
1111 $rc = subscribe_to_feed($this->link, $feed_url, $cat_id, $auth_login, $auth_pass);
1112
1113 switch ($rc) {
1114 case 1:
1115 print_notice(T_sprintf("Subscribed to <b>%s</b>.", $feed_url));
1116 break;
1117 case 2:
1118 print_error(T_sprintf("Could not subscribe to <b>%s</b>.", $feed_url));
1119 break;
1120 case 3:
1121 print_error(T_sprintf("No feeds found in <b>%s</b>.", $feed_url));
1122 break;
1123 case 0:
1124 print_warning(T_sprintf("Already subscribed to <b>%s</b>.", $feed_url));
1125 break;
1126 case 4:
d50edb08 1127 print_notice(__("Multiple feed URLs found."));
afcfe6ca
AD
1128
1129 $feed_urls = get_feeds_from_html($feed_url);
1130 break;
1131 case 5:
1132 print_error(T_sprintf("Could not subscribe to <b>%s</b>.<br>Can't download the Feed URL.", $feed_url));
1133 break;
1134 }
1135
1136 if ($p_from != 'tt-rss') {
1137
1138 if ($feed_urls) {
1139
1140 print "<form action=\"backend.php\">";
1141 print "<input type=\"hidden\" name=\"op\" value=\"pref-feeds\">";
1142 print "<input type=\"hidden\" name=\"quiet\" value=\"1\">";
1143 print "<input type=\"hidden\" name=\"method\" value=\"add\">";
1144
1145 print "<select name=\"feed_url\">";
1146
1147 foreach ($feed_urls as $url => $name) {
1148 $url = htmlspecialchars($url);
1149 $name = htmlspecialchars($name);
1150
1151 print "<option value=\"$url\">$name</option>";
1152 }
1153
1154 print "<input type=\"submit\" value=\"".__("Subscribe to selected feed").
1155 "\">";
1156
1157 print "</form>";
1158 }
1159
1160 $tp_uri = get_self_url_prefix() . "/prefs.php";
1161 $tt_uri = get_self_url_prefix();
1162
1163 if ($rc <= 2){
1164 $result = db_query($this->link, "SELECT id FROM ttrss_feeds WHERE
1165 feed_url = '$feed_url' AND owner_uid = " . $_SESSION["uid"]);
1166
1167 $feed_id = db_fetch_result($result, 0, "id");
1168 } else {
1169 $feed_id = 0;
1170 }
1171 print "<p>";
1172
1173 if ($feed_id) {
1174 print "<form method=\"GET\" style='display: inline'
1175 action=\"$tp_uri\">
1176 <input type=\"hidden\" name=\"tab\" value=\"feedConfig\">
1177 <input type=\"hidden\" name=\"method\" value=\"editFeed\">
1178 <input type=\"hidden\" name=\"methodparam\" value=\"$feed_id\">
1179 <input type=\"submit\" value=\"".__("Edit subscription options")."\">
1180 </form>";
1181 }
1182
1183 print "<form style='display: inline' method=\"GET\" action=\"$tt_uri\">
1184 <input type=\"submit\" value=\"".__("Return to Tiny Tiny RSS")."\">
1185 </form></p>";
1186
1187 print "</body></html>";
1188 return;
1189 }
1190 }
1191
1192 function categorize() {
1193 $ids = split(",", db_escape_string($_REQUEST["ids"]));
1194
1195 $cat_id = db_escape_string($_REQUEST["cat_id"]);
1196
1197 if ($cat_id == 0) {
1198 $cat_id_qpart = 'NULL';
1199 } else {
1200 $cat_id_qpart = "'$cat_id'";
1201 }
1202
1203 db_query($this->link, "BEGIN");
1204
1205 foreach ($ids as $id) {
1206
1207 db_query($this->link, "UPDATE ttrss_feeds SET cat_id = $cat_id_qpart
1208 WHERE id = '$id'
1209 AND owner_uid = " . $_SESSION["uid"]);
1210
1211 }
1212
1213 db_query($this->link, "COMMIT");
1214 }
1215
1216 function editCats() {
1217
1218 $action = $_REQUEST["action"];
1219
1220 if ($action == "save") {
1221
1222 $cat_title = db_escape_string(trim($_REQUEST["value"]));
1223 $cat_id = db_escape_string($_REQUEST["cid"]);
1224
1225 db_query($this->link, "BEGIN");
1226
1227 $result = db_query($this->link, "SELECT title FROM ttrss_feed_categories
1228 WHERE id = '$cat_id' AND owner_uid = ".$_SESSION["uid"]);
1229
1230 if (db_num_rows($result) == 1) {
1231
1232 $old_title = db_fetch_result($result, 0, "title");
1233
1234 if ($cat_title != "") {
1235 $result = db_query($this->link, "UPDATE ttrss_feed_categories SET
1236 title = '$cat_title' WHERE id = '$cat_id' AND
1237 owner_uid = ".$_SESSION["uid"]);
1238
1239 print $cat_title;
1240 } else {
1241 print $old_title;
1242 }
1243 } else {
1244 print $_REQUEST["value"];
1245 }
1246
1247 db_query($this->link, "COMMIT");
1248
1249 return;
1250
1251 }
1252
1253 if ($action == "add") {
1254
1255 $feed_cat = db_escape_string(trim($_REQUEST["cat"]));
1256
1257 if (!add_feed_category($this->link, $feed_cat))
1258 print_warning(T_sprintf("Category <b>$%s</b> already exists in the database.", $feed_cat));
1259
1260 }
1261
1262 if ($action == "remove") {
1263
1264 $ids = split(",", db_escape_string($_REQUEST["ids"]));
1265
1266 foreach ($ids as $id) {
1267 remove_feed_category($this->link, $id, $_SESSION["uid"]);
1268 }
1269 }
1270
ddb575c7
AD
1271 print "<div dojoType=\"dijit.Toolbar\">";
1272
1273 print "<div dojoType=\"dijit.form.DropDownButton\">".
1274 "<span>" . __('Select')."</span>";
1275 print "<div dojoType=\"dijit.Menu\" style=\"display: none;\">";
1276 print "<div onclick=\"selectTableRows('prefFeedCatList', 'all')\"
1277 dojoType=\"dijit.MenuItem\">".__('All')."</div>";
1278 print "<div onclick=\"selectTableRows('prefFeedCatList', 'none')\"
1279 dojoType=\"dijit.MenuItem\">".__('None')."</div>";
1280 print "</div></div>";
1281
1282 print "<div style='float : right'>";
1283
1284 print "<input dojoType=\"dijit.form.ValidationTextBox\" required=\"1\" name=\"newcat\">
afcfe6ca
AD
1285 <button dojoType=\"dijit.form.Button\" onclick=\"dijit.byId('feedCatEditDlg').addCategory()\">".
1286 __('Create category')."</button></div>";
1287
ddb575c7
AD
1288 print "</div>";
1289
7e454e81 1290 $result = db_query($this->link, "SELECT c.title, c.id,COUNT(f.id) AS count
a62812a6
AD
1291 FROM ttrss_feed_categories AS c LEFT JOIN ttrss_feeds AS f ON
1292 (f.cat_id = c.id)
1293 WHERE c.owner_uid = ".$_SESSION["uid"]."
1294 GROUP BY c.title, c.id ORDER BY title");
afcfe6ca
AD
1295
1296 if (db_num_rows($result) != 0) {
1297
1298 print "<div class=\"prefFeedCatHolder\">";
1299
1300 print "<table width=\"100%\" class=\"prefFeedCatList\"
1301 cellspacing=\"0\" id=\"prefFeedCatList\">";
1302
1303 $lnum = 0;
1304
1305 while ($line = db_fetch_assoc($result)) {
1306
1307 $class = ($lnum % 2) ? "even" : "odd";
1308
1309 $cat_id = $line["id"];
1310 $this_row_id = "id=\"FCATR-$cat_id\"";
1311
ddb575c7 1312 print "<tr class=\"placeholder\" $this_row_id>";
afcfe6ca
AD
1313
1314 $edit_title = htmlspecialchars($line["title"]);
1315
ddb575c7 1316 print "<td width='5%' align='center'><input id=\"FCATC-$cat_id\"
afcfe6ca
AD
1317 onclick='toggleSelectRow2(this);' dojoType=\"dijit.form.CheckBox\"
1318 type=\"checkbox\"></td>";
1319
1320 print "<td>";
1321
917c12ee
AD
1322 if ($line['count'] == 0) print '<em>';
1323
afcfe6ca
AD
1324 print "<span dojoType=\"dijit.InlineEditBox\"
1325 width=\"300px\" autoSave=\"false\"
1326 cat-id=\"$cat_id\">" . $edit_title .
1327 "<script type=\"dojo/method\" event=\"onChange\" args=\"item\">
1328 var elem = this;
1329 dojo.xhrPost({
1330 url: 'backend.php',
1331 content: {op: 'pref-feeds', method: 'editCats',
1332 action: 'save',
1333 value: this.value,
1334 cid: this.srcNodeRef.getAttribute('cat-id')},
1335 load: function(response) {
1336 elem.attr('value', response);
1337 updateFeedList();
1338 }
1339 });
1340 </script>
1341 </span>";
1342
917c12ee
AD
1343 if ($line['count'] == 0) print '</em>';
1344
1345 print "</td>";
1346
a62812a6
AD
1347 print "<td align='right' class='insensitive'>";
1348 echo T_sprintf("%d feeds", $line['count']);
afcfe6ca
AD
1349 print "</td></tr>";
1350
1351 ++$lnum;
1352 }
1353
1354 print "</table>";
1355 print "</div>";
1356
1357 } else {
1358 print "<p>".__('No feed categories defined.')."</p>";
1359 }
1360
1361 print "<div class='dlgButtons'>
1362 <div style='float : left'>
1363 <button dojoType=\"dijit.form.Button\" onclick=\"dijit.byId('feedCatEditDlg').removeSelected()\">".
1364 __('Remove selected categories')."</button>
1365 </div>";
1366
1367 print "<button dojoType=\"dijit.form.Button\" onclick=\"dijit.byId('feedCatEditDlg').hide()\">".
1368 __('Close this window')."</button></div>";
1369
1370 return;
1371
1372 }
1373
1374 function index() {
1375
1376 print "<div dojoType=\"dijit.layout.AccordionContainer\" region=\"center\">";
1377 print "<div id=\"pref-feeds-feeds\" dojoType=\"dijit.layout.AccordionPane\" title=\"".__('Feeds')."\">";
1378
1379 $result = db_query($this->link, "SELECT COUNT(id) AS num_errors
1380 FROM ttrss_feeds WHERE last_error != '' AND owner_uid = ".$_SESSION["uid"]);
1381
1382 $num_errors = db_fetch_result($result, 0, "num_errors");
1383
1384 if ($num_errors > 0) {
1385
1386 $error_button = "<button dojoType=\"dijit.form.Button\"
1387 onclick=\"showFeedsWithErrors()\" id=\"errorButton\">" .
1388 __("Feeds with errors") . "</button>";
1389 }
1390
1391 if (DB_TYPE == "pgsql") {
1392 $interval_qpart = "NOW() - INTERVAL '3 months'";
1393 } else {
1394 $interval_qpart = "DATE_SUB(NOW(), INTERVAL 3 MONTH)";
1395 }
1396
1397 $result = db_query($this->link, "SELECT COUNT(*) AS num_inactive FROM ttrss_feeds WHERE
1398 (SELECT MAX(updated) FROM ttrss_entries, ttrss_user_entries WHERE
1399 ttrss_entries.id = ref_id AND
1400 ttrss_user_entries.feed_id = ttrss_feeds.id) < $interval_qpart AND
1401 ttrss_feeds.owner_uid = ".$_SESSION["uid"]);
1402
1403 $num_inactive = db_fetch_result($result, 0, "num_inactive");
1404
1405 if ($num_inactive > 0) {
1406 $inactive_button = "<button dojoType=\"dijit.form.Button\"
1407 onclick=\"showInactiveFeeds()\">" .
1408 __("Inactive feeds") . "</button>";
1409 }
1410
1411 $feed_search = db_escape_string($_REQUEST["search"]);
1412
1413 if (array_key_exists("search", $_REQUEST)) {
1414 $_SESSION["prefs_feed_search"] = $feed_search;
1415 } else {
1416 $feed_search = $_SESSION["prefs_feed_search"];
1417 }
1418
1419 print '<div dojoType="dijit.layout.BorderContainer" gutters="false">';
1420
1421 print "<div region='top' dojoType=\"dijit.Toolbar\">"; #toolbar
1422
1423 print "<div style='float : right; padding-right : 4px;'>
1424 <input dojoType=\"dijit.form.TextBox\" id=\"feed_search\" size=\"20\" type=\"search\"
1425 value=\"$feed_search\">
1426 <button dojoType=\"dijit.form.Button\" onclick=\"updateFeedList()\">".
1427 __('Search')."</button>
1428 </div>";
1429
1430 print "<div dojoType=\"dijit.form.DropDownButton\">".
1431 "<span>" . __('Select')."</span>";
1432 print "<div dojoType=\"dijit.Menu\" style=\"display: none;\">";
1433 print "<div onclick=\"dijit.byId('feedTree').model.setAllChecked(true)\"
1434 dojoType=\"dijit.MenuItem\">".__('All')."</div>";
1435 print "<div onclick=\"dijit.byId('feedTree').model.setAllChecked(false)\"
1436 dojoType=\"dijit.MenuItem\">".__('None')."</div>";
1437 print "</div></div>";
1438
1439 print "<div dojoType=\"dijit.form.DropDownButton\">".
1440 "<span>" . __('Feeds')."</span>";
1441 print "<div dojoType=\"dijit.Menu\" style=\"display: none;\">";
1442 print "<div onclick=\"quickAddFeed()\"
1443 dojoType=\"dijit.MenuItem\">".__('Subscribe to feed')."</div>";
1444 print "<div onclick=\"editSelectedFeed()\"
1445 dojoType=\"dijit.MenuItem\">".__('Edit selected feeds')."</div>";
1446 print "<div onclick=\"resetFeedOrder()\"
1447 dojoType=\"dijit.MenuItem\">".__('Reset sort order')."</div>";
33f0fdd0
AD
1448 print "<div onclick=\"batchSubscribe()\"
1449 dojoType=\"dijit.MenuItem\">".__('Batch subscribe')."</div>";
afcfe6ca
AD
1450 print "</div></div>";
1451
1452 if (get_pref($this->link, 'ENABLE_FEED_CATS')) {
1453 print "<div dojoType=\"dijit.form.DropDownButton\">".
1454 "<span>" . __('Categories')."</span>";
1455 print "<div dojoType=\"dijit.Menu\" style=\"display: none;\">";
1456 print "<div onclick=\"editFeedCats()\"
1457 dojoType=\"dijit.MenuItem\">".__('Edit categories')."</div>";
5b7bd238
AD
1458 print "<div onclick=\"toggleHiddenFeedCats()\"
1459 dojoType=\"dijit.MenuItem\">".__('(Un)hide empty categories')."</div>";
afcfe6ca
AD
1460 print "<div onclick=\"resetCatOrder()\"
1461 dojoType=\"dijit.MenuItem\">".__('Reset sort order')."</div>";
1462 print "</div></div>";
1463
1464 }
1465
1466 print $error_button;
1467 print $inactive_button;
1468
1469 print "<button dojoType=\"dijit.form.Button\" onclick=\"removeSelectedFeeds()\">"
1470 .__('Unsubscribe')."</button dojoType=\"dijit.form.Button\"> ";
1471
1472 if (defined('_ENABLE_FEED_DEBUGGING')) {
1473
1474 print "<select id=\"feedActionChooser\" onchange=\"feedActionChange()\">
1475 <option value=\"facDefault\" selected>".__('More actions...')."</option>";
1476
1477 if (FORCE_ARTICLE_PURGE == 0) {
1478 print
1479 "<option value=\"facPurge\">".__('Manual purge')."</option>";
1480 }
1481
1482 print "
1483 <option value=\"facClear\">".__('Clear feed data')."</option>
1484 <option value=\"facRescore\">".__('Rescore articles')."</option>";
1485
1486 print "</select>";
1487
1488 }
1489
1490 print "</div>"; # toolbar
1491
1492 //print '</div>';
1493 print '<div dojoType="dijit.layout.ContentPane" region="center">';
1494
1495 print "<div id=\"feedlistLoading\">
1496 <img src='images/indicator_tiny.gif'>".
1497 __("Loading, please wait...")."</div>";
1498
1499 print "<div dojoType=\"fox.PrefFeedStore\" jsId=\"feedStore\"
1500 url=\"backend.php?op=pref-feeds&method=getfeedtree\">
1501 </div>
1502 <div dojoType=\"lib.CheckBoxStoreModel\" jsId=\"feedModel\" store=\"feedStore\"
1503 query=\"{id:'root'}\" rootId=\"root\" rootLabel=\"Feeds\"
1504 childrenAttrs=\"items\" checkboxStrict=\"false\" checkboxAll=\"false\">
1505 </div>
1506 <div dojoType=\"fox.PrefFeedTree\" id=\"feedTree\"
1507 dndController=\"dijit.tree.dndSource\"
1508 betweenThreshold=\"5\"
1509 model=\"feedModel\" openOnClick=\"false\">
1510 <script type=\"dojo/method\" event=\"onClick\" args=\"item\">
1511 var id = String(item.id);
1512 var bare_id = id.substr(id.indexOf(':')+1);
1513
1514 if (id.match('FEED:')) {
1515 editFeed(bare_id);
1516 } else if (id.match('CAT:')) {
1517 editCat(bare_id, item);
1518 }
1519 </script>
1520 <script type=\"dojo/method\" event=\"onLoad\" args=\"item\">
1521 Element.hide(\"feedlistLoading\");
1522 </script>
1523 </div>";
1524
1525 print "<div dojoType=\"dijit.Tooltip\" connectId=\"feedTree\" position=\"below\">
1526 ".__('<b>Hint:</b> you can drag feeds and categories around.')."
1527 </div>";
1528
1529 print '</div>';
1530 print '</div>';
1531
1532 print "</div>"; # feeds pane
1533
566faa14 1534 print "<div dojoType=\"dijit.layout.AccordionPane\" title=\"".__('Import and export')."\">";
afcfe6ca 1535
a1159c01 1536 print "<h3>" . __("OPML") . "</h3>";
afcfe6ca 1537
566faa14 1538 print "<p>" . __("Using OPML you can export and import your feeds, filters, labels and Tiny Tiny RSS settings.") . " ";
afcfe6ca 1539
566faa14 1540 print __("Only main settings profile can be migrated using OPML.") . "</p>";
afcfe6ca 1541
55f34b81 1542 print "<iframe id=\"upload_iframe\"
afcfe6ca
AD
1543 name=\"upload_iframe\" onload=\"opmlImportComplete(this)\"
1544 style=\"width: 400px; height: 100px; display: none;\"></iframe>";
1545
1546 print "<form name=\"opml_form\" style='display : block' target=\"upload_iframe\"
1547 enctype=\"multipart/form-data\" method=\"POST\"
55f34b81 1548 action=\"backend.php\">
afcfe6ca
AD
1549 <input id=\"opml_file\" name=\"opml_file\" type=\"file\">&nbsp;
1550 <input type=\"hidden\" name=\"op\" value=\"dlg\">
c4c74732 1551 <input type=\"hidden\" name=\"method\" value=\"importOpml\">
afcfe6ca 1552 <button dojoType=\"dijit.form.Button\" onclick=\"return opmlImport();\" type=\"submit\">" .
a1159c01 1553 __('Import my OPML') . "</button>";
afcfe6ca 1554
a1159c01 1555 print "<hr>";
afcfe6ca
AD
1556
1557 print "<p>" . __('Filename:') .
1558 " <input type=\"text\" id=\"filename\" value=\"TinyTinyRSS.opml\" />&nbsp;" .
a1159c01 1559 __('Include settings') . "<input type=\"checkbox\" id=\"settings\" checked=\"1\"/>";
afcfe6ca 1560
a1159c01 1561 print "</p><button dojoType=\"dijit.form.Button\"
afcfe6ca 1562 onclick=\"gotoExportOpml(document.opml_form.filename.value, document.opml_form.settings.checked)\" >" .
a1159c01 1563 __('Export OPML') . "</button></p></form>";
afcfe6ca 1564
a1159c01 1565 print "<hr>";
afcfe6ca
AD
1566
1567 print "<p>".__('Your OPML can be published publicly and can be subscribed by anyone who knows the URL below.') . " ";
1568
566faa14 1569 print __("Published OPML does not include your Tiny Tiny RSS settings, feeds that require authentication or feeds hidden from Popular feeds.") . "</p>";
afcfe6ca
AD
1570
1571 print "<button dojoType=\"dijit.form.Button\" onclick=\"return displayDlg('pubOPMLUrl')\">".
a1159c01 1572 __('Display published OPML URL')."</button> ";
afcfe6ca 1573
55f34b81 1574
a1159c01 1575 print "<h3>" . __("Article archive") . "</h3>";
566faa14 1576
a1159c01 1577 print "<p>" . __("You can export and import your Starred and Archived articles for safekeeping or when migrating between tt-rss instances.") . "</p>";
566faa14
AD
1578
1579 print "<button dojoType=\"dijit.form.Button\" onclick=\"return exportData()\">".
1580 __('Export my data')."</button> ";
1581
a1159c01 1582 print "<hr>";
55f34b81
AD
1583
1584 print "<iframe id=\"data_upload_iframe\"
1585 name=\"data_upload_iframe\" onload=\"dataImportComplete(this)\"
1586 style=\"width: 400px; height: 100px; display: none;\"></iframe>";
1587
41f68571 1588 print "<form name=\"import_form\" style='display : block' target=\"data_upload_iframe\"
55f34b81
AD
1589 enctype=\"multipart/form-data\" method=\"POST\"
1590 action=\"backend.php\">
1591 <input id=\"export_file\" name=\"export_file\" type=\"file\">&nbsp;
1592 <input type=\"hidden\" name=\"op\" value=\"dlg\">
1593 <input type=\"hidden\" name=\"method\" value=\"dataimport\">
1594 <button dojoType=\"dijit.form.Button\" onclick=\"return importData();\" type=\"submit\">" .
1595 __('Import') . "</button>";
1596
1597
afcfe6ca
AD
1598 print "</div>"; # pane
1599
1600 if (strpos($_SERVER['HTTP_USER_AGENT'], "Firefox") !== false) {
1601
1602 print "<div dojoType=\"dijit.layout.AccordionPane\" title=\"".__('Firefox integration')."\">";
1603
1604 print "<p>" . __('This Tiny Tiny RSS site can be used as a Firefox Feed Reader by clicking the link below.') . "</p>";
1605
1606 print "<p>";
1607
1608 print "<button onclick='window.navigator.registerContentHandler(" .
1609 "\"application/vnd.mozilla.maybe.feed\", " .
1610 "\"" . add_feed_url() . "\", " . " \"Tiny Tiny RSS\")'>" .
1611 __('Click here to register this site as a feed reader.') .
1612 "</button>";
1613
1614 print "</p>";
1615
1616 print "</div>"; # pane
1617 }
1618
1619 print "<div dojoType=\"dijit.layout.AccordionPane\" title=\"".__('Subscribing using bookmarklet')."\">";
1620
1621 print "<p>" . __("Drag the link below to your browser toolbar, open the feed you're interested in in your browser and click on the link to subscribe to it.") . "</p>";
1622
1623 $bm_subscribe_url = str_replace('%s', '', add_feed_url());
1624
b1e592d3 1625 $confirm_str = str_replace("'", "\'", __('Subscribe to %s in Tiny Tiny RSS?'));
afcfe6ca
AD
1626
1627 $bm_url = htmlspecialchars("javascript:{if(confirm('$confirm_str'.replace('%s',window.location.href)))window.location.href='$bm_subscribe_url'+window.location.href}");
1628
1629 print "<a href=\"$bm_url\" class='bookmarklet'>" . __('Subscribe in Tiny Tiny RSS'). "</a>";
1630
1631 print "</div>"; #pane
1632
e95e7819 1633 print "<div dojoType=\"dijit.layout.AccordionPane\" title=\"".__('Published & shared articles / Generated feeds')."\">";
afcfe6ca
AD
1634
1635 print "<h3>" . __("Published articles and generated feeds") . "</h3>";
1636
1637 print "<p>".__('Published articles are exported as a public RSS feed and can be subscribed by anyone who knows the URL specified below.')."</p>";
1638
1639 $rss_url = '-2::' . htmlspecialchars(get_self_url_prefix() .
1640 "/public.php?op=rss&id=-2&view-mode=all_articles");;
1641
1642 print "<button dojoType=\"dijit.form.Button\" onclick=\"return displayDlg('generatedFeed', '$rss_url')\">".
1643 __('Display URL')."</button> ";
1644
1645 print "<button dojoType=\"dijit.form.Button\" onclick=\"return clearFeedAccessKeys()\">".
1646 __('Clear all generated URLs')."</button> ";
1647
1648 print "<h3>" . __("Articles shared by URL") . "</h3>";
1649
1650 print "<p>" . __("You can disable all articles shared by unique URLs here.") . "</p>";
1651
1652 print "<button dojoType=\"dijit.form.Button\" onclick=\"return clearArticleAccessKeys()\">".
1653 __('Unshare all articles')."</button> ";
1654
1655 print "</div>"; #pane
1656
1657 if (defined('CONSUMER_KEY') && CONSUMER_KEY != '') {
1658
1659 print "<div id=\"pref-feeds-twitter\" dojoType=\"dijit.layout.AccordionPane\" title=\"".__('Twitter')."\">";
1660
1661 $result = db_query($this->link, "SELECT COUNT(*) AS cid FROM ttrss_users
1662 WHERE twitter_oauth IS NOT NULL AND twitter_oauth != '' AND
1663 id = " . $_SESSION['uid']);
1664
1665 $is_registered = db_fetch_result($result, 0, "cid") != 0;
1666
1667 if (!$is_registered) {
1668 print_notice(__('Before you can update your Twitter feeds, you must register this instance of Tiny Tiny RSS with Twitter.com.'));
1669 } else {
1670 print_notice(__('You have been successfully registered with Twitter.com and should be able to access your Twitter feeds.'));
1671 }
1672
1673 print "<button dojoType=\"dijit.form.Button\" onclick=\"window.location.href = 'twitter.php?op=register'\">".
1674 __("Register with Twitter.com")."</button>";
1675
1676 print " ";
1677
1678 print "<button dojoType=\"dijit.form.Button\"
1679 onclick=\"return clearTwitterCredentials()\">".
1680 __("Clear stored credentials")."</button>";
1681
1682 print "</div>"; # pane
1683
1684 }
1685
1686 print "</div>"; #container
1687
1688 }
1689}
1690?>