Feature: add a Server administration page
It contains mostly read only information about the current Shaarli instance, PHP version, extensions, file and folder permissions, etc. Also action buttons to clear the cache or sync thumbnails. Part of the content of this page is also displayed on the install page, to check server requirement before installing Shaarli config file. Fixes #40 Fixes #185
This commit is contained in:
parent
d8030c8155
commit
0cf76ccb47
16 changed files with 1086 additions and 104 deletions
|
@ -14,8 +14,9 @@ class ApplicationUtils
|
|||
*/
|
||||
public static $VERSION_FILE = 'shaarli_version.php';
|
||||
|
||||
private static $GIT_URL = 'https://raw.githubusercontent.com/shaarli/Shaarli';
|
||||
private static $GIT_BRANCHES = array('latest', 'stable');
|
||||
public static $GITHUB_URL = 'https://github.com/shaarli/Shaarli';
|
||||
public static $GIT_RAW_URL = 'https://raw.githubusercontent.com/shaarli/Shaarli';
|
||||
public static $GIT_BRANCHES = array('latest', 'stable');
|
||||
private static $VERSION_START_TAG = '<?php /* ';
|
||||
private static $VERSION_END_TAG = ' */ ?>';
|
||||
|
||||
|
@ -125,7 +126,7 @@ public static function checkUpdate(
|
|||
// 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) {
|
||||
|
@ -171,35 +172,45 @@ public static function checkPHPVersion($minVersion, $curVersion)
|
|||
/**
|
||||
* 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(
|
||||
foreach ([
|
||||
'application',
|
||||
'inc',
|
||||
'plugins',
|
||||
$rainTplDir,
|
||||
$rainTplDir . '/' . $conf->get('resource.theme'),
|
||||
) as $path) {
|
||||
] 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 ($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');
|
||||
}
|
||||
|
@ -208,6 +219,10 @@ public static function checkResourcePermissions($conf)
|
|||
}
|
||||
}
|
||||
|
||||
if ($minimalMode) {
|
||||
return $errors;
|
||||
}
|
||||
|
||||
// Check configuration files are readable and writable
|
||||
foreach (array(
|
||||
$conf->getConfigFileExt(),
|
||||
|
@ -246,4 +261,54 @@ public static function getVersionHash($currentVersion, $salt)
|
|||
{
|
||||
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');
|
||||
}
|
||||
}
|
||||
|
|
|
@ -81,4 +81,60 @@ public static function readFlatDB($file, $default = null)
|
|||
)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Recursively deletes a folder content, and deletes itself optionally.
|
||||
* If an excluded file is found, folders won't be deleted.
|
||||
*
|
||||
* Additional security: raise an exception if it tries to delete a folder outside of Shaarli directory.
|
||||
*
|
||||
* @param string $path
|
||||
* @param bool $selfDelete Delete the provided folder if true, only its content if false.
|
||||
* @param array $exclude
|
||||
*/
|
||||
public static function clearFolder(string $path, bool $selfDelete, array $exclude = []): bool
|
||||
{
|
||||
$skipped = false;
|
||||
|
||||
if (!is_dir($path)) {
|
||||
throw new IOException(t('Provided path is not a directory.'));
|
||||
}
|
||||
|
||||
if (!static::isPathInShaarliFolder($path)) {
|
||||
throw new IOException(t('Trying to delete a folder outside of Shaarli path.'));
|
||||
}
|
||||
|
||||
foreach (new \DirectoryIterator($path) as $file) {
|
||||
if($file->isDot()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (in_array($file->getBasename(), $exclude, true)) {
|
||||
$skipped = true;
|
||||
continue;
|
||||
}
|
||||
|
||||
if ($file->isFile()) {
|
||||
unlink($file->getPathname());
|
||||
} elseif($file->isDir()) {
|
||||
$skipped = static::clearFolder($file->getRealPath(), true, $exclude) || $skipped;
|
||||
}
|
||||
}
|
||||
|
||||
if ($selfDelete && !$skipped) {
|
||||
rmdir($path);
|
||||
}
|
||||
|
||||
return $skipped;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks that the given path is inside Shaarli directory.
|
||||
*/
|
||||
public static function isPathInShaarliFolder(string $path): bool
|
||||
{
|
||||
$rootDirectory = dirname(dirname(__FILE__));
|
||||
|
||||
return strpos(realpath($path), $rootDirectory) !== false;
|
||||
}
|
||||
}
|
||||
|
|
87
application/front/controller/admin/ServerController.php
Normal file
87
application/front/controller/admin/ServerController.php
Normal file
|
@ -0,0 +1,87 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Shaarli\Front\Controller\Admin;
|
||||
|
||||
use Shaarli\ApplicationUtils;
|
||||
use Shaarli\FileUtils;
|
||||
use Slim\Http\Request;
|
||||
use Slim\Http\Response;
|
||||
|
||||
/**
|
||||
* Slim controller used to handle Server administration page, and actions.
|
||||
*/
|
||||
class ServerController extends ShaarliAdminController
|
||||
{
|
||||
/** @var string Cache type - main - by default pagecache/ and tmp/ */
|
||||
protected const CACHE_MAIN = 'main';
|
||||
|
||||
/** @var string Cache type - thumbnails - by default cache/ */
|
||||
protected const CACHE_THUMB = 'thumbnails';
|
||||
|
||||
/**
|
||||
* GET /admin/server - Display page Server administration
|
||||
*/
|
||||
public function index(Request $request, Response $response): Response
|
||||
{
|
||||
$latestVersion = 'v' . ApplicationUtils::getVersion(
|
||||
ApplicationUtils::$GIT_RAW_URL . '/latest/' . ApplicationUtils::$VERSION_FILE
|
||||
);
|
||||
$currentVersion = ApplicationUtils::getVersion('./shaarli_version.php');
|
||||
$currentVersion = $currentVersion === 'dev' ? $currentVersion : 'v' . $currentVersion;
|
||||
$phpEol = new \DateTimeImmutable(ApplicationUtils::getPhpEol(PHP_VERSION));
|
||||
|
||||
$this->assignView('php_version', PHP_VERSION);
|
||||
$this->assignView('php_eol', format_date($phpEol, false));
|
||||
$this->assignView('php_has_reached_eol', $phpEol < new \DateTimeImmutable());
|
||||
$this->assignView('php_extensions', ApplicationUtils::getPhpExtensionsRequirement());
|
||||
$this->assignView('permissions', ApplicationUtils::checkResourcePermissions($this->container->conf));
|
||||
$this->assignView('release_url', ApplicationUtils::$GITHUB_URL . '/releases/tag/' . $latestVersion);
|
||||
$this->assignView('latest_version', $latestVersion);
|
||||
$this->assignView('current_version', $currentVersion);
|
||||
$this->assignView('thumbnails_mode', $this->container->conf->get('thumbnails.mode'));
|
||||
$this->assignView('index_url', index_url($this->container->environment));
|
||||
$this->assignView('client_ip', client_ip_id($this->container->environment));
|
||||
$this->assignView('trusted_proxies', $this->container->conf->get('security.trusted_proxies', []));
|
||||
|
||||
$this->assignView(
|
||||
'pagetitle',
|
||||
t('Server administration') . ' - ' . $this->container->conf->get('general.title', 'Shaarli')
|
||||
);
|
||||
|
||||
return $response->write($this->render('server'));
|
||||
}
|
||||
|
||||
/**
|
||||
* GET /admin/clear-cache?type={$type} - Action to trigger cache folder clearing (either main or thumbnails).
|
||||
*/
|
||||
public function clearCache(Request $request, Response $response): Response
|
||||
{
|
||||
$exclude = ['.htaccess'];
|
||||
|
||||
if ($request->getQueryParam('type') === static::CACHE_THUMB) {
|
||||
$folders = [$this->container->conf->get('resource.thumbnails_cache')];
|
||||
|
||||
$this->saveWarningMessage(
|
||||
t('Thumbnails cache has been cleared.') . ' ' .
|
||||
'<a href="'. $this->container->basePath .'/admin/thumbnails">' . t('Please synchronize them.') .'</a>'
|
||||
);
|
||||
} else {
|
||||
$folders = [
|
||||
$this->container->conf->get('resource.page_cache'),
|
||||
$this->container->conf->get('resource.raintpl_tmp'),
|
||||
];
|
||||
|
||||
$this->saveSuccessMessage(t('Shaarli\'s cache folder has been cleared!'));
|
||||
}
|
||||
|
||||
// Make sure that we don't delete root cache folder
|
||||
$folders = array_map('realpath', array_values(array_filter(array_map('trim', $folders))));
|
||||
foreach ($folders as $folder) {
|
||||
FileUtils::clearFolder($folder, false, $exclude);
|
||||
}
|
||||
|
||||
return $this->redirect($response, '/admin/server');
|
||||
}
|
||||
}
|
|
@ -169,16 +169,24 @@ public function permalink(Request $request, Response $response, array $args): Re
|
|||
*/
|
||||
protected function updateThumbnail(Bookmark $bookmark, bool $writeDatastore = true): bool
|
||||
{
|
||||
// Logged in, not async retrieval, thumbnails enabled, and thumbnail should be updated
|
||||
if ($this->container->loginManager->isLoggedIn()
|
||||
&& true !== $this->container->conf->get('general.enable_async_metadata', true)
|
||||
&& $this->container->conf->get('thumbnails.mode', Thumbnailer::MODE_NONE) !== Thumbnailer::MODE_NONE
|
||||
&& $bookmark->shouldUpdateThumbnail()
|
||||
) {
|
||||
$bookmark->setThumbnail($this->container->thumbnailer->get($bookmark->getUrl()));
|
||||
$this->container->bookmarkService->set($bookmark, $writeDatastore);
|
||||
if (false === $this->container->loginManager->isLoggedIn()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
// If thumbnail should be updated, we reset it to null
|
||||
if ($bookmark->shouldUpdateThumbnail()) {
|
||||
$bookmark->setThumbnail(null);
|
||||
|
||||
// Requires an update, not async retrieval, thumbnails enabled
|
||||
if ($bookmark->shouldUpdateThumbnail()
|
||||
&& true !== $this->container->conf->get('general.enable_async_metadata', true)
|
||||
&& $this->container->conf->get('thumbnails.mode', Thumbnailer::MODE_NONE) !== Thumbnailer::MODE_NONE
|
||||
) {
|
||||
$bookmark->setThumbnail($this->container->thumbnailer->get($bookmark->getUrl()));
|
||||
$this->container->bookmarkService->set($bookmark, $writeDatastore);
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
|
|
|
@ -53,6 +53,16 @@ public function index(Request $request, Response $response): Response
|
|||
$this->assignView('cities', $cities);
|
||||
$this->assignView('languages', Languages::getAvailableLanguages());
|
||||
|
||||
$phpEol = new \DateTimeImmutable(ApplicationUtils::getPhpEol(PHP_VERSION));
|
||||
|
||||
$this->assignView('php_version', PHP_VERSION);
|
||||
$this->assignView('php_eol', format_date($phpEol, false));
|
||||
$this->assignView('php_has_reached_eol', $phpEol < new \DateTimeImmutable());
|
||||
$this->assignView('php_extensions', ApplicationUtils::getPhpExtensionsRequirement());
|
||||
$this->assignView('permissions', ApplicationUtils::checkResourcePermissions($this->container->conf));
|
||||
|
||||
$this->assignView('pagetitle', t('Install Shaarli'));
|
||||
|
||||
return $response->write($this->render('install'));
|
||||
}
|
||||
|
||||
|
@ -150,7 +160,7 @@ public function save(Request $request, Response $response): Response
|
|||
protected function checkPermissions(): bool
|
||||
{
|
||||
// Ensure Shaarli has proper access to its resources
|
||||
$errors = ApplicationUtils::checkResourcePermissions($this->container->conf);
|
||||
$errors = ApplicationUtils::checkResourcePermissions($this->container->conf, true);
|
||||
if (empty($errors)) {
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -1047,7 +1047,7 @@ body,
|
|||
}
|
||||
|
||||
table {
|
||||
margin: auto;
|
||||
margin: 10px auto 25px auto;
|
||||
width: 90%;
|
||||
|
||||
.order {
|
||||
|
@ -1696,6 +1696,60 @@ form {
|
|||
}
|
||||
}
|
||||
|
||||
// SERVER PAGE
|
||||
|
||||
.server-tables-page,
|
||||
.server-tables {
|
||||
.window-subtitle {
|
||||
&::before {
|
||||
display: block;
|
||||
margin: 8px auto;
|
||||
background: linear-gradient(to right, var(--background-color), $dark-grey, var(--background-color));
|
||||
width: 50%;
|
||||
height: 1px;
|
||||
content: '';
|
||||
}
|
||||
}
|
||||
|
||||
.server-row {
|
||||
p {
|
||||
height: 25px;
|
||||
padding: 0 10px;
|
||||
}
|
||||
}
|
||||
|
||||
.server-label {
|
||||
text-align: right;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
i {
|
||||
&.fa-color-green {
|
||||
color: $main-green;
|
||||
}
|
||||
|
||||
&.fa-color-orange {
|
||||
color: $orange;
|
||||
}
|
||||
|
||||
&.fa-color-red {
|
||||
color: $red;
|
||||
}
|
||||
}
|
||||
|
||||
@media screen and (max-width: 64em) {
|
||||
.server-label {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.server-row {
|
||||
p {
|
||||
text-align: center;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Print rules
|
||||
@media print {
|
||||
.shaarli-menu {
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: Shaarli\n"
|
||||
"POT-Creation-Date: 2020-10-16 20:01+0200\n"
|
||||
"PO-Revision-Date: 2020-10-16 20:02+0200\n"
|
||||
"POT-Creation-Date: 2020-10-21 15:00+0200\n"
|
||||
"PO-Revision-Date: 2020-10-21 15:06+0200\n"
|
||||
"Last-Translator: \n"
|
||||
"Language-Team: Shaarli\n"
|
||||
"Language: fr_FR\n"
|
||||
|
@ -20,7 +20,7 @@ msgstr ""
|
|||
"X-Poedit-SearchPath-3: init.php\n"
|
||||
"X-Poedit-SearchPath-4: plugins\n"
|
||||
|
||||
#: application/ApplicationUtils.php:161
|
||||
#: application/ApplicationUtils.php:162
|
||||
#, php-format
|
||||
msgid ""
|
||||
"Your PHP version is obsolete! Shaarli requires at least PHP %s, and thus "
|
||||
|
@ -31,22 +31,62 @@ msgstr ""
|
|||
"peut donc pas fonctionner. Votre version de PHP a des failles de sécurités "
|
||||
"connues et devrait être mise à jour au plus tôt."
|
||||
|
||||
#: application/ApplicationUtils.php:192 application/ApplicationUtils.php:204
|
||||
#: application/ApplicationUtils.php:195 application/ApplicationUtils.php:215
|
||||
msgid "directory is not readable"
|
||||
msgstr "le répertoire n'est pas accessible en lecture"
|
||||
|
||||
#: application/ApplicationUtils.php:207
|
||||
#: application/ApplicationUtils.php:218
|
||||
msgid "directory is not writable"
|
||||
msgstr "le répertoire n'est pas accessible en écriture"
|
||||
|
||||
#: application/ApplicationUtils.php:225
|
||||
#: application/ApplicationUtils.php:240
|
||||
msgid "file is not readable"
|
||||
msgstr "le fichier n'est pas accessible en lecture"
|
||||
|
||||
#: application/ApplicationUtils.php:228
|
||||
#: application/ApplicationUtils.php:243
|
||||
msgid "file is not writable"
|
||||
msgstr "le fichier n'est pas accessible en écriture"
|
||||
|
||||
#: application/ApplicationUtils.php:277
|
||||
msgid "Configuration parsing"
|
||||
msgstr "Chargement de la configuration"
|
||||
|
||||
#: application/ApplicationUtils.php:278
|
||||
msgid "Slim Framework (routing, etc.)"
|
||||
msgstr "Slim Framwork (routage, etc.)"
|
||||
|
||||
#: application/ApplicationUtils.php:279
|
||||
msgid "Multibyte (Unicode) string support"
|
||||
msgstr "Support des chaînes de caractère multibytes (Unicode)"
|
||||
|
||||
#: application/ApplicationUtils.php:280
|
||||
msgid "Required to use thumbnails"
|
||||
msgstr "Obligatoire pour utiliser les miniatures"
|
||||
|
||||
#: application/ApplicationUtils.php:281
|
||||
msgid "Localized text sorting (e.g. e->è->f)"
|
||||
msgstr "Tri des textes traduits (ex : e->è->f)"
|
||||
|
||||
#: application/ApplicationUtils.php:282
|
||||
msgid "Better retrieval of bookmark metadata and thumbnail"
|
||||
msgstr "Meilleure récupération des meta-données des marque-pages et minatures"
|
||||
|
||||
#: application/ApplicationUtils.php:283
|
||||
msgid "Use the translation system in gettext mode"
|
||||
msgstr "Utiliser le système de traduction en mode gettext"
|
||||
|
||||
#: application/ApplicationUtils.php:284
|
||||
msgid "Login using LDAP server"
|
||||
msgstr "Authentification via un serveur LDAP"
|
||||
|
||||
#: application/FileUtils.php:100
|
||||
msgid "Provided path is not a directory."
|
||||
msgstr "Le chemin fourni n'est pas un dossier."
|
||||
|
||||
#: application/FileUtils.php:104
|
||||
msgid "Trying to delete a folder outside of Shaarli path."
|
||||
msgstr "Tentative de supprimer un dossier en dehors du chemin de Shaarli."
|
||||
|
||||
#: application/History.php:179
|
||||
msgid "History file isn't readable or writable"
|
||||
msgstr "Le fichier d'historique n'est pas accessible en lecture ou en écriture"
|
||||
|
@ -330,12 +370,13 @@ msgid "You have enabled or changed thumbnails mode."
|
|||
msgstr "Vous avez activé ou changé le mode de miniatures."
|
||||
|
||||
#: application/front/controller/admin/ConfigureController.php:103
|
||||
#: application/front/controller/admin/ServerController.php:68
|
||||
#: application/legacy/LegacyUpdater.php:538
|
||||
msgid "Please synchronize them."
|
||||
msgstr "Merci de les synchroniser."
|
||||
|
||||
#: application/front/controller/admin/ConfigureController.php:113
|
||||
#: application/front/controller/visitor/InstallController.php:136
|
||||
#: application/front/controller/visitor/InstallController.php:146
|
||||
msgid "Error while writing config file after configuration update."
|
||||
msgstr ""
|
||||
"Une erreur s'est produite lors de la sauvegarde du fichier de configuration."
|
||||
|
@ -377,33 +418,33 @@ msgstr ""
|
|||
msgid "Shaare a new link"
|
||||
msgstr "Partager un nouveau lien"
|
||||
|
||||
#: application/front/controller/admin/ManageShaareController.php:78
|
||||
#: application/front/controller/admin/ManageShaareController.php:64
|
||||
msgid "Note: "
|
||||
msgstr "Note : "
|
||||
|
||||
#: application/front/controller/admin/ManageShaareController.php:109
|
||||
#: application/front/controller/admin/ManageShaareController.php:206
|
||||
#: application/front/controller/admin/ManageShaareController.php:275
|
||||
#: application/front/controller/admin/ManageShaareController.php:315
|
||||
#: application/front/controller/admin/ManageShaareController.php:95
|
||||
#: application/front/controller/admin/ManageShaareController.php:193
|
||||
#: application/front/controller/admin/ManageShaareController.php:262
|
||||
#: application/front/controller/admin/ManageShaareController.php:302
|
||||
#, php-format
|
||||
msgid "Bookmark with identifier %s could not be found."
|
||||
msgstr "Le lien avec l'identifiant %s n'a pas pu être trouvé."
|
||||
|
||||
#: application/front/controller/admin/ManageShaareController.php:194
|
||||
#: application/front/controller/admin/ManageShaareController.php:252
|
||||
#: application/front/controller/admin/ManageShaareController.php:181
|
||||
#: application/front/controller/admin/ManageShaareController.php:239
|
||||
msgid "Invalid bookmark ID provided."
|
||||
msgstr "ID du lien non valide."
|
||||
|
||||
#: application/front/controller/admin/ManageShaareController.php:260
|
||||
#: application/front/controller/admin/ManageShaareController.php:247
|
||||
msgid "Invalid visibility provided."
|
||||
msgstr "Visibilité du lien non valide."
|
||||
|
||||
#: application/front/controller/admin/ManageShaareController.php:363
|
||||
#: application/front/controller/admin/ManageShaareController.php:352
|
||||
#: tmp/linklist.b91ef64efc3688266305ea9b42e5017e.rtpl.php:171
|
||||
msgid "Edit"
|
||||
msgstr "Modifier"
|
||||
|
||||
#: application/front/controller/admin/ManageShaareController.php:366
|
||||
#: application/front/controller/admin/ManageShaareController.php:355
|
||||
#: tmp/page.header.b91ef64efc3688266305ea9b42e5017e.rtpl.php:28
|
||||
#: tmp/page.header.cedf684561d925457130839629000a81.rtpl.php:28
|
||||
msgid "Shaare"
|
||||
|
@ -411,7 +452,7 @@ msgstr "Shaare"
|
|||
|
||||
#: application/front/controller/admin/ManageTagController.php:29
|
||||
#: tmp/changetag.b91ef64efc3688266305ea9b42e5017e.rtpl.php:13
|
||||
#: tmp/tools.b91ef64efc3688266305ea9b42e5017e.rtpl.php:36
|
||||
#: tmp/tools.b91ef64efc3688266305ea9b42e5017e.rtpl.php:42
|
||||
msgid "Manage tags"
|
||||
msgstr "Gérer les tags"
|
||||
|
||||
|
@ -435,7 +476,7 @@ msgstr[1] "Le tag a été renommé dans %d liens."
|
|||
|
||||
#: application/front/controller/admin/PasswordController.php:28
|
||||
#: tmp/changepassword.b91ef64efc3688266305ea9b42e5017e.rtpl.php:13
|
||||
#: tmp/tools.b91ef64efc3688266305ea9b42e5017e.rtpl.php:29
|
||||
#: tmp/tools.b91ef64efc3688266305ea9b42e5017e.rtpl.php:35
|
||||
msgid "Change password"
|
||||
msgstr "Modifier le mot de passe"
|
||||
|
||||
|
@ -467,6 +508,20 @@ msgstr ""
|
|||
"Une erreur s'est produite lors de la sauvegarde de la configuration des "
|
||||
"plugins : "
|
||||
|
||||
#: application/front/controller/admin/ServerController.php:50
|
||||
#: tmp/server.b91ef64efc3688266305ea9b42e5017e.rtpl.php:14
|
||||
#: tmp/tools.b91ef64efc3688266305ea9b42e5017e.rtpl.php:28
|
||||
msgid "Server administration"
|
||||
msgstr "Administration serveur"
|
||||
|
||||
#: application/front/controller/admin/ServerController.php:67
|
||||
msgid "Thumbnails cache has been cleared."
|
||||
msgstr "Le cache des miniatures a été vidé."
|
||||
|
||||
#: application/front/controller/admin/ServerController.php:76
|
||||
msgid "Shaarli's cache folder has been cleared!"
|
||||
msgstr "Le dossier de cache de Shaarli a été vidé !"
|
||||
|
||||
#: application/front/controller/admin/ThumbnailsController.php:37
|
||||
#: tmp/thumbnails.b91ef64efc3688266305ea9b42e5017e.rtpl.php:14
|
||||
msgid "Thumbnails update"
|
||||
|
@ -502,9 +557,14 @@ msgstr "Une erreur inattendue s'est produite."
|
|||
|
||||
#: application/front/controller/visitor/ErrorNotFoundController.php:25
|
||||
msgid "Requested page could not be found."
|
||||
msgstr ""
|
||||
msgstr "La page demandée n'a pas pu être trouvée."
|
||||
|
||||
#: application/front/controller/visitor/InstallController.php:73
|
||||
#: application/front/controller/visitor/InstallController.php:64
|
||||
#: tmp/install.b91ef64efc3688266305ea9b42e5017e.rtpl.php:22
|
||||
msgid "Install Shaarli"
|
||||
msgstr "Installation de Shaarli"
|
||||
|
||||
#: application/front/controller/visitor/InstallController.php:83
|
||||
#, php-format
|
||||
msgid ""
|
||||
"<pre>Sessions do not seem to work correctly on your server.<br>Make sure the "
|
||||
|
@ -523,14 +583,14 @@ msgstr ""
|
|||
"des cookies. Nous vous recommandons d'accéder à votre serveur depuis son "
|
||||
"adresse IP ou un <em>Fully Qualified Domain Name</em>.<br>"
|
||||
|
||||
#: application/front/controller/visitor/InstallController.php:144
|
||||
#: application/front/controller/visitor/InstallController.php:154
|
||||
msgid ""
|
||||
"Shaarli is now configured. Please login and start shaaring your bookmarks!"
|
||||
msgstr ""
|
||||
"Shaarli est maintenant configuré. Vous pouvez vous connecter et commencez à "
|
||||
"shaare vos liens !"
|
||||
|
||||
#: application/front/controller/visitor/InstallController.php:158
|
||||
#: application/front/controller/visitor/InstallController.php:168
|
||||
msgid "Insufficient permissions:"
|
||||
msgstr "Permissions insuffisantes :"
|
||||
|
||||
|
@ -1016,25 +1076,28 @@ msgstr ""
|
|||
"miniatures."
|
||||
|
||||
#: tmp/configure.b91ef64efc3688266305ea9b42e5017e.rtpl.php:328
|
||||
#: tmp/tools.b91ef64efc3688266305ea9b42e5017e.rtpl.php:56
|
||||
#: tmp/server.b91ef64efc3688266305ea9b42e5017e.rtpl.php:122
|
||||
msgid "Synchronize thumbnails"
|
||||
msgstr "Synchroniser les miniatures"
|
||||
|
||||
#: tmp/configure.b91ef64efc3688266305ea9b42e5017e.rtpl.php:339
|
||||
#: tmp/export.b91ef64efc3688266305ea9b42e5017e.rtpl.php:30
|
||||
#: tmp/server.b91ef64efc3688266305ea9b42e5017e.rtpl.php:102
|
||||
msgid "All"
|
||||
msgstr "Tous"
|
||||
|
||||
#: tmp/configure.b91ef64efc3688266305ea9b42e5017e.rtpl.php:343
|
||||
#: tmp/server.b91ef64efc3688266305ea9b42e5017e.rtpl.php:106
|
||||
msgid "Only common media hosts"
|
||||
msgstr "Seulement les hébergeurs de média connus"
|
||||
|
||||
#: tmp/configure.b91ef64efc3688266305ea9b42e5017e.rtpl.php:347
|
||||
#: tmp/server.b91ef64efc3688266305ea9b42e5017e.rtpl.php:110
|
||||
msgid "None"
|
||||
msgstr "Aucune"
|
||||
|
||||
#: tmp/configure.b91ef64efc3688266305ea9b42e5017e.rtpl.php:355
|
||||
#: tmp/editlink.b91ef64efc3688266305ea9b42e5017e.rtpl.php:88
|
||||
#: tmp/editlink.b91ef64efc3688266305ea9b42e5017e.rtpl.php:102
|
||||
#: tmp/pluginsadmin.b91ef64efc3688266305ea9b42e5017e.rtpl.php:139
|
||||
#: tmp/pluginsadmin.b91ef64efc3688266305ea9b42e5017e.rtpl.php:199
|
||||
msgid "Save"
|
||||
|
@ -1060,27 +1123,27 @@ msgstr "Tous les liens d'un jour sur une page."
|
|||
msgid "Next day"
|
||||
msgstr "Jour suivant"
|
||||
|
||||
#: tmp/editlink.b91ef64efc3688266305ea9b42e5017e.rtpl.php:18
|
||||
#: tmp/editlink.b91ef64efc3688266305ea9b42e5017e.rtpl.php:21
|
||||
msgid "Edit Shaare"
|
||||
msgstr "Modifier le Shaare"
|
||||
|
||||
#: tmp/editlink.b91ef64efc3688266305ea9b42e5017e.rtpl.php:18
|
||||
#: tmp/editlink.b91ef64efc3688266305ea9b42e5017e.rtpl.php:21
|
||||
msgid "New Shaare"
|
||||
msgstr "Nouveau Shaare"
|
||||
|
||||
#: tmp/editlink.b91ef64efc3688266305ea9b42e5017e.rtpl.php:26
|
||||
#: tmp/editlink.b91ef64efc3688266305ea9b42e5017e.rtpl.php:29
|
||||
msgid "Created:"
|
||||
msgstr "Création :"
|
||||
|
||||
#: tmp/editlink.b91ef64efc3688266305ea9b42e5017e.rtpl.php:29
|
||||
#: tmp/editlink.b91ef64efc3688266305ea9b42e5017e.rtpl.php:32
|
||||
msgid "URL"
|
||||
msgstr "URL"
|
||||
|
||||
#: tmp/editlink.b91ef64efc3688266305ea9b42e5017e.rtpl.php:35
|
||||
#: tmp/editlink.b91ef64efc3688266305ea9b42e5017e.rtpl.php:38
|
||||
msgid "Title"
|
||||
msgstr "Titre"
|
||||
|
||||
#: tmp/editlink.b91ef64efc3688266305ea9b42e5017e.rtpl.php:41
|
||||
#: tmp/editlink.b91ef64efc3688266305ea9b42e5017e.rtpl.php:49
|
||||
#: tmp/pluginsadmin.b91ef64efc3688266305ea9b42e5017e.rtpl.php:42
|
||||
#: tmp/pluginsadmin.b91ef64efc3688266305ea9b42e5017e.rtpl.php:75
|
||||
#: tmp/pluginsadmin.b91ef64efc3688266305ea9b42e5017e.rtpl.php:99
|
||||
|
@ -1088,33 +1151,33 @@ msgstr "Titre"
|
|||
msgid "Description"
|
||||
msgstr "Description"
|
||||
|
||||
#: tmp/editlink.b91ef64efc3688266305ea9b42e5017e.rtpl.php:47
|
||||
#: tmp/editlink.b91ef64efc3688266305ea9b42e5017e.rtpl.php:58
|
||||
msgid "Tags"
|
||||
msgstr "Tags"
|
||||
|
||||
#: tmp/editlink.b91ef64efc3688266305ea9b42e5017e.rtpl.php:60
|
||||
#: tmp/editlink.b91ef64efc3688266305ea9b42e5017e.rtpl.php:74
|
||||
#: tmp/export.b91ef64efc3688266305ea9b42e5017e.rtpl.php:35
|
||||
#: tmp/linklist.b91ef64efc3688266305ea9b42e5017e.rtpl.php:169
|
||||
msgid "Private"
|
||||
msgstr "Privé"
|
||||
|
||||
#: tmp/editlink.b91ef64efc3688266305ea9b42e5017e.rtpl.php:66
|
||||
#: tmp/editlink.b91ef64efc3688266305ea9b42e5017e.rtpl.php:80
|
||||
msgid "Description will be rendered with"
|
||||
msgstr "La description sera générée avec"
|
||||
|
||||
#: tmp/editlink.b91ef64efc3688266305ea9b42e5017e.rtpl.php:68
|
||||
#: tmp/editlink.b91ef64efc3688266305ea9b42e5017e.rtpl.php:82
|
||||
msgid "Markdown syntax documentation"
|
||||
msgstr "Documentation sur la syntaxe Markdown"
|
||||
|
||||
#: tmp/editlink.b91ef64efc3688266305ea9b42e5017e.rtpl.php:69
|
||||
#: tmp/editlink.b91ef64efc3688266305ea9b42e5017e.rtpl.php:83
|
||||
msgid "Markdown syntax"
|
||||
msgstr "la syntaxe Markdown"
|
||||
|
||||
#: tmp/editlink.b91ef64efc3688266305ea9b42e5017e.rtpl.php:88
|
||||
#: tmp/editlink.b91ef64efc3688266305ea9b42e5017e.rtpl.php:102
|
||||
msgid "Apply Changes"
|
||||
msgstr "Appliquer les changements"
|
||||
|
||||
#: tmp/editlink.b91ef64efc3688266305ea9b42e5017e.rtpl.php:93
|
||||
#: tmp/editlink.b91ef64efc3688266305ea9b42e5017e.rtpl.php:107
|
||||
#: tmp/linklist.b91ef64efc3688266305ea9b42e5017e.rtpl.php:173
|
||||
#: tmp/page.header.b91ef64efc3688266305ea9b42e5017e.rtpl.php:147
|
||||
#: tmp/page.header.cedf684561d925457130839629000a81.rtpl.php:147
|
||||
|
@ -1179,10 +1242,6 @@ msgstr "Les doublons s'appuient sur les URL"
|
|||
msgid "Add default tags"
|
||||
msgstr "Ajouter des tags par défaut"
|
||||
|
||||
#: tmp/install.b91ef64efc3688266305ea9b42e5017e.rtpl.php:22
|
||||
msgid "Install Shaarli"
|
||||
msgstr "Installation de Shaarli"
|
||||
|
||||
#: tmp/install.b91ef64efc3688266305ea9b42e5017e.rtpl.php:25
|
||||
msgid "It looks like it's the first time you run Shaarli. Please configure it."
|
||||
msgstr ""
|
||||
|
@ -1215,6 +1274,10 @@ msgstr "Mes liens"
|
|||
msgid "Install"
|
||||
msgstr "Installer"
|
||||
|
||||
#: tmp/install.b91ef64efc3688266305ea9b42e5017e.rtpl.php:190
|
||||
msgid "Server requirements"
|
||||
msgstr "Pré-requis serveur"
|
||||
|
||||
#: tmp/linklist.b91ef64efc3688266305ea9b42e5017e.rtpl.php:14
|
||||
#: tmp/linklist.b91ef64efc3688266305ea9b42e5017e.rtpl.php:79
|
||||
msgid "shaare"
|
||||
|
@ -1511,6 +1574,100 @@ msgstr "Configuration des extensions"
|
|||
msgid "No parameter available."
|
||||
msgstr "Aucun paramètre disponible."
|
||||
|
||||
#: tmp/server.b91ef64efc3688266305ea9b42e5017e.rtpl.php:16
|
||||
msgid "General"
|
||||
msgstr "Général"
|
||||
|
||||
#: tmp/server.b91ef64efc3688266305ea9b42e5017e.rtpl.php:20
|
||||
msgid "Index URL"
|
||||
msgstr "URL de l'index"
|
||||
|
||||
#: tmp/server.b91ef64efc3688266305ea9b42e5017e.rtpl.php:28
|
||||
msgid "Base path"
|
||||
msgstr "Chemin de base"
|
||||
|
||||
#: tmp/server.b91ef64efc3688266305ea9b42e5017e.rtpl.php:36
|
||||
msgid "Client IP"
|
||||
msgstr "IP du client"
|
||||
|
||||
#: tmp/server.b91ef64efc3688266305ea9b42e5017e.rtpl.php:44
|
||||
msgid "Trusted reverse proxies"
|
||||
msgstr "Reverse proxies de confiance"
|
||||
|
||||
#: tmp/server.b91ef64efc3688266305ea9b42e5017e.rtpl.php:58
|
||||
msgid "N/A"
|
||||
msgstr "N/A"
|
||||
|
||||
#: tmp/server.b91ef64efc3688266305ea9b42e5017e.rtpl.php:84
|
||||
msgid "Visit releases page on Github"
|
||||
msgstr "Visiter la page des releases sur Github"
|
||||
|
||||
#: tmp/server.b91ef64efc3688266305ea9b42e5017e.rtpl.php:121
|
||||
msgid "Synchronize all link thumbnails"
|
||||
msgstr "Synchroniser toutes les miniatures"
|
||||
|
||||
#: tmp/server.requirements.b91ef64efc3688266305ea9b42e5017e.rtpl.php:2
|
||||
#: tmp/server.requirements.cedf684561d925457130839629000a81.rtpl.php:2
|
||||
msgid "Permissions"
|
||||
msgstr "Permissions"
|
||||
|
||||
#: tmp/server.requirements.b91ef64efc3688266305ea9b42e5017e.rtpl.php:8
|
||||
#: tmp/server.requirements.cedf684561d925457130839629000a81.rtpl.php:8
|
||||
msgid "There are permissions that need to be fixed."
|
||||
msgstr "Il y a des permissions qui doivent être corrigées."
|
||||
|
||||
#: tmp/server.requirements.b91ef64efc3688266305ea9b42e5017e.rtpl.php:23
|
||||
#: tmp/server.requirements.cedf684561d925457130839629000a81.rtpl.php:23
|
||||
msgid "All read/write permissions are properly set."
|
||||
msgstr "Toutes les permissions de lecture/écriture sont définies correctement."
|
||||
|
||||
#: tmp/server.requirements.b91ef64efc3688266305ea9b42e5017e.rtpl.php:32
|
||||
#: tmp/server.requirements.cedf684561d925457130839629000a81.rtpl.php:32
|
||||
msgid "Running PHP"
|
||||
msgstr "Fonctionnant avec PHP"
|
||||
|
||||
#: tmp/server.requirements.b91ef64efc3688266305ea9b42e5017e.rtpl.php:36
|
||||
#: tmp/server.requirements.cedf684561d925457130839629000a81.rtpl.php:36
|
||||
msgid "End of life: "
|
||||
msgstr "Fin de vie : "
|
||||
|
||||
#: tmp/server.requirements.b91ef64efc3688266305ea9b42e5017e.rtpl.php:48
|
||||
#: tmp/server.requirements.cedf684561d925457130839629000a81.rtpl.php:48
|
||||
msgid "Extension"
|
||||
msgstr "Extension"
|
||||
|
||||
#: tmp/server.requirements.b91ef64efc3688266305ea9b42e5017e.rtpl.php:49
|
||||
#: tmp/server.requirements.cedf684561d925457130839629000a81.rtpl.php:49
|
||||
msgid "Usage"
|
||||
msgstr "Utilisation"
|
||||
|
||||
#: tmp/server.requirements.b91ef64efc3688266305ea9b42e5017e.rtpl.php:50
|
||||
#: tmp/server.requirements.cedf684561d925457130839629000a81.rtpl.php:50
|
||||
msgid "Status"
|
||||
msgstr "Statut"
|
||||
|
||||
#: tmp/server.requirements.b91ef64efc3688266305ea9b42e5017e.rtpl.php:51
|
||||
#: tmp/server.requirements.b91ef64efc3688266305ea9b42e5017e.rtpl.php:66
|
||||
#: tmp/server.requirements.cedf684561d925457130839629000a81.rtpl.php:51
|
||||
#: tmp/server.requirements.cedf684561d925457130839629000a81.rtpl.php:66
|
||||
msgid "Loaded"
|
||||
msgstr "Chargé"
|
||||
|
||||
#: tmp/server.requirements.b91ef64efc3688266305ea9b42e5017e.rtpl.php:60
|
||||
#: tmp/server.requirements.cedf684561d925457130839629000a81.rtpl.php:60
|
||||
msgid "Required"
|
||||
msgstr "Obligatoire"
|
||||
|
||||
#: tmp/server.requirements.b91ef64efc3688266305ea9b42e5017e.rtpl.php:60
|
||||
#: tmp/server.requirements.cedf684561d925457130839629000a81.rtpl.php:60
|
||||
msgid "Optional"
|
||||
msgstr "Optionnel"
|
||||
|
||||
#: tmp/server.requirements.b91ef64efc3688266305ea9b42e5017e.rtpl.php:70
|
||||
#: tmp/server.requirements.cedf684561d925457130839629000a81.rtpl.php:70
|
||||
msgid "Not loaded"
|
||||
msgstr "Non chargé"
|
||||
|
||||
#: tmp/tag.cloud.b91ef64efc3688266305ea9b42e5017e.rtpl.php:19
|
||||
#: tmp/tag.list.b91ef64efc3688266305ea9b42e5017e.rtpl.php:19
|
||||
msgid "tags"
|
||||
|
@ -1561,15 +1718,19 @@ msgstr "Configurer Shaarli"
|
|||
msgid "Enable, disable and configure plugins"
|
||||
msgstr "Activer, désactiver et configurer les extensions"
|
||||
|
||||
#: tmp/tools.b91ef64efc3688266305ea9b42e5017e.rtpl.php:28
|
||||
#: tmp/tools.b91ef64efc3688266305ea9b42e5017e.rtpl.php:27
|
||||
msgid "Check instance's server configuration"
|
||||
msgstr "Vérifier la configuration serveur de l'instance"
|
||||
|
||||
#: tmp/tools.b91ef64efc3688266305ea9b42e5017e.rtpl.php:34
|
||||
msgid "Change your password"
|
||||
msgstr "Modifier le mot de passe"
|
||||
|
||||
#: tmp/tools.b91ef64efc3688266305ea9b42e5017e.rtpl.php:35
|
||||
#: tmp/tools.b91ef64efc3688266305ea9b42e5017e.rtpl.php:41
|
||||
msgid "Rename or delete a tag in all links"
|
||||
msgstr "Renommer ou supprimer un tag dans tous les liens"
|
||||
|
||||
#: tmp/tools.b91ef64efc3688266305ea9b42e5017e.rtpl.php:41
|
||||
#: tmp/tools.b91ef64efc3688266305ea9b42e5017e.rtpl.php:47
|
||||
msgid ""
|
||||
"Import Netscape HTML bookmarks (as exported from Firefox, Chrome, Opera, "
|
||||
"delicious...)"
|
||||
|
@ -1577,11 +1738,11 @@ msgstr ""
|
|||
"Importer des marques pages au format Netscape HTML (comme exportés depuis "
|
||||
"Firefox, Chrome, Opera, delicious...)"
|
||||
|
||||
#: tmp/tools.b91ef64efc3688266305ea9b42e5017e.rtpl.php:42
|
||||
#: tmp/tools.b91ef64efc3688266305ea9b42e5017e.rtpl.php:48
|
||||
msgid "Import links"
|
||||
msgstr "Importer des liens"
|
||||
|
||||
#: tmp/tools.b91ef64efc3688266305ea9b42e5017e.rtpl.php:47
|
||||
#: tmp/tools.b91ef64efc3688266305ea9b42e5017e.rtpl.php:53
|
||||
msgid ""
|
||||
"Export Netscape HTML bookmarks (which can be imported in Firefox, Chrome, "
|
||||
"Opera, delicious...)"
|
||||
|
@ -1589,15 +1750,11 @@ msgstr ""
|
|||
"Exporter les marques pages au format Netscape HTML (comme exportés depuis "
|
||||
"Firefox, Chrome, Opera, delicious...)"
|
||||
|
||||
#: tmp/tools.b91ef64efc3688266305ea9b42e5017e.rtpl.php:48
|
||||
#: tmp/tools.b91ef64efc3688266305ea9b42e5017e.rtpl.php:54
|
||||
msgid "Export database"
|
||||
msgstr "Exporter les données"
|
||||
|
||||
#: tmp/tools.b91ef64efc3688266305ea9b42e5017e.rtpl.php:55
|
||||
msgid "Synchronize all link thumbnails"
|
||||
msgstr "Synchroniser toutes les miniatures"
|
||||
|
||||
#: tmp/tools.b91ef64efc3688266305ea9b42e5017e.rtpl.php:81
|
||||
#: tmp/tools.b91ef64efc3688266305ea9b42e5017e.rtpl.php:77
|
||||
msgid ""
|
||||
"Drag one of these button to your bookmarks toolbar or right-click it and "
|
||||
"\"Bookmark This Link\""
|
||||
|
@ -1605,13 +1762,13 @@ msgstr ""
|
|||
"Glisser un de ces boutons dans votre barre de favoris ou cliquer droit "
|
||||
"dessus et « Ajouter aux favoris »"
|
||||
|
||||
#: tmp/tools.b91ef64efc3688266305ea9b42e5017e.rtpl.php:82
|
||||
#: tmp/tools.b91ef64efc3688266305ea9b42e5017e.rtpl.php:78
|
||||
msgid "then click on the bookmarklet in any page you want to share."
|
||||
msgstr ""
|
||||
"puis cliquer sur le marque-page depuis un site que vous souhaitez partager."
|
||||
|
||||
#: tmp/tools.b91ef64efc3688266305ea9b42e5017e.rtpl.php:86
|
||||
#: tmp/tools.b91ef64efc3688266305ea9b42e5017e.rtpl.php:110
|
||||
#: tmp/tools.b91ef64efc3688266305ea9b42e5017e.rtpl.php:82
|
||||
#: tmp/tools.b91ef64efc3688266305ea9b42e5017e.rtpl.php:106
|
||||
msgid ""
|
||||
"Drag this link to your bookmarks toolbar or right-click it and Bookmark This "
|
||||
"Link"
|
||||
|
@ -1619,40 +1776,40 @@ msgstr ""
|
|||
"Glisser ce lien dans votre barre de favoris ou cliquer droit dessus et « "
|
||||
"Ajouter aux favoris »"
|
||||
|
||||
#: tmp/tools.b91ef64efc3688266305ea9b42e5017e.rtpl.php:87
|
||||
#: tmp/tools.b91ef64efc3688266305ea9b42e5017e.rtpl.php:83
|
||||
msgid "then click ✚Shaare link button in any page you want to share"
|
||||
msgstr "puis cliquer sur ✚Shaare depuis un site que vous souhaitez partager"
|
||||
|
||||
#: tmp/tools.b91ef64efc3688266305ea9b42e5017e.rtpl.php:96
|
||||
#: tmp/tools.b91ef64efc3688266305ea9b42e5017e.rtpl.php:118
|
||||
#: tmp/tools.b91ef64efc3688266305ea9b42e5017e.rtpl.php:92
|
||||
#: tmp/tools.b91ef64efc3688266305ea9b42e5017e.rtpl.php:114
|
||||
msgid "The selected text is too long, it will be truncated."
|
||||
msgstr "Le texte sélectionné est trop long, il sera tronqué."
|
||||
|
||||
#: tmp/tools.b91ef64efc3688266305ea9b42e5017e.rtpl.php:106
|
||||
#: tmp/tools.b91ef64efc3688266305ea9b42e5017e.rtpl.php:102
|
||||
msgid "Shaare link"
|
||||
msgstr "Shaare"
|
||||
|
||||
#: tmp/tools.b91ef64efc3688266305ea9b42e5017e.rtpl.php:111
|
||||
#: tmp/tools.b91ef64efc3688266305ea9b42e5017e.rtpl.php:107
|
||||
msgid ""
|
||||
"Then click ✚Add Note button anytime to start composing a private Note (text "
|
||||
"post) to your Shaarli"
|
||||
msgstr ""
|
||||
"Puis cliquer sur ✚Add Note pour commencer à rédiger une Note sur Shaarli"
|
||||
|
||||
#: tmp/tools.b91ef64efc3688266305ea9b42e5017e.rtpl.php:127
|
||||
#: tmp/tools.b91ef64efc3688266305ea9b42e5017e.rtpl.php:123
|
||||
msgid "Add Note"
|
||||
msgstr "Ajouter une Note"
|
||||
|
||||
#: tmp/tools.b91ef64efc3688266305ea9b42e5017e.rtpl.php:136
|
||||
#: tmp/tools.b91ef64efc3688266305ea9b42e5017e.rtpl.php:132
|
||||
msgid "3rd party"
|
||||
msgstr "Applications tierces"
|
||||
|
||||
#: tmp/tools.b91ef64efc3688266305ea9b42e5017e.rtpl.php:139
|
||||
#: tmp/tools.b91ef64efc3688266305ea9b42e5017e.rtpl.php:144
|
||||
#: tmp/tools.b91ef64efc3688266305ea9b42e5017e.rtpl.php:135
|
||||
#: tmp/tools.b91ef64efc3688266305ea9b42e5017e.rtpl.php:140
|
||||
msgid "plugin"
|
||||
msgstr "extension"
|
||||
|
||||
#: tmp/tools.b91ef64efc3688266305ea9b42e5017e.rtpl.php:169
|
||||
#: tmp/tools.b91ef64efc3688266305ea9b42e5017e.rtpl.php:165
|
||||
msgid ""
|
||||
"Drag this link to your bookmarks toolbar, or right-click it and choose "
|
||||
"Bookmark This Link"
|
||||
|
@ -1660,9 +1817,6 @@ msgstr ""
|
|||
"Glisser ce lien dans votre barre de favoris ou cliquer droit dessus et « "
|
||||
"Ajouter aux favoris »"
|
||||
|
||||
#~ msgid "Provided data is invalid"
|
||||
#~ msgstr "Les informations fournies ne sont pas valides"
|
||||
|
||||
#~ msgid "Rename"
|
||||
#~ msgstr "Renommer"
|
||||
|
||||
|
|
|
@ -128,6 +128,8 @@
|
|||
$this->get('/plugins', '\Shaarli\Front\Controller\Admin\PluginsController:index');
|
||||
$this->post('/plugins', '\Shaarli\Front\Controller\Admin\PluginsController:save');
|
||||
$this->get('/token', '\Shaarli\Front\Controller\Admin\TokenController:getToken');
|
||||
$this->get('/server', '\Shaarli\Front\Controller\Admin\ServerController:index');
|
||||
$this->get('/clear-cache', '\Shaarli\Front\Controller\Admin\ServerController:clearCache');
|
||||
$this->get('/thumbnails', '\Shaarli\Front\Controller\Admin\ThumbnailsController:index');
|
||||
$this->get('/metadata', '\Shaarli\Front\Controller\Admin\MetadataController:ajaxRetrieveTitle');
|
||||
$this->get('/visibility/{visibility}', '\Shaarli\Front\Controller\Admin\SessionFilterController:visibility');
|
||||
|
|
|
@ -339,6 +339,35 @@ public function testCheckCurrentResourcePermissionsErrors()
|
|||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks resource permissions in minimal mode.
|
||||
*/
|
||||
public function testCheckCurrentResourcePermissionsErrorsMinimalMode(): void
|
||||
{
|
||||
$conf = new ConfigManager('');
|
||||
$conf->set('resource.thumbnails_cache', 'null/cache');
|
||||
$conf->set('resource.config', 'null/data/config.php');
|
||||
$conf->set('resource.data_dir', 'null/data');
|
||||
$conf->set('resource.datastore', 'null/data/store.php');
|
||||
$conf->set('resource.ban_file', 'null/data/ipbans.php');
|
||||
$conf->set('resource.log', 'null/data/log.txt');
|
||||
$conf->set('resource.page_cache', 'null/pagecache');
|
||||
$conf->set('resource.raintpl_tmp', 'null/tmp');
|
||||
$conf->set('resource.raintpl_tpl', 'null/tpl');
|
||||
$conf->set('resource.raintpl_theme', 'null/tpl/default');
|
||||
$conf->set('resource.update_check', 'null/data/lastupdatecheck.txt');
|
||||
|
||||
static::assertSame(
|
||||
[
|
||||
'"null/tpl" directory is not readable',
|
||||
'"null/tpl/default" directory is not readable',
|
||||
'"null/tmp" directory is not readable',
|
||||
'"null/tmp" directory is not writable'
|
||||
],
|
||||
ApplicationUtils::checkResourcePermissions($conf, true)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check update with 'dev' as curent version (master branch).
|
||||
* It should always return false.
|
||||
|
@ -349,4 +378,37 @@ public function testCheckUpdateDev()
|
|||
ApplicationUtils::checkUpdate('dev', self::$testUpdateFile, 100, true, true)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Basic test of getPhpExtensionsRequirement()
|
||||
*/
|
||||
public function testGetPhpExtensionsRequirementSimple(): void
|
||||
{
|
||||
static::assertCount(8, ApplicationUtils::getPhpExtensionsRequirement());
|
||||
static::assertSame([
|
||||
'name' => 'json',
|
||||
'required' => true,
|
||||
'desc' => 'Configuration parsing',
|
||||
'loaded' => true,
|
||||
], ApplicationUtils::getPhpExtensionsRequirement()[0]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test getPhpEol with a known version: 7.4 -> 2022
|
||||
*/
|
||||
public function testGetKnownPhpEol(): void
|
||||
{
|
||||
static::assertSame('2022-11-28', ApplicationUtils::getPhpEol('7.4.7'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Test getPhpEol with an unknown version: 7.4 -> 2022
|
||||
*/
|
||||
public function testGetUnknownPhpEol(): void
|
||||
{
|
||||
static::assertSame(
|
||||
(((int) (new \DateTime())->format('Y')) + 2) . (new \DateTime())->format('-m-d'),
|
||||
ApplicationUtils::getPhpEol('7.51.34')
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,25 +3,48 @@
|
|||
namespace Shaarli;
|
||||
|
||||
use Exception;
|
||||
use Shaarli\Exceptions\IOException;
|
||||
|
||||
/**
|
||||
* Class FileUtilsTest
|
||||
*
|
||||
* Test file utility class.
|
||||
*/
|
||||
class FileUtilsTest extends \Shaarli\TestCase
|
||||
class FileUtilsTest extends TestCase
|
||||
{
|
||||
/**
|
||||
* @var string Test file path.
|
||||
*/
|
||||
protected static $file = 'sandbox/flat.db';
|
||||
|
||||
protected function setUp(): void
|
||||
{
|
||||
@mkdir('sandbox');
|
||||
mkdir('sandbox/folder2');
|
||||
touch('sandbox/file1');
|
||||
touch('sandbox/file2');
|
||||
mkdir('sandbox/folder1');
|
||||
touch('sandbox/folder1/file1');
|
||||
touch('sandbox/folder1/file2');
|
||||
mkdir('sandbox/folder3');
|
||||
mkdir('/tmp/shaarli-to-delete');
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete test file after every test.
|
||||
*/
|
||||
protected function tearDown(): void
|
||||
{
|
||||
@unlink(self::$file);
|
||||
|
||||
@unlink('sandbox/folder1/file1');
|
||||
@unlink('sandbox/folder1/file2');
|
||||
@rmdir('sandbox/folder1');
|
||||
@unlink('sandbox/file1');
|
||||
@unlink('sandbox/file2');
|
||||
@rmdir('sandbox/folder2');
|
||||
@rmdir('sandbox/folder3');
|
||||
@rmdir('/tmp/shaarli-to-delete');
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -107,4 +130,67 @@ public function testReadNotReadable()
|
|||
$this->assertEquals(null, FileUtils::readFlatDB(self::$file));
|
||||
$this->assertEquals(['test'], FileUtils::readFlatDB(self::$file, ['test']));
|
||||
}
|
||||
|
||||
/**
|
||||
* Test clearFolder with self delete and excluded files
|
||||
*/
|
||||
public function testClearFolderSelfDeleteWithExclusion(): void
|
||||
{
|
||||
FileUtils::clearFolder('sandbox', true, ['file2']);
|
||||
|
||||
static::assertFileExists('sandbox/folder1/file2');
|
||||
static::assertFileExists('sandbox/folder1');
|
||||
static::assertFileExists('sandbox/file2');
|
||||
static::assertFileExists('sandbox');
|
||||
|
||||
static::assertFileNotExists('sandbox/folder1/file1');
|
||||
static::assertFileNotExists('sandbox/file1');
|
||||
static::assertFileNotExists('sandbox/folder3');
|
||||
}
|
||||
|
||||
/**
|
||||
* Test clearFolder with self delete and excluded files
|
||||
*/
|
||||
public function testClearFolderSelfDeleteWithoutExclusion(): void
|
||||
{
|
||||
FileUtils::clearFolder('sandbox', true);
|
||||
|
||||
static::assertFileNotExists('sandbox');
|
||||
}
|
||||
|
||||
/**
|
||||
* Test clearFolder with self delete and excluded files
|
||||
*/
|
||||
public function testClearFolderNoSelfDeleteWithoutExclusion(): void
|
||||
{
|
||||
FileUtils::clearFolder('sandbox', false);
|
||||
|
||||
static::assertFileExists('sandbox');
|
||||
|
||||
// 2 because '.' and '..'
|
||||
static::assertCount(2, new \DirectoryIterator('sandbox'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Test clearFolder on a file instead of a folder
|
||||
*/
|
||||
public function testClearFolderOnANonDirectory(): void
|
||||
{
|
||||
$this->expectException(IOException::class);
|
||||
$this->expectExceptionMessage('Provided path is not a directory.');
|
||||
|
||||
FileUtils::clearFolder('sandbox/file1', false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test clearFolder on a file instead of a folder
|
||||
*/
|
||||
public function testClearFolderOutsideOfShaarliDirectory(): void
|
||||
{
|
||||
$this->expectException(IOException::class);
|
||||
$this->expectExceptionMessage('Trying to delete a folder outside of Shaarli path.');
|
||||
|
||||
|
||||
FileUtils::clearFolder('/tmp/shaarli-to-delete', true);
|
||||
}
|
||||
}
|
||||
|
|
184
tests/front/controller/admin/ServerControllerTest.php
Normal file
184
tests/front/controller/admin/ServerControllerTest.php
Normal file
|
@ -0,0 +1,184 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Shaarli\Front\Controller\Admin;
|
||||
|
||||
use Shaarli\Config\ConfigManager;
|
||||
use Shaarli\Security\SessionManager;
|
||||
use Shaarli\TestCase;
|
||||
use Slim\Http\Request;
|
||||
use Slim\Http\Response;
|
||||
|
||||
/**
|
||||
* Test Server administration controller.
|
||||
*/
|
||||
class ServerControllerTest extends TestCase
|
||||
{
|
||||
use FrontAdminControllerMockHelper;
|
||||
|
||||
/** @var ServerController */
|
||||
protected $controller;
|
||||
|
||||
public function setUp(): void
|
||||
{
|
||||
$this->createContainer();
|
||||
|
||||
$this->controller = new ServerController($this->container);
|
||||
|
||||
// initialize dummy cache
|
||||
@mkdir('sandbox/');
|
||||
foreach (['pagecache', 'tmp', 'cache'] as $folder) {
|
||||
@mkdir('sandbox/' . $folder);
|
||||
@touch('sandbox/' . $folder . '/.htaccess');
|
||||
@touch('sandbox/' . $folder . '/1');
|
||||
@touch('sandbox/' . $folder . '/2');
|
||||
}
|
||||
}
|
||||
|
||||
public function tearDown(): void
|
||||
{
|
||||
foreach (['pagecache', 'tmp', 'cache'] as $folder) {
|
||||
@unlink('sandbox/' . $folder . '/.htaccess');
|
||||
@unlink('sandbox/' . $folder . '/1');
|
||||
@unlink('sandbox/' . $folder . '/2');
|
||||
@rmdir('sandbox/' . $folder);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Test default display of server administration page.
|
||||
*/
|
||||
public function testIndex(): void
|
||||
{
|
||||
$request = $this->createMock(Request::class);
|
||||
$response = new Response();
|
||||
|
||||
// Save RainTPL assigned variables
|
||||
$assignedVariables = [];
|
||||
$this->assignTemplateVars($assignedVariables);
|
||||
|
||||
$result = $this->controller->index($request, $response);
|
||||
|
||||
static::assertSame(200, $result->getStatusCode());
|
||||
static::assertSame('server', (string) $result->getBody());
|
||||
|
||||
static::assertSame(PHP_VERSION, $assignedVariables['php_version']);
|
||||
static::assertArrayHasKey('php_has_reached_eol', $assignedVariables);
|
||||
static::assertArrayHasKey('php_eol', $assignedVariables);
|
||||
static::assertArrayHasKey('php_extensions', $assignedVariables);
|
||||
static::assertArrayHasKey('permissions', $assignedVariables);
|
||||
static::assertEmpty($assignedVariables['permissions']);
|
||||
|
||||
static::assertRegExp(
|
||||
'#https://github\.com/shaarli/Shaarli/releases/tag/v\d+\.\d+\.\d+#',
|
||||
$assignedVariables['release_url']
|
||||
);
|
||||
static::assertRegExp('#v\d+\.\d+\.\d+#', $assignedVariables['latest_version']);
|
||||
static::assertRegExp('#(v\d+\.\d+\.\d+|dev)#', $assignedVariables['current_version']);
|
||||
static::assertArrayHasKey('index_url', $assignedVariables);
|
||||
static::assertArrayHasKey('client_ip', $assignedVariables);
|
||||
static::assertArrayHasKey('trusted_proxies', $assignedVariables);
|
||||
|
||||
static::assertSame('Server administration - Shaarli', $assignedVariables['pagetitle']);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test clearing the main cache
|
||||
*/
|
||||
public function testClearMainCache(): void
|
||||
{
|
||||
$this->container->conf = $this->createMock(ConfigManager::class);
|
||||
$this->container->conf->method('get')->willReturnCallback(function (string $key, $default) {
|
||||
if ($key === 'resource.page_cache') {
|
||||
return 'sandbox/pagecache';
|
||||
} elseif ($key === 'resource.raintpl_tmp') {
|
||||
return 'sandbox/tmp';
|
||||
} elseif ($key === 'resource.thumbnails_cache') {
|
||||
return 'sandbox/cache';
|
||||
} else {
|
||||
return $default;
|
||||
}
|
||||
});
|
||||
|
||||
$this->container->sessionManager
|
||||
->expects(static::once())
|
||||
->method('setSessionParameter')
|
||||
->with(SessionManager::KEY_SUCCESS_MESSAGES, ['Shaarli\'s cache folder has been cleared!'])
|
||||
;
|
||||
|
||||
$request = $this->createMock(Request::class);
|
||||
$request->method('getQueryParam')->with('type')->willReturn('main');
|
||||
$response = new Response();
|
||||
|
||||
$result = $this->controller->clearCache($request, $response);
|
||||
|
||||
static::assertSame(302, $result->getStatusCode());
|
||||
static::assertSame('/subfolder/admin/server', (string) $result->getHeaderLine('Location'));
|
||||
|
||||
static::assertFileNotExists('sandbox/pagecache/1');
|
||||
static::assertFileNotExists('sandbox/pagecache/2');
|
||||
static::assertFileNotExists('sandbox/tmp/1');
|
||||
static::assertFileNotExists('sandbox/tmp/2');
|
||||
|
||||
static::assertFileExists('sandbox/pagecache/.htaccess');
|
||||
static::assertFileExists('sandbox/tmp/.htaccess');
|
||||
static::assertFileExists('sandbox/cache');
|
||||
static::assertFileExists('sandbox/cache/.htaccess');
|
||||
static::assertFileExists('sandbox/cache/1');
|
||||
static::assertFileExists('sandbox/cache/2');
|
||||
}
|
||||
|
||||
/**
|
||||
* Test clearing thumbnails cache
|
||||
*/
|
||||
public function testClearThumbnailsCache(): void
|
||||
{
|
||||
$this->container->conf = $this->createMock(ConfigManager::class);
|
||||
$this->container->conf->method('get')->willReturnCallback(function (string $key, $default) {
|
||||
if ($key === 'resource.page_cache') {
|
||||
return 'sandbox/pagecache';
|
||||
} elseif ($key === 'resource.raintpl_tmp') {
|
||||
return 'sandbox/tmp';
|
||||
} elseif ($key === 'resource.thumbnails_cache') {
|
||||
return 'sandbox/cache';
|
||||
} else {
|
||||
return $default;
|
||||
}
|
||||
});
|
||||
|
||||
$this->container->sessionManager
|
||||
->expects(static::once())
|
||||
->method('setSessionParameter')
|
||||
->willReturnCallback(function (string $key, array $value): SessionManager {
|
||||
static::assertSame(SessionManager::KEY_WARNING_MESSAGES, $key);
|
||||
static::assertCount(1, $value);
|
||||
static::assertStringStartsWith('Thumbnails cache has been cleared.', $value[0]);
|
||||
|
||||
return $this->container->sessionManager;
|
||||
});
|
||||
;
|
||||
|
||||
$request = $this->createMock(Request::class);
|
||||
$request->method('getQueryParam')->with('type')->willReturn('thumbnails');
|
||||
$response = new Response();
|
||||
|
||||
$result = $this->controller->clearCache($request, $response);
|
||||
|
||||
static::assertSame(302, $result->getStatusCode());
|
||||
static::assertSame('/subfolder/admin/server', (string) $result->getHeaderLine('Location'));
|
||||
|
||||
static::assertFileNotExists('sandbox/cache/1');
|
||||
static::assertFileNotExists('sandbox/cache/2');
|
||||
|
||||
static::assertFileExists('sandbox/cache/.htaccess');
|
||||
static::assertFileExists('sandbox/pagecache');
|
||||
static::assertFileExists('sandbox/pagecache/.htaccess');
|
||||
static::assertFileExists('sandbox/pagecache/1');
|
||||
static::assertFileExists('sandbox/pagecache/2');
|
||||
static::assertFileExists('sandbox/tmp');
|
||||
static::assertFileExists('sandbox/tmp/.htaccess');
|
||||
static::assertFileExists('sandbox/tmp/1');
|
||||
static::assertFileExists('sandbox/tmp/2');
|
||||
}
|
||||
}
|
|
@ -79,6 +79,15 @@ public function testInstallIndexWithValidSession(): void
|
|||
static::assertIsArray($assignedVariables['languages']);
|
||||
static::assertSame('Automatic', $assignedVariables['languages']['auto']);
|
||||
static::assertSame('French', $assignedVariables['languages']['fr']);
|
||||
|
||||
static::assertSame(PHP_VERSION, $assignedVariables['php_version']);
|
||||
static::assertArrayHasKey('php_has_reached_eol', $assignedVariables);
|
||||
static::assertArrayHasKey('php_eol', $assignedVariables);
|
||||
static::assertArrayHasKey('php_extensions', $assignedVariables);
|
||||
static::assertArrayHasKey('permissions', $assignedVariables);
|
||||
static::assertEmpty($assignedVariables['permissions']);
|
||||
|
||||
static::assertSame('Install Shaarli', $assignedVariables['pagetitle']);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -163,6 +163,16 @@ <h2 class="window-title">{'Install Shaarli'|t}</h2>
|
|||
</div>
|
||||
</div>
|
||||
</form>
|
||||
|
||||
<div class="pure-g">
|
||||
<div class="pure-u-lg-1-6 pure-u-1-24"></div>
|
||||
<div class="pure-u-lg-2-3 pure-u-22-24 page-form page-form-complete">
|
||||
<h2 class="window-title">{'Server requirements'|t}</h2>
|
||||
|
||||
{include="server.requirements"}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{include="page.footer"}
|
||||
</body>
|
||||
</html>
|
||||
|
|
129
tpl/default/server.html
Normal file
129
tpl/default/server.html
Normal file
|
@ -0,0 +1,129 @@
|
|||
<!DOCTYPE html>
|
||||
<html{if="$language !== 'auto'"} lang="{$language}"{/if}>
|
||||
<head>
|
||||
{include="includes"}
|
||||
</head>
|
||||
<body>
|
||||
{include="page.header"}
|
||||
|
||||
<div class="pure-g">
|
||||
<div class="pure-u-lg-1-4 pure-u-1-24"></div>
|
||||
<div class="pure-u-lg-1-2 pure-u-22-24 page-form server-tables-page">
|
||||
<h2 class="window-title">{'Server administration'|t}</h2>
|
||||
|
||||
<h3 class="window-subtitle">{'General'|t}</h3>
|
||||
|
||||
<div class="pure-g server-row">
|
||||
<div class="pure-u-lg-1-2 pure-u-1 server-label">
|
||||
<p>{'Index URL'|t}</p>
|
||||
</div>
|
||||
<div class="pure-u-lg-1-2 pure-u-1">
|
||||
<p><a href="{$index_url}" title="{$pagetitle}">{$index_url}</a></p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="pure-g server-row">
|
||||
<div class="pure-u-lg-1-2 pure-u-1 server-label">
|
||||
<p>{'Base path'|t}</p>
|
||||
</div>
|
||||
<div class="pure-u-lg-1-2 pure-u-1">
|
||||
<p>{$base_path}</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="pure-g server-row">
|
||||
<div class="pure-u-lg-1-2 pure-u-1 server-label">
|
||||
<p>{'Client IP'|t}</p>
|
||||
</div>
|
||||
<div class="pure-u-lg-1-2 pure-u-1">
|
||||
<p>{$client_ip}</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="pure-g server-row">
|
||||
<div class="pure-u-lg-1-2 pure-u-1 server-label">
|
||||
<p>{'Trusted reverse proxies'|t}</p>
|
||||
</div>
|
||||
<div class="pure-u-lg-1-2 pure-u-1">
|
||||
{if="count($trusted_proxies) > 0"}
|
||||
<p>
|
||||
{loop="$trusted_proxies"}
|
||||
{$value}<br>
|
||||
{/loop}
|
||||
</p>
|
||||
{else}
|
||||
<p>{'N/A'|t}</p>
|
||||
{/if}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{include="server.requirements"}
|
||||
|
||||
<h3 class="window-subtitle">Version</h3>
|
||||
|
||||
<div class="pure-g server-row">
|
||||
<div class="pure-u-lg-1-2 pure-u-1 server-label">
|
||||
<p>Current version</p>
|
||||
</div>
|
||||
<div class="pure-u-lg-1-2 pure-u-1">
|
||||
<p>{$current_version}</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="pure-g server-row">
|
||||
<div class="pure-u-lg-1-2 pure-u-1 server-label">
|
||||
<p>Latest release</p>
|
||||
</div>
|
||||
<div class="pure-u-lg-1-2 pure-u-1">
|
||||
<p>
|
||||
<a href="{$release_url}" title="{'Visit releases page on Github'|t}">
|
||||
{$latest_version}
|
||||
</a>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<h3 class="window-subtitle">Thumbnails</h3>
|
||||
|
||||
<div class="pure-g server-row">
|
||||
<div class="pure-u-lg-1-2 pure-u-1 server-label">
|
||||
<p>Thumbnails status</p>
|
||||
</div>
|
||||
<div class="pure-u-lg-1-2 pure-u-1">
|
||||
<p>
|
||||
{if="$thumbnails_mode==='all'"}
|
||||
{'All'|t}
|
||||
{elseif="$thumbnails_mode==='common'"}
|
||||
{'Only common media hosts'|t}
|
||||
{else}
|
||||
{'None'|t}
|
||||
{/if}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{if="$thumbnails_mode!=='none'"}
|
||||
<div class="center tools-item">
|
||||
<a href="{$base_path}/admin/thumbnails" title="{'Synchronize all link thumbnails'|t}">
|
||||
<span class="pure-button pure-u-lg-2-3 pure-u-3-4">{'Synchronize thumbnails'|t}</span>
|
||||
</a>
|
||||
</div>
|
||||
{/if}
|
||||
|
||||
<h3 class="window-subtitle">Cache</h3>
|
||||
|
||||
<div class="center tools-item">
|
||||
<a href="{$base_path}/admin/clear-cache?type=main">
|
||||
<span class="pure-button pure-u-lg-2-3 pure-u-3-4">Clear main cache</span>
|
||||
</a>
|
||||
</div>
|
||||
|
||||
<div class="center tools-item">
|
||||
<a href="{$base_path}/admin/clear-cache?type=thumbnails">
|
||||
<span class="pure-button pure-u-lg-2-3 pure-u-3-4">Clear thumbnails cache</span>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{include="page.footer"}
|
||||
|
||||
</body>
|
||||
</html>
|
68
tpl/default/server.requirements.html
Normal file
68
tpl/default/server.requirements.html
Normal file
|
@ -0,0 +1,68 @@
|
|||
<div class="server-tables">
|
||||
<h3 class="window-subtitle">{'Permissions'|t}</h3>
|
||||
|
||||
{if="count($permissions) > 0"}
|
||||
<p class="center">
|
||||
<i class="fa fa-close fa-color-red" aria-hidden="true"></i>
|
||||
{'There are permissions that need to be fixed.'|t}
|
||||
</p>
|
||||
|
||||
<p>
|
||||
{loop="$permissions"}
|
||||
<div class="center">{$value}</div>
|
||||
{/loop}
|
||||
</p>
|
||||
{else}
|
||||
<p class="center">
|
||||
<i class="fa fa-check fa-color-green" aria-hidden="true"></i>
|
||||
{'All read/write permissions are properly set.'|t}
|
||||
</p>
|
||||
{/if}
|
||||
|
||||
<h3 class="window-subtitle">PHP</h3>
|
||||
|
||||
<p class="center">
|
||||
<strong>{'Running PHP'|t} {$php_version}</strong>
|
||||
{if="$php_has_reached_eol"}
|
||||
<i class="fa fa-circle fa-color-orange" aria-label="hidden"></i><br>
|
||||
{'End of life: '|t} {$php_eol}
|
||||
{else}
|
||||
<i class="fa fa-circle fa-color-green" aria-label="hidden"></i><br>
|
||||
{/if}
|
||||
</p>
|
||||
|
||||
<table class="center">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>{'Extension'|t}</th>
|
||||
<th>{'Usage'|t}</th>
|
||||
<th>{'Status'|t}</th>
|
||||
<th>{'Loaded'|t}</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{loop="$php_extensions"}
|
||||
<tr>
|
||||
<td>{$value.name}</td>
|
||||
<td>{$value.desc}</td>
|
||||
<td>{$value.required ? t('Required') : t('Optional')}</td>
|
||||
<td>
|
||||
{if="$value.loaded"}
|
||||
{$classLoaded="fa-color-green"}
|
||||
{$strLoaded=t('Loaded')}
|
||||
{else}
|
||||
{$strLoaded=t('Not loaded')}
|
||||
{if="$value.required"}
|
||||
{$classLoaded="fa-color-red"}
|
||||
{else}
|
||||
{$classLoaded="fa-color-orange"}
|
||||
{/if}
|
||||
{/if}
|
||||
|
||||
<i class="fa fa-circle {$classLoaded}" aria-label="{$strLoaded}" title="{$strLoaded}"></i>
|
||||
</td>
|
||||
</tr>
|
||||
{/loop}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
|
@ -20,6 +20,12 @@ <h2 class="window-title">{'Settings'|t}</h2>
|
|||
<span class="pure-button pure-u-lg-2-3 pure-u-3-4">{'Plugin administration'|t}</span>
|
||||
</a>
|
||||
</div>
|
||||
<div class="tools-item">
|
||||
<a href="{$base_path}/admin/server"
|
||||
title="{'Check instance\'s server configuration'|t}">
|
||||
<span class="pure-button pure-u-lg-2-3 pure-u-3-4">{'Server administration'|t}</span>
|
||||
</a>
|
||||
</div>
|
||||
{if="!$openshaarli"}
|
||||
<div class="tools-item">
|
||||
<a href="{$base_path}/admin/password" title="{'Change your password'|t}">
|
||||
|
@ -45,14 +51,6 @@ <h2 class="window-title">{'Settings'|t}</h2>
|
|||
</a>
|
||||
</div>
|
||||
|
||||
{if="$thumbnails_enabled"}
|
||||
<div class="tools-item">
|
||||
<a href="{$base_path}/admin/thumbnails" title="{'Synchronize all link thumbnails'|t}">
|
||||
<span class="pure-button pure-u-lg-2-3 pure-u-3-4">{'Synchronize thumbnails'|t}</span>
|
||||
</a>
|
||||
</div>
|
||||
{/if}
|
||||
|
||||
{loop="$tools_plugin"}
|
||||
<div class="tools-item">
|
||||
{$value}
|
||||
|
|
Loading…
Reference in a new issue