diff options
author | Nicolas Lœuillet <nicolas@loeuillet.org> | 2014-02-21 15:57:10 +0100 |
---|---|---|
committer | Nicolas Lœuillet <nicolas@loeuillet.org> | 2014-02-21 15:57:10 +0100 |
commit | 99679d06884120c57f43b44e55e03595f1f87bed (patch) | |
tree | a3f2a1aa1afdaeca1386d0c6e8a75344fd2241fb /inc/poche | |
parent | 655214ab30ee84884dc408488b85586f36263fcb (diff) | |
parent | d3b47e94705e17b3ba3529cbb1dc6efe69c5d2b7 (diff) | |
download | wallabag-99679d06884120c57f43b44e55e03595f1f87bed.tar.gz wallabag-99679d06884120c57f43b44e55e03595f1f87bed.tar.zst wallabag-99679d06884120c57f43b44e55e03595f1f87bed.zip |
Merge pull request #481 from wallabag/dev1.5.2
1.5.2
Diffstat (limited to 'inc/poche')
-rwxr-xr-x[-rw-r--r--] | inc/poche/Database.class.php | 83 | ||||
-rwxr-xr-x[-rw-r--r--] | inc/poche/Poche.class.php | 142 | ||||
-rw-r--r-- | inc/poche/Tools.class.php | 2 | ||||
-rw-r--r-- | inc/poche/global.inc.php | 2 |
4 files changed, 166 insertions, 63 deletions
diff --git a/inc/poche/Database.class.php b/inc/poche/Database.class.php index 3332b5a3..c998fe14 100644..100755 --- a/inc/poche/Database.class.php +++ b/inc/poche/Database.class.php | |||
@@ -10,8 +10,15 @@ | |||
10 | 10 | ||
11 | class Database { | 11 | class Database { |
12 | var $handle; | 12 | var $handle; |
13 | 13 | private $order = array( | |
14 | function __construct() | 14 | 'ia' => 'ORDER BY entries.id', |
15 | 'id' => 'ORDER BY entries.id DESC', | ||
16 | 'ta' => 'ORDER BY lower(entries.title)', | ||
17 | 'td' => 'ORDER BY lower(entries.title) DESC', | ||
18 | 'default' => 'ORDER BY entries.id' | ||
19 | ); | ||
20 | |||
21 | function __construct() | ||
15 | { | 22 | { |
16 | switch (STORAGE) { | 23 | switch (STORAGE) { |
17 | case 'sqlite': | 24 | case 'sqlite': |
@@ -257,48 +264,62 @@ class Database { | |||
257 | $query = $this->executeQuery($sql, $params); | 264 | $query = $this->executeQuery($sql, $params); |
258 | } | 265 | } |
259 | 266 | ||
260 | public function getEntriesByView($view, $user_id, $limit = '') { | 267 | public function getEntriesByView($view, $user_id, $limit = '', $tag_id = 0) { |
261 | switch ($_SESSION['sort']) | 268 | switch ($view) { |
262 | { | 269 | case 'archive': |
263 | case 'ia': | 270 | $sql = "SELECT * FROM entries WHERE user_id=? AND is_read=? "; |
264 | $order = 'ORDER BY id'; | 271 | $params = array($user_id, 1); |
265 | break; | ||
266 | case 'id': | ||
267 | $order = 'ORDER BY id DESC'; | ||
268 | break; | 272 | break; |
269 | case 'ta': | 273 | case 'fav' : |
270 | $order = 'ORDER BY lower(title)'; | 274 | $sql = "SELECT * FROM entries WHERE user_id=? AND is_fav=? "; |
275 | $params = array($user_id, 1); | ||
271 | break; | 276 | break; |
272 | case 'td': | 277 | case 'tag' : |
273 | $order = 'ORDER BY lower(title) DESC'; | 278 | $sql = "SELECT entries.* FROM entries |
279 | LEFT JOIN tags_entries ON tags_entries.entry_id=entries.id | ||
280 | WHERE entries.user_id=? AND tags_entries.tag_id = ? "; | ||
281 | $params = array($user_id, $tag_id); | ||
274 | break; | 282 | break; |
275 | default: | 283 | default: |
276 | $order = 'ORDER BY id'; | 284 | $sql = "SELECT * FROM entries WHERE user_id=? AND is_read=? "; |
285 | $params = array($user_id, 0); | ||
277 | break; | 286 | break; |
278 | } | 287 | } |
279 | 288 | ||
280 | switch ($view) | 289 | $sql .= $this->getEntriesOrder().' ' . $limit; |
281 | { | 290 | |
291 | $query = $this->executeQuery($sql, $params); | ||
292 | $entries = $query->fetchAll(); | ||
293 | |||
294 | return $entries; | ||
295 | } | ||
296 | |||
297 | public function getEntriesByViewCount($view, $user_id, $tag_id = 0) { | ||
298 | switch ($view) { | ||
282 | case 'archive': | 299 | case 'archive': |
283 | $sql = "SELECT * FROM entries WHERE user_id=? AND is_read=? " . $order; | 300 | $sql = "SELECT count(*) FROM entries WHERE user_id=? AND is_read=? "; |
284 | $params = array($user_id, 1); | 301 | $params = array($user_id, 1); |
285 | break; | 302 | break; |
286 | case 'fav' : | 303 | case 'fav' : |
287 | $sql = "SELECT * FROM entries WHERE user_id=? AND is_fav=? " . $order; | 304 | $sql = "SELECT count(*) FROM entries WHERE user_id=? AND is_fav=? "; |
288 | $params = array($user_id, 1); | 305 | $params = array($user_id, 1); |
289 | break; | 306 | break; |
307 | case 'tag' : | ||
308 | $sql = "SELECT count(*) FROM entries | ||
309 | LEFT JOIN tags_entries ON tags_entries.entry_id=entries.id | ||
310 | WHERE entries.user_id=? AND tags_entries.tag_id = ? "; | ||
311 | $params = array($user_id, $tag_id); | ||
312 | break; | ||
290 | default: | 313 | default: |
291 | $sql = "SELECT * FROM entries WHERE user_id=? AND is_read=? " . $order; | 314 | $sql = "SELECT count(*) FROM entries WHERE user_id=? AND is_read=? "; |
292 | $params = array($user_id, 0); | 315 | $params = array($user_id, 0); |
293 | break; | 316 | break; |
294 | } | 317 | } |
295 | 318 | ||
296 | $sql .= ' ' . $limit; | ||
297 | |||
298 | $query = $this->executeQuery($sql, $params); | 319 | $query = $this->executeQuery($sql, $params); |
299 | $entries = $query->fetchAll(); | 320 | list($count) = $query->fetch(); |
300 | 321 | ||
301 | return $entries; | 322 | return $count; |
302 | } | 323 | } |
303 | 324 | ||
304 | public function updateContent($id, $content, $user_id) { | 325 | public function updateContent($id, $content, $user_id) { |
@@ -345,7 +366,7 @@ class Database { | |||
345 | } | 366 | } |
346 | 367 | ||
347 | public function retrieveAllTags($user_id) { | 368 | public function retrieveAllTags($user_id) { |
348 | $sql = "SELECT tags.* FROM tags | 369 | $sql = "SELECT DISTINCT tags.* FROM tags |
349 | LEFT JOIN tags_entries ON tags_entries.tag_id=tags.id | 370 | LEFT JOIN tags_entries ON tags_entries.tag_id=tags.id |
350 | LEFT JOIN entries ON tags_entries.entry_id=entries.id | 371 | LEFT JOIN entries ON tags_entries.entry_id=entries.id |
351 | WHERE entries.user_id=?"; | 372 | WHERE entries.user_id=?"; |
@@ -357,7 +378,7 @@ class Database { | |||
357 | 378 | ||
358 | public function retrieveTag($id, $user_id) { | 379 | public function retrieveTag($id, $user_id) { |
359 | $tag = NULL; | 380 | $tag = NULL; |
360 | $sql = "SELECT tags.* FROM tags | 381 | $sql = "SELECT DISTINCT tags.* FROM tags |
361 | LEFT JOIN tags_entries ON tags_entries.tag_id=tags.id | 382 | LEFT JOIN tags_entries ON tags_entries.tag_id=tags.id |
362 | LEFT JOIN entries ON tags_entries.entry_id=entries.id | 383 | LEFT JOIN entries ON tags_entries.entry_id=entries.id |
363 | WHERE tags.id=? AND entries.user_id=?"; | 384 | WHERE tags.id=? AND entries.user_id=?"; |
@@ -420,4 +441,14 @@ class Database { | |||
420 | $query = $this->executeQuery($sql_action, $params_action); | 441 | $query = $this->executeQuery($sql_action, $params_action); |
421 | return $query; | 442 | return $query; |
422 | } | 443 | } |
444 | |||
445 | private function getEntriesOrder() { | ||
446 | if (isset($_SESSION['sort']) and array_key_exists($_SESSION['sort'], $this->order)) { | ||
447 | return $this->order[$_SESSION['sort']]; | ||
448 | } | ||
449 | else { | ||
450 | return $this->order['default']; | ||
451 | } | ||
452 | } | ||
453 | |||
423 | } | 454 | } |
diff --git a/inc/poche/Poche.class.php b/inc/poche/Poche.class.php index 753bd7f0..34f2ff5a 100644..100755 --- a/inc/poche/Poche.class.php +++ b/inc/poche/Poche.class.php | |||
@@ -23,6 +23,19 @@ class Poche | |||
23 | private $currentLanguage = ''; | 23 | private $currentLanguage = ''; |
24 | private $notInstalledMessage = array(); | 24 | private $notInstalledMessage = array(); |
25 | 25 | ||
26 | private $language_names = array( | ||
27 | 'cs_CZ.utf8' => 'čeština', | ||
28 | 'de_DE.utf8' => 'German', | ||
29 | 'en_EN.utf8' => 'English', | ||
30 | 'es_ES.utf8' => 'Español', | ||
31 | 'fa_IR.utf8' => 'فارسی', | ||
32 | 'fr_FR.utf8' => 'Français', | ||
33 | 'it_IT.utf8' => 'Italiano', | ||
34 | 'pl_PL.utf8' => 'Polski', | ||
35 | 'ru_RU.utf8' => 'Pусский', | ||
36 | 'sl_SI.utf8' => 'Slovenščina', | ||
37 | 'uk_UA.utf8' => 'Український', | ||
38 | ); | ||
26 | public function __construct() | 39 | public function __construct() |
27 | { | 40 | { |
28 | if ($this->configFileIsAvailable()) { | 41 | if ($this->configFileIsAvailable()) { |
@@ -307,6 +320,8 @@ class Poche | |||
307 | $themes[$theme] = $this->getThemeInfo($theme); | 320 | $themes[$theme] = $this->getThemeInfo($theme); |
308 | } | 321 | } |
309 | 322 | ||
323 | ksort($themes); | ||
324 | |||
310 | return $themes; | 325 | return $themes; |
311 | } | 326 | } |
312 | 327 | ||
@@ -331,7 +346,7 @@ class Poche | |||
331 | $current = true; | 346 | $current = true; |
332 | } | 347 | } |
333 | 348 | ||
334 | $languages[] = array('name' => $language, 'current' => $current); | 349 | $languages[] = array('name' => $this->language_names[$language], 'value' => $language, 'current' => $current); |
335 | } | 350 | } |
336 | 351 | ||
337 | return $languages; | 352 | return $languages; |
@@ -348,24 +363,62 @@ class Poche | |||
348 | 363 | ||
349 | protected function getPageContent(Url $url) | 364 | protected function getPageContent(Url $url) |
350 | { | 365 | { |
351 | $options = array('http' => array('user_agent' => 'poche')); | 366 | // Saving and clearing context |
352 | if (isset($_SERVER['AUTH_TYPE']) && "basic" === strtolower($_SERVER['AUTH_TYPE'])) { | 367 | $REAL = array(); |
353 | $options['http']['header'] = sprintf( | 368 | foreach( $GLOBALS as $key => $value ) { |
354 | "Authorization: Basic %s", | 369 | if( $key != "GLOBALS" && $key != "_SESSION" ) { |
355 | base64_encode( | 370 | $GLOBALS[$key] = array(); |
356 | sprintf('%s:%s', $_SERVER['PHP_AUTH_USER'], $_SERVER['PHP_AUTH_PW']) | 371 | $REAL[$key] = $value; |
357 | ) | 372 | } |
373 | } | ||
374 | // Saving and clearing session | ||
375 | $REAL_SESSION = array(); | ||
376 | foreach( $_SESSION as $key => $value ) { | ||
377 | $REAL_SESSION[$key] = $value; | ||
378 | unset($_SESSION[$key]); | ||
379 | } | ||
380 | |||
381 | // Running code in different context | ||
382 | $scope = function() { | ||
383 | extract( func_get_arg(1) ); | ||
384 | $_GET = $_REQUEST = array( | ||
385 | "url" => $url->getUrl(), | ||
386 | "max" => 5, | ||
387 | "links" => "preserve", | ||
388 | "exc" => "", | ||
389 | "format" => "json", | ||
390 | "submit" => "Create Feed" | ||
358 | ); | 391 | ); |
392 | ob_start(); | ||
393 | require func_get_arg(0); | ||
394 | $json = ob_get_flush(); | ||
395 | return $json; | ||
396 | }; | ||
397 | $json = $scope( "inc/3rdparty/makefulltextfeed.php", array("url" => $url) ); | ||
398 | |||
399 | // Clearing and restoring context | ||
400 | foreach( $GLOBALS as $key => $value ) { | ||
401 | if( $key != "GLOBALS" && $key != "_SESSION" ) { | ||
402 | unset($GLOBALS[$key]); | ||
403 | } | ||
404 | } | ||
405 | foreach( $REAL as $key => $value ) { | ||
406 | $GLOBALS[$key] = $value; | ||
407 | } | ||
408 | // Clearing and restoring session | ||
409 | foreach( $_SESSION as $key => $value ) { | ||
410 | unset($_SESSION[$key]); | ||
411 | } | ||
412 | foreach( $REAL_SESSION as $key => $value ) { | ||
413 | $_SESSION[$key] = $value; | ||
359 | } | 414 | } |
360 | $context = stream_context_create($options); | ||
361 | $json = file_get_contents(Tools::getPocheUrl() . '/inc/3rdparty/makefulltextfeed.php?url='.urlencode($url->getUrl()).'&max=5&links=preserve&exc=&format=json&submit=Create+Feed', false, $context); | ||
362 | return json_decode($json, true); | 415 | return json_decode($json, true); |
363 | } | 416 | } |
364 | 417 | ||
365 | /** | 418 | /** |
366 | * Call action (mark as fav, archive, delete, etc.) | 419 | * Call action (mark as fav, archive, delete, etc.) |
367 | */ | 420 | */ |
368 | public function action($action, Url $url, $id = 0, $import = FALSE, $autoclose = FALSE) | 421 | public function action($action, Url $url, $id = 0, $import = FALSE, $autoclose = FALSE, $tags = null) |
369 | { | 422 | { |
370 | switch ($action) | 423 | switch ($action) |
371 | { | 424 | { |
@@ -374,6 +427,12 @@ class Poche | |||
374 | $title = ($content['rss']['channel']['item']['title'] != '') ? $content['rss']['channel']['item']['title'] : _('Untitled'); | 427 | $title = ($content['rss']['channel']['item']['title'] != '') ? $content['rss']['channel']['item']['title'] : _('Untitled'); |
375 | $body = $content['rss']['channel']['item']['description']; | 428 | $body = $content['rss']['channel']['item']['description']; |
376 | 429 | ||
430 | // clean content from prevent xss attack | ||
431 | $config = HTMLPurifier_Config::createDefault(); | ||
432 | $purifier = new HTMLPurifier($config); | ||
433 | $title = $purifier->purify($title); | ||
434 | $body = $purifier->purify($body); | ||
435 | |||
377 | //search for possible duplicate if not in import mode | 436 | //search for possible duplicate if not in import mode |
378 | if (!$import) { | 437 | if (!$import) { |
379 | $duplicate = $this->store->retrieveOneByURL($url->getUrl(), $this->user->getId()); | 438 | $duplicate = $this->store->retrieveOneByURL($url->getUrl(), $this->user->getId()); |
@@ -461,8 +520,14 @@ class Poche | |||
461 | } | 520 | } |
462 | break; | 521 | break; |
463 | case 'add_tag' : | 522 | case 'add_tag' : |
464 | $tags = explode(',', $_POST['value']); | 523 | if($import){ |
465 | $entry_id = $_POST['entry_id']; | 524 | $entry_id = $id; |
525 | $tags = explode(',', $tags); | ||
526 | } | ||
527 | else{ | ||
528 | $tags = explode(',', $_POST['value']); | ||
529 | $entry_id = $_POST['entry_id']; | ||
530 | } | ||
466 | $entry = $this->store->retrieveOneById($entry_id, $this->user->getId()); | 531 | $entry = $this->store->retrieveOneById($entry_id, $this->user->getId()); |
467 | if (!$entry) { | 532 | if (!$entry) { |
468 | $this->messages->add('e', _('Article not found!')); | 533 | $this->messages->add('e', _('Article not found!')); |
@@ -489,7 +554,9 @@ class Poche | |||
489 | # we assign the tag to the article | 554 | # we assign the tag to the article |
490 | $this->store->setTagToEntry($tag_id, $entry_id); | 555 | $this->store->setTagToEntry($tag_id, $entry_id); |
491 | } | 556 | } |
492 | Tools::redirect(); | 557 | if(!$import) { |
558 | Tools::redirect(); | ||
559 | } | ||
493 | break; | 560 | break; |
494 | case 'remove_tag' : | 561 | case 'remove_tag' : |
495 | $tag_id = $_GET['tag_id']; | 562 | $tag_id = $_GET['tag_id']; |
@@ -547,14 +614,7 @@ class Poche | |||
547 | $tpl_vars = array( | 614 | $tpl_vars = array( |
548 | 'entry_id' => $id, | 615 | 'entry_id' => $id, |
549 | 'tags' => $tags, | 616 | 'tags' => $tags, |
550 | ); | 617 | 'entry' => $entry, |
551 | break; | ||
552 | case 'tag': | ||
553 | $entries = $this->store->retrieveEntriesByTag($id, $this->user->getId()); | ||
554 | $tag = $this->store->retrieveTag($id, $this->user->getId()); | ||
555 | $tpl_vars = array( | ||
556 | 'tag' => $tag, | ||
557 | 'entries' => $entries, | ||
558 | ); | 618 | ); |
559 | break; | 619 | break; |
560 | case 'tags': | 620 | case 'tags': |
@@ -595,22 +655,28 @@ class Poche | |||
595 | Tools::logm('error in view call : entry is null'); | 655 | Tools::logm('error in view call : entry is null'); |
596 | } | 656 | } |
597 | break; | 657 | break; |
598 | default: # home, favorites and archive views | 658 | default: # home, favorites, archive and tag views |
599 | $entries = $this->store->getEntriesByView($view, $this->user->getId()); | ||
600 | $tpl_vars = array( | 659 | $tpl_vars = array( |
601 | 'entries' => '', | 660 | 'entries' => '', |
602 | 'page_links' => '', | 661 | 'page_links' => '', |
603 | 'nb_results' => '', | 662 | 'nb_results' => '', |
604 | ); | 663 | ); |
605 | 664 | ||
606 | if (count($entries) > 0) { | 665 | //if id is given - we retrive entries by tag: id is tag id |
607 | $this->pagination->set_total(count($entries)); | 666 | if ($id) { |
667 | $tpl_vars['tag'] = $this->store->retrieveTag($id, $this->user->getId()); | ||
668 | $tpl_vars['id'] = intval($id); | ||
669 | } | ||
670 | |||
671 | $count = $this->store->getEntriesByViewCount($view, $this->user->getId(), $id); | ||
672 | |||
673 | if ($count > 0) { | ||
674 | $this->pagination->set_total($count); | ||
608 | $page_links = str_replace(array('previous', 'next'), array(_('previous'), _('next')), | 675 | $page_links = str_replace(array('previous', 'next'), array(_('previous'), _('next')), |
609 | $this->pagination->page_links('?view=' . $view . '&sort=' . $_SESSION['sort'] . '&')); | 676 | $this->pagination->page_links('?view=' . $view . '&sort=' . $_SESSION['sort'] . (($id)?'&id='.$id:'') . '&' )); |
610 | $datas = $this->store->getEntriesByView($view, $this->user->getId(), $this->pagination->get_limit()); | 677 | $tpl_vars['entries'] = $this->store->getEntriesByView($view, $this->user->getId(), $this->pagination->get_limit(), $id); |
611 | $tpl_vars['entries'] = $datas; | ||
612 | $tpl_vars['page_links'] = $page_links; | 678 | $tpl_vars['page_links'] = $page_links; |
613 | $tpl_vars['nb_results'] = count($entries); | 679 | $tpl_vars['nb_results'] = $count; |
614 | } | 680 | } |
615 | Tools::logm('display ' . $view . ' view'); | 681 | Tools::logm('display ' . $view . ' view'); |
616 | break; | 682 | break; |
@@ -704,7 +770,7 @@ class Poche | |||
704 | $actualLanguage = false; | 770 | $actualLanguage = false; |
705 | 771 | ||
706 | foreach ($languages as $language) { | 772 | foreach ($languages as $language) { |
707 | if ($language['name'] == $_POST['language']) { | 773 | if ($language['value'] == $_POST['language']) { |
708 | $actualLanguage = true; | 774 | $actualLanguage = true; |
709 | break; | 775 | break; |
710 | } | 776 | } |
@@ -852,14 +918,18 @@ class Poche | |||
852 | $a = $li->find('a'); | 918 | $a = $li->find('a'); |
853 | $url = new Url(base64_encode($a[0]->href)); | 919 | $url = new Url(base64_encode($a[0]->href)); |
854 | $this->action('add', $url, 0, TRUE); | 920 | $this->action('add', $url, 0, TRUE); |
921 | $sequence = ''; | ||
922 | if (STORAGE == 'postgres') { | ||
923 | $sequence = 'entries_id_seq'; | ||
924 | } | ||
925 | $last_id = $this->store->getLastId($sequence); | ||
855 | if ($read == '1') { | 926 | if ($read == '1') { |
856 | $sequence = ''; | ||
857 | if (STORAGE == 'postgres') { | ||
858 | $sequence = 'entries_id_seq'; | ||
859 | } | ||
860 | $last_id = $this->store->getLastId($sequence); | ||
861 | $this->action('toggle_archive', $url, $last_id, TRUE); | 927 | $this->action('toggle_archive', $url, $last_id, TRUE); |
862 | } | 928 | } |
929 | $tags = $a[0]->tags; | ||
930 | if(!empty($tags)) { | ||
931 | $this->action('add_tag',$url,$last_id,true,false,$tags); | ||
932 | } | ||
863 | } | 933 | } |
864 | 934 | ||
865 | # the second <ul> is for read links | 935 | # the second <ul> is for read links |
diff --git a/inc/poche/Tools.class.php b/inc/poche/Tools.class.php index 515a08aa..4ed28ed1 100644 --- a/inc/poche/Tools.class.php +++ b/inc/poche/Tools.class.php | |||
@@ -92,7 +92,7 @@ class Tools | |||
92 | { | 92 | { |
93 | $views = array( | 93 | $views = array( |
94 | 'install', 'import', 'export', 'config', 'tags', | 94 | 'install', 'import', 'export', 'config', 'tags', |
95 | 'edit-tags', 'view', 'login', 'error', 'tag' | 95 | 'edit-tags', 'view', 'login', 'error' |
96 | ); | 96 | ); |
97 | 97 | ||
98 | if (in_array($view, $views)) { | 98 | if (in_array($view, $views)) { |
diff --git a/inc/poche/global.inc.php b/inc/poche/global.inc.php index e2beade1..d22b0588 100644 --- a/inc/poche/global.inc.php +++ b/inc/poche/global.inc.php | |||
@@ -29,6 +29,8 @@ require_once INCLUDES . '/3rdparty/libraries/feedwriter/FeedItem.php'; | |||
29 | require_once INCLUDES . '/3rdparty/libraries/feedwriter/FeedWriter.php'; | 29 | require_once INCLUDES . '/3rdparty/libraries/feedwriter/FeedWriter.php'; |
30 | require_once INCLUDES . '/3rdparty/FlattrItem.class.php'; | 30 | require_once INCLUDES . '/3rdparty/FlattrItem.class.php'; |
31 | 31 | ||
32 | require_once INCLUDES . '/3rdparty/htmlpurifier/HTMLPurifier.auto.php'; | ||
33 | |||
32 | # Composer its autoloader for automatically loading Twig | 34 | # Composer its autoloader for automatically loading Twig |
33 | if (! file_exists(ROOT . '/vendor/autoload.php')) { | 35 | if (! file_exists(ROOT . '/vendor/autoload.php')) { |
34 | Poche::$canRenderTemplates = false; | 36 | Poche::$canRenderTemplates = false; |