aboutsummaryrefslogtreecommitdiffhomepage
path: root/application
diff options
context:
space:
mode:
Diffstat (limited to 'application')
-rw-r--r--application/ApplicationUtils.php75
-rw-r--r--application/FileUtils.php8
-rw-r--r--application/History.php12
-rw-r--r--application/Languages.php1
-rw-r--r--application/Router.php43
-rw-r--r--application/Thumbnailer.php2
-rw-r--r--application/api/ApiMiddleware.php5
-rw-r--r--application/api/ApiUtils.php6
-rw-r--r--application/api/controllers/ApiController.php7
-rw-r--r--application/api/controllers/HistoryController.php (renamed from application/api/controllers/History.php)2
-rw-r--r--application/api/controllers/Tags.php1
-rw-r--r--application/api/exceptions/ApiLinkNotFoundException.php2
-rw-r--r--application/api/exceptions/ApiTagNotFoundException.php2
-rw-r--r--application/bookmark/LinkDB.php (renamed from application/LinkDB.php)61
-rw-r--r--application/bookmark/LinkFilter.php (renamed from application/LinkFilter.php)42
-rw-r--r--application/bookmark/LinkUtils.php (renamed from application/LinkUtils.php)6
-rw-r--r--application/bookmark/exception/LinkNotFoundException.php15
-rw-r--r--application/config/ConfigJson.php2
-rw-r--r--application/config/ConfigManager.php2
-rw-r--r--application/config/ConfigPhp.php4
-rw-r--r--application/exceptions/IOException.php5
-rw-r--r--application/feed/Cache.php (renamed from application/Cache.php)0
-rw-r--r--application/feed/CachedPage.php (renamed from application/CachedPage.php)5
-rw-r--r--application/feed/FeedBuilder.php (renamed from application/FeedBuilder.php)41
-rw-r--r--application/http/Base64Url.php (renamed from application/Base64Url.php)2
-rw-r--r--application/http/HttpUtils.php (renamed from application/HttpUtils.php)5
-rw-r--r--application/http/Url.php (renamed from application/Url.php)97
-rw-r--r--application/http/UrlUtils.php88
-rw-r--r--application/netscape/NetscapeBookmarkUtils.php (renamed from application/NetscapeBookmarkUtils.php)31
-rw-r--r--application/plugin/PluginManager.php (renamed from application/PluginManager.php)39
-rw-r--r--application/plugin/exception/PluginFileNotFoundException.php23
-rw-r--r--application/render/PageBuilder.php (renamed from application/PageBuilder.php)20
-rw-r--r--application/render/ThemeUtils.php (renamed from application/ThemeUtils.php)2
-rw-r--r--application/updater/Updater.php (renamed from application/Updater.php)138
-rw-r--r--application/updater/UpdaterUtils.php39
-rw-r--r--application/updater/exception/UpdaterException.php60
36 files changed, 493 insertions, 400 deletions
diff --git a/application/ApplicationUtils.php b/application/ApplicationUtils.php
index a3b2dcb1..7fe3cb32 100644
--- a/application/ApplicationUtils.php
+++ b/application/ApplicationUtils.php
@@ -1,4 +1,9 @@
1<?php 1<?php
2namespace Shaarli;
3
4use Exception;
5use Shaarli\Config\ConfigManager;
6
2/** 7/**
3 * Shaarli (application) utilities 8 * Shaarli (application) utilities
4 */ 9 */
@@ -51,7 +56,7 @@ class ApplicationUtils
51 return false; 56 return false;
52 } 57 }
53 } else { 58 } else {
54 if (! is_file($remote)) { 59 if (!is_file($remote)) {
55 return false; 60 return false;
56 } 61 }
57 $data = file_get_contents($remote); 62 $data = file_get_contents($remote);
@@ -97,7 +102,7 @@ class ApplicationUtils
97 // Do not check versions for visitors 102 // Do not check versions for visitors
98 // Do not check if the user doesn't want to 103 // Do not check if the user doesn't want to
99 // Do not check with dev version 104 // Do not check with dev version
100 if (! $isLoggedIn || empty($enableCheck) || $currentVersion === 'dev') { 105 if (!$isLoggedIn || empty($enableCheck) || $currentVersion === 'dev') {
101 return false; 106 return false;
102 } 107 }
103 108
@@ -111,7 +116,7 @@ class ApplicationUtils
111 return false; 116 return false;
112 } 117 }
113 118
114 if (! in_array($branch, self::$GIT_BRANCHES)) { 119 if (!in_array($branch, self::$GIT_BRANCHES)) {
115 throw new Exception( 120 throw new Exception(
116 'Invalid branch selected for updates: "' . $branch . '"' 121 'Invalid branch selected for updates: "' . $branch . '"'
117 ); 122 );
@@ -123,7 +128,7 @@ class ApplicationUtils
123 self::$GIT_URL . '/' . $branch . '/' . self::$VERSION_FILE 128 self::$GIT_URL . '/' . $branch . '/' . self::$VERSION_FILE
124 ); 129 );
125 130
126 if (! $latestVersion) { 131 if (!$latestVersion) {
127 // Only update the file's modification date 132 // Only update the file's modification date
128 file_put_contents($updateFile, $currentVersion); 133 file_put_contents($updateFile, $currentVersion);
129 return false; 134 return false;
@@ -152,9 +157,9 @@ class ApplicationUtils
152 if (version_compare($curVersion, $minVersion) < 0) { 157 if (version_compare($curVersion, $minVersion) < 0) {
153 $msg = t( 158 $msg = t(
154 'Your PHP version is obsolete!' 159 'Your PHP version is obsolete!'
155 . ' Shaarli requires at least PHP %s, and thus cannot run.' 160 . ' Shaarli requires at least PHP %s, and thus cannot run.'
156 . ' Your PHP version has known security vulnerabilities and should be' 161 . ' Your PHP version has known security vulnerabilities and should be'
157 . ' updated as soon as possible.' 162 . ' updated as soon as possible.'
158 ); 163 );
159 throw new Exception(sprintf($msg, $minVersion)); 164 throw new Exception(sprintf($msg, $minVersion));
160 } 165 }
@@ -174,50 +179,50 @@ class ApplicationUtils
174 179
175 // Check script and template directories are readable 180 // Check script and template directories are readable
176 foreach (array( 181 foreach (array(
177 'application', 182 'application',
178 'inc', 183 'inc',
179 'plugins', 184 'plugins',
180 $rainTplDir, 185 $rainTplDir,
181 $rainTplDir.'/'.$conf->get('resource.theme'), 186 $rainTplDir . '/' . $conf->get('resource.theme'),
182 ) as $path) { 187 ) as $path) {
183 if (! is_readable(realpath($path))) { 188 if (!is_readable(realpath($path))) {
184 $errors[] = '"'.$path.'" '. t('directory is not readable'); 189 $errors[] = '"' . $path . '" ' . t('directory is not readable');
185 } 190 }
186 } 191 }
187 192
188 // Check cache and data directories are readable and writable 193 // Check cache and data directories are readable and writable
189 foreach (array( 194 foreach (array(
190 $conf->get('resource.thumbnails_cache'), 195 $conf->get('resource.thumbnails_cache'),
191 $conf->get('resource.data_dir'), 196 $conf->get('resource.data_dir'),
192 $conf->get('resource.page_cache'), 197 $conf->get('resource.page_cache'),
193 $conf->get('resource.raintpl_tmp'), 198 $conf->get('resource.raintpl_tmp'),
194 ) as $path) { 199 ) as $path) {
195 if (! is_readable(realpath($path))) { 200 if (!is_readable(realpath($path))) {
196 $errors[] = '"'.$path.'" '. t('directory is not readable'); 201 $errors[] = '"' . $path . '" ' . t('directory is not readable');
197 } 202 }
198 if (! is_writable(realpath($path))) { 203 if (!is_writable(realpath($path))) {
199 $errors[] = '"'.$path.'" '. t('directory is not writable'); 204 $errors[] = '"' . $path . '" ' . t('directory is not writable');
200 } 205 }
201 } 206 }
202 207
203 // Check configuration files are readable and writable 208 // Check configuration files are readable and writable
204 foreach (array( 209 foreach (array(
205 $conf->getConfigFileExt(), 210 $conf->getConfigFileExt(),
206 $conf->get('resource.datastore'), 211 $conf->get('resource.datastore'),
207 $conf->get('resource.ban_file'), 212 $conf->get('resource.ban_file'),
208 $conf->get('resource.log'), 213 $conf->get('resource.log'),
209 $conf->get('resource.update_check'), 214 $conf->get('resource.update_check'),
210 ) as $path) { 215 ) as $path) {
211 if (! is_file(realpath($path))) { 216 if (!is_file(realpath($path))) {
212 # the file may not exist yet 217 # the file may not exist yet
213 continue; 218 continue;
214 } 219 }
215 220
216 if (! is_readable(realpath($path))) { 221 if (!is_readable(realpath($path))) {
217 $errors[] = '"'.$path.'" '. t('file is not readable'); 222 $errors[] = '"' . $path . '" ' . t('file is not readable');
218 } 223 }
219 if (! is_writable(realpath($path))) { 224 if (!is_writable(realpath($path))) {
220 $errors[] = '"'.$path.'" '. t('file is not writable'); 225 $errors[] = '"' . $path . '" ' . t('file is not writable');
221 } 226 }
222 } 227 }
223 228
diff --git a/application/FileUtils.php b/application/FileUtils.php
index b89ea12b..30560bfc 100644
--- a/application/FileUtils.php
+++ b/application/FileUtils.php
@@ -1,6 +1,8 @@
1<?php 1<?php
2 2
3require_once 'exceptions/IOException.php'; 3namespace Shaarli;
4
5use Shaarli\Exceptions\IOException;
4 6
5/** 7/**
6 * Class FileUtils 8 * Class FileUtils
@@ -44,7 +46,7 @@ class FileUtils
44 46
45 return file_put_contents( 47 return file_put_contents(
46 $file, 48 $file,
47 self::$phpPrefix.base64_encode(gzdeflate(serialize($content))).self::$phpSuffix 49 self::$phpPrefix . base64_encode(gzdeflate(serialize($content))) . self::$phpSuffix
48 ); 50 );
49 } 51 }
50 52
@@ -62,7 +64,7 @@ class FileUtils
62 { 64 {
63 // Note that gzinflate is faster than gzuncompress. 65 // Note that gzinflate is faster than gzuncompress.
64 // See: http://www.php.net/manual/en/function.gzdeflate.php#96439 66 // See: http://www.php.net/manual/en/function.gzdeflate.php#96439
65 if (! is_readable($file)) { 67 if (!is_readable($file)) {
66 return $default; 68 return $default;
67 } 69 }
68 70
diff --git a/application/History.php b/application/History.php
index 35ec016a..a5846652 100644
--- a/application/History.php
+++ b/application/History.php
@@ -1,4 +1,8 @@
1<?php 1<?php
2namespace Shaarli;
3
4use DateTime;
5use Exception;
2 6
3/** 7/**
4 * Class History 8 * Class History
@@ -66,7 +70,7 @@ class History
66 * History constructor. 70 * History constructor.
67 * 71 *
68 * @param string $historyFilePath History file path. 72 * @param string $historyFilePath History file path.
69 * @param int $retentionTime History content rentention time in seconds. 73 * @param int $retentionTime History content retention time in seconds.
70 * 74 *
71 * @throws Exception if something goes wrong. 75 * @throws Exception if something goes wrong.
72 */ 76 */
@@ -166,11 +170,11 @@ class History
166 */ 170 */
167 protected function check() 171 protected function check()
168 { 172 {
169 if (! is_file($this->historyFilePath)) { 173 if (!is_file($this->historyFilePath)) {
170 FileUtils::writeFlatDB($this->historyFilePath, []); 174 FileUtils::writeFlatDB($this->historyFilePath, []);
171 } 175 }
172 176
173 if (! is_writable($this->historyFilePath)) { 177 if (!is_writable($this->historyFilePath)) {
174 throw new Exception(t('History file isn\'t readable or writable')); 178 throw new Exception(t('History file isn\'t readable or writable'));
175 } 179 }
176 } 180 }
@@ -191,7 +195,7 @@ class History
191 */ 195 */
192 protected function write() 196 protected function write()
193 { 197 {
194 $comparaison = new DateTime('-'. $this->retentionTime . ' seconds'); 198 $comparaison = new DateTime('-' . $this->retentionTime . ' seconds');
195 foreach ($this->history as $key => $value) { 199 foreach ($this->history as $key => $value) {
196 if ($value['datetime'] < $comparaison) { 200 if ($value['datetime'] < $comparaison) {
197 unset($this->history[$key]); 201 unset($this->history[$key]);
diff --git a/application/Languages.php b/application/Languages.php
index b9c5d0e8..5cda802e 100644
--- a/application/Languages.php
+++ b/application/Languages.php
@@ -3,7 +3,6 @@
3namespace Shaarli; 3namespace Shaarli;
4 4
5use Gettext\GettextTranslator; 5use Gettext\GettextTranslator;
6use Gettext\Merge;
7use Gettext\Translations; 6use Gettext\Translations;
8use Gettext\Translator; 7use Gettext\Translator;
9use Gettext\TranslatorInterface; 8use Gettext\TranslatorInterface;
diff --git a/application/Router.php b/application/Router.php
index beb3165b..05877acd 100644
--- a/application/Router.php
+++ b/application/Router.php
@@ -1,4 +1,5 @@
1<?php 1<?php
2namespace Shaarli;
2 3
3/** 4/**
4 * Class Router 5 * Class Router
@@ -75,43 +76,43 @@ class Router
75 return self::$PAGE_LINKLIST; 76 return self::$PAGE_LINKLIST;
76 } 77 }
77 78
78 if (startsWith($query, 'do='. self::$PAGE_LOGIN) && $loggedIn === false) { 79 if (startsWith($query, 'do=' . self::$PAGE_LOGIN) && $loggedIn === false) {
79 return self::$PAGE_LOGIN; 80 return self::$PAGE_LOGIN;
80 } 81 }
81 82
82 if (startsWith($query, 'do='. self::$PAGE_PICWALL)) { 83 if (startsWith($query, 'do=' . self::$PAGE_PICWALL)) {
83 return self::$PAGE_PICWALL; 84 return self::$PAGE_PICWALL;
84 } 85 }
85 86
86 if (startsWith($query, 'do='. self::$PAGE_TAGCLOUD)) { 87 if (startsWith($query, 'do=' . self::$PAGE_TAGCLOUD)) {
87 return self::$PAGE_TAGCLOUD; 88 return self::$PAGE_TAGCLOUD;
88 } 89 }
89 90
90 if (startsWith($query, 'do='. self::$PAGE_TAGLIST)) { 91 if (startsWith($query, 'do=' . self::$PAGE_TAGLIST)) {
91 return self::$PAGE_TAGLIST; 92 return self::$PAGE_TAGLIST;
92 } 93 }
93 94
94 if (startsWith($query, 'do='. self::$PAGE_OPENSEARCH)) { 95 if (startsWith($query, 'do=' . self::$PAGE_OPENSEARCH)) {
95 return self::$PAGE_OPENSEARCH; 96 return self::$PAGE_OPENSEARCH;
96 } 97 }
97 98
98 if (startsWith($query, 'do='. self::$PAGE_DAILY)) { 99 if (startsWith($query, 'do=' . self::$PAGE_DAILY)) {
99 return self::$PAGE_DAILY; 100 return self::$PAGE_DAILY;
100 } 101 }
101 102
102 if (startsWith($query, 'do='. self::$PAGE_FEED_ATOM)) { 103 if (startsWith($query, 'do=' . self::$PAGE_FEED_ATOM)) {
103 return self::$PAGE_FEED_ATOM; 104 return self::$PAGE_FEED_ATOM;
104 } 105 }
105 106
106 if (startsWith($query, 'do='. self::$PAGE_FEED_RSS)) { 107 if (startsWith($query, 'do=' . self::$PAGE_FEED_RSS)) {
107 return self::$PAGE_FEED_RSS; 108 return self::$PAGE_FEED_RSS;
108 } 109 }
109 110
110 if (startsWith($query, 'do='. self::$PAGE_THUMBS_UPDATE)) { 111 if (startsWith($query, 'do=' . self::$PAGE_THUMBS_UPDATE)) {
111 return self::$PAGE_THUMBS_UPDATE; 112 return self::$PAGE_THUMBS_UPDATE;
112 } 113 }
113 114
114 if (startsWith($query, 'do='. self::$AJAX_THUMB_UPDATE)) { 115 if (startsWith($query, 'do=' . self::$AJAX_THUMB_UPDATE)) {
115 return self::$AJAX_THUMB_UPDATE; 116 return self::$AJAX_THUMB_UPDATE;
116 } 117 }
117 118
@@ -120,23 +121,23 @@ class Router
120 return self::$PAGE_LINKLIST; 121 return self::$PAGE_LINKLIST;
121 } 122 }
122 123
123 if (startsWith($query, 'do='. self::$PAGE_TOOLS)) { 124 if (startsWith($query, 'do=' . self::$PAGE_TOOLS)) {
124 return self::$PAGE_TOOLS; 125 return self::$PAGE_TOOLS;
125 } 126 }
126 127
127 if (startsWith($query, 'do='. self::$PAGE_CHANGEPASSWORD)) { 128 if (startsWith($query, 'do=' . self::$PAGE_CHANGEPASSWORD)) {
128 return self::$PAGE_CHANGEPASSWORD; 129 return self::$PAGE_CHANGEPASSWORD;
129 } 130 }
130 131
131 if (startsWith($query, 'do='. self::$PAGE_CONFIGURE)) { 132 if (startsWith($query, 'do=' . self::$PAGE_CONFIGURE)) {
132 return self::$PAGE_CONFIGURE; 133 return self::$PAGE_CONFIGURE;
133 } 134 }
134 135
135 if (startsWith($query, 'do='. self::$PAGE_CHANGETAG)) { 136 if (startsWith($query, 'do=' . self::$PAGE_CHANGETAG)) {
136 return self::$PAGE_CHANGETAG; 137 return self::$PAGE_CHANGETAG;
137 } 138 }
138 139
139 if (startsWith($query, 'do='. self::$PAGE_ADDLINK)) { 140 if (startsWith($query, 'do=' . self::$PAGE_ADDLINK)) {
140 return self::$PAGE_ADDLINK; 141 return self::$PAGE_ADDLINK;
141 } 142 }
142 143
@@ -148,27 +149,27 @@ class Router
148 return self::$PAGE_DELETELINK; 149 return self::$PAGE_DELETELINK;
149 } 150 }
150 151
151 if (startsWith($query, 'do='. self::$PAGE_PINLINK)) { 152 if (startsWith($query, 'do=' . self::$PAGE_PINLINK)) {
152 return self::$PAGE_PINLINK; 153 return self::$PAGE_PINLINK;
153 } 154 }
154 155
155 if (startsWith($query, 'do='. self::$PAGE_EXPORT)) { 156 if (startsWith($query, 'do=' . self::$PAGE_EXPORT)) {
156 return self::$PAGE_EXPORT; 157 return self::$PAGE_EXPORT;
157 } 158 }
158 159
159 if (startsWith($query, 'do='. self::$PAGE_IMPORT)) { 160 if (startsWith($query, 'do=' . self::$PAGE_IMPORT)) {
160 return self::$PAGE_IMPORT; 161 return self::$PAGE_IMPORT;
161 } 162 }
162 163
163 if (startsWith($query, 'do='. self::$PAGE_PLUGINSADMIN)) { 164 if (startsWith($query, 'do=' . self::$PAGE_PLUGINSADMIN)) {
164 return self::$PAGE_PLUGINSADMIN; 165 return self::$PAGE_PLUGINSADMIN;
165 } 166 }
166 167
167 if (startsWith($query, 'do='. self::$PAGE_SAVE_PLUGINSADMIN)) { 168 if (startsWith($query, 'do=' . self::$PAGE_SAVE_PLUGINSADMIN)) {
168 return self::$PAGE_SAVE_PLUGINSADMIN; 169 return self::$PAGE_SAVE_PLUGINSADMIN;
169 } 170 }
170 171
171 if (startsWith($query, 'do='. self::$GET_TOKEN)) { 172 if (startsWith($query, 'do=' . self::$GET_TOKEN)) {
172 return self::$GET_TOKEN; 173 return self::$GET_TOKEN;
173 } 174 }
174 175
diff --git a/application/Thumbnailer.php b/application/Thumbnailer.php
index 37ed97a1..a23f98e9 100644
--- a/application/Thumbnailer.php
+++ b/application/Thumbnailer.php
@@ -3,9 +3,9 @@
3namespace Shaarli; 3namespace Shaarli;
4 4
5use Shaarli\Config\ConfigManager; 5use Shaarli\Config\ConfigManager;
6use WebThumbnailer\Application\ConfigManager as WTConfigManager;
6use WebThumbnailer\Exception\WebThumbnailerException; 7use WebThumbnailer\Exception\WebThumbnailerException;
7use WebThumbnailer\WebThumbnailer; 8use WebThumbnailer\WebThumbnailer;
8use WebThumbnailer\Application\ConfigManager as WTConfigManager;
9 9
10/** 10/**
11 * Class Thumbnailer 11 * Class Thumbnailer
diff --git a/application/api/ApiMiddleware.php b/application/api/ApiMiddleware.php
index 66eac133..5ffb8c6d 100644
--- a/application/api/ApiMiddleware.php
+++ b/application/api/ApiMiddleware.php
@@ -1,9 +1,8 @@
1<?php 1<?php
2namespace Shaarli\Api; 2namespace Shaarli\Api;
3 3
4use Shaarli\Api\Exceptions\ApiException;
5use Shaarli\Api\Exceptions\ApiAuthorizationException; 4use Shaarli\Api\Exceptions\ApiAuthorizationException;
6 5use Shaarli\Api\Exceptions\ApiException;
7use Shaarli\Config\ConfigManager; 6use Shaarli\Config\ConfigManager;
8use Slim\Container; 7use Slim\Container;
9use Slim\Http\Request; 8use Slim\Http\Request;
@@ -127,7 +126,7 @@ class ApiMiddleware
127 */ 126 */
128 protected function setLinkDb($conf) 127 protected function setLinkDb($conf)
129 { 128 {
130 $linkDb = new \LinkDB( 129 $linkDb = new \Shaarli\Bookmark\LinkDB(
131 $conf->get('resource.datastore'), 130 $conf->get('resource.datastore'),
132 true, 131 true,
133 $conf->get('privacy.hide_public_links'), 132 $conf->get('privacy.hide_public_links'),
diff --git a/application/api/ApiUtils.php b/application/api/ApiUtils.php
index fc5ecaf1..1824b5d0 100644
--- a/application/api/ApiUtils.php
+++ b/application/api/ApiUtils.php
@@ -1,8 +1,8 @@
1<?php 1<?php
2namespace Shaarli\Api; 2namespace Shaarli\Api;
3 3
4use Shaarli\Base64Url;
5use Shaarli\Api\Exceptions\ApiAuthorizationException; 4use Shaarli\Api\Exceptions\ApiAuthorizationException;
5use Shaarli\Http\Base64Url;
6 6
7/** 7/**
8 * REST API utilities 8 * REST API utilities
@@ -12,7 +12,7 @@ class ApiUtils
12 /** 12 /**
13 * Validates a JWT token authenticity. 13 * Validates a JWT token authenticity.
14 * 14 *
15 * @param string $token JWT token extracted from the headers. 15 * @param string $token JWT token extracted from the headers.
16 * @param string $secret API secret set in the settings. 16 * @param string $secret API secret set in the settings.
17 * 17 *
18 * @throws ApiAuthorizationException the token is not valid. 18 * @throws ApiAuthorizationException the token is not valid.
@@ -50,7 +50,7 @@ class ApiUtils
50 /** 50 /**
51 * Format a Link for the REST API. 51 * Format a Link for the REST API.
52 * 52 *
53 * @param array $link Link data read from the datastore. 53 * @param array $link Link data read from the datastore.
54 * @param string $indexUrl Shaarli's index URL (used for relative URL). 54 * @param string $indexUrl Shaarli's index URL (used for relative URL).
55 * 55 *
56 * @return array Link data formatted for the REST API. 56 * @return array Link data formatted for the REST API.
diff --git a/application/api/controllers/ApiController.php b/application/api/controllers/ApiController.php
index 9edefcf6..a6e7cbab 100644
--- a/application/api/controllers/ApiController.php
+++ b/application/api/controllers/ApiController.php
@@ -2,8 +2,9 @@
2 2
3namespace Shaarli\Api\Controllers; 3namespace Shaarli\Api\Controllers;
4 4
5use Shaarli\Bookmark\LinkDB;
5use Shaarli\Config\ConfigManager; 6use Shaarli\Config\ConfigManager;
6use \Slim\Container; 7use Slim\Container;
7 8
8/** 9/**
9 * Abstract Class ApiController 10 * Abstract Class ApiController
@@ -25,12 +26,12 @@ abstract class ApiController
25 protected $conf; 26 protected $conf;
26 27
27 /** 28 /**
28 * @var \LinkDB 29 * @var LinkDB
29 */ 30 */
30 protected $linkDb; 31 protected $linkDb;
31 32
32 /** 33 /**
33 * @var \History 34 * @var HistoryController
34 */ 35 */
35 protected $history; 36 protected $history;
36 37
diff --git a/application/api/controllers/History.php b/application/api/controllers/HistoryController.php
index 4582e8b2..9afcfa26 100644
--- a/application/api/controllers/History.php
+++ b/application/api/controllers/HistoryController.php
@@ -14,7 +14,7 @@ use Slim\Http\Response;
14 * 14 *
15 * @package Shaarli\Api\Controllers 15 * @package Shaarli\Api\Controllers
16 */ 16 */
17class History extends ApiController 17class HistoryController extends ApiController
18{ 18{
19 /** 19 /**
20 * Service providing operation regarding Shaarli datastore and settings. 20 * Service providing operation regarding Shaarli datastore and settings.
diff --git a/application/api/controllers/Tags.php b/application/api/controllers/Tags.php
index 6dd78750..82f3ef74 100644
--- a/application/api/controllers/Tags.php
+++ b/application/api/controllers/Tags.php
@@ -4,7 +4,6 @@ namespace Shaarli\Api\Controllers;
4 4
5use Shaarli\Api\ApiUtils; 5use Shaarli\Api\ApiUtils;
6use Shaarli\Api\Exceptions\ApiBadParametersException; 6use Shaarli\Api\Exceptions\ApiBadParametersException;
7use Shaarli\Api\Exceptions\ApiLinkNotFoundException;
8use Shaarli\Api\Exceptions\ApiTagNotFoundException; 7use Shaarli\Api\Exceptions\ApiTagNotFoundException;
9use Slim\Http\Request; 8use Slim\Http\Request;
10use Slim\Http\Response; 9use Slim\Http\Response;
diff --git a/application/api/exceptions/ApiLinkNotFoundException.php b/application/api/exceptions/ApiLinkNotFoundException.php
index c727f4f0..7c2bb56e 100644
--- a/application/api/exceptions/ApiLinkNotFoundException.php
+++ b/application/api/exceptions/ApiLinkNotFoundException.php
@@ -2,8 +2,6 @@
2 2
3namespace Shaarli\Api\Exceptions; 3namespace Shaarli\Api\Exceptions;
4 4
5use Slim\Http\Response;
6
7/** 5/**
8 * Class ApiLinkNotFoundException 6 * Class ApiLinkNotFoundException
9 * 7 *
diff --git a/application/api/exceptions/ApiTagNotFoundException.php b/application/api/exceptions/ApiTagNotFoundException.php
index eee152fe..66ace8bf 100644
--- a/application/api/exceptions/ApiTagNotFoundException.php
+++ b/application/api/exceptions/ApiTagNotFoundException.php
@@ -2,8 +2,6 @@
2 2
3namespace Shaarli\Api\Exceptions; 3namespace Shaarli\Api\Exceptions;
4 4
5use Slim\Http\Response;
6
7/** 5/**
8 * Class ApiTagNotFoundException 6 * Class ApiTagNotFoundException
9 * 7 *
diff --git a/application/LinkDB.php b/application/bookmark/LinkDB.php
index 4bbc2950..c13a1141 100644
--- a/application/LinkDB.php
+++ b/application/bookmark/LinkDB.php
@@ -1,4 +1,15 @@
1<?php 1<?php
2
3namespace Shaarli\Bookmark;
4
5use ArrayAccess;
6use Countable;
7use DateTime;
8use Iterator;
9use Shaarli\Bookmark\Exception\LinkNotFoundException;
10use Shaarli\Exceptions\IOException;
11use Shaarli\FileUtils;
12
2/** 13/**
3 * Data storage for links. 14 * Data storage for links.
4 * 15 *
@@ -108,6 +119,7 @@ class LinkDB implements Iterator, Countable, ArrayAccess
108 $redirector = '', 119 $redirector = '',
109 $redirectorEncode = true 120 $redirectorEncode = true
110 ) { 121 ) {
122
111 $this->datastore = $datastore; 123 $this->datastore = $datastore;
112 $this->loggedIn = $isLoggedIn; 124 $this->loggedIn = $isLoggedIn;
113 $this->hidePublicLinks = $hidePublicLinks; 125 $this->hidePublicLinks = $hidePublicLinks;
@@ -137,7 +149,7 @@ class LinkDB implements Iterator, Countable, ArrayAccess
137 if (!isset($value['id']) || empty($value['url'])) { 149 if (!isset($value['id']) || empty($value['url'])) {
138 die(t('Internal Error: A link should always have an id and URL.')); 150 die(t('Internal Error: A link should always have an id and URL.'));
139 } 151 }
140 if (($offset !== null && ! is_int($offset)) || ! is_int($value['id'])) { 152 if (($offset !== null && !is_int($offset)) || !is_int($value['id'])) {
141 die(t('You must specify an integer as a key.')); 153 die(t('You must specify an integer as a key.'));
142 } 154 }
143 if ($offset !== null && $offset !== $value['id']) { 155 if ($offset !== null && $offset !== $value['id']) {
@@ -247,31 +259,31 @@ class LinkDB implements Iterator, Countable, ArrayAccess
247 $this->links = array(); 259 $this->links = array();
248 $link = array( 260 $link = array(
249 'id' => 1, 261 'id' => 1,
250 'title'=> t('The personal, minimalist, super-fast, database free, bookmarking service'), 262 'title' => t('The personal, minimalist, super-fast, database free, bookmarking service'),
251 'url'=>'https://shaarli.readthedocs.io', 263 'url' => 'https://shaarli.readthedocs.io',
252 'description'=>t( 264 'description' => t(
253 'Welcome to Shaarli! This is your first public bookmark. ' 265 'Welcome to Shaarli! This is your first public bookmark. '
254 .'To edit or delete me, you must first login. 266 . 'To edit or delete me, you must first login.
255 267
256To learn how to use Shaarli, consult the link "Documentation" at the bottom of this page. 268To learn how to use Shaarli, consult the link "Documentation" at the bottom of this page.
257 269
258You use the community supported version of the original Shaarli project, by Sebastien Sauvage.' 270You use the community supported version of the original Shaarli project, by Sebastien Sauvage.'
259 ), 271 ),
260 'private'=>0, 272 'private' => 0,
261 'created'=> new DateTime(), 273 'created' => new DateTime(),
262 'tags'=>'opensource software' 274 'tags' => 'opensource software'
263 ); 275 );
264 $link['shorturl'] = link_small_hash($link['created'], $link['id']); 276 $link['shorturl'] = link_small_hash($link['created'], $link['id']);
265 $this->links[1] = $link; 277 $this->links[1] = $link;
266 278
267 $link = array( 279 $link = array(
268 'id' => 0, 280 'id' => 0,
269 'title'=> t('My secret stuff... - Pastebin.com'), 281 'title' => t('My secret stuff... - Pastebin.com'),
270 'url'=>'http://sebsauvage.net/paste/?8434b27936c09649#bR7XsXhoTiLcqCpQbmOpBi3rq2zzQUC5hBI7ZT1O3x8=', 282 'url' => 'http://sebsauvage.net/paste/?8434b27936c09649#bR7XsXhoTiLcqCpQbmOpBi3rq2zzQUC5hBI7ZT1O3x8=',
271 'description'=> t('Shhhh! I\'m a private link only YOU can see. You can delete me too.'), 283 'description' => t('Shhhh! I\'m a private link only YOU can see. You can delete me too.'),
272 'private'=>1, 284 'private' => 1,
273 'created'=> new DateTime('1 minute ago'), 285 'created' => new DateTime('1 minute ago'),
274 'tags'=>'secretstuff', 286 'tags' => 'secretstuff',
275 ); 287 );
276 $link['shorturl'] = link_small_hash($link['created'], $link['id']); 288 $link['shorturl'] = link_small_hash($link['created'], $link['id']);
277 $this->links[0] = $link; 289 $this->links[0] = $link;
@@ -297,7 +309,7 @@ You use the community supported version of the original Shaarli project, by Seba
297 309
298 $toremove = array(); 310 $toremove = array();
299 foreach ($this->links as $key => &$link) { 311 foreach ($this->links as $key => &$link) {
300 if (! $this->loggedIn && $link['private'] != 0) { 312 if (!$this->loggedIn && $link['private'] != 0) {
301 // Transition for not upgraded databases. 313 // Transition for not upgraded databases.
302 unset($this->links[$key]); 314 unset($this->links[$key]);
303 continue; 315 continue;
@@ -307,7 +319,7 @@ You use the community supported version of the original Shaarli project, by Seba
307 sanitizeLink($link); 319 sanitizeLink($link);
308 320
309 // Remove private tags if the user is not logged in. 321 // Remove private tags if the user is not logged in.
310 if (! $this->loggedIn) { 322 if (!$this->loggedIn) {
311 $link['tags'] = preg_replace('/(^|\s+)\.[^($|\s)]+\s*/', ' ', $link['tags']); 323 $link['tags'] = preg_replace('/(^|\s+)\.[^($|\s)]+\s*/', ' ', $link['tags']);
312 } 324 }
313 325
@@ -324,10 +336,10 @@ You use the community supported version of the original Shaarli project, by Seba
324 } 336 }
325 337
326 // To be able to load links before running the update, and prepare the update 338 // To be able to load links before running the update, and prepare the update
327 if (! isset($link['created'])) { 339 if (!isset($link['created'])) {
328 $link['id'] = $link['linkdate']; 340 $link['id'] = $link['linkdate'];
329 $link['created'] = DateTime::createFromFormat(self::LINK_DATE_FORMAT, $link['linkdate']); 341 $link['created'] = DateTime::createFromFormat(self::LINK_DATE_FORMAT, $link['linkdate']);
330 if (! empty($link['updated'])) { 342 if (!empty($link['updated'])) {
331 $link['updated'] = DateTime::createFromFormat(self::LINK_DATE_FORMAT, $link['updated']); 343 $link['updated'] = DateTime::createFromFormat(self::LINK_DATE_FORMAT, $link['updated']);
332 } 344 }
333 $link['shorturl'] = smallHash($link['linkdate']); 345 $link['shorturl'] = smallHash($link['linkdate']);
@@ -413,12 +425,12 @@ You use the community supported version of the original Shaarli project, by Seba
413 /** 425 /**
414 * Filter links according to search parameters. 426 * Filter links according to search parameters.
415 * 427 *
416 * @param array $filterRequest Search request content. Supported keys: 428 * @param array $filterRequest Search request content. Supported keys:
417 * - searchtags: list of tags 429 * - searchtags: list of tags
418 * - searchterm: term search 430 * - searchterm: term search
419 * @param bool $casesensitive Optional: Perform case sensitive filter 431 * @param bool $casesensitive Optional: Perform case sensitive filter
420 * @param string $visibility return only all/private/public links 432 * @param string $visibility return only all/private/public links
421 * @param string $untaggedonly return only untagged links 433 * @param bool $untaggedonly return only untagged links
422 * 434 *
423 * @return array filtered links, all links if no suitable filter was provided. 435 * @return array filtered links, all links if no suitable filter was provided.
424 */ 436 */
@@ -428,6 +440,7 @@ You use the community supported version of the original Shaarli project, by Seba
428 $visibility = 'all', 440 $visibility = 'all',
429 $untaggedonly = false 441 $untaggedonly = false
430 ) { 442 ) {
443
431 // Filter link database according to parameters. 444 // Filter link database according to parameters.
432 $searchtags = isset($filterRequest['searchtags']) ? escape($filterRequest['searchtags']) : ''; 445 $searchtags = isset($filterRequest['searchtags']) ? escape($filterRequest['searchtags']) : '';
433 $searchterm = isset($filterRequest['searchterm']) ? escape($filterRequest['searchterm']) : ''; 446 $searchterm = isset($filterRequest['searchterm']) ? escape($filterRequest['searchterm']) : '';
@@ -443,8 +456,8 @@ You use the community supported version of the original Shaarli project, by Seba
443 /** 456 /**
444 * Returns the list tags appearing in the links with the given tags 457 * Returns the list tags appearing in the links with the given tags
445 * 458 *
446 * @param array $filteringTags tags selecting the links to consider 459 * @param array $filteringTags tags selecting the links to consider
447 * @param string $visibility process only all/private/public links 460 * @param string $visibility process only all/private/public links
448 * 461 *
449 * @return array tag => linksCount 462 * @return array tag => linksCount
450 */ 463 */
diff --git a/application/LinkFilter.php b/application/bookmark/LinkFilter.php
index 8f147974..9b966307 100644
--- a/application/LinkFilter.php
+++ b/application/bookmark/LinkFilter.php
@@ -1,5 +1,10 @@
1<?php 1<?php
2 2
3namespace Shaarli\Bookmark;
4
5use Exception;
6use Shaarli\Bookmark\Exception\LinkNotFoundException;
7
3/** 8/**
4 * Class LinkFilter. 9 * Class LinkFilter.
5 * 10 *
@@ -10,22 +15,22 @@ class LinkFilter
10 /** 15 /**
11 * @var string permalinks. 16 * @var string permalinks.
12 */ 17 */
13 public static $FILTER_HASH = 'permalink'; 18 public static $FILTER_HASH = 'permalink';
14 19
15 /** 20 /**
16 * @var string text search. 21 * @var string text search.
17 */ 22 */
18 public static $FILTER_TEXT = 'fulltext'; 23 public static $FILTER_TEXT = 'fulltext';
19 24
20 /** 25 /**
21 * @var string tag filter. 26 * @var string tag filter.
22 */ 27 */
23 public static $FILTER_TAG = 'tags'; 28 public static $FILTER_TAG = 'tags';
24 29
25 /** 30 /**
26 * @var string filter by day. 31 * @var string filter by day.
27 */ 32 */
28 public static $FILTER_DAY = 'FILTER_DAY'; 33 public static $FILTER_DAY = 'FILTER_DAY';
29 34
30 /** 35 /**
31 * @var string Allowed characters for hashtags (regex syntax). 36 * @var string Allowed characters for hashtags (regex syntax).
@@ -58,7 +63,7 @@ class LinkFilter
58 */ 63 */
59 public function filter($type, $request, $casesensitive = false, $visibility = 'all', $untaggedonly = false) 64 public function filter($type, $request, $casesensitive = false, $visibility = 'all', $untaggedonly = false)
60 { 65 {
61 if (! in_array($visibility, ['all', 'public', 'private'])) { 66 if (!in_array($visibility, ['all', 'public', 'private'])) {
62 $visibility = 'all'; 67 $visibility = 'all';
63 } 68 }
64 69
@@ -117,7 +122,7 @@ class LinkFilter
117 foreach ($this->links as $key => $value) { 122 foreach ($this->links as $key => $value) {
118 if ($value['private'] && $visibility === 'private') { 123 if ($value['private'] && $visibility === 'private') {
119 $out[$key] = $value; 124 $out[$key] = $value;
120 } elseif (! $value['private'] && $visibility === 'public') { 125 } elseif (!$value['private'] && $visibility === 'public') {
121 $out[$key] = $value; 126 $out[$key] = $value;
122 } 127 }
123 } 128 }
@@ -132,7 +137,7 @@ class LinkFilter
132 * 137 *
133 * @return array $filtered array containing permalink data. 138 * @return array $filtered array containing permalink data.
134 * 139 *
135 * @throws LinkNotFoundException if the smallhash doesn't match any link. 140 * @throws \Shaarli\Bookmark\Exception\LinkNotFoundException if the smallhash doesn't match any link.
136 */ 141 */
137 private function filterSmallHash($smallHash) 142 private function filterSmallHash($smallHash)
138 { 143 {
@@ -169,7 +174,7 @@ class LinkFilter
169 * - see https://github.com/shaarli/Shaarli/issues/75 for examples 174 * - see https://github.com/shaarli/Shaarli/issues/75 for examples
170 * 175 *
171 * @param string $searchterms search query. 176 * @param string $searchterms search query.
172 * @param string $visibility Optional: return only all/private/public links. 177 * @param string $visibility Optional: return only all/private/public links.
173 * 178 *
174 * @return array search results. 179 * @return array search results.
175 */ 180 */
@@ -207,7 +212,7 @@ class LinkFilter
207 foreach ($this->links as $id => $link) { 212 foreach ($this->links as $id => $link) {
208 // ignore non private links when 'privatonly' is on. 213 // ignore non private links when 'privatonly' is on.
209 if ($visibility !== 'all') { 214 if ($visibility !== 'all') {
210 if (! $link['private'] && $visibility === 'private') { 215 if (!$link['private'] && $visibility === 'private') {
211 continue; 216 continue;
212 } elseif ($link['private'] && $visibility === 'public') { 217 } elseif ($link['private'] && $visibility === 'public') {
213 continue; 218 continue;
@@ -250,7 +255,9 @@ class LinkFilter
250 255
251 /** 256 /**
252 * generate a regex fragment out of a tag 257 * generate a regex fragment out of a tag
258 *
253 * @param string $tag to to generate regexs from. may start with '-' to negate, contain '*' as wildcard 259 * @param string $tag to to generate regexs from. may start with '-' to negate, contain '*' as wildcard
260 *
254 * @return string generated regex fragment 261 * @return string generated regex fragment
255 */ 262 */
256 private static function tag2regex($tag) 263 private static function tag2regex($tag)
@@ -334,7 +341,7 @@ class LinkFilter
334 // check level of visibility 341 // check level of visibility
335 // ignore non private links when 'privateonly' is on. 342 // ignore non private links when 'privateonly' is on.
336 if ($visibility !== 'all') { 343 if ($visibility !== 'all') {
337 if (! $link['private'] && $visibility === 'private') { 344 if (!$link['private'] && $visibility === 'private') {
338 continue; 345 continue;
339 } elseif ($link['private'] && $visibility === 'public') { 346 } elseif ($link['private'] && $visibility === 'public') {
340 continue; 347 continue;
@@ -377,7 +384,7 @@ class LinkFilter
377 $filtered = []; 384 $filtered = [];
378 foreach ($this->links as $key => $link) { 385 foreach ($this->links as $key => $link) {
379 if ($visibility !== 'all') { 386 if ($visibility !== 'all') {
380 if (! $link['private'] && $visibility === 'private') { 387 if (!$link['private'] && $visibility === 'private') {
381 continue; 388 continue;
382 } elseif ($link['private'] && $visibility === 'public') { 389 } elseif ($link['private'] && $visibility === 'public') {
383 continue; 390 continue;
@@ -406,7 +413,7 @@ class LinkFilter
406 */ 413 */
407 public function filterDay($day) 414 public function filterDay($day)
408 { 415 {
409 if (! checkDateFormat('Ymd', $day)) { 416 if (!checkDateFormat('Ymd', $day)) {
410 throw new Exception('Invalid date format'); 417 throw new Exception('Invalid date format');
411 } 418 }
412 419
@@ -440,14 +447,3 @@ class LinkFilter
440 return preg_split('/\s+/', $tagsOut, -1, PREG_SPLIT_NO_EMPTY); 447 return preg_split('/\s+/', $tagsOut, -1, PREG_SPLIT_NO_EMPTY);
441 } 448 }
442} 449}
443
444class LinkNotFoundException extends Exception
445{
446 /**
447 * LinkNotFoundException constructor.
448 */
449 public function __construct()
450 {
451 $this->message = t('The link you are trying to reach does not exist or has been deleted.');
452 }
453}
diff --git a/application/LinkUtils.php b/application/bookmark/LinkUtils.php
index d56e019f..de5b61cb 100644
--- a/application/LinkUtils.php
+++ b/application/bookmark/LinkUtils.php
@@ -1,11 +1,13 @@
1<?php 1<?php
2 2
3use Shaarli\Bookmark\LinkDB;
4
3/** 5/**
4 * Get cURL callback function for CURLOPT_WRITEFUNCTION 6 * Get cURL callback function for CURLOPT_WRITEFUNCTION
5 * 7 *
6 * @param string $charset to extract from the downloaded page (reference) 8 * @param string $charset to extract from the downloaded page (reference)
7 * @param string $title to extract from the downloaded page (reference) 9 * @param string $title to extract from the downloaded page (reference)
8 * @param string $curlGetInfo Optionnaly overrides curl_getinfo function 10 * @param string $curlGetInfo Optionally overrides curl_getinfo function
9 * 11 *
10 * @return Closure 12 * @return Closure
11 */ 13 */
@@ -196,7 +198,7 @@ function space2nbsp($text)
196 * 198 *
197 * @param string $description shaare's description. 199 * @param string $description shaare's description.
198 * @param string $redirector if a redirector is set, use it to gerenate links. 200 * @param string $redirector if a redirector is set, use it to gerenate links.
199 * @param bool $urlEncode Use `urlencode()` on the URL after the redirector or not. 201 * @param bool $urlEncode Use `urlencode()` on the URL after the redirector or not.
200 * @param string $indexUrl URL to Shaarli's index. 202 * @param string $indexUrl URL to Shaarli's index.
201 203
202 * @return string formatted description. 204 * @return string formatted description.
diff --git a/application/bookmark/exception/LinkNotFoundException.php b/application/bookmark/exception/LinkNotFoundException.php
new file mode 100644
index 00000000..f9414428
--- /dev/null
+++ b/application/bookmark/exception/LinkNotFoundException.php
@@ -0,0 +1,15 @@
1<?php
2namespace Shaarli\Bookmark\Exception;
3
4use Exception;
5
6class LinkNotFoundException extends Exception
7{
8 /**
9 * LinkNotFoundException constructor.
10 */
11 public function __construct()
12 {
13 $this->message = t('The link you are trying to reach does not exist or has been deleted.');
14 }
15}
diff --git a/application/config/ConfigJson.php b/application/config/ConfigJson.php
index 8c8d5610..4509357c 100644
--- a/application/config/ConfigJson.php
+++ b/application/config/ConfigJson.php
@@ -47,7 +47,7 @@ class ConfigJson implements ConfigIO
47 $print = defined('JSON_PRETTY_PRINT') ? JSON_PRETTY_PRINT : 0; 47 $print = defined('JSON_PRETTY_PRINT') ? JSON_PRETTY_PRINT : 0;
48 $data = self::getPhpHeaders() . json_encode($conf, $print) . self::getPhpSuffix(); 48 $data = self::getPhpHeaders() . json_encode($conf, $print) . self::getPhpSuffix();
49 if (!file_put_contents($filepath, $data)) { 49 if (!file_put_contents($filepath, $data)) {
50 throw new \IOException( 50 throw new \Shaarli\Exceptions\IOException(
51 $filepath, 51 $filepath,
52 t('Shaarli could not create the config file. '. 52 t('Shaarli could not create the config file. '.
53 'Please make sure Shaarli has the right to write in the folder is it installed in.') 53 'Please make sure Shaarli has the right to write in the folder is it installed in.')
diff --git a/application/config/ConfigManager.php b/application/config/ConfigManager.php
index 32aaea48..e6c35073 100644
--- a/application/config/ConfigManager.php
+++ b/application/config/ConfigManager.php
@@ -207,7 +207,7 @@ class ConfigManager
207 * 207 *
208 * @throws MissingFieldConfigException: a mandatory field has not been provided in $conf. 208 * @throws MissingFieldConfigException: a mandatory field has not been provided in $conf.
209 * @throws UnauthorizedConfigException: user is not authorize to change configuration. 209 * @throws UnauthorizedConfigException: user is not authorize to change configuration.
210 * @throws \IOException: an error occurred while writing the new config file. 210 * @throws \Shaarli\Exceptions\IOException: an error occurred while writing the new config file.
211 */ 211 */
212 public function write($isLoggedIn) 212 public function write($isLoggedIn)
213 { 213 {
diff --git a/application/config/ConfigPhp.php b/application/config/ConfigPhp.php
index 9625fe1a..cad34594 100644
--- a/application/config/ConfigPhp.php
+++ b/application/config/ConfigPhp.php
@@ -27,7 +27,7 @@ class ConfigPhp implements ConfigIO
27 /** 27 /**
28 * Map legacy config keys with the new ones. 28 * Map legacy config keys with the new ones.
29 * If ConfigPhp is used, getting <newkey> will actually look for <legacykey>. 29 * If ConfigPhp is used, getting <newkey> will actually look for <legacykey>.
30 * The Updater will use this array to transform keys when switching to JSON. 30 * The updater will use this array to transform keys when switching to JSON.
31 * 31 *
32 * @var array current key => legacy key. 32 * @var array current key => legacy key.
33 */ 33 */
@@ -124,7 +124,7 @@ class ConfigPhp implements ConfigIO
124 if (!file_put_contents($filepath, $configStr) 124 if (!file_put_contents($filepath, $configStr)
125 || strcmp(file_get_contents($filepath), $configStr) != 0 125 || strcmp(file_get_contents($filepath), $configStr) != 0
126 ) { 126 ) {
127 throw new \IOException( 127 throw new \Shaarli\Exceptions\IOException(
128 $filepath, 128 $filepath,
129 t('Shaarli could not create the config file. '. 129 t('Shaarli could not create the config file. '.
130 'Please make sure Shaarli has the right to write in the folder is it installed in.') 130 'Please make sure Shaarli has the right to write in the folder is it installed in.')
diff --git a/application/exceptions/IOException.php b/application/exceptions/IOException.php
index 18e46b77..2aa25e5c 100644
--- a/application/exceptions/IOException.php
+++ b/application/exceptions/IOException.php
@@ -1,4 +1,7 @@
1<?php 1<?php
2namespace Shaarli\Exceptions;
3
4use Exception;
2 5
3/** 6/**
4 * Exception class thrown when a filesystem access failure happens 7 * Exception class thrown when a filesystem access failure happens
@@ -17,6 +20,6 @@ class IOException extends Exception
17 { 20 {
18 $this->path = $path; 21 $this->path = $path;
19 $this->message = empty($message) ? t('Error accessing') : $message; 22 $this->message = empty($message) ? t('Error accessing') : $message;
20 $this->message .= ' "' . $this->path .'"'; 23 $this->message .= ' "' . $this->path . '"';
21 } 24 }
22} 25}
diff --git a/application/Cache.php b/application/feed/Cache.php
index e5d43e61..e5d43e61 100644
--- a/application/Cache.php
+++ b/application/feed/Cache.php
diff --git a/application/CachedPage.php b/application/feed/CachedPage.php
index e11cc52d..d809bdd9 100644
--- a/application/CachedPage.php
+++ b/application/feed/CachedPage.php
@@ -1,4 +1,7 @@
1<?php 1<?php
2
3namespace Shaarli\Feed;
4
2/** 5/**
3 * Simple cache system, mainly for the RSS/ATOM feeds 6 * Simple cache system, mainly for the RSS/ATOM feeds
4 */ 7 */
@@ -24,7 +27,7 @@ class CachedPage
24 { 27 {
25 // TODO: check write access to the cache directory 28 // TODO: check write access to the cache directory
26 $this->cacheDir = $cacheDir; 29 $this->cacheDir = $cacheDir;
27 $this->filename = $this->cacheDir.'/'.sha1($url).'.cache'; 30 $this->filename = $this->cacheDir . '/' . sha1($url) . '.cache';
28 $this->shouldBeCached = $shouldBeCached; 31 $this->shouldBeCached = $shouldBeCached;
29 } 32 }
30 33
diff --git a/application/FeedBuilder.php b/application/feed/FeedBuilder.php
index 73fafcbe..b66f2f91 100644
--- a/application/FeedBuilder.php
+++ b/application/feed/FeedBuilder.php
@@ -1,4 +1,7 @@
1<?php 1<?php
2namespace Shaarli\Feed;
3
4use DateTime;
2 5
3/** 6/**
4 * FeedBuilder class. 7 * FeedBuilder class.
@@ -28,7 +31,7 @@ class FeedBuilder
28 public static $DEFAULT_NB_LINKS = 50; 31 public static $DEFAULT_NB_LINKS = 50;
29 32
30 /** 33 /**
31 * @var LinkDB instance. 34 * @var \Shaarli\Bookmark\LinkDB instance.
32 */ 35 */
33 protected $linkDB; 36 protected $linkDB;
34 37
@@ -38,12 +41,12 @@ class FeedBuilder
38 protected $feedType; 41 protected $feedType;
39 42
40 /** 43 /**
41 * @var array $_SERVER. 44 * @var array $_SERVER
42 */ 45 */
43 protected $serverInfo; 46 protected $serverInfo;
44 47
45 /** 48 /**
46 * @var array $_GET. 49 * @var array $_GET
47 */ 50 */
48 protected $userInput; 51 protected $userInput;
49 52
@@ -75,11 +78,12 @@ class FeedBuilder
75 /** 78 /**
76 * Feed constructor. 79 * Feed constructor.
77 * 80 *
78 * @param LinkDB $linkDB LinkDB instance. 81 * @param \Shaarli\Bookmark\LinkDB $linkDB LinkDB instance.
79 * @param string $feedType Type of feed. 82 * @param string $feedType Type of feed.
80 * @param array $serverInfo $_SERVER. 83 * @param array $serverInfo $_SERVER.
81 * @param array $userInput $_GET. 84 * @param array $userInput $_GET.
82 * @param boolean $isLoggedIn True if the user is currently logged in, false otherwise. 85 * @param boolean $isLoggedIn True if the user is currently logged in,
86 * false otherwise.
83 */ 87 */
84 public function __construct($linkDB, $feedType, $serverInfo, $userInput, $isLoggedIn) 88 public function __construct($linkDB, $feedType, $serverInfo, $userInput, $isLoggedIn)
85 { 89 {
@@ -124,7 +128,7 @@ class FeedBuilder
124 $data['show_dates'] = !$this->hideDates || $this->isLoggedIn; 128 $data['show_dates'] = !$this->hideDates || $this->isLoggedIn;
125 // Remove leading slash from REQUEST_URI. 129 // Remove leading slash from REQUEST_URI.
126 $data['self_link'] = escape(server_url($this->serverInfo)) 130 $data['self_link'] = escape(server_url($this->serverInfo))
127 . escape($this->serverInfo['REQUEST_URI']); 131 . escape($this->serverInfo['REQUEST_URI']);
128 $data['index_url'] = $pageaddr; 132 $data['index_url'] = $pageaddr;
129 $data['usepermalinks'] = $this->usePermalinks === true; 133 $data['usepermalinks'] = $this->usePermalinks === true;
130 $data['links'] = $linkDisplayed; 134 $data['links'] = $linkDisplayed;
@@ -142,18 +146,18 @@ class FeedBuilder
142 */ 146 */
143 protected function buildItem($link, $pageaddr) 147 protected function buildItem($link, $pageaddr)
144 { 148 {
145 $link['guid'] = $pageaddr .'?'. $link['shorturl']; 149 $link['guid'] = $pageaddr . '?' . $link['shorturl'];
146 // Check for both signs of a note: starting with ? and 7 chars long. 150 // Check for both signs of a note: starting with ? and 7 chars long.
147 if ($link['url'][0] === '?' && strlen($link['url']) === 7) { 151 if ($link['url'][0] === '?' && strlen($link['url']) === 7) {
148 $link['url'] = $pageaddr . $link['url']; 152 $link['url'] = $pageaddr . $link['url'];
149 } 153 }
150 if ($this->usePermalinks === true) { 154 if ($this->usePermalinks === true) {
151 $permalink = '<a href="'. $link['url'] .'" title="'. t('Direct link') .'">'. t('Direct link') .'</a>'; 155 $permalink = '<a href="' . $link['url'] . '" title="' . t('Direct link') . '">' . t('Direct link') . '</a>';
152 } else { 156 } else {
153 $permalink = '<a href="'. $link['guid'] .'" title="'. t('Permalink') .'">'. t('Permalink') .'</a>'; 157 $permalink = '<a href="' . $link['guid'] . '" title="' . t('Permalink') . '">' . t('Permalink') . '</a>';
154 } 158 }
155 $link['description'] = format_description($link['description'], '', false, $pageaddr); 159 $link['description'] = format_description($link['description'], '', false, $pageaddr);
156 $link['description'] .= PHP_EOL .'<br>&#8212; '. $permalink; 160 $link['description'] .= PHP_EOL . '<br>&#8212; ' . $permalink;
157 161
158 $pubDate = $link['created']; 162 $pubDate = $link['created'];
159 $link['pub_iso_date'] = $this->getIsoDate($pubDate); 163 $link['pub_iso_date'] = $this->getIsoDate($pubDate);
@@ -164,7 +168,6 @@ class FeedBuilder
164 $link['up_iso_date'] = $this->getIsoDate($upDate, DateTime::ATOM); 168 $link['up_iso_date'] = $this->getIsoDate($upDate, DateTime::ATOM);
165 } else { 169 } else {
166 $link['up_iso_date'] = $this->getIsoDate($pubDate, DateTime::ATOM); 170 $link['up_iso_date'] = $this->getIsoDate($pubDate, DateTime::ATOM);
167 ;
168 } 171 }
169 172
170 // Save the more recent item. 173 // Save the more recent item.
@@ -223,11 +226,11 @@ class FeedBuilder
223 public function getTypeLanguage() 226 public function getTypeLanguage()
224 { 227 {
225 // Use the locale do define the language, if available. 228 // Use the locale do define the language, if available.
226 if (! empty($this->locale) && preg_match('/^\w{2}[_\-]\w{2}/', $this->locale)) { 229 if (!empty($this->locale) && preg_match('/^\w{2}[_\-]\w{2}/', $this->locale)) {
227 $length = ($this->feedType == self::$FEED_RSS) ? 5 : 2; 230 $length = ($this->feedType === self::$FEED_RSS) ? 5 : 2;
228 return str_replace('_', '-', substr($this->locale, 0, $length)); 231 return str_replace('_', '-', substr($this->locale, 0, $length));
229 } 232 }
230 return ($this->feedType == self::$FEED_RSS) ? 'en-en' : 'en'; 233 return ($this->feedType === self::$FEED_RSS) ? 'en-en' : 'en';
231 } 234 }
232 235
233 /** 236 /**
@@ -287,7 +290,7 @@ class FeedBuilder
287 } 290 }
288 291
289 $intNb = intval($this->userInput['nb']); 292 $intNb = intval($this->userInput['nb']);
290 if (! is_int($intNb) || $intNb == 0) { 293 if (!is_int($intNb) || $intNb == 0) {
291 return self::$DEFAULT_NB_LINKS; 294 return self::$DEFAULT_NB_LINKS;
292 } 295 }
293 296
diff --git a/application/Base64Url.php b/application/http/Base64Url.php
index 54d0fcd5..33fa7c1f 100644
--- a/application/Base64Url.php
+++ b/application/http/Base64Url.php
@@ -1,6 +1,6 @@
1<?php 1<?php
2 2
3namespace Shaarli; 3namespace Shaarli\Http;
4 4
5/** 5/**
6 * URL-safe Base64 operations 6 * URL-safe Base64 operations
diff --git a/application/HttpUtils.php b/application/http/HttpUtils.php
index 9c438160..2ea9195d 100644
--- a/application/HttpUtils.php
+++ b/application/http/HttpUtils.php
@@ -1,4 +1,7 @@
1<?php 1<?php
2
3use Shaarli\Http\Url;
4
2/** 5/**
3 * GET an HTTP URL to retrieve its content 6 * GET an HTTP URL to retrieve its content
4 * Uses the cURL library or a fallback method 7 * Uses the cURL library or a fallback method
@@ -38,7 +41,7 @@ function get_http_response($url, $timeout = 30, $maxBytes = 4194304, $curlWriteF
38 $cleanUrl = $urlObj->idnToAscii(); 41 $cleanUrl = $urlObj->idnToAscii();
39 42
40 if (!filter_var($cleanUrl, FILTER_VALIDATE_URL) || !$urlObj->isHttp()) { 43 if (!filter_var($cleanUrl, FILTER_VALIDATE_URL) || !$urlObj->isHttp()) {
41 return array(array(0 => 'Invalid HTTP Url'), false); 44 return array(array(0 => 'Invalid HTTP UrlUtils'), false);
42 } 45 }
43 46
44 $userAgent = 47 $userAgent =
diff --git a/application/Url.php b/application/http/Url.php
index 3b7f19c2..90444a2f 100644
--- a/application/Url.php
+++ b/application/http/Url.php
@@ -1,91 +1,6 @@
1<?php 1<?php
2/**
3 * Converts an array-represented URL to a string
4 *
5 * Source: http://php.net/manual/en/function.parse-url.php#106731
6 *
7 * @see http://php.net/manual/en/function.parse-url.php
8 *
9 * @param array $parsedUrl an array-represented URL
10 *
11 * @return string the string representation of the URL
12 */
13function unparse_url($parsedUrl)
14{
15 $scheme = isset($parsedUrl['scheme']) ? $parsedUrl['scheme'].'://' : '';
16 $host = isset($parsedUrl['host']) ? $parsedUrl['host'] : '';
17 $port = isset($parsedUrl['port']) ? ':'.$parsedUrl['port'] : '';
18 $user = isset($parsedUrl['user']) ? $parsedUrl['user'] : '';
19 $pass = isset($parsedUrl['pass']) ? ':'.$parsedUrl['pass'] : '';
20 $pass = ($user || $pass) ? "$pass@" : '';
21 $path = isset($parsedUrl['path']) ? $parsedUrl['path'] : '';
22 $query = isset($parsedUrl['query']) ? '?'.$parsedUrl['query'] : '';
23 $fragment = isset($parsedUrl['fragment']) ? '#'.$parsedUrl['fragment'] : '';
24 2
25 return "$scheme$user$pass$host$port$path$query$fragment"; 3namespace Shaarli\Http;
26}
27
28/**
29 * Removes undesired query parameters and fragments
30 *
31 * @param string url Url to be cleaned
32 *
33 * @return string the string representation of this URL after cleanup
34 */
35function cleanup_url($url)
36{
37 $obj_url = new Url($url);
38 return $obj_url->cleanup();
39}
40
41/**
42 * Get URL scheme.
43 *
44 * @param string url Url for which the scheme is requested
45 *
46 * @return mixed the URL scheme or false if none is provided.
47 */
48function get_url_scheme($url)
49{
50 $obj_url = new Url($url);
51 return $obj_url->getScheme();
52}
53
54/**
55 * Adds a trailing slash at the end of URL if necessary.
56 *
57 * @param string $url URL to check/edit.
58 *
59 * @return string $url URL with a end trailing slash.
60 */
61function add_trailing_slash($url)
62{
63 return $url . (!endsWith($url, '/') ? '/' : '');
64}
65
66/**
67 * Replace not whitelisted protocols by 'http://' from given URL.
68 *
69 * @param string $url URL to clean
70 * @param array $protocols List of allowed protocols (aside from http(s)).
71 *
72 * @return string URL with allowed protocol
73 */
74function whitelist_protocols($url, $protocols)
75{
76 if (startsWith($url, '?') || startsWith($url, '/')) {
77 return $url;
78 }
79 $protocols = array_merge(['http', 'https'], $protocols);
80 $protocol = preg_match('#^(\w+):/?/?#', $url, $match);
81 // Protocol not allowed: we remove it and replace it with http
82 if ($protocol === 1 && ! in_array($match[1], $protocols)) {
83 $url = str_replace($match[0], 'http://', $url);
84 } elseif ($protocol !== 1) {
85 $url = 'http://' . $url;
86 }
87 return $url;
88}
89 4
90/** 5/**
91 * URL representation and cleanup utilities 6 * URL representation and cleanup utilities
@@ -182,7 +97,7 @@ class Url
182 } 97 }
183 return $input; 98 return $input;
184 } 99 }
185 100
186 /** 101 /**
187 * Returns a string representation of this URL 102 * Returns a string representation of this URL
188 */ 103 */
@@ -196,7 +111,7 @@ class Url
196 */ 111 */
197 protected function cleanupQuery() 112 protected function cleanupQuery()
198 { 113 {
199 if (! isset($this->parts['query'])) { 114 if (!isset($this->parts['query'])) {
200 return; 115 return;
201 } 116 }
202 117
@@ -224,7 +139,7 @@ class Url
224 */ 139 */
225 protected function cleanupFragment() 140 protected function cleanupFragment()
226 { 141 {
227 if (! isset($this->parts['fragment'])) { 142 if (!isset($this->parts['fragment'])) {
228 return; 143 return;
229 } 144 }
230 145
@@ -257,7 +172,7 @@ class Url
257 public function idnToAscii() 172 public function idnToAscii()
258 { 173 {
259 $out = $this->cleanup(); 174 $out = $this->cleanup();
260 if (! function_exists('idn_to_ascii') || ! isset($this->parts['host'])) { 175 if (!function_exists('idn_to_ascii') || !isset($this->parts['host'])) {
261 return $out; 176 return $out;
262 } 177 }
263 $asciiHost = idn_to_ascii($this->parts['host'], 0, INTL_IDNA_VARIANT_UTS46); 178 $asciiHost = idn_to_ascii($this->parts['host'], 0, INTL_IDNA_VARIANT_UTS46);
@@ -291,7 +206,7 @@ class Url
291 } 206 }
292 207
293 /** 208 /**
294 * Test if the Url is an HTTP one. 209 * Test if the UrlUtils is an HTTP one.
295 * 210 *
296 * @return true is HTTP, false otherwise. 211 * @return true is HTTP, false otherwise.
297 */ 212 */
diff --git a/application/http/UrlUtils.php b/application/http/UrlUtils.php
new file mode 100644
index 00000000..4bc84b82
--- /dev/null
+++ b/application/http/UrlUtils.php
@@ -0,0 +1,88 @@
1<?php
2/**
3 * Converts an array-represented URL to a string
4 *
5 * Source: http://php.net/manual/en/function.parse-url.php#106731
6 *
7 * @see http://php.net/manual/en/function.parse-url.php
8 *
9 * @param array $parsedUrl an array-represented URL
10 *
11 * @return string the string representation of the URL
12 */
13function unparse_url($parsedUrl)
14{
15 $scheme = isset($parsedUrl['scheme']) ? $parsedUrl['scheme'].'://' : '';
16 $host = isset($parsedUrl['host']) ? $parsedUrl['host'] : '';
17 $port = isset($parsedUrl['port']) ? ':'.$parsedUrl['port'] : '';
18 $user = isset($parsedUrl['user']) ? $parsedUrl['user'] : '';
19 $pass = isset($parsedUrl['pass']) ? ':'.$parsedUrl['pass'] : '';
20 $pass = ($user || $pass) ? "$pass@" : '';
21 $path = isset($parsedUrl['path']) ? $parsedUrl['path'] : '';
22 $query = isset($parsedUrl['query']) ? '?'.$parsedUrl['query'] : '';
23 $fragment = isset($parsedUrl['fragment']) ? '#'.$parsedUrl['fragment'] : '';
24
25 return "$scheme$user$pass$host$port$path$query$fragment";
26}
27
28/**
29 * Removes undesired query parameters and fragments
30 *
31 * @param string url UrlUtils to be cleaned
32 *
33 * @return string the string representation of this URL after cleanup
34 */
35function cleanup_url($url)
36{
37 $obj_url = new \Shaarli\Http\Url($url);
38 return $obj_url->cleanup();
39}
40
41/**
42 * Get URL scheme.
43 *
44 * @param string url UrlUtils for which the scheme is requested
45 *
46 * @return mixed the URL scheme or false if none is provided.
47 */
48function get_url_scheme($url)
49{
50 $obj_url = new \Shaarli\Http\Url($url);
51 return $obj_url->getScheme();
52}
53
54/**
55 * Adds a trailing slash at the end of URL if necessary.
56 *
57 * @param string $url URL to check/edit.
58 *
59 * @return string $url URL with a end trailing slash.
60 */
61function add_trailing_slash($url)
62{
63 return $url . (!endsWith($url, '/') ? '/' : '');
64}
65
66/**
67 * Replace not whitelisted protocols by 'http://' from given URL.
68 *
69 * @param string $url URL to clean
70 * @param array $protocols List of allowed protocols (aside from http(s)).
71 *
72 * @return string URL with allowed protocol
73 */
74function whitelist_protocols($url, $protocols)
75{
76 if (startsWith($url, '?') || startsWith($url, '/')) {
77 return $url;
78 }
79 $protocols = array_merge(['http', 'https'], $protocols);
80 $protocol = preg_match('#^(\w+):/?/?#', $url, $match);
81 // Protocol not allowed: we remove it and replace it with http
82 if ($protocol === 1 && ! in_array($match[1], $protocols)) {
83 $url = str_replace($match[0], 'http://', $url);
84 } elseif ($protocol !== 1) {
85 $url = 'http://' . $url;
86 }
87 return $url;
88}
diff --git a/application/NetscapeBookmarkUtils.php b/application/netscape/NetscapeBookmarkUtils.php
index 84dd2b20..2fb1a4a6 100644
--- a/application/NetscapeBookmarkUtils.php
+++ b/application/netscape/NetscapeBookmarkUtils.php
@@ -1,9 +1,16 @@
1<?php 1<?php
2 2
3namespace Shaarli\Netscape;
4
5use DateTime;
6use DateTimeZone;
7use Exception;
8use Katzgrau\KLogger\Logger;
3use Psr\Log\LogLevel; 9use Psr\Log\LogLevel;
10use Shaarli\Bookmark\LinkDB;
4use Shaarli\Config\ConfigManager; 11use Shaarli\Config\ConfigManager;
12use Shaarli\History;
5use Shaarli\NetscapeBookmarkParser\NetscapeBookmarkParser; 13use Shaarli\NetscapeBookmarkParser\NetscapeBookmarkParser;
6use Katzgrau\KLogger\Logger;
7 14
8/** 15/**
9 * Utilities to import and export bookmarks using the Netscape format 16 * Utilities to import and export bookmarks using the Netscape format
@@ -31,8 +38,8 @@ class NetscapeBookmarkUtils
31 public static function filterAndFormat($linkDb, $selection, $prependNoteUrl, $indexUrl) 38 public static function filterAndFormat($linkDb, $selection, $prependNoteUrl, $indexUrl)
32 { 39 {
33 // see tpl/export.html for possible values 40 // see tpl/export.html for possible values
34 if (! in_array($selection, array('all', 'public', 'private'))) { 41 if (!in_array($selection, array('all', 'public', 'private'))) {
35 throw new Exception(t('Invalid export selection:') .' "'.$selection.'"'); 42 throw new Exception(t('Invalid export selection:') . ' "' . $selection . '"');
36 } 43 }
37 44
38 $bookmarkLinks = array(); 45 $bookmarkLinks = array();
@@ -84,7 +91,7 @@ class NetscapeBookmarkUtils
84 $status .= vsprintf( 91 $status .= vsprintf(
85 t( 92 t(
86 'was successfully processed in %d seconds: ' 93 'was successfully processed in %d seconds: '
87 .'%d links imported, %d links overwritten, %d links skipped.' 94 . '%d links imported, %d links overwritten, %d links skipped.'
88 ), 95 ),
89 [$duration, $importCount, $overwriteCount, $skipCount] 96 [$duration, $importCount, $overwriteCount, $skipCount]
90 ); 97 );
@@ -95,11 +102,11 @@ class NetscapeBookmarkUtils
95 /** 102 /**
96 * Imports Web bookmarks from an uploaded Netscape bookmark dump 103 * Imports Web bookmarks from an uploaded Netscape bookmark dump
97 * 104 *
98 * @param array $post Server $_POST parameters 105 * @param array $post Server $_POST parameters
99 * @param array $files Server $_FILES parameters 106 * @param array $files Server $_FILES parameters
100 * @param LinkDB $linkDb Loaded LinkDB instance 107 * @param LinkDB $linkDb Loaded LinkDB instance
101 * @param ConfigManager $conf instance 108 * @param ConfigManager $conf instance
102 * @param History $history History instance 109 * @param History $history History instance
103 * 110 *
104 * @return string Summary of the bookmark import status 111 * @return string Summary of the bookmark import status
105 */ 112 */
@@ -115,7 +122,7 @@ class NetscapeBookmarkUtils
115 } 122 }
116 123
117 // Overwrite existing links? 124 // Overwrite existing links?
118 $overwrite = ! empty($post['overwrite']); 125 $overwrite = !empty($post['overwrite']);
119 126
120 // Add tags to all imported links? 127 // Add tags to all imported links?
121 if (empty($post['default_tags'])) { 128 if (empty($post['default_tags'])) {
@@ -138,7 +145,7 @@ class NetscapeBookmarkUtils
138 ); 145 );
139 $logger = new Logger( 146 $logger = new Logger(
140 $conf->get('resource.data_dir'), 147 $conf->get('resource.data_dir'),
141 ! $conf->get('dev.debug') ? LogLevel::INFO : LogLevel::DEBUG, 148 !$conf->get('dev.debug') ? LogLevel::INFO : LogLevel::DEBUG,
142 [ 149 [
143 'prefix' => 'import.', 150 'prefix' => 'import.',
144 'extension' => 'log', 151 'extension' => 'log',
@@ -193,7 +200,7 @@ class NetscapeBookmarkUtils
193 } 200 }
194 201
195 // Add a new link - @ used for UNIX timestamps 202 // Add a new link - @ used for UNIX timestamps
196 $newLinkDate = new DateTime('@'.strval($bkm['time'])); 203 $newLinkDate = new DateTime('@' . strval($bkm['time']));
197 $newLinkDate->setTimezone(new DateTimeZone(date_default_timezone_get())); 204 $newLinkDate->setTimezone(new DateTimeZone(date_default_timezone_get()));
198 $newLink['created'] = $newLinkDate; 205 $newLink['created'] = $newLinkDate;
199 $newLink['id'] = $linkDb->getNextId(); 206 $newLink['id'] = $linkDb->getNextId();
diff --git a/application/PluginManager.php b/application/plugin/PluginManager.php
index 1ed4db4b..f7b24a8e 100644
--- a/application/PluginManager.php
+++ b/application/plugin/PluginManager.php
@@ -1,4 +1,8 @@
1<?php 1<?php
2namespace Shaarli\Plugin;
3
4use Shaarli\Config\ConfigManager;
5use Shaarli\Plugin\Exception\PluginFileNotFoundException;
2 6
3/** 7/**
4 * Class PluginManager 8 * Class PluginManager
@@ -9,12 +13,14 @@ class PluginManager
9{ 13{
10 /** 14 /**
11 * List of authorized plugins from configuration file. 15 * List of authorized plugins from configuration file.
16 *
12 * @var array $authorizedPlugins 17 * @var array $authorizedPlugins
13 */ 18 */
14 private $authorizedPlugins; 19 private $authorizedPlugins;
15 20
16 /** 21 /**
17 * List of loaded plugins. 22 * List of loaded plugins.
23 *
18 * @var array $loadedPlugins 24 * @var array $loadedPlugins
19 */ 25 */
20 private $loadedPlugins = array(); 26 private $loadedPlugins = array();
@@ -31,12 +37,14 @@ class PluginManager
31 37
32 /** 38 /**
33 * Plugins subdirectory. 39 * Plugins subdirectory.
40 *
34 * @var string $PLUGINS_PATH 41 * @var string $PLUGINS_PATH
35 */ 42 */
36 public static $PLUGINS_PATH = 'plugins'; 43 public static $PLUGINS_PATH = 'plugins';
37 44
38 /** 45 /**
39 * Plugins meta files extension. 46 * Plugins meta files extension.
47 *
40 * @var string $META_EXT 48 * @var string $META_EXT
41 */ 49 */
42 public static $META_EXT = 'meta'; 50 public static $META_EXT = 'meta';
@@ -84,9 +92,9 @@ class PluginManager
84 /** 92 /**
85 * Execute all plugins registered hook. 93 * Execute all plugins registered hook.
86 * 94 *
87 * @param string $hook name of the hook to trigger. 95 * @param string $hook name of the hook to trigger.
88 * @param array $data list of data to manipulate passed by reference. 96 * @param array $data list of data to manipulate passed by reference.
89 * @param array $params additional parameters such as page target. 97 * @param array $params additional parameters such as page target.
90 * 98 *
91 * @return void 99 * @return void
92 */ 100 */
@@ -118,7 +126,7 @@ class PluginManager
118 * @param string $pluginName plugin's name. 126 * @param string $pluginName plugin's name.
119 * 127 *
120 * @return void 128 * @return void
121 * @throws PluginFileNotFoundException - plugin files not found. 129 * @throws \Shaarli\Plugin\Exception\PluginFileNotFoundException - plugin files not found.
122 */ 130 */
123 private function loadPlugin($dir, $pluginName) 131 private function loadPlugin($dir, $pluginName)
124 { 132 {
@@ -204,8 +212,8 @@ class PluginManager
204 212
205 $metaData[$plugin]['parameters'][$param]['value'] = ''; 213 $metaData[$plugin]['parameters'][$param]['value'] = '';
206 // Optional parameter description in parameter.PARAM_NAME= 214 // Optional parameter description in parameter.PARAM_NAME=
207 if (isset($metaData[$plugin]['parameter.'. $param])) { 215 if (isset($metaData[$plugin]['parameter.' . $param])) {
208 $metaData[$plugin]['parameters'][$param]['desc'] = t($metaData[$plugin]['parameter.'. $param]); 216 $metaData[$plugin]['parameters'][$param]['desc'] = t($metaData[$plugin]['parameter.' . $param]);
209 } 217 }
210 } 218 }
211 } 219 }
@@ -223,22 +231,3 @@ class PluginManager
223 return $this->errors; 231 return $this->errors;
224 } 232 }
225} 233}
226
227/**
228 * Class PluginFileNotFoundException
229 *
230 * Raise when plugin files can't be found.
231 */
232class PluginFileNotFoundException extends Exception
233{
234 /**
235 * Construct exception with plugin name.
236 * Generate message.
237 *
238 * @param string $pluginName name of the plugin not found
239 */
240 public function __construct($pluginName)
241 {
242 $this->message = sprintf(t('Plugin "%s" files not found.'), $pluginName);
243 }
244}
diff --git a/application/plugin/exception/PluginFileNotFoundException.php b/application/plugin/exception/PluginFileNotFoundException.php
new file mode 100644
index 00000000..e5386f02
--- /dev/null
+++ b/application/plugin/exception/PluginFileNotFoundException.php
@@ -0,0 +1,23 @@
1<?php
2namespace Shaarli\Plugin\Exception;
3
4use Exception;
5
6/**
7 * Class PluginFileNotFoundException
8 *
9 * Raise when plugin files can't be found.
10 */
11class PluginFileNotFoundException extends Exception
12{
13 /**
14 * Construct exception with plugin name.
15 * Generate message.
16 *
17 * @param string $pluginName name of the plugin not found
18 */
19 public function __construct($pluginName)
20 {
21 $this->message = sprintf(t('Plugin "%s" files not found.'), $pluginName);
22 }
23}
diff --git a/application/PageBuilder.php b/application/render/PageBuilder.php
index 2ca95832..0569b67f 100644
--- a/application/PageBuilder.php
+++ b/application/render/PageBuilder.php
@@ -1,5 +1,11 @@
1<?php 1<?php
2 2
3namespace Shaarli\Render;
4
5use Exception;
6use RainTPL;
7use Shaarli\ApplicationUtils;
8use Shaarli\Bookmark\LinkDB;
3use Shaarli\Config\ConfigManager; 9use Shaarli\Config\ConfigManager;
4use Shaarli\Thumbnailer; 10use Shaarli\Thumbnailer;
5 11
@@ -37,7 +43,9 @@ class PageBuilder
37 */ 43 */
38 protected $token; 44 protected $token;
39 45
40 /** @var bool $isLoggedIn Whether the user is logged in **/ 46 /**
47 * @var bool $isLoggedIn Whether the user is logged in
48 */
41 protected $isLoggedIn = false; 49 protected $isLoggedIn = false;
42 50
43 /** 51 /**
@@ -101,7 +109,7 @@ class PageBuilder
101 ApplicationUtils::getVersionHash(SHAARLI_VERSION, $this->conf->get('credentials.salt')) 109 ApplicationUtils::getVersionHash(SHAARLI_VERSION, $this->conf->get('credentials.salt'))
102 ); 110 );
103 $this->tpl->assign('index_url', index_url($_SERVER)); 111 $this->tpl->assign('index_url', index_url($_SERVER));
104 $visibility = ! empty($_SESSION['visibility']) ? $_SESSION['visibility'] : ''; 112 $visibility = !empty($_SESSION['visibility']) ? $_SESSION['visibility'] : '';
105 $this->tpl->assign('visibility', $visibility); 113 $this->tpl->assign('visibility', $visibility);
106 $this->tpl->assign('untaggedonly', !empty($_SESSION['untaggedonly'])); 114 $this->tpl->assign('untaggedonly', !empty($_SESSION['untaggedonly']));
107 $this->tpl->assign('pagetitle', $this->conf->get('general.title', 'Shaarli')); 115 $this->tpl->assign('pagetitle', $this->conf->get('general.title', 'Shaarli'));
@@ -126,7 +134,7 @@ class PageBuilder
126 $this->tpl->assign('thumbnails_width', $this->conf->get('thumbnails.width')); 134 $this->tpl->assign('thumbnails_width', $this->conf->get('thumbnails.width'));
127 $this->tpl->assign('thumbnails_height', $this->conf->get('thumbnails.height')); 135 $this->tpl->assign('thumbnails_height', $this->conf->get('thumbnails.height'));
128 136
129 if (! empty($_SESSION['warnings'])) { 137 if (!empty($_SESSION['warnings'])) {
130 $this->tpl->assign('global_warnings', $_SESSION['warnings']); 138 $this->tpl->assign('global_warnings', $_SESSION['warnings']);
131 unset($_SESSION['warnings']); 139 unset($_SESSION['warnings']);
132 } 140 }
@@ -189,16 +197,16 @@ class PageBuilder
189 197
190 /** 198 /**
191 * Render a 404 page (uses the template : tpl/404.tpl) 199 * Render a 404 page (uses the template : tpl/404.tpl)
192 * usage : $PAGE->render404('The link was deleted') 200 * usage: $PAGE->render404('The link was deleted')
193 * 201 *
194 * @param string $message A messate to display what is not found 202 * @param string $message A message to display what is not found
195 */ 203 */
196 public function render404($message = '') 204 public function render404($message = '')
197 { 205 {
198 if (empty($message)) { 206 if (empty($message)) {
199 $message = t('The page you are trying to reach does not exist or has been deleted.'); 207 $message = t('The page you are trying to reach does not exist or has been deleted.');
200 } 208 }
201 header($_SERVER['SERVER_PROTOCOL'] .' '. t('404 Not Found')); 209 header($_SERVER['SERVER_PROTOCOL'] . ' ' . t('404 Not Found'));
202 $this->tpl->assign('error_message', $message); 210 $this->tpl->assign('error_message', $message);
203 $this->renderPage('404'); 211 $this->renderPage('404');
204 } 212 }
diff --git a/application/ThemeUtils.php b/application/render/ThemeUtils.php
index 16f2f6a2..86096c64 100644
--- a/application/ThemeUtils.php
+++ b/application/render/ThemeUtils.php
@@ -1,6 +1,6 @@
1<?php 1<?php
2 2
3namespace Shaarli; 3namespace Shaarli\Render;
4 4
5/** 5/**
6 * Class ThemeUtils 6 * Class ThemeUtils
diff --git a/application/Updater.php b/application/updater/Updater.php
index 6b94c5e3..f12e3516 100644
--- a/application/Updater.php
+++ b/application/updater/Updater.php
@@ -1,11 +1,24 @@
1<?php 1<?php
2
3namespace Shaarli\Updater;
4
5use Exception;
6use RainTPL;
7use ReflectionClass;
8use ReflectionException;
9use ReflectionMethod;
10use Shaarli\ApplicationUtils;
11use Shaarli\Bookmark\LinkDB;
12use Shaarli\Bookmark\LinkFilter;
2use Shaarli\Config\ConfigJson; 13use Shaarli\Config\ConfigJson;
3use Shaarli\Config\ConfigPhp;
4use Shaarli\Config\ConfigManager; 14use Shaarli\Config\ConfigManager;
15use Shaarli\Config\ConfigPhp;
16use Shaarli\Exceptions\IOException;
5use Shaarli\Thumbnailer; 17use Shaarli\Thumbnailer;
18use Shaarli\Updater\Exception\UpdaterException;
6 19
7/** 20/**
8 * Class Updater. 21 * Class updater.
9 * Used to update stuff when a new Shaarli's version is reached. 22 * Used to update stuff when a new Shaarli's version is reached.
10 * Update methods are ran only once, and the stored in a JSON file. 23 * Update methods are ran only once, and the stored in a JSON file.
11 */ 24 */
@@ -83,12 +96,12 @@ class Updater
83 } 96 }
84 97
85 if ($this->methods === null) { 98 if ($this->methods === null) {
86 throw new UpdaterException(t('Couldn\'t retrieve Updater class methods.')); 99 throw new UpdaterException(t('Couldn\'t retrieve updater class methods.'));
87 } 100 }
88 101
89 foreach ($this->methods as $method) { 102 foreach ($this->methods as $method) {
90 // Not an update method or already done, pass. 103 // Not an update method or already done, pass.
91 if (! startsWith($method->getName(), 'updateMethod') 104 if (!startsWith($method->getName(), 'updateMethod')
92 || in_array($method->getName(), $this->doneUpdates) 105 || in_array($method->getName(), $this->doneUpdates)
93 ) { 106 ) {
94 continue; 107 continue;
@@ -139,7 +152,7 @@ class Updater
139 } 152 }
140 } 153 }
141 $this->conf->write($this->isLoggedIn); 154 $this->conf->write($this->isLoggedIn);
142 unlink($this->conf->get('resource.data_dir').'/options.php'); 155 unlink($this->conf->get('resource.data_dir') . '/options.php');
143 } 156 }
144 157
145 return true; 158 return true;
@@ -174,10 +187,10 @@ class Updater
174 $subConfig = array('config', 'plugins'); 187 $subConfig = array('config', 'plugins');
175 foreach ($subConfig as $sub) { 188 foreach ($subConfig as $sub) {
176 foreach ($oldConfig[$sub] as $key => $value) { 189 foreach ($oldConfig[$sub] as $key => $value) {
177 if (isset($legacyMap[$sub .'.'. $key])) { 190 if (isset($legacyMap[$sub . '.' . $key])) {
178 $configKey = $legacyMap[$sub .'.'. $key]; 191 $configKey = $legacyMap[$sub . '.' . $key];
179 } else { 192 } else {
180 $configKey = $sub .'.'. $key; 193 $configKey = $sub . '.' . $key;
181 } 194 }
182 $this->conf->set($configKey, $value); 195 $this->conf->set($configKey, $value);
183 } 196 }
@@ -233,7 +246,7 @@ class Updater
233 return true; 246 return true;
234 } 247 }
235 248
236 $save = $this->conf->get('resource.data_dir') .'/datastore.'. date('YmdHis') .'.php'; 249 $save = $this->conf->get('resource.data_dir') . '/datastore.' . date('YmdHis') . '.php';
237 copy($this->conf->get('resource.datastore'), $save); 250 copy($this->conf->get('resource.datastore'), $save);
238 251
239 $links = array(); 252 $links = array();
@@ -307,7 +320,7 @@ class Updater
307 // We run the update only if this folder still contains the template files. 320 // We run the update only if this folder still contains the template files.
308 $tplDir = $this->conf->get('resource.raintpl_tpl'); 321 $tplDir = $this->conf->get('resource.raintpl_tpl');
309 $tplFile = $tplDir . '/linklist.html'; 322 $tplFile = $tplDir . '/linklist.html';
310 if (! file_exists($tplFile)) { 323 if (!file_exists($tplFile)) {
311 return true; 324 return true;
312 } 325 }
313 326
@@ -331,7 +344,7 @@ class Updater
331 */ 344 */
332 public function updateMethodMoveUserCss() 345 public function updateMethodMoveUserCss()
333 { 346 {
334 if (! is_file('inc/user.css')) { 347 if (!is_file('inc/user.css')) {
335 return true; 348 return true;
336 } 349 }
337 350
@@ -367,11 +380,11 @@ class Updater
367 */ 380 */
368 public function updateMethodPiwikUrl() 381 public function updateMethodPiwikUrl()
369 { 382 {
370 if (! $this->conf->exists('plugins.PIWIK_URL') || startsWith($this->conf->get('plugins.PIWIK_URL'), 'http')) { 383 if (!$this->conf->exists('plugins.PIWIK_URL') || startsWith($this->conf->get('plugins.PIWIK_URL'), 'http')) {
371 return true; 384 return true;
372 } 385 }
373 386
374 $this->conf->set('plugins.PIWIK_URL', 'http://'. $this->conf->get('plugins.PIWIK_URL')); 387 $this->conf->set('plugins.PIWIK_URL', 'http://' . $this->conf->get('plugins.PIWIK_URL'));
375 $this->conf->write($this->isLoggedIn); 388 $this->conf->write($this->isLoggedIn);
376 389
377 return true; 390 return true;
@@ -481,11 +494,11 @@ class Updater
481 return true; 494 return true;
482 } 495 }
483 496
484 if (! $this->conf->exists('general.download_max_size')) { 497 if (!$this->conf->exists('general.download_max_size')) {
485 $this->conf->set('general.download_max_size', 1024*1024*4); 498 $this->conf->set('general.download_max_size', 1024 * 1024 * 4);
486 } 499 }
487 500
488 if (! $this->conf->exists('general.download_timeout')) { 501 if (!$this->conf->exists('general.download_timeout')) {
489 $this->conf->set('general.download_timeout', 30); 502 $this->conf->set('general.download_timeout', 30);
490 } 503 }
491 504
@@ -538,96 +551,3 @@ class Updater
538 return true; 551 return true;
539 } 552 }
540} 553}
541
542/**
543 * Class UpdaterException.
544 */
545class UpdaterException extends Exception
546{
547 /**
548 * @var string Method where the error occurred.
549 */
550 protected $method;
551
552 /**
553 * @var Exception The parent exception.
554 */
555 protected $previous;
556
557 /**
558 * Constructor.
559 *
560 * @param string $message Force the error message if set.
561 * @param string $method Method where the error occurred.
562 * @param Exception|bool $previous Parent exception.
563 */
564 public function __construct($message = '', $method = '', $previous = false)
565 {
566 $this->method = $method;
567 $this->previous = $previous;
568 $this->message = $this->buildMessage($message);
569 }
570
571 /**
572 * Build the exception error message.
573 *
574 * @param string $message Optional given error message.
575 *
576 * @return string The built error message.
577 */
578 private function buildMessage($message)
579 {
580 $out = '';
581 if (! empty($message)) {
582 $out .= $message . PHP_EOL;
583 }
584
585 if (! empty($this->method)) {
586 $out .= t('An error occurred while running the update ') . $this->method . PHP_EOL;
587 }
588
589 if (! empty($this->previous)) {
590 $out .= ' '. $this->previous->getMessage();
591 }
592
593 return $out;
594 }
595}
596
597/**
598 * Read the updates file, and return already done updates.
599 *
600 * @param string $updatesFilepath Updates file path.
601 *
602 * @return array Already done update methods.
603 */
604function read_updates_file($updatesFilepath)
605{
606 if (! empty($updatesFilepath) && is_file($updatesFilepath)) {
607 $content = file_get_contents($updatesFilepath);
608 if (! empty($content)) {
609 return explode(';', $content);
610 }
611 }
612 return array();
613}
614
615/**
616 * Write updates file.
617 *
618 * @param string $updatesFilepath Updates file path.
619 * @param array $updates Updates array to write.
620 *
621 * @throws Exception Couldn't write version number.
622 */
623function write_updates_file($updatesFilepath, $updates)
624{
625 if (empty($updatesFilepath)) {
626 throw new Exception(t('Updates file path is not set, can\'t write updates.'));
627 }
628
629 $res = file_put_contents($updatesFilepath, implode(';', $updates));
630 if ($res === false) {
631 throw new Exception(t('Unable to write updates in '. $updatesFilepath . '.'));
632 }
633}
diff --git a/application/updater/UpdaterUtils.php b/application/updater/UpdaterUtils.php
new file mode 100644
index 00000000..34d4f422
--- /dev/null
+++ b/application/updater/UpdaterUtils.php
@@ -0,0 +1,39 @@
1<?php
2
3/**
4 * Read the updates file, and return already done updates.
5 *
6 * @param string $updatesFilepath Updates file path.
7 *
8 * @return array Already done update methods.
9 */
10function read_updates_file($updatesFilepath)
11{
12 if (! empty($updatesFilepath) && is_file($updatesFilepath)) {
13 $content = file_get_contents($updatesFilepath);
14 if (! empty($content)) {
15 return explode(';', $content);
16 }
17 }
18 return array();
19}
20
21/**
22 * Write updates file.
23 *
24 * @param string $updatesFilepath Updates file path.
25 * @param array $updates Updates array to write.
26 *
27 * @throws Exception Couldn't write version number.
28 */
29function write_updates_file($updatesFilepath, $updates)
30{
31 if (empty($updatesFilepath)) {
32 throw new Exception(t('Updates file path is not set, can\'t write updates.'));
33 }
34
35 $res = file_put_contents($updatesFilepath, implode(';', $updates));
36 if ($res === false) {
37 throw new Exception(t('Unable to write updates in '. $updatesFilepath . '.'));
38 }
39}
diff --git a/application/updater/exception/UpdaterException.php b/application/updater/exception/UpdaterException.php
new file mode 100644
index 00000000..20aceccf
--- /dev/null
+++ b/application/updater/exception/UpdaterException.php
@@ -0,0 +1,60 @@
1<?php
2
3namespace Shaarli\Updater\Exception;
4
5use Exception;
6
7/**
8 * Class UpdaterException.
9 */
10class UpdaterException extends Exception
11{
12 /**
13 * @var string Method where the error occurred.
14 */
15 protected $method;
16
17 /**
18 * @var Exception The parent exception.
19 */
20 protected $previous;
21
22 /**
23 * Constructor.
24 *
25 * @param string $message Force the error message if set.
26 * @param string $method Method where the error occurred.
27 * @param Exception|bool $previous Parent exception.
28 */
29 public function __construct($message = '', $method = '', $previous = false)
30 {
31 $this->method = $method;
32 $this->previous = $previous;
33 $this->message = $this->buildMessage($message);
34 }
35
36 /**
37 * Build the exception error message.
38 *
39 * @param string $message Optional given error message.
40 *
41 * @return string The built error message.
42 */
43 private function buildMessage($message)
44 {
45 $out = '';
46 if (!empty($message)) {
47 $out .= $message . PHP_EOL;
48 }
49
50 if (!empty($this->method)) {
51 $out .= t('An error occurred while running the update ') . $this->method . PHP_EOL;
52 }
53
54 if (!empty($this->previous)) {
55 $out .= ' ' . $this->previous->getMessage();
56 }
57
58 return $out;
59 }
60}