]>
git.wh0rd.org - tt-rss.git/blob - classes/api.php
bb4d332471f2ddd86d81fe3b5806b9445f1941c1
2 class API
extends Handler
{
11 function before ( $method ) {
12 if ( parent
:: before ( $method )) {
13 header ( "Content-Type: text/json" );
15 if (! $_SESSION [ "uid" ] && $method != "login" && $method != "isloggedin" ) {
16 $this -> wrap ( self
:: STATUS_ERR
, array ( "error" => 'NOT_LOGGED_IN' ));
20 if ( $_SESSION [ "uid" ] && $method != "logout" && ! get_pref ( 'ENABLE_API_ACCESS' )) {
21 $this -> wrap ( self
:: STATUS_ERR
, array ( "error" => 'API_DISABLED' ));
25 $this -> seq
= ( int ) $_REQUEST [ 'seq' ];
32 function wrap ( $status , $reply ) {
33 print json_encode ( array ( "seq" => $this -> seq
,
35 "content" => $reply ));
38 function getVersion () {
39 $rv = array ( "version" => VERSION
);
40 $this -> wrap ( self
:: STATUS_OK
, $rv );
43 function getApiLevel () {
44 $rv = array ( "level" => self
:: API_LEVEL
);
45 $this -> wrap ( self
:: STATUS_OK
, $rv );
52 $login = $this -> dbh
-> escape_string ( $_REQUEST [ "user" ]);
53 $password = $_REQUEST [ "password" ];
54 $password_base64 = base64_decode ( $_REQUEST [ "password" ]);
56 if ( SINGLE_USER_MODE
) $login = "admin" ;
58 $result = $this -> dbh
-> query ( "SELECT id FROM ttrss_users WHERE login = ' $login '" );
60 if ( $this -> dbh
-> num_rows ( $result ) != 0 ) {
61 $uid = $this -> dbh
-> fetch_result ( $result , 0 , "id" );
67 $this -> wrap ( self
:: STATUS_ERR
, array ( "error" => "LOGIN_ERROR" ));
71 if ( get_pref ( "ENABLE_API_ACCESS" , $uid )) {
72 if ( authenticate_user ( $login , $password )) { // try login with normal password
73 $this -> wrap ( self
:: STATUS_OK
, array ( "session_id" => session_id (),
74 "api_level" => self
:: API_LEVEL
));
75 } else if ( authenticate_user ( $login , $password_base64 )) { // else try with base64_decoded password
76 $this -> wrap ( self
:: STATUS_OK
, array ( "session_id" => session_id (),
77 "api_level" => self
:: API_LEVEL
));
78 } else { // else we are not logged in
79 user_error ( "Failed login attempt for $login from { $_SERVER ['REMOTE_ADDR']}" , E_USER_WARNING
);
80 $this -> wrap ( self
:: STATUS_ERR
, array ( "error" => "LOGIN_ERROR" ));
83 $this -> wrap ( self
:: STATUS_ERR
, array ( "error" => "API_DISABLED" ));
90 $this -> wrap ( self
:: STATUS_OK
, array ( "status" => "OK" ));
93 function isLoggedIn () {
94 $this -> wrap ( self
:: STATUS_OK
, array ( "status" => $_SESSION [ "uid" ] != '' ));
97 function getUnread () {
98 $feed_id = $this -> dbh
-> escape_string ( $_REQUEST [ "feed_id" ]);
99 $is_cat = $this -> dbh
-> escape_string ( $_REQUEST [ "is_cat" ]);
102 $this -> wrap ( self
:: STATUS_OK
, array ( "unread" => getFeedUnread ( $feed_id , $is_cat )));
104 $this -> wrap ( self
:: STATUS_OK
, array ( "unread" => Feeds
:: getGlobalUnread ()));
108 /* Method added for ttrss-reader for Android */
109 function getCounters () {
110 $this -> wrap ( self
:: STATUS_OK
, Counters
:: getAllCounters ());
113 function getFeeds () {
114 $cat_id = $this -> dbh
-> escape_string ( $_REQUEST [ "cat_id" ]);
115 $unread_only = sql_bool_to_bool ( $_REQUEST [ "unread_only" ]);
116 $limit = ( int ) $this -> dbh
-> escape_string ( $_REQUEST [ "limit" ]);
117 $offset = ( int ) $this -> dbh
-> escape_string ( $_REQUEST [ "offset" ]);
118 $include_nested = sql_bool_to_bool ( $_REQUEST [ "include_nested" ]);
120 $feeds = $this -> api_get_feeds ( $cat_id , $unread_only , $limit , $offset , $include_nested );
122 $this -> wrap ( self
:: STATUS_OK
, $feeds );
125 function getCategories () {
126 $unread_only = sql_bool_to_bool ( $_REQUEST [ "unread_only" ]);
127 $enable_nested = sql_bool_to_bool ( $_REQUEST [ "enable_nested" ]);
128 $include_empty = sql_bool_to_bool ( $_REQUEST [ 'include_empty' ]);
130 // TODO do not return empty categories, return Uncategorized and standard virtual cats
133 $nested_qpart = "parent_cat IS NULL" ;
135 $nested_qpart = "true" ;
137 $result = $this -> dbh
-> query ( "SELECT
138 id, title, order_id, (SELECT COUNT(id) FROM
140 ttrss_feed_categories.id IS NOT NULL AND cat_id = ttrss_feed_categories.id) AS num_feeds,
141 (SELECT COUNT(id) FROM
142 ttrss_feed_categories AS c2 WHERE
143 c2.parent_cat = ttrss_feed_categories.id) AS num_cats
144 FROM ttrss_feed_categories
145 WHERE $nested_qpart AND owner_uid = " .
150 while ( $line = $this -> dbh
-> fetch_assoc ( $result )) {
151 if ( $include_empty ||
$line [ "num_feeds" ] > 0 ||
$line [ "num_cats" ] > 0 ) {
152 $unread = getFeedUnread ( $line [ "id" ], true );
155 $unread +
= Feeds
:: getCategoryChildrenUnread ( $line [ "id" ]);
157 if ( $unread ||
! $unread_only ) {
158 array_push ( $cats , array ( "id" => $line [ "id" ],
159 "title" => $line [ "title" ],
161 "order_id" => ( int ) $line [ "order_id" ],
167 foreach ( array (- 2 ,- 1 , 0 ) as $cat_id ) {
168 if ( $include_empty ||
! $this -> isCategoryEmpty ( $cat_id )) {
169 $unread = getFeedUnread ( $cat_id , true );
171 if ( $unread ||
! $unread_only ) {
172 array_push ( $cats , array ( "id" => $cat_id ,
173 "title" => Feeds
:: getCategoryTitle ( $cat_id ),
174 "unread" => $unread ));
179 $this -> wrap ( self
:: STATUS_OK
, $cats );
182 function getHeadlines () {
183 $feed_id = $this -> dbh
-> escape_string ( $_REQUEST [ "feed_id" ]);
184 if ( $feed_id != "" ) {
186 if ( is_numeric ( $feed_id )) $feed_id = ( int ) $feed_id ;
188 $limit = ( int ) $this -> dbh
-> escape_string ( $_REQUEST [ "limit" ]);
190 if (! $limit ||
$limit >= 200 ) $limit = 200 ;
192 $offset = ( int ) $this -> dbh
-> escape_string ( $_REQUEST [ "skip" ]);
193 $filter = $this -> dbh
-> escape_string ( $_REQUEST [ "filter" ]);
194 $is_cat = sql_bool_to_bool ( $_REQUEST [ "is_cat" ]);
195 $show_excerpt = sql_bool_to_bool ( $_REQUEST [ "show_excerpt" ]);
196 $show_content = sql_bool_to_bool ( $_REQUEST [ "show_content" ]);
197 /* all_articles, unread, adaptive, marked, updated */
198 $view_mode = $this -> dbh
-> escape_string ( $_REQUEST [ "view_mode" ]);
199 $include_attachments = sql_bool_to_bool ( $_REQUEST [ "include_attachments" ]);
200 $since_id = ( int ) $this -> dbh
-> escape_string ( $_REQUEST [ "since_id" ]);
201 $include_nested = sql_bool_to_bool ( $_REQUEST [ "include_nested" ]);
202 $sanitize_content = ! isset ( $_REQUEST [ "sanitize" ]) ||
203 sql_bool_to_bool ( $_REQUEST [ "sanitize" ]);
204 $force_update = sql_bool_to_bool ( $_REQUEST [ "force_update" ]);
205 $has_sandbox = sql_bool_to_bool ( $_REQUEST [ "has_sandbox" ]);
206 $excerpt_length = ( int ) $this -> dbh
-> escape_string ( $_REQUEST [ "excerpt_length" ]);
207 $check_first_id = ( int ) $this -> dbh
-> escape_string ( $_REQUEST [ "check_first_id" ]);
208 $include_header = sql_bool_to_bool ( $_REQUEST [ "include_header" ]);
210 $_SESSION [ 'hasSandbox' ] = $has_sandbox ;
212 $skip_first_id_check = false ;
214 $override_order = false ;
215 switch ( $_REQUEST [ "order_by" ]) {
217 $override_order = "ttrss_entries.title, date_entered, updated" ;
220 $override_order = "score DESC, date_entered, updated" ;
221 $skip_first_id_check = true ;
224 $override_order = "updated DESC" ;
228 /* do not rely on params below */
230 $search = $this -> dbh
-> escape_string ( $_REQUEST [ "search" ]);
232 list ( $headlines , $headlines_header ) = $this -> api_get_headlines ( $feed_id , $limit , $offset ,
233 $filter , $is_cat , $show_excerpt , $show_content , $view_mode , $override_order ,
234 $include_attachments , $since_id , $search ,
235 $include_nested , $sanitize_content , $force_update , $excerpt_length , $check_first_id , $skip_first_id_check );
237 if ( $include_header ) {
238 $this -> wrap ( self
:: STATUS_OK
, array ( $headlines_header , $headlines ));
240 $this -> wrap ( self
:: STATUS_OK
, $headlines );
243 $this -> wrap ( self
:: STATUS_ERR
, array ( "error" => 'INCORRECT_USAGE' ));
247 function updateArticle () {
248 $article_ids = array_filter ( explode ( "," , $this -> dbh
-> escape_string ( $_REQUEST [ "article_ids" ])), is_numeric
);
249 $mode = ( int ) $this -> dbh
-> escape_string ( $_REQUEST [ "mode" ]);
250 $data = $this -> dbh
-> escape_string ( $_REQUEST [ "data" ]);
251 $field_raw = ( int ) $this -> dbh
-> escape_string ( $_REQUEST [ "field" ]);
256 switch ( $field_raw ) {
259 $additional_fields = ",last_marked = NOW()" ;
262 $field = "published" ;
263 $additional_fields = ",last_published = NOW()" ;
267 $additional_fields = ",last_read = NOW()" ;
281 $set_to = "NOT $field " ;
285 if ( $field == "note" ) $set_to = "' $data '" ;
287 if ( $field && $set_to && count ( $article_ids ) > 0 ) {
289 $article_ids = join ( ", " , $article_ids );
291 $result = $this -> dbh
-> query ( "UPDATE ttrss_user_entries SET $field = $set_to $additional_fields WHERE ref_id IN ( $article_ids ) AND owner_uid = " . $_SESSION [ "uid" ]);
293 $num_updated = $this -> dbh
-> affected_rows ( $result );
295 if ( $num_updated > 0 && $field == "unread" ) {
296 $result = $this -> dbh
-> query ( "SELECT DISTINCT feed_id FROM ttrss_user_entries
297 WHERE ref_id IN ( $article_ids )" );
299 while ( $line = $this -> dbh
-> fetch_assoc ( $result )) {
300 CCache
:: update ( $line [ "feed_id" ], $_SESSION [ "uid" ]);
304 $this -> wrap ( self
:: STATUS_OK
, array ( "status" => "OK" ,
305 "updated" => $num_updated ));
308 $this -> wrap ( self
:: STATUS_ERR
, array ( "error" => 'INCORRECT_USAGE' ));
313 function getArticle () {
315 $article_id = join ( "," , array_filter ( explode ( "," , $this -> dbh
-> escape_string ( $_REQUEST [ "article_id" ])), is_numeric
));
316 $sanitize_content = ! isset ( $_REQUEST [ "sanitize" ]) ||
317 sql_bool_to_bool ( $_REQUEST [ "sanitize" ]);
321 $query = "SELECT id,guid,title,link,content,feed_id,comments,int_id,
322 marked,unread,published,score,note,lang,
323 " . SUBSTRING_FOR_DATE
. "(updated,1,16) as updated,
324 author,(SELECT title FROM ttrss_feeds WHERE id = feed_id) AS feed_title,
325 (SELECT site_url FROM ttrss_feeds WHERE id = feed_id) AS site_url,
326 (SELECT hide_images FROM ttrss_feeds WHERE id = feed_id) AS hide_images
327 FROM ttrss_entries,ttrss_user_entries
328 WHERE id IN ( $article_id ) AND ref_id = id AND owner_uid = " .
331 $result = $this -> dbh
-> query ( $query );
335 if ( $this -> dbh
-> num_rows ( $result ) != 0 ) {
337 while ( $line = $this -> dbh
-> fetch_assoc ( $result )) {
339 $attachments = Article
:: get_article_enclosures ( $line [ 'id' ]);
343 "guid" => $line [ "guid" ],
344 "title" => $line [ "title" ],
345 "link" => $line [ "link" ],
346 "labels" => Article
:: get_article_labels ( $line [ 'id' ]),
347 "unread" => sql_bool_to_bool ( $line [ "unread" ]),
348 "marked" => sql_bool_to_bool ( $line [ "marked" ]),
349 "published" => sql_bool_to_bool ( $line [ "published" ]),
350 "comments" => $line [ "comments" ],
351 "author" => $line [ "author" ],
352 "updated" => ( int ) strtotime ( $line [ "updated" ]),
353 "feed_id" => $line [ "feed_id" ],
354 "attachments" => $attachments ,
355 "score" => ( int ) $line [ "score" ],
356 "feed_title" => $line [ "feed_title" ],
357 "note" => $line [ "note" ],
358 "lang" => $line [ "lang" ]
361 if ( $sanitize_content ) {
362 $article [ "content" ] = sanitize (
364 sql_bool_to_bool ( $line [ 'hide_images' ]),
365 false , $line [ "site_url" ], false , $line [ "id" ]);
367 $article [ "content" ] = $line [ "content" ];
370 foreach ( PluginHost
:: getInstance ()-> get_hooks ( PluginHost
:: HOOK_RENDER_ARTICLE_API
) as $p ) {
371 $article = $p -> hook_render_article_api ( array ( "article" => $article ));
375 array_push ( $articles , $article );
380 $this -> wrap ( self
:: STATUS_OK
, $articles );
382 $this -> wrap ( self
:: STATUS_ERR
, array ( "error" => 'INCORRECT_USAGE' ));
386 function getConfig () {
388 "icons_dir" => ICONS_DIR
,
389 "icons_url" => ICONS_URL
);
391 $config [ "daemon_is_running" ] = file_is_locked ( "update_daemon.lock" );
393 $result = $this -> dbh
-> query ( "SELECT COUNT(*) AS cf FROM
394 ttrss_feeds WHERE owner_uid = " . $_SESSION [ "uid" ]);
396 $num_feeds = $this -> dbh
-> fetch_result ( $result , 0 , "cf" );
398 $config [ "num_feeds" ] = ( int ) $num_feeds ;
400 $this -> wrap ( self
:: STATUS_OK
, $config );
403 function updateFeed () {
404 $feed_id = ( int ) $this -> dbh
-> escape_string ( $_REQUEST [ "feed_id" ]);
406 if (! ini_get ( "open_basedir" )) {
407 RSSUtils
:: update_rss_feed ( $feed_id );
410 $this -> wrap ( self
:: STATUS_OK
, array ( "status" => "OK" ));
413 function catchupFeed () {
414 $feed_id = $this -> dbh
-> escape_string ( $_REQUEST [ "feed_id" ]);
415 $is_cat = $this -> dbh
-> escape_string ( $_REQUEST [ "is_cat" ]);
417 Feeds
:: catchup_feed ( $feed_id , $is_cat );
419 $this -> wrap ( self
:: STATUS_OK
, array ( "status" => "OK" ));
423 $pref_name = $this -> dbh
-> escape_string ( $_REQUEST [ "pref_name" ]);
425 $this -> wrap ( self
:: STATUS_OK
, array ( "value" => get_pref ( $pref_name )));
428 function getLabels () {
429 //$article_ids = array_filter(explode(",", $this->dbh->escape_string($_REQUEST["article_ids"])), is_numeric);
431 $article_id = ( int ) $_REQUEST [ 'article_id' ];
435 $result = $this -> dbh
-> query ( "SELECT id, caption, fg_color, bg_color
437 WHERE owner_uid = '" . $_SESSION [ 'uid' ]. "' ORDER BY caption" );
440 $article_labels = Article
:: get_article_labels ( $article_id );
442 $article_labels = array ();
444 while ( $line = $this -> dbh
-> fetch_assoc ( $result )) {
447 foreach ( $article_labels as $al ) {
448 if ( Labels
:: feed_to_label_id ( $al [ 0 ]) == $line [ 'id' ]) {
454 array_push ( $rv , array (
455 "id" => ( int ) Labels
:: label_to_feed_id ( $line [ 'id' ]),
456 "caption" => $line [ 'caption' ],
457 "fg_color" => $line [ 'fg_color' ],
458 "bg_color" => $line [ 'bg_color' ],
459 "checked" => $checked ));
462 $this -> wrap ( self
:: STATUS_OK
, $rv );
465 function setArticleLabel () {
467 $article_ids = array_filter ( explode ( "," , $this -> dbh
-> escape_string ( $_REQUEST [ "article_ids" ])), is_numeric
);
468 $label_id = ( int ) $this -> dbh
-> escape_string ( $_REQUEST [ 'label_id' ]);
469 $assign = sql_bool_to_bool ( $_REQUEST [ 'assign' ]);
471 $label = $this -> dbh
-> escape_string ( Labels
:: find_caption (
472 Labels
:: feed_to_label_id ( $label_id ), $_SESSION [ "uid" ]));
478 foreach ( $article_ids as $id ) {
481 Labels
:: add_article ( $id , $label , $_SESSION [ "uid" ]);
483 Labels
:: remove_article ( $id , $label , $_SESSION [ "uid" ]);
490 $this -> wrap ( self
:: STATUS_OK
, array ( "status" => "OK" ,
491 "updated" => $num_updated ));
495 function index ( $method ) {
496 $plugin = PluginHost
:: getInstance ()-> get_api_method ( strtolower ( $method ));
498 if ( $plugin && method_exists ( $plugin , $method )) {
499 $reply = $plugin -> $method ();
501 $this -> wrap ( $reply [ 0 ], $reply [ 1 ]);
504 $this -> wrap ( self
:: STATUS_ERR
, array ( "error" => 'UNKNOWN_METHOD' , "method" => $method ));
508 function shareToPublished () {
509 $title = $this -> dbh
-> escape_string ( strip_tags ( $_REQUEST [ "title" ]));
510 $url = $this -> dbh
-> escape_string ( strip_tags ( $_REQUEST [ "url" ]));
511 $content = $this -> dbh
-> escape_string ( strip_tags ( $_REQUEST [ "content" ]));
513 if ( Article
:: create_published_article ( $title , $url , $content , "" , $_SESSION [ "uid" ])) {
514 $this -> wrap ( self
:: STATUS_OK
, array ( "status" => 'OK' ));
516 $this -> wrap ( self
:: STATUS_ERR
, array ( "error" => 'Publishing failed' ));
520 static function api_get_feeds ( $cat_id , $unread_only , $limit , $offset , $include_nested = false ) {
526 if ( $cat_id == - 4 ||
$cat_id == - 2 ) {
527 $counters = Counters
:: getLabelCounters ( true );
529 foreach ( array_values ( $counters ) as $cv ) {
531 $unread = $cv [ "counter" ];
533 if ( $unread ||
! $unread_only ) {
536 "id" => ( int ) $cv [ "id" ],
537 "title" => $cv [ "description" ],
538 "unread" => $cv [ "counter" ],
542 array_push ( $feeds , $row );
549 if ( $cat_id == - 4 ||
$cat_id == - 1 ) {
550 foreach ( array (- 1 , - 2 , - 3 , - 4 , - 6 , 0 ) as $i ) {
551 $unread = getFeedUnread ( $i );
553 if ( $unread ||
! $unread_only ) {
554 $title = Feeds
:: getFeedTitle ( $i );
562 array_push ( $feeds , $row );
570 if ( $include_nested && $cat_id ) {
571 $result = db_query ( "SELECT
572 id, title, order_id FROM ttrss_feed_categories
573 WHERE parent_cat = ' $cat_id ' AND owner_uid = " . $_SESSION [ "uid" ] .
574 " ORDER BY id, title" );
576 while ( $line = db_fetch_assoc ( $result )) {
577 $unread = getFeedUnread ( $line [ "id" ], true ) +
578 Feeds
:: getCategoryChildrenUnread ( $line [ "id" ]);
580 if ( $unread ||
! $unread_only ) {
582 "id" => ( int ) $line [ "id" ],
583 "title" => $line [ "title" ],
586 "order_id" => ( int ) $line [ "order_id" ]
588 array_push ( $feeds , $row );
596 $limit_qpart = "LIMIT $limit OFFSET $offset " ;
601 if ( $cat_id == - 4 ||
$cat_id == - 3 ) {
602 $result = db_query ( "SELECT
603 id, feed_url, cat_id, title, order_id, " .
604 SUBSTRING_FOR_DATE
. "(last_updated,1,19) AS last_updated
605 FROM ttrss_feeds WHERE owner_uid = " . $_SESSION [ "uid" ] .
606 " ORDER BY cat_id, title " . $limit_qpart );
610 $cat_qpart = "cat_id = ' $cat_id '" ;
612 $cat_qpart = "cat_id IS NULL" ;
614 $result = db_query ( "SELECT
615 id, feed_url, cat_id, title, order_id, " .
616 SUBSTRING_FOR_DATE
. "(last_updated,1,19) AS last_updated
617 FROM ttrss_feeds WHERE
618 $cat_qpart AND owner_uid = " . $_SESSION [ "uid" ] .
619 " ORDER BY cat_id, title " . $limit_qpart );
622 while ( $line = db_fetch_assoc ( $result )) {
624 $unread = getFeedUnread ( $line [ "id" ]);
626 $has_icon = feed_has_icon ( $line [ 'id' ]);
628 if ( $unread ||
! $unread_only ) {
631 "feed_url" => $line [ "feed_url" ],
632 "title" => $line [ "title" ],
633 "id" => ( int ) $line [ "id" ],
634 "unread" => ( int ) $unread ,
635 "has_icon" => $has_icon ,
636 "cat_id" => ( int ) $line [ "cat_id" ],
637 "last_updated" => ( int ) strtotime ( $line [ "last_updated" ]),
638 "order_id" => ( int ) $line [ "order_id" ],
641 array_push ( $feeds , $row );
649 * @SuppressWarnings(PHPMD.UnusedFormalParameter)
651 static function api_get_headlines ( $feed_id , $limit , $offset ,
652 $filter , $is_cat , $show_excerpt , $show_content , $view_mode , $order ,
653 $include_attachments , $since_id ,
654 $search = "" , $include_nested = false , $sanitize_content = true ,
655 $force_update = false , $excerpt_length = 100 , $check_first_id = false , $skip_first_id_check = false ) {
657 if ( $force_update && $feed_id > 0 && is_numeric ( $feed_id )) {
658 // Update the feed if required with some basic flood control
661 "SELECT cache_images," . SUBSTRING_FOR_DATE
. "(last_updated,1,19) AS last_updated
662 FROM ttrss_feeds WHERE id = ' $feed_id '" );
664 if ( db_num_rows ( $result ) != 0 ) {
665 $last_updated = strtotime ( db_fetch_result ( $result , 0 , "last_updated" ));
666 $cache_images = sql_bool_to_bool ( db_fetch_result ( $result , 0 , "cache_images" ));
668 if (! $cache_images && time () - $last_updated > 120 ) {
669 RSSUtils
:: update_rss_feed ( $feed_id , true );
671 db_query ( "UPDATE ttrss_feeds SET last_updated = '1970-01-01', last_update_started = '1970-01-01'
672 WHERE id = ' $feed_id '" );
680 "view_mode" => $view_mode ,
681 "cat_view" => $is_cat ,
683 "override_order" => $order ,
685 "since_id" => $since_id ,
686 "include_children" => $include_nested ,
687 "check_first_id" => $check_first_id ,
688 "skip_first_id_check" => $skip_first_id_check
691 $qfh_ret = Feeds
:: queryFeedHeadlines ( $params );
693 $result = $qfh_ret [ 0 ];
694 $feed_title = $qfh_ret [ 1 ];
695 $first_id = $qfh_ret [ 6 ];
697 $headlines = array ();
699 $headlines_header = array (
701 'first_id' => $first_id ,
702 'is_cat' => $is_cat );
704 if (! is_numeric ( $result )) {
705 while ( $line = db_fetch_assoc ( $result )) {
706 $line [ "content_preview" ] = truncate_string ( strip_tags ( $line [ "content" ]), $excerpt_length );
707 foreach ( PluginHost
:: getInstance ()-> get_hooks ( PluginHost
:: HOOK_QUERY_HEADLINES
) as $p ) {
708 $line = $p -> hook_query_headlines ( $line , $excerpt_length , true );
711 $is_updated = ( $line [ "last_read" ] == "" &&
712 ( $line [ "unread" ] != "t" && $line [ "unread" ] != "1" ));
714 $tags = explode ( "," , $line [ "tag_cache" ]);
716 $label_cache = $line [ "label_cache" ];
720 $label_cache = json_decode ( $label_cache , true );
723 if ( $label_cache [ "no-labels" ] == 1 )
726 $labels = $label_cache ;
730 if (! is_array ( $labels )) $labels = Article
:: get_article_labels ( $line [ "id" ]);
732 $headline_row = array (
733 "id" => ( int ) $line [ "id" ],
734 "guid" => $line [ "guid" ],
735 "unread" => sql_bool_to_bool ( $line [ "unread" ]),
736 "marked" => sql_bool_to_bool ( $line [ "marked" ]),
737 "published" => sql_bool_to_bool ( $line [ "published" ]),
738 "updated" => ( int ) strtotime ( $line [ "updated" ]),
739 "is_updated" => $is_updated ,
740 "title" => $line [ "title" ],
741 "link" => $line [ "link" ],
742 "feed_id" => $line [ "feed_id" ],
746 if ( $include_attachments )
747 $headline_row [ 'attachments' ] = Article
:: get_article_enclosures (
751 $headline_row [ "excerpt" ] = $line [ "content_preview" ];
755 if ( $sanitize_content ) {
756 $headline_row [ "content" ] = sanitize (
758 sql_bool_to_bool ( $line [ 'hide_images' ]),
759 false , $line [ "site_url" ], false , $line [ "id" ]);
761 $headline_row [ "content" ] = $line [ "content" ];
765 // unify label output to ease parsing
766 if ( $labels [ "no-labels" ] == 1 ) $labels = array ();
768 $headline_row [ "labels" ] = $labels ;
770 $headline_row [ "feed_title" ] = $line [ "feed_title" ] ?
$line [ "feed_title" ] :
773 $headline_row [ "comments_count" ] = ( int ) $line [ "num_comments" ];
774 $headline_row [ "comments_link" ] = $line [ "comments" ];
776 $headline_row [ "always_display_attachments" ] = sql_bool_to_bool ( $line [ "always_display_enclosures" ]);
778 $headline_row [ "author" ] = $line [ "author" ];
780 $headline_row [ "score" ] = ( int ) $line [ "score" ];
781 $headline_row [ "note" ] = $line [ "note" ];
782 $headline_row [ "lang" ] = $line [ "lang" ];
784 foreach ( PluginHost
:: getInstance ()-> get_hooks ( PluginHost
:: HOOK_RENDER_ARTICLE_API
) as $p ) {
785 $headline_row = $p -> hook_render_article_api ( array ( "headline" => $headline_row ));
788 array_push ( $headlines , $headline_row );
790 } else if ( is_numeric ( $result ) && $result == - 1 ) {
791 $headlines_header [ 'first_id_changed' ] = true ;
794 return array ( $headlines , $headlines_header );
797 function unsubscribeFeed () {
798 $feed_id = ( int ) $this -> dbh
-> escape_string ( $_REQUEST [ "feed_id" ]);
800 $result = $this -> dbh
-> query ( "SELECT id FROM ttrss_feeds WHERE
801 id = ' $feed_id ' AND owner_uid = " . $_SESSION [ "uid" ]);
803 if ( $this -> dbh
-> num_rows ( $result ) != 0 ) {
804 Pref_Feeds
:: remove_feed ( $feed_id , $_SESSION [ "uid" ]);
805 $this -> wrap ( self
:: STATUS_OK
, array ( "status" => "OK" ));
807 $this -> wrap ( self
:: STATUS_ERR
, array ( "error" => "FEED_NOT_FOUND" ));
811 function subscribeToFeed () {
812 $feed_url = $this -> dbh
-> escape_string ( $_REQUEST [ "feed_url" ]);
813 $category_id = ( int ) $this -> dbh
-> escape_string ( $_REQUEST [ "category_id" ]);
814 $login = $this -> dbh
-> escape_string ( $_REQUEST [ "login" ]);
815 $password = $this -> dbh
-> escape_string ( $_REQUEST [ "password" ]);
818 $rc = Feeds
:: subscribe_to_feed ( $feed_url , $category_id , $login , $password );
820 $this -> wrap ( self
:: STATUS_OK
, array ( "status" => $rc ));
822 $this -> wrap ( self
:: STATUS_ERR
, array ( "error" => 'INCORRECT_USAGE' ));
826 function getFeedTree () {
827 $include_empty = sql_bool_to_bool ( $_REQUEST [ 'include_empty' ]);
829 $pf = new Pref_Feeds ( $_REQUEST );
831 $_REQUEST [ 'mode' ] = 2 ;
832 $_REQUEST [ 'force_show_empty' ] = $include_empty ;
835 $data = $pf -> makefeedtree ();
836 $this -> wrap ( self
:: STATUS_OK
, array ( "categories" => $data ));
838 $this -> wrap ( self
:: STATUS_ERR
, array ( "error" =>
839 'UNABLE_TO_INSTANTIATE_OBJECT' ));
844 // only works for labels or uncategorized for the time being
845 private function isCategoryEmpty ( $id ) {
848 $result = $this -> dbh
-> query ( "SELECT COUNT(*) AS count FROM ttrss_labels2
849 WHERE owner_uid = " . $_SESSION [ "uid" ]);
851 return $this -> dbh
-> fetch_result ( $result , 0 , "count" ) == 0 ;
853 } else if ( $id == 0 ) {
854 $result = $this -> dbh
-> query ( "SELECT COUNT(*) AS count FROM ttrss_feeds
855 WHERE cat_id IS NULL AND owner_uid = " . $_SESSION [ "uid" ]);
857 return $this -> dbh
-> fetch_result ( $result , 0 , "count" ) == 0 ;