]> git.immae.eu Git - github/shaarli/Shaarli.git/blame - application/ApplicationUtils.php
Add an updateMethod to match the current remote branch for updates
[github/shaarli/Shaarli.git] / application / ApplicationUtils.php
CommitLineData
2e28269b
V
1<?php
2/**
3 * Shaarli (application) utilities
4 */
5class ApplicationUtils
6{
4bf35ba5 7 private static $GIT_URL = 'https://raw.githubusercontent.com/shaarli/Shaarli';
b897c81f 8 private static $GIT_BRANCHES = array('latest', 'stable');
4bf35ba5
V
9 private static $VERSION_FILE = 'shaarli_version.php';
10 private static $VERSION_START_TAG = '<?php /* ';
11 private static $VERSION_END_TAG = ' */ ?>';
12
13 /**
14 * Gets the latest version code from the Git repository
15 *
16 * The code is read from the raw content of the version file on the Git server.
17 *
7af9a418
A
18 * @param string $url URL to reach to get the latest version.
19 * @param int $timeout Timeout to check the URL (in seconds).
20 *
4bf35ba5
V
21 * @return mixed the version code from the repository if available, else 'false'
22 */
23 public static function getLatestGitVersionCode($url, $timeout=2)
24 {
1557cefb 25 list($headers, $data) = get_http_response($url, $timeout);
4bf35ba5
V
26
27 if (strpos($headers[0], '200 OK') === false) {
28 error_log('Failed to retrieve ' . $url);
29 return false;
30 }
31
32 return str_replace(
33 array(self::$VERSION_START_TAG, self::$VERSION_END_TAG, PHP_EOL),
34 array('', '', ''),
35 $data
36 );
37 }
38
39 /**
40 * Checks if a new Shaarli version has been published on the Git repository
41 *
42 * Updates checks are run periodically, according to the following criteria:
43 * - the update checks are enabled (install, global config);
44 * - the user is logged in (or this is an open instance);
45 * - the last check is older than a given interval;
46 * - the check is non-blocking if the HTTPS connection to Git fails;
47 * - in case of failure, the update file's modification date is updated,
48 * to avoid intempestive connection attempts.
49 *
50 * @param string $currentVersion the current version code
51 * @param string $updateFile the file where to store the latest version code
52 * @param int $checkInterval the minimum interval between update checks (in seconds
53 * @param bool $enableCheck whether to check for new versions
54 * @param bool $isLoggedIn whether the user is logged in
7af9a418 55 * @param string $branch check update for the given branch
4bf35ba5 56 *
4a7af975
V
57 * @throws Exception an invalid branch has been set for update checks
58 *
4bf35ba5
V
59 * @return mixed the new version code if available and greater, else 'false'
60 */
4407b45f
V
61 public static function checkUpdate($currentVersion,
62 $updateFile,
63 $checkInterval,
64 $enableCheck,
65 $isLoggedIn,
66 $branch='stable')
4bf35ba5 67 {
b897c81f
A
68 // Do not check versions for visitors
69 // Do not check if the user doesn't want to
70 // Do not check with dev version
71 if (! $isLoggedIn || empty($enableCheck) || $currentVersion === 'dev') {
4bf35ba5
V
72 return false;
73 }
74
75 if (is_file($updateFile) && (filemtime($updateFile) > time() - $checkInterval)) {
76 // Shaarli has checked for updates recently - skip HTTP query
77 $latestKnownVersion = file_get_contents($updateFile);
78
79 if (version_compare($latestKnownVersion, $currentVersion) == 1) {
80 return $latestKnownVersion;
81 }
82 return false;
83 }
84
4407b45f
V
85 if (! in_array($branch, self::$GIT_BRANCHES)) {
86 throw new Exception(
87 'Invalid branch selected for updates: "' . $branch . '"'
88 );
89 }
90
4bf35ba5
V
91 // Late Static Binding allows overriding within tests
92 // See http://php.net/manual/en/language.oop5.late-static-bindings.php
93 $latestVersion = static::getLatestGitVersionCode(
4407b45f 94 self::$GIT_URL . '/' . $branch . '/' . self::$VERSION_FILE
4bf35ba5
V
95 );
96
97 if (! $latestVersion) {
98 // Only update the file's modification date
99 file_put_contents($updateFile, $currentVersion);
100 return false;
101 }
102
103 // Update the file's content and modification date
104 file_put_contents($updateFile, $latestVersion);
105
106 if (version_compare($latestVersion, $currentVersion) == 1) {
107 return $latestVersion;
108 }
109
110 return false;
111 }
2e28269b 112
c9cf2715
V
113 /**
114 * Checks the PHP version to ensure Shaarli can run
115 *
116 * @param string $minVersion minimum PHP required version
117 * @param string $curVersion current PHP version (use PHP_VERSION)
118 *
119 * @throws Exception the PHP version is not supported
120 */
121 public static function checkPHPVersion($minVersion, $curVersion)
122 {
123 if (version_compare($curVersion, $minVersion) < 0) {
124 throw new Exception(
125 'Your PHP version is obsolete!'
126 .' Shaarli requires at least PHP '.$minVersion.', and thus cannot run.'
127 .' Your PHP version has known security vulnerabilities and should be'
128 .' updated as soon as possible.'
129 );
130 }
131 }
132
2e28269b
V
133 /**
134 * Checks Shaarli has the proper access permissions to its resources
135 *
278d9ee2
A
136 * @param ConfigManager $conf Configuration Manager instance.
137 *
2e28269b
V
138 * @return array A list of the detected configuration issues
139 */
278d9ee2 140 public static function checkResourcePermissions($conf)
2e28269b
V
141 {
142 $errors = array();
143
144 // Check script and template directories are readable
145 foreach (array(
146 'application',
147 'inc',
148 'plugins',
894a3c4b 149 $conf->get('resource.raintpl_tpl'),
adc4aee8 150 $conf->get('resource.raintpl_tpl').'/'.$conf->get('resource.theme'),
2e28269b
V
151 ) as $path) {
152 if (! is_readable(realpath($path))) {
153 $errors[] = '"'.$path.'" directory is not readable';
154 }
155 }
156
7af9a418 157 // Check cache and data directories are readable and writable
2e28269b 158 foreach (array(
894a3c4b
A
159 $conf->get('resource.thumbnails_cache'),
160 $conf->get('resource.data_dir'),
161 $conf->get('resource.page_cache'),
162 $conf->get('resource.raintpl_tmp'),
2e28269b
V
163 ) as $path) {
164 if (! is_readable(realpath($path))) {
165 $errors[] = '"'.$path.'" directory is not readable';
166 }
167 if (! is_writable(realpath($path))) {
168 $errors[] = '"'.$path.'" directory is not writable';
169 }
170 }
171
7af9a418 172 // Check configuration files are readable and writable
2e28269b 173 foreach (array(
278d9ee2 174 $conf->getConfigFileExt(),
894a3c4b
A
175 $conf->get('resource.datastore'),
176 $conf->get('resource.ban_file'),
177 $conf->get('resource.log'),
178 $conf->get('resource.update_check'),
2e28269b
V
179 ) as $path) {
180 if (! is_file(realpath($path))) {
181 # the file may not exist yet
182 continue;
183 }
184
185 if (! is_readable(realpath($path))) {
186 $errors[] = '"'.$path.'" file is not readable';
187 }
188 if (! is_writable(realpath($path))) {
189 $errors[] = '"'.$path.'" file is not writable';
190 }
191 }
192
193 return $errors;
194 }
195}