]>
git.immae.eu Git - github/wallabag/wallabag.git/blob - inc/poche/Poche.class.php
3 * wallabag, self hostable application allowing you to not miss any content anymore
6 * @author Nicolas Lœuillet <nicolas@loeuillet.org>
8 * @license http://www.wtfpl.net/ see COPYING file
13 public static $canRenderTemplates = true ;
14 public static $configFileAvailable = true ;
22 private $currentTheme = '' ;
23 private $currentLanguage = '' ;
24 private $notInstalledMessage = array ();
26 public function __construct ()
28 if ( $this- > configFileIsAvailable ()) {
32 if ( $this- > themeIsInstalled ()) {
36 if ( $this- > systemIsInstalled ()) {
37 $this- > store
= new Database ();
38 $this- > messages
= new Messages ();
40 if (! $this- > store
-> isInstalled ()) {
43 $this- > store
-> checkTags ();
47 private function init ()
50 Session
:: $sessionName = 'poche' ;
53 if ( isset ( $_SESSION [ 'poche_user' ]) && $_SESSION [ 'poche_user' ] != array ()) {
54 $this- > user
= $_SESSION [ 'poche_user' ];
56 # fake user, just for install & login screens
57 $this- > user
= new User ();
58 $this- > user
-> setConfig ( $this- > getDefaultConfig ());
62 $language = $this- > user
-> getConfigValue ( 'language' );
63 putenv ( 'LC_ALL=' . $language );
64 setlocale ( LC_ALL
, $language );
65 bindtextdomain ( $language , LOCALE
);
66 textdomain ( $language );
69 $this- > pagination
= new Paginator ( $this- > user
-> getConfigValue ( 'pager' ), 'p' );
72 $themeDirectory = $this- > user
-> getConfigValue ( 'theme' );
74 if ( $themeDirectory === false ) {
75 $themeDirectory = DEFAULT_THEME
;
78 $this- > currentTheme
= $themeDirectory ;
81 $languageDirectory = $this- > user
-> getConfigValue ( 'language' );
83 if ( $languageDirectory === false ) {
84 $languageDirectory = DEFAULT_THEME
;
87 $this- > currentLanguage
= $languageDirectory ;
90 public function configFileIsAvailable () {
91 if (! self
:: $configFileAvailable ) {
92 $this- > notInstalledMessage
[] = 'You have to rename inc/poche/config.inc.php.new to inc/poche/config.inc.php.' ;
100 public function themeIsInstalled () {
102 # Twig is an absolute requirement for Poche to function. Abort immediately if the Composer installer hasn't been run yet
103 if (! self
:: $canRenderTemplates ) {
104 $this- > notInstalledMessage
[] = 'Twig does not seem to be installed. Please initialize the Composer installation to automatically fetch dependencies. You can also download <a href="http://wllbg.org/vendor">vendor.zip</a> and extract it in your wallabag folder.' ;
108 if (! is_writable ( CACHE
)) {
109 $this- > notInstalledMessage
[] = 'You don \' t have write access on cache directory.' ;
111 self
:: $canRenderTemplates = false ;
116 # Check if the selected theme and its requirements are present
117 $theme = $this- > getTheme ();
119 if ( $theme != '' && ! is_dir ( THEME
. '/' . $theme )) {
120 $this- > notInstalledMessage
[] = 'The currently selected theme (' . $theme . ') does not seem to be properly installed (Missing directory: ' . THEME
. '/' . $theme . ')' ;
122 self
:: $canRenderTemplates = false ;
127 $themeInfo = $this- > getThemeInfo ( $theme );
128 if ( isset ( $themeInfo [ 'requirements' ]) && is_array ( $themeInfo [ 'requirements' ])) {
129 foreach ( $themeInfo [ 'requirements' ] as $requiredTheme ) {
130 if (! is_dir ( THEME
. '/' . $requiredTheme )) {
131 $this- > notInstalledMessage
[] = 'The required "' . $requiredTheme . '" theme is missing for the current theme (' . $theme . ')' ;
133 self
:: $canRenderTemplates = false ;
149 * all checks before installation.
150 * @todo move HTML to template
153 public function systemIsInstalled ()
157 $configSalt = defined ( 'SALT' ) ? constant ( 'SALT' ) : '' ;
159 if ( empty ( $configSalt )) {
160 $this- > notInstalledMessage
[] = 'You have not yet filled in the SALT value in the config.inc.php file.' ;
163 if ( STORAGE
== 'sqlite' && ! file_exists ( STORAGE_SQLITE
)) {
164 Tools
:: logm ( 'sqlite file doesn \' t exist' );
165 $this- > notInstalledMessage
[] = 'sqlite file doesn \' t exist, you can find it in install folder. Copy it in /db folder.' ;
168 if ( is_dir ( ROOT
. '/install' ) && ! DEBUG_POCHE
) {
169 $this- > notInstalledMessage
[] = 'you have to delete the /install folder before using poche.' ;
172 if ( STORAGE
== 'sqlite' && ! is_writable ( STORAGE_SQLITE
)) {
173 Tools
:: logm ( 'you don \' t have write access on sqlite file' );
174 $this- > notInstalledMessage
[] = 'You don \' t have write access on sqlite file.' ;
185 public function getNotInstalledMessage () {
186 return $this- > notInstalledMessage
;
189 private function initTpl ()
191 $loaderChain = new Twig_Loader_Chain ();
192 $theme = $this- > getTheme ();
194 # add the current theme as first to the loader chain so Twig will look there first for overridden template files
196 $loaderChain- > addLoader ( new Twig_Loader_Filesystem ( THEME
. '/' . $theme ));
197 } catch ( Twig_Error_Loader
$e ) {
198 # @todo isInstalled() should catch this, inject Twig later
199 die ( 'The currently selected theme (' . $theme . ') does not seem to be properly installed (' . THEME
. '/' . $theme . ' is missing)' );
202 # add all required themes to the loader chain
203 $themeInfo = $this- > getThemeInfo ( $theme );
204 if ( isset ( $themeInfo [ 'requirements' ]) && is_array ( $themeInfo [ 'requirements' ])) {
205 foreach ( $themeInfo [ 'requirements' ] as $requiredTheme ) {
207 $loaderChain- > addLoader ( new Twig_Loader_Filesystem ( THEME
. '/' . $requiredTheme ));
208 } catch ( Twig_Error_Loader
$e ) {
209 # @todo isInstalled() should catch this, inject Twig later
210 die ( 'The required "' . $requiredTheme . '" theme is missing for the current theme (' . $theme . ')' );
216 $twigParams = array ();
218 $twigParams = array ( 'cache' => CACHE
);
221 $this- > tpl
= new Twig_Environment ( $loaderChain , $twigParams );
222 $this- > tpl
-> addExtension ( new Twig_Extensions_Extension_I18n ());
224 # filter to display domain name of an url
225 $filter = new Twig_SimpleFilter ( 'getDomain' , 'Tools::getDomain' );
226 $this- > tpl
-> addFilter ( $filter );
228 # filter for reading time
229 $filter = new Twig_SimpleFilter ( 'getReadingTime' , 'Tools::getReadingTime' );
230 $this- > tpl
-> addFilter ( $filter );
233 private function install ()
235 Tools
:: logm ( 'poche still not installed' );
236 echo $this- > tpl
-> render ( 'install.twig' , array (
237 'token' => Session
:: getToken (),
238 'theme' => $this- > getTheme (),
239 'poche_url' => Tools
:: getPocheUrl ()
241 if ( isset ( $_GET [ 'install' ])) {
242 if (( $_POST [ 'password' ] == $_POST [ 'password_repeat' ])
243 && $_POST [ 'password' ] != "" && $_POST [ 'login' ] != "" ) {
244 # let's rock, install poche baby !
245 if ( $this- > store
-> install ( $_POST [ 'login' ], Tools
:: encodeString ( $_POST [ 'password' ] . $_POST [ 'login' ])))
248 Tools
:: logm ( 'poche is now installed' );
253 Tools
:: logm ( 'error during installation' );
260 public function getTheme () {
261 return $this- > currentTheme
;
265 * Provides theme information by parsing theme.ini file if present in the theme's root directory.
266 * In all cases, the following data will be returned:
267 * - name: theme's name, or key if the theme is unnamed,
268 * - current: boolean informing if the theme is the current user theme.
270 * @param string $theme Theme key (directory name)
271 * @return array|boolean Theme information, or false if the theme doesn't exist.
273 public function getThemeInfo ( $theme ) {
274 if (! is_dir ( THEME
. '/' . $theme )) {
278 $themeIniFile = THEME
. '/' . $theme . '/theme.ini' ;
279 $themeInfo = array ();
281 if ( is_file ( $themeIniFile ) && is_readable ( $themeIniFile )) {
282 $themeInfo = parse_ini_file ( $themeIniFile );
285 if ( $themeInfo === false ) {
286 $themeInfo = array ();
288 if (! isset ( $themeInfo [ 'name' ])) {
289 $themeInfo [ 'name' ] = $theme ;
291 $themeInfo [ 'current' ] = ( $theme === $this- > getTheme ());
296 public function getInstalledThemes () {
297 $handle = opendir ( THEME
);
300 while (( $theme = readdir ( $handle )) !== false ) {
301 # Themes are stored in a directory, so all directory names are themes
302 # @todo move theme installation data to database
303 if (! is_dir ( THEME
. '/' . $theme ) || in_array ( $theme , array ( '.' , '..' ))) {
307 $themes [ $theme ] = $this- > getThemeInfo ( $theme );
313 public function getLanguage () {
314 return $this- > currentLanguage
;
317 public function getInstalledLanguages () {
318 $handle = opendir ( LOCALE
);
319 $languages = array ();
321 while (( $language = readdir ( $handle )) !== false ) {
322 # Languages are stored in a directory, so all directory names are languages
323 # @todo move language installation data to database
324 if (! is_dir ( LOCALE
. '/' . $language ) || in_array ( $language , array ( '..' , '.' ))) {
330 if ( $language === $this- > getLanguage ()) {
334 $languages [] = array ( 'name' => $language , 'current' => $current );
340 public function getDefaultConfig ()
343 'pager' => PAGINATION
,
345 'theme' => DEFAULT_THEME
349 protected function getPageContent ( Url
$url )
351 $options = array ( 'http' => array ( 'user_agent' => 'poche' ));
352 if ( isset ( $_SERVER [ 'AUTH_TYPE' ]) && "basic" === strtolower ( $_SERVER [ 'AUTH_TYPE' ])) {
353 $options [ 'http' ][ 'header' ] = sprintf (
354 "Authorization: Basic %s" ,
356 sprintf ( '%s:%s' , $_SERVER [ 'PHP_AUTH_USER' ], $_SERVER [ 'PHP_AUTH_PW' ])
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 );
366 * Call action (mark as fav, archive, delete, etc.)
368 public function action ( $action , Url
$url , $id = 0 , $import = FALSE , $autoclose = FALSE )
373 $content = $this- > getPageContent ( $url );
374 $title = ( $content [ 'rss' ][ 'channel' ][ 'item' ][ 'title' ] != '' ) ? $content [ 'rss' ][ 'channel' ][ 'item' ][ 'title' ] : _ ( 'Untitled' );
375 $body = $content [ 'rss' ][ 'channel' ][ 'item' ][ 'description' ];
377 if ( $this- > store
-> add ( $url- > getUrl (), $title , $body , $this- > user
-> getId ())) {
378 Tools
:: logm ( 'add link ' . $url- > getUrl ());
380 if ( STORAGE
== 'postgres' ) {
381 $sequence = 'entries_id_seq' ;
383 $last_id = $this- > store
-> getLastId ( $sequence );
384 if ( DOWNLOAD_PICTURES
) {
385 $content = filtre_picture ( $body , $url- > getUrl (), $last_id );
386 Tools
:: logm ( 'updating content article' );
387 $this- > store
-> updateContent ( $last_id , $content , $this- > user
-> getId ());
390 $this- > messages
-> add ( 's' , _ ( 'the link has been added successfully' ));
395 $this- > messages
-> add ( 'e' , _ ( 'error during insertion : the link wasn \' t added' ));
396 Tools
:: logm ( 'error during insertion : the link wasn \' t added ' . $url- > getUrl ());
401 if ( $autoclose == TRUE ) {
402 Tools
:: redirect ( '?view=home' );
404 Tools
:: redirect ( '?view=home&closewin=true' );
409 $msg = 'delete link #' . $id ;
410 if ( $this- > store
-> deleteById ( $id , $this- > user
-> getId ())) {
411 if ( DOWNLOAD_PICTURES
) {
412 remove_directory ( ABS_PATH
. $id );
414 $this- > messages
-> add ( 's' , _ ( 'the link has been deleted successfully' ));
417 $this- > messages
-> add ( 'e' , _ ( 'the link wasn \' t deleted' ));
418 $msg = 'error : can \' t delete link #' . $id ;
421 Tools
:: redirect ( '?' );
424 $this- > store
-> favoriteById ( $id , $this- > user
-> getId ());
425 Tools
:: logm ( 'mark as favorite link #' . $id );
430 case 'toggle_archive' :
431 $this- > store
-> archiveById ( $id , $this- > user
-> getId ());
432 Tools
:: logm ( 'archive link #' . $id );
438 $this- > store
-> archiveAll ( $this- > user
-> getId ());
439 Tools
:: logm ( 'archive all links' );
445 $tags = explode ( ',' , $_POST [ 'value' ]);
446 $entry_id = $_POST [ 'entry_id' ];
447 foreach ( $tags as $key => $tag_value ) {
448 $value = trim ( $tag_value );
449 $tag = $this- > store
-> retrieveTagByValue ( $value );
453 $tag = $this- > store
-> createTag ( $value );
455 if ( STORAGE
== 'postgres' ) {
456 $sequence = 'tags_id_seq' ;
458 $tag_id = $this- > store
-> getLastId ( $sequence );
461 $tag_id = $tag [ 'id' ];
464 # we assign the tag to the article
465 $this- > store
-> setTagToEntry ( $tag_id , $entry_id );
470 $tag_id = $_GET [ 'tag_id' ];
471 $this- > store
-> removeTagForEntry ( $id , $tag_id );
479 function displayView ( $view , $id = 0 )
486 $dev = trim ( $this- > getPocheVersion ( 'dev' ));
487 $prod = trim ( $this- > getPocheVersion ( 'prod' ));
488 $compare_dev = version_compare ( POCHE
, $dev );
489 $compare_prod = version_compare ( POCHE
, $prod );
490 $themes = $this- > getInstalledThemes ();
491 $languages = $this- > getInstalledLanguages ();
492 $token = $this- > user
-> getConfigValue ( 'token' );
493 $http_auth = ( isset ( $_SERVER [ 'PHP_AUTH_USER' ]) || isset ( $_SERVER [ 'REMOTE_USER' ])) ? true : false ;
496 'languages' => $languages ,
499 'compare_dev' => $compare_dev ,
500 'compare_prod' => $compare_prod ,
502 'user_id' => $this- > user
-> getId (),
503 'http_auth' => $http_auth ,
505 Tools
:: logm ( 'config view' );
509 $tags = $this- > store
-> retrieveTagsByEntry ( $id );
516 $entries = $this- > store
-> retrieveEntriesByTag ( $id );
517 $tag = $this- > store
-> retrieveTag ( $id );
520 'entries' => $entries ,
524 $token = $this- > user
-> getConfigValue ( 'token' );
525 $tags = $this- > store
-> retrieveAllTags ();
528 'user_id' => $this- > user
-> getId (),
533 $entry = $this- > store
-> retrieveOneById ( $id , $this- > user
-> getId ());
534 if ( $entry != NULL ) {
535 Tools
:: logm ( 'view link #' . $id );
536 $content = $entry [ 'content' ];
537 if ( function_exists ( 'tidy_parse_string' )) {
538 $tidy = tidy_parse_string ( $content , array ( 'indent' => true , 'show-body-only' => true ), 'UTF8' );
539 $tidy- > cleanRepair ();
540 $content = $tidy- > value
;
544 $flattr = new FlattrItem ();
545 $flattr- > checkItem ( $entry [ 'url' ], $entry [ 'id' ]);
548 $tags = $this- > store
-> retrieveTagsByEntry ( $entry [ 'id' ]);
552 'content' => $content ,
558 Tools
:: logm ( 'error in view call : entry is null' );
561 default : # home, favorites and archive views
562 $entries = $this- > store
-> getEntriesByView ( $view , $this- > user
-> getId ());
569 if ( count ( $entries ) > 0 ) {
570 $this- > pagination
-> set_total ( count ( $entries ));
571 $page_links = str_replace ( array ( 'previous' , 'next' ), array ( _ ( 'previous' ), _ ( 'next' )),
572 $this- > pagination
-> page_links ( '?view=' . $view . '&sort=' . $_SESSION [ 'sort' ] . '&' ));
573 $datas = $this- > store
-> getEntriesByView ( $view , $this- > user
-> getId (), $this- > pagination
-> get_limit ());
574 $tpl_vars [ 'entries' ] = $datas ;
575 $tpl_vars [ 'page_links' ] = $page_links ;
576 $tpl_vars [ 'nb_results' ] = count ( $entries );
578 Tools
:: logm ( 'display ' . $view . ' view' );
586 * update the password of the current user.
587 * if MODE_DEMO is TRUE, the password can't be updated.
588 * @todo add the return value
589 * @todo set the new password in function header like this updatePassword($newPassword)
592 public function updatePassword ()
595 $this- > messages
-> add ( 'i' , _ ( 'in demo mode, you can \' t update your password' ));
596 Tools
:: logm ( 'in demo mode, you can \' t do this' );
597 Tools
:: redirect ( '?view=config' );
600 if ( isset ( $_POST [ 'password' ]) && isset ( $_POST [ 'password_repeat' ])) {
601 if ( $_POST [ 'password' ] == $_POST [ 'password_repeat' ] && $_POST [ 'password' ] != "" ) {
602 $this- > messages
-> add ( 's' , _ ( 'your password has been updated' ));
603 $this- > store
-> updatePassword ( $this- > user
-> getId (), Tools
:: encodeString ( $_POST [ 'password' ] . $this- > user
-> getUsername ()));
605 Tools
:: logm ( 'password updated' );
609 $this- > messages
-> add ( 'e' , _ ( 'the two fields have to be filled & the password must be the same in the two fields' ));
610 Tools
:: redirect ( '?view=config' );
616 public function updateTheme ()
619 if ( empty ( $_POST [ 'theme' ])) {
622 # we are not going to change it to the current theme...
623 if ( $_POST [ 'theme' ] == $this- > getTheme ()) {
624 $this- > messages
-> add ( 'w' , _ ( 'still using the "' . $this- > getTheme () . '" theme!' ));
625 Tools
:: redirect ( '?view=config' );
628 $themes = $this- > getInstalledThemes ();
629 $actualTheme = false ;
631 foreach ( array_keys ( $themes ) as $theme ) {
632 if ( $theme == $_POST [ 'theme' ]) {
638 if (! $actualTheme ) {
639 $this- > messages
-> add ( 'e' , _ ( 'that theme does not seem to be installed' ));
640 Tools
:: redirect ( '?view=config' );
643 $this- > store
-> updateUserConfig ( $this- > user
-> getId (), 'theme' , $_POST [ 'theme' ]);
644 $this- > messages
-> add ( 's' , _ ( 'you have changed your theme preferences' ));
646 $currentConfig = $_SESSION [ 'poche_user' ]-> config
;
647 $currentConfig [ 'theme' ] = $_POST [ 'theme' ];
649 $_SESSION [ 'poche_user' ]-> setConfig ( $currentConfig );
651 Tools
:: redirect ( '?view=config' );
654 public function updateLanguage ()
657 if ( empty ( $_POST [ 'language' ])) {
660 # we are not going to change it to the current language...
661 if ( $_POST [ 'language' ] == $this- > getLanguage ()) {
662 $this- > messages
-> add ( 'w' , _ ( 'still using the "' . $this- > getLanguage () . '" language!' ));
663 Tools
:: redirect ( '?view=config' );
666 $languages = $this- > getInstalledLanguages ();
667 $actualLanguage = false ;
669 foreach ( $languages as $language ) {
670 if ( $language [ 'name' ] == $_POST [ 'language' ]) {
671 $actualLanguage = true ;
676 if (! $actualLanguage ) {
677 $this- > messages
-> add ( 'e' , _ ( 'that language does not seem to be installed' ));
678 Tools
:: redirect ( '?view=config' );
681 $this- > store
-> updateUserConfig ( $this- > user
-> getId (), 'language' , $_POST [ 'language' ]);
682 $this- > messages
-> add ( 's' , _ ( 'you have changed your language preferences' ));
684 $currentConfig = $_SESSION [ 'poche_user' ]-> config
;
685 $currentConfig [ 'language' ] = $_POST [ 'language' ];
687 $_SESSION [ 'poche_user' ]-> setConfig ( $currentConfig );
689 Tools
:: redirect ( '?view=config' );
693 * get credentials from differents sources
694 * it redirects the user to the $referer link
697 private function credentials () {
698 if ( isset ( $_SERVER [ 'PHP_AUTH_USER' ])) {
699 return array ( $_SERVER [ 'PHP_AUTH_USER' ], 'php_auth' , true );
701 if (! empty ( $_POST [ 'login' ]) && ! empty ( $_POST [ 'password' ])) {
702 return array ( $_POST [ 'login' ], $_POST [ 'password' ], false );
704 if ( isset ( $_SERVER [ 'REMOTE_USER' ])) {
705 return array ( $_SERVER [ 'REMOTE_USER' ], 'http_auth' , true );
708 return array ( false , false , false );
712 * checks if login & password are correct and save the user in session.
713 * it redirects the user to the $referer link
714 * @param string $referer the url to redirect after login
715 * @todo add the return value
718 public function login ( $referer )
720 list ( $login , $password , $isauthenticated )= $this- > credentials ();
721 if ( $login === false || $password === false ) {
722 $this- > messages
-> add ( 'e' , _ ( 'login failed: you have to fill all fields' ));
723 Tools
:: logm ( 'login failed' );
726 if (! empty ( $login ) && ! empty ( $password )) {
727 $user = $this- > store
-> login ( $login , Tools
:: encodeString ( $password . $login ), $isauthenticated );
728 if ( $user != array ()) {
729 # Save login into Session
730 $longlastingsession = isset ( $_POST [ 'longlastingsession' ]);
731 $passwordTest = ( $isauthenticated ) ? $user [ 'password' ] : Tools
:: encodeString ( $password . $login );
732 Session
:: login ( $user [ 'username' ], $user [ 'password' ], $login , $passwordTest , $longlastingsession , array ( 'poche_user' => new User ( $user )));
733 $this- > messages
-> add ( 's' , _ ( 'welcome to your wallabag' ));
734 Tools
:: logm ( 'login successful' );
735 Tools
:: redirect ( $referer );
737 $this- > messages
-> add ( 'e' , _ ( 'login failed: bad login or password' ));
738 Tools
:: logm ( 'login failed' );
744 * log out the poche user. It cleans the session.
745 * @todo add the return value
748 public function logout ()
750 $this- > user
= array ();
752 Tools
:: logm ( 'logout' );
757 * import from Instapaper. poche needs a ./instapaper-export.html file
758 * @todo add the return value
759 * @param string $targetFile the file used for importing
762 private function importFromInstapaper ( $targetFile )
764 # TODO gestion des articles favs
765 $html = new simple_html_dom ();
766 $html- > load_file ( $targetFile );
767 Tools
:: logm ( 'starting import from instapaper' );
771 foreach ( $html- > find ( 'ol' ) as $ul )
773 foreach ( $ul- > find ( 'li' ) as $li )
776 $url = new Url ( base64_encode ( $a [ 0 ]-> href
));
777 $this- > action ( 'add' , $url , 0 , TRUE );
780 if ( STORAGE
== 'postgres' ) {
781 $sequence = 'entries_id_seq' ;
783 $last_id = $this- > store
-> getLastId ( $sequence );
784 $this- > action ( 'toggle_archive' , $url , $last_id , TRUE );
788 # the second <ol> is for read links
791 $this- > messages
-> add ( 's' , _ ( 'import from instapaper completed' ));
792 Tools
:: logm ( 'import from instapaper completed' );
797 * import from Pocket. poche needs a ./ril_export.html file
798 * @todo add the return value
799 * @param string $targetFile the file used for importing
802 private function importFromPocket ( $targetFile )
804 # TODO gestion des articles favs
805 $html = new simple_html_dom ();
806 $html- > load_file ( $targetFile );
807 Tools
:: logm ( 'starting import from pocket' );
811 foreach ( $html- > find ( 'ul' ) as $ul )
813 foreach ( $ul- > find ( 'li' ) as $li )
816 $url = new Url ( base64_encode ( $a [ 0 ]-> href
));
817 $this- > action ( 'add' , $url , 0 , TRUE );
820 if ( STORAGE
== 'postgres' ) {
821 $sequence = 'entries_id_seq' ;
823 $last_id = $this- > store
-> getLastId ( $sequence );
824 $this- > action ( 'toggle_archive' , $url , $last_id , TRUE );
828 # the second <ul> is for read links
831 $this- > messages
-> add ( 's' , _ ( 'import from pocket completed' ));
832 Tools
:: logm ( 'import from pocket completed' );
837 * import from Readability. poche needs a ./readability file
838 * @todo add the return value
839 * @param string $targetFile the file used for importing
842 private function importFromReadability ( $targetFile )
844 # TODO gestion des articles lus / favs
845 $str_data = file_get_contents ( $targetFile );
846 $data = json_decode ( $str_data , true );
847 Tools
:: logm ( 'starting import from Readability' );
849 foreach ( $data as $key => $value ) {
853 foreach ( $value as $item ) {
854 foreach ( $item as $attr => $value ) {
855 if ( $attr == 'article__url' ) {
856 $url = new Url ( base64_encode ( $value ));
859 if ( STORAGE
== 'postgres' ) {
860 $sequence = 'entries_id_seq' ;
862 if ( $value == 'true' ) {
863 if ( $attr == 'favorite' ) {
866 if ( $attr == 'archive' ) {
873 if (! is_null ( $url ) && $url- > isCorrect ()) {
874 $this- > action ( 'add' , $url , 0 , TRUE );
877 $last_id = $this- > store
-> getLastId ( $sequence );
878 $this- > action ( 'toggle_fav' , $url , $last_id , TRUE );
881 $last_id = $this- > store
-> getLastId ( $sequence );
882 $this- > action ( 'toggle_archive' , $url , $last_id , TRUE );
887 $this- > messages
-> add ( 's' , _ ( 'import from Readability completed. ' . $count . ' new links.' ));
888 Tools
:: logm ( 'import from Readability completed' );
893 * import from Poche exported file
894 * @param string $targetFile the file used for importing
897 private function importFromPoche ( $targetFile )
899 $str_data = file_get_contents ( $targetFile );
900 $data = json_decode ( $str_data , true );
901 Tools
:: logm ( 'starting import from Poche' );
905 if ( STORAGE
== 'postgres' ) {
906 $sequence = 'entries_id_seq' ;
910 foreach ( $data as $value ) {
912 $url = new Url ( base64_encode ( $value [ 'url' ]));
913 $favorite = ( $value [ 'is_fav' ] == - 1 );
914 $archive = ( $value [ 'is_read' ] == - 1 );
917 if (! is_null ( $url ) && $url- > isCorrect ()) {
919 $this- > action ( 'add' , $url , 0 , TRUE );
923 $last_id = $this- > store
-> getLastId ( $sequence );
924 $this- > action ( 'toggle_fav' , $url , $last_id , TRUE );
927 $last_id = $this- > store
-> getLastId ( $sequence );
928 $this- > action ( 'toggle_archive' , $url , $last_id , TRUE );
933 $this- > messages
-> add ( 's' , _ ( 'import from Poche completed. ' . $count . ' new links.' ));
934 Tools
:: logm ( 'import from Poche completed' );
939 * import datas into your poche
940 * @param string $from name of the service to import : pocket, instapaper or readability
941 * @todo add the return value
944 public function import ( $from )
947 'pocket' => 'importFromPocket' ,
948 'readability' => 'importFromReadability' ,
949 'instapaper' => 'importFromInstapaper' ,
950 'poche' => 'importFromPoche' ,
953 if (! isset ( $providers [ $from ])) {
954 $this- > messages
-> add ( 'e' , _ ( 'Unknown import provider.' ));
958 $targetDefinition = 'IMPORT_' . strtoupper ( $from ) . '_FILE' ;
959 $targetFile = constant ( $targetDefinition );
961 if (! defined ( $targetDefinition )) {
962 $this- > messages
-> add ( 'e' , _ ( 'Incomplete inc/poche/define.inc.php file, please define "' . $targetDefinition . '".' ));
966 if (! file_exists ( $targetFile )) {
967 $this- > messages
-> add ( 'e' , _ ( 'Could not find required "' . $targetFile . '" import file.' ));
971 $this- > $providers [ $from ]( $targetFile );
975 * export poche entries in json
976 * @return json all poche entries
978 public function export ()
980 $entries = $this- > store
-> retrieveAll ( $this- > user
-> getId ());
981 echo $this- > tpl
-> render ( 'export.twig' , array (
982 'export' => Tools
:: renderJson ( $entries ),
984 Tools
:: logm ( 'export view' );
988 * Checks online the latest version of poche and cache it
989 * @param string $which 'prod' or 'dev'
990 * @return string latest $which version
992 private function getPocheVersion ( $which = 'prod' )
994 $cache_file = CACHE
. '/' . $which ;
996 # checks if the cached version file exists
997 if ( file_exists ( $cache_file ) && ( filemtime ( $cache_file ) > ( time () - 86400 ))) {
998 $version = file_get_contents ( $cache_file );
1000 $version = file_get_contents ( 'http://static.wallabag.org/versions/' . $which );
1001 file_put_contents ( $cache_file , $version , LOCK_EX
);
1006 public function generateToken ()
1008 if ( ini_get ( 'open_basedir' ) === '' ) {
1009 $token = substr ( base64_encode ( file_get_contents ( '/dev/urandom' , false , null , 0 , 20 )), 0 , 15 );
1012 $token = substr ( base64_encode ( uniqid ( mt_rand (), true )), 0 , 20 );
1015 $token = str_replace ( '+' , '' , $token );
1016 $this- > store
-> updateUserConfig ( $this- > user
-> getId (), 'token' , $token );
1017 $currentConfig = $_SESSION [ 'poche_user' ]-> config
;
1018 $currentConfig [ 'token' ] = $token ;
1019 $_SESSION [ 'poche_user' ]-> setConfig ( $currentConfig );
1022 public function generateFeeds ( $token , $user_id , $tag_id , $type = 'home' )
1024 $allowed_types = array ( 'home' , 'fav' , 'archive' , 'tag' );
1025 $config = $this- > store
-> getConfigUser ( $user_id );
1027 if (! in_array ( $type , $allowed_types ) ||
1028 $token != $config [ 'token' ]) {
1029 die ( _ ( 'Uh, there is a problem while generating feeds.' ));
1033 $feed = new FeedWriter ( RSS2
);
1034 $feed- > setTitle ( 'wallabag — ' . $type . ' feed' );
1035 $feed- > setLink ( Tools
:: getPocheUrl ());
1036 $feed- > setChannelElement ( 'updated' , date ( DATE_RSS
, time ()));
1037 $feed- > setChannelElement ( 'author' , 'wallabag' );
1039 if ( $type == 'tag' ) {
1040 $entries = $this- > store
-> retrieveEntriesByTag ( $tag_id );
1043 $entries = $this- > store
-> getEntriesByView ( $type , $user_id );
1046 if ( count ( $entries ) > 0 ) {
1047 foreach ( $entries as $entry ) {
1048 $newItem = $feed- > createNewItem ();
1049 $newItem- > setTitle ( $entry [ 'title' ]);
1050 $newItem- > setLink ( Tools
:: getPocheUrl () . '?view=view&id=' . $entry [ 'id' ]);
1051 $newItem- > setDate ( time ());
1052 $newItem- > setDescription ( $entry [ 'content' ]);
1053 $feed- > addItem ( $newItem );
1057 $feed- > genarateFeed ();