aboutsummaryrefslogtreecommitdiffhomepage
path: root/inc/poche/Poche.class.php
diff options
context:
space:
mode:
Diffstat (limited to 'inc/poche/Poche.class.php')
-rwxr-xr-xinc/poche/Poche.class.php317
1 files changed, 194 insertions, 123 deletions
diff --git a/inc/poche/Poche.class.php b/inc/poche/Poche.class.php
index 42a2dd9a..ee3b2ac2 100755
--- a/inc/poche/Poche.class.php
+++ b/inc/poche/Poche.class.php
@@ -18,7 +18,7 @@ class Poche
18 public $tpl; 18 public $tpl;
19 public $messages; 19 public $messages;
20 public $pagination; 20 public $pagination;
21 21
22 private $currentTheme = ''; 22 private $currentTheme = '';
23 private $currentLanguage = ''; 23 private $currentLanguage = '';
24 private $notInstalledMessage = array(); 24 private $notInstalledMessage = array();
@@ -42,11 +42,11 @@ class Poche
42 if ($this->configFileIsAvailable()) { 42 if ($this->configFileIsAvailable()) {
43 $this->init(); 43 $this->init();
44 } 44 }
45 45
46 if ($this->themeIsInstalled()) { 46 if ($this->themeIsInstalled()) {
47 $this->initTpl(); 47 $this->initTpl();
48 } 48 }
49 49
50 if ($this->systemIsInstalled()) { 50 if ($this->systemIsInstalled()) {
51 $this->store = new Database(); 51 $this->store = new Database();
52 $this->messages = new Messages(); 52 $this->messages = new Messages();
@@ -57,8 +57,8 @@ class Poche
57 $this->store->checkTags(); 57 $this->store->checkTags();
58 } 58 }
59 } 59 }
60 60
61 private function init() 61 private function init()
62 { 62 {
63 Tools::initPhp(); 63 Tools::initPhp();
64 64
@@ -74,28 +74,28 @@ class Poche
74 $language = $this->user->getConfigValue('language'); 74 $language = $this->user->getConfigValue('language');
75 putenv('LC_ALL=' . $language); 75 putenv('LC_ALL=' . $language);
76 setlocale(LC_ALL, $language); 76 setlocale(LC_ALL, $language);
77 bindtextdomain($language, LOCALE); 77 bindtextdomain($language, LOCALE);
78 textdomain($language); 78 textdomain($language);
79 79
80 # Pagination 80 # Pagination
81 $this->pagination = new Paginator($this->user->getConfigValue('pager'), 'p'); 81 $this->pagination = new Paginator($this->user->getConfigValue('pager'), 'p');
82 82
83 # Set up theme 83 # Set up theme
84 $themeDirectory = $this->user->getConfigValue('theme'); 84 $themeDirectory = $this->user->getConfigValue('theme');
85 85
86 if ($themeDirectory === false) { 86 if ($themeDirectory === false) {
87 $themeDirectory = DEFAULT_THEME; 87 $themeDirectory = DEFAULT_THEME;
88 } 88 }
89 89
90 $this->currentTheme = $themeDirectory; 90 $this->currentTheme = $themeDirectory;
91 91
92 # Set up language 92 # Set up language
93 $languageDirectory = $this->user->getConfigValue('language'); 93 $languageDirectory = $this->user->getConfigValue('language');
94 94
95 if ($languageDirectory === false) { 95 if ($languageDirectory === false) {
96 $languageDirectory = DEFAULT_THEME; 96 $languageDirectory = DEFAULT_THEME;
97 } 97 }
98 98
99 $this->currentLanguage = $languageDirectory; 99 $this->currentLanguage = $languageDirectory;
100 } 100 }
101 101
@@ -108,7 +108,7 @@ class Poche
108 108
109 return true; 109 return true;
110 } 110 }
111 111
112 public function themeIsInstalled() { 112 public function themeIsInstalled() {
113 $passTheme = TRUE; 113 $passTheme = TRUE;
114 # Twig is an absolute requirement for Poche to function. Abort immediately if the Composer installer hasn't been run yet 114 # Twig is an absolute requirement for Poche to function. Abort immediately if the Composer installer hasn't been run yet
@@ -123,27 +123,27 @@ class Poche
123 self::$canRenderTemplates = false; 123 self::$canRenderTemplates = false;
124 124
125 $passTheme = FALSE; 125 $passTheme = FALSE;
126 } 126 }
127 127
128 # Check if the selected theme and its requirements are present 128 # Check if the selected theme and its requirements are present
129 $theme = $this->getTheme(); 129 $theme = $this->getTheme();
130 130
131 if ($theme != '' && ! is_dir(THEME . '/' . $theme)) { 131 if ($theme != '' && ! is_dir(THEME . '/' . $theme)) {
132 $this->notInstalledMessage[] = 'The currently selected theme (' . $theme . ') does not seem to be properly installed (Missing directory: ' . THEME . '/' . $theme . ')'; 132 $this->notInstalledMessage[] = 'The currently selected theme (' . $theme . ') does not seem to be properly installed (Missing directory: ' . THEME . '/' . $theme . ')';
133 133
134 self::$canRenderTemplates = false; 134 self::$canRenderTemplates = false;
135 135
136 $passTheme = FALSE; 136 $passTheme = FALSE;
137 } 137 }
138 138
139 $themeInfo = $this->getThemeInfo($theme); 139 $themeInfo = $this->getThemeInfo($theme);
140 if (isset($themeInfo['requirements']) && is_array($themeInfo['requirements'])) { 140 if (isset($themeInfo['requirements']) && is_array($themeInfo['requirements'])) {
141 foreach ($themeInfo['requirements'] as $requiredTheme) { 141 foreach ($themeInfo['requirements'] as $requiredTheme) {
142 if (! is_dir(THEME . '/' . $requiredTheme)) { 142 if (! is_dir(THEME . '/' . $requiredTheme)) {
143 $this->notInstalledMessage[] = 'The required "' . $requiredTheme . '" theme is missing for the current theme (' . $theme . ')'; 143 $this->notInstalledMessage[] = 'The required "' . $requiredTheme . '" theme is missing for the current theme (' . $theme . ')';
144 144
145 self::$canRenderTemplates = false; 145 self::$canRenderTemplates = false;
146 146
147 $passTheme = FALSE; 147 $passTheme = FALSE;
148 } 148 }
149 } 149 }
@@ -153,21 +153,21 @@ class Poche
153 return FALSE; 153 return FALSE;
154 } 154 }
155 155
156 156
157 return true; 157 return true;
158 } 158 }
159 159
160 /** 160 /**
161 * all checks before installation. 161 * all checks before installation.
162 * @todo move HTML to template 162 * @todo move HTML to template
163 * @return boolean 163 * @return boolean
164 */ 164 */
165 public function systemIsInstalled() 165 public function systemIsInstalled()
166 { 166 {
167 $msg = TRUE; 167 $msg = TRUE;
168 168
169 $configSalt = defined('SALT') ? constant('SALT') : ''; 169 $configSalt = defined('SALT') ? constant('SALT') : '';
170 170
171 if (empty($configSalt)) { 171 if (empty($configSalt)) {
172 $this->notInstalledMessage[] = 'You have not yet filled in the SALT value in the config.inc.php file.'; 172 $this->notInstalledMessage[] = 'You have not yet filled in the SALT value in the config.inc.php file.';
173 $msg = FALSE; 173 $msg = FALSE;
@@ -193,7 +193,7 @@ class Poche
193 193
194 return true; 194 return true;
195 } 195 }
196 196
197 public function getNotInstalledMessage() { 197 public function getNotInstalledMessage() {
198 return $this->notInstalledMessage; 198 return $this->notInstalledMessage;
199 } 199 }
@@ -202,7 +202,7 @@ class Poche
202 { 202 {
203 $loaderChain = new Twig_Loader_Chain(); 203 $loaderChain = new Twig_Loader_Chain();
204 $theme = $this->getTheme(); 204 $theme = $this->getTheme();
205 205
206 # add the current theme as first to the loader chain so Twig will look there first for overridden template files 206 # add the current theme as first to the loader chain so Twig will look there first for overridden template files
207 try { 207 try {
208 $loaderChain->addLoader(new Twig_Loader_Filesystem(THEME . '/' . $theme)); 208 $loaderChain->addLoader(new Twig_Loader_Filesystem(THEME . '/' . $theme));
@@ -210,7 +210,7 @@ class Poche
210 # @todo isInstalled() should catch this, inject Twig later 210 # @todo isInstalled() should catch this, inject Twig later
211 die('The currently selected theme (' . $theme . ') does not seem to be properly installed (' . THEME . '/' . $theme .' is missing)'); 211 die('The currently selected theme (' . $theme . ') does not seem to be properly installed (' . THEME . '/' . $theme .' is missing)');
212 } 212 }
213 213
214 # add all required themes to the loader chain 214 # add all required themes to the loader chain
215 $themeInfo = $this->getThemeInfo($theme); 215 $themeInfo = $this->getThemeInfo($theme);
216 if (isset($themeInfo['requirements']) && is_array($themeInfo['requirements'])) { 216 if (isset($themeInfo['requirements']) && is_array($themeInfo['requirements'])) {
@@ -223,16 +223,16 @@ class Poche
223 } 223 }
224 } 224 }
225 } 225 }
226 226
227 if (DEBUG_POCHE) { 227 if (DEBUG_POCHE) {
228 $twigParams = array(); 228 $twigParams = array();
229 } else { 229 } else {
230 $twigParams = array('cache' => CACHE); 230 $twigParams = array('cache' => CACHE);
231 } 231 }
232 232
233 $this->tpl = new Twig_Environment($loaderChain, $twigParams); 233 $this->tpl = new Twig_Environment($loaderChain, $twigParams);
234 $this->tpl->addExtension(new Twig_Extensions_Extension_I18n()); 234 $this->tpl->addExtension(new Twig_Extensions_Extension_I18n());
235 235
236 # filter to display domain name of an url 236 # filter to display domain name of an url
237 $filter = new Twig_SimpleFilter('getDomain', 'Tools::getDomain'); 237 $filter = new Twig_SimpleFilter('getDomain', 'Tools::getDomain');
238 $this->tpl->addFilter($filter); 238 $this->tpl->addFilter($filter);
@@ -251,7 +251,7 @@ class Poche
251 'poche_url' => Tools::getPocheUrl() 251 'poche_url' => Tools::getPocheUrl()
252 )); 252 ));
253 if (isset($_GET['install'])) { 253 if (isset($_GET['install'])) {
254 if (($_POST['password'] == $_POST['password_repeat']) 254 if (($_POST['password'] == $_POST['password_repeat'])
255 && $_POST['password'] != "" && $_POST['login'] != "") { 255 && $_POST['password'] != "" && $_POST['login'] != "") {
256 # let's rock, install poche baby ! 256 # let's rock, install poche baby !
257 if ($this->store->install($_POST['login'], Tools::encodeString($_POST['password'] . $_POST['login']))) 257 if ($this->store->install($_POST['login'], Tools::encodeString($_POST['password'] . $_POST['login'])))
@@ -268,7 +268,7 @@ class Poche
268 } 268 }
269 exit(); 269 exit();
270 } 270 }
271 271
272 public function getTheme() { 272 public function getTheme() {
273 return $this->currentTheme; 273 return $this->currentTheme;
274 } 274 }
@@ -293,7 +293,7 @@ class Poche
293 if (is_file($themeIniFile) && is_readable($themeIniFile)) { 293 if (is_file($themeIniFile) && is_readable($themeIniFile)) {
294 $themeInfo = parse_ini_file($themeIniFile); 294 $themeInfo = parse_ini_file($themeIniFile);
295 } 295 }
296 296
297 if ($themeInfo === false) { 297 if ($themeInfo === false) {
298 $themeInfo = array(); 298 $themeInfo = array();
299 } 299 }
@@ -304,7 +304,7 @@ class Poche
304 304
305 return $themeInfo; 305 return $themeInfo;
306 } 306 }
307 307
308 public function getInstalledThemes() { 308 public function getInstalledThemes() {
309 $handle = opendir(THEME); 309 $handle = opendir(THEME);
310 $themes = array(); 310 $themes = array();
@@ -331,28 +331,28 @@ class Poche
331 public function getInstalledLanguages() { 331 public function getInstalledLanguages() {
332 $handle = opendir(LOCALE); 332 $handle = opendir(LOCALE);
333 $languages = array(); 333 $languages = array();
334 334
335 while (($language = readdir($handle)) !== false) { 335 while (($language = readdir($handle)) !== false) {
336 # Languages are stored in a directory, so all directory names are languages 336 # Languages are stored in a directory, so all directory names are languages
337 # @todo move language installation data to database 337 # @todo move language installation data to database
338 if (! is_dir(LOCALE . '/' . $language) || in_array($language, array('..', '.', 'tools'))) { 338 if (! is_dir(LOCALE . '/' . $language) || in_array($language, array('..', '.', 'tools'))) {
339 continue; 339 continue;
340 } 340 }
341 341
342 $current = false; 342 $current = false;
343 343
344 if ($language === $this->getLanguage()) { 344 if ($language === $this->getLanguage()) {
345 $current = true; 345 $current = true;
346 } 346 }
347 347
348 $languages[] = array('name' => (isset($this->language_names[$language]) ? $this->language_names[$language] : $language), 'value' => $language, 'current' => $current); 348 $languages[] = array('name' => (isset($this->language_names[$language]) ? $this->language_names[$language] : $language), 'value' => $language, 'current' => $current);
349 } 349 }
350 350
351 return $languages; 351 return $languages;
352 } 352 }
353 353
354 public function getDefaultConfig() 354 public function getDefaultConfig()
355 { 355 {
356 return array( 356 return array(
357 'pager' => PAGINATION, 357 'pager' => PAGINATION,
358 'language' => LANG, 358 'language' => LANG,
@@ -385,19 +385,15 @@ class Poche
385 $body = ''; 385 $body = '';
386 } 386 }
387 387
388 //search for possible duplicate if not in import mode 388 //search for possible duplicate
389 $duplicate = NULL; 389 $duplicate = NULL;
390 if (!$import) { 390 if (!$import) {
391 $duplicate = $this->store->retrieveOneByURL($url->getUrl(), $this->user->getId()); 391 $duplicate = $this->store->retrieveOneByURL($url->getUrl(), $this->user->getId());
392 } 392 }
393 393
394 if ($this->store->add($url->getUrl(), $title, $body, $this->user->getId())) { 394 $last_id = $this->store->add($url->getUrl(), $title, $body, $this->user->getId());
395 if ( $last_id && !$import ) {
395 Tools::logm('add link ' . $url->getUrl()); 396 Tools::logm('add link ' . $url->getUrl());
396 $sequence = '';
397 if (STORAGE == 'postgres') {
398 $sequence = 'entries_id_seq';
399 }
400 $last_id = $this->store->getLastId($sequence);
401 if (DOWNLOAD_PICTURES) { 397 if (DOWNLOAD_PICTURES) {
402 $content = filtre_picture($body, $url->getUrl(), $last_id); 398 $content = filtre_picture($body, $url->getUrl(), $last_id);
403 Tools::logm('updating content article'); 399 Tools::logm('updating content article');
@@ -417,9 +413,7 @@ class Poche
417 } 413 }
418 } 414 }
419 415
420 if (!$import) { 416 $this->messages->add('s', _('the link has been added successfully'));
421 $this->messages->add('s', _('the link has been added successfully'));
422 }
423 } 417 }
424 else { 418 else {
425 if (!$import) { 419 if (!$import) {
@@ -603,20 +597,19 @@ class Poche
603 'tags' => $tags, 597 'tags' => $tags,
604 ); 598 );
605 break; 599 break;
606 600 case 'search':
607 case 'search': 601 if (isset($_GET['search'])) {
608 if (isset($_GET['search'])){ 602 $search = filter_var($_GET['search'], FILTER_SANITIZE_STRING);
609 $search = filter_var($_GET['search'], FILTER_SANITIZE_STRING); 603 $tpl_vars['entries'] = $this->store->search($search, $this->user->getId());
610 $tpl_vars['entries'] = $this->store->search($search,$this->user->getId()); 604 $count = count($tpl_vars['entries']);
611 $count = count($tpl_vars['entries']); 605 $this->pagination->set_total($count);
612 $this->pagination->set_total($count); 606 $page_links = str_replace(array('previous', 'next'), array(_('previous'), _('next')),
613 $page_links = str_replace(array('previous', 'next'), array(_('previous'), _('next')), 607 $this->pagination->page_links('?view=' . $view . '?search=' . $search . '&sort=' . $_SESSION['sort'] . '&' ));
614 $this->pagination->page_links('?view=' . $view . '?search=' . $search . '&sort=' . $_SESSION['sort'] . '&' )); 608 $tpl_vars['page_links'] = $page_links;
615 $tpl_vars['page_links'] = $page_links; 609 $tpl_vars['nb_results'] = $count;
616 $tpl_vars['nb_results'] = $count; 610 $tpl_vars['search_term'] = $search;
617 $tpl_vars['search_term'] = $search; 611 }
618 } 612 break;
619 break;
620 case 'view': 613 case 'view':
621 $entry = $this->store->retrieveOneById($id, $this->user->getId()); 614 $entry = $this->store->retrieveOneById($id, $this->user->getId());
622 if ($entry != NULL) { 615 if ($entry != NULL) {
@@ -653,7 +646,7 @@ class Poche
653 'nb_results' => '', 646 'nb_results' => '',
654 'listmode' => (isset($_COOKIE['listmode']) ? true : false), 647 'listmode' => (isset($_COOKIE['listmode']) ? true : false),
655 ); 648 );
656 649
657 //if id is given - we retrive entries by tag: id is tag id 650 //if id is given - we retrive entries by tag: id is tag id
658 if ($id) { 651 if ($id) {
659 $tpl_vars['tag'] = $this->store->retrieveTag($id, $this->user->getId()); 652 $tpl_vars['tag'] = $this->store->retrieveTag($id, $this->user->getId());
@@ -678,8 +671,8 @@ class Poche
678 } 671 }
679 672
680 /** 673 /**
681 * update the password of the current user. 674 * update the password of the current user.
682 * if MODE_DEMO is TRUE, the password can't be updated. 675 * if MODE_DEMO is TRUE, the password can't be updated.
683 * @todo add the return value 676 * @todo add the return value
684 * @todo set the new password in function header like this updatePassword($newPassword) 677 * @todo set the new password in function header like this updatePassword($newPassword)
685 * @return boolean 678 * @return boolean
@@ -707,44 +700,44 @@ class Poche
707 } 700 }
708 } 701 }
709 } 702 }
710 703
711 public function updateTheme() 704 public function updateTheme()
712 { 705 {
713 # no data 706 # no data
714 if (empty($_POST['theme'])) { 707 if (empty($_POST['theme'])) {
715 } 708 }
716 709
717 # we are not going to change it to the current theme... 710 # we are not going to change it to the current theme...
718 if ($_POST['theme'] == $this->getTheme()) { 711 if ($_POST['theme'] == $this->getTheme()) {
719 $this->messages->add('w', _('still using the "' . $this->getTheme() . '" theme!')); 712 $this->messages->add('w', _('still using the "' . $this->getTheme() . '" theme!'));
720 Tools::redirect('?view=config'); 713 Tools::redirect('?view=config');
721 } 714 }
722 715
723 $themes = $this->getInstalledThemes(); 716 $themes = $this->getInstalledThemes();
724 $actualTheme = false; 717 $actualTheme = false;
725 718
726 foreach (array_keys($themes) as $theme) { 719 foreach (array_keys($themes) as $theme) {
727 if ($theme == $_POST['theme']) { 720 if ($theme == $_POST['theme']) {
728 $actualTheme = true; 721 $actualTheme = true;
729 break; 722 break;
730 } 723 }
731 } 724 }
732 725
733 if (! $actualTheme) { 726 if (! $actualTheme) {
734 $this->messages->add('e', _('that theme does not seem to be installed')); 727 $this->messages->add('e', _('that theme does not seem to be installed'));
735 Tools::redirect('?view=config'); 728 Tools::redirect('?view=config');
736 } 729 }
737 730
738 $this->store->updateUserConfig($this->user->getId(), 'theme', $_POST['theme']); 731 $this->store->updateUserConfig($this->user->getId(), 'theme', $_POST['theme']);
739 $this->messages->add('s', _('you have changed your theme preferences')); 732 $this->messages->add('s', _('you have changed your theme preferences'));
740 733
741 $currentConfig = $_SESSION['poche_user']->config; 734 $currentConfig = $_SESSION['poche_user']->config;
742 $currentConfig['theme'] = $_POST['theme']; 735 $currentConfig['theme'] = $_POST['theme'];
743 736
744 $_SESSION['poche_user']->setConfig($currentConfig); 737 $_SESSION['poche_user']->setConfig($currentConfig);
745 738
746 $this->emptyCache(); 739 $this->emptyCache();
747 740
748 Tools::redirect('?view=config'); 741 Tools::redirect('?view=config');
749 } 742 }
750 743
@@ -753,40 +746,40 @@ class Poche
753 # no data 746 # no data
754 if (empty($_POST['language'])) { 747 if (empty($_POST['language'])) {
755 } 748 }
756 749
757 # we are not going to change it to the current language... 750 # we are not going to change it to the current language...
758 if ($_POST['language'] == $this->getLanguage()) { 751 if ($_POST['language'] == $this->getLanguage()) {
759 $this->messages->add('w', _('still using the "' . $this->getLanguage() . '" language!')); 752 $this->messages->add('w', _('still using the "' . $this->getLanguage() . '" language!'));
760 Tools::redirect('?view=config'); 753 Tools::redirect('?view=config');
761 } 754 }
762 755
763 $languages = $this->getInstalledLanguages(); 756 $languages = $this->getInstalledLanguages();
764 $actualLanguage = false; 757 $actualLanguage = false;
765 758
766 foreach ($languages as $language) { 759 foreach ($languages as $language) {
767 if ($language['value'] == $_POST['language']) { 760 if ($language['value'] == $_POST['language']) {
768 $actualLanguage = true; 761 $actualLanguage = true;
769 break; 762 break;
770 } 763 }
771 } 764 }
772 765
773 if (! $actualLanguage) { 766 if (! $actualLanguage) {
774 $this->messages->add('e', _('that language does not seem to be installed')); 767 $this->messages->add('e', _('that language does not seem to be installed'));
775 Tools::redirect('?view=config'); 768 Tools::redirect('?view=config');
776 } 769 }
777 770
778 $this->store->updateUserConfig($this->user->getId(), 'language', $_POST['language']); 771 $this->store->updateUserConfig($this->user->getId(), 'language', $_POST['language']);
779 $this->messages->add('s', _('you have changed your language preferences')); 772 $this->messages->add('s', _('you have changed your language preferences'));
780 773
781 $currentConfig = $_SESSION['poche_user']->config; 774 $currentConfig = $_SESSION['poche_user']->config;
782 $currentConfig['language'] = $_POST['language']; 775 $currentConfig['language'] = $_POST['language'];
783 776
784 $_SESSION['poche_user']->setConfig($currentConfig); 777 $_SESSION['poche_user']->setConfig($currentConfig);
785 778
786 $this->emptyCache(); 779 $this->emptyCache();
787 780
788 Tools::redirect('?view=config'); 781 Tools::redirect('?view=config');
789 } 782 }
790 /** 783 /**
791 * get credentials from differents sources 784 * get credentials from differents sources
792 * it redirects the user to the $referer link 785 * it redirects the user to the $referer link
@@ -841,7 +834,7 @@ class Poche
841 /** 834 /**
842 * log out the poche user. It cleans the session. 835 * log out the poche user. It cleans the session.
843 * @todo add the return value 836 * @todo add the return value
844 * @return boolean 837 * @return boolean
845 */ 838 */
846 public function logout() 839 public function logout()
847 { 840 {
@@ -897,7 +890,7 @@ class Poche
897 * import from Pocket. poche needs a ./ril_export.html file 890 * import from Pocket. poche needs a ./ril_export.html file
898 * @todo add the return value 891 * @todo add the return value
899 * @param string $targetFile the file used for importing 892 * @param string $targetFile the file used for importing
900 * @return boolean 893 * @return boolean
901 */ 894 */
902 private function importFromPocket($targetFile) 895 private function importFromPocket($targetFile)
903 { 896 {
@@ -928,7 +921,7 @@ class Poche
928 $this->action('add_tag',$url,$last_id,true,false,$tags); 921 $this->action('add_tag',$url,$last_id,true,false,$tags);
929 } 922 }
930 } 923 }
931 924
932 # the second <ul> is for read links 925 # the second <ul> is for read links
933 $read = 1; 926 $read = 1;
934 } 927 }
@@ -943,7 +936,7 @@ class Poche
943 * import from Readability. poche needs a ./readability file 936 * import from Readability. poche needs a ./readability file
944 * @todo add the return value 937 * @todo add the return value
945 * @param string $targetFile the file used for importing 938 * @param string $targetFile the file used for importing
946 * @return boolean 939 * @return boolean
947 */ 940 */
948 private function importFromReadability($targetFile) 941 private function importFromReadability($targetFile)
949 { 942 {
@@ -1000,7 +993,7 @@ class Poche
1000 /** 993 /**
1001 * import from Poche exported file 994 * import from Poche exported file
1002 * @param string $targetFile the file used for importing 995 * @param string $targetFile the file used for importing
1003 * @return boolean 996 * @return boolean
1004 */ 997 */
1005 private function importFromPoche($targetFile) 998 private function importFromPoche($targetFile)
1006 { 999 {
@@ -1020,12 +1013,12 @@ class Poche
1020 $url = new Url(base64_encode($value['url'])); 1013 $url = new Url(base64_encode($value['url']));
1021 $favorite = ($value['is_fav'] == -1); 1014 $favorite = ($value['is_fav'] == -1);
1022 $archive = ($value['is_read'] == -1); 1015 $archive = ($value['is_read'] == -1);
1023 1016
1024 # we can add the url 1017 # we can add the url
1025 if (!is_null($url) && $url->isCorrect()) { 1018 if (!is_null($url) && $url->isCorrect()) {
1026 1019
1027 $this->action('add', $url, 0, TRUE); 1020 $this->action('add', $url, 0, TRUE);
1028 1021
1029 $count++; 1022 $count++;
1030 if ($favorite) { 1023 if ($favorite) {
1031 $last_id = $this->store->getLastId($sequence); 1024 $last_id = $this->store->getLastId($sequence);
@@ -1036,7 +1029,7 @@ class Poche
1036 $this->action('toggle_archive', $url, $last_id, TRUE); 1029 $this->action('toggle_archive', $url, $last_id, TRUE);
1037 } 1030 }
1038 } 1031 }
1039 1032
1040 } 1033 }
1041 1034
1042 unlink($targetFile); 1035 unlink($targetFile);
@@ -1047,37 +1040,115 @@ class Poche
1047 1040
1048 /** 1041 /**
1049 * import datas into your poche 1042 * import datas into your poche
1050 * @param string $from name of the service to import : pocket, instapaper or readability 1043 * @return boolean
1051 * @todo add the return value
1052 * @return boolean
1053 */ 1044 */
1054 public function import($from) 1045 public function import() {
1055 { 1046
1056 $providers = array( 1047 if ( isset($_FILES['file']) ) {
1057 'pocket' => 'importFromPocket', 1048 // assume, that file is in json format
1058 'readability' => 'importFromReadability', 1049 $str_data = file_get_contents($_FILES['file']['tmp_name']);
1059 'instapaper' => 'importFromInstapaper', 1050 $data = json_decode($str_data, true);
1060 'poche' => 'importFromPoche', 1051
1061 ); 1052 if ( $data === null ) {
1062 1053 //not json - assume html
1063 if (! isset($providers[$from])) { 1054 $html = new simple_html_dom();
1064 $this->messages->add('e', _('Unknown import provider.')); 1055 $html->load_file($_FILES['file']['tmp_name']);
1065 Tools::redirect(); 1056 $data = array();
1057 $read = 0;
1058 foreach (array('ol','ul') as $list) {
1059 foreach ($html->find($list) as $ul) {
1060 foreach ($ul->find('li') as $li) {
1061 $tmpEntry = array();
1062 $a = $li->find('a');
1063 $tmpEntry['url'] = $a[0]->href;
1064 $tmpEntry['tags'] = $a[0]->tags;
1065 $tmpEntry['is_read'] = $read;
1066 if ($tmpEntry['url']) {
1067 $data[] = $tmpEntry;
1068 }
1069 }
1070 # the second <ol/ul> is for read links
1071 $read = ((sizeof($data) && $read)?0:1);
1072 }
1073 }
1066 } 1074 }
1067 1075
1068 $targetFile = CACHE . '/' . constant(strtoupper($from) . '_FILE'); 1076 $i = 0; //counter for articles inserted
1069 1077 foreach ($data as $record) {
1070 if (! file_exists($targetFile)) { 1078 //echo '<pre>';
1071 $this->messages->add('e', _('Could not find required "' . $targetFile . '" import file.')); 1079 //var_dump($record);
1072 Tools::redirect(); 1080 // foreach ($record as $key=>$val) {
1081 // echo "\n=================\n$i: $key: $val\n";
1082 // }
1083 // exit;
1084
1085 $url = trim($record['url']);
1086 if ( $url ) {
1087 $title = (isset($record['title']) ? $record['title'] : _('Untitled - Import - ').'</a> <a href="./?import">'._('click to finish import').'</a><a>');
1088 $body = (isset($record['content']) ? $record['content'] : '');
1089 $isRead = (isset($record['is_read']) ? intval($record['is_read']) : 0);
1090 $isFavorite = (isset($record['is_fav']) ? intval($record['is_fav']) : 0);
1091 //insert new record
1092 $id = $this->store->add($url, $title, $body, $this->user->getId(), $isFavorite, $isRead);
1093 if ( $id ) {
1094 //increment no of records inserted
1095 $i++;
1096 if ( isset($record['tags']) && trim($record['tags']) ) {
1097 //@TODO: set tags
1098
1099 }
1100 }
1101 }
1102 }
1103
1104 if ( $i > 0 ) {
1105 $this->messages->add('s', _('Articles inserted: ').$i._('. Please note, that some may be marked as "read".'));
1073 } 1106 }
1074 1107 }
1075 $this->$providers[$from]($targetFile); 1108 //file parsing finished here
1109
1110 //now download article contents if any
1111
1112 //check if we need to download any content
1113 $recordsDownloadRequired = $this->store->retrieveUnfetchedEntriesCount($this->user->getId());
1114 if ( $recordsDownloadRequired == 0 ) {
1115 //nothing to download
1116 $this->messages->add('s', _('Import finished.'));
1117 Tools::redirect();
1118 }
1119 else {
1120 //if just inserted - don't download anything, download will start in next reload
1121 if ( !isset($_FILES['file']) ) {
1122 //download next batch
1123 $items = $this->store->retrieveUnfetchedEntries($this->user->getId(), IMPORT_LIMIT);
1124
1125 $config = HTMLPurifier_Config::createDefault();
1126 $config->set('Cache.SerializerPath', CACHE);
1127 $purifier = new HTMLPurifier($config);
1128
1129 foreach ($items as $item) {
1130 $url = new Url(base64_encode($item['url']));
1131 $content = Tools::getPageContent($url);
1132
1133 $title = (($content['rss']['channel']['item']['title'] != '') ? $content['rss']['channel']['item']['title'] : _('Untitled'));
1134 $body = (($content['rss']['channel']['item']['description'] != '') ? $content['rss']['channel']['item']['description'] : _('Undefined'));
1135
1136 //clean content to prevent xss attack
1137 $title = $purifier->purify($title);
1138 $body = $purifier->purify($body);
1139
1140 $this->store->updateContentAndTitle($item['id'], $title, $body, $this->user->getId());
1141 }
1142
1143 }
1144 }
1145
1146 return array('includeImport'=>true, 'import'=>array('recordsDownloadRequired'=>$recordsDownloadRequired, 'recordsUnderDownload'=> IMPORT_LIMIT, 'delay'=> IMPORT_DELAY * 1000) );
1076 } 1147 }
1077 1148
1078 public function uploadFile() { 1149 public function uploadFile() {
1079 if(isset($_FILES['file'])) 1150 if (isset($_FILES['file']))
1080 { 1151 {
1081 $dir = CACHE . '/'; 1152 $dir = CACHE . '/';
1082 $file = basename($_FILES['file']['name']); 1153 $file = basename($_FILES['file']['name']);
1083 if(move_uploaded_file($_FILES['file']['tmp_name'], $dir . $file)) { 1154 if(move_uploaded_file($_FILES['file']['tmp_name'], $dir . $file)) {
@@ -1087,7 +1158,7 @@ class Poche
1087 $this->messages->add('e', _('Error while importing file. Do you have access to upload it?')); 1158 $this->messages->add('e', _('Error while importing file. Do you have access to upload it?'));
1088 } 1159 }
1089 } 1160 }
1090 1161
1091 Tools::redirect('?view=config'); 1162 Tools::redirect('?view=config');
1092 } 1163 }
1093 1164
@@ -1099,7 +1170,7 @@ class Poche
1099 { 1170 {
1100 $filename = "wallabag-export-".$this->user->getId()."-".date("Y-m-d").".json"; 1171 $filename = "wallabag-export-".$this->user->getId()."-".date("Y-m-d").".json";
1101 header('Content-Disposition: attachment; filename='.$filename); 1172 header('Content-Disposition: attachment; filename='.$filename);
1102 1173
1103 $entries = $this->store->retrieveAll($this->user->getId()); 1174 $entries = $this->store->retrieveAll($this->user->getId());
1104 echo $this->tpl->render('export.twig', array( 1175 echo $this->tpl->render('export.twig', array(
1105 'export' => Tools::renderJson($entries), 1176 'export' => Tools::renderJson($entries),