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