X-Git-Url: https://git.immae.eu/?a=blobdiff_plain;f=application%2FApplicationUtils.php;h=bd1c7cf3f42a06a427d817821c5c9a058f549aba;hb=e6215a2ad97182efcf88ef532ec6bd65ae35fd19;hp=911873a071ca7813f7ef9e3fa75d8ce18b2f8ec8;hpb=d8acf8550480694d050091e270a06c01e7b313f0;p=github%2Fshaarli%2FShaarli.git diff --git a/application/ApplicationUtils.php b/application/ApplicationUtils.php index 911873a0..bd1c7cf3 100644 --- a/application/ApplicationUtils.php +++ b/application/ApplicationUtils.php @@ -1,4 +1,9 @@ '; @@ -24,7 +30,7 @@ class ApplicationUtils * * @return mixed the version code from the repository if available, else 'false' */ - public static function getLatestGitVersionCode($url, $timeout=2) + public static function getLatestGitVersionCode($url, $timeout = 2) { list($headers, $data) = get_http_response($url, $timeout); @@ -51,7 +57,7 @@ class ApplicationUtils return false; } } else { - if (! is_file($remote)) { + if (!is_file($remote)) { return false; } $data = file_get_contents($remote); @@ -86,17 +92,18 @@ class ApplicationUtils * * @return mixed the new version code if available and greater, else 'false' */ - public static function checkUpdate($currentVersion, - $updateFile, - $checkInterval, - $enableCheck, - $isLoggedIn, - $branch='stable') - { + public static function checkUpdate( + $currentVersion, + $updateFile, + $checkInterval, + $enableCheck, + $isLoggedIn, + $branch = 'stable' + ) { // Do not check versions for visitors // Do not check if the user doesn't want to // Do not check with dev version - if (! $isLoggedIn || empty($enableCheck) || $currentVersion === 'dev') { + if (!$isLoggedIn || empty($enableCheck) || $currentVersion === 'dev') { return false; } @@ -110,7 +117,7 @@ class ApplicationUtils return false; } - if (! in_array($branch, self::$GIT_BRANCHES)) { + if (!in_array($branch, self::$GIT_BRANCHES)) { throw new Exception( 'Invalid branch selected for updates: "' . $branch . '"' ); @@ -119,10 +126,10 @@ class ApplicationUtils // Late Static Binding allows overriding within tests // See http://php.net/manual/en/language.oop5.late-static-bindings.php $latestVersion = static::getVersion( - self::$GIT_URL . '/' . $branch . '/' . self::$VERSION_FILE + self::$GIT_RAW_URL . '/' . $branch . '/' . self::$VERSION_FILE ); - if (! $latestVersion) { + if (!$latestVersion) { // Only update the file's modification date file_put_contents($updateFile, $currentVersion); return false; @@ -144,6 +151,8 @@ class ApplicationUtils * @param string $minVersion minimum PHP required version * @param string $curVersion current PHP version (use PHP_VERSION) * + * @return bool true on success + * * @throws Exception the PHP version is not supported */ public static function checkPHPVersion($minVersion, $curVersion) @@ -151,72 +160,87 @@ class ApplicationUtils if (version_compare($curVersion, $minVersion) < 0) { $msg = t( 'Your PHP version is obsolete!' - . ' Shaarli requires at least PHP %s, and thus cannot run.' - . ' Your PHP version has known security vulnerabilities and should be' - . ' updated as soon as possible.' + . ' Shaarli requires at least PHP %s, and thus cannot run.' + . ' Your PHP version has known security vulnerabilities and should be' + . ' updated as soon as possible.' ); throw new Exception(sprintf($msg, $minVersion)); } + return true; } /** * Checks Shaarli has the proper access permissions to its resources * - * @param ConfigManager $conf Configuration Manager instance. + * @param ConfigManager $conf Configuration Manager instance. + * @param bool $minimalMode In minimal mode we only check permissions to be able to display a template. + * Currently we only need to be able to read the theme and write in raintpl cache. * * @return array A list of the detected configuration issues */ - public static function checkResourcePermissions($conf) + public static function checkResourcePermissions(ConfigManager $conf, bool $minimalMode = false): array { - $errors = array(); + $errors = []; $rainTplDir = rtrim($conf->get('resource.raintpl_tpl'), '/'); // Check script and template directories are readable - foreach (array( - 'application', - 'inc', - 'plugins', - $rainTplDir, - $rainTplDir.'/'.$conf->get('resource.theme'), - ) as $path) { - if (! is_readable(realpath($path))) { - $errors[] = '"'.$path.'" '. t('directory is not readable'); + foreach ([ + 'application', + 'inc', + 'plugins', + $rainTplDir, + $rainTplDir . '/' . $conf->get('resource.theme'), + ] as $path) { + if (!is_readable(realpath($path))) { + $errors[] = '"' . $path . '" ' . t('directory is not readable'); } } // Check cache and data directories are readable and writable - foreach (array( - $conf->get('resource.thumbnails_cache'), - $conf->get('resource.data_dir'), - $conf->get('resource.page_cache'), - $conf->get('resource.raintpl_tmp'), - ) as $path) { - if (! is_readable(realpath($path))) { - $errors[] = '"'.$path.'" '. t('directory is not readable'); + if ($minimalMode) { + $folders = [ + $conf->get('resource.raintpl_tmp'), + ]; + } else { + $folders = [ + $conf->get('resource.thumbnails_cache'), + $conf->get('resource.data_dir'), + $conf->get('resource.page_cache'), + $conf->get('resource.raintpl_tmp'), + ]; + } + + foreach ($folders as $path) { + if (!is_readable(realpath($path))) { + $errors[] = '"' . $path . '" ' . t('directory is not readable'); } - if (! is_writable(realpath($path))) { - $errors[] = '"'.$path.'" '. t('directory is not writable'); + if (!is_writable(realpath($path))) { + $errors[] = '"' . $path . '" ' . t('directory is not writable'); } } + if ($minimalMode) { + return $errors; + } + // Check configuration files are readable and writable foreach (array( - $conf->getConfigFileExt(), - $conf->get('resource.datastore'), - $conf->get('resource.ban_file'), - $conf->get('resource.log'), - $conf->get('resource.update_check'), - ) as $path) { - if (! is_file(realpath($path))) { + $conf->getConfigFileExt(), + $conf->get('resource.datastore'), + $conf->get('resource.ban_file'), + $conf->get('resource.log'), + $conf->get('resource.update_check'), + ) as $path) { + if (!is_file(realpath($path))) { # the file may not exist yet continue; } - if (! is_readable(realpath($path))) { - $errors[] = '"'.$path.'" '. t('file is not readable'); + if (!is_readable(realpath($path))) { + $errors[] = '"' . $path . '" ' . t('file is not readable'); } - if (! is_writable(realpath($path))) { - $errors[] = '"'.$path.'" '. t('file is not writable'); + if (!is_writable(realpath($path))) { + $errors[] = '"' . $path . '" ' . t('file is not writable'); } } @@ -237,4 +261,54 @@ class ApplicationUtils { return hash_hmac('sha256', $currentVersion, $salt); } + + /** + * Get a list of PHP extensions used by Shaarli. + * + * @return array[] List of extension with following keys: + * - name: extension name + * - required: whether the extension is required to use Shaarli + * - desc: short description of extension usage in Shaarli + * - loaded: whether the extension is properly loaded or not + */ + public static function getPhpExtensionsRequirement(): array + { + $extensions = [ + ['name' => 'json', 'required' => true, 'desc' => t('Configuration parsing')], + ['name' => 'simplexml', 'required' => true, 'desc' => t('Slim Framework (routing, etc.)')], + ['name' => 'mbstring', 'required' => true, 'desc' => t('Multibyte (Unicode) string support')], + ['name' => 'gd', 'required' => false, 'desc' => t('Required to use thumbnails')], + ['name' => 'intl', 'required' => false, 'desc' => t('Localized text sorting (e.g. e->è->f)')], + ['name' => 'curl', 'required' => false, 'desc' => t('Better retrieval of bookmark metadata and thumbnail')], + ['name' => 'gettext', 'required' => false, 'desc' => t('Use the translation system in gettext mode')], + ['name' => 'ldap', 'required' => false, 'desc' => t('Login using LDAP server')], + ]; + + foreach ($extensions as &$extension) { + $extension['loaded'] = extension_loaded($extension['name']); + } + + return $extensions; + } + + /** + * Return the EOL date of given PHP version. If the version is unknown, + * we return today + 2 years. + * + * @param string $fullVersion PHP version, e.g. 7.4.7 + * + * @return string Date format: YYYY-MM-DD + */ + public static function getPhpEol(string $fullVersion): string + { + preg_match('/(\d+\.\d+)\.\d+/', $fullVersion, $matches); + + return [ + '7.1' => '2019-12-01', + '7.2' => '2020-11-30', + '7.3' => '2021-12-06', + '7.4' => '2022-11-28', + '8.0' => '2023-12-01', + ][$matches[1]] ?? (new \DateTime('+2 year'))->format('Y-m-d'); + } }