diff options
Diffstat (limited to 'inc/poche/Poche.class.php')
-rw-r--r-- | inc/poche/Poche.class.php | 335 |
1 files changed, 255 insertions, 80 deletions
diff --git a/inc/poche/Poche.class.php b/inc/poche/Poche.class.php index 646193f7..18860ddc 100644 --- a/inc/poche/Poche.class.php +++ b/inc/poche/Poche.class.php | |||
@@ -10,77 +10,200 @@ | |||
10 | 10 | ||
11 | class Poche | 11 | class Poche |
12 | { | 12 | { |
13 | public static $canRenderTemplates = true; | ||
14 | public static $configFileAvailable = true; | ||
15 | |||
13 | public $user; | 16 | public $user; |
14 | public $store; | 17 | public $store; |
15 | public $tpl; | 18 | public $tpl; |
16 | public $messages; | 19 | public $messages; |
17 | public $pagination; | 20 | public $pagination; |
18 | 21 | ||
19 | function __construct() | 22 | private $currentTheme = ''; |
23 | private $notInstalledMessage = ''; | ||
24 | |||
25 | # @todo make this dynamic (actually install themes and save them in the database including author information et cetera) | ||
26 | private $installedThemes = array( | ||
27 | 'default' => array('requires' => array()), | ||
28 | 'dark' => array('requires' => array('default')), | ||
29 | 'dmagenta' => array('requires' => array('default')), | ||
30 | 'solarized' => array('requires' => array('default')), | ||
31 | 'solarized-dark' => array('requires' => array('default')) | ||
32 | ); | ||
33 | |||
34 | public function __construct() | ||
20 | { | 35 | { |
36 | if (! $this->configFileIsAvailable()) { | ||
37 | return; | ||
38 | } | ||
39 | |||
40 | $this->init(); | ||
41 | |||
42 | if (! $this->themeIsInstalled()) { | ||
43 | return; | ||
44 | } | ||
45 | |||
21 | $this->initTpl(); | 46 | $this->initTpl(); |
22 | if (!$this->checkBeforeInstall()) { | 47 | |
23 | exit; | 48 | if (! $this->systemIsInstalled()) { |
49 | return; | ||
24 | } | 50 | } |
51 | |||
25 | $this->store = new Database(); | 52 | $this->store = new Database(); |
26 | $this->init(); | ||
27 | $this->messages = new Messages(); | 53 | $this->messages = new Messages(); |
28 | 54 | ||
29 | # installation | 55 | # installation |
30 | if(!$this->store->isInstalled()) | 56 | if (! $this->store->isInstalled()) { |
31 | { | ||
32 | $this->install(); | 57 | $this->install(); |
33 | } | 58 | } |
34 | } | 59 | } |
60 | |||
61 | private function init() | ||
62 | { | ||
63 | Tools::initPhp(); | ||
64 | Session::$sessionName = 'poche'; | ||
65 | Session::init(); | ||
35 | 66 | ||
67 | if (isset($_SESSION['poche_user']) && $_SESSION['poche_user'] != array()) { | ||
68 | $this->user = $_SESSION['poche_user']; | ||
69 | } else { | ||
70 | # fake user, just for install & login screens | ||
71 | $this->user = new User(); | ||
72 | $this->user->setConfig($this->getDefaultConfig()); | ||
73 | } | ||
74 | |||
75 | # l10n | ||
76 | $language = $this->user->getConfigValue('language'); | ||
77 | putenv('LC_ALL=' . $language); | ||
78 | setlocale(LC_ALL, $language); | ||
79 | bindtextdomain($language, LOCALE); | ||
80 | textdomain($language); | ||
81 | |||
82 | # Pagination | ||
83 | $this->pagination = new Paginator($this->user->getConfigValue('pager'), 'p'); | ||
84 | |||
85 | # Set up theme | ||
86 | $themeDirectory = $this->user->getConfigValue('theme'); | ||
87 | |||
88 | if ($themeDirectory === false) { | ||
89 | $themeDirectory = DEFAULT_THEME; | ||
90 | } | ||
91 | |||
92 | $this->currentTheme = $themeDirectory; | ||
93 | } | ||
94 | |||
95 | public function configFileIsAvailable() { | ||
96 | if (! self::$configFileAvailable) { | ||
97 | $this->notInstalledMessage = 'You have to rename <strong>inc/poche/config.inc.php.new</strong> to <strong>inc/poche/config.inc.php</strong>.'; | ||
98 | |||
99 | return false; | ||
100 | } | ||
101 | |||
102 | return true; | ||
103 | } | ||
104 | |||
105 | public function themeIsInstalled() { | ||
106 | # Twig is an absolute requirement for Poche to function. Abort immediately if the Composer installer hasn't been run yet | ||
107 | if (! self::$canRenderTemplates) { | ||
108 | $this->notInstalledMessage = 'Twig does not seem to be installed. Please initialize the Composer installation to automatically fetch dependencies. Have a look at <a href="http://inthepoche.com/?pages/Documentation">the documentation.</a>'; | ||
109 | |||
110 | return false; | ||
111 | } | ||
112 | |||
113 | # Check if the selected theme and its requirements are present | ||
114 | if (! is_dir(THEME . '/' . $this->getTheme())) { | ||
115 | $this->notInstalledMessage = 'The currently selected theme (' . $this->getTheme() . ') does not seem to be properly installed (Missing directory: ' . THEME . '/' . $this->getTheme() . ')'; | ||
116 | |||
117 | self::$canRenderTemplates = false; | ||
118 | |||
119 | return false; | ||
120 | } | ||
121 | |||
122 | foreach ($this->installedThemes[$this->getTheme()]['requires'] as $requiredTheme) { | ||
123 | if (! is_dir(THEME . '/' . $requiredTheme)) { | ||
124 | $this->notInstalledMessage = 'The required "' . $requiredTheme . '" theme is missing for the current theme (' . $this->getTheme() . ')'; | ||
125 | |||
126 | self::$canRenderTemplates = false; | ||
127 | |||
128 | return false; | ||
129 | } | ||
130 | } | ||
131 | |||
132 | return true; | ||
133 | } | ||
134 | |||
36 | /** | 135 | /** |
37 | * all checks before installation. | 136 | * all checks before installation. |
137 | * @todo move HTML to template | ||
38 | * @return boolean | 138 | * @return boolean |
39 | */ | 139 | */ |
40 | private function checkBeforeInstall() | 140 | public function systemIsInstalled() |
41 | { | 141 | { |
42 | $msg = ''; | 142 | $msg = ''; |
43 | $allIsGood = TRUE; | 143 | |
44 | 144 | $configSalt = defined('SALT') ? constant('SALT') : ''; | |
45 | if (!is_writable(CACHE)) { | 145 | |
146 | if (empty($configSalt)) { | ||
147 | $msg = '<h1>error</h1><p>You have not yet filled in the SALT value in the config.inc.php file.</p>'; | ||
148 | } else if (! is_writable(CACHE)) { | ||
46 | Tools::logm('you don\'t have write access on cache directory'); | 149 | Tools::logm('you don\'t have write access on cache directory'); |
47 | die('You don\'t have write access on cache directory.'); | 150 | $msg = '<h1>error</h1><p>You don\'t have write access on cache directory.</p>'; |
48 | } | 151 | } else if (STORAGE == 'sqlite' && ! file_exists(STORAGE_SQLITE)) { |
49 | else if (file_exists('./install/update.php') && !DEBUG_POCHE) { | 152 | Tools::logm('sqlite file doesn\'t exist'); |
153 | $msg = '<h1>error</h1><p>sqlite file doesn\'t exist, you can find it in install folder. Copy it in /db folder.</p>'; | ||
154 | } else if (file_exists(ROOT . '/install/update.php') && ! DEBUG_POCHE) { | ||
50 | $msg = '<h1>setup</h1><p><strong>It\'s your first time here?</strong> Please copy /install/poche.sqlite in db folder. Then, delete install folder.<br /><strong>If you have already installed poche</strong>, an update is needed <a href="install/update.php">by clicking here</a>.</p>'; | 155 | $msg = '<h1>setup</h1><p><strong>It\'s your first time here?</strong> Please copy /install/poche.sqlite in db folder. Then, delete install folder.<br /><strong>If you have already installed poche</strong>, an update is needed <a href="install/update.php">by clicking here</a>.</p>'; |
51 | $allIsGood = FALSE; | 156 | } else if (is_dir(ROOT . '/install') && ! DEBUG_POCHE) { |
52 | } | ||
53 | else if (file_exists('./install') && !DEBUG_POCHE) { | ||
54 | $msg = '<h1>setup</h1><p><strong>If you want to update your poche</strong>, you just have to delete /install folder. <br /><strong>To install your poche with sqlite</strong>, copy /install/poche.sqlite in /db and delete the folder /install. you have to delete the /install folder before using poche.</p>'; | 157 | $msg = '<h1>setup</h1><p><strong>If you want to update your poche</strong>, you just have to delete /install folder. <br /><strong>To install your poche with sqlite</strong>, copy /install/poche.sqlite in /db and delete the folder /install. you have to delete the /install folder before using poche.</p>'; |
55 | $allIsGood = FALSE; | 158 | } else if (STORAGE == 'sqlite' && ! is_writable(STORAGE_SQLITE)) { |
56 | } | ||
57 | else if (STORAGE == 'sqlite' && !is_writable(STORAGE_SQLITE)) { | ||
58 | Tools::logm('you don\'t have write access on sqlite file'); | 159 | Tools::logm('you don\'t have write access on sqlite file'); |
59 | $msg = '<h1>error</h1><p>You don\'t have write access on sqlite file.</p>'; | 160 | $msg = '<h1>error</h1><p>You don\'t have write access on sqlite file.</p>'; |
60 | $allIsGood = FALSE; | ||
61 | } | 161 | } |
62 | 162 | ||
63 | if (!$allIsGood) { | 163 | if (! empty($msg)) { |
64 | echo $this->tpl->render('error.twig', array( | 164 | $this->notInstalledMessage = $msg; |
65 | 'msg' => $msg | 165 | |
66 | )); | 166 | return false; |
67 | } | 167 | } |
68 | 168 | ||
69 | return $allIsGood; | 169 | return true; |
170 | } | ||
171 | |||
172 | public function getNotInstalledMessage() { | ||
173 | return $this->notInstalledMessage; | ||
70 | } | 174 | } |
71 | 175 | ||
72 | private function initTpl() | 176 | private function initTpl() |
73 | { | 177 | { |
74 | # template engine | 178 | $loaderChain = new Twig_Loader_Chain(); |
75 | $loader = new Twig_Loader_Filesystem(TPL); | 179 | |
180 | # add the current theme as first to the loader chain so Twig will look there first for overridden template files | ||
181 | try { | ||
182 | $loaderChain->addLoader(new Twig_Loader_Filesystem(THEME . '/' . $this->getTheme())); | ||
183 | } catch (Twig_Error_Loader $e) { | ||
184 | # @todo isInstalled() should catch this, inject Twig later | ||
185 | die('The currently selected theme (' . $this->getTheme() . ') does not seem to be properly installed (' . THEME . '/' . $this->getTheme() .' is missing)'); | ||
186 | } | ||
187 | |||
188 | # add all required themes to the loader chain | ||
189 | foreach ($this->installedThemes[$this->getTheme()]['requires'] as $requiredTheme) { | ||
190 | try { | ||
191 | $loaderChain->addLoader(new Twig_Loader_Filesystem(THEME . '/' . DEFAULT_THEME)); | ||
192 | } catch (Twig_Error_Loader $e) { | ||
193 | # @todo isInstalled() should catch this, inject Twig later | ||
194 | die('The required "' . $requiredTheme . '" theme is missing for the current theme (' . $this->getTheme() . ')'); | ||
195 | } | ||
196 | } | ||
197 | |||
76 | if (DEBUG_POCHE) { | 198 | if (DEBUG_POCHE) { |
77 | $twig_params = array(); | 199 | $twig_params = array(); |
78 | } | 200 | } else { |
79 | else { | ||
80 | $twig_params = array('cache' => CACHE); | 201 | $twig_params = array('cache' => CACHE); |
81 | } | 202 | } |
82 | $this->tpl = new Twig_Environment($loader, $twig_params); | 203 | |
204 | $this->tpl = new Twig_Environment($loaderChain, $twig_params); | ||
83 | $this->tpl->addExtension(new Twig_Extensions_Extension_I18n()); | 205 | $this->tpl->addExtension(new Twig_Extensions_Extension_I18n()); |
206 | |||
84 | # filter to display domain name of an url | 207 | # filter to display domain name of an url |
85 | $filter = new Twig_SimpleFilter('getDomain', 'Tools::getDomain'); | 208 | $filter = new Twig_SimpleFilter('getDomain', 'Tools::getDomain'); |
86 | $this->tpl->addFilter($filter); | 209 | $this->tpl->addFilter($filter); |
@@ -88,38 +211,19 @@ class Poche | |||
88 | # filter for reading time | 211 | # filter for reading time |
89 | $filter = new Twig_SimpleFilter('getReadingTime', 'Tools::getReadingTime'); | 212 | $filter = new Twig_SimpleFilter('getReadingTime', 'Tools::getReadingTime'); |
90 | $this->tpl->addFilter($filter); | 213 | $this->tpl->addFilter($filter); |
91 | } | 214 | |
92 | 215 | # filter for simple filenames in config view | |
93 | private function init() | 216 | $filter = new Twig_SimpleFilter('getPrettyFilename', function($string) { return str_replace(ROOT, '', $string); }); |
94 | { | 217 | $this->tpl->addFilter($filter); |
95 | Tools::initPhp(); | ||
96 | Session::init(); | ||
97 | |||
98 | if (isset($_SESSION['poche_user']) && $_SESSION['poche_user'] != array()) { | ||
99 | $this->user = $_SESSION['poche_user']; | ||
100 | } | ||
101 | else { | ||
102 | # fake user, just for install & login screens | ||
103 | $this->user = new User(); | ||
104 | $this->user->setConfig($this->getDefaultConfig()); | ||
105 | } | ||
106 | |||
107 | # l10n | ||
108 | $language = $this->user->getConfigValue('language'); | ||
109 | putenv('LC_ALL=' . $language); | ||
110 | setlocale(LC_ALL, $language); | ||
111 | bindtextdomain($language, LOCALE); | ||
112 | textdomain($language); | ||
113 | |||
114 | # Pagination | ||
115 | $this->pagination = new Paginator($this->user->getConfigValue('pager'), 'p'); | ||
116 | } | 218 | } |
117 | 219 | ||
118 | private function install() | 220 | private function install() |
119 | { | 221 | { |
120 | Tools::logm('poche still not installed'); | 222 | Tools::logm('poche still not installed'); |
121 | echo $this->tpl->render('install.twig', array( | 223 | echo $this->tpl->render('install.twig', array( |
122 | 'token' => Session::getToken() | 224 | 'token' => Session::getToken(), |
225 | 'theme' => $this->getTheme(), | ||
226 | 'poche_url' => Tools::getPocheUrl() | ||
123 | )); | 227 | )); |
124 | if (isset($_GET['install'])) { | 228 | if (isset($_GET['install'])) { |
125 | if (($_POST['password'] == $_POST['password_repeat']) | 229 | if (($_POST['password'] == $_POST['password_repeat']) |
@@ -139,13 +243,41 @@ class Poche | |||
139 | } | 243 | } |
140 | exit(); | 244 | exit(); |
141 | } | 245 | } |
246 | |||
247 | public function getTheme() { | ||
248 | return $this->currentTheme; | ||
249 | } | ||
250 | |||
251 | public function getInstalledThemes() { | ||
252 | $handle = opendir(THEME); | ||
253 | $themes = array(); | ||
254 | |||
255 | while (($theme = readdir($handle)) !== false) { | ||
256 | # Themes are stored in a directory, so all directory names are themes | ||
257 | # @todo move theme installation data to database | ||
258 | if (! is_dir(THEME . '/' . $theme) || in_array($theme, array('..', '.'))) { | ||
259 | continue; | ||
260 | } | ||
261 | |||
262 | $current = false; | ||
263 | |||
264 | if ($theme === $this->getTheme()) { | ||
265 | $current = true; | ||
266 | } | ||
267 | |||
268 | $themes[] = array('name' => $theme, 'current' => $current); | ||
269 | } | ||
270 | |||
271 | return $themes; | ||
272 | } | ||
142 | 273 | ||
143 | public function getDefaultConfig() | 274 | public function getDefaultConfig() |
144 | { | 275 | { |
145 | return array( | 276 | return array( |
146 | 'pager' => PAGINATION, | 277 | 'pager' => PAGINATION, |
147 | 'language' => LANG, | 278 | 'language' => LANG, |
148 | ); | 279 | 'theme' => DEFAULT_THEME |
280 | ); | ||
149 | } | 281 | } |
150 | 282 | ||
151 | /** | 283 | /** |
@@ -166,7 +298,7 @@ class Poche | |||
166 | } | 298 | } |
167 | $last_id = $this->store->getLastId($sequence); | 299 | $last_id = $this->store->getLastId($sequence); |
168 | if (DOWNLOAD_PICTURES) { | 300 | if (DOWNLOAD_PICTURES) { |
169 | $content = filtre_picture($parametres_url['body'], $url->getUrl(), $last_id); | 301 | $content = filtre_picture($content['body'], $url->getUrl(), $last_id); |
170 | Tools::logm('updating content article'); | 302 | Tools::logm('updating content article'); |
171 | $this->store->updateContent($last_id, $content, $this->user->getId()); | 303 | $this->store->updateContent($last_id, $content, $this->user->getId()); |
172 | } | 304 | } |
@@ -182,7 +314,7 @@ class Poche | |||
182 | } | 314 | } |
183 | 315 | ||
184 | if (!$import) { | 316 | if (!$import) { |
185 | Tools::redirect(); | 317 | Tools::redirect('?view=home'); |
186 | } | 318 | } |
187 | break; | 319 | break; |
188 | case 'delete': | 320 | case 'delete': |
@@ -230,7 +362,9 @@ class Poche | |||
230 | $prod = $this->getPocheVersion('prod'); | 362 | $prod = $this->getPocheVersion('prod'); |
231 | $compare_dev = version_compare(POCHE_VERSION, $dev); | 363 | $compare_dev = version_compare(POCHE_VERSION, $dev); |
232 | $compare_prod = version_compare(POCHE_VERSION, $prod); | 364 | $compare_prod = version_compare(POCHE_VERSION, $prod); |
365 | $themes = $this->getInstalledThemes(); | ||
233 | $tpl_vars = array( | 366 | $tpl_vars = array( |
367 | 'themes' => $themes, | ||
234 | 'dev' => $dev, | 368 | 'dev' => $dev, |
235 | 'prod' => $prod, | 369 | 'prod' => $prod, |
236 | 'compare_dev' => $compare_dev, | 370 | 'compare_dev' => $compare_dev, |
@@ -247,25 +381,37 @@ class Poche | |||
247 | $tidy = tidy_parse_string($content, array('indent'=>true, 'show-body-only' => true), 'UTF8'); | 381 | $tidy = tidy_parse_string($content, array('indent'=>true, 'show-body-only' => true), 'UTF8'); |
248 | $tidy->cleanRepair(); | 382 | $tidy->cleanRepair(); |
249 | $content = $tidy->value; | 383 | $content = $tidy->value; |
250 | } | 384 | |
251 | $tpl_vars = array( | 385 | # flattr checking |
386 | $flattr = new FlattrItem(); | ||
387 | $flattr->checkItem($entry['url']); | ||
388 | |||
389 | $tpl_vars = array( | ||
252 | 'entry' => $entry, | 390 | 'entry' => $entry, |
253 | 'content' => $content, | 391 | 'content' => $content, |
254 | ); | 392 | 'flattr' => $flattr |
393 | ); | ||
394 | } | ||
255 | } | 395 | } |
256 | else { | 396 | else { |
257 | Tools::logm('error in view call : entry is null'); | 397 | Tools::logm('error in view call : entry is null'); |
258 | } | 398 | } |
259 | break; | 399 | break; |
260 | default: # home view | 400 | default: # home, favorites and archive views |
261 | $entries = $this->store->getEntriesByView($view, $this->user->getId()); | 401 | $entries = $this->store->getEntriesByView($view, $this->user->getId()); |
262 | $this->pagination->set_total(count($entries)); | ||
263 | $page_links = $this->pagination->page_links('?view=' . $view . '&sort=' . $_SESSION['sort'] . '&'); | ||
264 | $datas = $this->store->getEntriesByView($view, $this->user->getId(), $this->pagination->get_limit()); | ||
265 | $tpl_vars = array( | 402 | $tpl_vars = array( |
266 | 'entries' => $datas, | 403 | 'entries' => '', |
267 | 'page_links' => $page_links, | 404 | 'page_links' => '', |
405 | 'nb_results' => '', | ||
268 | ); | 406 | ); |
407 | if (count($entries) > 0) { | ||
408 | $this->pagination->set_total(count($entries)); | ||
409 | $page_links = $this->pagination->page_links('?view=' . $view . '&sort=' . $_SESSION['sort'] . '&'); | ||
410 | $datas = $this->store->getEntriesByView($view, $this->user->getId(), $this->pagination->get_limit()); | ||
411 | $tpl_vars['entries'] = $datas; | ||
412 | $tpl_vars['page_links'] = $page_links; | ||
413 | $tpl_vars['nb_results'] = count($entries); | ||
414 | } | ||
269 | Tools::logm('display ' . $view . ' view'); | 415 | Tools::logm('display ' . $view . ' view'); |
270 | break; | 416 | break; |
271 | } | 417 | } |
@@ -303,6 +449,44 @@ class Poche | |||
303 | } | 449 | } |
304 | } | 450 | } |
305 | } | 451 | } |
452 | |||
453 | public function updateTheme() | ||
454 | { | ||
455 | # no data | ||
456 | if (empty($_POST['theme'])) { | ||
457 | } | ||
458 | |||
459 | # we are not going to change it to the current theme... | ||
460 | if ($_POST['theme'] == $this->getTheme()) { | ||
461 | $this->messages->add('w', _('still using the "' . $this->getTheme() . '" theme!')); | ||
462 | Tools::redirect('?view=config'); | ||
463 | } | ||
464 | |||
465 | $themes = $this->getInstalledThemes(); | ||
466 | $actualTheme = false; | ||
467 | |||
468 | foreach ($themes as $theme) { | ||
469 | if ($theme['name'] == $_POST['theme']) { | ||
470 | $actualTheme = true; | ||
471 | break; | ||
472 | } | ||
473 | } | ||
474 | |||
475 | if (! $actualTheme) { | ||
476 | $this->messages->add('e', _('that theme does not seem to be installed')); | ||
477 | Tools::redirect('?view=config'); | ||
478 | } | ||
479 | |||
480 | $this->store->updateUserConfig($this->user->getId(), 'theme', $_POST['theme']); | ||
481 | $this->messages->add('s', _('you have changed your theme preferences')); | ||
482 | |||
483 | $currentConfig = $_SESSION['poche_user']->config; | ||
484 | $currentConfig['theme'] = $_POST['theme']; | ||
485 | |||
486 | $_SESSION['poche_user']->setConfig($currentConfig); | ||
487 | |||
488 | Tools::redirect('?view=config'); | ||
489 | } | ||
306 | 490 | ||
307 | /** | 491 | /** |
308 | * checks if login & password are correct and save the user in session. | 492 | * checks if login & password are correct and save the user in session. |
@@ -318,16 +502,7 @@ class Poche | |||
318 | if ($user != array()) { | 502 | if ($user != array()) { |
319 | # Save login into Session | 503 | # Save login into Session |
320 | Session::login($user['username'], $user['password'], $_POST['login'], Tools::encodeString($_POST['password'] . $_POST['login']), array('poche_user' => new User($user))); | 504 | Session::login($user['username'], $user['password'], $_POST['login'], Tools::encodeString($_POST['password'] . $_POST['login']), array('poche_user' => new User($user))); |
321 | |||
322 | $this->messages->add('s', _('welcome to your poche')); | 505 | $this->messages->add('s', _('welcome to your poche')); |
323 | if (!empty($_POST['longlastingsession'])) { | ||
324 | $_SESSION['longlastingsession'] = 31536000; | ||
325 | $_SESSION['expires_on'] = time() + $_SESSION['longlastingsession']; | ||
326 | session_set_cookie_params($_SESSION['longlastingsession']); | ||
327 | } else { | ||
328 | session_set_cookie_params(0); | ||
329 | } | ||
330 | session_regenerate_id(true); | ||
331 | Tools::logm('login successful'); | 506 | Tools::logm('login successful'); |
332 | Tools::redirect($referer); | 507 | Tools::redirect($referer); |
333 | } | 508 | } |