Compare commits
34 Commits
Author | SHA1 | Date | |
---|---|---|---|
cbc7a1ad19 | |||
e7e0fef37e | |||
d0f14f0e60 | |||
cca646b1be | |||
6db9837238 | |||
ca313a2b18 | |||
547dea7350 | |||
9d6e229e0a | |||
22d69ccafb | |||
5e59984211 | |||
0301e1f31d | |||
1f0d490688 | |||
288393778a | |||
7773bc916f | |||
5ebbcfcb9d | |||
f237d0bca1 | |||
70fa6efee7 | |||
30ed4349d9 | |||
ad998c17d1 | |||
4d6b6f8d4f | |||
dd3582b9db | |||
0e26e71a50 | |||
9a56fc9572 | |||
ac8689b40a | |||
0f9a79411d | |||
b944a3bac7 | |||
4bab81c541 | |||
2f3dd5926b | |||
959139b239 | |||
e958287b9e | |||
e110e7b4f9 | |||
61ec8c04be | |||
f0ccf8eb2f | |||
b831275901 |
@ -1,4 +1,4 @@
|
||||
# ZwiiCampus 1.19.03
|
||||
# ZwiiCampus 1.21.00
|
||||
|
||||
ZwiiCampus (Learning Management System) est logiciel auteur destiné à mettre en ligne des tutoriels. Il dispose de plusieurs modalités d'ouverture et d'accès des contenus. Basé sur la version 13 du CMS Zwii, la structure logicielle est solide, le framework de Zwii est éprouvé.
|
||||
|
||||
|
@ -170,6 +170,7 @@ class JsonDb extends \Prowebcraft\Dot
|
||||
if ($this->data === null) {
|
||||
throw new \RuntimeException('Tentative de sauvegarde de données nulles');
|
||||
}
|
||||
|
||||
try {
|
||||
$encoded_data = json_encode($this->data, JSON_UNESCAPED_UNICODE | JSON_FORCE_OBJECT | JSON_THROW_ON_ERROR);
|
||||
} catch (\JsonException $e) {
|
||||
@ -190,8 +191,11 @@ class JsonDb extends \Prowebcraft\Dot
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
error_log("Échec sauvegarde : longueur incorrecte ou renommage échoué (tentative " . ($attempt + 1) . ")");
|
||||
} catch (\Exception $e) {
|
||||
// Nettoyer le fichier temporaire en cas d'exception
|
||||
error_log('Erreur de sauvegarde : ' . $e->getMessage());
|
||||
|
||||
if (file_exists($temp_file)) {
|
||||
unlink($temp_file);
|
||||
}
|
||||
@ -200,7 +204,6 @@ class JsonDb extends \Prowebcraft\Dot
|
||||
usleep(pow(2, $attempt) * 250000);
|
||||
}
|
||||
|
||||
// Erreur fatale si tous les essais échouent
|
||||
throw new \RuntimeException('Échec de sauvegarde après ' . $max_attempts . ' tentatives');
|
||||
}
|
||||
}
|
||||
|
@ -613,8 +613,7 @@ class layout extends common
|
||||
}
|
||||
|
||||
// Retourne les items du menu
|
||||
echo '<ul class="navMain" id="menuLeft">' . $itemsLeft . '</ul><ul class="navMain" id="menuRight">' . $itemsRight;
|
||||
echo '</ul>';
|
||||
echo '<ul class="navMain" id="menuLeft">' . $itemsLeft . '</ul><ul class="navMain" id="menuRight">' . $itemsRight . '</ul>';
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -254,18 +254,18 @@ class core extends common
|
||||
|
||||
|
||||
// Déterminer la hauteur max du menu pour éviter les débordements
|
||||
$padding = $this->getData(['theme', 'menu', 'height']); // Par exemple, "10px 20px"
|
||||
$fontSize = (float) $this->getData(['theme', 'text', 'fontSize']); // Taille de référence en pixels
|
||||
$menuFontSize = (float) $this->getData(['theme', 'menu', 'fontSize']); // Taille du menu en em
|
||||
// $padding = $this->getData(['theme', 'menu', 'height']); // Par exemple, "10px 20px"
|
||||
// $fontSize = (float) $this->getData(['theme', 'text', 'fontSize']); // Taille de référence en pixels
|
||||
// $menuFontSize = (float) $this->getData(['theme', 'menu', 'fontSize']); // Taille du menu en em
|
||||
|
||||
// Extraire la première valeur du padding (par exemple "10px 20px" -> "10px")
|
||||
$firstPadding = (float) explode(" ", $padding)[0]; // Nous prenons la première valeur, supposée être en px
|
||||
// $firstPadding = (float) explode(" ", $padding)[0]; // Nous prenons la première valeur, supposée être en px
|
||||
|
||||
// Convertir menuFontSize (en em) en pixels
|
||||
$menuFontSizeInPx = $menuFontSize * $fontSize;
|
||||
// $menuFontSizeInPx = $menuFontSize * $fontSize;
|
||||
|
||||
// Calculer la hauteur totale
|
||||
$totalHeight = $firstPadding + $fontSize + $menuFontSizeInPx;
|
||||
// $totalHeight = $firstPadding + $fontSize + $menuFontSizeInPx;
|
||||
|
||||
// Fixer la hauteur maximale de la barre de menu
|
||||
// $css .= '#menuLeft, nav, a.active {max-height:' . $totalHeight . 'px}';
|
||||
|
@ -884,6 +884,10 @@ class template
|
||||
$html = '<div id="' . $attributes['id'] . 'Wrapper" class="tableWrapper ' . $attributes['classWrapper'] . '">';
|
||||
// Début tableau
|
||||
$html .= '<table id="' . $attributes['id'] . '" class="table ' . $attributes['class'] . '">';
|
||||
// Pas de tableau d'Id transmis, générer une numérotation
|
||||
if (empty($rowsId)) {
|
||||
$rowsId = range(0, count($cols));
|
||||
}
|
||||
// Entêtes
|
||||
if ($head) {
|
||||
// Début des entêtes
|
||||
@ -891,21 +895,17 @@ class template
|
||||
$html .= '<tr class="nodrag">';
|
||||
$i = 0;
|
||||
foreach ($head as $th) {
|
||||
$html .= '<th class="col' . $cols[$i++] . '">' . $th . '</th>';
|
||||
$html .= '<th id="' . $rowsId[$i] . '" class="col' . $cols[$i++] . '">' . $th . '</th>';
|
||||
}
|
||||
// Fin des entêtes
|
||||
$html .= '</tr>';
|
||||
$html .= '</thead>';
|
||||
}
|
||||
// Pas de tableau d'Id transmis, générer une numérotation
|
||||
if (empty($rowsId)) {
|
||||
$rowsId = range(0, count($body));
|
||||
}
|
||||
// Début contenu
|
||||
$j = 0;
|
||||
foreach ($body as $tr) {
|
||||
// Id de ligne pour les tableaux drag and drop
|
||||
$html .= '<tr id="' . $rowsId[$j++] . '">';
|
||||
$html .= '<tr>';
|
||||
$i = 0;
|
||||
foreach ($tr as $td) {
|
||||
$html .= '<td class="col' . $cols[$i++] . '">' . $td . '</td>';
|
||||
|
@ -374,12 +374,11 @@ core.start = function () {
|
||||
var totalHeight = firstPadding + fontSize + menuFontSizeInPx;
|
||||
$("#menuLeft").css({
|
||||
"visibility": "hidden",
|
||||
"overflow": "hidden",
|
||||
"max-width": "10px"
|
||||
});
|
||||
|
||||
// Par défaut pour tous les thèmes.
|
||||
$("#menuLeft, nav").css("max-height", totalHeight + "px").css("min-height", totalHeight + "px");
|
||||
$("#menuLeft").css("max-height", totalHeight + "px").css("min-height", totalHeight + "px");
|
||||
}
|
||||
};
|
||||
|
||||
|
150
core/core.php
150
core/core.php
@ -51,7 +51,7 @@ class common
|
||||
const ACCESS_TIMER = 1800;
|
||||
|
||||
// Numéro de version
|
||||
const ZWII_VERSION = '1.19.03';
|
||||
const ZWII_VERSION = '1.21.00';
|
||||
|
||||
// URL autoupdate
|
||||
const ZWII_UPDATE_URL = 'https://forge.chapril.org/ZwiiCMS-Team/campus-update/raw/branch/master/';
|
||||
@ -1251,66 +1251,94 @@ class common
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Création d'une miniature
|
||||
* Fonction utilisée lors de la mise à jour d'une version 9 à une version 10
|
||||
* @param string $src image source
|
||||
* @param string $dets image destination
|
||||
* @param integer $desired_width largeur demandée
|
||||
*/
|
||||
function makeThumb($src, $dest, $desired_width)
|
||||
{
|
||||
// Vérifier l'existence du dossier de destination.
|
||||
$fileInfo = pathinfo($dest);
|
||||
if (!is_dir($fileInfo['dirname'])) {
|
||||
mkdir($fileInfo['dirname'], 0755, true);
|
||||
}
|
||||
$source_image = '';
|
||||
// Type d'image
|
||||
switch ($fileInfo['extension']) {
|
||||
case 'jpeg':
|
||||
case 'jpg':
|
||||
$source_image = imagecreatefromjpeg($src);
|
||||
break;
|
||||
case 'png':
|
||||
$source_image = imagecreatefrompng($src);
|
||||
break;
|
||||
case 'gif':
|
||||
$source_image = imagecreatefromgif($src);
|
||||
break;
|
||||
case 'webp':
|
||||
$source_image = imagecreatefromwebp($src);
|
||||
break;
|
||||
case 'avif':
|
||||
$source_image = imagecreatefromavif($src);
|
||||
}
|
||||
// Image valide
|
||||
if ($source_image) {
|
||||
$width = imagesx($source_image);
|
||||
$height = imagesy($source_image);
|
||||
/* find the "desired height" of this thumbnail, relative to the desired width */
|
||||
$desired_height = floor($height * ($desired_width / $width));
|
||||
/* create a new, "virtual" image */
|
||||
$virtual_image = imagecreatetruecolor($desired_width, $desired_height);
|
||||
/* copy source image at a resized size */
|
||||
imagecopyresampled($virtual_image, $source_image, 0, 0, 0, 0, $desired_width, $desired_height, $width, $height);
|
||||
switch (mime_content_type($src)) {
|
||||
case 'image/jpeg':
|
||||
case 'image/jpg':
|
||||
return (imagejpeg($virtual_image, $dest));
|
||||
case 'image/png':
|
||||
return (imagepng($virtual_image, $dest));
|
||||
case 'image/gif':
|
||||
return (imagegif($virtual_image, $dest));
|
||||
case 'image/webp':
|
||||
return (imagewebp($virtual_image, $dest));
|
||||
case 'image/avif':
|
||||
return (imageavif($virtual_image, $dest));
|
||||
}
|
||||
} else {
|
||||
return (false);
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Crée une miniature à partir d'une image source.
|
||||
* Cette fonction prend en charge les formats raster (JPEG, PNG, GIF, WebP, AVIF) et vectoriels (SVG).
|
||||
* Pour les images vectorielles (SVG), aucune redimension n'est effectuée : une copie est réalisée.
|
||||
*
|
||||
* @param string $src Chemin de l'image source.
|
||||
* @param string $dest Chemin de l'image destination (avec le nom du fichier et l'extension).
|
||||
* @param int $desired_width Largeur demandée pour la miniature (ignorée pour les SVG).
|
||||
* @return bool True si l'opération a réussi, false sinon.
|
||||
*/
|
||||
function makeThumb($src, $dest, $desired_width)
|
||||
{
|
||||
// Vérifier l'existence du dossier de destination.
|
||||
$fileInfo = pathinfo($dest);
|
||||
if (!is_dir($fileInfo['dirname'])) {
|
||||
mkdir($fileInfo['dirname'], 0755, true);
|
||||
}
|
||||
|
||||
$extension = strtolower($fileInfo['extension']);
|
||||
$mime_type = mime_content_type($src);
|
||||
|
||||
// Gestion des fichiers SVG (copie simple sans redimensionnement)
|
||||
if ($extension === 'svg' || $mime_type === 'image/svg+xml') {
|
||||
return copy($src, $dest);
|
||||
}
|
||||
|
||||
// Chargement de l'image source selon le type
|
||||
$source_image = '';
|
||||
switch ($extension) {
|
||||
case 'jpeg':
|
||||
case 'jpg':
|
||||
$source_image = imagecreatefromjpeg($src);
|
||||
break;
|
||||
case 'png':
|
||||
$source_image = imagecreatefrompng($src);
|
||||
break;
|
||||
case 'gif':
|
||||
$source_image = imagecreatefromgif($src);
|
||||
break;
|
||||
case 'webp':
|
||||
$source_image = imagecreatefromwebp($src);
|
||||
break;
|
||||
case 'avif':
|
||||
if (function_exists('imagecreatefromavif')) {
|
||||
$source_image = imagecreatefromavif($src);
|
||||
} else {
|
||||
return false; // AVIF non supporté
|
||||
}
|
||||
break;
|
||||
default:
|
||||
return false; // Format non pris en charge
|
||||
}
|
||||
|
||||
// Image valide (formats raster uniquement)
|
||||
if (is_resource($source_image) || (is_object($source_image) && $source_image instanceof GdImage)) {
|
||||
$width = imagesx($source_image);
|
||||
$height = imagesy($source_image);
|
||||
|
||||
// Calcul de la hauteur proportionnelle à la largeur demandée
|
||||
$desired_height = floor($height * ($desired_width / $width));
|
||||
|
||||
// Création d'une nouvelle image virtuelle redimensionnée
|
||||
$virtual_image = imagecreatetruecolor($desired_width, $desired_height);
|
||||
|
||||
// Copie de l'image source dans l'image virtuelle avec redimensionnement
|
||||
imagecopyresampled($virtual_image, $source_image, 0, 0, 0, 0, $desired_width, $desired_height, $width, $height);
|
||||
|
||||
// Enregistrement de l'image redimensionnée au format approprié
|
||||
switch ($mime_type) {
|
||||
case 'image/jpeg':
|
||||
case 'image/jpg':
|
||||
return imagejpeg($virtual_image, $dest);
|
||||
case 'image/png':
|
||||
return imagepng($virtual_image, $dest);
|
||||
case 'image/gif':
|
||||
return imagegif($virtual_image, $dest);
|
||||
case 'image/webp':
|
||||
return imagewebp($virtual_image, $dest);
|
||||
case 'image/avif':
|
||||
if (function_exists('imageavif')) {
|
||||
return imageavif($virtual_image, $dest);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false; // En cas d'échec
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
|
@ -3,26 +3,23 @@
|
||||
/**
|
||||
* Vérification de la version de PHP
|
||||
*/
|
||||
|
||||
if(version_compare(PHP_VERSION, '7.2.0', '<') ) {
|
||||
exit('PHP 7.2+ mini requis - PHP 7.2+ mini required');
|
||||
|
||||
if (version_compare(PHP_VERSION, '7.2.0', '<')) {
|
||||
displayErrorPage('PHP 7.2+ mini requis - PHP 7.2+ mini required');
|
||||
}
|
||||
|
||||
if ( version_compare(PHP_VERSION, '8.3.999', '>') ) {
|
||||
exit('PHP 8.3 pas encore supporté, installez PHP 7.n ou PHP 8.1.n - PHP 8.3 not yet supported, install PHP 7.n or PHP 8.1.n');
|
||||
if (version_compare(PHP_VERSION, '8.3.999', '>')) {
|
||||
displayErrorPage('PHP 8.3 pas encore supporté, installez PHP 7.n ou PHP 8.1.n - PHP 8.3 not yet supported, install PHP 7.n or PHP 8.1.n');
|
||||
}
|
||||
|
||||
/**
|
||||
* Check les modules installés
|
||||
*/
|
||||
|
||||
$e = [
|
||||
'gd',
|
||||
'json',
|
||||
'date',
|
||||
'mbstring',
|
||||
'zip',
|
||||
'zip',
|
||||
'intl',
|
||||
'exif',
|
||||
'Phar',
|
||||
@ -31,26 +28,57 @@ $e = [
|
||||
];
|
||||
$m = get_loaded_extensions();
|
||||
$b = false;
|
||||
$missingModules = [];
|
||||
foreach ($e as $k => $v) {
|
||||
if (array_search($v,$m) === false) {
|
||||
if (array_search($v, $m) === false) {
|
||||
$b = true;
|
||||
echo '<pre><p>Module PHP : ' . $v . ' manquant - Module PHP ' . $v . ' missing.</p></pre>';
|
||||
$missingModules[] = $v;
|
||||
}
|
||||
}
|
||||
if ($b)
|
||||
exit('<pre><p>ZwiiCMS ne peut pas démarrer ; activez les extensions requises dans PHP.ini- ZwiiCMS cannot start, enabled PHP missing extensions into PHP.ini</p></pre>');
|
||||
/**
|
||||
* Contrôle les htacess
|
||||
*/
|
||||
if ($b) {
|
||||
$errorMessage = 'ZwiiCMS ne peut pas démarrer ; les modules PHP suivants sont manquants : ' . implode(', ', $missingModules) . '<br />';
|
||||
$errorMessage .= 'ZwiiCMS cannot start, the following PHP modules are missing: ' . implode(', ', $missingModules);
|
||||
displayErrorPage($errorMessage);
|
||||
}
|
||||
|
||||
/**
|
||||
* Contrôle les htaccess
|
||||
*/
|
||||
$d = [
|
||||
'',
|
||||
'site/data/',
|
||||
'site/backup/',
|
||||
'site/tmp/',
|
||||
// 'site/i18n/', pas contrôler pour éviter les pbs de mise à jour
|
||||
// 'site/i18n/', pas contrôler pour éviter les pbs de mise à jour
|
||||
];
|
||||
foreach ($d as $key) {
|
||||
if (file_exists($key . '.htaccess') === false)
|
||||
exit('<pre>ZwiiCMS ne peut pas démarrer, le fichier ' .$key . '.htaccess est manquant.<br />ZwiiCMS cannot start, file ' . $key . '.htaccess is missing.</pre>' );
|
||||
if (file_exists($key . '.htaccess') === false) {
|
||||
$errorMessage = 'ZwiiCMS ne peut pas démarrer, le fichier ' . $key . '.htaccess est manquant.<br />';
|
||||
$errorMessage .= 'ZwiiCMS cannot start, file ' . $key . '.htaccess is missing.';
|
||||
displayErrorPage($errorMessage);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Fonction pour afficher une page d'erreur stylisée
|
||||
*/
|
||||
function displayErrorPage($message)
|
||||
{
|
||||
echo '<!DOCTYPE html>
|
||||
<html lang="fr">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>Erreur - ZwiiCMS</title>
|
||||
<link rel="stylesheet" href="core\layout\error.css">
|
||||
</head>
|
||||
<body>
|
||||
<div class="error-container">
|
||||
<h1>Erreur</h1>
|
||||
<p>' . $message . '</p>
|
||||
</div>
|
||||
</body>
|
||||
</html>';
|
||||
exit;
|
||||
}
|
||||
|
@ -22,7 +22,6 @@ if (
|
||||
$this->setData(['core', 'dataVersion', 1700]);
|
||||
}
|
||||
|
||||
|
||||
if (
|
||||
$this->getData(['core', 'dataVersion']) < 1800
|
||||
) {
|
||||
@ -45,4 +44,33 @@ if (
|
||||
fclose($fp);
|
||||
}
|
||||
$this->setData(['core', 'dataVersion', 1800]);
|
||||
}
|
||||
}
|
||||
|
||||
if (
|
||||
$this->getData(['core', 'dataVersion']) < 12002
|
||||
) {
|
||||
|
||||
/**
|
||||
* Installe dans le thème du menu la variable hidePages
|
||||
**/
|
||||
// Tableau à insérer
|
||||
$a = [
|
||||
'theme' =>
|
||||
['menu' => [
|
||||
'hidePages' => false
|
||||
]]];
|
||||
// Parcourir la structure pour écrire dans les fichiers JSON
|
||||
foreach ($this->getData(['course']) as $courseId => $courseValues) {
|
||||
$d = json_decode(file_get_contents(self::DATA_DIR . $courseId . '/theme.json'), true);
|
||||
// Insérer la variable hidePages si elle n'existe pas
|
||||
if (isset($d['theme']['menu']['hidePages']) === false) {
|
||||
$result = array_replace_recursive($d, $a);
|
||||
file_put_contents(self::DATA_DIR . $courseId . '/theme.json', json_encode($result,JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES));
|
||||
}
|
||||
// Forcer la régénération du fichier theme.css
|
||||
if (file_exists(self::DATA_DIR . $courseId . '/theme.css')) {
|
||||
unlink(self::DATA_DIR . $courseId . '/theme.css');
|
||||
}
|
||||
}
|
||||
$this->setData(['core', 'dataVersion', 12002]);
|
||||
}
|
||||
|
@ -657,6 +657,7 @@ nav a:hover {
|
||||
|
||||
#menuLeft {
|
||||
display: inline-flex;
|
||||
float: left;
|
||||
}
|
||||
|
||||
#menuRight {
|
||||
|
22
core/layout/error.css
Normal file
22
core/layout/error.css
Normal file
@ -0,0 +1,22 @@
|
||||
body {
|
||||
color: #000;
|
||||
font: 75%/1.7em "Helvetica Neue", Helvetica, arial, sans-serif;
|
||||
margin: 0;
|
||||
padding: 80px;
|
||||
background: url('../vendor/zwiico/png/error.png') 30px 30px no-repeat #fff;
|
||||
}
|
||||
|
||||
h1 {
|
||||
font-weight: bold;
|
||||
color: #000;
|
||||
font-size: 300%;
|
||||
margin: 20px 0;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
p {
|
||||
margin: 10px 0;
|
||||
color: #777;
|
||||
font-size: 16px;
|
||||
line-height: 1.6;
|
||||
}
|
@ -44,7 +44,7 @@
|
||||
<?php echo template::checkbox('configRewrite', true, 'Apache URL intelligentes', [
|
||||
'checked' => helper::checkRewrite(),
|
||||
'help' => 'Supprime le point d\'interrogation dans les URL, l\'option est indisponible avec les autres serveurs Web',
|
||||
'disabled' => helper::checkServerSoftware() === false and config->isModRewriteEnabled()
|
||||
'disabled' => helper::checkServerSoftware() === false and self::isModRewriteEnabled()
|
||||
]); ?>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -339,7 +339,7 @@ class course extends common
|
||||
|
||||
// Valeurs en sortie
|
||||
$this->addOutput([
|
||||
'title' => sprintf('%s %s (%s)', helper::translate('Editer l\'espace'), $this->getData(['course', $courseId, 'title' ]), $this->getUrl(2)),
|
||||
'title' => sprintf('%s %s (%s)', helper::translate('Editer l\'espace'), $this->getData(['course', $courseId, 'title']), $this->getUrl(2)),
|
||||
'view' => 'edit'
|
||||
]);
|
||||
}
|
||||
@ -398,7 +398,7 @@ class course extends common
|
||||
|
||||
// Valeurs en sortie
|
||||
$this->addOutput([
|
||||
'title' => sprintf('%s %s (%s)', helper::translate('Gérer l\'espace'), $this->getData(['course', $courseId, 'title' ]), $this->getUrl(2)),
|
||||
'title' => sprintf('%s %s (%s)', helper::translate('Gérer l\'espace'), $this->getData(['course', $courseId, 'title']), $this->getUrl(2)),
|
||||
'view' => 'manage'
|
||||
]);
|
||||
}
|
||||
@ -736,17 +736,15 @@ class course extends common
|
||||
}
|
||||
self::$courseUsers[] = [
|
||||
//$userId,
|
||||
sprintf('%s %s',$this->getData(['user', $userId, 'lastname']), $this->getData(['user', $userId, 'firstname'])),
|
||||
array_key_exists('lastPageView', $userValue) && isset($pages[$userValue['lastPageView']]['title'])
|
||||
? $pages[$userValue['lastPageView']]['title']
|
||||
: '',
|
||||
array_key_exists('lastPageView', $userValue)
|
||||
? helper::dateUTF8('%d/%m/%Y', $userValue['datePageView'])
|
||||
: '',
|
||||
array_key_exists('datePageView', $userValue)
|
||||
? helper::dateUTF8('%H:%M', $userValue['datePageView'])
|
||||
sprintf('%s %s', $this->getData(['user', $userId, 'lastname']), $this->getData(['user', $userId, 'firstname'])),
|
||||
array_key_exists('lastPageView', $userValue) && isset($pages['page'][$userValue['lastPageView']]['title'])
|
||||
? $pages['page'][$userValue['lastPageView']]['title']
|
||||
: '',
|
||||
$this->getData(['user', $userId, 'tags']),
|
||||
array_key_exists('lastPageView', $userValue)
|
||||
// ? helper::dateUTF8('%d/%m/%Y', $userValue['datePageView'])
|
||||
? $userValue['datePageView']
|
||||
: '',
|
||||
$reportButton,
|
||||
template::button('userDelete' . $userId, [
|
||||
'class' => 'userDelete buttonRed',
|
||||
@ -1846,7 +1844,7 @@ class course extends common
|
||||
|
||||
// Valeurs en sortie
|
||||
$this->addOutput([
|
||||
'title' => sprintf('%s %s (%s)', helper::translate('Export des pages de l\'espace'), $this->getData(['course', $courseId, 'title' ]), $this->getUrl(2)),
|
||||
'title' => sprintf('%s %s (%s)', helper::translate('Export des pages de l\'espace'), $this->getData(['course', $courseId, 'title']), $this->getUrl(2)),
|
||||
'view' => 'export'
|
||||
]);
|
||||
}
|
||||
@ -2223,4 +2221,4 @@ class course extends common
|
||||
// Afficher le JSON;
|
||||
return $data;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -21,7 +21,6 @@ $(document).ready((function () {
|
||||
$(location).attr("href", _this.attr("href"))
|
||||
}))
|
||||
}));
|
||||
$.fn.dataTable.moment( 'DD/MM/YYYY' );
|
||||
$('#dataTables').DataTable({
|
||||
language: {
|
||||
url: "core/vendor/datatables/french.json"
|
||||
@ -29,14 +28,20 @@ $(document).ready((function () {
|
||||
order: [[3, 'desc']],
|
||||
locale: 'fr',
|
||||
stateSave: true,
|
||||
"lengthMenu": [[10, 25, 50, 100, 299, -1], [10, 25, 50, 100, 200, "Tout"]],
|
||||
"lengthMenu": [[10, 25, 50, 100, 299, -1], [10, 25, 50, 100, 200, "Tout"]],
|
||||
"columnDefs": [
|
||||
{
|
||||
target: 6,
|
||||
targets: 3,
|
||||
type: 'numeric',
|
||||
render: function (data) {
|
||||
return moment(data * 1000).format('DD/MM/YYYY HH:mm');
|
||||
}
|
||||
},
|
||||
{
|
||||
targets: 5,
|
||||
orderable: false,
|
||||
searchable: false
|
||||
}
|
||||
]
|
||||
}]
|
||||
});
|
||||
|
||||
}));
|
@ -53,7 +53,7 @@
|
||||
</div>
|
||||
<?php echo template::formClose(); ?>
|
||||
<?php if (course::$courseUsers): ?>
|
||||
<?php echo template::table([3, 4, 1, 1, 1, 1, 1], course::$courseUsers, ['Nom Prénom', 'Dernière page vue', 'Date' , 'Heure', 'Étiquettes', 'Progression', ''], ['id' => 'dataTables']); ?>
|
||||
<?php echo template::table([3, 3, 2, 2, 1, 1], course::$courseUsers, ['Nom Prénom', 'Dernière page vue', 'Date' , 'Étiquettes', 'Progression', ''], ['id' => 'dataTables']); ?>
|
||||
<?php else: ?>
|
||||
<?php echo template::speech('Aucun participant'); ?>
|
||||
<?php endif; ?>
|
@ -64,7 +64,7 @@ class init extends common
|
||||
]
|
||||
],
|
||||
'core' => [
|
||||
'dataVersion' => 1700,
|
||||
'dataVersion' => 12002,
|
||||
'lastBackup' => 0,
|
||||
'lastClearTmp' => 0,
|
||||
'lastAutoUpdate' => 0,
|
||||
@ -903,7 +903,8 @@ class init extends common
|
||||
'selectSpace' => true,
|
||||
'burgerLogo' => '',
|
||||
'burgerContent' => 'title',
|
||||
'width' => 'container'
|
||||
'width' => 'container',
|
||||
'hidePages' => false,
|
||||
],
|
||||
'site' => [
|
||||
'backgroundColor' => 'rgba(255, 255, 255, 1)',
|
||||
|
@ -15,4 +15,8 @@
|
||||
|
||||
/** NE PAS EFFACER
|
||||
* admin.css
|
||||
*/
|
||||
*/
|
||||
|
||||
.container.light {
|
||||
filter: drop-shadow(5px 5px 10px rgba(0, 0, 0, 0.2));
|
||||
}
|
@ -19,4 +19,8 @@
|
||||
|
||||
.title {
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.container.light {
|
||||
filter: drop-shadow(5px 5px 10px rgba(0, 0, 0, 0.2));
|
||||
}
|
@ -24,7 +24,6 @@ class page extends common
|
||||
'duplicate' => self::GROUP_EDITOR,
|
||||
'jsEditor' => self::GROUP_EDITOR,
|
||||
'cssEditor' => self::GROUP_EDITOR,
|
||||
'register' => self::GROUP_EDITOR,
|
||||
];
|
||||
public static $pagesNoParentId = [
|
||||
'' => 'Aucune'
|
||||
@ -474,7 +473,7 @@ class page extends common
|
||||
$this->setData(['config', 'page302', $pageId], false);
|
||||
}
|
||||
// Sauvegarde la base manuellement
|
||||
$this->saveDB(module: 'config');
|
||||
$this->saveDB('config');
|
||||
// Si la page est une page enfant, actualise les positions des autres enfants du parent, sinon actualise les pages sans parents
|
||||
$lastPosition = 1;
|
||||
$hierarchy = $this->getInput('pageEditParentPageId') ? $this->getHierarchy($this->getInput('pageEditParentPageId')) : array_keys($this->getHierarchy());
|
||||
@ -594,6 +593,19 @@ class page extends common
|
||||
]
|
||||
]);
|
||||
|
||||
/**
|
||||
* Sauvegarde l'onglet de l'utilisateur
|
||||
*/
|
||||
$this->setData([
|
||||
'user',
|
||||
$this->getUser('id'),
|
||||
'view',
|
||||
[
|
||||
'page' => $this->getInput('containerSelected'),
|
||||
'config' => $this->getData(['user', $this->getUser('id'), 'view', 'config']),
|
||||
]
|
||||
]);
|
||||
|
||||
// Creation du contenu de la page
|
||||
if (!is_dir(self::DATA_DIR . self::$siteContent . '/content')) {
|
||||
mkdir(self::DATA_DIR . self::$siteContent . '/content', 0755);
|
||||
@ -760,25 +772,4 @@ class page extends common
|
||||
return json_encode($d);
|
||||
}
|
||||
|
||||
/**
|
||||
* Stocke la variable dans les paramètres de l'utilisateur pour activer la tab à sa prochaine visite
|
||||
* @return never
|
||||
*/
|
||||
public function register(): void
|
||||
{
|
||||
$this->setData([
|
||||
'user',
|
||||
$this->getUser('id'),
|
||||
'view',
|
||||
[
|
||||
'page' => $this->getUrl(2),
|
||||
'config' => $this->getData(['user', $this->getUser('id'), 'view', 'config']),
|
||||
]
|
||||
]);
|
||||
// Valeurs en sortie
|
||||
$this->addOutput([
|
||||
'redirect' => helper::baseUrl() . 'page/edit/' . $this->getUrl(3) . '/' . self::$siteContent,
|
||||
]);
|
||||
}
|
||||
|
||||
}
|
@ -54,15 +54,15 @@ function protectModule() {
|
||||
*/
|
||||
$( document ).ready(function() {
|
||||
|
||||
// Changement de profil
|
||||
// Changement de profil
|
||||
$(".pageEditGroupProfil").hide();
|
||||
$("#pageEditGroupProfil" + $("#pageEditGroup").val()).show();
|
||||
|
||||
$("#pageEditGroup").on("change", function () {
|
||||
$(".pageEditGroupProfil").hide();
|
||||
$("#pageEditGroupProfil" + $("#pageEditGroup").val()).show();
|
||||
|
||||
$("#pageEditGroup").on("change", function () {
|
||||
$(".pageEditGroupProfil").hide();
|
||||
$("#pageEditGroupProfil" + $(this).val()).show();
|
||||
});
|
||||
|
||||
$("#pageEditGroupProfil" + $(this).val()).show();
|
||||
});
|
||||
|
||||
|
||||
/**
|
||||
* Sélection des onglets
|
||||
@ -70,7 +70,7 @@ $( document ).ready(function() {
|
||||
var pageLayout = "<?php echo $this->getData(['user', $this->getUser('id'), 'view', 'page']);?>";
|
||||
// Non défini, valeur par défaut
|
||||
if (pageLayout == "") {
|
||||
pageLayout = "content";
|
||||
pageLayout = "content";
|
||||
}
|
||||
// Tout cacher
|
||||
$("#pageEditContentContainer").hide();
|
||||
@ -283,10 +283,18 @@ $( document ).ready(function() {
|
||||
// Gestion des évènements
|
||||
//--------------------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Transmet le bouton de l'onglet sélectionné avant la soumission
|
||||
*/
|
||||
$('#pageEditForm').on('submit', function () {
|
||||
$('#containerSelected').val(pageLayout);
|
||||
});
|
||||
|
||||
/**
|
||||
* Sélection de la page de configuration à afficher
|
||||
*/
|
||||
$("#pageEditContentButton").on("click", function () {
|
||||
pageLayout = "locale";
|
||||
$("#pageEditContentContainer").show();
|
||||
$("#pageEditExtensionContainer").hide();
|
||||
$("#pageEditPositionContainer").hide();
|
||||
@ -294,23 +302,12 @@ $( document ).ready(function() {
|
||||
$("#pageEditPermissionContainer").hide();
|
||||
$("#pageEditContentButton").addClass("activeButton");
|
||||
$("#pageEditExtensionButton").removeClass("activeButton");
|
||||
$("#PageEditPositionButton").removeClass("activeButton");
|
||||
$("#pageEditPositionButton").removeClass("activeButton");
|
||||
$("#pageEditLayoutButton").removeClass("activeButton");
|
||||
$("#pageEditPermissionButton").removeClass("activeButton");
|
||||
});
|
||||
$("#pageEditExtensionButton").on("click", function () {
|
||||
$("#pageEditContentContainer").hide();
|
||||
$("#pageEditExtensionContainer").show();
|
||||
$("#pageEditPositionContainer").hide();
|
||||
$("#pageEditLayoutContainer").hide();
|
||||
$("#pageEditPermissionContainer").hide();
|
||||
$("#pageEditContentButton").removeClass("activeButton");
|
||||
$("#pageEditExtensionButton").addClass("activeButton");
|
||||
$("#PageEditPositionButton").removeClass("activeButton");
|
||||
$("#pageEditLayoutButton").removeClass("activeButton");
|
||||
$("#pageEditPermissionButton").removeClass("activeButton");
|
||||
});
|
||||
$("#PageEditPositionButton").on("click", function () {
|
||||
$("#pageEditPositionButton").on("click", function () {
|
||||
pageLayout = "position";
|
||||
$("#pageEditContentContainer").hide();
|
||||
$("#pageEditExtensionContainer").hide();
|
||||
$("#pageEditPositionContainer").show();
|
||||
@ -318,11 +315,25 @@ $( document ).ready(function() {
|
||||
$("#pageEditPermissionContainer").hide();
|
||||
$("#pageEditContentButton").removeClass("activeButton");
|
||||
$("#pageEditExtensionButton").removeClass("activeButton");
|
||||
$("#PageEditPositionButton").addClass("activeButton");
|
||||
$("#pageEditPositionButton").addClass("activeButton");
|
||||
$("#pageEditLayoutButton").removeClass("activeButton");
|
||||
$("#pageEditPermissionButton").removeClass("activeButton");
|
||||
});
|
||||
$("#pageEditExtensionButton").on("click", function () {
|
||||
pageLayout = "extension";
|
||||
$("#pageEditContentContainer").hide();
|
||||
$("#pageEditExtensionContainer").show();
|
||||
$("#pageEditPositionContainer").hide();
|
||||
$("#pageEditLayoutContainer").hide();
|
||||
$("#pageEditPermissionContainer").hide();
|
||||
$("#pageEditContentButton").removeClass("activeButton");
|
||||
$("#pageEditExtensionButton").addClass("activeButton");
|
||||
$("#pageEditPositionButton").removeClass("activeButton");
|
||||
$("#pageEditLayoutButton").removeClass("activeButton");
|
||||
$("#pageEditPermissionButton").removeClass("activeButton");
|
||||
});
|
||||
$("#pageEditLayoutButton").on("click", function () {
|
||||
pageLayout = "layout";
|
||||
$("#pageEditContentContainer").hide();
|
||||
$("#pageEditExtensionContainer").hide();
|
||||
$("#pageEditPositionContainer").hide();
|
||||
@ -330,11 +341,12 @@ $( document ).ready(function() {
|
||||
$("#pageEditPermissionContainer").hide();
|
||||
$("#pageEditContentButton").removeClass("activeButton");
|
||||
$("#pageEditExtensionButton").removeClass("activeButton");
|
||||
$("#PageEditPositionButton").removeClass("activeButton");
|
||||
$("#pageEditPositionButton").removeClass("activeButton");
|
||||
$("#pageEditLayoutButton").addClass("activeButton");
|
||||
$("#pageEditPermissionButton").removeClass("activeButton");
|
||||
});
|
||||
$("#pageEditPermissionButton").on("click", function () {
|
||||
pageLayout = "permission";
|
||||
$("#pageEditContentContainer").hide();
|
||||
$("#pageEditExtensionContainer").hide();
|
||||
$("#pageEditPositionContainer").hide();
|
||||
|
@ -35,30 +35,33 @@
|
||||
<?php echo template::button('pageEditContentButton', [
|
||||
'value' => 'Contenu',
|
||||
'class' => 'buttonTab',
|
||||
'href' => helper::baseUrl() . 'page/register/content/' . $this->geturl(2)
|
||||
//'href' => helper::baseUrl() . 'page/register/content/' . $this->geturl(2)
|
||||
]); ?>
|
||||
<?php echo template::button('pageEditPositionButton', [
|
||||
'value' => 'Menu',
|
||||
'class' => 'buttonTab',
|
||||
'href' => helper::baseUrl() . 'page/register/position/' . $this->geturl(2)
|
||||
//'href' => helper::baseUrl() . 'page/register/position/' . $this->geturl(2)
|
||||
]); ?>
|
||||
<?php echo template::button('pageEditExtensionButton', [
|
||||
'value' => 'Extension',
|
||||
'class' => 'buttonTab',
|
||||
'href' => helper::baseUrl() . 'page/register/extension/' . $this->geturl(2)
|
||||
//'href' => helper::baseUrl() . 'page/register/extension/' . $this->geturl(2)
|
||||
]); ?>
|
||||
<?php echo template::button('pageEditLayoutButton', [
|
||||
'value' => 'Mise en page',
|
||||
'class' => 'buttonTab',
|
||||
'href' => helper::baseUrl() . 'page/register/layout/' . $this->geturl(2)
|
||||
//'href' => helper::baseUrl() . 'page/register/layout/' . $this->geturl(2)
|
||||
]); ?>
|
||||
<?php echo template::button('pageEditPermissionButton', [
|
||||
'value' => 'Permission',
|
||||
'class' => 'buttonTab',
|
||||
'href' => helper::baseUrl() . 'page/register/permission/' . $this->geturl(2)
|
||||
//'href' => helper::baseUrl() . 'page/register/permission/' . $this->geturl(2)
|
||||
]); ?>
|
||||
</div>
|
||||
|
||||
<!-- Champ caché pour transmettre l'onglet-->
|
||||
<?php echo template::hidden('containerSelected'); ?>
|
||||
|
||||
<div id="pageEditContentContainer" class="tabContent">
|
||||
<div class="row">
|
||||
<div class="col12">
|
||||
|
@ -151,9 +151,9 @@ class user extends common
|
||||
$userMail,
|
||||
'Compte créé sur ' . $this->getData(['config', 'title']),
|
||||
'Bonjour <strong>' . $userFirstname . ' ' . $userLastname . '</strong>,<br><br>' .
|
||||
'Un administrateur vous a créé un compte sur le site ' . $this->getData(['config', 'title']) . '. Vous trouverez ci-dessous les détails de votre compte.<br><br>' .
|
||||
'<strong>Identifiant du compte :</strong> ' . $this->getInput('userAddId') . '<br>' .
|
||||
'<small>Nous ne conservons pas les mots de passe, en conséquence nous vous conseillons de conserver ce message tant que vous ne vous êtes pas connecté. Vous pourrez modifier votre mot de passe après votre première connexion.</small>',
|
||||
'Un administrateur vous a créé un compte sur le site ' . $this->getData(['config', 'title']) . '. Vous trouverez ci-dessous les détails de votre compte.<br><br>' .
|
||||
'<strong>Identifiant du compte :</strong> ' . $this->getInput('userAddId') . '<br>' .
|
||||
'<small>Nous ne conservons pas les mots de passe, en conséquence nous vous conseillons de conserver ce message tant que vous ne vous êtes pas connecté. Vous pourrez modifier votre mot de passe après votre première connexion.</small>',
|
||||
null,
|
||||
$this->getData(['config', 'smtp', 'from'])
|
||||
);
|
||||
@ -284,7 +284,6 @@ class user extends common
|
||||
'notification' => sprintf($count > 1 ? $notification . 's' : $notification, $count),
|
||||
'state' => $success
|
||||
]);
|
||||
|
||||
}
|
||||
|
||||
// Liste des groupes et des profils
|
||||
@ -367,7 +366,6 @@ class user extends common
|
||||
$this->getData(['user', $userId, 'lastname']),
|
||||
$this->getData(['user', $userId, 'tags']),
|
||||
];
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@ -409,7 +407,7 @@ class user extends common
|
||||
$this->getData(['user', $this->getUrl(2)]) === null
|
||||
// Droit d'édition
|
||||
and (
|
||||
// Impossible de s'auto-éditer
|
||||
// Impossible de s'auto-éditer
|
||||
($this->getUser('id') === $this->getUrl(2)
|
||||
and $this->getUrl('group') <= self::GROUP_VISITOR
|
||||
)
|
||||
@ -571,33 +569,34 @@ class user extends common
|
||||
public function forgot()
|
||||
{
|
||||
// Soumission du formulaire
|
||||
if (
|
||||
$this->isPost()
|
||||
) {
|
||||
if ($this->isPost()) {
|
||||
$userId = $this->getInput('userForgotId', helper::FILTER_ID, true);
|
||||
$sent = false;
|
||||
if ($this->getData(['user', $userId])) {
|
||||
// Enregistre la date de la demande dans le compte utilisateur
|
||||
$this->setData(['user', $userId, 'forgot', time()]);
|
||||
// Crée un id unique pour la réinitialisation
|
||||
$uniqId = md5(json_encode($this->getData(['user', $userId, 'forgot'])));
|
||||
// Génère une clé unique avec timestamp et partie aléatoire
|
||||
$timestamp = time(); // Timestamp actuel
|
||||
$randomPart = bin2hex(random_bytes(8)); // Partie aléatoire (16 caractères hexadécimaux)
|
||||
$uniqId = $timestamp . '_' . $randomPart; // Combine les deux
|
||||
|
||||
// Enregistre la clé unique dans le compte utilisateur
|
||||
$this->setData(['user', $userId, 'forgot', $uniqId]);
|
||||
|
||||
// Envoi le mail
|
||||
$sent = $this->sendMail(
|
||||
$this->getData(['user', $userId, 'mail']),
|
||||
'Réinitialisation de votre mot de passe',
|
||||
'Bonjour <strong>' . $this->getData(['user', $userId, 'firstname']) . ' ' . $this->getData(['user', $userId, 'lastname']) . '</strong>,<br><br>' .
|
||||
'Vous avez demandé à changer le mot de passe lié à votre compte. Vous trouverez ci-dessous un lien vous permettant de modifier celui-ci.<br><br>' .
|
||||
'<a href="' . helper::baseUrl() . 'user/reset/' . $userId . '/' . $uniqId . '" target="_blank">' . helper::baseUrl() . 'user/reset/' . $userId . '/' . $uniqId . '</a><br><br>' .
|
||||
'<small>Si nous n\'avez pas demandé à réinitialiser votre mot de passe, veuillez ignorer ce mail.</small>',
|
||||
'Vous avez demandé à changer le mot de passe lié à votre compte. Vous trouverez ci-dessous un lien vous permettant de modifier celui-ci.<br><br>' .
|
||||
'<a href="' . helper::baseUrl() . 'user/reset/' . $userId . '/' . $uniqId . '" target="_blank">' . helper::baseUrl() . 'user/reset/' . $userId . '/' . $uniqId . '</a><br><br>' .
|
||||
'<small>Si nous n\'avez pas demandé à réinitialiser votre mot de passe, veuillez ignorer ce mail.</small>',
|
||||
null,
|
||||
$this->getData(['config', 'smtp', 'from'])
|
||||
);
|
||||
|
||||
}
|
||||
|
||||
// Valeurs en sortie
|
||||
$this->addOutput([
|
||||
'notification' => $sent ? helper::translate('Un mail a été envoyé pour confirmer la réinitialisation') : helper::translate('Impossible de réinitialiser le mot de passe de ce compte !'),
|
||||
'notification' => $sent === true ? helper::translate('Un mail a été envoyé pour confirmer la réinitialisation') : helper::translate('Le mail de réinitialisation ne peut pas être envoyé, contactez l\'administrateur'),
|
||||
'state' => ($sent === true ? true : false),
|
||||
'redirect' => helper::baseUrl()
|
||||
]);
|
||||
@ -680,18 +679,19 @@ class user extends common
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
|
||||
// Formatage de la liste
|
||||
self::$users[] = [
|
||||
//$userId,
|
||||
sprintf('%s %s',$userLastNames, $this->getData(['user', $userId, 'firstname'])),
|
||||
sprintf('%s %s', $userLastNames, $this->getData(['user', $userId, 'firstname'])),
|
||||
helper::translate(self::$groups[(int) $this->getData(['user', $userId, 'group'])]),
|
||||
empty($this->getData(['profil', $this->getData(['user', $userId, 'group']), $this->getData(['user', $userId, 'profil']), 'name']))
|
||||
? helper::translate(self::$groups[(int) $this->getData(['user', $userId, 'group'])])
|
||||
: $this->getData(['profil', $this->getData(['user', $userId, 'group']), $this->getData(['user', $userId, 'profil']), 'name']),
|
||||
? helper::translate(self::$groups[(int) $this->getData(['user', $userId, 'group'])])
|
||||
: $this->getData(['profil', $this->getData(['user', $userId, 'group']), $this->getData(['user', $userId, 'profil']), 'name']),
|
||||
$this->getData(['user', $userId, 'tags']),
|
||||
helper::dateUTF8('%d/%m/%Y', $this->getData(['user', $userId, 'accessTimer']), self::$i18nUI),
|
||||
is_null($this->getData(['user', $userId, 'accessTimer']))
|
||||
? 'Jamais'
|
||||
: $this->getData(['user', $userId, 'accessTimer']),
|
||||
//helper::dateUTF8('%d/%m/%Y', $this->getData(['user', $userId, 'accessTimer']), self::$i18nUI),
|
||||
//helper::dateUTF8('%H:%M', $this->getData(['user', $userId, 'accessTimer']), self::$i18nUI),
|
||||
template::button('userEdit' . $userId, [
|
||||
'href' => helper::baseUrl() . 'user/edit/' . $userId,
|
||||
@ -705,7 +705,6 @@ class user extends common
|
||||
'help' => 'Supprimer'
|
||||
])
|
||||
];
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@ -1352,7 +1351,7 @@ class user extends common
|
||||
$this->getData(['user', $userId, 'mail']),
|
||||
'Validation de la connexion à votre compte',
|
||||
'<p>Clé de validation à saisir dans le formulaire de connexion :</p>' .
|
||||
'<h1><center>' . $keyByMail . '</center></h1>',
|
||||
'<h1><center>' . $keyByMail . '</center></h1>',
|
||||
null,
|
||||
$this->getData(['config', 'smtp', 'from'])
|
||||
);
|
||||
@ -1474,7 +1473,7 @@ class user extends common
|
||||
$inputKey = $this->getInput('userAuthKey', helper::FILTER_INT);
|
||||
// Redirection
|
||||
$pageId = $this->getUrl(2);
|
||||
$redirect = $pageId? helper::baseUrl() . $pageId : helper::baseUrl() ;
|
||||
$redirect = $pageId ? helper::baseUrl() . $pageId : helper::baseUrl();
|
||||
if (
|
||||
// La clé est valide ou le message n'ayant pas été expédié, la double authentification est désactivée
|
||||
$targetKey === $inputKey || $this->getData(['config', 'connect', 'mailAuth', 0]) === 0
|
||||
@ -1555,44 +1554,44 @@ class user extends common
|
||||
if (
|
||||
// L'utilisateur n'existe pas
|
||||
$this->getData(['user', $this->getUrl(2)]) === null
|
||||
// Lien de réinitialisation trop vieux
|
||||
or $this->getData(['user', $this->getUrl(2), 'forgot']) + 86400 < time()
|
||||
// Id unique incorrecte
|
||||
or $this->getUrl(3) !== md5(json_encode($this->getData(['user', $this->getUrl(2), 'forgot'])))
|
||||
// Lien de réinitialisation trop vieux (24 heures)
|
||||
or $this->getData(['user', $this->getUrl(2), 'forgot']) === null
|
||||
or (int) explode('_', $this->getData(['user', $this->getUrl(2), 'forgot']))[0] + 86400 < time()
|
||||
// Clé unique incorrecte
|
||||
or $this->getUrl(3) !== $this->getData(['user', $this->getUrl(2), 'forgot'])
|
||||
) {
|
||||
$this->saveLog(
|
||||
' Erreur de réinitialisation de mot de passe ' . $this->getUrl(2) .
|
||||
' Compte : ' . $this->getData(['user', $this->getUrl(2)]) .
|
||||
' Temps : ' . $this->getData(['user', $this->getUrl(2), 'forgot']) + 86400 < time() .
|
||||
' Clé : ' . $this->getUrl(3) !== md5(json_encode($this->getData(['user', $this->getUrl(2), 'forgot'])))
|
||||
' Temps : ' . ($this->getData(['user', $this->getUrl(2), 'forgot']) === null ? 'Clé manquante' : ((int) explode('_', $this->getData(['user', $this->getUrl(2), 'forgot']))[0] + 86400 < time() ? 'Temps dépassé' : 'Temps valide')) .
|
||||
' Clé : ' . ($this->getUrl(3) !== $this->getData(['user', $this->getUrl(2), 'forgot']) ? 'Clé invalide' : 'Clé valide')
|
||||
);
|
||||
|
||||
// Message d'erreur en cas de problème de réinitialisation de mot de passe
|
||||
$message = $this->getData(['user', $this->getUrl(2)]) === null
|
||||
? ' Utilisateur inconnu '
|
||||
: '';
|
||||
$message = $this->getData(['user', $this->getUrl(2), 'forgot']) + 86400 < time()
|
||||
$message = $this->getData(['user', $this->getUrl(2), 'forgot']) === null
|
||||
? ' Clé manquante '
|
||||
: $message;
|
||||
$message = (int) explode('_', $this->getData(['user', $this->getUrl(2), 'forgot']))[0] + 86400 < time()
|
||||
? ' Temps dépassé '
|
||||
: $message;
|
||||
$message = $this->getUrl(3) !== md5(json_encode($this->getData(['user', $this->getUrl(2)])))
|
||||
$message = $this->getUrl(3) !== $this->getData(['user', $this->getUrl(2), 'forgot'])
|
||||
? ' Clé invalide '
|
||||
: $message;
|
||||
|
||||
|
||||
// Valeurs en sortie
|
||||
$this->addOutput([
|
||||
'redirect' => helper::baseurl(),
|
||||
'notification' => helper::translate('Impossible de réinitialiser le mot de passe de ce compte !') . $message,
|
||||
'state' => false
|
||||
//'access' => false
|
||||
]);
|
||||
}
|
||||
// Accès autorisé
|
||||
else {
|
||||
// Soumission du formulaire
|
||||
if (
|
||||
// Tous les users peuvent réinitialiser
|
||||
// $this->getUser('permission', __CLASS__, __FUNCTION__) === true &&
|
||||
$this->isPost()
|
||||
) {
|
||||
if ($this->isPost()) {
|
||||
// Double vérification pour le mot de passe
|
||||
if ($this->getInput('userResetNewPassword')) {
|
||||
// La confirmation ne correspond pas au mot de passe
|
||||
@ -1691,8 +1690,8 @@ class user extends common
|
||||
$item['prenom'],
|
||||
self::$groups[$item['groupe']],
|
||||
empty($this->getData(['profil', $this->getData(['user', $userId, 'group']), $this->getData(['user', $userId, 'profil']), 'name']))
|
||||
? helper::translate(self::$groups[(int) $this->getData(['user', $userId, 'group'])])
|
||||
: $this->getData(['profil', $this->getData(['user', $userId, 'group']), $this->getData(['user', $userId, 'profil']), 'name']),
|
||||
? helper::translate(self::$groups[(int) $this->getData(['user', $userId, 'group'])])
|
||||
: $this->getData(['profil', $this->getData(['user', $userId, 'group']), $this->getData(['user', $userId, 'profil']), 'name']),
|
||||
$item['prenom'],
|
||||
helper::filter($item['email'], helper::FILTER_MAIL),
|
||||
$item['tags'],
|
||||
@ -1736,9 +1735,9 @@ class user extends common
|
||||
$item['email'],
|
||||
'Compte créé sur ' . $this->getData(['config', 'title']),
|
||||
'Bonjour <strong>' . $item['prenom'] . ' ' . $item['nom'] . '</strong>,<br><br>' .
|
||||
'Un administrateur vous a créé un compte sur le site ' . $this->getData(['config', 'title']) . '. Vous trouverez ci-dessous les détails de votre compte.<br><br>' .
|
||||
'<strong>Identifiant du compte :</strong> ' . $userId . '<br>' .
|
||||
'<small>Un mot de passe provisoire vous été attribué, à la première connexion cliquez sur Mot de passe Oublié.</small>',
|
||||
'Un administrateur vous a créé un compte sur le site ' . $this->getData(['config', 'title']) . '. Vous trouverez ci-dessous les détails de votre compte.<br><br>' .
|
||||
'<strong>Identifiant du compte :</strong> ' . $userId . '<br>' .
|
||||
'<small>Un mot de passe provisoire vous été attribué, à la première connexion cliquez sur Mot de passe Oublié.</small>',
|
||||
null,
|
||||
$this->getData(['config', 'smtp', 'from'])
|
||||
);
|
||||
@ -1754,8 +1753,8 @@ class user extends common
|
||||
$item['prenom'],
|
||||
self::$groups[$item['groupe']],
|
||||
empty($this->getData(['profil', $this->getData(['user', $userId, 'group']), $this->getData(['user', $userId, 'profil']), 'name']))
|
||||
? helper::translate(self::$groups[(int) $this->getData(['user', $userId, 'group'])])
|
||||
: $this->getData(['profil', $this->getData(['user', $userId, 'group']), $this->getData(['user', $userId, 'profil']), 'name']),
|
||||
? helper::translate(self::$groups[(int) $this->getData(['user', $userId, 'group'])])
|
||||
: $this->getData(['profil', $this->getData(['user', $userId, 'group']), $this->getData(['user', $userId, 'profil']), 'name']),
|
||||
$item['prenom'],
|
||||
$item['email'],
|
||||
$item['tags'],
|
||||
@ -1763,7 +1762,6 @@ class user extends common
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
// Sauvegarde la base manuellement
|
||||
$this->saveDB('user');
|
||||
@ -1805,7 +1803,6 @@ class user extends common
|
||||
readfile($path . $file);
|
||||
exit();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public function tag()
|
||||
@ -1848,7 +1845,6 @@ class user extends common
|
||||
'notification' => sprintf($count > 1 ? $notification . 's' : $notification, $count),
|
||||
'state' => $success
|
||||
]);
|
||||
|
||||
}
|
||||
|
||||
|
||||
@ -1932,7 +1928,6 @@ class user extends common
|
||||
$this->getData(['user', $userId, 'lastname']),
|
||||
$this->getData(['user', $userId, 'tags']),
|
||||
];
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@ -1953,7 +1948,6 @@ class user extends common
|
||||
'datatables'
|
||||
]
|
||||
]);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
@ -1987,5 +1981,4 @@ class user extends common
|
||||
closedir($dh);
|
||||
return $subdirs;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
@ -15,4 +15,14 @@
|
||||
|
||||
/** NE PAS EFFACER
|
||||
* admin.css
|
||||
*/
|
||||
*/
|
||||
|
||||
/** Hide the timestamp column in the user list
|
||||
*/
|
||||
tbody td:nth-child(5) {
|
||||
color: transparent; /* Masquer le texte par défaut */
|
||||
}
|
||||
|
||||
tbody td.visible-text {
|
||||
color: inherit; /* Rétablir la couleur du texte */
|
||||
}
|
@ -31,6 +31,20 @@ $(document).ready((function () {
|
||||
stateSave: true,
|
||||
"lengthMenu": [[10, 25, 50, -1], [10, 25, 50, "Tout"]],
|
||||
"columnDefs": [
|
||||
{
|
||||
target: 4,
|
||||
type: 'num', // Utilisez 'num' pour le tri
|
||||
render: function (data) {
|
||||
// Si data est un nombre, formatez-le en date
|
||||
if (typeof data === 'number' || !isNaN(data)) {
|
||||
return moment(Number(data) * 1000).format('DD/MM/YYYY HH:mm');
|
||||
} else {
|
||||
return data; // Sinon, affichez le texte tel quel
|
||||
}
|
||||
},
|
||||
orderable: false,
|
||||
searchable: false
|
||||
},
|
||||
{
|
||||
target: 5,
|
||||
orderable: false,
|
||||
@ -43,4 +57,15 @@ $(document).ready((function () {
|
||||
}
|
||||
]
|
||||
});
|
||||
|
||||
// Injecter la règle CSS pour la colonne cible
|
||||
$('<style>')
|
||||
.prop('type', 'text/css')
|
||||
.html(`
|
||||
table.dataTable tbody td:nth-child(5) {
|
||||
color: inherit !important; /* Rétablir la couleur du texte */
|
||||
}
|
||||
`)
|
||||
.appendTo('head');
|
||||
|
||||
}));
|
@ -68,4 +68,4 @@
|
||||
</div>
|
||||
</div>
|
||||
<?php echo template::formClose(); ?>
|
||||
<?php echo template::table([3, 2, 2, 2, 2, 1, 1], user::$users, ['Nom', 'Groupe', 'Profil', 'Étiquettes', 'Date dernière vue', '', ''], ['id' => 'dataTables']); ?>
|
||||
<?php echo template::table([3, 2, 2, 1, 3, 1, 1], user::$users, ['Nom', 'Groupe', 'Profil', 'Étiquettes', 'Dernière connexion', '', ''], ['id' => 'dataTables'], ['name','group','profile','tag','data-timestamp','edit','delete']); ?>
|
4
core/vendor/datatables/datatables.min.js
vendored
4
core/vendor/datatables/datatables.min.js
vendored
File diff suppressed because one or more lines are too long
BIN
core/vendor/zwiico/png/error.png
vendored
Normal file
BIN
core/vendor/zwiico/png/error.png
vendored
Normal file
Binary file not shown.
After Width: | Height: | Size: 9.6 KiB |
Loading…
x
Reference in New Issue
Block a user