Compare commits
365 Commits
Author | SHA1 | Date | |
---|---|---|---|
13f7203054 | |||
ed3779b6a0 | |||
c157ae9f41 | |||
27ec459730 | |||
dcb1ee360d | |||
cdc5293580 | |||
dfdda38b1c | |||
9bf614fcc5 | |||
9dba1b8e79 | |||
124aeeeb98 | |||
7d8d0d7a18 | |||
ab89016836 | |||
f172eb4961 | |||
276950b117 | |||
0c8c9f89fd | |||
1debefc9ab | |||
b93e08e9a4 | |||
c13aa495f0 | |||
e6d044d0e1 | |||
e596f5eef6 | |||
db2b6bc518 | |||
130b88ace1 | |||
9df1fe8be2 | |||
0f71d820c5 | |||
a8891b310f | |||
59de6bc32f | |||
3a25c33e3a | |||
eff57bf0ab | |||
20c09d8b0a | |||
a634445dde | |||
4c88d7a71d | |||
bb9b8b086f | |||
61752a9a51 | |||
889e2754fc | |||
77b241c69f | |||
442b84a99d | |||
09f9f6bdd6 | |||
5eace20e26 | |||
18df3848f8 | |||
7b9d145533 | |||
75ad5853cf | |||
7862815f1f | |||
a87d439282 | |||
509c1d6365 | |||
e641ec1c03 | |||
3dec8a8ce5 | |||
54f0b0c6e3 | |||
931e59db2e | |||
cae0e6c8fb | |||
afee77b1e7 | |||
cf8963248e | |||
22af8ac751 | |||
2d4385f038 | |||
c4bb124bea | |||
a474a41402 | |||
e9f65a1e22 | |||
8183b0bb0b | |||
585c888007 | |||
d0997ccbf9 | |||
1a6bfab54b | |||
23f38a606f | |||
f1e1989c97 | |||
9bb5793720 | |||
64443322a0 | |||
76258c835f | |||
dc81614114 | |||
8dc1adc28a | |||
65eac4ac4a | |||
a8f70dc73a | |||
02aeb6ec22 | |||
5bdb38dfec | |||
5700200bc3 | |||
4ffca0e34a | |||
f4553110e1 | |||
bf3b1f9cb0 | |||
05d8ae9e0b | |||
6128d0778d | |||
c38bd7d12f | |||
cd509dfcb1 | |||
5ab8efe72e | |||
6cf6a8d6b2 | |||
daaf309b4d | |||
2d5c395aec | |||
5d5b1e3140 | |||
8aa24e50ab | |||
8574970bb0 | |||
89e6e12748 | |||
9234b76062 | |||
08c1619162 | |||
576f349b4a | |||
be6eaa748e | |||
1dc7b08d2e | |||
35521766cd | |||
c8ee063963 | |||
f0aba44ddb | |||
e6236e5de2 | |||
e5629de660 | |||
92d3da27a3 | |||
1fd0c5492f | |||
bab06033ed | |||
f7cf0f94fc | |||
c244651b62 | |||
beb58da3bd | |||
8756162428 | |||
511a6ff0bb | |||
4175ff828d | |||
087b5d9999 | |||
fea1c40a4b | |||
2dce24f9f2 | |||
0e0fd23913 | |||
0eab6c9049 | |||
ca7ce4e857 | |||
510afbe8f1 | |||
c89a64ca7f | |||
9280d59aac | |||
3accdc135b | |||
3d31ce5e55 | |||
8c60eba918 | |||
b182c2ec90 | |||
523f30027a | |||
f9faaa651e | |||
1aca92b1c7 | |||
4444c58902 | |||
75dbae7cc6 | |||
79e0ac2a38 | |||
1cb4b191bf | |||
485392e772 | |||
9c5f6448b1 | |||
b78e52c5d4 | |||
e687f26d2d | |||
769808ca4e | |||
5ba20aec09 | |||
5c0efda0ca | |||
b6d3eb8ec2 | |||
30df948d81 | |||
15430af1d6 | |||
2aae298d7d | |||
adeaeb624b | |||
d98e235dfc | |||
ef5de018b0 | |||
c024340af7 | |||
6a964938bc | |||
f024a960e4 | |||
c3ff13856b | |||
806e1cc14f | |||
a48cdf6690 | |||
df646488d6 | |||
1a36e233be | |||
b8c5d613bc | |||
60455ae036 | |||
893db4034d | |||
3d1d4be997 | |||
5f3bd590a8 | |||
cbffc3f44b | |||
8131162dae | |||
72655aec3d | |||
08ed4075c7 | |||
6d5ddf1f8d | |||
8b354ff40e | |||
5be3d0b1a7 | |||
f0c4ea6bd0 | |||
cbe06426bb | |||
adac7395cc | |||
2c459a03d4 | |||
751bc450b5 | |||
6c8d9097f6 | |||
b0814d50dc | |||
a7a2424d93 | |||
43b15987d6 | |||
e100a580ad | |||
397bdee655 | |||
78b2d87ec1 | |||
8dedb39a33 | |||
7cee16389f | |||
04b2877c48 | |||
f6c7e5f954 | |||
b5ea22021b | |||
3ee1398e2f | |||
cfb07b81d5 | |||
0da23149db | |||
1322cb4eb0 | |||
167ad06dde | |||
271ee347a8 | |||
04a6d86999 | |||
05e6ff8f9b | |||
6e53ca8766 | |||
dda93cf3d3 | |||
075e4afa1c | |||
fd144d55f0 | |||
b595120227 | |||
b0b3b34bde | |||
2f592e2818 | |||
8c9bc40a02 | |||
37f77b3d50 | |||
a5130e1d9f | |||
256da35d53 | |||
bb93b1b313 | |||
195ed682f6 | |||
ae71b9649d | |||
71418548e7 | |||
03c7e0a7fa | |||
6bc8636692 | |||
c0d14596a7 | |||
6a72676c7c | |||
44c4997436 | |||
cce73886a2 | |||
b9733d7391 | |||
56ff0580a1 | |||
5b9f86fb38 | |||
d43a78d307 | |||
deedb002e8 | |||
6d7c2f725d | |||
5ede9b71c2 | |||
04f4c7be6d | |||
0c94b2f546 | |||
8b72ae01dc | |||
1ca77b89ce | |||
0934bf847d | |||
2a152a9a1d | |||
bc8fbc17b8 | |||
a8635f0c8a | |||
ca875f9f05 | |||
b4258fe496 | |||
509c95a680 | |||
2027c5918f | |||
3593e853d8 | |||
cb13d2b0c9 | |||
0f55df8d31 | |||
939cb8d53f | |||
730e4ac9c4 | |||
d3d96f795a | |||
e68f58fad1 | |||
6c0f34ae71 | |||
9373880239 | |||
a35036e0fa | |||
19246a59c9 | |||
15c4d1edd3 | |||
24f679d531 | |||
56f8f03581 | |||
ae1f15e8b8 | |||
7544bb9862 | |||
ebd078848a | |||
e8e4f98be0 | |||
c8c74d9be3 | |||
63541cf83a | |||
1cb54d46b1 | |||
cf3936b7c0 | |||
84df59c52b | |||
c75b71f217 | |||
269abc5699 | |||
638ddadb61 | |||
10f8340e76 | |||
7c0feae8ee | |||
25889b0759 | |||
1e0cca8685 | |||
a02a796f4a | |||
e640aa327e | |||
ed34728f5e | |||
b6e4b39e78 | |||
64f19f0f96 | |||
b6fb2d75b4 | |||
7138c07a89 | |||
137c151e19 | |||
548daad047 | |||
c8abde012c | |||
caa348a571 | |||
8e1488b86f | |||
1d4f8405b1 | |||
0fece8c7ca | |||
0deec384bc | |||
7452faab55 | |||
e9ed55b065 | |||
d35010f100 | |||
14683133c8 | |||
4e174124fe | |||
64594e23ff | |||
7d5d6edf25 | |||
74fabce177 | |||
e64e819d48 | |||
2dd835593a | |||
9664ce49b7 | |||
3502d78632 | |||
65a121cb0a | |||
e6c52c29ee | |||
31994d33e0 | |||
cfb0d8a0e9 | |||
5a8fc68049 | |||
8988e2e130 | |||
724d391d00 | |||
78102b96b4 | |||
0535556b68 | |||
db0637ca1c | |||
6d42f792e4 | |||
dd194e2488 | |||
fc197b647d | |||
d2dc4c64c0 | |||
f65fe62da7 | |||
372db6dc3a | |||
fd5aabd910 | |||
36604a1ee4 | |||
4dfd73453e | |||
2eab0090d1 | |||
f74c7fd6f7 | |||
2bdb09b958 | |||
0407bd082d | |||
d42ce3c733 | |||
260098d0a5 | |||
52fb225650 | |||
b5693abbf5 | |||
a8f1387c96 | |||
083d819597 | |||
d829f57582 | |||
31986d138e | |||
3b77452bbe | |||
c6358b4c63 | |||
084471aa3b | |||
97a782eb4d | |||
3884573de9 | |||
572f0206a8 | |||
d3675f62f4 | |||
8e9c356188 | |||
3b5ddb5a3f | |||
91e4a4047c | |||
caf193611d | |||
ee4fc93afe | |||
3c76bcdf4c | |||
e9e39f5a03 | |||
b5382fa5f2 | |||
cd69635448 | |||
0c8569f7cf | |||
13227a5cd4 | |||
c43ce394e4 | |||
6c2c6a1acb | |||
656d6e557e | |||
9bf135337e | |||
6d77995439 | |||
9a3de92678 | |||
7b5f182be4 | |||
98f68f284c | |||
3ebb305cae | |||
e80564c106 | |||
e90929ea3b | |||
ac8d3016c7 | |||
ffb872fd03 | |||
08fb2d25fd | |||
63f7767460 | |||
17b76e1a0f | |||
a4164e4a2d | |||
595d068de2 | |||
cc92c90403 | |||
6da8223209 | |||
3bedbed4ef | |||
023ba99c0b | |||
b8123b0534 | |||
931b56f6a3 | |||
fcee5a8cde | |||
25d1c2400e | |||
48725b8703 | |||
9bea40ed08 | |||
01d6300d90 | |||
ac28fe496f | |||
ef371092a0 | |||
21afc43656 | |||
cd03316a9b | |||
7ce30078f6 |
1
.gitignore
vendored
1
.gitignore
vendored
@ -9,3 +9,4 @@ site/i18n/*.json
|
||||
core/vendor/tinymce/link_list.json
|
||||
robots.txt
|
||||
sitemap.xml
|
||||
core/module/config/tool/data.key
|
@ -32,5 +32,13 @@ Options -Indexes
|
||||
Options -MultiViews
|
||||
</IfModule>
|
||||
|
||||
# Enlever le slash final des URL
|
||||
RewriteCond %{REQUEST_FILENAME} !-f
|
||||
RewriteCond %{REQUEST_FILENAME} !-d
|
||||
RewriteCond %{REQUEST_URI} ^(.+)/$
|
||||
RewriteRule ^ %1 [R=301,L]
|
||||
|
||||
# ne pas supprimer la ligne URL rewriting !
|
||||
|
||||
# URL rewriting
|
||||
|
||||
|
15
README.md
15
README.md
@ -1,7 +1,17 @@
|
||||
# ZwiiCampus 1.4.20
|
||||
# ZwiiCampus 1.15.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é.
|
||||
|
||||
Ce logiciel s'installe en ligne ou localement depuis un serveur Web.
|
||||
|
||||
## Principales fonctionnalités :
|
||||
- Gestion des espaces d'enseignement : Créez des espaces de formation avec accès restreint.
|
||||
- Participation et suivi des apprenants : Inscription libre, imposée ou avec clé, et suivi statistique détaillé des participants.
|
||||
- Gestion des accès : Contrôlez la disponibilité des espaces (ouvert, limité dans le temps, fermé).
|
||||
- Outils statistiques : Visualisation et exportation CSV des progrès des apprenants.
|
||||
- Facilité d'installation : Pas besoin de base de données, tout fonctionne avec des fichiers JSON.
|
||||
- Sauvegarde et restauration : Outils de gestion pour réinitialiser les espaces et les participations.
|
||||
|
||||
|
||||
## Configuration recommandée
|
||||
|
||||
@ -68,6 +78,7 @@ A l'occasion de l'installation d'une version majeure, il est recommandé de réa
|
||||
[F] module.json Données des modules de pages
|
||||
[F] theme.css Thème de ce contenu
|
||||
[F] theme.json Thème de ce contenu
|
||||
[F] report.csv Rapport de participation
|
||||
[R] content Dossier des contenus de page
|
||||
[F] accueil.html Exemple contenu de la page d'accueil
|
||||
[R] fonts Dossier contenant les fontes installées
|
||||
@ -84,7 +95,7 @@ A l'occasion de l'installation d'une version majeure, il est recommandé de réa
|
||||
[F] core.json Configuration du noyau
|
||||
[F] course.json Données de contenus
|
||||
[F] custom.css Feuille de style de la personnalisation avancée
|
||||
[F] enrolment.json Données des inscriptions et des statistiques par contenu
|
||||
[F] enrolment.json Inscriptions dans les espaces, dernière page vue et timetamp
|
||||
[F] font.json Descripteur des fontes personnalisées
|
||||
[F] journal.log Journalisation des activités
|
||||
[F] language.json Langues de l'interface
|
||||
|
@ -8,7 +8,7 @@ class helper
|
||||
|
||||
/** Filtres personnalisés */
|
||||
const FILTER_BOOLEAN = 1;
|
||||
const FILTER_DATETIME = 2;
|
||||
const FILTER_DATETIME = 2; // filtre pour le champ de formulaire A conserver pour la compatibilité
|
||||
const FILTER_FLOAT = 3;
|
||||
const FILTER_ID = 4;
|
||||
const FILTER_INT = 5;
|
||||
@ -16,8 +16,14 @@ class helper
|
||||
const FILTER_PASSWORD = 7;
|
||||
const FILTER_STRING_LONG = 8;
|
||||
const FILTER_STRING_SHORT = 9;
|
||||
const FILTER_TIMESTAMP = 10;
|
||||
const FILTER_TIMESTAMP = 10; // Saisie d'une date en locatime
|
||||
const FILTER_URL = 11;
|
||||
const FILTER_DATE = 12; // filtre pour le champ de formulaire
|
||||
const FILTER_TIME = 13; // filtre pour le champ de formulair
|
||||
const FILTER_MONTH = 14; // filtre pour le champ de formulair
|
||||
const FILTER_YEAR = 16; // filtre pour le champ de formulair
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
@ -29,12 +35,12 @@ class helper
|
||||
|
||||
// La traduction existe déjà dans le core
|
||||
/*
|
||||
if (array_key_exists($text, core::$dialog) === false && !empty($text)) {
|
||||
$dialogues = json_decode(file_get_contents('core/module/install/ressource/i18n/fr_FR.json' ), true);
|
||||
$data = array_merge($dialogues,[$text => '']);
|
||||
file_put_contents ('core/module/install/ressource/i18n/fr_FR.json', json_encode($data, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES | JSON_PRETTY_PRINT), LOCK_EX);
|
||||
}
|
||||
*/
|
||||
if (array_key_exists($text, core::$dialog) === false && !empty($text)) {
|
||||
$dialogues = json_decode(file_get_contents('core/module/install/ressource/i18n/fr_FR.json' ), true);
|
||||
$data = array_merge($dialogues,[$text => '']);
|
||||
file_put_contents ('core/module/install/ressource/i18n/fr_FR.json', json_encode($data, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES | JSON_PRETTY_PRINT), LOCK_EX);
|
||||
}
|
||||
*/
|
||||
return (array_key_exists($text, core::$dialog) && !empty(core::$dialog[$text]) ? core::$dialog[$text] : $text);
|
||||
}
|
||||
|
||||
@ -77,7 +83,7 @@ class helper
|
||||
// Créer la variable
|
||||
$data = array_merge($data, [$text => '']);
|
||||
}
|
||||
file_put_contents('site/i18n/' . $to . '.json', json_encode($data, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES | JSON_PRETTY_PRINT), LOCK_EX);
|
||||
file_put_contents('site/i18n/' . $to . '.json', json_encode($data, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES | JSON_PRETTY_PRINT));
|
||||
|
||||
}
|
||||
}
|
||||
@ -191,14 +197,20 @@ class helper
|
||||
|
||||
public static function autoBackup($folder, $filter = ['backup', 'tmp'])
|
||||
{
|
||||
// Creation du ZIP
|
||||
// Création du nom de fichier ZIP
|
||||
$baseName = str_replace('/', '', helper::baseUrl(false, false));
|
||||
$baseName = empty($baseName) ? 'ZwiiCMS' : $baseName;
|
||||
$fileName = $baseName . '-backup-' . date('Y-m-d-H-i-s', time()) . '.zip';
|
||||
$fileName = $baseName . '-backup-' . date('Y-m-d-H-i-s') . '.zip';
|
||||
|
||||
// Initialisation de l'archive ZIP
|
||||
$zip = new ZipArchive();
|
||||
$zip->open($folder . $fileName, ZipArchive::CREATE | ZipArchive::OVERWRITE);
|
||||
if ($zip->open($folder . $fileName, ZipArchive::CREATE | ZipArchive::OVERWRITE) !== true) {
|
||||
return false; // Retourne false si l'ouverture échoue
|
||||
}
|
||||
|
||||
$directory = 'site/';
|
||||
//$filter = array('backup','tmp','file');
|
||||
|
||||
// Récupération des fichiers et des dossiers
|
||||
$files = new RecursiveIteratorIterator(
|
||||
new RecursiveCallbackFilterIterator(
|
||||
new RecursiveDirectoryIterator(
|
||||
@ -206,21 +218,26 @@ class helper
|
||||
RecursiveDirectoryIterator::SKIP_DOTS
|
||||
),
|
||||
function ($fileInfo, $key, $iterator) use ($filter) {
|
||||
return $fileInfo->isFile() || !in_array($fileInfo->getBaseName(), $filter);
|
||||
// Inclure les fichiers ou les répertoires non filtrés
|
||||
return $fileInfo->isFile() || ($fileInfo->isDir() && !in_array($fileInfo->getBaseName(), $filter));
|
||||
}
|
||||
)
|
||||
);
|
||||
foreach ($files as $name => $file) {
|
||||
|
||||
// Ajout des fichiers à l'archive
|
||||
foreach ($files as $file) {
|
||||
if (!$file->isDir()) {
|
||||
$filePath = $file->getRealPath();
|
||||
$relativePath = substr($filePath, strlen(realpath($directory)) + 1);
|
||||
$relativePath = str_replace(DIRECTORY_SEPARATOR, '/', substr($filePath, strlen(realpath($directory)) + 1));
|
||||
$zip->addFile($filePath, $relativePath);
|
||||
}
|
||||
}
|
||||
$zip->close();
|
||||
return ($fileName);
|
||||
}
|
||||
|
||||
// Fermeture de l'archive ZIP
|
||||
$zip->close();
|
||||
|
||||
return $fileName;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
@ -337,18 +354,25 @@ class helper
|
||||
public static function checkRewrite()
|
||||
{
|
||||
// N'interroge que le serveur Apache
|
||||
if (strpos($_SERVER["SERVER_SOFTWARE"], 'Apache') > 0) {
|
||||
self::$rewriteStatus === false;
|
||||
} elseif (self::$rewriteStatus === null) {
|
||||
if ((helper::checkServerSoftware() === false)) {
|
||||
self::$rewriteStatus = false;
|
||||
} else {
|
||||
// Ouvre et scinde le fichier .htaccess
|
||||
$htaccess = explode('# URL rewriting', file_get_contents('.htaccess'));
|
||||
// Retourne un boolean en fonction du contenu de la partie réservée à l'URL rewriting
|
||||
//self::$rewriteStatus = (empty($htaccess[1]) === false);
|
||||
self::$rewriteStatus = (strpos($htaccess[1], 'RewriteEngine on') > 0) ? true : false;
|
||||
self::$rewriteStatus = (strpos($htaccess[1], 'RewriteEngine on') !== false);
|
||||
}
|
||||
return self::$rewriteStatus;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retourne vrai ou faux selon que le serveur est comptatible avec htaccess
|
||||
* @return bool
|
||||
*/
|
||||
public static function checkServerSoftware() {
|
||||
return (stripos($_SERVER['SERVER_SOFTWARE'], 'Apache') !== false || stripos($_SERVER['SERVER_SOFTWARE'], 'LiteSpeed') !== false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Renvoie le numéro de version de Zwii est en ligne
|
||||
* @return string
|
||||
@ -374,7 +398,6 @@ class helper
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Génère des variations d'une couleur
|
||||
* @param string $rgba Code rgba de la couleur
|
||||
@ -391,10 +414,10 @@ class helper
|
||||
'text' => self::relativeLuminanceW3C($rgba) > .22 ? "#222" : "#DDD",
|
||||
'rgb' => 'rgb(' . $rgba[0] . ',' . $rgba[1] . ',' . $rgba[2] . ')',
|
||||
'invert' => 'rgba (' .
|
||||
($rgba[0] < 128 ? 255 : 0) . ',' .
|
||||
($rgba[1] < 128 ? 255 : 0) . ',' .
|
||||
($rgba[1] < 128 ? 255 : 0) . ',' .
|
||||
($rgba[0] < 128 ? 255 : 0) . ')'
|
||||
($rgba[0] < 128 ? 255 : 0) . ',' .
|
||||
($rgba[1] < 128 ? 255 : 0) . ',' .
|
||||
($rgba[1] < 128 ? 255 : 0) . ',' .
|
||||
($rgba[0] < 128 ? 255 : 0) . ')'
|
||||
];
|
||||
}
|
||||
|
||||
@ -404,8 +427,8 @@ class helper
|
||||
*/
|
||||
public static function deleteCookie($cookieKey)
|
||||
{
|
||||
unset($_COOKIE[$cookieKey]);
|
||||
setcookie($cookieKey, '', time() - 3600, helper::baseUrl(false, false), '', false, true);
|
||||
unset($_COOKIE[$cookieKey]);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -428,7 +451,8 @@ class helper
|
||||
$text = (int) $date->format('U');
|
||||
break;
|
||||
case self::FILTER_FLOAT:
|
||||
$text = filter_var($text, FILTER_SANITIZE_NUMBER_FLOAT);
|
||||
$text = str_replace(',', '.', $text); // Remplacer les virgules par des points
|
||||
$text = filter_var($text, FILTER_SANITIZE_NUMBER_FLOAT, FILTER_FLAG_ALLOW_FRACTION);
|
||||
$text = (float) $text;
|
||||
break;
|
||||
case self::FILTER_ID:
|
||||
@ -475,6 +499,11 @@ class helper
|
||||
case self::FILTER_URL:
|
||||
$text = filter_var($text, FILTER_SANITIZE_URL);
|
||||
break;
|
||||
case self::FILTER_DATE:
|
||||
$text = date('Y-m-d', $text);
|
||||
break;
|
||||
case self::FILTER_TIME:
|
||||
$text = date('H:i', $text);
|
||||
}
|
||||
return $text;
|
||||
}
|
||||
@ -663,10 +692,30 @@ class helper
|
||||
public static function subword($text, $start, $length)
|
||||
{
|
||||
$text = trim($text);
|
||||
if (strlen($text) > $length) {
|
||||
|
||||
// Vérifier si la longueur du texte sans les balises dépasse la longueur souhaitée
|
||||
if (mb_strlen(strip_tags($text)) > $length) {
|
||||
// Utiliser mb_substr pour couper le texte
|
||||
$text = mb_substr($text, $start, $length);
|
||||
$text = mb_substr($text, 0, min(mb_strlen($text), mb_strrpos($text, ' ')));
|
||||
|
||||
// S'assurer que le texte ne se termine pas au milieu d'un mot
|
||||
$lastSpace = mb_strrpos($text, ' ');
|
||||
if ($lastSpace !== false) {
|
||||
$text = mb_substr($text, 0, $lastSpace);
|
||||
}
|
||||
|
||||
// Fermer les balises HTML ouvertes
|
||||
$dom = new DOMDocument();
|
||||
@$dom->loadHTML('<div>' . $text . '</div>', LIBXML_HTML_NOIMPLIED | LIBXML_HTML_NODEFDTD);
|
||||
$text = $dom->saveHTML();
|
||||
|
||||
// Retirer la balise de conteneur ajoutée
|
||||
$text = preg_replace('~^<div>(.*)</div>$~s', '$1', $text);
|
||||
|
||||
// Ajouter des points de suspension si le texte a été coupé
|
||||
$text .= '...';
|
||||
}
|
||||
|
||||
return $text;
|
||||
}
|
||||
|
||||
|
@ -101,7 +101,7 @@ class Dot implements \ArrayAccess, \Iterator, \Countable
|
||||
}
|
||||
} else {
|
||||
// Iterate path
|
||||
$keys = explode('.', (string)$key);
|
||||
$keys = explode('.', (string) $key);
|
||||
if ($pop === true) {
|
||||
array_pop($keys);
|
||||
}
|
||||
@ -141,7 +141,7 @@ class Dot implements \ArrayAccess, \Iterator, \Countable
|
||||
} elseif (is_array($key)) {
|
||||
// Iterate array of paths
|
||||
foreach ($key as $k) {
|
||||
self::delete($k);
|
||||
self::deleteValue($array, $k);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -199,7 +199,7 @@ class Dot implements \ArrayAccess, \Iterator, \Countable
|
||||
*/
|
||||
public function has($key)
|
||||
{
|
||||
$keys = explode('.', (string)$key);
|
||||
$keys = explode('.', (string) $key);
|
||||
$data = &$this->data;
|
||||
foreach ($keys as $key) {
|
||||
if (!isset($data[$key])) {
|
||||
@ -371,7 +371,7 @@ class Dot implements \ArrayAccess, \Iterator, \Countable
|
||||
*/
|
||||
public function isEmpty(): bool
|
||||
{
|
||||
return !(bool)count($this->data);
|
||||
return !(bool) count($this->data);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -391,7 +391,7 @@ class Dot implements \ArrayAccess, \Iterator, \Countable
|
||||
*/
|
||||
public function toJson()
|
||||
{
|
||||
return json_encode($this->data, JSON_UNESCAPED_UNICODE|JSON_PRETTY_PRINT);
|
||||
return json_encode($this->data, JSON_UNESCAPED_UNICODE | JSON_PRETTY_PRINT);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -121,17 +121,17 @@ class JsonDb extends \Prowebcraft\Dot
|
||||
} else {
|
||||
if ($this->config['backup']) {
|
||||
try {
|
||||
//todo make backup of database
|
||||
copy($this->config['dir'] . DIRECTORY_SEPARATOR . $this->config['name'], $this->config['dir'] . DIRECTORY_SEPARATOR . $this->config['name'] . '.backup');
|
||||
} catch (\Exception $e) {
|
||||
|
||||
error_log('Erreur de chargement : ' . $e);
|
||||
exit('Erreur de chargement : ' . $e);
|
||||
}
|
||||
}
|
||||
}
|
||||
$this->data = json_decode(file_get_contents($this->db), true);
|
||||
if (!$this->data === null) {
|
||||
throw new \InvalidArgumentException('Database file ' . $this->db
|
||||
. ' contains invalid json object. Please validate or remove file');
|
||||
if (!$this->data === null && json_last_error() !== JSON_ERROR_NONE) {
|
||||
throw new \InvalidArgumentException('Le fichier ' . $this->db
|
||||
. ' contient des données invalides.');
|
||||
}
|
||||
}
|
||||
return $this->data;
|
||||
@ -142,20 +142,38 @@ class JsonDb extends \Prowebcraft\Dot
|
||||
*/
|
||||
public function save()
|
||||
{
|
||||
//$v = json_encode($this->data, JSON_UNESCAPED_UNICODE );
|
||||
$v = json_encode($this->data, JSON_UNESCAPED_UNICODE | JSON_FORCE_OBJECT);
|
||||
$l = strlen($v);
|
||||
$t = 0;
|
||||
while ($t < 5) {
|
||||
$w = file_put_contents($this->db, $v); // Multi user get a locker
|
||||
if ($w == $l) {
|
||||
// Encode les données au format JSON avec les options spécifiées
|
||||
$encoded_data = json_encode($this->data, JSON_UNESCAPED_UNICODE | JSON_FORCE_OBJECT);
|
||||
|
||||
// Vérifie la longueur de la chaîne JSON encodée
|
||||
$encoded_length = strlen($encoded_data);
|
||||
|
||||
// Initialise le compteur de tentatives
|
||||
$attempt = 0;
|
||||
|
||||
// Tente d'encoder les données en JSON et de les sauvegarder jusqu'à 5 fois en cas d'échec
|
||||
while ($attempt < 5) {
|
||||
// Essaye d'écrire les données encodées dans le fichier de base de données
|
||||
$write_result = file_put_contents($this->db, $encoded_data, LOCK_EX); // Les utilisateurs multiples obtiennent un verrou
|
||||
|
||||
// $now = \DateTime::createFromFormat('U.u', microtime(true));
|
||||
// file_put_contents("tmplog.txt", '[JsonDb][' . $now->format('H:i:s.u') . ']--' . $this->db . "\r\n", FILE_APPEND);
|
||||
|
||||
// Vérifie si l'écriture a réussi
|
||||
if ($write_result === $encoded_length) {
|
||||
// Sort de la boucle si l'écriture a réussi
|
||||
break;
|
||||
}
|
||||
$t++;
|
||||
// Incrémente le compteur de tentatives
|
||||
$attempt++;
|
||||
}
|
||||
if ($w !== $l) {
|
||||
exit('Erreur d\'écriture, les données n\'ont pas été sauvegardées');
|
||||
// Vérifie si l'écriture a échoué même après plusieurs tentatives
|
||||
if ($write_result !== $encoded_length) {
|
||||
// Enregistre un message d'erreur dans le journal des erreurs
|
||||
error_log('Erreur d\'écriture, les données n\'ont pas été sauvegardées.');
|
||||
// Affiche un message d'erreur et termine le script
|
||||
exit('Erreur d\'écriture, les données n\'ont pas été sauvegardées.');
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
@ -82,17 +82,25 @@ class layout extends common
|
||||
$content = 'col' . $blocks[1];
|
||||
$blockright = 'col' . $blocks[2];
|
||||
}
|
||||
// Page pleine pour la configuration des modules et l'édition des pages sauf l'affichage d'un article de blog
|
||||
$pattern = ['config', 'edit', 'add', 'comment', 'data'];
|
||||
// Toujours en pleine page pour la configuration des modules et l'édition des pages sauf l'affichage d'un article de blog
|
||||
$pattern = ['config', 'edit', 'add', 'comment', 'data', 'option', 'theme', 'comment', 'article', 'data', 'gallery', 'update', 'users', 'validate'];
|
||||
if (
|
||||
(sizeof($blocks) === 1 ||
|
||||
in_array($this->getUrl(1), $pattern))
|
||||
) { // Pleine page en mode configuration
|
||||
if ($this->getData(['page', $this->getUrl(0), 'navLeft']) === 'top' || $this->getData(['page', $this->getUrl(0), 'navRight']) === 'top') {
|
||||
if (
|
||||
($this->getData(['page', $this->getUrl(0), 'navLeft']) === 'top'
|
||||
|| $this->getData(['page', $this->getUrl(0), 'navRight']) === 'top')
|
||||
&& in_array($this->getUrl(1), $pattern) === false
|
||||
) {
|
||||
$this->showNavButtons('top');
|
||||
}
|
||||
$this->showContent();
|
||||
if ($this->getData(['page', $this->getUrl(0), 'navLeft']) === 'bottom' || $this->getData(['page', $this->getUrl(0), 'navRight']) === 'bottom') {
|
||||
if (
|
||||
($this->getData(['page', $this->getUrl(0), 'navLeft']) === 'bottom'
|
||||
|| $this->getData(['page', $this->getUrl(0), 'navRight']) === 'bottom')
|
||||
&& in_array($this->getUrl(1), $pattern) === false
|
||||
) {
|
||||
$this->showNavButtons('bottom');
|
||||
}
|
||||
} else {
|
||||
@ -151,7 +159,7 @@ class layout extends common
|
||||
}
|
||||
echo '</div>';
|
||||
}
|
||||
echo '</main></section>';
|
||||
echo '</section></main>';
|
||||
}
|
||||
|
||||
/**
|
||||
@ -330,7 +338,7 @@ class layout extends common
|
||||
// Affichage du lien de connexion
|
||||
if (
|
||||
($this->getData(['theme', 'footer', 'loginLink'])
|
||||
and $this->getUser('password') !== $this->getInput('ZWII_USER_PASSWORD')
|
||||
and $this->isConnected() === false
|
||||
)
|
||||
or $this->getUrl(0) === 'theme'
|
||||
) {
|
||||
@ -353,9 +361,11 @@ class layout extends common
|
||||
$items .= '<wbr> | ';
|
||||
if (
|
||||
$this->getUser('permission', 'filemanager') === true
|
||||
&& $this->getUser('permission', 'folder', (self::$siteContent === 'home' ? 'homePath' : 'coursePath')) !== 'none'
|
||||
) {
|
||||
$folder = '&fldr=/' . (self::$siteContent === 'home' ? '' : self::$siteContent);
|
||||
$items .= '<wbr>' . template::ico('folder', [
|
||||
'href' => helper::baseUrl(false) . 'core/vendor/filemanager/dialog.php?type=0&akey=' . md5_file(self::DATA_DIR . 'core.json') . '&lang=' . $this->getData(['user', $this->getUser('id'), 'language']),
|
||||
'href' => helper::baseUrl(false) . 'core/vendor/filemanager/dialog.php?type=0&akey=' . md5_file(self::DATA_DIR . 'core.json') . '&lang=' . $this->getData(['user', $this->getUser('id'), 'language']) . $folder,
|
||||
'margin' => 'all',
|
||||
'attr' => 'data-lity',
|
||||
'help' => 'Fichiers du site'
|
||||
@ -499,10 +509,10 @@ class layout extends common
|
||||
$this->getUser('group') === self::GROUP_MEMBER
|
||||
&& $this->getData(['theme', 'menu', 'selectSpace']) === true
|
||||
) {
|
||||
if ($this->getCoursesByUser()) {
|
||||
if ($this->getCoursesByProfil()) {
|
||||
$itemsRight .= '<li><select id="menuSelectCourse" >';
|
||||
$itemsRight .= '<option name="' . helper::translate('Accueil') . '" value="' . helper::baseUrl(true) . 'course/swap/home" ' . ('home' === self::$siteContent ? 'selected' : '') . '>' . helper::translate('Accueil') . '</option>';
|
||||
foreach ($this->getCoursesByUser() as $courseId => $value) {
|
||||
foreach ($this->getCoursesByProfil() as $courseId => $value) {
|
||||
$itemsRight .= '<option name="' . $this->getData(['course', $courseId, 'title']) . '" value="' . helper::baseUrl(true) . 'course/swap/' . $courseId . '" ' . ($courseId === self::$siteContent ? 'selected' : '') . '>' . $this->getData(['course', $courseId, 'title']) . '</option>';
|
||||
}
|
||||
$itemsRight .= '</select></li>';
|
||||
@ -519,9 +529,13 @@ class layout extends common
|
||||
) {
|
||||
|
||||
// Affiche l'icône RFM
|
||||
if ($this->getUser('permission', 'filemanager') === true) {
|
||||
if (
|
||||
$this->getUser('permission', 'filemanager') === true
|
||||
&& $this->getUser('permission', 'folder', (self::$siteContent === 'home' ? 'homePath' : 'coursePath')) !== 'none'
|
||||
) {
|
||||
$folder = '&fldr=/' . (self::$siteContent === 'home' ? '' : self::$siteContent);
|
||||
$itemsRight .= '<li>' . template::ico('folder', [
|
||||
'href' => helper::baseUrl(false) . 'core/vendor/filemanager/dialog.php?type=0&akey=' . md5_file(self::DATA_DIR . 'core.json') . '&lang=' . $this->getData(['user', $this->getUser('id'), 'language']),
|
||||
'href' => helper::baseUrl(false) . 'core/vendor/filemanager/dialog.php?type=0&akey=' . md5_file(self::DATA_DIR . 'core.json') . '&lang=' . $this->getData(['user', $this->getUser('id'), 'language']) . $folder,
|
||||
'attr' => 'data-lity',
|
||||
'help' => 'Fichiers du site'
|
||||
]) . '</li>';
|
||||
@ -545,7 +559,7 @@ class layout extends common
|
||||
// Lien de connexion
|
||||
if (
|
||||
($this->getData(['theme', 'menu', 'loginLink'])
|
||||
and $this->getUser('password') !== $this->getInput('ZWII_USER_PASSWORD')
|
||||
and $this->isConnected() === false
|
||||
)
|
||||
or $this->getUrl(0) === 'theme'
|
||||
) {
|
||||
@ -590,9 +604,9 @@ class layout extends common
|
||||
|
||||
if (
|
||||
($this->getData(['page', $parentPageId, 'disable']) === true
|
||||
and $this->getUser('password') !== $this->getInput('ZWII_USER_PASSWORD')
|
||||
and $this->isConnected() === false
|
||||
) or ($this->getData(['page', $parentPageId, 'disable']) === true
|
||||
and $this->getUser('password') === $this->getInput('ZWII_USER_PASSWORD')
|
||||
and $this->isConnected() === true
|
||||
and $this->getUser('group') < self::GROUP_EDITOR
|
||||
)
|
||||
) {
|
||||
@ -656,9 +670,9 @@ class layout extends common
|
||||
$items .= '<li id=' . $childKey . '>';
|
||||
if (
|
||||
($this->getData(['page', $childKey, 'disable']) === true
|
||||
and $this->getUser('password') !== $this->getInput('ZWII_USER_PASSWORD')
|
||||
and $this->isConnected() === false
|
||||
) or ($this->getData(['page', $childKey, 'disable']) === true
|
||||
and $this->getUser('password') === $this->getInput('ZWII_USER_PASSWORD')
|
||||
and $this->isConnected() === true
|
||||
and $this->getUser('group') < self::GROUP_EDITOR
|
||||
)
|
||||
) {
|
||||
@ -752,7 +766,7 @@ class layout extends common
|
||||
$items .= '<li class="menuSideChild">';
|
||||
if (
|
||||
$this->getData(['page', $parentPageId, 'disable']) === true
|
||||
and $this->getUser('password') !== $this->getInput('ZWII_USER_PASSWORD')
|
||||
and $this->isConnected() === false
|
||||
) {
|
||||
$items .= '<a href="' . $this->getUrl(1) . '">';
|
||||
} else {
|
||||
@ -776,7 +790,7 @@ class layout extends common
|
||||
|
||||
if (
|
||||
$this->getData(['page', $childKey, 'disable']) === true
|
||||
and $this->getUser('password') !== $this->getInput('ZWII_USER_PASSWORD')
|
||||
and $this->isConnected() === false
|
||||
) {
|
||||
$itemsChildren .= '<a href="' . $this->getUrl(1) . '">';
|
||||
} else {
|
||||
@ -912,26 +926,27 @@ class layout extends common
|
||||
*/
|
||||
public function showBar()
|
||||
{
|
||||
if ($this->getUser('password') === $this->getInput('ZWII_USER_PASSWORD')) {
|
||||
if ($this->isConnected() === true) {
|
||||
// Items de gauche
|
||||
$leftItems = '';
|
||||
// Sélecteur de contenu
|
||||
/**
|
||||
* Les admins voient tousles contenus
|
||||
* Les admins voient tous les contenus
|
||||
* Les enseignants les contenus dont ils sont auteurs
|
||||
*/
|
||||
if ($this->getUser('group') >= self::GROUP_EDITOR) {
|
||||
if ($this->getCoursesByUser()) {
|
||||
if (is_array($this->getCoursesByProfil())) {
|
||||
$leftItems .= '<li><select id="barSelectCourse" >';
|
||||
$leftItems .= '<option name="' . helper::translate('Accueil') . '" value="' . helper::baseUrl(true) . 'course/swap/home" ' . ('home' === self::$siteContent ? 'selected' : '') . '>' . helper::translate('Accueil') . '</option>';
|
||||
foreach ($this->getCoursesByUser() as $courseId => $value) {
|
||||
foreach ($this->getCoursesByProfil() as $courseId => $value) {
|
||||
$leftItems .= '<option name="' . $this->getData(['course', $courseId, 'title']) . '" value="' . helper::baseUrl(true) . 'course/swap/' . $courseId . '" ' . ($courseId === self::$siteContent ? 'selected' : '') . '>' . $this->getData(['course', $courseId, 'title']) . '</option>';
|
||||
}
|
||||
$leftItems .= '</select></li>';
|
||||
}
|
||||
|
||||
$leftItems .= '<li>' . template::ico('cubes', [
|
||||
'href' => helper::baseUrl() . 'course',
|
||||
'help' => 'Espaces'
|
||||
'help' => 'Gérer les espaces'
|
||||
]) . '</li>';
|
||||
}
|
||||
if ($this->getUser('group') >= self::GROUP_ADMIN) {
|
||||
@ -940,8 +955,11 @@ class layout extends common
|
||||
'href' => helper::baseUrl() . 'theme'
|
||||
]) . '</li>';
|
||||
}
|
||||
// Liste des pages
|
||||
if ($this->getUser('group') >= self::GROUP_EDITOR) {
|
||||
// Liste des pages et bouton de gestion interdit pour l'accueil sauf admin
|
||||
if (
|
||||
($this->getUser('group') === self::GROUP_EDITOR && self::$siteContent != 'home')
|
||||
|| $this->getUser('group') === self::GROUP_ADMIN
|
||||
) {
|
||||
$leftItems .= '<li><select id="barSelectPage">';
|
||||
$leftItems .= '<option value="">' . helper::translate('Pages du site') . '</option>';
|
||||
$leftItems .= '<optgroup label="' . helper::translate('Pages orphelines') . '">';
|
||||
@ -995,7 +1013,7 @@ class layout extends common
|
||||
// Bouton Ajouter une page
|
||||
if ($this->getUser('permission', 'page', 'add')) {
|
||||
$leftItems .= '<li>' . template::ico('plus', [
|
||||
'href' => helper::baseUrl() . 'page/add',
|
||||
'href' => helper::baseUrl() . 'page/add/' . self::$siteContent,
|
||||
'help' => 'Nouvelle page ou barre latérale'
|
||||
]) . '</li>';
|
||||
}
|
||||
@ -1012,16 +1030,20 @@ class layout extends common
|
||||
or $this->getUrl(0) === ''
|
||||
) {
|
||||
// Bouton Editer une page
|
||||
if ($this->getUser('permission', 'page', 'edit')) {
|
||||
if (
|
||||
$this->getUser('permission', 'page', 'edit')
|
||||
and $this->geturl(1) !== 'edit'
|
||||
) {
|
||||
$leftItems .= '<li>' . template::ico('pencil', [
|
||||
'href' => helper::baseUrl() . 'page/edit/' . $this->getUrl(0),
|
||||
'href' => helper::baseUrl() . 'page/edit/' . $this->getUrl(0) . '/' . self::$siteContent,
|
||||
'help' => 'Éditer la page'
|
||||
]) . '</li>';
|
||||
}
|
||||
// Bouton Editer le module d'une page
|
||||
if (
|
||||
$this->getUser('permission', 'page', 'module')
|
||||
&& $this->getData(['page', $this->getUrl(0), 'moduleId'])
|
||||
and $this->geturl(1) !== 'edit'
|
||||
and $this->getData(['page', $this->getUrl(0), 'moduleId'])
|
||||
) {
|
||||
$leftItems .= '<li>' . template::ico('gear', [
|
||||
'href' => helper::baseUrl() . $this->getUrl(0) . '/config',
|
||||
@ -1031,9 +1053,10 @@ class layout extends common
|
||||
// Bouton dupliquer une page
|
||||
if (
|
||||
$this->getUser('permission', 'page', 'duplicate')
|
||||
and $this->geturl(1) !== 'edit'
|
||||
) {
|
||||
$leftItems .= '<li>' . template::ico('clone', [
|
||||
'href' => helper::baseUrl() . 'page/duplicate/' . $this->getUrl(0),
|
||||
'href' => helper::baseUrl() . 'page/duplicate/' . $this->getUrl(0) . '/' . self::$siteContent,
|
||||
'help' => 'Dupliquer la page'
|
||||
])
|
||||
. '</li>';
|
||||
@ -1041,9 +1064,11 @@ class layout extends common
|
||||
// Bouton Effacer une page
|
||||
if (
|
||||
$this->getUser('permission', 'page', 'delete')
|
||||
and $this->geturl(1) !== 'edit'
|
||||
|
||||
) {
|
||||
$leftItems .= '<li>' . template::ico('trash', [
|
||||
'href' => helper::baseUrl() . 'page/delete/' . $this->getUrl(0),
|
||||
'href' => helper::baseUrl() . 'page/delete/' . $this->getUrl(0) . '/' . self::$siteContent,
|
||||
'help' => 'Supprimer la page',
|
||||
'id' => 'pageDelete'
|
||||
])
|
||||
@ -1055,18 +1080,16 @@ class layout extends common
|
||||
$rightItems = '';
|
||||
if (
|
||||
(
|
||||
// ZwiiCampus ------
|
||||
self::$siteContent !== 'home'
|
||||
// ZwiiCampus ------
|
||||
&& $this->getUser('group') >= self::GROUP_MEMBER
|
||||
&& $this->getUser('permission', 'filemanager')
|
||||
|
||||
$this->getUser('group') === self::GROUP_EDITOR
|
||||
&& $this->getUser('permission', 'filemanager') === true
|
||||
&& $this->getUser('permission', 'folder', (self::$siteContent === 'home' ? 'homePath' : 'coursePath')) !== 'none'
|
||||
)
|
||||
|| $this->getUser('group') == self::GROUP_ADMIN
|
||||
|| $this->getUser('group') === self::GROUP_ADMIN
|
||||
) {
|
||||
$folder = '&fldr=/' . (self::$siteContent === 'home' ? '' : self::$siteContent);
|
||||
$rightItems .= '<li>' . template::ico('folder', [
|
||||
'help' => 'Fichiers',
|
||||
'href' => helper::baseUrl(false) . 'core/vendor/filemanager/dialog.php?type=0&akey=' . md5_file(self::DATA_DIR . 'core.json') . '&lang=' . $this->getData(['user', $this->getUser('id'), 'language']),
|
||||
'href' => helper::baseUrl(false) . 'core/vendor/filemanager/dialog.php?type=0&akey=' . md5_file(self::DATA_DIR . 'core.json') . '&lang=' . $this->getData(['user', $this->getUser('id'), 'language']) . $folder,
|
||||
'attr' => 'data-lity'
|
||||
]) . '</li>';
|
||||
}
|
||||
@ -1074,22 +1097,18 @@ class layout extends common
|
||||
self::$siteContent === 'home'
|
||||
&& $this->getUser('group') >= self::GROUP_ADMIN
|
||||
) {
|
||||
$rightItems .= '<li>' . template::ico('puzzle', [
|
||||
'help' => 'Modules',
|
||||
'href' => helper::baseUrl() . 'plugin'
|
||||
]) . '</li>';
|
||||
$rightItems .= '<li>' . template::ico('flag', [
|
||||
'help' => 'Langues',
|
||||
'href' => helper::baseUrl() . 'language'
|
||||
]) . '</li>';
|
||||
$rightItems .= '<li>' . template::ico('cog-alt', [
|
||||
'help' => 'Configuration',
|
||||
'href' => helper::baseUrl() . 'config'
|
||||
]) . '</li>';
|
||||
$rightItems .= '<li>' . template::ico('users', [
|
||||
'help' => 'Utilisateurs',
|
||||
'href' => helper::baseUrl() . 'user'
|
||||
]) . '</li>';
|
||||
$rightItems .= '<li>' . template::ico('cog-alt', [
|
||||
'help' => 'Configuration',
|
||||
'href' => helper::baseUrl() . 'config'
|
||||
]) . '</li>';
|
||||
// Mise à jour automatique
|
||||
$today = mktime(0, 0, 0);
|
||||
$checkUpdate = $this->getData(['core', 'lastAutoUpdate']);
|
||||
@ -1101,21 +1120,54 @@ class layout extends common
|
||||
$today > $checkUpdate + $this->getData(['config', 'autoUpdateDelay', 86400])
|
||||
) {
|
||||
// Dernier auto controle
|
||||
$this->setData(['core', 'lastAutoUpdate', $today]);
|
||||
$this->setData(['core', 'lastAutoUpdate', $today], false);
|
||||
if (
|
||||
helper::checkNewVersion(common::ZWII_UPDATE_CHANNEL)
|
||||
) {
|
||||
$this->setData(['core', 'updateAvailable', true]);
|
||||
$this->setData(['core', 'updateAvailable', true], false);
|
||||
}
|
||||
// Modules installés
|
||||
$infoModules = helper::getModules();
|
||||
// Recherche de mise à jour des modules
|
||||
$store = plugin::getStore();
|
||||
if (is_array($store)) {
|
||||
// Parcourir les données des modules du store
|
||||
foreach ($store as $key => $value) {
|
||||
if (empty($key)) {
|
||||
continue;
|
||||
}
|
||||
// Mise à jour d'un module
|
||||
// Le module est installé et une mise à jour est en ligne
|
||||
if (
|
||||
isset($infoModules[$key])
|
||||
&&
|
||||
version_compare($infoModules[$key]['version'], $value['version'], '<')
|
||||
) {
|
||||
$this->setData(['core', 'updateModuleAvailable', true], false);
|
||||
}
|
||||
}
|
||||
}
|
||||
// Sauvegarde la base manuellement
|
||||
$this->saveDB('core');
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Afficher le bouton : Mise à jour détectée + activée
|
||||
if ($this->getData(['core', 'updateAvailable'])) {
|
||||
$rightItems .= '<li><a href="' . helper::baseUrl() . 'install/update" data-tippy-content="Mettre à jour Zwii ' . common::ZWII_VERSION . ' vers ' . helper::getOnlineVersion(common::ZWII_UPDATE_CHANNEL) . '">' . template::ico('update colorRed') . '</a></li>';
|
||||
}
|
||||
}
|
||||
if ($this->getData(['core', 'updateModuleAvailable'])) {
|
||||
$rightItems .= '<li>' . template::ico('puzzle colorRed', [
|
||||
'help' => 'Modules',
|
||||
'href' => helper::baseUrl() . 'plugin'
|
||||
]) . '</li>';
|
||||
} else {
|
||||
$rightItems .= '<li>' . template::ico('puzzle', [
|
||||
'help' => 'Modules',
|
||||
'href' => helper::baseUrl() . 'plugin'
|
||||
]) . '</li>';
|
||||
}
|
||||
// Boutons depuis le groupe éditeur
|
||||
if (
|
||||
$this->getUser('group') >= self::GROUP_EDITOR
|
||||
&& $this->getUser('permission', 'user', 'edit')
|
||||
@ -1203,7 +1255,7 @@ class layout extends common
|
||||
$vars = 'var baseUrl = ' . json_encode(helper::baseUrl(false)) . ';';
|
||||
$vars .= 'var baseUrlQs = ' . json_encode(helper::baseUrl()) . ';';
|
||||
if (
|
||||
$this->getUser('password') === $this->getInput('ZWII_USER_PASSWORD')
|
||||
$this->isConnected() === true
|
||||
and $this->getUser('group') >= self::GROUP_EDITOR
|
||||
) {
|
||||
$vars .= 'var privateKey = ' . json_encode(md5_file(self::DATA_DIR . 'core.json')) . ';';
|
||||
|
@ -11,16 +11,16 @@ class core extends common
|
||||
parent::__construct();
|
||||
// Token CSRF
|
||||
if (empty($_SESSION['csrf'])) {
|
||||
$_SESSION['csrf'] = bin2hex(openssl_random_pseudo_bytes(128));
|
||||
$_SESSION['csrf'] = bin2hex(openssl_random_pseudo_bytes(64));
|
||||
}
|
||||
|
||||
// Fuseau horaire
|
||||
self::$timezone = $this->getData(['config', 'timezone']); // Utile pour transmettre le timezone à la classe helper
|
||||
date_default_timezone_set(self::$timezone);
|
||||
common::$timezone = $this->getData(['config', 'timezone']); // Utile pour transmettre le timezone à la classe helper
|
||||
date_default_timezone_set(common::$timezone);
|
||||
// Supprime les fichiers temporaires
|
||||
$lastClearTmp = mktime(0, 0, 0);
|
||||
if ($lastClearTmp > $this->getData(['core', 'lastClearTmp']) + 86400) {
|
||||
$iterator = new DirectoryIterator(self::TEMP_DIR);
|
||||
$iterator = new DirectoryIterator(common::TEMP_DIR);
|
||||
foreach ($iterator as $fileInfos) {
|
||||
if (
|
||||
$fileInfos->isFile() &&
|
||||
@ -32,8 +32,6 @@ class core extends common
|
||||
}
|
||||
// Date de la dernière suppression
|
||||
$this->setData(['core', 'lastClearTmp', $lastClearTmp]);
|
||||
// Enregistre les données
|
||||
//$this->SaveData();
|
||||
}
|
||||
// Backup automatique des données
|
||||
$lastBackup = mktime(0, 0, 0);
|
||||
@ -43,11 +41,11 @@ class core extends common
|
||||
and $this->getData(['user']) // Pas de backup pendant l'installation
|
||||
) {
|
||||
// Copie des fichier de données
|
||||
helper::autoBackup(self::BACKUP_DIR, ['backup', 'tmp', 'file']);
|
||||
helper::autoBackup(common::BACKUP_DIR, ['backup', 'tmp', 'file']);
|
||||
// Date du dernier backup
|
||||
$this->setData(['core', 'lastBackup', $lastBackup]);
|
||||
// Supprime les backups de plus de 30 jours
|
||||
$iterator = new DirectoryIterator(self::BACKUP_DIR);
|
||||
$iterator = new DirectoryIterator(common::BACKUP_DIR);
|
||||
foreach ($iterator as $fileInfos) {
|
||||
if (
|
||||
$fileInfos->isFile()
|
||||
@ -60,23 +58,23 @@ class core extends common
|
||||
}
|
||||
|
||||
// Crée le fichier de personnalisation avancée
|
||||
if (file_exists(self::DATA_DIR . 'custom.css') === false) {
|
||||
file_put_contents(self::DATA_DIR . 'custom.css', ('core/module/theme/resource/custom.css'));
|
||||
chmod(self::DATA_DIR . 'custom.css', 0755);
|
||||
if (file_exists(common::DATA_DIR . 'custom.css') === false) {
|
||||
file_put_contents(common::DATA_DIR . 'custom.css', ('core/module/theme/resource/custom.css'));
|
||||
chmod(common::DATA_DIR . 'custom.css', 0755);
|
||||
}
|
||||
// Crée le fichier de personnalisation
|
||||
if (file_exists(self::DATA_DIR . self::$siteContent . '/theme.css') === false) {
|
||||
file_put_contents(self::DATA_DIR . self::$siteContent . '/theme.css', '');
|
||||
chmod(self::DATA_DIR . self::$siteContent . '/theme.css', 0755);
|
||||
if (file_exists(common::DATA_DIR . common::$siteContent . '/theme.css') === false) {
|
||||
file_put_contents(common::DATA_DIR . common::$siteContent . '/theme.css', '');
|
||||
chmod(common::DATA_DIR . common::$siteContent . '/theme.css', 0755);
|
||||
}
|
||||
// Crée le fichier de personnalisation de l'administration
|
||||
if (file_exists(self::DATA_DIR . 'admin.css') === false) {
|
||||
file_put_contents(self::DATA_DIR . 'admin.css', '');
|
||||
chmod(self::DATA_DIR . 'admin.css', 0755);
|
||||
if (file_exists(common::DATA_DIR . 'admin.css') === false) {
|
||||
file_put_contents(common::DATA_DIR . 'admin.css', '');
|
||||
chmod(common::DATA_DIR . 'admin.css', 0755);
|
||||
}
|
||||
|
||||
// Check la version rafraichissement du theme
|
||||
$cssVersion = preg_split('/\*+/', file_get_contents(self::DATA_DIR . self::$siteContent . '/theme.css'));
|
||||
$cssVersion = preg_split('/\*+/', file_get_contents(common::DATA_DIR . common::$siteContent . '/theme.css'));
|
||||
if (empty($cssVersion[1]) or $cssVersion[1] !== md5(json_encode($this->getData(['theme'])))) {
|
||||
// Version
|
||||
$css = '/*' . md5(json_encode($this->getData(['theme']))) . '*/';
|
||||
@ -92,7 +90,7 @@ class core extends common
|
||||
// Fonts disponibles
|
||||
$fontsAvailable['files'] = $this->getData(['font', 'files']);
|
||||
$fontsAvailable['imported'] = $this->getData(['font', 'imported']);
|
||||
$fontsAvailable['websafe'] = self::$fontsWebSafe;
|
||||
$fontsAvailable['websafe'] = common::$fontsWebSafe;
|
||||
|
||||
// Fontes installées
|
||||
$fonts = [
|
||||
@ -273,7 +271,7 @@ class core extends common
|
||||
$css .= '#footerCopyright{text-align:' . $this->getData(['theme', 'footer', 'copyrightAlign']) . '}';
|
||||
|
||||
// Enregistre la personnalisation
|
||||
file_put_contents(self::DATA_DIR . self::$siteContent . '/theme.css', $css);
|
||||
file_put_contents(common::DATA_DIR . common::$siteContent . '/theme.css', $css);
|
||||
|
||||
// Effacer le cache pour tenir compte de la couleur de fond TinyMCE
|
||||
header("Expires: Tue, 01 Jan 2000 00:00:00 GMT");
|
||||
@ -284,7 +282,7 @@ class core extends common
|
||||
}
|
||||
|
||||
// Check la version rafraichissement du theme admin
|
||||
$cssVersion = preg_split('/\*+/', file_get_contents(self::DATA_DIR . 'admin.css'));
|
||||
$cssVersion = preg_split('/\*+/', file_get_contents(common::DATA_DIR . 'admin.css'));
|
||||
if (empty($cssVersion[1]) or $cssVersion[1] !== md5(json_encode($this->getData(['admin'])))) {
|
||||
|
||||
// Version
|
||||
@ -293,7 +291,7 @@ class core extends common
|
||||
// Fonts disponibles
|
||||
$fontsAvailable['files'] = $this->getData(['font', 'files']);
|
||||
$fontsAvailable['imported'] = $this->getData(['font', 'imported']);
|
||||
$fontsAvailable['websafe'] = self::$fontsWebSafe;
|
||||
$fontsAvailable['websafe'] = common::$fontsWebSafe;
|
||||
|
||||
/**
|
||||
* Import des polices de caractères
|
||||
@ -368,7 +366,7 @@ class core extends common
|
||||
// Bordure du contour TinyMCE
|
||||
$css .= '.mce-tinymce{border: 1px solid ' . $this->getData(['admin', 'borderBlockColor']) . '!important;}';
|
||||
// Enregistre la personnalisation
|
||||
file_put_contents(self::DATA_DIR . 'admin.css', $css);
|
||||
file_put_contents(common::DATA_DIR . 'admin.css', $css);
|
||||
}
|
||||
}
|
||||
/**
|
||||
@ -384,8 +382,8 @@ class core extends common
|
||||
require 'core/module/' . $classPath;
|
||||
}
|
||||
// Module
|
||||
elseif (is_readable(self::MODULE_DIR . $classPath)) {
|
||||
require self::MODULE_DIR . $classPath;
|
||||
elseif (is_readable(common::MODULE_DIR . $classPath)) {
|
||||
require common::MODULE_DIR . $classPath;
|
||||
}
|
||||
// Librairie
|
||||
elseif (is_readable('core/vendor/' . $classPath)) {
|
||||
@ -411,25 +409,43 @@ class core extends common
|
||||
exit();
|
||||
}
|
||||
|
||||
// Sauvegarde la dernière page visitée par l'utilisateur connecté et enregistre l'historique des consultations
|
||||
|
||||
/*
|
||||
* Récupère les statistiques de l'utilisateur non admin
|
||||
* en dehors de home
|
||||
* et si la connextion est nécessaire et que le membre est connecté
|
||||
* stocke la progression dans la base des inscriptions
|
||||
* */
|
||||
if (
|
||||
// L'utilisateur est renseigné
|
||||
$this->getUser('id')
|
||||
&& self::$siteContent !== 'home'
|
||||
// L'accueil ne stocke pas lea progression
|
||||
&& common::$siteContent !== 'home'
|
||||
// La page existe
|
||||
&& in_array($this->getUrl(0), array_keys($this->getData(['page'])))
|
||||
// Le userId n'est pas celui d'un admis ni le prof du contenu
|
||||
// L'espace dispose d'un accès nécessitant un compte
|
||||
&& $this->getData(['course', self::$siteContent, 'enrolment']) > 0
|
||||
// Le userId n'est pas celui d'un admis ni le compte d'un gestionnaire de cet espace
|
||||
&& (
|
||||
$this->getUser('group') < self::GROUP_ADMIN
|
||||
|| $this->getUser('id') !== $this->getData(['course', self::$siteContent, 'author'])
|
||||
$this->getUser('group') < common::GROUP_ADMIN
|
||||
|| $this->getUser('id') !== $this->getData(['course', common::$siteContent, 'author'])
|
||||
)
|
||||
) {
|
||||
// Stocke l'historique des pages vues
|
||||
$data = is_array($this->getData(['enrolment', self::$siteContent, $this->getUser('id'), 'history', $this->getUrl(0)]))
|
||||
? array_merge([time()], $this->getData(['enrolment', self::$siteContent, $this->getUser('id'), 'history', $this->getUrl(0)]))
|
||||
: [time()];
|
||||
$this->setData(['enrolment', self::$siteContent, $this->getUser('id'), 'history', $this->getUrl(0), $data]);
|
||||
|
||||
$course = new course();
|
||||
|
||||
// Met à jour la progression de l'utisateur et obtient le nombre de pages vues
|
||||
$userProgress = $course->setUserProgress(self::$siteContent, $this->getUser('id'));
|
||||
|
||||
// Stockage dans les données d'inscription du membre
|
||||
$this->setData(['enrolment', self::$siteContent, $this->getUser('id'), 'progress', $userProgress], false);
|
||||
|
||||
// Les rapports sont activés
|
||||
// Stocke la dernière page vue et sa date de consultation
|
||||
$this->setData(['enrolment', self::$siteContent, $this->getUser('id'), 'lastPageView', $this->getUrl(0)]);
|
||||
$this->setData(['enrolment', self::$siteContent, $this->getUser('id'), 'datePageView', time()]);
|
||||
if ($this->getdata(['course', common::$siteContent, 'report']) === true) {
|
||||
$this->setData(['enrolment', common::$siteContent, $this->getUser('id'), 'lastPageView', $this->getUrl(0)], false);
|
||||
$this->setData(['enrolment', common::$siteContent, $this->getUser('id'), 'datePageView', time()]);
|
||||
}
|
||||
}
|
||||
|
||||
// Journalisation
|
||||
@ -437,8 +453,8 @@ class core extends common
|
||||
|
||||
// Force la déconnexion des membres bannis ou d'une seconde session
|
||||
if (
|
||||
$this->getUser('password') === $this->getInput('ZWII_USER_PASSWORD')
|
||||
and ($this->getUser('group') === self::GROUP_BANNED
|
||||
$this->isConnected() === true
|
||||
and ($this->getUser('group') === common::GROUP_BANNED
|
||||
or ($_SESSION['csrf'] !== $this->getData(['user', $this->getUser('id'), 'accessCsrf'])
|
||||
and $this->getData(['config', 'connect', 'autoDisconnect']) === true)
|
||||
)
|
||||
@ -451,9 +467,9 @@ class core extends common
|
||||
$this->getData(['config', 'maintenance'])
|
||||
and in_array($this->getUrl(0), ['maintenance', 'user']) === false
|
||||
and $this->getUrl(1) !== 'login'
|
||||
and ($this->getUser('password') !== $this->getInput('ZWII_USER_PASSWORD')
|
||||
or ($this->getUser('password') === $this->getInput('ZWII_USER_PASSWORD')
|
||||
and $this->getUser('group') < self::GROUP_ADMIN
|
||||
and ($this->isConnected() === false
|
||||
or ($this->isConnected() === true
|
||||
and $this->getUser('group') < common::GROUP_ADMIN
|
||||
)
|
||||
)
|
||||
) {
|
||||
@ -466,32 +482,12 @@ class core extends common
|
||||
exit();
|
||||
}
|
||||
|
||||
// Pour éviter une 404 sur une langue étrangère, bascule dans la langue correcte.
|
||||
if (is_null($this->getData(['page', $this->getUrl(0)]))) {
|
||||
foreach ($this->getData(['course']) as $key => $value) {;
|
||||
if (
|
||||
is_dir(self::DATA_DIR . $key) &&
|
||||
file_exists(self::DATA_DIR . $key . '/page.json')
|
||||
) {
|
||||
$pagesId = json_decode(file_get_contents(self::DATA_DIR . $key . '/page.json'), true);
|
||||
if (
|
||||
is_array($pagesId['page']) &&
|
||||
array_key_exists($this->getUrl(0), $pagesId['page'])
|
||||
) {
|
||||
//$_SESSION['ZWII_SITE_CONTENT'] = $key;
|
||||
header('Refresh:0; url=' . helper::baseUrl() . 'course/swap/' . $key . '/' . $this->getUrl(0));
|
||||
exit();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Check l'accès à la page
|
||||
$access = null;
|
||||
if ($this->getData(['page', $this->getUrl(0)]) !== null) {
|
||||
if (
|
||||
$this->getData(['page', $this->getUrl(0), 'group']) === self::GROUP_VISITOR
|
||||
or ($this->getUser('password') === $this->getInput('ZWII_USER_PASSWORD')
|
||||
$this->getData(['page', $this->getUrl(0), 'group']) === common::GROUP_VISITOR
|
||||
or ($this->isConnected() === true
|
||||
// and $this->getUser('group') >= $this->getData(['page', $this->getUrl(0), 'group'])
|
||||
// Modification qui tient compte du profil de la page
|
||||
and ($this->getUser('group') * 10 + $this->getUser('profil')) >= ($this->getData(['page', $this->getUrl(0), 'group']) * 10 + $this->getData(['page', $this->getUrl(0), 'profil']))
|
||||
@ -508,14 +504,38 @@ class core extends common
|
||||
// Empêcher l'accès aux pages désactivées par URL directe
|
||||
if (
|
||||
($this->getData(['page', $this->getUrl(0), 'disable']) === true
|
||||
and $this->getUser('password') !== $this->getInput('ZWII_USER_PASSWORD')
|
||||
and $this->isConnected() === false
|
||||
) or ($this->getData(['page', $this->getUrl(0), 'disable']) === true
|
||||
and $this->getUser('password') === $this->getInput('ZWII_USER_PASSWORD')
|
||||
and $this->getUser('group') < self::GROUP_EDITOR
|
||||
and $this->isConnected() === true
|
||||
and $this->getUser('group') < common::GROUP_EDITOR
|
||||
)
|
||||
) {
|
||||
$access = false;
|
||||
}
|
||||
// Lève une erreur si l'url est celle d'une page avec des éléments surnuméraires https://www.site.fr/page/truc
|
||||
if (
|
||||
array_key_exists($this->getUrl(0), $this->getData(['page']))
|
||||
and $this->getUrl(1)
|
||||
and $this->getData(['page', $this->getUrl(0), 'moduleId']) === ''
|
||||
) {
|
||||
$access = false;
|
||||
}
|
||||
|
||||
/** Empêche la consultation d'un espace laissé ouvert après la déconnexion et redirige vers home
|
||||
* L'utilisateur n'est pas connecté
|
||||
* ET l'accueil n'est pas affiché
|
||||
* ET l'espace affiché nécessite un compte d'accès, enrolment vaut 1,2 ou 3
|
||||
* */
|
||||
|
||||
if (
|
||||
$this->isConnected() === false
|
||||
and self::$siteContent !== 'home'
|
||||
and $this->getData(['course', self::$siteContent, 'enrolment']) > 0
|
||||
) {
|
||||
$_SESSION['ZWII_SITE_CONTENT'] = 'home';
|
||||
header(header: 'Location:' . helper::baseUrl(true) . 'swap/' . self::$siteContent);
|
||||
exit();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@ -537,9 +557,9 @@ class core extends common
|
||||
$this->getUser('id') &&
|
||||
$userId !== $this->getUser('id') &&
|
||||
$this->getData(['user', $userId, 'accessUrl']) === $this->getUrl() &&
|
||||
array_intersect($t, self::$concurrentAccess) &&
|
||||
//array_intersect($t, self::$accessExclude) !== false &&
|
||||
time() < $this->getData(['user', $userId, 'accessTimer']) + self::ACCESS_TIMER
|
||||
array_intersect($t, common::$concurrentAccess) &&
|
||||
//array_intersect($t, common::$accessExclude) !== false &&
|
||||
time() < $this->getData(['user', $userId, 'accessTimer']) + common::ACCESS_TIMER
|
||||
) {
|
||||
$access = false;
|
||||
$accessInfo['userName'] = $this->getData(['user', $userId, 'lastname']) . ' ' . $this->getData(['user', $userId, 'firstname']);
|
||||
@ -549,10 +569,11 @@ class core extends common
|
||||
}
|
||||
// Accès concurrent stocke la page visitée
|
||||
if (
|
||||
$this->getUser('password') === $this->getInput('ZWII_USER_PASSWORD')
|
||||
$this->isConnected() === true
|
||||
&& $this->getUser('id')
|
||||
&& !$this->isPost()
|
||||
) {
|
||||
$this->setData(['user', $this->getUser('id'), 'accessUrl', $this->getUrl()]);
|
||||
$this->setData(['user', $this->getUser('id'), 'accessUrl', $this->getUrl()], false);
|
||||
$this->setData(['user', $this->getUser('id'), 'accessTimer', time()]);
|
||||
}
|
||||
// Breadcrumb
|
||||
@ -576,10 +597,10 @@ class core extends common
|
||||
$inlineScript[] = $this->getData(['page', $this->getUrl(0), 'js']) === null ? '' : $this->getData(['page', $this->getUrl(0), 'js']);
|
||||
|
||||
// Importe le contenu, le CSS et le script des barres
|
||||
$contentRight = $this->getData(['page', $this->getUrl(0), 'barRight']) ? $this->getPage($this->getData(['page', $this->getUrl(0), 'barRight']), self::$siteContent) : '';
|
||||
$contentRight = $this->getData(['page', $this->getUrl(0), 'barRight']) ? $this->getPage($this->getData(['page', $this->getUrl(0), 'barRight']), common::$siteContent) : '';
|
||||
$inlineStyle[] = $this->getData(['page', $this->getData(['page', $this->getUrl(0), 'barRight']), 'css']) === null ? '' : $this->getData(['page', $this->getData(['page', $this->getUrl(0), 'barRight']), 'css']);
|
||||
$inlineScript[] = $this->getData(['page', $this->getData(['page', $this->getUrl(0), 'barRight']), 'js']) === null ? '' : $this->getData(['page', $this->getData(['page', $this->getUrl(0), 'barRight']), 'js']);
|
||||
$contentLeft = $this->getData(['page', $this->getUrl(0), 'barLeft']) ? $this->getPage($this->getData(['page', $this->getUrl(0), 'barLeft']), self::$siteContent) : '';
|
||||
$contentLeft = $this->getData(['page', $this->getUrl(0), 'barLeft']) ? $this->getPage($this->getData(['page', $this->getUrl(0), 'barLeft']), common::$siteContent) : '';
|
||||
$inlineStyle[] = $this->getData(['page', $this->getData(['page', $this->getUrl(0), 'barLeft']), 'css']) === null ? '' : $this->getData(['page', $this->getData(['page', $this->getUrl(0), 'barLeft']), 'css']);
|
||||
$inlineScript[] = $this->getData(['page', $this->getData(['page', $this->getUrl(0), 'barLeft']), 'js']) === null ? '' : $this->getData(['page', $this->getData(['page', $this->getUrl(0), 'barLeft']), 'js']);
|
||||
|
||||
@ -597,7 +618,7 @@ class core extends common
|
||||
|
||||
$this->addOutput([
|
||||
'title' => $title,
|
||||
'content' => $this->getPage($this->getUrl(0), self::$siteContent),
|
||||
'content' => $this->getPage($this->getUrl(0), common::$siteContent),
|
||||
'metaDescription' => $this->getData(['page', $this->getUrl(0), 'metaDescription']),
|
||||
'metaTitle' => $this->getData(['page', $this->getUrl(0), 'metaTitle']),
|
||||
'typeMenu' => $this->getData(['page', $this->getUrl(0), 'typeMenu']),
|
||||
@ -623,7 +644,7 @@ class core extends common
|
||||
: $this->getData(['page', $this->getUrl(0), 'metaDescription']);
|
||||
|
||||
// Importe le CSS de la page principale
|
||||
$pageContent = $this->getPage($this->getUrl(0), self::$siteContent);
|
||||
$pageContent = $this->getPage($this->getUrl(0), common::$siteContent);
|
||||
|
||||
$this->addOutput([
|
||||
'title' => $title,
|
||||
@ -668,8 +689,8 @@ class core extends common
|
||||
$output = $module->output;
|
||||
// Check le groupe de l'utilisateur
|
||||
if (
|
||||
($module::$actions[$action] === self::GROUP_VISITOR
|
||||
or ($this->getUser('password') === $this->getInput('ZWII_USER_PASSWORD')
|
||||
($module::$actions[$action] === common::GROUP_VISITOR
|
||||
or ($this->isConnected() === true
|
||||
and $this->getUser('group') >= $module::$actions[$action]
|
||||
and $this->getUser('permission', $moduleId, $action)
|
||||
)
|
||||
@ -681,10 +702,10 @@ class core extends common
|
||||
foreach ($_POST as $postId => $postValue) {
|
||||
if (is_array($postValue)) {
|
||||
foreach ($postValue as $subPostId => $subPostValue) {
|
||||
self::$inputBefore[$postId . '_' . $subPostId] = $subPostValue;
|
||||
common::$inputBefore[$postId . '_' . $subPostId] = $subPostValue;
|
||||
}
|
||||
} else {
|
||||
self::$inputBefore[$postId] = $postValue;
|
||||
common::$inputBefore[$postId] = $postValue;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -724,9 +745,9 @@ class core extends common
|
||||
// Contenu par vue
|
||||
elseif ($output['view']) {
|
||||
// Chemin en fonction d'un module du coeur ou d'un module
|
||||
$modulePath = in_array($moduleId, self::$coreModuleIds) ? 'core/' : '';
|
||||
$modulePath = in_array($moduleId, common::$coreModuleIds) ? 'core/' : '';
|
||||
// CSS
|
||||
$stylePath = $modulePath . self::MODULE_DIR . $moduleId . '/view/' . $output['view'] . '/' . $output['view'] . '.css';
|
||||
$stylePath = $modulePath . common::MODULE_DIR . $moduleId . '/view/' . $output['view'] . '/' . $output['view'] . '.css';
|
||||
if (file_exists($stylePath)) {
|
||||
$this->addOutput([
|
||||
'style' => file_get_contents($stylePath)
|
||||
@ -739,7 +760,7 @@ class core extends common
|
||||
}
|
||||
|
||||
// JS
|
||||
$scriptPath = $modulePath . self::MODULE_DIR . $moduleId . '/view/' . $output['view'] . '/' . $output['view'] . '.js.php';
|
||||
$scriptPath = $modulePath . common::MODULE_DIR . $moduleId . '/view/' . $output['view'] . '/' . $output['view'] . '.js.php';
|
||||
if (file_exists($scriptPath)) {
|
||||
ob_start();
|
||||
include $scriptPath;
|
||||
@ -748,7 +769,7 @@ class core extends common
|
||||
]);
|
||||
}
|
||||
// Vue
|
||||
$viewPath = $modulePath . self::MODULE_DIR . $moduleId . '/view/' . $output['view'] . '/' . $output['view'] . '.php';
|
||||
$viewPath = $modulePath . common::MODULE_DIR . $moduleId . '/view/' . $output['view'] . '/' . $output['view'] . '.php';
|
||||
if (file_exists($viewPath)) {
|
||||
ob_start();
|
||||
include $viewPath;
|
||||
@ -757,7 +778,7 @@ class core extends common
|
||||
$this->addOutput([
|
||||
'content' => ob_get_clean() . ($output['showPageContent'] ? $pageContent : '')
|
||||
]);
|
||||
} else if ($modpos === 'free') {
|
||||
} elseif ($modpos === 'free' && strstr($pageContent, '[MODULE]')) {
|
||||
if (strstr($pageContent, '[MODULE]', true) === false) {
|
||||
$begin = strstr($pageContent, '[]', true);
|
||||
} else {
|
||||
@ -817,32 +838,61 @@ class core extends common
|
||||
if ($accessInfo['userName']) {
|
||||
$this->addOutput([
|
||||
'title' => 'Accès verrouillé',
|
||||
'content' => template::speech('<p>'. sprintf(helper::translate('La page %s est ouverte par l\'utilisateur %s</p><p><a style="color:inherit" href="javascript:history.back()">%s</a></p>'), $accessInfo['pageId'], $accessInfo['userName'], helper::translate('Retour')))
|
||||
'content' => template::speech('<p>' . sprintf(helper::translate('La page %s est ouverte par l\'utilisateur %s</p><p><a style="color:inherit" href="javascript:history.back()">%s</a></p>'), $accessInfo['pageId'], $accessInfo['userName'], helper::translate('Retour')))
|
||||
]);
|
||||
} else {
|
||||
if (
|
||||
$this->getData(['config', 'page403']) !== 'none'
|
||||
and $this->getData(['page', $this->getData(['config', 'page403'])])
|
||||
//and $this->getData(['page', $this->getData(['config', 'page403'])])
|
||||
) {
|
||||
$_SESSION['ZWII_SITE_CONTENT'] = 'home';
|
||||
header('Location:' . helper::baseUrl() . $this->getData(['config', 'page403']));
|
||||
} else {
|
||||
$this->addOutput([
|
||||
'title' => 'Accès interdit',
|
||||
'content' => template::speech('<p>' . helper::translate('Vous n\'êtes pas autorisé à consulter cette page (erreur 403)') . '</p><p><a style="color:inherit" href="javascript:history.back()">'. helper::translate('Retour') . '</a></p>')
|
||||
'content' => template::speech('<p>' . helper::translate('Vous n\'êtes pas autorisé à consulter cette page (erreur 403)') . '</p><p><a style="color:inherit" href="javascript:history.back()">' . helper::translate('Retour') . '</a></p>')
|
||||
]);
|
||||
}
|
||||
}
|
||||
} elseif ($this->output['content'] === '') {
|
||||
|
||||
// Pour éviter une 404, bascule dans l'espace correct si la page existe dans cet espace.
|
||||
// Parcourir les espaces y compris l'accueil
|
||||
foreach (array_merge(['home' => []], $this->getData(['course'])) as $courseId => $value) {
|
||||
;
|
||||
if (
|
||||
// l'espace existe
|
||||
is_dir(common::DATA_DIR . $courseId) &&
|
||||
file_exists(common::DATA_DIR . $courseId . '/page.json')
|
||||
) {
|
||||
// Lire les données des pages
|
||||
$pagesId = json_decode(file_get_contents(common::DATA_DIR . $courseId . '/page.json'), true);
|
||||
if (
|
||||
// La page existe
|
||||
is_array($pagesId['page']) &&
|
||||
array_key_exists($this->getUrl(0), $pagesId['page'])
|
||||
) {
|
||||
// Basculer
|
||||
$_SESSION['ZWII_SITE_CONTENT'] = $courseId;
|
||||
header('Refresh:0; url=' . helper::baseUrl() . $this->getUrl());
|
||||
exit();
|
||||
}
|
||||
}
|
||||
}
|
||||
// La page n'existe pas dans les esapces, on génére une erreur 404
|
||||
http_response_code(404);
|
||||
if (
|
||||
// une page est définie dans la configuration mais dans home
|
||||
$this->getData(['config', 'page404']) !== 'none'
|
||||
and $this->getData(['page', $this->getData(['config', 'page404'])])
|
||||
) {
|
||||
// Bascule sur l'acccueil et rediriger
|
||||
$_SESSION['ZWII_SITE_CONTENT'] = 'home';
|
||||
header('Location:' . helper::baseUrl() . $this->getData(['config', 'page404']));
|
||||
} else {
|
||||
// Page par défaut
|
||||
$this->addOutput([
|
||||
'title' => 'Page indisponible',
|
||||
'content' => template::speech('<p>' . helper::translate('La page demandée n\'existe pas ou est introuvable (erreur 404)') . '</p><p><a style="color:inherit" href="javascript:history.back()">'. helper::translate('Retour') . '</a></p>')
|
||||
'content' => template::speech('<p>' . helper::translate('La page demandée n\'existe pas ou est introuvable (erreur 404)') . '</p><p><a style="color:inherit" href="javascript:history.back()">' . helper::translate('Retour') . '</a></p>')
|
||||
]);
|
||||
}
|
||||
}
|
||||
@ -865,25 +915,25 @@ class core extends common
|
||||
}
|
||||
switch ($this->output['display']) {
|
||||
// Layout brut
|
||||
case self::DISPLAY_RAW:
|
||||
case common::DISPLAY_RAW:
|
||||
echo $this->output['content'];
|
||||
break;
|
||||
// Layout vide
|
||||
case self::DISPLAY_LAYOUT_BLANK:
|
||||
case common::DISPLAY_LAYOUT_BLANK:
|
||||
require 'core/layout/blank.php';
|
||||
break;
|
||||
// Affichage en JSON
|
||||
case self::DISPLAY_JSON:
|
||||
case common::DISPLAY_JSON:
|
||||
header('Content-Type: application/json');
|
||||
echo json_encode($this->output['content']);
|
||||
break;
|
||||
// RSS feed
|
||||
case self::DISPLAY_RSS:
|
||||
case common::DISPLAY_RSS:
|
||||
header('Content-type: application/rss+xml; charset=UTF-8');
|
||||
echo $this->output['content'];
|
||||
break;
|
||||
// Layout allégé
|
||||
case self::DISPLAY_LAYOUT_LIGHT:
|
||||
case common::DISPLAY_LAYOUT_LIGHT:
|
||||
ob_start();
|
||||
require 'core/layout/light.php';
|
||||
$content = ob_get_clean();
|
||||
@ -894,7 +944,7 @@ class core extends common
|
||||
echo $content;
|
||||
break;
|
||||
// Layout principal
|
||||
case self::DISPLAY_LAYOUT_MAIN:
|
||||
case common::DISPLAY_LAYOUT_MAIN:
|
||||
ob_start();
|
||||
require 'core/layout/main.php';
|
||||
$content = ob_get_clean();
|
||||
|
@ -128,7 +128,17 @@ class SitemapGenerator
|
||||
*/
|
||||
private $sampleRobotsLines = [
|
||||
"User-agent: *",
|
||||
"Disallow: /",
|
||||
"User-agent: Googlebot",
|
||||
"Allow: /",
|
||||
"User-agent: bingbot",
|
||||
"Allow: /",
|
||||
"User-agent: Slurp",
|
||||
"Allow: /",
|
||||
"User-agent: DuckDuckBot",
|
||||
"Allow: /",
|
||||
"User-agent: Baiduspider",
|
||||
"Allow: /"
|
||||
];
|
||||
/**
|
||||
* @var array list of valid changefreq values according to the spec
|
||||
|
@ -28,7 +28,7 @@ class template
|
||||
$attributes['value'] = helper::translate($attributes['value']);
|
||||
$attributes['help'] = helper::translate($attributes['help']);
|
||||
// Retourne le html
|
||||
return sprintf(
|
||||
return sprintf(
|
||||
'<a %s class="button %s %s %s" %s>%s</a>',
|
||||
helper::sprintAttributes($attributes, ['class', 'disabled', 'ico', 'value']),
|
||||
$attributes['disabled'] ? 'disabled' : '',
|
||||
@ -65,12 +65,12 @@ class template
|
||||
// Limite addition et soustraction selon le type de captcha
|
||||
$numbers = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 12, 13, 14, 15, 16, 17, 18, 19, 20];
|
||||
$letters = ['u', 't', 's', 'r', 'q', 'p', 'o', 'n', 'm', 'l', 'k', 'j', 'i', 'h', 'g', 'f', 'e', 'd', 'c', 'b', 'a'];
|
||||
$limit = $attributes['limit'] ? count($letters) - 1 : 10;
|
||||
$limit = $attributes['limit'] ? count($letters) - 1 : 10;
|
||||
|
||||
// Tirage de l'opération
|
||||
mt_srand();
|
||||
// Captcha simple limité à l'addition
|
||||
$operator = $attributes['limit'] ? mt_rand(1, 4) : 1;
|
||||
$operator = $attributes['limit'] ? mt_rand(1, 4) : 1;
|
||||
|
||||
// Limite si multiplication ou division
|
||||
if ($operator > 2) {
|
||||
@ -94,15 +94,15 @@ class template
|
||||
switch ($operator) {
|
||||
case 1:
|
||||
$operator = template::ico('plus', ['fontSize' => '2em;']);
|
||||
$result = $firstNumber + $secondNumber;
|
||||
$result = $firstNumber + $secondNumber;
|
||||
break;
|
||||
case 2:
|
||||
$operator = template::ico('minus', ['fontSize' => '2em;']);
|
||||
$result = $firstNumber - $secondNumber;
|
||||
$result = $firstNumber - $secondNumber;
|
||||
break;
|
||||
case 3:
|
||||
$operator = template::ico('cancel', ['fontSize' => '2em;']);
|
||||
$result = $firstNumber * $secondNumber;
|
||||
$result = $firstNumber * $secondNumber;
|
||||
break;
|
||||
case 4:
|
||||
$operator = template::ico('divide', ['fontSize' => '2em;']);
|
||||
@ -112,7 +112,7 @@ class template
|
||||
}
|
||||
mt_srand();
|
||||
$secondNumber = mt_rand(1, $limit);
|
||||
$firstNumber = $firstNumber * $secondNumber;
|
||||
$firstNumber = $firstNumber * $secondNumber;
|
||||
$result = $firstNumber / $secondNumber;
|
||||
break;
|
||||
}
|
||||
@ -125,8 +125,8 @@ class template
|
||||
$secondLetter = uniqid();
|
||||
|
||||
// Masquage image source pour éviter un décodage
|
||||
copy('core/vendor/zwiico/png/' . $attributes['type'] . '/' . $letters[$firstNumber] . '.png', 'site/tmp/' . $firstLetter . '.png');
|
||||
copy('core/vendor/zwiico/png/' . $attributes['type'] . '/' . $letters[$secondNumber] . '.png', 'site/tmp/' . $secondLetter . '.png');
|
||||
copy('core/vendor/zwiico/png/' . $attributes['type'] . '/' . $letters[$firstNumber] . '.png', 'site/tmp/' . $firstLetter . '.png');
|
||||
copy('core/vendor/zwiico/png/' . $attributes['type'] . '/' . $letters[$secondNumber] . '.png', 'site/tmp/' . $secondLetter . '.png');
|
||||
|
||||
|
||||
// Début du wrapper
|
||||
@ -134,7 +134,7 @@ class template
|
||||
// Label
|
||||
$html .= self::label(
|
||||
$attributes['id'],
|
||||
'<img class="captcha' . ucFirst($attributes['type']) . '" src="' . helper::baseUrl(false) . 'site/tmp/' . $firstLetter . '.png" /> <strong>' . $operator . '</strong> <img class="captcha' . ucFirst($attributes['type']) . '" src="' . helper::baseUrl(false) . 'site/tmp/' . $secondLetter . '.png" />' . template::ico('eq', ['fontSize' => '2em;']),
|
||||
'<img class="captcha' . ucFirst($attributes['type']) . '" src="' . helper::baseUrl(false) . 'site/tmp/' . $firstLetter . '.png" /> <strong>' . $operator . '</strong> <img class="captcha' . ucFirst($attributes['type']) . '" src="' . helper::baseUrl(false) . 'site/tmp/' . $secondLetter . '.png" />' . template::ico('eq', ['fontSize' => '2em;']),
|
||||
[
|
||||
'help' => $attributes['help']
|
||||
]
|
||||
@ -224,7 +224,7 @@ class template
|
||||
* Crée un champ date
|
||||
* @param string $nameId Nom et id du champ
|
||||
* @param array $attributes Attributs ($key => $value)
|
||||
* @param string type date time datetime-local month week
|
||||
* @param string type date seule ; time heure seule ; datetime-local (jour et heure)
|
||||
* @return string
|
||||
*/
|
||||
public static function date($nameId, array $attributes = [])
|
||||
@ -244,17 +244,32 @@ class template
|
||||
'placeholder' => '',
|
||||
'readonly' => false,
|
||||
'value' => '',
|
||||
'type'=> 'date',
|
||||
'type' => 'date',
|
||||
], $attributes);
|
||||
// Traduction de l'aide et de l'étiquette
|
||||
$attributes['label'] = helper::translate($attributes['label']);
|
||||
$attributes['help'] = helper::translate($attributes['help']);
|
||||
//$attributes['placeholder'] = helper::translate($attributes['placeholder']);
|
||||
// Filtre selon le type
|
||||
switch ($attributes['type']) {
|
||||
case 'datetime-local':
|
||||
$filter = helper::FILTER_TIMESTAMP;
|
||||
break;
|
||||
case 'date':
|
||||
$filter = helper::FILTER_DATE; // Pour générer une valeur uniquement sur la date
|
||||
break;
|
||||
case 'time':
|
||||
$filter = helper::FILTER_TIME; // Pour générer une valeur uniquement sur l'heure
|
||||
break;
|
||||
default:
|
||||
$filter = null; // pas de filtre pour month and year
|
||||
break;
|
||||
}
|
||||
// Sauvegarde des données en cas d'erreur
|
||||
if ($attributes['before'] and array_key_exists($attributes['id'], common::$inputBefore)) {
|
||||
$attributes['value'] = common::$inputBefore[$attributes['id']];
|
||||
} else {
|
||||
$attributes['value'] = ($attributes['value'] ? helper::filter($attributes['value'], helper::FILTER_TIMESTAMP) : '');
|
||||
$attributes['value'] = ($attributes['value'] ? helper::filter($attributes['value'], $filter) : '');
|
||||
}
|
||||
// Début du wrapper
|
||||
$html = '<div id="' . $attributes['id'] . 'Wrapper" class="inputWrapper ' . $attributes['classWrapper'] . '">';
|
||||
@ -310,6 +325,7 @@ class template
|
||||
'name' => $nameId,
|
||||
'type' => 2,
|
||||
'value' => '',
|
||||
'folder' => '',
|
||||
'language' => 'fr_FR'
|
||||
], $attributes);
|
||||
// Traduction de l'aide et de l'étiquette
|
||||
@ -346,14 +362,16 @@ class template
|
||||
$html .= sprintf(
|
||||
'<a
|
||||
href="' .
|
||||
helper::baseUrl(false) . 'core/vendor/filemanager/dialog.php' .
|
||||
'?relative_url=1' .
|
||||
'&lang=' . $attributes['language'] .
|
||||
'&field_id=' . $attributes['id'] .
|
||||
'&type=' . $attributes['type'] .
|
||||
'&akey=' . md5_file(core::DATA_DIR . 'core.json') .
|
||||
($attributes['extensions'] ? '&extensions=' . $attributes['extensions'] : '')
|
||||
. '"
|
||||
helper::baseUrl(false) . 'core/vendor/filemanager/dialog.php' .
|
||||
'?relative_url=1' .
|
||||
'&lang=' . $attributes['language'] .
|
||||
'&field_id=' . $attributes['id'] .
|
||||
'&type=' . $attributes['type'] .
|
||||
'&akey=' . md5_file(core::DATA_DIR . 'core.json') .
|
||||
// Ajoute le nom du dossier si la variable est passée
|
||||
(empty($attributes['folder']) ? '&fldr=/': '&fldr=' . $attributes['folder']) .
|
||||
($attributes['extensions'] ? '&extensions=' . $attributes['extensions'] : '') .
|
||||
'"
|
||||
class="inputFile %s %s"
|
||||
%s
|
||||
data-lity
|
||||
@ -471,7 +489,7 @@ class template
|
||||
// Traduction de l'aide
|
||||
$attributes['help'] = helper::translate($attributes['help']);
|
||||
// Contenu de l'icône
|
||||
$alt = $attributes['help'] ? $attributes['help'] : $ico;
|
||||
$alt = $attributes['help'] ? $attributes['help'] : $ico;
|
||||
$item = $attributes['href'] ? '<a id="' . $attributes['id'] . '" data-tippy-content="' . $attributes['help'] . '" alt="' . $alt . '" href="' . $attributes['href'] . '" ' . $attributes['attr'] . ' >' : '';
|
||||
$item .= '<span class="zwiico-' . $ico . ($attributes['margin'] ? ' zwiico-margin-' . $attributes['margin'] : '') . ($attributes['animate'] ? ' animate-spin' : '') . '" style="font-size:' . $attributes['fontSize'] . '"><!----></span>';
|
||||
$item .= ($attributes['href']) ? '</a>' : '';
|
||||
@ -486,7 +504,7 @@ class template
|
||||
*/
|
||||
public static function flag($langId, $size = 'auto')
|
||||
{
|
||||
$lang = 'home';
|
||||
$lang = 'fr_FR';
|
||||
switch ($langId) {
|
||||
case '':
|
||||
break;
|
||||
@ -496,6 +514,8 @@ class template
|
||||
case 'selected':
|
||||
if (isset($_SESSION['ZWII_SITE_CONTENT'])) {
|
||||
$lang = $_SESSION['ZWII_SITE_CONTENT'];
|
||||
} else {
|
||||
$lang = 'fr_FR';
|
||||
}
|
||||
}
|
||||
return '<img class="flag" src="' . helper::baseUrl(false) . 'core/vendor/i18n/png/' . $lang . '.png"
|
||||
@ -684,12 +704,12 @@ class template
|
||||
'label' => '',
|
||||
'name' => $nameId,
|
||||
'selected' => '',
|
||||
'font' => [],
|
||||
'font' => [],
|
||||
'multiple' => ''
|
||||
], $attributes);
|
||||
// Traduction de l'aide et de l'étiquette
|
||||
$attributes['label'] = helper::translate($attributes['label']);
|
||||
$attributes['help'] = helper::translate($attributes['help']);
|
||||
$attributes['help'] = helper::translate($attributes['help']);
|
||||
// Stocker les fontes et remettre à zéro le tableau des fontes transmis pour éviter une erreur de sprintAttributes
|
||||
if (empty($attributes['font']) === false) {
|
||||
$fonts = $attributes['font'];
|
||||
@ -726,7 +746,7 @@ class template
|
||||
);
|
||||
foreach ($options as $value => $text) {
|
||||
// Select des liste de fontes
|
||||
$html .= isset($fonts) ? sprintf(
|
||||
$html .= isset($fonts) ? sprintf(
|
||||
'<option value="%s"%s style="font-family: %s;">%s</option>',
|
||||
$value,
|
||||
$attributes['selected'] == $value ? ' selected' : '', // Double == pour ignorer le type de variable car $_POST change les types en string
|
||||
@ -748,6 +768,7 @@ class template
|
||||
return $html;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Crée une bulle de dialogue
|
||||
* @param string $text Texte de la bulle
|
||||
@ -779,7 +800,7 @@ class template
|
||||
// Traduction de l'aide et de l'étiquette
|
||||
$attributes['value'] = helper::translate($attributes['value']);
|
||||
// Retourne le html
|
||||
return sprintf(
|
||||
return sprintf(
|
||||
'<button type="submit" class="%s%s" %s>%s</button>',
|
||||
$attributes['class'],
|
||||
$attributes['uniqueSubmission'] ? 'uniqueSubmission' : '',
|
||||
@ -807,7 +828,7 @@ class template
|
||||
], $attributes);
|
||||
// Traduction de l'aide et de l'étiquette
|
||||
foreach ($head as $value) {
|
||||
$head[array_search($value, $head)] = helper::translate($value);
|
||||
$head[array_search($value, $head)] = helper::translate($value);
|
||||
}
|
||||
// Début du wrapper
|
||||
$html = '<div id="' . $attributes['id'] . 'Wrapper" class="tableWrapper ' . $attributes['classWrapper'] . '">';
|
||||
@ -902,7 +923,7 @@ class template
|
||||
$html .= self::notice($attributes['id'], $notice);
|
||||
// Texte
|
||||
$html .= sprintf(
|
||||
'<input type="' . $attributes['type']. '" %s>',
|
||||
'<input type="' . $attributes['type'] . '" %s>',
|
||||
helper::sprintAttributes($attributes)
|
||||
);
|
||||
// Fin du wrapper
|
||||
|
@ -216,15 +216,16 @@ core.start = function () {
|
||||
// Variables des cookies
|
||||
var getUrl = window.location;
|
||||
var domain = "domain=" + getUrl.hostname + ";";
|
||||
var basePath = getUrl.pathname.substring(0, getUrl.pathname.lastIndexOf('/') + 1);
|
||||
var path = "path=" + basePath + ";";
|
||||
var e = new Date();
|
||||
e.setFullYear(e.getFullYear() + 1);
|
||||
var expires = "expires=" + e.toUTCString();
|
||||
var expires = "expires=" + e.toUTCString() + ";";
|
||||
|
||||
// Stocke le cookie d'acceptation
|
||||
document.cookie = "ZWII_COOKIE_CONSENT=true;samesite=strict;" + domain + expires;
|
||||
document.cookie = "ZWII_COOKIE_CONSENT=true; samesite=lax; " + domain + path + expires;
|
||||
});
|
||||
|
||||
|
||||
/**
|
||||
* Fermeture de la popup des cookies
|
||||
*/
|
||||
@ -462,7 +463,7 @@ $(document).ready(function () {
|
||||
/**
|
||||
* Chargement paresseux des images et des iframes
|
||||
*/
|
||||
$("img,picture,iframe").attr("loading", "lazy");
|
||||
$("img").attr("loading", "lazy");
|
||||
|
||||
/**
|
||||
* Effet accordéon
|
||||
|
225
core/core.php
225
core/core.php
@ -51,7 +51,7 @@ class common
|
||||
const ACCESS_TIMER = 1800;
|
||||
|
||||
// Numéro de version
|
||||
const ZWII_VERSION = '1.4.21';
|
||||
const ZWII_VERSION = '1.15.01';
|
||||
|
||||
// URL autoupdate
|
||||
const ZWII_UPDATE_URL = 'https://forge.chapril.org/ZwiiCMS-Team/campus-update/raw/branch/master/';
|
||||
@ -148,24 +148,24 @@ class common
|
||||
self::GROUP_BANNED => 'Banni',
|
||||
self::GROUP_VISITOR => 'Visiteur',
|
||||
self::GROUP_MEMBER => 'Étudiant',
|
||||
self::GROUP_EDITOR => 'Enseignant',
|
||||
self::GROUP_EDITOR => 'Formateur',
|
||||
self::GROUP_ADMIN => 'Administrateur'
|
||||
];
|
||||
public static $groupEdits = [
|
||||
self::GROUP_BANNED => 'Banni',
|
||||
self::GROUP_MEMBER => 'Étudiant',
|
||||
self::GROUP_EDITOR => 'Enseignant',
|
||||
self::GROUP_EDITOR => 'Formateur',
|
||||
self::GROUP_ADMIN => 'Administrateur'
|
||||
];
|
||||
public static $groupNews = [
|
||||
self::GROUP_MEMBER => 'Étudiant',
|
||||
self::GROUP_EDITOR => 'Enseignant',
|
||||
self::GROUP_EDITOR => 'Formateur',
|
||||
self::GROUP_ADMIN => 'Administrateur'
|
||||
];
|
||||
public static $groupPublics = [
|
||||
self::GROUP_VISITOR => 'Visiteur',
|
||||
self::GROUP_MEMBER => 'Étudiant',
|
||||
self::GROUP_EDITOR => 'Enseignant',
|
||||
self::GROUP_EDITOR => 'Formateur',
|
||||
self::GROUP_ADMIN => 'Administrateur'
|
||||
];
|
||||
|
||||
@ -174,8 +174,12 @@ class common
|
||||
public static $dialog;
|
||||
// Langue de l'interface sélectionnée
|
||||
public static $i18nUI = 'fr_FR';
|
||||
// Langues de contenu
|
||||
|
||||
// Espace, contenu sélectionné
|
||||
public static $siteContent = 'home';
|
||||
// Progression d'un participant
|
||||
// public static $userProgress = '';
|
||||
|
||||
public static $languages = [
|
||||
'de' => 'Deutsch',
|
||||
'en_EN' => 'English',
|
||||
@ -319,31 +323,57 @@ class common
|
||||
public function __construct()
|
||||
{
|
||||
|
||||
// Construct cache
|
||||
if (isset($GLOBALS['common_construct'])) {
|
||||
$this->input['_POST'] = $GLOBALS['common_construct']['input']['_POST'];
|
||||
$this->input['_COOKIE'] = $GLOBALS['common_construct']['input']['_COOKIE'];
|
||||
self::$siteContent = $GLOBALS['common_construct']['siteContent'];
|
||||
$this->dataFiles = $GLOBALS['common_construct']['dataFiles'];
|
||||
$this->configFiles = $GLOBALS['common_construct']['configFiles'];
|
||||
$this->user = $GLOBALS['common_construct']['user'];
|
||||
self::$i18nUI = $GLOBALS['common_construct']['i18nUI'];
|
||||
$this->hierarchy = $GLOBALS['common_construct']['hierarchy'];
|
||||
$this->url = $GLOBALS['common_construct']['url'];
|
||||
self::$dialog = $GLOBALS['common_construct']['dialog'];
|
||||
return;
|
||||
}
|
||||
|
||||
// Extraction des données http
|
||||
if (isset($_POST)) {
|
||||
$this->input['_POST'] = $_POST;
|
||||
// Cache
|
||||
$GLOBALS['common_construct']['input']['_POST'] = $this->input['_POST'];
|
||||
}
|
||||
if (isset($_COOKIE)) {
|
||||
$this->input['_COOKIE'] = $_COOKIE;
|
||||
// Cache
|
||||
$GLOBALS['common_construct']['input']['_COOKIE'] = $this->input['_COOKIE'];
|
||||
}
|
||||
|
||||
// Extraction de la sesion
|
||||
// $this->input['_SESSION'] = $_SESSION;
|
||||
|
||||
// Déterminer le contenu du site
|
||||
if (isset($_SESSION['ZWII_SITE_CONTENT'])) {
|
||||
// Déterminé par la session présente
|
||||
self::$siteContent = $_SESSION['ZWII_SITE_CONTENT'];
|
||||
} else {
|
||||
$_SESSION['ZWII_SITE_CONTENT'] = 'home';
|
||||
self::$siteContent = 'home';
|
||||
}
|
||||
// Cache
|
||||
$GLOBALS['common_construct']['siteContent'] = self::$siteContent;
|
||||
|
||||
// Instanciation de la classe des entrées / sorties
|
||||
// Les fichiers de configuration
|
||||
foreach ($this->configFiles as $module => $value) {
|
||||
$this->initDB($module);
|
||||
}
|
||||
// Cache
|
||||
$GLOBALS['common_construct']['configFiles'] = $this->configFiles;
|
||||
// Les fichiers des contenus
|
||||
foreach ($this->contentFiles as $module => $value) {
|
||||
$this->initDB($module, self::$siteContent);
|
||||
}
|
||||
// Cache
|
||||
$GLOBALS['common_construct']['dataFiles'] = $this->dataFiles;
|
||||
|
||||
|
||||
// Installation fraîche, initialisation de la configuration inexistante
|
||||
@ -370,6 +400,8 @@ class common
|
||||
if ($this->user === []) {
|
||||
$this->user = $this->getData(['user', $this->getInput('ZWII_USER_ID')]);
|
||||
}
|
||||
// Cache
|
||||
$GLOBALS['common_construct']['user'] = $this->user;
|
||||
|
||||
// Langue de l'administration si le user est connecté
|
||||
if ($this->getData(['user', $this->getUser('id'), 'language'])) {
|
||||
@ -380,25 +412,29 @@ class common
|
||||
? self::$i18nUI
|
||||
: 'fr_FR';
|
||||
} else {
|
||||
if (isset($_SESSION['ZWII_UI'])) {
|
||||
self::$i18nUI = $_SESSION['ZWII_UI'];
|
||||
} elseif (isset($_COOKIE['ZWII_UI'])) {
|
||||
self::$i18nUI = $_COOKIE['ZWII_UI'];
|
||||
// Par défaut la langue définie par défaut à l'installation
|
||||
if ($this->getData(['config','defaultLanguageUI'])) {
|
||||
self::$i18nUI = $this->getData(['config','defaultLanguageUI']);
|
||||
} else {
|
||||
self::$i18nUI = 'fr_FR';
|
||||
$this->setData(['config','defaultLanguageUI', 'fr_FR']);
|
||||
}
|
||||
$_SESSION['ZWII_UI'] = self::$i18nUI;
|
||||
}
|
||||
|
||||
// Stocker le cookie de langue pour l'éditeur de texte ainsi que l'url du contenu pour le theme
|
||||
setcookie('ZWII_UI', self::$i18nUI, time() + 3600, '', '', false, false);
|
||||
// Stocker l'courseId pour le thème de TinyMCE
|
||||
setcookie('ZWII_SITE_CONTENT', self::$siteContent, time() + 3600, '', '', false, false);
|
||||
//setcookie('ZWII_SITE_CONTENT', self::$siteContent, time() + 3600, '', '', false, false);
|
||||
setlocale(LC_ALL, self::$i18nUI);
|
||||
// Cache
|
||||
$GLOBALS['common_construct']['i18nUI'] = self::$i18nUI;
|
||||
|
||||
// Construit la liste des pages parents/enfants
|
||||
if ($this->hierarchy['all'] === []) {
|
||||
$this->buildHierarchy();
|
||||
}
|
||||
// Cache
|
||||
$GLOBALS['common_construct']['hierarchy'] = $this->hierarchy;
|
||||
|
||||
// Construit l'url
|
||||
if ($this->url === '') {
|
||||
@ -408,6 +444,8 @@ class common
|
||||
$this->url = $this->homePageId();
|
||||
}
|
||||
}
|
||||
// Cache
|
||||
$GLOBALS['common_construct']['url'] = $this->url;
|
||||
|
||||
// Chargement des dialogues
|
||||
if (!file_exists(self::I18N_DIR . self::$i18nUI . '.json')) {
|
||||
@ -427,6 +465,8 @@ class common
|
||||
self::$dialog = array_merge(self::$dialog, $d);
|
||||
}
|
||||
}
|
||||
// Cache
|
||||
$GLOBALS['common_construct']['dialog'] = self::$dialog;
|
||||
|
||||
// Données de proxy
|
||||
$proxy = $this->getData(['config', 'proxyType']) . $this->getData(['config', 'proxyUrl']) . ':' . $this->getData(['config', 'proxyPort']);
|
||||
@ -454,8 +494,6 @@ class common
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Ajoute les valeurs en sortie
|
||||
* @param array $output Valeurs en sortie
|
||||
@ -515,8 +553,10 @@ class common
|
||||
/**
|
||||
* Sauvegarde des données
|
||||
* @param array $keys Clé(s) des données
|
||||
* @param bool $save Indique si le fichier doit être sauvegardé après modification (par défaut true)
|
||||
* @return bool Succès de l'opération
|
||||
*/
|
||||
public function setData($keys = [])
|
||||
public function setData($keys = [], $save = true)
|
||||
{
|
||||
// Pas d'enregistrement lorsqu'une notice est présente ou tableau transmis vide
|
||||
if (
|
||||
@ -544,11 +584,12 @@ class common
|
||||
$query .= '.' . $keys[$i];
|
||||
}
|
||||
// Appliquer la modification, le dernier élément étant la donnée à sauvegarder
|
||||
$success = is_object($db->set($query, $keys[count($keys) - 1], true));
|
||||
$success = is_object($db->set($query, $keys[count($keys) - 1], $save));
|
||||
}
|
||||
return $success;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Accède aux données
|
||||
* @param array $keys Clé(s) des données
|
||||
@ -592,13 +633,13 @@ class common
|
||||
/**
|
||||
* Ecrire les données de la page
|
||||
* @param string pageId
|
||||
* @param string contenu de la page
|
||||
* @param array contenu de la page
|
||||
* @return int nombre d'octets écrits ou erreur
|
||||
*/
|
||||
public function setPage($page, $value, $path)
|
||||
{
|
||||
|
||||
return file_put_contents(self::DATA_DIR . $path . '/content/' . $page . '.html', $value);
|
||||
return $this->secure_file_put_contents(self::DATA_DIR . $path . '/content/' . $page . '.html', $value);
|
||||
}
|
||||
|
||||
|
||||
@ -614,18 +655,74 @@ class common
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Écrit les données dans un fichier avec plusieurs tentatives d'écriture et verrouillage
|
||||
*
|
||||
* @param string $filename Le nom du fichier
|
||||
* @param string $data Les données à écrire dans le fichier
|
||||
* @param int $flags Les drapeaux optionnels à passer à la fonction $this->secure_file_put_contents
|
||||
* @return bool True si l'écriture a réussi, sinon false
|
||||
*/
|
||||
function secure_file_put_contents($filename, $data, $flags = 0)
|
||||
{
|
||||
|
||||
// Initialise le compteur de tentatives
|
||||
$attempts = 0;
|
||||
|
||||
// Vérifie la longueur des données
|
||||
$data_length = strlen($data);
|
||||
|
||||
// Effectue jusqu'à 5 tentatives d'écriture
|
||||
while ($attempts < 5) {
|
||||
// Essaye d'écrire les données dans le fichier avec verrouillage exclusif
|
||||
$write_result = file_put_contents($filename, $data, LOCK_EX | $flags);
|
||||
|
||||
// $now = \DateTime::createFromFormat('U.u', microtime(true));
|
||||
// file_put_contents("tmplog.txt", '[SecurePut][' . $now->format('H:i:s.u') . ']' . "\r\n", FILE_APPEND);
|
||||
|
||||
// Vérifie si l'écriture a réussi
|
||||
if ($write_result !== false && $write_result === $data_length) {
|
||||
// Sort de la boucle si l'écriture a réussi
|
||||
break;
|
||||
}
|
||||
|
||||
// Incrémente le compteur de tentatives
|
||||
$attempts++;
|
||||
sleep(1);
|
||||
}
|
||||
// Etat de l'écriture
|
||||
return ($attempts < 5);
|
||||
}
|
||||
|
||||
public function initDB($module, $path = '')
|
||||
{
|
||||
// Instanciation de la classe des entrées / sorties
|
||||
// Constructeur JsonDB;
|
||||
$this->dataFiles[$module] = new \Prowebcraft\JsonDb([
|
||||
// Chemin complet vers le fichier JSON
|
||||
$dir = empty($path) ? self::DATA_DIR : self::DATA_DIR . $path . '/';
|
||||
$config = [
|
||||
'name' => $module . '.json',
|
||||
'dir' => self::DATA_DIR . $path . '/',
|
||||
'backup' => file_exists('site/data/.backup')
|
||||
]);
|
||||
'dir' => $dir,
|
||||
'backup' => file_exists('site/data/.backup'),
|
||||
'update' => false,
|
||||
];
|
||||
|
||||
// Instanciation de l'objet et stockage dans dataFiles
|
||||
$this->dataFiles[$module] = new \Prowebcraft\JsonDb($config);
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Cette fonction est liée à saveData
|
||||
* @param mixed $module
|
||||
* @return void
|
||||
*/
|
||||
public function saveDB($module): void
|
||||
{
|
||||
$db = $this->dataFiles[$module];
|
||||
$db->save();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Initialisation des données sur un contenu ou la page d'accueil
|
||||
* @param string $course : id du module à générer
|
||||
@ -708,7 +805,7 @@ class common
|
||||
* Fonction pour construire le tableau des pages
|
||||
*/
|
||||
|
||||
private function buildHierarchy()
|
||||
public function buildHierarchy()
|
||||
{
|
||||
|
||||
$pages = helper::arrayColumn($this->getData(['page']), 'position', 'SORT_ASC');
|
||||
@ -716,10 +813,10 @@ class common
|
||||
foreach ($pages as $pageId => $pagePosition) {
|
||||
if (
|
||||
// Page parent
|
||||
$this->getData(['page', $pageId, 'parentPageId']) === ''
|
||||
$this->getData(['page', $pageId, 'parentPageId']) === ""
|
||||
// Ignore les pages dont l'utilisateur n'a pas accès
|
||||
and ($this->getData(['page', $pageId, 'group']) === self::GROUP_VISITOR
|
||||
or ($this->getUser('password') === $this->getInput('ZWII_USER_PASSWORD')
|
||||
or ($this->getUser('authKey') === $this->getInput('ZWII_AUTH_KEY')
|
||||
//and $this->getUser('group') >= $this->getData(['page', $pageId, 'group'])
|
||||
// Modification qui tient compte du profil de la page
|
||||
and ($this->getUser('group') * self::MAX_PROFILS + $this->getUser('profil')) >= ($this->getData(['page', $pageId, 'group']) * self::MAX_PROFILS + $this->getData(['page', $pageId, 'profil']))
|
||||
@ -738,21 +835,21 @@ class common
|
||||
}
|
||||
// Enfants
|
||||
foreach ($pages as $pageId => $pagePosition) {
|
||||
|
||||
if (
|
||||
// Page parent
|
||||
$parentId = $this->getData(['page', $pageId, 'parentPageId'])
|
||||
// Ignore les pages dont l'utilisateur n'a pas accès
|
||||
and (
|
||||
($this->getData(['page', $pageId, 'group']) === self::GROUP_VISITOR
|
||||
and $this->getData(['page', $parentId, 'group']) === self::GROUP_VISITOR
|
||||
(
|
||||
$this->getData(['page', $pageId, 'group']) === self::GROUP_VISITOR
|
||||
and
|
||||
$this->getData(['page', $parentId, 'group']) === self::GROUP_VISITOR
|
||||
)
|
||||
or ($this->getUser('password') === $this->getInput('ZWII_USER_PASSWORD')
|
||||
//and $this->getUser('group') >= $this->getData(['page', $parentId, 'group'])
|
||||
//and $this->getUser('group') >= $this->getData(['page', $pageId, 'group'])
|
||||
|
||||
// Modification qui tient compte du profil de la page
|
||||
and ($this->getUser('group') * self::MAX_PROFILS + $this->getUser('profil')) >= ($this->getData(['page', $this->$parentId, 'group']) * self::MAX_PROFILS + $this->getData(['page', $this->$parentId, 'profil']))
|
||||
and ($this->getUser('group') * self::MAX_PROFILS + $this->getUser('profil')) >= ($this->getData(['page', $this->$pageId, 'group']) * self::MAX_PROFILS + $this->getData(['page', $pageId, 'profil']))
|
||||
or (
|
||||
$this->getUser('authKey') === $this->getInput('ZWII_AUTH_KEY')
|
||||
and
|
||||
$this->getUser('group') * self::MAX_PROFILS + $this->getUser('profil')) >= ($this->getData(['page', $pageId, 'group']) * self::MAX_PROFILS + $this->getData(['page', $pageId, 'profil'])
|
||||
|
||||
)
|
||||
)
|
||||
@ -976,6 +1073,17 @@ class common
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return bool l'utilisateur est connecté true sinon false
|
||||
*/
|
||||
public function isConnected()
|
||||
{
|
||||
return (
|
||||
!empty($this->getUser('authKey'))
|
||||
&&
|
||||
$this->getUser('authKey') === $this->getInput('ZWII_AUTH_KEY'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Check qu'une valeur est transmise par la méthode _POST
|
||||
* @return bool
|
||||
@ -1066,8 +1174,9 @@ class common
|
||||
}
|
||||
// Articles du blog
|
||||
if (
|
||||
$this->getData(['page', $parentPageId, 'moduleId']) === 'blog' &&
|
||||
!empty($this->getData(['module', $parentPageId]))
|
||||
$this->getData(['page', $parentPageId, 'moduleId']) === 'blog'
|
||||
&& !empty($this->getData(['module', $parentPageId]))
|
||||
&& $this->getData(['module', $parentPageId, 'posts'])
|
||||
) {
|
||||
foreach ($this->getData(['module', $parentPageId, 'posts']) as $articleId => $article) {
|
||||
if ($this->getData(['module', $parentPageId, 'posts', $articleId, 'state']) === true) {
|
||||
@ -1164,8 +1273,7 @@ class common
|
||||
$source_image = imagecreatefromwebp($src);
|
||||
break;
|
||||
case 'avif':
|
||||
$source_image = function_exists('imagecreatefromavif') ? imagecreatefromavif($src) : null;
|
||||
break;
|
||||
$source_image = imagecreatefromavif($src);
|
||||
}
|
||||
// Image valide
|
||||
if ($source_image) {
|
||||
@ -1185,9 +1293,9 @@ class common
|
||||
return (imagepng($virtual_image, $dest));
|
||||
case 'image/gif':
|
||||
return (imagegif($virtual_image, $dest));
|
||||
case 'webp':
|
||||
case 'image/webp':
|
||||
return (imagewebp($virtual_image, $dest));
|
||||
case 'avif':
|
||||
case 'image/avif':
|
||||
return (imageavif($virtual_image, $dest));
|
||||
}
|
||||
} else {
|
||||
@ -1405,7 +1513,7 @@ class common
|
||||
public function saveLog($message = '')
|
||||
{
|
||||
// Journalisation
|
||||
$dataLog = helper::dateUTF8('%Y%m%d', time(), self::$siteContent) . ';' . helper::dateUTF8('%H:%M', time(), self::$siteContent) . ';';
|
||||
$dataLog = helper::dateUTF8('%Y%m%d', time(), self::$i18nUI) . ';' . helper::dateUTF8('%H:%M', time(), self::$i18nUI) . ';';
|
||||
$dataLog .= helper::getIp($this->getData(['config', 'connect', 'anonymousIp'])) . ';';
|
||||
$dataLog .= empty($this->getUser('id')) ? 'visitor;' : $this->getUser('id') . ';';
|
||||
$dataLog .= $message ? $this->getUrl() . ';' . $message : $this->getUrl();
|
||||
@ -1422,39 +1530,39 @@ class common
|
||||
* @param string $userId identifiant
|
||||
* @param string $serStatus teacher ou student ou admin
|
||||
*
|
||||
* CETTE FONCTION N'EST PAS UTILISEE
|
||||
* CETTE FONCTION EST UTILISEE PAR LAYOUT
|
||||
*
|
||||
*/
|
||||
public function getCoursesByUser()
|
||||
public function getCoursesByProfil()
|
||||
{
|
||||
$courses = $this->getData([('course')]);
|
||||
$courses = helper::arraycolumn($courses, 'title', 'SORT_ASC');
|
||||
$filter = array();
|
||||
$userId = $this->getUser('id');
|
||||
switch ($this->getUser('group')) {
|
||||
case self::GROUP_ADMIN:
|
||||
// Affiche tout
|
||||
return $courses;
|
||||
case self::GROUP_EDITOR:
|
||||
foreach ($courses as $courseId => $value) {
|
||||
$students = $this->getData(['enrolment', $courseId]);
|
||||
// Affiche les espaces gérés par l'éditeur, les espaces où il participe et les espaces ouverts
|
||||
// Affiche les espaces gérés par l'éditeur, les espaces où il participe et les espaces anonymes
|
||||
if (
|
||||
isset($students[$userId]) === true ||
|
||||
$this->getData(['course', $courseId, 'author']) === $userId ||
|
||||
$this->getData(['course', $courseId, 'enrolment']) === self::COURSE_ENROLMENT_GUEST
|
||||
// le membre est inscrit
|
||||
($this->getData(['enrolment', $courseId]) && array_key_exists($this->getUser('id'), $this->getData(['enrolment', $courseId])))
|
||||
// Il est l'auteur
|
||||
|| $this->getUser('id') === $this->getData(['course', $courseId, 'author'])
|
||||
// Le cours est ouvert
|
||||
|| $this->getData(['course', $courseId, 'enrolment']) === self::COURSE_ENROLMENT_GUEST
|
||||
) {
|
||||
$filter[$courseId] = $courses[$courseId];
|
||||
}
|
||||
}
|
||||
return $courses;
|
||||
return $filter;
|
||||
case self::GROUP_MEMBER:
|
||||
foreach ($courses as $courseId => $value) {
|
||||
// Affiche les espaces du participant et les espaces anonymes
|
||||
$students = $this->getData(['enrolment', $courseId]);
|
||||
if (
|
||||
isset($students[$userId]) === true ||
|
||||
$this->getData(['course', $courseId, 'enrolment']) === self::COURSE_ENROLMENT_GUEST
|
||||
($this->getData(['enrolment', $courseId]) && array_key_exists($this->getUser('id'), $this->getData(['enrolment', $courseId])))
|
||||
|| $this->getData(['course', $courseId, 'enrolment']) === self::COURSE_ENROLMENT_GUEST
|
||||
) {
|
||||
$filter[$courseId] = $courses[$courseId];
|
||||
}
|
||||
@ -1464,7 +1572,6 @@ class common
|
||||
foreach ($courses as $courseId => $value) {
|
||||
// Affiche les espaces anonymes
|
||||
if ($this->getData(['course', $courseId, 'enrolment']) === self::COURSE_ENROLMENT_GUEST) {
|
||||
echo $this->getData(['course', $courseId, 'access']) ;
|
||||
$filter[$courseId] = $courses[$courseId];
|
||||
}
|
||||
}
|
||||
|
@ -1,5 +1,48 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Mises à jour suivant les versions de Zwii
|
||||
* Mises à jour suivant les versions de ZwiiCampus
|
||||
*/
|
||||
|
||||
|
||||
if (
|
||||
$this->getData(['core', 'dataVersion']) < 1700
|
||||
) {
|
||||
// Supprime la variable path des profils, seul l'accès à l'espace et autorisé.
|
||||
foreach (['1', '2'] as $group) {
|
||||
foreach (array_keys($this->getData(['profil', $group])) as $profil) {
|
||||
if (is_null($this->getData(['profil', $group, $profil, 'folder', 'path'])) === false) {
|
||||
$path = $this->getData(['profil', $group, $profil, 'folder', 'path']);
|
||||
$this->setData(['profil', $group, $profil, 'folder', 'homePath', $path]);
|
||||
$this->setData(['profil', $group, $profil, 'folder', 'coursePath', $path]);
|
||||
$this->deleteData(['profil', $group, $profil, 'folder', 'path']);
|
||||
}
|
||||
}
|
||||
}
|
||||
$this->setData(['core', 'dataVersion', 1700]);
|
||||
}
|
||||
|
||||
|
||||
if (
|
||||
$this->getData(['core', 'dataVersion']) < 1800
|
||||
) {
|
||||
// Parcourir la structure pour écrire dans les fichiers CSV
|
||||
foreach ($this->getData(['enrolment']) as $courseId => $users) {
|
||||
$filename = self::DATA_DIR . $courseId . '/report.csv';
|
||||
$fp = fopen($filename, 'w');
|
||||
foreach ($users as $userId => $userData) {
|
||||
$history = array_key_exists('history', $userData) ? $userData['history'] : null;
|
||||
|
||||
if (is_array($history)) {
|
||||
foreach ($history as $pageId => $timestamps) {
|
||||
foreach ($timestamps as $timestamp) {
|
||||
fputcsv($fp, [$userId, $pageId, $timestamp], ';');
|
||||
}
|
||||
}
|
||||
}
|
||||
$this->deleteData(['enrolment', $courseId, $userId, 'history']);
|
||||
}
|
||||
fclose($fp);
|
||||
}
|
||||
$this->setData(['core', 'dataVersion', 1800]);
|
||||
}
|
@ -2,7 +2,7 @@
|
||||
<html prefix="og: http://ogp.me/ns#" lang="fr_FR">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta http-equiv="content-type" content="text/html; charset=UTF-8">
|
||||
<meta http-equiv="content-type" content="text/html;">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<?php $layout->showMetaTitle(); ?>
|
||||
<?php $layout->showMetaDescription(); ?>
|
||||
|
@ -118,7 +118,7 @@ h3 {
|
||||
font-size: 1.4em;
|
||||
}
|
||||
|
||||
h4 {
|
||||
h4, details {
|
||||
font-size: 1.0em;
|
||||
}
|
||||
|
||||
@ -161,7 +161,8 @@ h4,
|
||||
p,
|
||||
hr,
|
||||
ul,
|
||||
ol {
|
||||
ol,
|
||||
details {
|
||||
margin: 15px 0;
|
||||
}
|
||||
|
||||
@ -1127,7 +1128,7 @@ footer #footerSocials .zwiico-twitch:hover {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
.block h4 {
|
||||
.block h4, details {
|
||||
margin: -20px -20px 10px -20px;
|
||||
padding: 10px;
|
||||
/* background: #ECEFF1;*/
|
||||
|
@ -2,7 +2,7 @@
|
||||
<html prefix="og: http://ogp.me/ns#" lang="fr_FR">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta http-equiv="content-type" content="text/html; charset=UTF-8">
|
||||
<meta http-equiv="content-type" content="text/html;">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<?php $layout->showMetaTitle(); ?>
|
||||
<?php $layout->showMetaDescription(); ?>
|
||||
|
@ -2,7 +2,7 @@
|
||||
<html xmlns="http://www.w3.org/1999/xhtml" lang="fr_FR">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta http-equiv="content-type" content="text/html; charset=UTF-8">
|
||||
<meta http-equiv="content-type" content="text/html;">
|
||||
<meta name="viewport" content="width=device-width">
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
||||
<meta name="x-apple-disable-message-reformatting">
|
||||
|
@ -2,7 +2,7 @@
|
||||
<html prefix="og: http://ogp.me/ns#" lang="fr_FR">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta http-equiv="content-type" content="text/html; charset=UTF-8">
|
||||
<meta http-equiv="content-type" content="text/html;">
|
||||
<meta meta="description=" content="ZwiiCMS le CMS multilingue sans base de données">
|
||||
<meta name="generator" content="ZiiCMS https://forge.chapril.org/ZwiiCMS-Team/ZwiiCMS">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
@ -47,7 +47,7 @@
|
||||
if (
|
||||
$this->getData(['theme', 'menu', 'position']) === 'top'
|
||||
and $this->getData(['theme', 'menu', 'fixed']) === true
|
||||
and $this->getUser('password') === $this->getInput('ZWII_USER_PASSWORD')
|
||||
and $this->isConnected() === true
|
||||
and $this->getUser('group') > self::GROUP_MEMBER
|
||||
) {
|
||||
echo '<nav id="navfixedconnected" >';
|
||||
|
@ -22,7 +22,7 @@ class config extends common
|
||||
'copyBackups' => self::GROUP_ADMIN,
|
||||
'delBackups' => self::GROUP_ADMIN,
|
||||
'configMetaImage' => self::GROUP_ADMIN,
|
||||
'siteMap' => self::GROUP_ADMIN,
|
||||
'sitemap' => self::GROUP_ADMIN,
|
||||
'index' => self::GROUP_ADMIN,
|
||||
'restore' => self::GROUP_ADMIN,
|
||||
'updateBaseUrl' => self::GROUP_ADMIN,
|
||||
@ -30,7 +30,8 @@ class config extends common
|
||||
'logReset' => self::GROUP_ADMIN,
|
||||
'logDownload' => self::GROUP_ADMIN,
|
||||
'blacklistReset' => self::GROUP_ADMIN,
|
||||
'blacklistDownload' => self::GROUP_ADMIN
|
||||
'blacklistDownload' => self::GROUP_ADMIN,
|
||||
'register' => self::GROUP_ADMIN,
|
||||
];
|
||||
|
||||
public static $timezones = [
|
||||
@ -213,7 +214,7 @@ class config extends common
|
||||
* Sitemap compressé et non compressé
|
||||
* Robots.txt
|
||||
*/
|
||||
public function siteMap()
|
||||
public function sitemap()
|
||||
{
|
||||
// La page n'existe pas
|
||||
if (
|
||||
@ -429,6 +430,17 @@ class config extends common
|
||||
*/
|
||||
public function index()
|
||||
{
|
||||
|
||||
// Action interdite hors de l'espace accueil
|
||||
if (
|
||||
self::$siteContent !== 'home'
|
||||
) {
|
||||
// Valeurs en sortie
|
||||
$this->addOutput([
|
||||
'access' => false
|
||||
]);
|
||||
}
|
||||
|
||||
// Soumission du formulaire
|
||||
if (
|
||||
$this->getUser('permission', __CLASS__, __FUNCTION__) === true &&
|
||||
@ -479,7 +491,7 @@ class config extends common
|
||||
'cookiesFooterText' => $this->getInput('configLocaleCookiesFooterText', helper::FILTER_STRING_SHORT, $this->getInput('configCookieConsent', helper::FILTER_BOOLEAN)),
|
||||
'buttonValidLabel' => $this->getInput('configLocaleCookiesButtonText', helper::FILTER_STRING_SHORT, $this->getInput('configCookieConsent', helper::FILTER_BOOLEAN)),
|
||||
],
|
||||
'social' => [
|
||||
'social' => [
|
||||
'facebookId' => $this->getInput('socialFacebookId'),
|
||||
'linkedinId' => $this->getInput('socialLinkedinId'),
|
||||
'instagramId' => $this->getInput('socialInstagramId'),
|
||||
@ -517,7 +529,8 @@ class config extends common
|
||||
'autoDisconnect' => $this->getInput('connectAutoDisconnect', helper::FILTER_BOOLEAN),
|
||||
'captchaType' => $this->getInput('connectCaptchaType'),
|
||||
'showPassword' => $this->getInput('connectShowPassword', helper::FILTER_BOOLEAN),
|
||||
'redirectLogin' => $this->getInput('connectRedirectLogin', helper::FILTER_BOOLEAN)
|
||||
'redirectLogin' => $this->getInput('connectRedirectLogin', helper::FILTER_BOOLEAN),
|
||||
'mailAuth' => $this->getInput('connectAuthMail', helper::FILTER_BOOLEAN),
|
||||
]
|
||||
]
|
||||
]);
|
||||
@ -545,7 +558,7 @@ class config extends common
|
||||
) {
|
||||
// Ajout des lignes dans le .htaccess
|
||||
$fileContent = file_get_contents('.htaccess');
|
||||
$rewriteData = PHP_EOL .
|
||||
$rewriteData =
|
||||
'# URL rewriting' . PHP_EOL .
|
||||
'<IfModule mod_rewrite.c>' . PHP_EOL .
|
||||
"\tRewriteEngine on" . PHP_EOL .
|
||||
@ -554,7 +567,7 @@ class config extends common
|
||||
"\tRewriteCond %{REQUEST_FILENAME} !-d" . PHP_EOL .
|
||||
"\tRewriteRule ^(.*)$ index.php?$1 [L]" . PHP_EOL .
|
||||
'</IfModule>' . PHP_EOL .
|
||||
'# URL rewriting' . PHP_EOL;
|
||||
'# URL rewriting';
|
||||
$fileContent = str_replace('# URL rewriting', $rewriteData, $fileContent);
|
||||
file_put_contents(
|
||||
'.htaccess',
|
||||
@ -581,7 +594,7 @@ class config extends common
|
||||
}
|
||||
}
|
||||
// Générer robots.txt et sitemap
|
||||
$this->siteMap();
|
||||
$this->sitemap();
|
||||
// Valeurs en sortie
|
||||
$this->addOutput([
|
||||
'title' => helper::translate('Configuration'),
|
||||
@ -946,4 +959,40 @@ class config extends common
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Fonction pour vérifier la présence du module de réécriture
|
||||
* @return bool
|
||||
*/
|
||||
public function isModRewriteEnabled() {
|
||||
// Check if Apache and mod_rewrite is loaded
|
||||
if (function_exists('apache_get_modules')) {
|
||||
$modules = apache_get_modules();
|
||||
return in_array('mod_rewrite', $modules);
|
||||
} else {
|
||||
// Fallback if not using Apache or unable to detect modules
|
||||
return getenv('HTTP_MOD_REWRITE') == 'On' || getenv('REDIRECT_STATUS') == '200';
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 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',
|
||||
[
|
||||
'config' => $this->getUrl(2),
|
||||
'page' => $this->getData(['user', $this->getUser('id'), 'view', 'page']),
|
||||
]
|
||||
]);
|
||||
// Valeurs en sortie
|
||||
$this->addOutput([
|
||||
'redirect' => helper::baseUrl() . 'config/' . $this->getUrl(2),
|
||||
]);
|
||||
}
|
||||
}
|
4
core/module/config/tool/.htaccess
Normal file
4
core/module/config/tool/.htaccess
Normal file
@ -0,0 +1,4 @@
|
||||
<Files "data.key">
|
||||
Order Allow,Deny
|
||||
Deny from all
|
||||
</Files>
|
68
core/module/config/tool/autobackup.php
Normal file
68
core/module/config/tool/autobackup.php
Normal file
@ -0,0 +1,68 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
Ce script PHP est conçu pour être appelé via une requête HTTP GET avec une clé spécifique pour déclencher la création d'une archive ZIP de sauvegarde.
|
||||
|
||||
Exemple d'appel dans une URL :
|
||||
http://example.com/chemin/vers/autobackup.php?key=your_secret_key&filter=site
|
||||
|
||||
La clé doit être fournie en tant que paramètre "key" dans l'URL et correspondre à celle stockée dans le fichier "data.key" pour que la création de l'archive soit autorisée. Si la clé est valide, le script parcourt le répertoire spécifié en fonction du paramètre "filter" et ajoute les fichiers à l'archive ZIP. Si la clé est invalide ou absente, le script renvoie une réponse avec le code d'erreur 401 Unauthorized.
|
||||
|
||||
Le paramètre "filter" en GET permet de spécifier le filtre à appliquer lors de la création de l'archive. Sa valeur peut être "file" ou "data". Si le paramètre n'est pas spécifié, le filtre est vide par défaut, ce qui signifie que tous les fichiers seront inclus dans l'archive.
|
||||
|
||||
*/
|
||||
|
||||
// Vérification de la clé
|
||||
if (isset($_GET['key'])) {
|
||||
$key = $_GET['key'];
|
||||
$storedKey = file_get_contents('data.key');
|
||||
if ($key !== $storedKey) {
|
||||
http_response_code(401); // Clé invalide, renvoie une réponse avec le code d'erreur 401 Unauthorized
|
||||
echo 'Clé incorrecte';
|
||||
exit;
|
||||
}
|
||||
|
||||
// Définition du filtre par défaut
|
||||
$filter = ['backup', 'tmp', 'i18n'];
|
||||
|
||||
// Tableau de correspondance entre les valeurs de "filter" et les répertoires à inclure
|
||||
$filterDirectories = [
|
||||
'file' => ['backup', 'tmp', 'file'],
|
||||
'data' => ['backup', 'tmp', 'data'],
|
||||
];
|
||||
|
||||
// Vérification et traitement du paramètre "filter" en GET
|
||||
if (isset($_GET['filter']) && isset($filterDirectories[$_GET['filter']])) {
|
||||
$filter = $filterDirectories[$_GET['filter']];
|
||||
}
|
||||
|
||||
// Création du ZIP
|
||||
$fileName = date('Y-m-d-H-i-s', time()) . '-rolling-backup.zip';
|
||||
$zip = new ZipArchive();
|
||||
$zip->open('../../../../site/backup/' . $fileName, ZipArchive::CREATE | ZipArchive::OVERWRITE);
|
||||
$directory = '../../../../site';
|
||||
$files = new RecursiveIteratorIterator(
|
||||
new RecursiveCallbackFilterIterator(
|
||||
new RecursiveDirectoryIterator(
|
||||
$directory,
|
||||
RecursiveDirectoryIterator::SKIP_DOTS
|
||||
),
|
||||
function ($fileInfo, $key, $iterator) use ($filter) {
|
||||
return $fileInfo->isFile() || !in_array($fileInfo->getBaseName(), $filter);
|
||||
}
|
||||
)
|
||||
);
|
||||
foreach ($files as $name => $file) {
|
||||
if (!$file->isDir()) {
|
||||
$filePath = $file->getRealPath();
|
||||
$relativePath = substr($filePath, strlen(realpath($directory)) + 1);
|
||||
$zip->addFile($filePath, $relativePath);
|
||||
}
|
||||
}
|
||||
$zip->close();
|
||||
|
||||
http_response_code(201); // Création de l'archive réussie, renvoie une réponse avec le code 201 Created
|
||||
echo 'Sauvegarde terminée';
|
||||
exit;
|
||||
}
|
||||
?>
|
52
core/module/config/tool/cleanautobackup.php
Normal file
52
core/module/config/tool/cleanautobackup.php
Normal file
@ -0,0 +1,52 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
Ce script PHP est conçu pour supprimer les fichiers ayant l'extension 'tar.gz' dans un répertoire de sauvegarde si leur dernière modification remonte à un certain nombre de jours spécifié via une requête HTTP GET.
|
||||
|
||||
Exemple d'appel dans une URL avec le nombre de jours spécifié :
|
||||
http://example.com/chemin/vers/script.php?days=7&key=your_secret_key
|
||||
|
||||
Le script vérifie également la présence et la validité d'une clé spécifique pour déclencher son exécution. La clé doit être fournie en tant que paramètre "key" dans l'URL et correspondre à celle stockée dans le fichier "data.key" pour que la suppression des fichiers soit autorisée. Si la clé est invalide ou absente, le script affiche un message d'erreur et termine son exécution.
|
||||
|
||||
*/
|
||||
|
||||
// Vérification de la clé
|
||||
if (isset ($_GET['key'])) {
|
||||
// Récupération de la clé fournie en GET
|
||||
$key = $_GET['key'];
|
||||
|
||||
// Récupération de la clé stockée dans le fichier data.key
|
||||
$storedKey = file_get_contents('data.key');
|
||||
|
||||
// Vérification de correspondance entre les clés
|
||||
if ($key !== $storedKey) {
|
||||
http_response_code(401);
|
||||
echo 'Clé incorrecte';
|
||||
exit;
|
||||
}
|
||||
|
||||
// Récupère le nombre de jours à partir de la variable GET 'days'
|
||||
$days = isset ($_GET['days']) ? (int) $_GET['days'] : 1; // Par défaut à 1 si non spécifié
|
||||
|
||||
// Chemin vers le répertoire contenant les fichiers
|
||||
$directory = '../../../../site/backup/'; // Remplacez par le chemin réel
|
||||
|
||||
// Convertit le nombre de jours en secondes
|
||||
$timeLimit = strtotime("-$days days");
|
||||
|
||||
// Crée un nouvel objet DirectoryIterator
|
||||
foreach (new DirectoryIterator($directory) as $file) {
|
||||
// Vérifie si l'élément courant est un fichier et a l'extension 'tar.gz'
|
||||
if ($file->isFile() && $file->getExtension() === 'tar.gz') {
|
||||
// Vérifie si le fichier a été modifié avant la limite de temps
|
||||
if ($file->getMTime() < $timeLimit) {
|
||||
// Supprime le fichier
|
||||
unlink($file->getRealPath());
|
||||
}
|
||||
}
|
||||
}
|
||||
// Si la clé est manquante, affiche un message d'erreur et arrête l'exécution du script
|
||||
http_response_code(201);
|
||||
echo 'Sauvegarde terminée';
|
||||
exit;
|
||||
}
|
@ -17,7 +17,8 @@
|
||||
<div class="row">
|
||||
<div class="col12">
|
||||
<div class="block">
|
||||
<h4><?php echo helper::translate('Paramètres de la sauvegarde'); ?>
|
||||
<h4>
|
||||
<?php echo helper::translate('Paramètres de la sauvegarde'); ?>
|
||||
</h4>
|
||||
<div class="row">
|
||||
<div class="col12">
|
||||
@ -27,7 +28,10 @@
|
||||
]); ?>
|
||||
</div>
|
||||
<div class="col12">
|
||||
<em>L'archive est générée dans <a href="<?php echo helper::baseUrl(false); ?>core/vendor/filemanager/dialog.php?fldr=backup&type=0&akey=<?php echo md5_file(self::DATA_DIR . 'core.json'); ?>&lang=<?php echo $this->getData(['user', $this->getUser('id'), 'language']);?>" data-lity>le dossier Backup</a> du gestionnaire de fichiers.</em>
|
||||
<em>L'archive est générée dans
|
||||
<a href="<?php echo helper::baseUrl(false); ?>core/vendor/filemanager/dialog.php?fldr=backup&type=0&akey=<?php echo md5_file(self::DATA_DIR . 'core.json'); ?>&lang=<?php echo $this->getData(['user', $this->getUser('id'), 'language']); ?>"
|
||||
data-lity>le dossier Backup</a> du gestionnaire de fichiers.
|
||||
</em>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -3,13 +3,7 @@
|
||||
<div class="col12">
|
||||
<div class="block">
|
||||
<h4><?php echo helper::translate('Sécurité de la connexion'); ?>
|
||||
<!--<span id="specialeHelpButton" class="helpDisplayButton">
|
||||
<a href="https://doc.zwiicms.fr/connexion" target="_blank" title="Cliquer pour consulter l'aide en ligne">
|
||||
<?php // echo template::ico('help', ['margin' => 'left']); ?>
|
||||
</a>
|
||||
</span>-->
|
||||
</h4>
|
||||
|
||||
<div class="row">
|
||||
<div class="col4">
|
||||
<?php echo template::checkbox('connectShowPassword', true, 'Dévoiler le mot de passe', [
|
||||
@ -31,44 +25,36 @@
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col3">
|
||||
<div class="col4">
|
||||
<?php echo template::select('connectAttempt', $module::$connectAttempt, [
|
||||
'label' => 'Limitation des tentatives',
|
||||
'selected' => $this->getData(['config', 'connect', 'attempt'])
|
||||
]); ?>
|
||||
</div>
|
||||
<div class="col3">
|
||||
<div class="col4">
|
||||
<?php echo template::select('connectTimeout', $module::$connectTimeout, [
|
||||
'label' => 'Blocage après échecs',
|
||||
'selected' => $this->getData(['config', 'connect', 'timeout'])
|
||||
]); ?>
|
||||
</div>
|
||||
<div class="col3 verticalAlignBottom">
|
||||
<label id="helpBlacklist"><?php echo helper::translate('Liste noire'); ?>
|
||||
<?php echo template::help(
|
||||
'La liste noire énumère les tentatives de connexion à partir de comptes inexistants. Sont stockés : la date, l\'heure, le nom du compte et l\'IP.
|
||||
Après le nombre de tentatives autorisées, l\'IP et le compte sont bloqués.'
|
||||
);
|
||||
?>
|
||||
</label>
|
||||
<?php echo template::button('ConnectBlackListDownload', [
|
||||
'href' => helper::baseUrl() . 'config/blacklistDownload',
|
||||
'value' => 'Télécharger la liste',
|
||||
'ico' => 'download'
|
||||
]); ?>
|
||||
</div>
|
||||
<div class="col3 verticalAlignBottom">
|
||||
<?php echo template::button('CnnectBlackListReset', [
|
||||
'class' => 'buttonRed',
|
||||
'href' => helper::baseUrl() . 'config/blacklistReset',
|
||||
'value' => 'Réinitialiser la liste',
|
||||
'ico' => 'trash'
|
||||
<div class="col4">
|
||||
<?php echo template::select('connectAuthMail', array_merge([''=>'Aucune'], self::$groupNews), [
|
||||
'label' => 'Validation par messagerie ⚠️',
|
||||
'selected' => $this->getData(['config', 'connect', 'mailAuth']),
|
||||
'help' => 'La connexion est confirmée par une clé transmise par messagerie. Depuis le groupe sélectionnée et les groupes supérieurs. Vérifiez le bon fonctionnement du serveur de messagerie AVANT d\'activer cette option!'
|
||||
]); ?>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col12">
|
||||
<div class="block">
|
||||
<h4><?php echo helper::translate('Captcha à la connexion'); ?>
|
||||
</h4>
|
||||
<div class="row">
|
||||
<div class="col3">
|
||||
<?php echo template::checkbox('connectCaptcha', true, 'Captcha à la connexion', [
|
||||
<?php echo template::checkbox('connectCaptcha', true, 'Activer', [
|
||||
'checked' => $this->getData(['config', 'connect', 'captcha'])
|
||||
]); ?>
|
||||
</div>
|
||||
@ -92,40 +78,66 @@
|
||||
<div class="col12">
|
||||
<div class="block">
|
||||
<h4><?php echo helper::translate('Journalisation'); ?>
|
||||
<!--<span id="specialeHelpButton" class="helpDisplayButton">
|
||||
<a href="https://doc.zwiicms.fr/journalisation" target="_blank" title="Cliquer pour consulter l'aide en ligne">
|
||||
<?php // echo template::ico('help', ['margin' => 'left']); ?>
|
||||
</a>
|
||||
</span>
|
||||
-->
|
||||
</h4>
|
||||
<div class="row">
|
||||
<div class="col3">
|
||||
<?php echo template::checkbox('connectLog', true, 'Activer la journalisation', [
|
||||
'checked' => $this->getData(['config', 'connect', 'log'])
|
||||
]); ?>
|
||||
<div class="col6">
|
||||
<div class="row">
|
||||
<div class="col6">
|
||||
<?php echo template::checkbox('connectLog', true, 'Activer la journalisation', [
|
||||
'checked' => $this->getData(['config', 'connect', 'log'])
|
||||
]); ?>
|
||||
</div>
|
||||
<div class="col6">
|
||||
<?php echo template::select('connectAnonymousIp', $module::$anonIP, [
|
||||
'label' => 'Anonymat des adresses IP',
|
||||
'selected' => $this->getData(['config', 'connect', 'anonymousIp']),
|
||||
'help' => 'La règlementation française impose un anonymat de niveau 2'
|
||||
]); ?>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col6 ">
|
||||
<?php echo template::button('ConfigLogDownload', [
|
||||
'href' => helper::baseUrl() . 'config/logDownload',
|
||||
'value' => 'Télécharger le journal',
|
||||
'ico' => 'download'
|
||||
]); ?>
|
||||
</div>
|
||||
<div class="col6">
|
||||
<?php echo template::button('ConnectLogReset', [
|
||||
'class' => 'buttonRed',
|
||||
'href' => helper::baseUrl() . 'config/logReset',
|
||||
'value' => 'Réinitialiser le journal',
|
||||
'ico' => 'trash'
|
||||
]); ?>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col3">
|
||||
<?php echo template::select('connectAnonymousIp', $module::$anonIP, [
|
||||
'label' => 'Anonymat des adresses IP',
|
||||
'selected' => $this->getData(['config', 'connect', 'anonymousIp']),
|
||||
'help' => 'La règlementation française impose un anonymat de niveau 2'
|
||||
]); ?>
|
||||
</div>
|
||||
<div class="col3 verticalAlignBottom">
|
||||
<?php echo template::button('ConfigLogDownload', [
|
||||
'href' => helper::baseUrl() . 'config/logDownload',
|
||||
'value' => 'Télécharger le journal',
|
||||
'ico' => 'download'
|
||||
]); ?>
|
||||
</div>
|
||||
<div class="col3 verticalAlignBottom">
|
||||
<?php echo template::button('ConnectLogReset', [
|
||||
'class' => 'buttonRed',
|
||||
'href' => helper::baseUrl() . 'config/logReset',
|
||||
'value' => 'Réinitialiser le journal',
|
||||
'ico' => 'trash'
|
||||
]); ?>
|
||||
<div class="col6 verticalAlignBottom">
|
||||
<div class="row">
|
||||
<div class="col6 verticalAlignBottom">
|
||||
<label id="helpBlacklist"><?php echo helper::translate('Liste noire'); ?>
|
||||
<?php echo template::help(
|
||||
'La liste noire énumère les tentatives de connexion à partir de comptes inexistants. Sont stockés : la date, l\'heure, le nom du compte et l\'IP.
|
||||
Après le nombre de tentatives autorisées, l\'IP et le compte sont bloqués.'
|
||||
);
|
||||
?>
|
||||
</label>
|
||||
<?php echo template::button('ConnectBlackListDownload', [
|
||||
'href' => helper::baseUrl() . 'config/blacklistDownload',
|
||||
'value' => 'Télécharger la liste',
|
||||
'ico' => 'download'
|
||||
]); ?>
|
||||
</div>
|
||||
<div class="col6 verticalAlignBottom">
|
||||
<?php echo template::button('CnnectBlackListReset', [
|
||||
'class' => 'buttonRed',
|
||||
'href' => helper::baseUrl() . 'config/blacklistReset',
|
||||
'value' => 'Réinitialiser la liste',
|
||||
'ico' => 'trash'
|
||||
]); ?>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -66,11 +66,12 @@ $(document).ready(function () {
|
||||
$("#connectCaptchaStrong").prop("checked", false);
|
||||
}
|
||||
|
||||
var configLayout = getCookie("configLayout");
|
||||
if (configLayout == null) {
|
||||
configLayout = "locale";
|
||||
setCookie("configLayout", "locale");
|
||||
}
|
||||
var configLayout = "<?php echo $this->getData(['user', $this->getUser('id'), 'view', 'config']);?>";
|
||||
// Non défini, valeur par défaut
|
||||
if (configLayout == "") {
|
||||
configLayout = "setup";
|
||||
}
|
||||
|
||||
$("#localeContainer").hide();
|
||||
$("#socialContainer").hide();
|
||||
$("#connectContainer").hide();
|
||||
@ -168,7 +169,6 @@ $(document).ready(function () {
|
||||
$("#configSocialButton").removeClass("activeButton");
|
||||
$("#configConnectButton").removeClass("activeButton");
|
||||
$("#configNetworkButton").removeClass("activeButton");
|
||||
setCookie("configLayout", "locale");
|
||||
});
|
||||
$("#configSetupButton").on("click", function () {
|
||||
$("#localeContainer").hide();
|
||||
@ -181,7 +181,6 @@ $(document).ready(function () {
|
||||
$("#configSocialButton").removeClass("activeButton");
|
||||
$("#configConnectButton").removeClass("activeButton");
|
||||
$("#configNetworkButton").removeClass("activeButton");
|
||||
setCookie("configLayout", "setup");
|
||||
});
|
||||
|
||||
$("#configSocialButton").on("click", function () {
|
||||
@ -195,7 +194,6 @@ $(document).ready(function () {
|
||||
$("#configSocialButton").addClass("activeButton");
|
||||
$("#configConnectButton").removeClass("activeButton");
|
||||
$("#configNetworkButton").removeClass("activeButton");
|
||||
setCookie("configLayout", "social");
|
||||
});
|
||||
$("#configConnectButton").on("click", function () {
|
||||
$("#setupContainer").hide();
|
||||
@ -208,7 +206,6 @@ $(document).ready(function () {
|
||||
$("#configSocialButton").removeClass("activeButton");
|
||||
$("#configConnectButton").addClass("activeButton");
|
||||
$("#configNetworkButton").removeClass("activeButton");
|
||||
setCookie("configLayout", "connect");
|
||||
});
|
||||
$("#configNetworkButton").on("click", function () {
|
||||
$("#setupContainer").hide();
|
||||
@ -221,7 +218,6 @@ $(document).ready(function () {
|
||||
$("#configSocialButton").removeClass("activeButton");
|
||||
$("#configConnectButton").removeClass("activeButton");
|
||||
$("#configNetworkButton").addClass("activeButton");
|
||||
setCookie("configLayout", "network");
|
||||
});
|
||||
|
||||
|
||||
@ -308,27 +304,6 @@ $(document).ready(function () {
|
||||
});
|
||||
|
||||
|
||||
function setCookie(name, value, days) {
|
||||
var expires = "";
|
||||
if (days) {
|
||||
var date = new Date();
|
||||
date.setTime(date.getTime() + (days * 24 * 60 * 60 * 1000));
|
||||
expires = "; expires=" + date.toUTCString();
|
||||
}
|
||||
document.cookie = name + "=" + (value || "") + expires + "; path=/; samesite=lax";
|
||||
}
|
||||
|
||||
function getCookie(name) {
|
||||
var nameEQ = name + "=";
|
||||
var ca = document.cookie.split(';');
|
||||
for (var i = 0; i < ca.length; i++) {
|
||||
var c = ca[i];
|
||||
while (c.charAt(0) == ' ') c = c.substring(1, c.length);
|
||||
if (c.indexOf(nameEQ) == 0) return c.substring(nameEQ.length, c.length);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
// Define function to capitalize the first letter of a string
|
||||
function capitalizeFirstLetter(string) {
|
||||
return string.charAt(0).toUpperCase() + string.slice(1);
|
||||
|
@ -7,44 +7,35 @@
|
||||
'value' => template::ico('home')
|
||||
]); ?>
|
||||
</div>
|
||||
<div class="col1">
|
||||
<?php /**echo template::button('configHelp', [
|
||||
'class' => 'buttonHelp',
|
||||
'href' => 'https://doc.zwiicms.fr/configuration-du-site',
|
||||
'target' => '_blank',
|
||||
'value' => template::ico('help'),
|
||||
'help' => 'Consulter l\'aide en ligne'
|
||||
]); */?>
|
||||
</div>
|
||||
<div class="col2 offset8">
|
||||
<div class="col2 offset9">
|
||||
<?php echo template::submit('Submit'); ?>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="tab">
|
||||
<?php echo template::button('configLocaleButton', [
|
||||
'value' => 'Identité - Etiquettes',
|
||||
'value' => 'Identité - Étiquettes',
|
||||
'class' => 'buttonTab'
|
||||
]); ?>
|
||||
<?php echo template::button('configSetupButton', [
|
||||
'value' => 'Configuration - Outils',
|
||||
'class' => 'buttonTab'
|
||||
'value' => 'Configuration',
|
||||
'class' => 'buttonTab',
|
||||
'href' => helper::baseUrl() . 'config/register/setup'
|
||||
]); ?>
|
||||
<?php echo template::button('configSocialButton', [
|
||||
'value' => 'Réseaux sociaux',
|
||||
'class' => 'buttonTab'
|
||||
'value' => 'Référencement',
|
||||
'class' => 'buttonTab',
|
||||
'href' => helper::baseUrl() . 'config/register/social'
|
||||
]); ?>
|
||||
|
||||
<?php echo template::button('configConnectButton', [
|
||||
'value' => 'Sécurité',
|
||||
'class' => 'buttonTab'
|
||||
'value' => 'Connexion',
|
||||
'class' => 'buttonTab',
|
||||
'href' => helper::baseUrl() . 'config/register/connect'
|
||||
]); ?>
|
||||
|
||||
<?php echo template::button('configNetworkButton', [
|
||||
'value' => 'Réseau',
|
||||
'class' => 'buttonTab'
|
||||
'class' => 'buttonTab',
|
||||
'href' => helper::baseUrl() . 'config/register/network'
|
||||
]); ?>
|
||||
|
||||
</div>
|
||||
<?php include('core/module/config/view/locale/locale.php') ?>
|
||||
<?php include('core/module/config/view/setup/setup.php') ?>
|
||||
|
@ -98,7 +98,7 @@
|
||||
<h4>
|
||||
<?php echo helper::translate('Étiquettes des pages spéciales'); ?>
|
||||
<!--<span id="labelHelpButton" class="helpDisplayButton" title="Cliquer pour consulter l'aide en ligne">
|
||||
<a href="https://doc.zwiicms.fr/etiquettes-des-pages-speciales" target="_blank">
|
||||
<a href="https://doc.zwiicms.fr/Étiquettes-des-pages-speciales" target="_blank">
|
||||
<?php //echo template::ico('help', ['margin' => 'left']); ?>
|
||||
</a>
|
||||
</span>-->
|
||||
|
@ -7,7 +7,7 @@
|
||||
'value' => template::ico('left')
|
||||
]); ?>
|
||||
</div>
|
||||
<div class="col2 offset8">
|
||||
<div class="col2 offset9">
|
||||
<?php echo template::submit('configManageSubmit', [
|
||||
'value' => 'Valider',
|
||||
'ico' => 'check'
|
||||
|
@ -3,12 +3,6 @@
|
||||
<div class="col12">
|
||||
<div class="block">
|
||||
<h4><?php echo helper::translate('Paramètres'); ?>
|
||||
<!--<span id="setupHelpButton" class="helpDisplayButton">
|
||||
<a href="https://doc.zwiicms.fr/parametres" target="_blank" title="Cliquer pour consulter l'aide en ligne">
|
||||
<?php //echo template::ico('help', ['margin' => 'left']);
|
||||
?>
|
||||
</a>-->
|
||||
</span>
|
||||
</h4>
|
||||
<div class="row">
|
||||
<div class="col4">
|
||||
@ -17,7 +11,8 @@
|
||||
'language' => $this->getData(['user', $this->getUser('id'), 'language']),
|
||||
'help' => 'Pensez à supprimer le cache de votre navigateur si la favicon ne change pas.',
|
||||
'label' => 'Favicon',
|
||||
'value' => $this->getData(['config', 'favicon'])
|
||||
'value' => $this->getData(['config', 'favicon']),
|
||||
'folder' => $this->getData(['config', 'favicon']) ? dirname($this->getData(['config', 'favicon'])) : ''
|
||||
]); ?>
|
||||
</div>
|
||||
<div class="col4">
|
||||
@ -26,7 +21,8 @@
|
||||
'language' => $this->getData(['user', $this->getUser('id'), 'language']),
|
||||
'help' => 'Sélectionnez une icône adaptée à un thème sombre.<br>Pensez à supprimer le cache de votre navigateur si la favicon ne change pas.',
|
||||
'label' => 'Favicon thème sombre',
|
||||
'value' => $this->getData(['config', 'faviconDark'])
|
||||
'value' => $this->getData(['config', 'faviconDark']),
|
||||
'folder' => $this->getData(['config', 'faviconDark']) ? dirname($this->getData(['config', 'faviconDark'])) : ''
|
||||
]); ?>
|
||||
</div>
|
||||
<div class="col4">
|
||||
@ -47,8 +43,8 @@
|
||||
<div class="col6">
|
||||
<?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' => stripos($_SERVER["SERVER_SOFTWARE"], 'nginx')
|
||||
'help' => 'Supprime le point d\'interrogation dans les URL, l\'option est indisponible avec les autres serveurs Web',
|
||||
'disabled' => helper::checkServerSoftware() === false and $module->isModRewriteEnabled()
|
||||
]); ?>
|
||||
</div>
|
||||
</div>
|
||||
@ -59,12 +55,6 @@
|
||||
<div class="col12">
|
||||
<div class="block">
|
||||
<h4><?php echo helper::translate('Mise à jour automatisée'); ?>
|
||||
<!--<span id="updateHelpButton" class="helpDisplayButton">
|
||||
<a href="https://doc.zwiicms.fr/mise-a-jour" target="_blank" title="Cliquer pour consulter l'aide en ligne">
|
||||
<?php //echo template::ico('help', ['margin' => 'left']);
|
||||
?>
|
||||
</a>
|
||||
</span>-->
|
||||
</h4>
|
||||
<div class="row">
|
||||
<div class="col6">
|
||||
@ -90,8 +80,8 @@
|
||||
]); ?>
|
||||
</div>
|
||||
<div class="col3 offset1 verticalAlignBottom">
|
||||
<pre>Version installée : <strong><?php echo common::ZWII_VERSION ; ?></strong></pre>
|
||||
<pre>Version en ligne : <strong><?php echo helper::getOnlineVersion(common::ZWII_UPDATE_CHANNEL) ; ?></strong></pre>
|
||||
<pre>Version installée : <strong><?php echo common::ZWII_VERSION; ?></strong></pre>
|
||||
<pre>Version en ligne : <strong><?php echo helper::getOnlineVersion(common::ZWII_UPDATE_CHANNEL); ?></strong></pre>
|
||||
</div>
|
||||
<div class="col3 offset2 verticalAlignBottom">
|
||||
<?php echo template::button('configUpdateForced', [
|
||||
@ -109,12 +99,6 @@
|
||||
<div class="col12">
|
||||
<div class="block">
|
||||
<h4><?php echo helper::translate('Maintenance'); ?>
|
||||
<!--<span id="maintenanceHelpButton" class="helpDisplayButton">
|
||||
<a href="https://doc.zwiicms.fr/mode-maintenance" target="_blank" title="Cliquer pour consulter l'aide en ligne">
|
||||
<?php //echo template::ico('help', ['margin' => 'left']);
|
||||
?>
|
||||
</a>
|
||||
</span>-->
|
||||
</h4>
|
||||
<div class="row">
|
||||
<div class="col6">
|
||||
@ -169,12 +153,6 @@
|
||||
<div class="col12">
|
||||
<div class="block">
|
||||
<h4><?php echo helper::translate('Scripts externes'); ?>
|
||||
<!--<span id="specialeHelpButton" class="helpDisplayButton">
|
||||
<a href="https://doc.zwiicms.fr/scripts-externes" target="_blank" title="Cliquer pour consulter l'aide en ligne">
|
||||
<?php //echo template::ico('help', ['margin' => 'left']);
|
||||
?>
|
||||
</a>
|
||||
</span>-->
|
||||
</h4>
|
||||
<div class="row">
|
||||
<div class="col4 offset1 verticalAlignBottom">
|
||||
@ -198,13 +176,21 @@
|
||||
<div class="row">
|
||||
<div class="col12">
|
||||
<div class="block">
|
||||
<h4>ZwiiCMS <a href="https://zwiicms.fr" target="_blank">Site Web</a> - <a href="https://forum.zwiicms.fr" target="_blank">Forum</a>
|
||||
<h4>ZwiiCMS <a href="https://zwiicms.fr" target="_blank">Site Web</a> - <a
|
||||
href="https://forum.zwiicms.fr" target="_blank">Forum</a>
|
||||
</h4>
|
||||
<div class="row textAlignCenter">
|
||||
<div class="col12">
|
||||
<a rel="license" href="http://creativecommons.org/licenses/by-nc-nd/4.0/"><img alt="Licence Creative Commons" style="border-width:0" src="https://i.creativecommons.org/l/by-nc-nd/4.0/88x31.png" /></a>
|
||||
<p>Cette œuvre est mise à disposition selon les termes de la <a rel="license" href="http://creativecommons.org/licenses/by-nc-nd/4.0/">Licence Creative Commons Attribution - Pas d'Utilisation Commerciale - Pas de Modification 4.0 International.</a></p>
|
||||
<p>Pour voir une copie de cette licence, visitez http://creativecommons.org/licenses/by-nc-nd/4.0/ ou écrivez à Creative Commons, PO Box 1866, Mountain View, CA 94042, USA.</p>
|
||||
<a rel="license" href="http://creativecommons.org/licenses/by-nc-nd/4.0/"><img
|
||||
alt="Licence Creative Commons" style="border-width:0"
|
||||
src="https://i.creativecommons.org/l/by-nc-nd/4.0/88x31.png" /></a>
|
||||
<p>Cette œuvre est mise à disposition selon les termes de la <a rel="license"
|
||||
href="http://creativecommons.org/licenses/by-nc-nd/4.0/">Licence Creative Commons
|
||||
Attribution - Pas d'Utilisation Commerciale - Pas de Modification 4.0
|
||||
International.</a></p>
|
||||
<p>Pour voir une copie de cette licence, visitez
|
||||
http://creativecommons.org/licenses/by-nc-nd/4.0/ ou écrivez à Creative Commons, PO Box
|
||||
1866, Mountain View, CA 94042, USA.</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -4,11 +4,6 @@
|
||||
<div class="block">
|
||||
<h4>
|
||||
<?php echo helper::translate('Capture d\'écran Open Graph'); ?>
|
||||
<!--<span id="specialeHelpButton" class="helpDisplayButton">
|
||||
<a href="https://doc.zwiicms.fr/referencement" target="_blank" title="Cliquer pour consulter l'aide en ligne">
|
||||
<?php //echo template::ico('help', ['margin' => 'left']); ?>
|
||||
</a>
|
||||
</span>-->
|
||||
</h4>
|
||||
<div class="row">
|
||||
<div class="col6">
|
||||
@ -18,29 +13,30 @@
|
||||
'language' => $this->getData(['user', $this->getUser('id'), 'language']),
|
||||
'label' => 'Image Open Graph',
|
||||
'value' => $this->getData(['config', 'seo', 'openGraphImage']),
|
||||
'folder' => $this->getData(['config', 'seo', 'openGraphImage']) ? dirname($this->getData(['config', 'seo', 'openGraphImage'])) : '',
|
||||
'type' => 1,
|
||||
'help' => sprintf('%s : JPG - PNG<br />', helper::translate('Format')) .
|
||||
sprintf('%s : 1200 x 630 pixels<br />', helper::translate('Dimensions minimales')) .
|
||||
sprintf('%s : 1.91:1<br />', helper::translate('Ratio')) .
|
||||
sprintf('%s : %s, %s<br />', helper::translate('Taille maximale du fichier'), helper::translate('5 Mo pour les images JPEG'), helper::translate('1 Mo pour les images PNG'))
|
||||
'help' => sprintf('%s : JPG - PNG<br />', helper::translate('Format')) .
|
||||
sprintf('%s : 1200 x 630 pixels<br />', helper::translate('Dimensions minimales')) .
|
||||
sprintf('%s : 1.91:1<br />', helper::translate('Ratio')) .
|
||||
sprintf('%s : %s, %s<br />', helper::translate('Taille maximale du fichier'), helper::translate('5 Mo pour les images JPEG'), helper::translate('1 Mo pour les images PNG'))
|
||||
]); ?>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col10 textAlignCenter">
|
||||
<?php if( !empty($module::$imageOpenGraph['type']) ): ?>
|
||||
<p>
|
||||
<?php echo sprintf('%s : <span id="screenType">%s</span>', helper::translate('Format'), $module::$imageOpenGraph['type']); ?>
|
||||
</p>
|
||||
<p>
|
||||
<?php echo sprintf('%s : <span id="screenWide">%s</span> x <span id="screenHeight">%s</span> pixels', helper::translate('Dimensions minimales'), $module::$imageOpenGraph['wide'], $module::$imageOpenGraph['height'] ); ?>
|
||||
</p>
|
||||
<p>
|
||||
<?php echo sprintf('%s : <span id="screenRatio">%s</span><span id="screenFract">:1</span>' , helper::translate('Ratio'), round($module::$imageOpenGraph['ratio'], 2)); ?>
|
||||
</p>
|
||||
<p>
|
||||
<?php echo sprintf('%s : <span id="screenWeight">%s</span>', helper::translate('Poids'), $module::$imageOpenGraph['size']); ?>
|
||||
</p>
|
||||
<?php if (!empty($module::$imageOpenGraph['type'])): ?>
|
||||
<p>
|
||||
<?php echo sprintf('%s : <span id="screenType">%s</span>', helper::translate('Format'), $module::$imageOpenGraph['type']); ?>
|
||||
</p>
|
||||
<p>
|
||||
<?php echo sprintf('%s : <span id="screenWide">%s</span> x <span id="screenHeight">%s</span> pixels', helper::translate('Dimensions minimales'), $module::$imageOpenGraph['wide'], $module::$imageOpenGraph['height']); ?>
|
||||
</p>
|
||||
<p>
|
||||
<?php echo sprintf('%s : <span id="screenRatio">%s</span><span id="screenFract">:1</span>', helper::translate('Ratio'), round($module::$imageOpenGraph['ratio'], 2)); ?>
|
||||
</p>
|
||||
<p>
|
||||
<?php echo sprintf('%s : <span id="screenWeight">%s</span>', helper::translate('Poids'), $module::$imageOpenGraph['size']); ?>
|
||||
</p>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
</div>
|
||||
@ -48,10 +44,10 @@
|
||||
<div class="col6">
|
||||
<?php if (
|
||||
$this->getData(['config', 'seo', 'openGraphImage']) &&
|
||||
file_exists(self::FILE_DIR . 'source/' . $this->getData(['config', 'seo', 'openGraphImage']))
|
||||
file_exists(self::FILE_DIR . 'source/' . $this->getData(['config', 'seo', 'openGraphImage']))
|
||||
): ?>
|
||||
<img
|
||||
src="<?php echo self::FILE_DIR . 'source/' . $this->getData(['config', 'seo', 'openGraphImage']); ?>" />
|
||||
src="<?php echo self::FILE_DIR . 'source/' . $this->getData(['config', 'seo', 'openGraphImage']); ?>" />
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
</div>
|
||||
@ -84,12 +80,6 @@
|
||||
<div class="col12">
|
||||
<div class="block">
|
||||
<h4>
|
||||
<?php echo helper::translate('Réseaux sociaux'); ?>
|
||||
<!--<span id="specialeHelpButton" class="helpDisplayButton">
|
||||
<a href="https://doc.zwiicms.fr/reseaux-sociaux" target="_blank" title="Cliquer pour consulter l'aide en ligne">
|
||||
<?php //echo template::ico('help', ['margin' => 'left']); ?>
|
||||
</a>
|
||||
</span>-->
|
||||
</h4>
|
||||
<div class="row">
|
||||
<div class="col3">
|
||||
|
File diff suppressed because it is too large
Load Diff
98
core/module/course/resource/style.css
Normal file
98
core/module/course/resource/style.css
Normal file
@ -0,0 +1,98 @@
|
||||
/* Réinitialisation de base pour supprimer les marges et les espacements par défaut */
|
||||
body, h1, h2, h3, h4, h5, h6, p, ul, ol, li {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
font-family: Arial, sans-serif;
|
||||
line-height: 1.6;
|
||||
}
|
||||
|
||||
body {
|
||||
margin: 20px;
|
||||
padding: 0;
|
||||
background-color: #f5f5f5;
|
||||
color: #333;
|
||||
}
|
||||
|
||||
h1, h2, h3, h4, h5, h6 {
|
||||
margin-bottom: 10px;
|
||||
color: #2c3e50;
|
||||
}
|
||||
|
||||
p {
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
ul, ol {
|
||||
margin-bottom: 10px;
|
||||
padding-left: 20px;
|
||||
}
|
||||
|
||||
a {
|
||||
color: #3498db;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
a:hover {
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
img {
|
||||
max-width: 100%;
|
||||
height: auto;
|
||||
display: block;
|
||||
margin: 0 auto 10px;
|
||||
}
|
||||
|
||||
.container {
|
||||
max-width: 800px;
|
||||
margin: 0 auto;
|
||||
background-color: #fff;
|
||||
padding: 20px;
|
||||
box-shadow: 0 0 10px rgba(0, 0, 0, 0.1);
|
||||
}
|
||||
|
||||
.header, .footer {
|
||||
background-color: #34495e;
|
||||
color: #fff;
|
||||
text-align: center;
|
||||
padding: 10px 0;
|
||||
}
|
||||
|
||||
.header h1, .footer p {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.content {
|
||||
padding: 20px;
|
||||
}
|
||||
|
||||
code {
|
||||
background-color: #f4f4f4;
|
||||
border: 1px solid #e1e1e1;
|
||||
padding: 2px 4px;
|
||||
font-family: "Courier New", Courier, monospace;
|
||||
color: #c7254e;
|
||||
display: block;
|
||||
margin-bottom: 10px;
|
||||
white-space: pre-wrap;
|
||||
}
|
||||
|
||||
pre {
|
||||
background-color: #f4f4f4;
|
||||
border: 1px solid #e1e1e1;
|
||||
padding: 10px;
|
||||
font-family: "Courier New", Courier, monospace;
|
||||
overflow-x: auto;
|
||||
color: #333;
|
||||
}
|
||||
|
||||
/* Media Queries pour rendre la page responsive */
|
||||
@media (max-width: 600px) {
|
||||
body {
|
||||
margin: 10px;
|
||||
}
|
||||
|
||||
.container {
|
||||
padding: 10px;
|
||||
}
|
||||
}
|
@ -87,6 +87,12 @@
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col4">
|
||||
<?php echo template::checkbox('courseAddEnrolmentReport', true, 'Rapport des consultations', [
|
||||
'help' => 'Enregistre une trace des consultations. Ne s\'applique pas à l\'inscription anonyme',
|
||||
'checked' => true
|
||||
]); ?>
|
||||
</div>
|
||||
<div class="col4">
|
||||
<?php echo template::checkbox('courseAddEnrolmentLimit', true, 'Date de fin d\'inscription', [
|
||||
'help' => 'Ne s\'applique pas à l\'inscription anonyme',
|
||||
|
@ -33,7 +33,7 @@
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col6">
|
||||
<?php echo template::select('courseEditHomePageId', helper::arrayColumn($module::$pagesList, 'title', 'SORT_ASC'), [
|
||||
<?php echo template::select('courseEditHomePageId', helper::arrayColumn($module::$pagesList, 'title'), [
|
||||
'label' => 'Page d\'accueil',
|
||||
'selected' => $this->getdata(['course', $this->getUrl(2), 'homePageId']),
|
||||
]); ?>
|
||||
@ -90,6 +90,12 @@
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col4">
|
||||
<?php echo template::checkbox('courseEditEnrolmentReport', true, 'Rapport des consultations', [
|
||||
'checked' => $this->getdata(['course', $this->getUrl(2), 'report']),
|
||||
'help' => 'Enregistre une trace des consultations. Ne s\'applique pas à l\'inscription anonyme',
|
||||
]); ?>
|
||||
</div>
|
||||
<div class="col4">
|
||||
<?php echo template::checkbox('courseEditEnrolmentLimit', true, 'Date de fin d\'inscription', [
|
||||
'checked' => $this->getdata(['course', $this->getUrl(2), 'limitEnrolment']),
|
||||
@ -99,11 +105,12 @@
|
||||
<div class="col4">
|
||||
<?php echo template::date('courseEditEnrolmentLimitDate', [
|
||||
'type' => 'datetime-local',
|
||||
'label' => 'Fermeture',
|
||||
'label' => 'Fin d\'inscription',
|
||||
'value' => is_null($this->getdata(['course', $this->getUrl(2), 'limitEnrolmentDate'])) ? '' : floor($this->getdata(['course', $this->getUrl(2), 'limitEnrolmentDate']) / 60) * 60
|
||||
]); ?>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<?php echo template::formClose(); ?>
|
||||
</div>
|
||||
<?php echo template::formClose(); ?>
|
27
core/module/course/view/export/export.js.php
Normal file
27
core/module/course/view/export/export.js.php
Normal file
@ -0,0 +1,27 @@
|
||||
/**
|
||||
* This file is part of Zwii.
|
||||
*
|
||||
* For full copyright and license information, please see the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*
|
||||
* @author Rémi Jean <remi.jean@outlook.com>
|
||||
* @copyright Copyright (C) 2008-2018, Rémi Jean
|
||||
* @author Frédéric Tempez <frederic.tempez@outlook.com>
|
||||
* @copyright Copyright (C) 2018-2024, Frédéric Tempez
|
||||
* @license CC Attribution-NonCommercial-NoDerivatives 4.0 International
|
||||
* @link http://zwiicms.fr/
|
||||
*/
|
||||
|
||||
$(document).ready(function() {
|
||||
// Quand le bouton "Cocher toutes" est cliqué
|
||||
$('#courseExportSelectAll').on('click', function() {
|
||||
// Cocher toutes les checkboxes avec la classe 'courseManageCheckbox'
|
||||
$('.courseManageCheckbox').prop('checked', true);
|
||||
});
|
||||
|
||||
// Quand le bouton "Décocher toutes" est cliqué
|
||||
$('#courseExportSelectNone').on('click', function() {
|
||||
// Décocher toutes les checkboxes avec la classe 'courseManageCheckbox'
|
||||
$('.courseManageCheckbox').prop('checked', false);
|
||||
});
|
||||
});
|
42
core/module/course/view/export/export.php
Normal file
42
core/module/course/view/export/export.php
Normal file
@ -0,0 +1,42 @@
|
||||
<?php echo template::formOpen('courseExportForm'); ?>
|
||||
<div class="row">
|
||||
<div class="col1">
|
||||
<?php echo template::button('courseExportBack', [
|
||||
'class' => 'buttonGrey',
|
||||
'href' => helper::baseUrl() . 'course/manage/' . $this->getUrl(2),
|
||||
'value' => template::ico('left')
|
||||
]); ?>
|
||||
</div>
|
||||
<div class="col1 offset7">
|
||||
<?php echo template::button('courseExportSelectAll', [
|
||||
'value' => template::ico('square-check'),
|
||||
'help' => 'Tout sélectionner'
|
||||
]); ?>
|
||||
</div>
|
||||
<div class="col1">
|
||||
<?php echo template::button('courseExportSelectNone', [
|
||||
'value' => template::ico('square-check-empty'),
|
||||
'help' => 'Tout désélectionner'
|
||||
]); ?>
|
||||
</div>
|
||||
<div class="col2">
|
||||
<?php echo template::submit('courseExportSubmit', [
|
||||
'value' => 'Valider'
|
||||
]); ?>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col12">
|
||||
<div class="block">
|
||||
<h4><?php echo helper::translate('Sélection des pages de l\'espace') ?></h4>
|
||||
<div class='row'>
|
||||
<div class='col10 offset2'>
|
||||
<?php foreach ($module::$pagesList as $key => $value) {
|
||||
echo $value;
|
||||
}
|
||||
?>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
@ -17,11 +17,23 @@ $(document).ready(function () {
|
||||
url: "core/vendor/datatables/french.json"
|
||||
},
|
||||
locale: 'fr',
|
||||
stateSave: true,
|
||||
"lengthMenu": [[10, 25, 50, -1], [10, 25, 50, "Tout"]],
|
||||
"columnDefs": [
|
||||
{
|
||||
target: 2,
|
||||
orderable: false,
|
||||
searchable: false
|
||||
},
|
||||
{
|
||||
target: 3,
|
||||
orderable: false,
|
||||
searchable: false
|
||||
},
|
||||
{
|
||||
target: 4,
|
||||
orderable: false,
|
||||
searchable: false
|
||||
}
|
||||
]
|
||||
});
|
||||
|
@ -6,41 +6,38 @@
|
||||
'value' => template::ico('home')
|
||||
]); ?>
|
||||
</div>
|
||||
<?php if ($this->getUser('group') === self::GROUP_ADMIN): ?>
|
||||
<div class="col1 offset8">
|
||||
<?php echo template::button('courseUpload', [
|
||||
'href' => helper::baseUrl() . 'course/restore/',
|
||||
'value' => template::ico('upload-cloud'),
|
||||
'help' => 'Restaurer'
|
||||
]); ?>
|
||||
</div>
|
||||
<div class="col1">
|
||||
<?php echo template::button('courseCategory', [
|
||||
'href' => helper::baseUrl() . 'course/category',
|
||||
'value' => template::ico('table'),
|
||||
'help' => 'Catégories'
|
||||
]); ?>
|
||||
</div>
|
||||
<div class="col1">
|
||||
<div class="col1 offset8">
|
||||
<?php if ($this->getUser('permission', 'course', 'add') === true): ?>
|
||||
<?php echo template::button('courseAdd', [
|
||||
'class' => 'buttonGreen',
|
||||
'href' => helper::baseUrl() . 'course/add',
|
||||
'value' => template::ico('plus'),
|
||||
'help' => 'Ajouter un espace'
|
||||
]); ?>
|
||||
</div>
|
||||
<?php else: ?>
|
||||
<div class="col1 offset10">
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
<div class="col1">
|
||||
<?php if ($this->getUser('permission', 'course', 'category') === true): ?>
|
||||
<?php echo template::button('courseCategory', [
|
||||
'href' => helper::baseUrl() . 'course/category',
|
||||
'value' => template::ico('table'),
|
||||
'help' => 'Catégories des espaces'
|
||||
]); ?>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
<div class="col1">
|
||||
<?php if ($this->getUser('permission', 'course', 'restore') === true): ?>
|
||||
<?php echo template::button('courseUpload', [
|
||||
'href' => helper::baseUrl() . 'course/restore/',
|
||||
'value' => template::ico('upload-cloud'),
|
||||
'help' => 'Restaurer depuis le dossier de l\'espace ' . self::$siteContent
|
||||
'help' => 'Restaurer un espace'
|
||||
]); ?>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
<?php endif; ?>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
<?php if ($module::$courses): ?>
|
||||
<?php echo template::table([4, 4, 3, 1 ], $module::$courses, ['Titre court', 'Description', 'Inscription', '',], ['id' => 'dataTables']); ?>
|
||||
<?php echo template::table([4, 3, 3, 1, 1], $module::$courses, ['Titre court', 'Description', 'Inscription', '', '',], ['id' => 'dataTables']); ?>
|
||||
<?php else: ?>
|
||||
<?php echo template::speech('Aucun espace'); ?>
|
||||
<?php endif; ?>
|
@ -21,3 +21,14 @@ $(".courseDelete").on("click", function () {
|
||||
$(location).attr("href", _this.attr("href"));
|
||||
});
|
||||
});
|
||||
|
||||
/**
|
||||
* Confirmation de suppression
|
||||
*/
|
||||
$(".courseReset").on("click", function () {
|
||||
var _this = $(this);
|
||||
var message = "<?php echo helper::translate('Réinitialiser cet espace ?'); ?>";
|
||||
return core.confirm(message, function () {
|
||||
$(location).attr("href", _this.attr("href"));
|
||||
});
|
||||
});
|
@ -7,150 +7,183 @@
|
||||
]); ?>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col2 offset1">
|
||||
<?php echo template::button('categoryUser' . $this->getUrl(2), [
|
||||
'href' => helper::baseUrl() . 'course/users/' . $this->getUrl(2),
|
||||
'value' => 'Participants',
|
||||
'ico' => 'users'
|
||||
]); ?>
|
||||
</div>
|
||||
<div class="col2">
|
||||
<?php echo template::button('courseManageEdit' . $this->getUrl(2), [
|
||||
'href' => helper::baseUrl() . 'course/edit/' . $this->getUrl(2),
|
||||
'value' => 'Éditer',
|
||||
'ico' => 'pencil'
|
||||
]); ?>
|
||||
</div>
|
||||
<div class="col2">
|
||||
<?php echo
|
||||
template::button('courseManageDuplicate' . $this->getUrl(2), [
|
||||
'href' => helper::baseUrl() . 'course/clone/' . $this->getUrl(2),
|
||||
'value' => 'Cloner',
|
||||
'ico' => 'clone'
|
||||
]); ?>
|
||||
</div>
|
||||
<div class="col2">
|
||||
<?php echo
|
||||
template::button('courseManageDownload' . $this->getUrl(2), [
|
||||
'href' => helper::baseUrl() . 'course/backup/' . $this->getUrl(2),
|
||||
'value' => 'Sauvegarder',
|
||||
'ico' => 'download-cloud'
|
||||
]); ?>
|
||||
</div>
|
||||
<div class="col2 ">
|
||||
<?php echo
|
||||
template::button('courseManageDelete' . $this->getUrl(2), [
|
||||
<div class="row textAlignCenter">
|
||||
<?php if ($this->getUser('permission', 'course', 'delete') === true): ?>
|
||||
<div class="col2 ">
|
||||
<?php echo template::button('courseManageDelete' . $this->getUrl(2), [
|
||||
'class' => 'courseDelete buttonRed',
|
||||
'href' => helper::baseUrl() . 'course/delete/' . $this->getUrl(2),
|
||||
'value' => 'Supprimer',
|
||||
'ico' => 'trash'
|
||||
'ico' => 'trash',
|
||||
'help' => 'Supprime l\'espace et les historiques des participants',
|
||||
]); ?>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col12">
|
||||
<div class="block">
|
||||
<h4>
|
||||
<?php echo helper::translate('Paramètres'); ?>
|
||||
</h4>
|
||||
<div class="row">
|
||||
<div class="col7">
|
||||
<?php echo template::text('courseManageShortTitle', [
|
||||
'label' => 'Titre',
|
||||
'value' => $this->getdata(['course', $this->getUrl(2), 'title']),
|
||||
'disabled' => true,
|
||||
]); ?>
|
||||
</div>
|
||||
<div class="col5">
|
||||
<?php echo template::select('courseManageAuthor', $module::$courseTeachers, [
|
||||
'label' => 'Auteur',
|
||||
'selected' => $this->getdata(['course', $this->getUrl(2), 'author']),
|
||||
'disabled' => true,
|
||||
]); ?>
|
||||
</div>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
<?php if ($this->getUser('permission', 'course', 'reset') === true): ?>
|
||||
<div class="col2 ">
|
||||
<?php echo template::button('courseManageReset' . $this->getUrl(2), [
|
||||
'class' => 'courseReset buttonRed',
|
||||
'href' => helper::baseUrl() . 'course/reset/' . $this->getUrl(2),
|
||||
'value' => 'Réinitaliser',
|
||||
'ico' => 'cancel',
|
||||
'help' => 'Désinscrit les participants et supprime les historiques',
|
||||
]); ?>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
<?php if ($this->getUser('permission', 'course', 'backup') === true): ?>
|
||||
<div class="col2">
|
||||
<?php echo template::button('courseManageDownload' . $this->getUrl(2), [
|
||||
'href' => helper::baseUrl() . 'course/backup/' . $this->getUrl(2),
|
||||
'value' => 'Sauvegarder',
|
||||
'ico' => 'download-cloud',
|
||||
'help' => 'Génère une copie de sauvegarde de l\'espace',
|
||||
]); ?>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
<?php if ($this->getUser('permission', 'course', 'clone') === true): ?>
|
||||
<div class="col2">
|
||||
<?php echo template::button('courseManageDuplicate' . $this->getUrl(2), [
|
||||
'href' => helper::baseUrl() . 'course/clone/' . $this->getUrl(2),
|
||||
'value' => 'Cloner',
|
||||
'ico' => 'clone',
|
||||
'help' => 'Copie l\'espace et son contenu sans les participants et leurs historiques',
|
||||
]); ?>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
<?php if ($this->getUser('permission', 'course', 'edit') === true): ?>
|
||||
<div class="col2">
|
||||
<?php echo template::button('courseManageEdit' . $this->getUrl(2), [
|
||||
'href' => helper::baseUrl() . 'course/edit/' . $this->getUrl(2),
|
||||
'value' => 'Éditer',
|
||||
'ico' => 'pencil',
|
||||
'help' => 'Modifie les paramètres de l\'espace',
|
||||
]); ?>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
<?php if ($this->getUser('permission', 'course', 'export') === true): ?>
|
||||
<div class="col2">
|
||||
<?php echo template::button('courseManageExport' . $this->getUrl(2), [
|
||||
'href' => helper::baseUrl() . 'course/export/' . $this->getUrl(2),
|
||||
'value' => 'Exporter HTML',
|
||||
'ico' => 'upload',
|
||||
'help' => 'Le contenu de l\'espace est exporté dans une page web autonome',
|
||||
]); ?>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
<div class="col12">
|
||||
<div class="block">
|
||||
<h4>
|
||||
<?php echo helper::translate('Paramètres'); ?>
|
||||
</h4>
|
||||
<div class="row">
|
||||
<div class="col7">
|
||||
<?php echo template::text('courseManageShortTitle', [
|
||||
'label' => 'Titre',
|
||||
'value' => $this->getdata(['course', $this->getUrl(2), 'title']),
|
||||
'readonly' => true,
|
||||
]); ?>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col6">
|
||||
<?php echo template::select('courseManageHomePageId', helper::arrayColumn($module::$pagesList, 'title', 'SORT_ASC'), [
|
||||
'label' => 'Page d\'accueil',
|
||||
'selected' => $this->getdata(['course', $this->getUrl(2), 'homePageId']),
|
||||
'disabled' => true,
|
||||
]); ?>
|
||||
</div>
|
||||
<div class="col6">
|
||||
<?php echo template::select('courseManageCategorie', $module::$courseCategories, [
|
||||
'label' => 'Catégorie',
|
||||
'selected' => $this->getdata(['course', $this->getUrl(2), 'category']),
|
||||
'disabled' => true,
|
||||
]); ?>
|
||||
</div>
|
||||
<div class="col5">
|
||||
<?php echo template::text('courseManageAuthor', [
|
||||
'label' => 'Auteur',
|
||||
'value' => $this->signature($this->getdata(['course', $this->getUrl(2), 'author'])),
|
||||
'readonly' => true,
|
||||
]); ?>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col12">
|
||||
<?php echo template::textarea('courseManageDescription', [
|
||||
'label' => 'Description',
|
||||
'value' => $this->getdata(['course', $this->getUrl(2), 'description']),
|
||||
'disabled' => true,
|
||||
]); ?>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col6">
|
||||
<?php echo template::text('courseManageHomePageId', [
|
||||
'label' => 'Page d\'accueil',
|
||||
'value' => $module::$pagesList[$this->getdata(['course', $this->getUrl(2), 'homePageId'])]['shortTitle'],
|
||||
'readonly' => true,
|
||||
]); ?>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col4">
|
||||
<?php echo template::select('courseManageAccess', $module::$courseAccess, [
|
||||
'label' => 'Disponibilité',
|
||||
'selected' => $this->getdata(['course', $this->getUrl(2), 'access']),
|
||||
'disabled' => true,
|
||||
]); ?>
|
||||
</div>
|
||||
<div class="col4">
|
||||
<?php echo template::date('courseOpeningDate', [
|
||||
'type' => 'datetime-local',
|
||||
'label' => 'Ouverture',
|
||||
'value' => is_null($this->getdata(['course', $this->getUrl(2), 'openingDate'])) ? '' : floor($this->getdata(['course', $this->getUrl(2), 'openingDate']) / 60) * 60,
|
||||
'disabled' => true,
|
||||
]); ?>
|
||||
</div>
|
||||
<div class="col4">
|
||||
<?php echo template::date('courseClosingDate', [
|
||||
'type' => 'datetime-local',
|
||||
'label' => 'Fermeture',
|
||||
'value' => is_null($this->getdata(['course', $this->getUrl(2), 'closingDate'])) ? '' : floor($this->getdata(['course', $this->getUrl(2), 'closingDate']) / 60) * 60,
|
||||
'disabled' => true,
|
||||
]); ?>
|
||||
</div>
|
||||
<div class="col6">
|
||||
<?php echo template::text('courseManageCategorie', [
|
||||
'label' => 'Catégorie',
|
||||
'value' => $module::$courseCategories[$this->getdata(['course', $this->getUrl(2), 'category'])],
|
||||
'readonly' => true,
|
||||
]); ?>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col4">
|
||||
<?php echo template::select('courseManageEnrolment', $module::$courseEnrolment, [
|
||||
'label' => 'Participation',
|
||||
'selected' => $this->getdata(['course', $this->getUrl(2), 'enrolment']),
|
||||
'disabled' => true,
|
||||
]); ?>
|
||||
</div>
|
||||
<div class="col4">
|
||||
<?php echo template::text('courseManageEnrolmentKey', [
|
||||
'label' => 'Clé',
|
||||
'value' => $this->getdata(['course', $this->getUrl(2), 'enrolmentKey']),
|
||||
'disabled' => true,
|
||||
]); ?>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col12">
|
||||
<?php echo template::textarea('courseManageDescription', [
|
||||
'label' => 'Description',
|
||||
'value' => $this->getdata(['course', $this->getUrl(2), 'description']),
|
||||
'readonly' => true,
|
||||
]); ?>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col4">
|
||||
<?php echo template::checkbox('courseManageEnrolmentLimit', true, 'Date de fin d\'inscription', [
|
||||
'checked' => $this->getdata(['course', $this->getUrl(2), 'limitEnrolment']),
|
||||
'help' => 'Ne s\'applique pas à l\'inscription anonyme',
|
||||
'disabled' => true,
|
||||
]); ?>
|
||||
</div>
|
||||
<div class="col4">
|
||||
<?php echo template::date('courseManageEnrolmentLimitDate', [
|
||||
'type' => 'datetime-local',
|
||||
'label' => 'Fermeture',
|
||||
'value' => is_null($this->getdata(['course', $this->getUrl(2), 'limitEnrolmentDate'])) ? '' : floor($this->getdata(['course', $this->getUrl(2), 'limitEnrolmentDate']) / 60) * 60,
|
||||
'disabled' => true,
|
||||
]); ?>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col4">
|
||||
<?php echo template::text('courseManageAccess', [
|
||||
'label' => 'Disponibilité',
|
||||
'value' => $module::$courseAccess[$this->getdata(['course', $this->getUrl(2), 'access'])],
|
||||
'readonly' => true,
|
||||
]); ?>
|
||||
</div>
|
||||
<div class="col4">
|
||||
<?php echo template::date('courseOpeningDate', [
|
||||
'type' => 'datetime-local',
|
||||
'label' => 'Ouverture',
|
||||
'value' => is_null($this->getdata(['course', $this->getUrl(2), 'openingDate'])) ? '' : floor($this->getdata(['course', $this->getUrl(2), 'openingDate']) / 60) * 60,
|
||||
'readonly' => true,
|
||||
]); ?>
|
||||
</div>
|
||||
<div class="col4">
|
||||
<?php echo template::date('courseClosingDate', [
|
||||
'type' => 'datetime-local',
|
||||
'label' => 'Fermeture',
|
||||
'value' => is_null($this->getdata(['course', $this->getUrl(2), 'closingDate'])) ? '' : floor($this->getdata(['course', $this->getUrl(2), 'closingDate']) / 60) * 60,
|
||||
'readonly' => true,
|
||||
]); ?>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col4">
|
||||
<?php echo template::text('courseManageEnrolment', [
|
||||
'label' => 'Participation',
|
||||
'value' => $module::$courseEnrolment[$this->getdata(['course', $this->getUrl(2), 'enrolment'])],
|
||||
'readonly' => true,
|
||||
]); ?>
|
||||
</div>
|
||||
<div class="col4">
|
||||
<?php echo template::text('courseManageEnrolmentKey', [
|
||||
'label' => 'Clé',
|
||||
'value' => $this->getdata(['course', $this->getUrl(2), 'enrolmentKey']),
|
||||
'readonly' => true,
|
||||
]); ?>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col4">
|
||||
<?php echo template::checkbox('courseManageEnrolmentReport', true, 'Rapport des consultations', [
|
||||
'checked' => $this->getdata(['course', $this->getUrl(2), 'report']),
|
||||
'help' => 'Ne s\'applique pas à l\'inscription anonyme',
|
||||
'disabled' => true,
|
||||
]); ?>
|
||||
</div>
|
||||
<div class="col4">
|
||||
<?php echo template::checkbox('courseManageEnrolmentLimit', true, 'Date de fin d\'inscription', [
|
||||
'checked' => $this->getdata(['course', $this->getUrl(2), 'limitEnrolment']),
|
||||
'help' => 'Ne s\'applique pas à l\'inscription anonyme',
|
||||
'disabled' => true,
|
||||
]); ?>
|
||||
</div>
|
||||
<div class="col4">
|
||||
<?php echo template::date('courseManageEnrolmentLimitDate', [
|
||||
'type' => 'datetime-local',
|
||||
'label' => 'Fin d\'inscription',
|
||||
'value' => is_null($this->getdata(['course', $this->getUrl(2), 'limitEnrolmentDate'])) ? '' : floor($this->getdata(['course', $this->getUrl(2), 'limitEnrolmentDate']) / 60) * 60,
|
||||
'readonly' => true,
|
||||
]); ?>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
@ -1,5 +1,6 @@
|
||||
/**
|
||||
* This file is part of Zwii.
|
||||
*
|
||||
* For full copyright and license information, please see the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*
|
||||
@ -11,15 +12,11 @@
|
||||
* @link http://zwiicms.fr/
|
||||
*/
|
||||
|
||||
$(document).ready((function () {
|
||||
$('#dataTables').DataTable({
|
||||
language: {
|
||||
url: "core/vendor/datatables/french.json"
|
||||
},
|
||||
locale: 'fr',
|
||||
searching: false,
|
||||
pageLength: 100,
|
||||
lengthChange: false,
|
||||
paging: false
|
||||
});
|
||||
}));
|
||||
|
||||
/** NE PAS EFFACER
|
||||
* admin.css
|
||||
*/
|
||||
|
||||
table td {
|
||||
text-align: left;
|
||||
}
|
44
core/module/course/view/userReport/userReport.js.php
Normal file
44
core/module/course/view/userReport/userReport.js.php
Normal file
@ -0,0 +1,44 @@
|
||||
/**
|
||||
* This file is part of Zwii.
|
||||
* For full copyright and license information, please see the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*
|
||||
* @author Rémi Jean <remi.jean@outlook.com>
|
||||
* @copyright Copyright (C) 2008-2018, Rémi Jean
|
||||
* @author Frédéric Tempez <frederic.tempez@outlook.com>
|
||||
* @copyright Copyright (C) 2018-2024, Frédéric Tempez
|
||||
* @license CC Attribution-NonCommercial-NoDerivatives 4.0 International
|
||||
* @link http://zwiicms.fr/
|
||||
*/
|
||||
|
||||
$(document).ready((function () {
|
||||
|
||||
var dataX = <?php echo json_encode(array_map(function ($item) { return $item[0]; }, $module::$userGraph)); ?>;
|
||||
var dataY = <?php echo json_encode(array_map(function ($item) { return $item[1];}, $module::$userGraph)); ?>;
|
||||
var dataText = <?php echo json_encode(array_map(function ($item) { return $item[2];}, $module::$userGraph)); ?>;
|
||||
|
||||
var data = [{
|
||||
x: dataX,
|
||||
y: dataY,
|
||||
text: dataText,
|
||||
mode: 'markers', // Mode de tracé des points
|
||||
type: 'scatter' // Type de graphe
|
||||
}];
|
||||
|
||||
// Créer un objet layout et définir les propriétés du titre, des axes, etc.
|
||||
var layout = {
|
||||
title: 'Consultations par jour', // Titre du graphe
|
||||
xaxis: {
|
||||
title: 'Jours', // Titre de l'axe des abscisses
|
||||
type: 'date' // Type de l'axe des abscisses
|
||||
},
|
||||
yaxis: {
|
||||
title: 'Temps (en secondes)', // Titre de l'axe des ordonnées
|
||||
type: 'linear' // Type de l'axe des ordonnées
|
||||
}
|
||||
};
|
||||
|
||||
// Créer et afficher le graphe dans l'élément <div>
|
||||
Plotly.newPlot('graph', data, layout, {locale: 'fr-CH'});
|
||||
|
||||
}));
|
@ -8,31 +8,45 @@
|
||||
</div>
|
||||
<div class="col1 offset10">
|
||||
<?php echo template::button('userDeleteAll', [
|
||||
'href' => helper::baseUrl() . 'course/userHistoryExport/' . $this->getUrl(2) . '/' . $this->getUrl(3),
|
||||
'href' => helper::baseUrl() . 'course/userReportExport/' . $this->getUrl(2) . '/' . $this->getUrl(3),
|
||||
'value' => template::ico('download'),
|
||||
'help' => 'Exporter',
|
||||
'help' => 'Exporter rapport',
|
||||
]) ?>
|
||||
</div>
|
||||
</div>
|
||||
<?php if ($module::$userHistory): ?>
|
||||
<div class="row">
|
||||
<div class="col10 offset1">
|
||||
<div id="graph">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<?php if ($module::$userReport): ?>
|
||||
<div class="row">
|
||||
<div class="col4 offset2">
|
||||
<?php if ($this->getData(['course', $this->getUrl(2), 'access']) === self::COURSE_ACCESS_DATE): ?>
|
||||
<p>Espace ouvert le :
|
||||
<?php echo helper::dateUTF8('%d %B %Y %H:%M', $this->getData(['course', $this->getUrl(2), 'openingDate'])); ?></p
|
||||
<?php echo helper::dateUTF8('%d %B %Y %H:%M', $this->getData(['course', $this->getUrl(2), 'openingDate'])); ?>
|
||||
</p>
|
||||
<p>Espace fermé le :
|
||||
<?php echo helper::dateUTF8('%d %B %Y %H:%M', $this->getData(['course', $this->getUrl(2), 'closingDate'])); ?></p>
|
||||
<?php endif;?>
|
||||
<?php echo helper::dateUTF8('%d %B %Y %H:%M', $this->getData(['course', $this->getUrl(2), 'closingDate'])); ?>
|
||||
</p>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
<div class="col4">
|
||||
<p>Commencé le : <?php echo $module::$userStat['floor'];?></p>
|
||||
<p>Terminé le : <?php echo $module::$userStat['top'];?></p>
|
||||
<p>Temps passé : <?php echo $module::$userStat['time'];?></p>
|
||||
<p>Commencé le :
|
||||
<?php echo $module::$userStat['floor']; ?>
|
||||
</p>
|
||||
<p>Terminé le :
|
||||
<?php echo $module::$userStat['top']; ?>
|
||||
</p>
|
||||
<p>Temps passé :
|
||||
<?php echo $module::$userStat['time']; ?>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row textAlignCenter">
|
||||
<div class="col8">
|
||||
<?php echo template::table([1, 6, 5], $module::$userHistory, ['Ordre', 'Page', 'Consultation'], ['id' => 'dataTables']);?>
|
||||
<?php echo template::table([6, 3, 3], $module::$userReport, ['Page', 'Début de Consultation', 'Temps consultation']); ?>
|
||||
</div>
|
||||
</div>
|
||||
<?php else: ?>
|
@ -21,12 +21,15 @@ $(document).ready((function () {
|
||||
$(location).attr("href", _this.attr("href"))
|
||||
}))
|
||||
}));
|
||||
|
||||
$.fn.dataTable.moment( 'DD/MM/YYYY' );
|
||||
$('#dataTables').DataTable({
|
||||
language: {
|
||||
url: "core/vendor/datatables/french.json"
|
||||
},
|
||||
order: [[3, 'desc']],
|
||||
locale: 'fr',
|
||||
stateSave: true,
|
||||
"lengthMenu": [[10, 25, 50, 100, 299, -1], [10, 25, 50, 100, 200, "Tout"]],
|
||||
"columnDefs": [
|
||||
{
|
||||
target: 6,
|
||||
|
@ -2,15 +2,15 @@
|
||||
<div class="col1">
|
||||
<?php echo template::button('courseUserBack', [
|
||||
'class' => 'buttonGrey',
|
||||
'href' => helper::baseUrl() . 'course/manage/' . $this->getUrl(2),
|
||||
'href' => helper::baseUrl() . 'course/' . $this->getUrl(2),
|
||||
'value' => template::ico('left')
|
||||
]); ?>
|
||||
</div>
|
||||
<div class="col1 offset8">
|
||||
<?php echo template::button('userDeleteAll', [
|
||||
'href' => helper::baseUrl() . 'course/usersHistoryExport/' . $this->getUrl(2),
|
||||
'href' => helper::baseUrl() . 'course/usersReportExport/' . $this->getUrl(2),
|
||||
'value' => template::ico('download'),
|
||||
'help' => 'Exporter',
|
||||
'help' => 'Exporter rapports',
|
||||
]) ?>
|
||||
</div>
|
||||
<div class="col1">
|
||||
@ -53,7 +53,7 @@
|
||||
</div>
|
||||
<?php echo template::formClose(); ?>
|
||||
<?php if ($module::$courseUsers): ?>
|
||||
<?php echo template::table([2, 2, 2, 2, 2, 1, 1], $module::$courseUsers, ['Id', 'Nom Prénom', 'Dernière page vue', 'Date - Heure', 'Étiquettes', 'Progression', ''], ['id' => 'dataTables']); ?>
|
||||
<?php echo template::table([3, 4, 1, 1, 1, 1, 1], $module::$courseUsers, ['Nom Prénom', 'Dernière page vue', 'Date' , 'Heure', 'Étiquettes', 'Progression', ''], ['id' => 'dataTables']); ?>
|
||||
<?php else: ?>
|
||||
<?php echo template::speech('Aucun participant'); ?>
|
||||
<?php endif; ?>
|
@ -16,3 +16,7 @@
|
||||
/** NE PAS EFFACER
|
||||
* admin.css
|
||||
*/
|
||||
|
||||
tr {
|
||||
cursor: pointer;
|
||||
}
|
@ -13,6 +13,13 @@
|
||||
|
||||
$(document).ready((function () {
|
||||
|
||||
$('tr').click(function(){
|
||||
// Cochez ou décochez la case à cocher dans cette ligne
|
||||
$(this).find('input[type="checkbox"]').prop('checked', function(i, val){
|
||||
return !val; // Inverse l'état actuel de la case à cocher
|
||||
});
|
||||
});
|
||||
|
||||
$('#courseUserAddSelectAll').on('click', function() {
|
||||
$('.checkboxSelect').prop('checked', true);
|
||||
saveCheckboxState();
|
||||
@ -32,6 +39,8 @@ $(document).ready((function () {
|
||||
url: "core/vendor/datatables/french.json"
|
||||
},
|
||||
locale: 'fr',
|
||||
stateSave: true,
|
||||
"lengthMenu": [[10, 25, 50, 100, 299, -1], [10, 25, 50, 100, 200, "Tout"]],
|
||||
"columnDefs": [
|
||||
{
|
||||
target: 0,
|
||||
|
@ -7,19 +7,10 @@
|
||||
'value' => template::ico('left')
|
||||
]); ?>
|
||||
</div>
|
||||
<div class="col1 offset7">
|
||||
<?php echo template::button('courseUserAddSelectAll', [
|
||||
'value' => 'Tout'
|
||||
]); ?>
|
||||
</div>
|
||||
<div class="col1">
|
||||
<?php echo template::button('courseUserAddSelectNone', [
|
||||
'value' => 'Aucun'
|
||||
]); ?>
|
||||
</div>
|
||||
<div class="col2">
|
||||
<div class="col2 offset9">
|
||||
<?php echo template::submit('courseUsersAddSubmit', [
|
||||
'value' => 'Inscrire'
|
||||
'value' => 'Inscrire',
|
||||
'ico' => 'plus',
|
||||
]); ?>
|
||||
</div>
|
||||
</div>
|
||||
@ -42,6 +33,18 @@
|
||||
'selected' => isset($_POST['courseFilterLastName']) ? $_POST['courseFilterLastName'] : 'all',
|
||||
]); ?>
|
||||
</div>
|
||||
<div class="col1 offset1 verticalAlignBottom">
|
||||
<?php echo template::button('courseUserAddSelectAll', [
|
||||
'value' => template::ico('square-check'),
|
||||
'help' => 'Tout sélectionner'
|
||||
]); ?>
|
||||
</div>
|
||||
<div class="col1 verticalAlignBottom">
|
||||
<?php echo template::button('courseUserAddSelectNone', [
|
||||
'value' => template::ico('square-check-empty'),
|
||||
'help' => 'Tout désélectionner'
|
||||
]); ?>
|
||||
</div>
|
||||
</div>
|
||||
<?php if ($module::$courseUsers): ?>
|
||||
<?php echo template::table([1, 2, 3, 3, 3], $module::$courseUsers, ['', 'Id', 'Prénom', 'Nom', 'Étiquettes'], ['id' => 'dataTables']); ?>
|
||||
|
@ -16,3 +16,11 @@
|
||||
/** NE PAS EFFACER
|
||||
* admin.css
|
||||
*/
|
||||
|
||||
#courseUsersDeleteSubmit {
|
||||
background-color: rgba(217, 95, 78, 1);
|
||||
}
|
||||
|
||||
tr {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
@ -13,11 +13,18 @@
|
||||
|
||||
$(document).ready((function () {
|
||||
|
||||
$('#courseUserDeleteSelectAll').on('click', function() {
|
||||
$('tr').click(function () {
|
||||
// Cochez ou décochez la case à cocher dans cette ligne
|
||||
$(this).find('input[type="checkbox"]').prop('checked', function (i, val) {
|
||||
return !val; // Inverse l'état actuel de la case à cocher
|
||||
});
|
||||
});
|
||||
|
||||
$('#courseUserDeleteSelectAll').on('click', function () {
|
||||
$('.checkboxSelect').prop('checked', true);
|
||||
saveCheckboxState();
|
||||
});
|
||||
$('#courseUserDeleteSelectNone').on('click', function() {
|
||||
$('#courseUserDeleteSelectNone').on('click', function () {
|
||||
$('.checkboxSelect').prop('checked', false);
|
||||
saveCheckboxState();
|
||||
});
|
||||
@ -32,6 +39,7 @@ $(document).ready((function () {
|
||||
url: "core/vendor/datatables/french.json"
|
||||
},
|
||||
locale: 'fr',
|
||||
"lengthMenu": [[10, 25, 50, 100, 299, -1], [10, 25, 50, 100, 200, "Tout"]],
|
||||
"columnDefs": [
|
||||
{
|
||||
target: 0,
|
||||
@ -80,7 +88,7 @@ $(document).ready((function () {
|
||||
// Function to restore checkbox state
|
||||
function restoreCheckboxState() {
|
||||
var checkboxState = JSON.parse(localStorage.getItem('checkboxState')) || {};
|
||||
// console.log(checkboxState);
|
||||
// console.log(checkboxState);
|
||||
for (var checkboxId in checkboxState) {
|
||||
if (checkboxState.hasOwnProperty(checkboxId)) {
|
||||
var checked = checkboxState[checkboxId];
|
||||
|
@ -7,23 +7,14 @@
|
||||
'value' => template::ico('left')
|
||||
]); ?>
|
||||
</div>
|
||||
<div class="col1 offset7">
|
||||
<?php echo template::button('courseUserDeleteSelectAll', [
|
||||
'value' => 'Tout'
|
||||
]); ?>
|
||||
</div>
|
||||
<div class="col1">
|
||||
<?php echo template::button('courseUserDeleteSelectNone', [
|
||||
'value' => 'Aucun'
|
||||
]); ?>
|
||||
</div>
|
||||
<div class="col2">
|
||||
<div class="col2 offset9">
|
||||
<?php echo template::submit('courseUsersDeleteSubmit', [
|
||||
'class' => 'buttonRed',
|
||||
'value' => 'Désinscrire'
|
||||
'ico' => 'minus',
|
||||
'value' => 'Désinscrire',
|
||||
]); ?>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row" id="Bfrtip">
|
||||
<div class="col3">
|
||||
<?php echo template::select('courseFilterGroup', $module::$courseGroups, [
|
||||
@ -43,9 +34,21 @@
|
||||
'selected' => isset($_POST['courseFilterLastName']) ? $_POST['courseFilterLastName'] : 'all',
|
||||
]); ?>
|
||||
</div>
|
||||
<div class="col1 offset1 verticalAlignBottom">
|
||||
<?php echo template::button('courseUserDeleteSelectAll', [
|
||||
'value' => template::ico('square-check'),
|
||||
'help' => 'Tout sélectionner'
|
||||
]); ?>
|
||||
</div>
|
||||
<div class="col1 verticalAlignBottom">
|
||||
<?php echo template::button('courseUserDeleteSelectNone', [
|
||||
'value' => template::ico('square-check-empty'),
|
||||
'help' => 'Tout désélectionner'
|
||||
]); ?>
|
||||
</div>
|
||||
</div>
|
||||
<?php if ($module::$courseUsers): ?>
|
||||
<?php echo template::table([1, 2, 3, 3, 3], $module::$courseUsers, ['', 'Id', 'Prénom', 'Nom', 'Étiquettes'], ['id' => 'dataTables']); ?>
|
||||
<?php echo template::table([1, 2, 3, 3, 3], $module::$courseUsers, ['', 'Id', 'Prénom', 'Nom', 'Étiquettes'], ['id' => 'dataTables']); ?>
|
||||
<?php else: ?>
|
||||
<?php echo template::speech('Aucun inscrit'); ?>
|
||||
<?php endif; ?>
|
||||
|
@ -119,6 +119,8 @@ class install extends common
|
||||
// Validation de la langue transmise
|
||||
self::$i18nUI = $_SESSION['ZWII_UI'];
|
||||
self::$i18nUI = array_key_exists(self::$i18nUI, self::$languages) ? self::$i18nUI : 'fr_FR';
|
||||
// Stockage de la langue par défaut afin d'afficher le site dans cette langue lors de l'affichage de la bannière de connexion.
|
||||
$this->setData(['config', 'defaultLanguageUI', self::$i18nUI], false);
|
||||
|
||||
// Création du dossier de contenu avec le marqueur de langue par défaut
|
||||
if (!is_dir(self::DATA_DIR . $_SESSION['ZWII_SITE_CONTENT'])) {
|
||||
@ -158,9 +160,9 @@ class install extends common
|
||||
);
|
||||
|
||||
// Sauvegarder la configuration du Proxy
|
||||
$this->setData(['config', 'proxyType', $this->getInput('installProxyType')]);
|
||||
$this->setData(['config', 'proxyUrl', $this->getInput('installProxyUrl')]);
|
||||
$this->setData(['config', 'proxyPort', $this->getInput('installProxyPort', helper::FILTER_INT)]);
|
||||
$this->setData(['config', 'proxyType', $this->getInput('installProxyType')], false);
|
||||
$this->setData(['config', 'proxyUrl', $this->getInput('installProxyUrl')], false);
|
||||
$this->setData(['config', 'proxyPort', $this->getInput('installProxyPort', helper::FILTER_INT)], false);
|
||||
|
||||
// Images exemples livrées dans tous les cas
|
||||
try {
|
||||
@ -194,11 +196,16 @@ class install extends common
|
||||
mkdir(self::I18N_DIR);
|
||||
}
|
||||
|
||||
// Créer le dossier de l'accueil dans les fichiers
|
||||
if (is_dir(self::FILE_DIR . 'source/home') === false) {
|
||||
mkdir(self::FILE_DIR . 'source/home');
|
||||
}
|
||||
|
||||
// Créer la base de données des langues
|
||||
$this->copyDir('core/module/install/ressource/i18n', self::I18N_DIR);
|
||||
|
||||
// Fixe l'adresse from pour les envois d'email
|
||||
$this->setData(['config', 'smtp', 'from', 'no-reply@' . str_replace('www.', '', $_SERVER['HTTP_HOST'])]);
|
||||
$this->setData(['config', 'smtp', 'from', 'no-reply@' . str_replace('www.', '', $_SERVER['HTTP_HOST'])], false);
|
||||
|
||||
// Valeurs en sortie
|
||||
$this->addOutput([
|
||||
@ -207,9 +214,10 @@ class install extends common
|
||||
'state' => true
|
||||
]);
|
||||
}
|
||||
// Force la sauvegarde
|
||||
$this->saveDB('config');
|
||||
|
||||
// Affichage du formulaire
|
||||
|
||||
// Valeurs en sortie
|
||||
$this->addOutput([
|
||||
'display' => self::DISPLAY_LAYOUT_LIGHT,
|
||||
@ -382,7 +390,7 @@ class install extends common
|
||||
'</IfModule>' . PHP_EOL .
|
||||
'# URL rewriting' . PHP_EOL;
|
||||
$fileContent = str_replace('# URL rewriting', $rewriteData, $fileContent);
|
||||
$success = file_put_contents(
|
||||
$success = $this->secure_file_put_contents(
|
||||
'.htaccess',
|
||||
$fileContent
|
||||
);
|
||||
|
@ -64,7 +64,7 @@ class init extends common
|
||||
]
|
||||
],
|
||||
'core' => [
|
||||
'dataVersion' => 1000,
|
||||
'dataVersion' => 1700,
|
||||
'lastBackup' => 0,
|
||||
'lastClearTmp' => 0,
|
||||
'lastAutoUpdate' => 0,
|
||||
@ -240,6 +240,21 @@ class init extends common
|
||||
'copycut' => false,
|
||||
'chmod' => false
|
||||
],
|
||||
'course' => [
|
||||
'tutor' => false,
|
||||
'index' => false,
|
||||
'manage' => false,
|
||||
'users' => false,
|
||||
'userHistory' => false,
|
||||
'userReportExport' => false,
|
||||
'usersAdd' => false,
|
||||
'userDelete' => false,
|
||||
'usersDelete' => false,
|
||||
'edit' => false,
|
||||
'backup' => false,
|
||||
'restore' => false,
|
||||
'reset' => false,
|
||||
],
|
||||
'folder' => [
|
||||
'create' => false,
|
||||
'delete' => false,
|
||||
@ -247,7 +262,8 @@ class init extends common
|
||||
'copycut' => false,
|
||||
'chmod' => false,
|
||||
'share' => false,
|
||||
'path' => null,
|
||||
'coursePath' => 'none',
|
||||
'homePath' => 'none'
|
||||
],
|
||||
'page' => [
|
||||
'add' => false,
|
||||
@ -321,6 +337,21 @@ class init extends common
|
||||
'copycut' => false,
|
||||
'chmod' => false
|
||||
],
|
||||
'course' => [
|
||||
'tutor' => false,
|
||||
'index' => false,
|
||||
'manage' => false,
|
||||
'users' => false,
|
||||
'userHistory' => false,
|
||||
'userReportExport' => false,
|
||||
'usersAdd' => false,
|
||||
'userDelete' => false,
|
||||
'usersDelete' => false,
|
||||
'edit' => false,
|
||||
'backup' => false,
|
||||
'restore' => false,
|
||||
'reset' => false,
|
||||
],
|
||||
'folder' => [
|
||||
'create' => false,
|
||||
'delete' => false,
|
||||
@ -328,7 +359,8 @@ class init extends common
|
||||
'copycut' => false,
|
||||
'chmod' => false,
|
||||
'share' => true,
|
||||
'path' => '/site/file/source/partage/',
|
||||
'coursePath' => 'none',
|
||||
'homePath' => '/site/file/source/partage/'
|
||||
],
|
||||
'page' => [
|
||||
'add' => false,
|
||||
@ -407,6 +439,21 @@ class init extends common
|
||||
'copycut' => false,
|
||||
'chmod' => false
|
||||
],
|
||||
'course' => [
|
||||
'tutor' => true,
|
||||
'index' => true,
|
||||
'manage' => true,
|
||||
'users' => true,
|
||||
'userHistory' => true,
|
||||
'userReportExport' => true,
|
||||
'usersAdd' => true,
|
||||
'userDelete' => false,
|
||||
'usersDelete' => false,
|
||||
'edit' => false,
|
||||
'backup' => false,
|
||||
'restore' => false,
|
||||
'reset' => false,
|
||||
],
|
||||
'folder' => [
|
||||
'create' => false,
|
||||
'delete' => false,
|
||||
@ -414,7 +461,8 @@ class init extends common
|
||||
'copycut' => false,
|
||||
'chmod' => false,
|
||||
'share' => true,
|
||||
'path' => '',
|
||||
'coursePath' => '',
|
||||
'homePath' => '/site/file/source/partage/'
|
||||
],
|
||||
'page' => [
|
||||
'add' => false,
|
||||
@ -489,6 +537,21 @@ class init extends common
|
||||
'copycut' => true,
|
||||
'chmod' => true
|
||||
],
|
||||
'course' => [
|
||||
'tutor' => false,
|
||||
'index' => true,
|
||||
'manage' => true,
|
||||
'users' => true,
|
||||
'userHistory' => true,
|
||||
'userReportExport' => true,
|
||||
'usersAdd' => true,
|
||||
'userDelete' => true,
|
||||
'usersDelete' => true,
|
||||
'edit' => true,
|
||||
'backup' => true,
|
||||
'restore' => true,
|
||||
'reset' => true,
|
||||
],
|
||||
'folder' => [
|
||||
'create' => true,
|
||||
'delete' => true,
|
||||
@ -496,7 +559,8 @@ class init extends common
|
||||
'copycut' => true,
|
||||
'chmod' => true,
|
||||
'share' => true,
|
||||
'path' => '',
|
||||
'coursePath' => '',
|
||||
'homePath' => '/site/file/source/partage/'
|
||||
],
|
||||
'page' => [
|
||||
'add' => true,
|
||||
|
Binary file not shown.
@ -6,7 +6,7 @@
|
||||
<div class="col6 offset3">
|
||||
<?php echo template::select('installLanguage', $module::$i18nFiles, [
|
||||
'label' => 'Langues installées',
|
||||
'selected' => array_key_exists ('fr_FR', $module::$i18nFiles) ? 'fr_FR': reset($module::$i18nFiles),
|
||||
'selected' => isset(self::$i18nUI) ? self::$i18nUI : 'fr_FR',
|
||||
]); ?>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -99,7 +99,7 @@ class language extends common
|
||||
is_array($descripteur['language'][$lang])
|
||||
) {
|
||||
if ($this->setData(['language', $lang, $descripteur['language'][$lang]])) {
|
||||
$success = file_put_contents(self::I18N_DIR . $lang . '.json', json_encode($languageData, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES | JSON_PRETTY_PRINT));
|
||||
$success = $this->secure_file_put_contents(self::I18N_DIR . $lang . '.json', json_encode($languageData, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES | JSON_PRETTY_PRINT));
|
||||
$success = is_int($success) ? true : false;
|
||||
}
|
||||
}
|
||||
|
@ -23,7 +23,8 @@ class page extends common
|
||||
'edit' => self::GROUP_EDITOR,
|
||||
'duplicate' => self::GROUP_EDITOR,
|
||||
'jsEditor' => self::GROUP_EDITOR,
|
||||
'cssEditor' => self::GROUP_EDITOR
|
||||
'cssEditor' => self::GROUP_EDITOR,
|
||||
'register' => self::GROUP_EDITOR,
|
||||
];
|
||||
public static $pagesNoParentId = [
|
||||
'' => 'Aucune'
|
||||
@ -68,10 +69,10 @@ class page extends common
|
||||
public static $userProfils = [];
|
||||
|
||||
public static $navIconTemplate = [
|
||||
'dir' => 'Petit triangle',
|
||||
'open' => 'Grand triangle',
|
||||
'big' => 'Flèche',
|
||||
];
|
||||
'dir' => 'Petit triangle',
|
||||
'open' => 'Grand triangle',
|
||||
'big' => 'Flèche',
|
||||
];
|
||||
|
||||
public static $navIconPosition = [
|
||||
'none' => 'Masqué',
|
||||
@ -85,12 +86,23 @@ class page extends common
|
||||
*/
|
||||
public function duplicate()
|
||||
{
|
||||
// La session ne correspond pas au site ouvert dans cet onglet
|
||||
if (
|
||||
// Contrôle la présence de l'id d'espace uniquement si l'id est fourni afin de ne pas bloquer les modules non mis à jour
|
||||
$this->getUrl(3) && $this->getUrl(3) != self::$siteContent
|
||||
) {
|
||||
$_SESSION['ZWII_SITE_CONTENT'] = $this->getUrl(3);
|
||||
header('Refresh:0; url=' . helper::baseUrl() . $this->getUrl());
|
||||
exit();
|
||||
}
|
||||
|
||||
// Adresse sans le token
|
||||
$page = $this->getUrl(2);
|
||||
|
||||
// La page n'existe pas
|
||||
if (
|
||||
$this->getUser('permission', __CLASS__, __FUNCTION__) !== true ||
|
||||
$this->getData(['page', $page]) === null
|
||||
$this->getUser('permission', __CLASS__, __FUNCTION__) !== true
|
||||
|| $this->getData(['page', $page]) === null
|
||||
) {
|
||||
// Valeurs en sortie
|
||||
$this->addOutput([
|
||||
@ -107,18 +119,20 @@ class page extends common
|
||||
$page
|
||||
]);
|
||||
// Ecriture
|
||||
$this->setData(['page', $pageId, $data]);
|
||||
$this->setData(['page', $pageId, $data], false);
|
||||
$notification = helper::translate('Page dupliquée');
|
||||
// Duplication du module présent
|
||||
if ($this->getData(['page', $page, 'moduleId'])) {
|
||||
$data = $this->getData(['module', $page]);
|
||||
$this->setData(['module', $pageId, $data]);
|
||||
$this->setData(['module', $pageId, $data], false);
|
||||
$notification = helper::translate('Page et module dupliqués');
|
||||
}
|
||||
// Force la sauvegarde
|
||||
$this->saveDB('page');
|
||||
|
||||
// Valeurs en sortie
|
||||
$this->addOutput([
|
||||
'redirect' => helper::baseUrl() . 'page/edit/' . $pageId,
|
||||
'redirect' => helper::baseUrl() . 'page/edit/' . $pageId . '/' . self::$siteContent,
|
||||
'notification' => $notification,
|
||||
'state' => true
|
||||
]);
|
||||
@ -131,7 +145,19 @@ class page extends common
|
||||
*/
|
||||
public function add()
|
||||
{
|
||||
if ($this->getUser('permission', __CLASS__, __FUNCTION__) !== true) {
|
||||
// La session ne correspond pas au site ouvert dans cet onglet
|
||||
if (
|
||||
// Contrôle la présence de l'id d'espace uniquement si l'id est fourni afin de ne pas bloquer les modules non mis à jour
|
||||
$this->getUrl(3) && $this->getUrl(3) != self::$siteContent
|
||||
) {
|
||||
$_SESSION['ZWII_SITE_CONTENT'] = $this->getUrl(3);
|
||||
header('Refresh:0; url=' . helper::baseUrl() . $this->getUrl());
|
||||
exit();
|
||||
}
|
||||
|
||||
if (
|
||||
$this->getUser('permission', __CLASS__, __FUNCTION__) !== true
|
||||
) {
|
||||
// Valeurs en sortie
|
||||
$this->addOutput([
|
||||
'access' => false
|
||||
@ -180,8 +206,8 @@ class page extends common
|
||||
//file_put_contents(self::DATA_DIR . self::$siteContent . '/content/' . $pageId . '.html', '<p>Contenu de votre nouvelle page.</p>');
|
||||
$this->setPage($pageId, '<p>Contenu de votre nouvelle page.</p>', self::$siteContent);
|
||||
|
||||
// Met à jour le sitemap
|
||||
$this->updateSitemap();
|
||||
// Ne met à jour le sitemap pour éviter un warning, de toute manière la nouvelle page doit être éditée.
|
||||
// $this->updateSitemap();
|
||||
|
||||
// Valeurs en sortie
|
||||
$this->addOutput([
|
||||
@ -198,12 +224,24 @@ class page extends common
|
||||
*/
|
||||
public function delete()
|
||||
{
|
||||
|
||||
// La session ne correspond pas au site ouvert dans cet onglet
|
||||
if (
|
||||
// Contrôle la présence de l'id d'espace uniquement si l'id est fourni afin de ne pas bloquer les modules non mis à jour
|
||||
$this->getUrl(3) && $this->getUrl(3) != self::$siteContent
|
||||
) {
|
||||
$_SESSION['ZWII_SITE_CONTENT'] = $this->getUrl(3);
|
||||
header('Refresh:0; url=' . helper::baseUrl() . $this->getUrl());
|
||||
exit();
|
||||
}
|
||||
|
||||
// $url prend l'adresse sans le token
|
||||
$page = $this->getUrl(2);
|
||||
|
||||
// La page n'existe pas
|
||||
if (
|
||||
$this->getUser('permission', __CLASS__, __FUNCTION__) !== true ||
|
||||
$this->getData(['page', $page]) === null
|
||||
$this->getUser('permission', __CLASS__, __FUNCTION__) !== true
|
||||
|| $this->getData(['page', $page]) === null
|
||||
) {
|
||||
// Valeurs en sortie
|
||||
$this->addOutput([
|
||||
@ -214,8 +252,10 @@ class page extends common
|
||||
elseif ($page === $this->homePageId()) {
|
||||
// Valeurs en sortie
|
||||
$this->addOutput([
|
||||
'redirect' => helper::baseUrl() . 'config',
|
||||
'notification' => helper::translate('Suppression interdite, page active dans la configuration de la langue du site')
|
||||
'redirect' => helper::baseUrl() . $this->homePageId(),
|
||||
'notification' => self::$siteContent === 'home'
|
||||
? helper::translate('Suppression interdite, cette page est définie comme page d\'accueil du site')
|
||||
: helper::translate('Suppression interdite, cette page est définie comme page d\'accueil d\'un espace')
|
||||
]);
|
||||
}
|
||||
// Impossible de supprimer la page affectée
|
||||
@ -223,7 +263,7 @@ class page extends common
|
||||
// Valeurs en sortie
|
||||
$this->addOutput([
|
||||
'redirect' => helper::baseUrl() . 'config',
|
||||
'notification' => helper::translate('Suppression interdite, page active dans la configuration de la langue du site')
|
||||
'notification' => helper::translate('Suppression interdite, page active dans la configuration du site')
|
||||
]);
|
||||
}
|
||||
// Impossible de supprimer la page affectée
|
||||
@ -231,7 +271,7 @@ class page extends common
|
||||
// Valeurs en sortie
|
||||
$this->addOutput([
|
||||
'redirect' => helper::baseUrl() . 'config',
|
||||
'notification' => helper::translate('Suppression interdite, page active dans la configuration de la langue du site')
|
||||
'notification' => helper::translate('Suppression interdite, page active dans la configuration du site')
|
||||
]);
|
||||
}
|
||||
// Impossible de supprimer la page affectée
|
||||
@ -239,7 +279,7 @@ class page extends common
|
||||
// Valeurs en sortie
|
||||
$this->addOutput([
|
||||
'redirect' => helper::baseUrl() . 'config',
|
||||
'notification' => helper::translate('Suppression interdite, page active dans la configuration de la langue du site')
|
||||
'notification' => helper::translate('Suppression interdite, page active dans la configuration du site')
|
||||
]);
|
||||
}
|
||||
// Impossible de supprimer la page affectée
|
||||
@ -247,7 +287,7 @@ class page extends common
|
||||
// Valeurs en sortie
|
||||
$this->addOutput([
|
||||
'redirect' => helper::baseUrl() . 'config',
|
||||
'notification' => helper::translate('Suppression interdite, page active dans la configuration de la langue du site')
|
||||
'notification' => helper::translate('Suppression interdite, page active dans la configuration du site')
|
||||
]);
|
||||
}
|
||||
// Impossible de supprimer la page affectée
|
||||
@ -255,14 +295,14 @@ class page extends common
|
||||
// Valeurs en sortie
|
||||
$this->addOutput([
|
||||
'redirect' => helper::baseUrl() . 'config',
|
||||
'notification' => helper::translate('Suppression interdite, page active dans la configuration de la langue du site')
|
||||
'notification' => helper::translate('Suppression interdite, page active dans la configuration du site')
|
||||
]);
|
||||
}
|
||||
// Impossible de supprimer une page contenant des enfants
|
||||
elseif ($this->getHierarchy($page, null)) {
|
||||
// Valeurs en sortie
|
||||
$this->addOutput([
|
||||
'redirect' => helper::baseUrl() . 'page/edit/' . $page,
|
||||
'redirect' => helper::baseUrl() . 'page/edit/' . $page . '/' . self::$siteContent,
|
||||
'notification' => helper::translate('Impossible de supprimer une page contenant des pages enfants')
|
||||
]);
|
||||
}
|
||||
@ -302,10 +342,24 @@ class page extends common
|
||||
*/
|
||||
public function edit()
|
||||
{
|
||||
// La session ne correspond pas au site ouvert dans cet onglet
|
||||
if (
|
||||
// Contrôle la présence de l'id d'espace uniquement si l'id est fourni afin de ne pas bloquer les modules non mis à jour
|
||||
$this->getUrl(3) && $this->getUrl(3) != self::$siteContent
|
||||
) {
|
||||
$_SESSION['ZWII_SITE_CONTENT'] = $this->getUrl(3);
|
||||
header('Refresh:0; url=' . helper::baseUrl() . $this->getUrl());
|
||||
exit();
|
||||
}
|
||||
// La page n'existe pas
|
||||
if (
|
||||
$this->getUser('permission', __CLASS__, __FUNCTION__) !== true ||
|
||||
$this->getData(['page', $this->getUrl(2)]) === null
|
||||
$this->getUser('permission', __CLASS__, __FUNCTION__) !== true
|
||||
|| $this->getData(['page', $this->getUrl(2)]) === null
|
||||
// Contrôle la présence de l'id d'espace uniquement si l'id est fourni afin de ne pas bloquer les modules non mis à jour
|
||||
|| (
|
||||
$this->getUrl(3)
|
||||
&& $this->getUrl(3) != self::$siteContent
|
||||
)
|
||||
) {
|
||||
// Valeurs en sortie
|
||||
$this->addOutput([
|
||||
@ -339,11 +393,11 @@ class page extends common
|
||||
$pageId = helper::increment($pageId, self::$moduleIds);
|
||||
// Met à jour les enfants
|
||||
foreach ($this->getHierarchy($this->getUrl(2), null) as $childrenPageId) {
|
||||
$this->setData(['page', $childrenPageId, 'parentPageId', $pageId]);
|
||||
$this->setData(['page', $childrenPageId, 'parentPageId', $pageId], false);
|
||||
}
|
||||
// Change l'id de page dans les données des modules
|
||||
if ($this->getData(['module', $this->getUrl(2)]) !== null) {
|
||||
$this->setData(['module', $pageId, $this->getData(['module', $this->getUrl(2)])]);
|
||||
$this->setData(['module', $pageId, $this->getData(['module', $this->getUrl(2)])], false);
|
||||
$this->deleteData(['module', $this->getUrl(2)]);
|
||||
// Renommer le dossier du module
|
||||
$moduleId = $this->getData(['page', $this->getUrl(2), 'moduleId']);
|
||||
@ -354,12 +408,42 @@ class page extends common
|
||||
copy($modulesData[$moduleId]['dataDirectory'] . $this->getUrl(2), $modulesData[$moduleId]['dataDirectory'] . $pageId);
|
||||
$this->deleteDir($modulesData[$moduleId]['dataDirectory'] . $this->getUrl(2));
|
||||
// Mettre à jour le nom de la feuille de style
|
||||
$this->setData(['module', $pageId, 'theme', 'style', $modulesData[$moduleId]['dataDirectory'] . $pageId]);
|
||||
$this->setData(['module', $pageId, 'theme', 'style', $modulesData[$moduleId]['dataDirectory'] . $pageId], false);
|
||||
}
|
||||
// Sauvegarde la base manuellement
|
||||
$this->saveDB('module');
|
||||
}
|
||||
/*
|
||||
*
|
||||
* Met à jour les historiques des utilisateurs
|
||||
foreach ($this->getData(['enrolment', self::$siteContent]) as $userId => $userData) {
|
||||
// Vérifier si l'utilisateur a un historique
|
||||
if (
|
||||
isset($userData["history"])
|
||||
&& isset($userData['history'][$this->getUrl(2)])
|
||||
) {
|
||||
// Remplacer l'ancienne ID par la nouvelle
|
||||
$datas = $this->getData(['enrolment', self::$siteContent, $userId, 'history', $this->getUrl(2)]);
|
||||
$this->setData(['enrolment', self::$siteContent, $userId, 'history', $pageId, $datas], false);
|
||||
$this->deleteData(['enrolment', self::$siteContent, $userId, 'history', $this->getUrl(2)]);
|
||||
}
|
||||
// Mettre à jour la dernière page vue si nécessaire
|
||||
if ($this->getData(['enrolment', self::$siteContent, $userId, 'lastPageView']) === $this->getUrl(2)) {
|
||||
$this->setData(['enrolment', self::$siteContent, $userId, 'lastPageView', $pageId], false);
|
||||
}
|
||||
}
|
||||
// Sauvegarde la base manuellement
|
||||
$this->saveDB('enrolment');
|
||||
**/
|
||||
|
||||
// Met à jour la homePage si nécessaire
|
||||
if ($this->getUrl(2) === $this->getData(['course', self::$siteContent, 'homePageId'])) {
|
||||
$this->setData(['course', self::$siteContent, 'homePageId', $pageId]);
|
||||
}
|
||||
|
||||
// Si la page correspond à la page d'accueil, change l'id dans la configuration du site
|
||||
if ($this->getData(['config', 'homePageId']) === $this->getUrl(2)) {
|
||||
$this->setData(['config', 'homePageId', $pageId]);
|
||||
$this->setData(['config', 'homePageId', $pageId], false);
|
||||
}
|
||||
}
|
||||
// Supprime les données du module en cas de changement de module
|
||||
@ -375,20 +459,22 @@ class page extends common
|
||||
}
|
||||
// Traitement des pages spéciales affectées dans la config :
|
||||
if ($this->getUrl(2) === $this->getData(['config', 'legalPageId'])) {
|
||||
$this->setData(['config', 'legalPageId', $pageId]);
|
||||
$this->setData(['config', 'legalPageId', $pageId], false);
|
||||
}
|
||||
if ($this->getUrl(2) === $this->getData(['config', 'searchPageId'])) {
|
||||
$this->setData(['config', 'searchPageId', $pageId]);
|
||||
$this->setData(['config', 'searchPageId', $pageId], false);
|
||||
}
|
||||
if ($this->getUrl(2) === $this->getData(['config', 'page404'])) {
|
||||
$this->setData(['config', 'page404', $pageId]);
|
||||
$this->setData(['config', 'page404', $pageId], false);
|
||||
}
|
||||
if ($this->getUrl(2) === $this->getData(['config', 'page403'])) {
|
||||
$this->setData(['config', 'page403', $pageId]);
|
||||
$this->setData(['config', 'page403', $pageId], false);
|
||||
}
|
||||
if ($this->getUrl(2) === $this->getData(['config', 'page302'])) {
|
||||
$this->setData(['config', 'page302', $pageId]);
|
||||
$this->setData(['config', 'page302', $pageId], false);
|
||||
}
|
||||
// Sauvegarde la base manuellement
|
||||
$this->saveDB(module: '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());
|
||||
@ -407,11 +493,12 @@ class page extends common
|
||||
$lastPosition++;
|
||||
}
|
||||
// Change la position
|
||||
$this->setData(['page', $hierarchyPageId, 'position', $lastPosition]);
|
||||
$this->setData(['page', $hierarchyPageId, 'position', $lastPosition], false);
|
||||
// Incrémente pour la prochaine position
|
||||
$lastPosition++;
|
||||
}
|
||||
}
|
||||
|
||||
if ($this->getinput('pageEditBlock') !== 'bar') {
|
||||
$barLeft = $this->getinput('pageEditBarLeft');
|
||||
$barRight = $this->getinput('pageEditBarRight');
|
||||
@ -432,7 +519,7 @@ class page extends common
|
||||
) {
|
||||
foreach ($this->getHierarchy($pageId) as $parentId => $childId) {
|
||||
if ($this->getData(['page', $childId, 'parentPageId']) === $pageId) {
|
||||
$this->setData(['page', $childId, 'position', 0]);
|
||||
$this->setData(['page', $childId, 'position', 0], false);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -441,17 +528,17 @@ class page extends common
|
||||
if ($this->getinput('pageEditBlock') === 'bar') {
|
||||
foreach ($this->getHierarchy() as $eachPageId => $parentId) {
|
||||
if ($this->getData(['page', $eachPageId, 'barRight']) === $this->getUrl(2)) {
|
||||
$this->setData(['page', $eachPageId, 'barRight', $pageId]);
|
||||
$this->setData(['page', $eachPageId, 'barRight', $pageId], false);
|
||||
}
|
||||
if ($this->getData(['page', $eachPageId, 'barLeft']) === $this->getUrl(2)) {
|
||||
$this->setData(['page', $eachPageId, 'barLeft', $pageId]);
|
||||
$this->setData(['page', $eachPageId, 'barLeft', $pageId], false);
|
||||
}
|
||||
foreach ($parentId as $childId) {
|
||||
if ($this->getData(['page', $childId, 'barRight']) === $this->getUrl(2)) {
|
||||
$this->setData(['page', $childId, 'barRight', $pageId]);
|
||||
$this->setData(['page', $childId, 'barRight', $pageId], false);
|
||||
}
|
||||
if ($this->getData(['page', $childId, 'barLeft']) === $this->getUrl(2)) {
|
||||
$this->setData(['page', $childId, 'barLeft', $pageId]);
|
||||
$this->setData(['page', $childId, 'barLeft', $pageId], false);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -602,14 +689,15 @@ class page extends common
|
||||
$css = $this->getInput('pageCssEditorContent', helper::FILTER_STRING_LONG) === null ? '' : $this->getInput('pageCssEditorContent', helper::FILTER_STRING_LONG);
|
||||
// Enregistre le CSS
|
||||
$this->setData([
|
||||
'page', $this->getUrl(2),
|
||||
'page',
|
||||
$this->getUrl(2),
|
||||
'css',
|
||||
$css
|
||||
]);
|
||||
// Valeurs en sortie
|
||||
$this->addOutput([
|
||||
'notification' => helper::translate('Modifications enregistrées'),
|
||||
'redirect' => helper::baseUrl() . 'page/edit/' . $this->getUrl(2),
|
||||
'redirect' => helper::baseUrl() . 'page/edit/' . $this->getUrl(2) . '/' . self::$siteContent,
|
||||
'state' => true
|
||||
]);
|
||||
}
|
||||
@ -636,14 +724,15 @@ class page extends common
|
||||
$js = $this->getInput('pageJsEditorContent', helper::FILTER_STRING_LONG) === null ? '' : $this->getInput('pageJsEditorContent', helper::FILTER_STRING_LONG);
|
||||
// Enregistre le JS
|
||||
$this->setData([
|
||||
'page', $this->getUrl(2),
|
||||
'page',
|
||||
$this->getUrl(2),
|
||||
'js',
|
||||
$js
|
||||
]);
|
||||
// Valeurs en sortie
|
||||
$this->addOutput([
|
||||
'notification' => helper::translate('Modifications enregistrées'),
|
||||
'redirect' => helper::baseUrl() . 'page/edit/' . $this->getUrl(2),
|
||||
'redirect' => helper::baseUrl() . 'page/edit/' . $this->getUrl(2) . '/' . self::$siteContent,
|
||||
'state' => true
|
||||
]);
|
||||
}
|
||||
@ -659,7 +748,7 @@ class page extends common
|
||||
|
||||
/**
|
||||
* Retourne les informations sur les pages en omettant les clés CSS et JS qui occasionnent des bugs d'affichage dans l'éditeur de page
|
||||
* @return array tableau associatif des pages dans le menu
|
||||
* @return string tableau associatif des pages dans le menu
|
||||
*/
|
||||
public function getPageInfo()
|
||||
{
|
||||
@ -669,6 +758,27 @@ class page extends common
|
||||
return $d;
|
||||
}, $p);
|
||||
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,
|
||||
]);
|
||||
}
|
||||
|
||||
}
|
@ -3,7 +3,7 @@
|
||||
<div class="col1">
|
||||
<?php echo template::button('pageCssEditorBack', [
|
||||
'class' => 'buttonGrey',
|
||||
'href' => helper::baseUrl() . 'page/edit/' . $this->getUrl(2),
|
||||
'href' => helper::baseUrl() . 'page/edit/' . $this->getUrl(2) . '/' . self::$siteContent,
|
||||
'value' => template::ico('left')
|
||||
]); ?>
|
||||
</div>
|
||||
|
@ -67,16 +67,18 @@ $( document ).ready(function() {
|
||||
/**
|
||||
* Sélection des onglets
|
||||
*/
|
||||
var pageLayout = getCookie("pageLayout");
|
||||
if (pageLayout == null) {
|
||||
var pageLayout = "<?php echo $this->getData(['user', $this->getUser('id'), 'view', 'page']);?>";
|
||||
// Non défini, valeur par défaut
|
||||
if (pageLayout == "") {
|
||||
pageLayout = "content";
|
||||
setCookie("pageLayout", "content");
|
||||
}
|
||||
// Tout cacher
|
||||
$("#pageEditContentContainer").hide();
|
||||
$("#pageEditExtensionContainer").hide();
|
||||
$("#pageEditPositionContainer").hide();
|
||||
$("#pageEditLayoutContainer").hide();
|
||||
$("#pageEditPermissionContainer").hide();
|
||||
// Afficher la bonne tab
|
||||
$("#pageEdit" + capitalizeFirstLetter(pageLayout) + "Container").show();
|
||||
$("#pageEdit" + capitalizeFirstLetter(pageLayout) + "Button").addClass("activeButton");
|
||||
|
||||
@ -295,7 +297,6 @@ $( document ).ready(function() {
|
||||
$("#PageEditPositionButton").removeClass("activeButton");
|
||||
$("#pageEditLayoutButton").removeClass("activeButton");
|
||||
$("#pageEditPermissionButton").removeClass("activeButton");
|
||||
setCookie("pageLayout", "content");
|
||||
});
|
||||
$("#pageEditExtensionButton").on("click", function () {
|
||||
$("#pageEditContentContainer").hide();
|
||||
@ -308,7 +309,6 @@ $( document ).ready(function() {
|
||||
$("#PageEditPositionButton").removeClass("activeButton");
|
||||
$("#pageEditLayoutButton").removeClass("activeButton");
|
||||
$("#pageEditPermissionButton").removeClass("activeButton");
|
||||
setCookie("pageLayout", "extension");
|
||||
});
|
||||
$("#PageEditPositionButton").on("click", function () {
|
||||
$("#pageEditContentContainer").hide();
|
||||
@ -321,7 +321,6 @@ $( document ).ready(function() {
|
||||
$("#PageEditPositionButton").addClass("activeButton");
|
||||
$("#pageEditLayoutButton").removeClass("activeButton");
|
||||
$("#pageEditPermissionButton").removeClass("activeButton");
|
||||
setCookie("pageLayout", "position");
|
||||
});
|
||||
$("#pageEditLayoutButton").on("click", function () {
|
||||
$("#pageEditContentContainer").hide();
|
||||
@ -334,7 +333,6 @@ $( document ).ready(function() {
|
||||
$("#PageEditPositionButton").removeClass("activeButton");
|
||||
$("#pageEditLayoutButton").addClass("activeButton");
|
||||
$("#pageEditPermissionButton").removeClass("activeButton");
|
||||
setCookie("pageLayout", "layout");
|
||||
});
|
||||
$("#pageEditPermissionButton").on("click", function () {
|
||||
$("#pageEditContentContainer").hide();
|
||||
@ -347,7 +345,6 @@ $( document ).ready(function() {
|
||||
$("#pageEditPositionButton").removeClass("activeButton");
|
||||
$("#pageEditLayoutButton").removeClass("activeButton");
|
||||
$("#pageEditPermissionButton").addClass("activeButton");
|
||||
setCookie("pageLayout", "permission");
|
||||
});
|
||||
|
||||
/**
|
||||
@ -722,30 +719,6 @@ function buildPagesList(extraPosition) {
|
||||
positionDOM.val(positionSelected);
|
||||
};
|
||||
|
||||
/**
|
||||
* Cookies
|
||||
*/
|
||||
function setCookie(name, value, days) {
|
||||
var expires = "";
|
||||
if (days) {
|
||||
var date = new Date();
|
||||
date.setTime(date.getTime() + (days * 24 * 60 * 60 * 1000));
|
||||
expires = "; expires=" + date.toUTCString();
|
||||
}
|
||||
document.cookie = name + "=" + (value || "") + expires + "; path=/; samesite=lax";
|
||||
}
|
||||
|
||||
function getCookie(name) {
|
||||
var nameEQ = name + "=";
|
||||
var ca = document.cookie.split(';');
|
||||
for (var i = 0; i < ca.length; i++) {
|
||||
var c = ca[i];
|
||||
while (c.charAt(0) == ' ') c = c.substring(1, c.length);
|
||||
if (c.indexOf(nameEQ) == 0) return c.substring(nameEQ.length, c.length);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
// Define function to capitalize the first letter of a string
|
||||
function capitalizeFirstLetter(string) {
|
||||
return string.charAt(0).toUpperCase() + string.slice(1);
|
||||
|
@ -1,4 +1,6 @@
|
||||
<?php echo template::formOpen('pageEditForm'); ?>
|
||||
<!-- Variable transmise à TinyMCE -->
|
||||
<div id="zwii_site_content" data-variable="<?php echo htmlspecialchars(isset($_SESSION['ZWII_SITE_CONTENT']) ? $_SESSION['ZWII_SITE_CONTENT'] : 'home'); ?>"></div>
|
||||
<div class="row">
|
||||
<div class="col1">
|
||||
<?php echo template::button('configModulesBack', [
|
||||
@ -7,26 +9,17 @@
|
||||
'value' => template::ico('left')
|
||||
]); ?>
|
||||
</div>
|
||||
<div class="col1">
|
||||
<?php /**echo template::button('pageEditHelp', [
|
||||
'href' => 'https://doc.zwiicms.fr/edition-des-pages',
|
||||
'target' => '_blank',
|
||||
'value' => template::ico('help'),
|
||||
'class' => 'buttonHelp',
|
||||
'help' => 'Consulter l\'aide en ligne'
|
||||
]); */?>
|
||||
</div>
|
||||
<div class="col1 offset6">
|
||||
<div class="col1 offset7">
|
||||
<?php echo template::button('pageEditDelete', [
|
||||
'class' => 'buttonRed',
|
||||
'href' => helper::baseUrl() . 'page/delete/' . $this->getUrl(2),
|
||||
'href' => helper::baseUrl() . 'page/delete/' . $this->getUrl(2) . '/' . self::$siteContent,
|
||||
'value' => template::ico('trash'),
|
||||
'help' => 'Effacer la page'
|
||||
]); ?>
|
||||
</div>
|
||||
<div class="col1">
|
||||
<?php echo template::button('pageEditDuplicate', [
|
||||
'href' => helper::baseUrl() . 'page/duplicate/' . $this->getUrl(2),
|
||||
'href' => helper::baseUrl() . 'page/duplicate/' . $this->getUrl(2) . '/' . self::$siteContent,
|
||||
'value' => template::ico('clone'),
|
||||
'help' => 'Dupliquer la page'
|
||||
]); ?>
|
||||
@ -41,23 +34,28 @@
|
||||
<div class="tab">
|
||||
<?php echo template::button('pageEditContentButton', [
|
||||
'value' => 'Contenu',
|
||||
'class' => 'buttonTab'
|
||||
'class' => 'buttonTab',
|
||||
'href' => helper::baseUrl() . 'page/register/content/' . $this->geturl(2)
|
||||
]); ?>
|
||||
<?php echo template::button('PageEditPositionButton', [
|
||||
<?php echo template::button('pageEditPositionButton', [
|
||||
'value' => 'Menu',
|
||||
'class' => 'buttonTab'
|
||||
'class' => 'buttonTab',
|
||||
'href' => helper::baseUrl() . 'page/register/position/' . $this->geturl(2)
|
||||
]); ?>
|
||||
<?php echo template::button('pageEditExtensionButton', [
|
||||
'value' => 'Extension',
|
||||
'class' => 'buttonTab'
|
||||
'class' => 'buttonTab',
|
||||
'href' => helper::baseUrl() . 'page/register/extension/' . $this->geturl(2)
|
||||
]); ?>
|
||||
<?php echo template::button('pageEditLayoutButton', [
|
||||
'value' => 'Mise en page',
|
||||
'class' => 'buttonTab'
|
||||
'class' => 'buttonTab',
|
||||
'href' => helper::baseUrl() . 'page/register/layout/' . $this->geturl(2)
|
||||
]); ?>
|
||||
<?php echo template::button('pageEditPermissionButton', [
|
||||
'value' => 'Permission',
|
||||
'class' => 'buttonTab'
|
||||
'class' => 'buttonTab',
|
||||
'href' => helper::baseUrl() . 'page/register/permission/' . $this->geturl(2)
|
||||
]); ?>
|
||||
</div>
|
||||
|
||||
@ -67,11 +65,6 @@
|
||||
<div class="block">
|
||||
<h4>
|
||||
<?php echo helper::translate('Titres'); ?>
|
||||
<!--<span id="infoHelpButton" class="helpDisplayButton">
|
||||
<a href="https://doc.zwiicms.fr/informations-generales" target="_blank" title="Cliquer pour consulter l'aide en ligne">
|
||||
<?php //echo template::ico('help', ['margin' => 'left']); ?>
|
||||
</a>
|
||||
</span>-->
|
||||
</h4>
|
||||
<div class="row">
|
||||
<div class="col8">
|
||||
@ -120,11 +113,6 @@
|
||||
<div class="block">
|
||||
<h4>
|
||||
<?php echo helper::translate('Emplacement dans le menu'); ?>
|
||||
<!--<span id="positionHelpButton" class="helpDisplayButton">
|
||||
<a href="https://doc.zwiicms.fr/emplacement-dans-le-menu" target="_blank" title="Cliquer pour consulter l'aide en ligne">
|
||||
<?php //echo template::ico('help', ['margin' => 'left']); ?>
|
||||
</a>
|
||||
</span>-->
|
||||
</h4>
|
||||
<div class="blockContainer">
|
||||
<div class="row">
|
||||
@ -176,11 +164,6 @@
|
||||
<div class="block">
|
||||
<h4>
|
||||
<?php echo helper::translate('Options avancées'); ?>
|
||||
<!--<span id="advancedHelpButton" class="helpDisplayButton">
|
||||
<a href="https://doc.zwiicms.fr/options-d-emplacement-avancee" target="_blank" title="Cliquer pour consulter l'aide en ligne">
|
||||
<?php //echo template::ico('help', ['margin' => 'left']); ?>
|
||||
</a>
|
||||
</span>-->
|
||||
</h4>
|
||||
<div class="blockContainer">
|
||||
<div class="row">
|
||||
@ -195,7 +178,8 @@
|
||||
'help' => 'Sélectionnez une image ou une icône de petite dimension',
|
||||
'language' => $this->getData(['user', $this->getUser('id'), 'language']),
|
||||
'label' => 'Icône',
|
||||
'value' => $this->getData(['page', $this->getUrl(2), 'iconUrl'])
|
||||
'value' => $this->getData(['page', $this->getUrl(2), 'iconUrl']),
|
||||
'folder' => $this->getData(['page', $this->getUrl(2), 'iconUrl']) ? dirname($this->getData(['page', $this->getUrl(2), 'iconUrl'])) : '',
|
||||
]); ?>
|
||||
</div>
|
||||
</div>
|
||||
@ -292,11 +276,6 @@
|
||||
<div class="block">
|
||||
<h4>
|
||||
<?php echo helper::translate('Mise en page'); ?>
|
||||
<!--<span id="layoutHelpButton" class="helpDisplayButton">
|
||||
<a href="https://doc.zwiicms.fr/mise-en-page-2" target="_blank" title="Cliquer pour consulter l'aide en ligne">
|
||||
<?php //echo template::ico('help', ['margin' => 'left']); ?>
|
||||
</a>
|
||||
</span>-->
|
||||
</h4>
|
||||
<div class="blockContainer">
|
||||
<div class="row">
|
||||
@ -372,11 +351,6 @@
|
||||
<div class="block">
|
||||
<h4>
|
||||
<?php echo helper::translate('Permission et référencement'); ?>
|
||||
<!--<span id="seoHelpButton" class="helpDisplayButton">
|
||||
<a href="https://doc.zwiicms.fr/permission-et-referencement" target="_blank" title="Cliquer pour consulter l'aide en ligne">
|
||||
<?php //echo template::ico('help', ['margin' => 'left']); ?>
|
||||
</a>
|
||||
</span>-->
|
||||
</h4>
|
||||
<div class="blockContainer">
|
||||
<div class="row">
|
||||
@ -424,5 +398,4 @@
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<?php echo template::formClose(); ?>
|
@ -3,7 +3,7 @@
|
||||
<div class="col1">
|
||||
<?php echo template::button('pageJsEditorBack', [
|
||||
'class' => 'buttonGrey',
|
||||
'href' => helper::baseUrl() . 'page/edit/' . $this->getUrl(2),
|
||||
'href' => helper::baseUrl() . 'page/edit/' . $this->getUrl(2) . '/' . self::$siteContent,
|
||||
'value' => template::ico('left')
|
||||
]); ?>
|
||||
</div>
|
||||
|
@ -25,7 +25,7 @@ class plugin extends common
|
||||
'delete' => self::GROUP_ADMIN,
|
||||
'save' => self::GROUP_ADMIN,
|
||||
'store' => self::GROUP_ADMIN,
|
||||
'item' => self::GROUP_ADMIN,
|
||||
//'item' => self::GROUP_ADMIN,
|
||||
// détail d'un objet
|
||||
'upload' => self::GROUP_ADMIN,
|
||||
// Téléverser catalogue
|
||||
@ -237,8 +237,8 @@ class plugin extends common
|
||||
return ([
|
||||
'success' => $success,
|
||||
'notification' => $success
|
||||
? sprintf(helper::translate('Le module %s a été %s'), $module['name'], $t)
|
||||
: helper::translate('Erreur inconnue, le module n\'est pas installé')
|
||||
? sprintf(helper::translate('Le module %s a été %s'), $module['name'], $t)
|
||||
: helper::translate('Erreur inconnue, le module n\'est pas installé')
|
||||
]);
|
||||
} else {
|
||||
// Supprimer le dossier temporaire
|
||||
@ -391,7 +391,6 @@ class plugin extends common
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
// Valeurs en sortie
|
||||
$this->addOutput([
|
||||
'title' => helper::translate('Catalogue de modules'),
|
||||
@ -414,6 +413,16 @@ class plugin extends common
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Retourne le contenu du store en ligne
|
||||
* @return mixed
|
||||
*/
|
||||
public static function getStore()
|
||||
{
|
||||
$store = json_decode(helper::getUrlContents(self::BASEURL_STORE . self::MODULE_STORE . 'list'), true);
|
||||
return $store;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gestion des modules
|
||||
*/
|
||||
@ -561,6 +570,9 @@ class plugin extends common
|
||||
}
|
||||
}
|
||||
|
||||
// Désactive l'icône rouge
|
||||
$this->setData(['core', 'updateModuleAvailable', false]);
|
||||
|
||||
// Valeurs en sortie
|
||||
$this->addOutput([
|
||||
'title' => helper::translate('Gestion des modules'),
|
||||
|
@ -507,21 +507,23 @@ class theme extends common
|
||||
'featureContent' => $featureContent,
|
||||
'featureFiles' => $files
|
||||
]
|
||||
]);
|
||||
], false);
|
||||
// Modification de la position du menu selon la position de la bannière
|
||||
if ($this->getData(['theme', 'header', 'position']) == 'site') {
|
||||
$this->setData(['theme', 'menu', 'position', str_replace('body-', 'site-', $this->getData(['theme', 'menu', 'position']))]);
|
||||
$this->setData(['theme', 'menu', 'position', str_replace('body-', 'site-', $this->getData(['theme', 'menu', 'position']))], false);
|
||||
}
|
||||
if ($this->getData(['theme', 'header', 'position']) == 'body') {
|
||||
$this->setData(['theme', 'menu', 'position', str_replace('site-', 'body-', $this->getData(['theme', 'menu', 'position']))]);
|
||||
$this->setData(['theme', 'menu', 'position', str_replace('site-', 'body-', $this->getData(['theme', 'menu', 'position']))], false);
|
||||
}
|
||||
// Menu accroché à la bannière qui devient cachée
|
||||
if (
|
||||
$this->getData(['theme', 'header', 'position']) == 'hide' &&
|
||||
in_array($this->getData(['theme', 'menu', 'position']), ['body-first', 'site-first', 'body-first', 'site-second'])
|
||||
) {
|
||||
$this->setData(['theme', 'menu', 'position', 'site']);
|
||||
$this->setData(['theme', 'menu', 'position', 'site'], false);
|
||||
}
|
||||
// Sauvegarde la base manuellement
|
||||
$this->saveDB(module: 'theme');
|
||||
// Valeurs en sortie
|
||||
$this->addOutput([
|
||||
'notification' => helper::translate('Modifications enregistrées'),
|
||||
@ -636,11 +638,11 @@ class theme extends common
|
||||
// Polices liées aux thèmes des espaces
|
||||
foreach ($this->getData(['course']) as $courseId => $courseValue) {
|
||||
$theme = json_decode(file_get_contents(self::DATA_DIR . $courseId . '/theme.json'), true);
|
||||
$fonts['Bannière ('. $courseId .')'] = $theme['theme']['header']['font'];
|
||||
$fonts['Menu ('. $courseId .')'] = $theme['theme']['menu']['font'];
|
||||
$fonts['Titre ('. $courseId .')'] = $theme['theme']['title']['font'];
|
||||
$fonts['Texte ('. $courseId .')'] = $theme['theme']['text']['font'];
|
||||
$fonts['Pied de page ('. $courseId .')'] = $theme['theme']['footer']['font'];
|
||||
$fonts['Bannière (' . $courseId . ')'] = $theme['theme']['header']['font'];
|
||||
$fonts['Menu (' . $courseId . ')'] = $theme['theme']['menu']['font'];
|
||||
$fonts['Titre (' . $courseId . ')'] = $theme['theme']['title']['font'];
|
||||
$fonts['Texte (' . $courseId . ')'] = $theme['theme']['text']['font'];
|
||||
$fonts['Pied de page (' . $courseId . ')'] = $theme['theme']['footer']['font'];
|
||||
}
|
||||
|
||||
// Récupérer le détail des fontes installées
|
||||
@ -658,7 +660,7 @@ class theme extends common
|
||||
if (is_array($typeValue)) {
|
||||
foreach ($typeValue as $fontId => $fontValue) {
|
||||
// Recherche les correspondances
|
||||
$result = array_filter($fonts, function($value) use ($fontId) {
|
||||
$result = array_filter($fonts, function ($value) use ($fontId) {
|
||||
return $value == $fontId;
|
||||
});
|
||||
$keyResults = array_keys($result);
|
||||
@ -929,7 +931,7 @@ class theme extends common
|
||||
'fontWeight' => $this->getInput('themeTitleFontWeight'),
|
||||
'textTransform' => $this->getInput('themeTitleTextTransform')
|
||||
]
|
||||
]);
|
||||
], false);
|
||||
$this->setData([
|
||||
'theme',
|
||||
'text',
|
||||
@ -939,7 +941,7 @@ class theme extends common
|
||||
'textColor' => $this->getInput('themeTextTextColor'),
|
||||
'linkColor' => $this->getInput('themeTextLinkColor')
|
||||
]
|
||||
]);
|
||||
], false);
|
||||
$this->setData([
|
||||
'theme',
|
||||
'site',
|
||||
@ -950,14 +952,14 @@ class theme extends common
|
||||
'width' => $this->getInput('themeSiteWidth'),
|
||||
'margin' => $this->getInput('themeSiteMargin', helper::FILTER_BOOLEAN)
|
||||
]
|
||||
]);
|
||||
], false);
|
||||
$this->setData([
|
||||
'theme',
|
||||
'button',
|
||||
[
|
||||
'backgroundColor' => $this->getInput('themeButtonBackgroundColor')
|
||||
]
|
||||
]);
|
||||
], false);
|
||||
$this->setData([
|
||||
'theme',
|
||||
'block',
|
||||
|
@ -7,15 +7,7 @@
|
||||
'value' => template::ico('left')
|
||||
]); ?>
|
||||
</div>
|
||||
<div class="col1">
|
||||
<?php /* echo template::button('themeBodyHelp', [
|
||||
'href' => 'https://doc.zwiicms.fr/arriere-plan',
|
||||
'target' => '_blank',
|
||||
'value' => template::ico('help'),
|
||||
'class' => 'buttonHelp'
|
||||
]); */ ?>
|
||||
</div>
|
||||
<div class="col2 offset8">
|
||||
<div class="col2 offset9">
|
||||
<?php echo template::submit('themeBodySubmit'); ?>
|
||||
</div>
|
||||
</div>
|
||||
@ -35,7 +27,7 @@
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col6">
|
||||
<?php echo template::text('themeBodyToTopColor', [
|
||||
<?php echo template::text('themeBodyToTopColor', [
|
||||
'class' => 'colorPicker',
|
||||
'help' => 'Le curseur horizontal règle le niveau de transparence.',
|
||||
'label' => 'Couleur icône haut de page',
|
||||
@ -68,7 +60,8 @@
|
||||
'language' => $this->getData(['user', $this->getUser('id'), 'language']),
|
||||
'label' => 'Arrière plan',
|
||||
'type' => 1,
|
||||
'value' => $imageFile
|
||||
'value' => $imageFile,
|
||||
'folder' => $imageFile ? dirname($imageFile) : ''
|
||||
]); ?>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -19,6 +19,8 @@ $('#dataTables').DataTable({
|
||||
url: "core/vendor/datatables/french.json",
|
||||
},
|
||||
locale: 'fr',
|
||||
stateSave: true,
|
||||
"lengthMenu": [[10, 25, 50, -1], [10, 25, 50, "Tout"]],
|
||||
"columnDefs": [{
|
||||
target: 5,
|
||||
orderable: false,
|
||||
|
@ -7,15 +7,7 @@
|
||||
'value' => template::ico('left')
|
||||
]); ?>
|
||||
</div>
|
||||
<div class="col1">
|
||||
<?php /* echo template::button('themeHeaderHelp', [
|
||||
'href' => 'https://doc.zwiicms.fr/banniere',
|
||||
'target' => '_blank',
|
||||
'value' => template::ico('help'),
|
||||
'class' => 'buttonHelp'
|
||||
]); */?>
|
||||
</div>
|
||||
<div class="col2 offset8">
|
||||
<div class="col2 offset9">
|
||||
<?php echo template::submit('themeHeaderSubmit'); ?>
|
||||
</div>
|
||||
</div>
|
||||
@ -158,13 +150,17 @@
|
||||
'label' => 'Image',
|
||||
'language' => $this->getData(['user', $this->getUser('id'), 'language']),
|
||||
'type' => 1,
|
||||
'value' => $imageFile
|
||||
'value' => $imageFile,
|
||||
'folder' => $imageFile ? dirname($imageFile) : ''
|
||||
]);
|
||||
?>
|
||||
<span class="themeHeaderImageOptions displayNone" id="themeHeaderImageInfo">
|
||||
<?php echo helper::translate('Largeur de l\'image'); ?> <span id="themeHeaderImageWidth"></span> ; <?php echo helper::translate('Largeur du site :'); ?> <?php echo $this->getData(['theme', 'site', 'width']); ?>
|
||||
<?php echo helper::translate('Largeur de l\'image'); ?> <span id="themeHeaderImageWidth"></span>
|
||||
; <?php echo helper::translate('Largeur du site :'); ?>
|
||||
<?php echo $this->getData(['theme', 'site', 'width']); ?>
|
||||
|
|
||||
<?php echo helper::translate('Hauteur de l\'image'); ?> <span id="themeHeaderImageHeight"></span>
|
||||
<?php echo helper::translate('Hauteur de l\'image'); ?> <span
|
||||
id="themeHeaderImageHeight"></span>
|
||||
|
|
||||
<?php echo helper::translate('Ratio'); ?> <span id="themeHeaderImageRatio"></span>
|
||||
</span>
|
||||
|
@ -7,15 +7,7 @@
|
||||
'value' => template::ico('left')
|
||||
]); ?>
|
||||
</div>
|
||||
<div class="col1">
|
||||
<?php /* echo template::button('themeMenuHelp', [
|
||||
'href' => 'https://doc.zwiicms.fr/menu',
|
||||
'target' => '_blank',
|
||||
'value' => template::ico('help'),
|
||||
'class' => 'buttonHelp'
|
||||
]); */?>
|
||||
</div>
|
||||
<div class="col2 offset8">
|
||||
<div class="col2 offset9">
|
||||
<?php echo template::submit('themeMenuSubmit'); ?>
|
||||
</div>
|
||||
</div>
|
||||
@ -112,117 +104,117 @@
|
||||
'selected' => $this->getData(['theme', 'menu', 'burgerContent']),
|
||||
]); ?>
|
||||
</div>
|
||||
<div class="col6" id="themeMenuBurgerLogoId"
|
||||
class="<?php if ($this->getData(['theme', 'menu', 'burgerContent']) !== 'logo')
|
||||
echo 'displayNone'; ?>">
|
||||
<?php $imageFile = file_exists(self::FILE_DIR . 'source/' . $this->getData(['theme', 'menu', 'burgerLogo'])) ? $this->getData(['theme', 'menu', 'burgerLogo']) : ""; ?>
|
||||
<?php echo template::file('themeMenuBurgerLogo', [
|
||||
'help' => 'Sélectionner une image de dimensions adaptées',
|
||||
'language' => $this->getData(['user', $this->getUser('id'), 'language']),
|
||||
'label' => 'Logo du menu burger',
|
||||
'type' => 1,
|
||||
'value' => $imageFile
|
||||
]);
|
||||
?>
|
||||
</div>
|
||||
<div class="col6" id="themeMenuBurgerLogoId" class="<?php if ($this->getData(['theme', 'menu', 'burgerContent']) !== 'logo')
|
||||
echo 'displayNone'; ?>">
|
||||
<?php $imageFile = file_exists(self::FILE_DIR . 'source/' . $this->getData(['theme', 'menu', 'burgerLogo'])) ? $this->getData(['theme', 'menu', 'burgerLogo']) : ""; ?>
|
||||
<?php echo template::file('themeMenuBurgerLogo', [
|
||||
'help' => 'Sélectionner une image de dimensions adaptées',
|
||||
'language' => $this->getData(['user', $this->getUser('id'), 'language']),
|
||||
'label' => 'Logo du menu burger',
|
||||
'type' => 1,
|
||||
'value' => $imageFile,
|
||||
'folder' => $imageFile ? dirname($imageFile) : ''
|
||||
]);
|
||||
?>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col12">
|
||||
<div class="block">
|
||||
<h4>
|
||||
<?php echo helper::translate('Couleurs'); ?>
|
||||
</h4>
|
||||
<div class="row">
|
||||
<div class="col4">
|
||||
<?php echo template::text('themeMenuTextColor', [
|
||||
'class' => 'colorPicker',
|
||||
'help' => 'Le curseur horizontal règle le niveau de transparence.',
|
||||
'label' => 'Texte',
|
||||
'value' => $this->getData(['theme', 'menu', 'textColor'])
|
||||
]); ?>
|
||||
</div>
|
||||
<div class="col4">
|
||||
<?php echo template::text('themeMenuBackgroundColor', [
|
||||
'class' => 'colorPicker',
|
||||
'help' => 'Le curseur horizontal règle le niveau de transparence.',
|
||||
'label' => 'Arrière plan',
|
||||
'value' => $this->getData(['theme', 'menu', 'backgroundColor'])
|
||||
]); ?>
|
||||
</div>
|
||||
<div class="col4">
|
||||
<?php echo template::text('themeMenuBackgroundColorSub', [
|
||||
'class' => 'colorPicker',
|
||||
'help' => 'Le curseur horizontal règle le niveau de transparence.',
|
||||
'label' => 'Fond du sous-menu',
|
||||
'value' => $this->getData(['theme', 'menu', 'backgroundColorSub'])
|
||||
]); ?>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col12">
|
||||
<div class="block">
|
||||
<h4>
|
||||
<?php echo helper::translate('Couleurs'); ?>
|
||||
</h4>
|
||||
<div class="row">
|
||||
<div class="col4">
|
||||
<?php echo template::text('themeMenuTextColor', [
|
||||
'class' => 'colorPicker',
|
||||
'help' => 'Le curseur horizontal règle le niveau de transparence.',
|
||||
'label' => 'Texte',
|
||||
'value' => $this->getData(['theme', 'menu', 'textColor'])
|
||||
]); ?>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col4">
|
||||
<?php echo template::text('themeMenuActiveTextColor', [
|
||||
'class' => 'colorPicker',
|
||||
'help' => 'Le curseur horizontal règle le niveau de transparence.',
|
||||
'label' => 'Couleur texte page active',
|
||||
'value' => $this->getData(['theme', 'menu', 'activeTextColor'])
|
||||
]); ?>
|
||||
</div>
|
||||
<div class="col4 verticalAlignBottom">
|
||||
<?php
|
||||
echo template::checkbox('themeMenuActiveColorAuto', true, 'Couleur de fond automatique', [
|
||||
'checked' => $this->getData(['theme', 'menu', 'activeColorAuto']),
|
||||
]); ?>
|
||||
</div>
|
||||
<div class="col4">
|
||||
<?php echo template::text('themeMenuActiveColor', [
|
||||
'class' => 'colorPicker',
|
||||
'help' => 'Couleur de fond de la page sélectionnée dans le menu.<br>Le curseur horizontal règle le niveau de transparence.',
|
||||
'label' => 'Fond page active',
|
||||
'value' => $this->getData(['theme', 'menu', 'activeColor'])
|
||||
]); ?>
|
||||
</div>
|
||||
<div class="col4">
|
||||
<?php echo template::text('themeMenuBackgroundColor', [
|
||||
'class' => 'colorPicker',
|
||||
'help' => 'Le curseur horizontal règle le niveau de transparence.',
|
||||
'label' => 'Arrière plan',
|
||||
'value' => $this->getData(['theme', 'menu', 'backgroundColor'])
|
||||
]); ?>
|
||||
</div>
|
||||
<div class="col4">
|
||||
<?php echo template::text('themeMenuBackgroundColorSub', [
|
||||
'class' => 'colorPicker',
|
||||
'help' => 'Le curseur horizontal règle le niveau de transparence.',
|
||||
'label' => 'Fond du sous-menu',
|
||||
'value' => $this->getData(['theme', 'menu', 'backgroundColorSub'])
|
||||
]); ?>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col4">
|
||||
<?php echo template::text('themeMenuActiveTextColor', [
|
||||
'class' => 'colorPicker',
|
||||
'help' => 'Le curseur horizontal règle le niveau de transparence.',
|
||||
'label' => 'Couleur texte page active',
|
||||
'value' => $this->getData(['theme', 'menu', 'activeTextColor'])
|
||||
]); ?>
|
||||
</div>
|
||||
<div class="col4 verticalAlignBottom">
|
||||
<?php
|
||||
echo template::checkbox('themeMenuActiveColorAuto', true, 'Couleur de fond automatique', [
|
||||
'checked' => $this->getData(['theme', 'menu', 'activeColorAuto']),
|
||||
]); ?>
|
||||
</div>
|
||||
<div class="col4">
|
||||
<?php echo template::text('themeMenuActiveColor', [
|
||||
'class' => 'colorPicker',
|
||||
'help' => 'Couleur de fond de la page sélectionnée dans le menu.<br>Le curseur horizontal règle le niveau de transparence.',
|
||||
'label' => 'Fond page active',
|
||||
'value' => $this->getData(['theme', 'menu', 'activeColor'])
|
||||
]); ?>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col12">
|
||||
<div class="block">
|
||||
<h4>
|
||||
<?php echo helper::translate('Mise en forme du texte'); ?>
|
||||
</h4>
|
||||
<div class="row">
|
||||
<div class="col3">
|
||||
<?php echo template::select('themeMenuFont', $module::$fonts['name'], [
|
||||
'label' => 'Fonte',
|
||||
'selected' => $this->getData(['theme', 'menu', 'font']),
|
||||
'font' => $module::$fonts['family']
|
||||
]); ?>
|
||||
</div>
|
||||
<div class="col3">
|
||||
<?php echo template::select('themeMenuFontSize', $module::$menuFontSizes, [
|
||||
'label' => 'Taille',
|
||||
'help' => 'Proportionnelle à la taille définie dans le site.',
|
||||
'selected' => $this->getData(['theme', 'menu', 'fontSize'])
|
||||
]); ?>
|
||||
</div>
|
||||
<div class="col3">
|
||||
<?php echo template::select('themeMenuFontWeight', $module::$fontWeights, [
|
||||
'label' => 'Style',
|
||||
'selected' => $this->getData(['theme', 'menu', 'fontWeight'])
|
||||
]); ?>
|
||||
</div>
|
||||
<div class="col3">
|
||||
<?php echo template::select('themeMenuTextTransform', $module::$textTransforms, [
|
||||
'label' => 'Casse',
|
||||
'selected' => $this->getData(['theme', 'menu', 'textTransform'])
|
||||
]); ?>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col12">
|
||||
<div class="block">
|
||||
<h4>
|
||||
<?php echo helper::translate('Mise en forme du texte'); ?>
|
||||
</h4>
|
||||
<div class="row">
|
||||
<div class="col3">
|
||||
<?php echo template::select('themeMenuFont', $module::$fonts['name'], [
|
||||
'label' => 'Fonte',
|
||||
'selected' => $this->getData(['theme', 'menu', 'font']),
|
||||
'font' => $module::$fonts['family']
|
||||
]); ?>
|
||||
</div>
|
||||
<div class="col3">
|
||||
<?php echo template::select('themeMenuFontSize', $module::$menuFontSizes, [
|
||||
'label' => 'Taille',
|
||||
'help' => 'Proportionnelle à la taille définie dans le site.',
|
||||
'selected' => $this->getData(['theme', 'menu', 'fontSize'])
|
||||
]); ?>
|
||||
</div>
|
||||
<div class="col3">
|
||||
<?php echo template::select('themeMenuFontWeight', $module::$fontWeights, [
|
||||
'label' => 'Style',
|
||||
'selected' => $this->getData(['theme', 'menu', 'fontWeight'])
|
||||
]); ?>
|
||||
</div>
|
||||
<div class="col3">
|
||||
<?php echo template::select('themeMenuTextTransform', $module::$textTransforms, [
|
||||
'label' => 'Casse',
|
||||
'selected' => $this->getData(['theme', 'menu', 'textTransform'])
|
||||
]); ?>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<?php echo template::formClose(); ?>
|
||||
</div>
|
||||
<?php echo template::formClose(); ?>
|
@ -19,6 +19,7 @@ class user extends common
|
||||
public static $actions = [
|
||||
'add' => self::GROUP_ADMIN,
|
||||
'delete' => self::GROUP_ADMIN,
|
||||
'usersDelete' => self::GROUP_ADMIN,
|
||||
'import' => self::GROUP_ADMIN,
|
||||
'index' => self::GROUP_ADMIN,
|
||||
'template' => self::GROUP_ADMIN,
|
||||
@ -26,11 +27,13 @@ class user extends common
|
||||
'logout' => self::GROUP_MEMBER,
|
||||
'forgot' => self::GROUP_VISITOR,
|
||||
'login' => self::GROUP_VISITOR,
|
||||
'auth' => self::GROUP_VISITOR,
|
||||
'reset' => self::GROUP_VISITOR,
|
||||
'profil' => self::GROUP_ADMIN,
|
||||
'profilEdit' => self::GROUP_ADMIN,
|
||||
'profilAdd' => self::GROUP_ADMIN,
|
||||
'profilDelete' => self::GROUP_ADMIN,
|
||||
'tag' => self::GROUP_ADMIN,
|
||||
];
|
||||
|
||||
public static $users = [];
|
||||
@ -61,7 +64,7 @@ class user extends common
|
||||
public static $languagesInstalled = [];
|
||||
|
||||
public static $sharePath = [
|
||||
'/site/file/source/'
|
||||
'site/file/source/'
|
||||
];
|
||||
|
||||
public static $groupProfils = [
|
||||
@ -229,6 +232,161 @@ class user extends common
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Désinscription de tous les utilisateurs
|
||||
* Les désinscriptions ne suppriment pas les historiques
|
||||
*/
|
||||
public function usersDelete()
|
||||
{
|
||||
|
||||
// Contenu sélectionné
|
||||
$courseId = $this->getUrl(2);
|
||||
|
||||
// Accès limité aux admins, à l'auteur ou éditeurs inscrits
|
||||
if (
|
||||
$this->getUser('permission', __CLASS__, __FUNCTION__) !== true
|
||||
) {
|
||||
// Valeurs en sortie
|
||||
$this->addOutput([
|
||||
'access' => false
|
||||
]);
|
||||
}
|
||||
|
||||
// Inscription des utilisateurs cochés
|
||||
if (
|
||||
isset($_POST['usersDeleteSubmit'])
|
||||
) {
|
||||
$notification = helper::translate('Suppression de %s compte');
|
||||
$success = true;
|
||||
$count = 0;
|
||||
foreach ($_POST as $keyPost => $valuePost) {
|
||||
// Exclure les variables post qui ne sont pas des userId et ne traiter que les non inscrits
|
||||
if (
|
||||
$this->getData(['user', $keyPost]) !== null
|
||||
) {
|
||||
|
||||
if ($keyPost === $this->getUser('id')) {
|
||||
$notification = helper::translate('Votre compte n\'a pas été supprimé !') . '<br />' . $notification;
|
||||
$success = 1;
|
||||
} else {
|
||||
$this->deleteData(['user', $keyPost]);
|
||||
$count += 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
// Valeurs en sortie
|
||||
$this->addOutput([
|
||||
'redirect' => helper::baseUrl() . 'user/usersDelete',
|
||||
'notification' => sprintf($count > 1 ? $notification . 's' : $notification, $count),
|
||||
'state' => $success
|
||||
]);
|
||||
|
||||
}
|
||||
|
||||
// Liste des groupes et des profils
|
||||
$usersGroups = $this->getData(['profil']);
|
||||
|
||||
foreach ($usersGroups as $groupId => $groupValue) {
|
||||
switch ($groupId) {
|
||||
case "-1":
|
||||
case "0":
|
||||
break;
|
||||
case "3":
|
||||
self::$usersGroups['30'] = 'Administrateur';
|
||||
$profils['30'] = 0;
|
||||
break;
|
||||
case "1":
|
||||
case "2":
|
||||
foreach ($groupValue as $profilId => $profilValue) {
|
||||
if ($profilId) {
|
||||
self::$usersGroups[$groupId . $profilId] = sprintf(helper::translate('Groupe %s - Profil %s'), self::$groupPublics[$groupId], $profilValue['name']);
|
||||
$profils[$groupId . $profilId] = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Liste alphabétique
|
||||
self::$alphabet = range('A', 'Z');
|
||||
$alphabet = range('A', 'Z');
|
||||
self::$alphabet = array_combine($alphabet, self::$alphabet);
|
||||
self::$alphabet = array_merge(['all' => 'Tout'], self::$alphabet);
|
||||
|
||||
// Liste des inscrits dans le contenu sélectionné.
|
||||
$users = $this->getData(['user']);
|
||||
if (is_array($users)) {
|
||||
// Tri du tableau par défaut par $userId
|
||||
ksort($users);
|
||||
foreach ($users as $userId => $userValue) {
|
||||
|
||||
// Compte les rôles
|
||||
if (isset($profils[$this->getData(['user', $userId, 'group']) . $this->getData(['user', $userId, 'profil'])])) {
|
||||
$profils[$this->getData(['user', $userId, 'group']) . $this->getData(['user', $userId, 'profil'])]++;
|
||||
}
|
||||
|
||||
// Filtres
|
||||
if (
|
||||
isset($_POST['usersFilterGroup'])
|
||||
|| isset($_POST['usersFilterFirstName'])
|
||||
|| isset($_POST['usersFilterLastName'])
|
||||
) {
|
||||
|
||||
// Groupe et profils
|
||||
$group = (string) $this->getData(['user', $userId, 'group']);
|
||||
$profil = (string) $this->getData(['user', $userId, 'profil']);
|
||||
$firstName = $this->getData(['user', $userId, 'firstname']);
|
||||
$lastName = $this->getData(['user', $userId, 'lastname']);
|
||||
if (
|
||||
$this->getInput('usersFilterGroup', helper::FILTER_INT) > 0
|
||||
&& $this->getInput('usersFilterGroup', helper::FILTER_STRING_SHORT) !== $group . $profil
|
||||
)
|
||||
continue;
|
||||
// Première lettre du prénom
|
||||
if (
|
||||
$this->getInput('usersFilterFirstName', helper::FILTER_STRING_SHORT) !== 'all'
|
||||
&& $this->getInput('usersFilterFirstName', helper::FILTER_STRING_SHORT) !== strtoupper(substr($firstName, 0, 1))
|
||||
)
|
||||
continue;
|
||||
// Première lettre du nom
|
||||
if (
|
||||
$this->getInput('usersFilterLastName', helper::FILTER_STRING_SHORT) !== 'all'
|
||||
&& $this->getInput('usersFilterLastName', helper::FILTER_STRING_SHORT) !== strtoupper(substr($lastName, 0, 1))
|
||||
)
|
||||
continue;
|
||||
}
|
||||
|
||||
// Construction du tableau
|
||||
self::$users[] = [
|
||||
template::checkbox($userId, true, '', ['class' => 'checkboxSelect']),
|
||||
$userId,
|
||||
$this->getData(['user', $userId, 'firstname']),
|
||||
$this->getData(['user', $userId, 'lastname']),
|
||||
$this->getData(['user', $userId, 'tags']),
|
||||
];
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
// Ajoute les effectifs aux profils du sélecteur
|
||||
foreach (self::$usersGroups as $groupId => $groupValue) {
|
||||
if ($groupId === 'all') {
|
||||
self::$usersGroups['all'] = self::$usersGroups['all'] . ' (' . array_sum($profils) . ')';
|
||||
} else {
|
||||
self::$usersGroups[$groupId] = self::$usersGroups[$groupId] . ' (' . $profils[$groupId] . ')';
|
||||
}
|
||||
}
|
||||
|
||||
// Valeurs en sortie
|
||||
$this->addOutput([
|
||||
'title' => helper::translate('Désincription en masse'),
|
||||
'view' => 'usersDelete',
|
||||
'vendor' => [
|
||||
'datatables'
|
||||
]
|
||||
]);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Édition
|
||||
*/
|
||||
@ -271,7 +429,9 @@ class user extends common
|
||||
if ($this->getUser('group') < self::GROUP_ADMIN) {
|
||||
if ($this->getInput('userEditNewPassword')) {
|
||||
// L'ancien mot de passe est correct
|
||||
if (password_verify(html_entity_decode($this->getInput('userEditOldPassword')), $this->getData(['user', $this->getUrl(2), 'password']))) {
|
||||
if (
|
||||
password_verify(html_entity_decode($this->getInput('userEditOldPassword')), $this->getData(['user', $this->getUrl(2), 'password']))
|
||||
) {
|
||||
// La confirmation correspond au mot de passe
|
||||
if ($this->getInput('userEditNewPassword') === $this->getInput('userEditConfirmPassword')) {
|
||||
$newPassword = $this->getInput('userEditNewPassword', helper::FILTER_PASSWORD, true);
|
||||
@ -345,6 +505,7 @@ class user extends common
|
||||
'files' => $this->getInput('userEditFiles', helper::FILTER_BOOLEAN),
|
||||
'language' => $this->getInput('userEditLanguage', helper::FILTER_STRING_SHORT),
|
||||
'tags' => $this->getInput('userEditTags', helper::FILTER_STRING_SHORT),
|
||||
'authKey' => $this->getData(['user', $this->getUrl(2), 'authKey']),
|
||||
]
|
||||
]);
|
||||
// Redirection spécifique si l'utilisateur change son mot de passe
|
||||
@ -415,7 +576,7 @@ class user extends common
|
||||
// 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])));
|
||||
$uniqId = md5(json_encode($this->getData(['user', $userId, 'forgot'])));
|
||||
// Envoi le mail
|
||||
$sent = $this->sendMail(
|
||||
$this->getData(['user', $userId, 'mail']),
|
||||
@ -518,13 +679,15 @@ class user extends common
|
||||
|
||||
// Formatage de la liste
|
||||
self::$users[] = [
|
||||
$userId,
|
||||
//$userId,
|
||||
$this->getData(['user', $userId, 'firstname']) . ' ' . $userLastNames,
|
||||
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']),
|
||||
$this->getData(['user', $userId, 'tags']),
|
||||
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,
|
||||
'value' => template::ico('pencil'),
|
||||
@ -554,9 +717,9 @@ class user extends common
|
||||
$this->addOutput([
|
||||
'title' => helper::translate('Utilisateurs'),
|
||||
'view' => 'index',
|
||||
'vendor' => [
|
||||
'datatables'
|
||||
]
|
||||
'vendor' => [
|
||||
'datatables'
|
||||
]
|
||||
]);
|
||||
}
|
||||
|
||||
@ -574,7 +737,7 @@ class user extends common
|
||||
// Stoppe si le profil est affecté
|
||||
foreach ($groups as $userId) {
|
||||
if ((string) $this->getData(['user', $userId, 'profil']) === $this->getUrl(3)) {
|
||||
$profilUsed= false;
|
||||
$profilUsed = false;
|
||||
}
|
||||
}
|
||||
foreach ($this->getData(['profil']) as $groupId => $groupData) {
|
||||
@ -690,7 +853,8 @@ class user extends common
|
||||
'rename' => $this->getInput('profilEditFolderRename', helper::FILTER_BOOLEAN),
|
||||
'copycut' => $this->getInput('profilEditFolderCopycut', helper::FILTER_BOOLEAN),
|
||||
'chmod' => $this->getInput('profilEditFolderChmod', helper::FILTER_BOOLEAN),
|
||||
'path' => preg_replace('/^\\./', '', $this->getInput('profilEditPath')), // Supprime le point pour préserver le chemin
|
||||
'coursePath' => $this->getInput('profilEditCoursePath'), // Supprime le point pour préserver le chemin
|
||||
'homePath' => $this->getInput('profilEditHomePath'), // Supprime le point pour préserver le chemin
|
||||
],
|
||||
'page' => [
|
||||
'add' => $this->getInput('profilEditPageAdd', helper::FILTER_BOOLEAN),
|
||||
@ -703,6 +867,48 @@ class user extends common
|
||||
],
|
||||
'user' => [
|
||||
'edit' => $this->getInput('profilEditUserEdit', helper::FILTER_BOOLEAN),
|
||||
],
|
||||
'course' => [
|
||||
// Droit d'intervenir sur tous les espaces
|
||||
'tutor' => $this->getInput('profilEditCourseTutor', helper::FILTER_BOOLEAN),
|
||||
// Droit d'accéder à la fenêtre de gestion pour tous les éditeurs et plus
|
||||
'index' => $this->getInput('profilEditCourseUsers', helper::FILTER_BOOLEAN)
|
||||
|| $this->getInput('profilEditCourseUserHistory', helper::FILTER_BOOLEAN)
|
||||
|| $this->getInput('profilEditCourseUserExport', helper::FILTER_BOOLEAN)
|
||||
|| $this->getInput('profilEditCoursExport', helper::FILTER_BOOLEAN)
|
||||
|| $this->getInput('profilEditCourseUserAdd', helper::FILTER_BOOLEAN)
|
||||
|| $this->getInput('profilEditCourseUsersAdd', helper::FILTER_BOOLEAN)
|
||||
|| $this->getInput('profilEditCourseUserDelete', helper::FILTER_BOOLEAN)
|
||||
|| $this->getInput('profilEditCourseUsersDelete', helper::FILTER_BOOLEAN)
|
||||
|| $this->getInput('profilEditCourseEdit', helper::FILTER_BOOLEAN)
|
||||
|| $this->getInput('profilEditCourseBackup', helper::FILTER_BOOLEAN)
|
||||
|| $this->getInput('profilEditCourseRestore', helper::FILTER_BOOLEAN),
|
||||
|
||||
'manage' => $this->getInput('profilEditCourseUsers', helper::FILTER_BOOLEAN)
|
||||
|| $this->getInput('profilEditCourseUserHistory', helper::FILTER_BOOLEAN)
|
||||
|| $this->getInput('profilEditCourseUserExport', helper::FILTER_BOOLEAN)
|
||||
|| $this->getInput('profilEditCoursExport', helper::FILTER_BOOLEAN)
|
||||
|| $this->getInput('profilEditCourseUserAdd', helper::FILTER_BOOLEAN)
|
||||
|| $this->getInput('profilEditCourseUsersAdd', helper::FILTER_BOOLEAN)
|
||||
|| $this->getInput('profilEditCourseUserDelete', helper::FILTER_BOOLEAN)
|
||||
|| $this->getInput('profilEditCourseUsersDelete', helper::FILTER_BOOLEAN)
|
||||
|| $this->getInput('profilEditCourseEdit', helper::FILTER_BOOLEAN)
|
||||
|| $this->getInput('profilEditCourseBackup', helper::FILTER_BOOLEAN)
|
||||
|| $this->getInput('profilEditCourseRestore', helper::FILTER_BOOLEAN)
|
||||
|| $this->getInput('profilEditCourseReset', helper::FILTER_BOOLEAN),
|
||||
// Droits spécifiques
|
||||
'users' => $this->getInput('profilEditCourseUsers', helper::FILTER_BOOLEAN),
|
||||
'userHistory' => $this->getInput('profilEditCourseUserHistory', helper::FILTER_BOOLEAN),
|
||||
'userReportExport' => $this->getInput('profilEditCourseuserReportExport', helper::FILTER_BOOLEAN),
|
||||
'export' => $this->getInput('profilEditCourseExport', helper::FILTER_BOOLEAN),
|
||||
'userAdd' => $this->getInput('profilEditCourseUserAdd', helper::FILTER_BOOLEAN),
|
||||
'usersAdd' => $this->getInput('profilEditCourseUsersAdd', helper::FILTER_BOOLEAN),
|
||||
'userDelete' => $this->getInput('profilEditCourseUserDelete', helper::FILTER_BOOLEAN),
|
||||
'usersDelete' => $this->getInput('profilEditCourseUsersDelete', helper::FILTER_BOOLEAN),
|
||||
'edit' => $this->getInput('profilEditCourseEdit', helper::FILTER_BOOLEAN),
|
||||
'backup' => $this->getInput('profilEditCourseBackup', helper::FILTER_BOOLEAN),
|
||||
'restore' => $this->getInput('profilEditCourseRestore', helper::FILTER_BOOLEAN),
|
||||
'reset' => $this->getInput('profilEditCourseReset', helper::FILTER_BOOLEAN),
|
||||
]
|
||||
];
|
||||
|
||||
@ -736,11 +942,20 @@ class user extends common
|
||||
}
|
||||
|
||||
// Chemin vers les dossiers du gestionnaire de fichier
|
||||
self::$sharePath = $this->getSubdirectories('./site/file/source');
|
||||
self::$sharePath = $this->getSubdirectories('site/file/source');
|
||||
|
||||
// Exclure les espaces des cours
|
||||
foreach (array_keys($this->getData(['course'])) as $courseId) {
|
||||
self::$sharePath = array_filter(self::$sharePath, function ($key) use ($courseId) {
|
||||
return strpos($key, $courseId) === false;
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
self::$sharePath = array_flip(self::$sharePath);
|
||||
self::$sharePath = array_merge(['./site/file/source/' => 'Tous les dossiers'], self::$sharePath);
|
||||
//self::$sharePath = array_merge(['' => 'Aucun dossier'], self::$sharePath);
|
||||
self::$sharePath = array_merge(['' => 'Dossier de l\'espace actif'], self::$sharePath);
|
||||
self::$sharePath = array_merge(['none' => 'Aucun Accès'], self::$sharePath);
|
||||
self::$sharePath = array_merge(['' => 'Confiné dans le dossier de l\'espace ouvert'], self::$sharePath);
|
||||
self::$sharePath = array_merge(['site/file/source/' => 'Tout le gestionnaire de fichiers'], self::$sharePath);
|
||||
|
||||
// Liste des modules installés
|
||||
self::$listModules = helper::getModules();
|
||||
@ -838,7 +1053,8 @@ class user extends common
|
||||
'rename' => $this->getInput('profilAddFolderRename', helper::FILTER_BOOLEAN),
|
||||
'copycut' => $this->getInput('profilAddFolderCopycut', helper::FILTER_BOOLEAN),
|
||||
'chmod' => $this->getInput('profilAddFolderChmod', helper::FILTER_BOOLEAN),
|
||||
'path' => preg_replace('/^\\./', '', $this->getInput('profilEditPath')), // Supprime le point pour préserver le chemin,
|
||||
'coursePath' => $this->getInput('profilAddCoursePath'), // Supprime le point pour préserver le chemin
|
||||
'homePath' => $this->getInput('profilAddHomePath'), // Supprime le point pour préserver le chemin
|
||||
],
|
||||
'page' => [
|
||||
'add' => $this->getInput('profilAddPageAdd', helper::FILTER_BOOLEAN),
|
||||
@ -851,6 +1067,45 @@ class user extends common
|
||||
],
|
||||
'user' => [
|
||||
'edit' => $this->getInput('profilAddUserEdit', helper::FILTER_BOOLEAN),
|
||||
],
|
||||
'course' => [
|
||||
'tutor' => $this->getInput('profilAddCourseTutor', helper::FILTER_BOOLEAN),
|
||||
'index' => $this->getInput('profilAddCourseUsers', helper::FILTER_BOOLEAN)
|
||||
|| $this->getInput('profilAddCourseUserHistory', helper::FILTER_BOOLEAN)
|
||||
|| $this->getInput('profilAddCourseUserExport', helper::FILTER_BOOLEAN)
|
||||
|| $this->getInput('profilAddCoursExport', helper::FILTER_BOOLEAN)
|
||||
|| $this->getInput('profilAddCourseUserAdd', helper::FILTER_BOOLEAN)
|
||||
|| $this->getInput('profilAddCourseUsersAdd', helper::FILTER_BOOLEAN)
|
||||
|| $this->getInput('profilAddCourseUserDelete', helper::FILTER_BOOLEAN)
|
||||
|| $this->getInput('profilAddCourseUsersDelete', helper::FILTER_BOOLEAN)
|
||||
|| $this->getInput('profilAddCourseEdit', helper::FILTER_BOOLEAN)
|
||||
|| $this->getInput('profilAddCourseBackup', helper::FILTER_BOOLEAN)
|
||||
|| $this->getInput('profilAddCourseRestore', helper::FILTER_BOOLEAN),
|
||||
'manage' => $this->getInput('profilAddCourseUsers', helper::FILTER_BOOLEAN)
|
||||
|| $this->getInput('profilAddCourseUserHistory', helper::FILTER_BOOLEAN)
|
||||
|| $this->getInput('profilAddCourseUserExport', helper::FILTER_BOOLEAN)
|
||||
|| $this->getInput('profilAddCoursExport', helper::FILTER_BOOLEAN)
|
||||
|| $this->getInput('profilAddCourseUserAdd', helper::FILTER_BOOLEAN)
|
||||
|| $this->getInput('profilAddCourseUsersAdd', helper::FILTER_BOOLEAN)
|
||||
|| $this->getInput('profilAddCourseUserDelete', helper::FILTER_BOOLEAN)
|
||||
|| $this->getInput('profilAddCourseUsersDelete', helper::FILTER_BOOLEAN)
|
||||
|| $this->getInput('profilAddCourseEdit', helper::FILTER_BOOLEAN)
|
||||
|| $this->getInput('profilAddCourseBackup', helper::FILTER_BOOLEAN)
|
||||
|| $this->getInput('profilAddCourseRestore', helper::FILTER_BOOLEAN)
|
||||
|| $this->getInput('profilAddCourseReset', helper::FILTER_BOOLEAN),
|
||||
// La suite
|
||||
'users' => $this->getInput('profilAddCourseUsers', helper::FILTER_BOOLEAN),
|
||||
'userHistory' => $this->getInput('profilAddCourseUserHistory', helper::FILTER_BOOLEAN),
|
||||
'userReportExport' => $this->getInput('profilAddCourseuserReportExport', helper::FILTER_BOOLEAN),
|
||||
'export' => $this->getInput('profilAddCourseExport', helper::FILTER_BOOLEAN),
|
||||
'userAdd' => $this->getInput('profilAddCourseUserAdd', helper::FILTER_BOOLEAN),
|
||||
'usersAdd' => $this->getInput('profilAddCourseUsersAdd', helper::FILTER_BOOLEAN),
|
||||
'userDelete' => $this->getInput('profilAddCourseUserDelete', helper::FILTER_BOOLEAN),
|
||||
'usersDelete' => $this->getInput('profilAddCourseUsersDelete', helper::FILTER_BOOLEAN),
|
||||
'edit' => $this->getInput('profilAddCourseEdit', helper::FILTER_BOOLEAN),
|
||||
'backup' => $this->getInput('profilAddCourseBackup', helper::FILTER_BOOLEAN),
|
||||
'restore' => $this->getInput('profilAddCourseRestore', helper::FILTER_BOOLEAN),
|
||||
'reset' => $this->getInput('profilAddCourseReset', helper::FILTER_BOOLEAN),
|
||||
]
|
||||
];
|
||||
|
||||
@ -892,11 +1147,21 @@ class user extends common
|
||||
}
|
||||
|
||||
// Chemin vers les dossiers du gestionnaire de fichier
|
||||
self::$sharePath = $this->getSubdirectories('./site/file/source');
|
||||
self::$sharePath = $this->getSubdirectories('site/file/source');
|
||||
|
||||
// Exclure les espaces des cours
|
||||
/*
|
||||
foreach (array_keys($this->getData(['course'])) as $courseId) {
|
||||
self::$sharePath = array_filter(self::$sharePath, function ($key) use ($courseId) {
|
||||
return strpos($key, $courseId) === false;
|
||||
});
|
||||
}
|
||||
*/
|
||||
|
||||
self::$sharePath = array_flip(self::$sharePath);
|
||||
self::$sharePath = array_merge(['./site/file/source/' => 'Tous les dossiers'], self::$sharePath);
|
||||
//self::$sharePath = array_merge(['' => 'Aucun dossier'], self::$sharePath);
|
||||
self::$sharePath = array_merge(['' => 'Dossier de l\'espace actif'], self::$sharePath);
|
||||
self::$sharePath = array_merge(['none' => 'Aucun Accès'], self::$sharePath);
|
||||
self::$sharePath = array_merge(['' => 'Confiné dans le dossier de l\'espace ouvert'], self::$sharePath);
|
||||
self::$sharePath = array_merge(['site/file/source/' => 'Tout le gestionnaire de fichiers'], self::$sharePath);
|
||||
|
||||
// Liste des modules installés
|
||||
self::$listModules = helper::getModules();
|
||||
@ -932,11 +1197,11 @@ class user extends common
|
||||
// recherche les membres du groupe
|
||||
$groups = helper::arrayColumn($this->getData(['user']), 'group');
|
||||
$groups = array_keys($groups, $this->getUrl(2));
|
||||
$flag= true;
|
||||
$flag = true;
|
||||
// Stoppe si le profil est affecté
|
||||
foreach ($groups as $userId) {
|
||||
if ((string) $this->getData(['user', $userId, 'profil']) === $this->getUrl(3)) {
|
||||
$flag= false;
|
||||
$flag = false;
|
||||
}
|
||||
}
|
||||
if (
|
||||
@ -963,9 +1228,6 @@ class user extends common
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Connexion
|
||||
*/
|
||||
public function login()
|
||||
{
|
||||
// Soumission du formulaire
|
||||
@ -1027,8 +1289,8 @@ class user extends common
|
||||
$this->getData(['user', $userId, 'connectTimeout']) + $this->getData(['config', 'connect', 'timeout']) < time()
|
||||
and $this->getData(['user', $userId, 'connectFail']) === $this->getData(['config', 'connect', 'attempt'])
|
||||
) {
|
||||
$this->setData(['user', $userId, 'connectFail', 0]);
|
||||
$this->setData(['user', $userId, 'connectTimeout', 0]);
|
||||
$this->setData(['user', $userId, 'connectFail', 0], false);
|
||||
$this->setData(['user', $userId, 'connectTimeout', 0], false);
|
||||
}
|
||||
// Check la présence des variables et contrôle du blocage du compte si valeurs dépassées
|
||||
// Vérification du mot de passe et du groupe
|
||||
@ -1039,15 +1301,14 @@ class user extends common
|
||||
and $this->getData(['user', $userId, 'group']) >= self::GROUP_MEMBER
|
||||
and $captcha === true
|
||||
) {
|
||||
// RAZ
|
||||
$this->setData(['user', $userId, 'connectFail', 0]);
|
||||
$this->setData(['user', $userId, 'connectTimeout', 0]);
|
||||
// Expiration
|
||||
$expire = $this->getInput('userLoginLongTime', helper::FILTER_BOOLEAN) === true ? strtotime("+1 year") : 0;
|
||||
setcookie('ZWII_USER_ID', $userId, $expire, helper::baseUrl(false, false), '', helper::isHttps(), true);
|
||||
setcookie('ZWII_USER_PASSWORD', $this->getData(['user', $userId, 'password']), $expire, helper::baseUrl(false, false), '', helper::isHttps(), true);
|
||||
|
||||
// RAZ des compteurs de blocage
|
||||
$this->setData(['user', $userId, 'connectFail', 0], false);
|
||||
$this->setData(['user', $userId, 'connectTimeout', 0], false);
|
||||
|
||||
// Accès multiples avec le même compte
|
||||
$this->setData(['user', $userId, 'accessCsrf', $_SESSION['csrf']]);
|
||||
$this->setData(['user', $userId, 'accessCsrf', $_SESSION['csrf']], false);
|
||||
|
||||
// Valeurs en sortie lorsque le site est en maintenance et que l'utilisateur n'est pas administrateur
|
||||
if (
|
||||
$this->getData(['config', 'maintenance'])
|
||||
@ -1059,14 +1320,57 @@ class user extends common
|
||||
'state' => false
|
||||
]);
|
||||
} else {
|
||||
$logStatus = 'Connexion réussie';
|
||||
/**
|
||||
* Le site n'est pas en maintenance
|
||||
* Double authentification en cas de saisie correcte
|
||||
*/
|
||||
|
||||
// Clé d'authenfication utlisée pour lié le compte au cookie au lieu de stocke le hash du mot de passe
|
||||
$authKey = uniqid('', true) . bin2hex(random_bytes(8));
|
||||
if ($this->getData(['config', 'connect', 'mailAuth']) >= $this->getData(['user', $userId, 'group'])) {
|
||||
$logStatus = 'Envoi du mail d\'authentification';
|
||||
// Redirection vers la page d'authentification
|
||||
$authRedirect = 'user/auth/';
|
||||
// Stocker la clé envoyée par email
|
||||
$this->setData(['user', $userId, 'authKey', rand(100000, 999999)]);
|
||||
|
||||
} else {
|
||||
$logStatus = 'Connexion réussie';
|
||||
// La page d'autentification est vide
|
||||
$authRedirect = '';
|
||||
$this->setData(['user', $userId, 'authKey', $authKey]);
|
||||
|
||||
}
|
||||
|
||||
// Validité du cookie
|
||||
$expire = $this->getInput('userLoginLongTime', helper::FILTER_BOOLEAN) === true ? strtotime("+1 year") : 0;
|
||||
switch ($this->getInput('userLoginLongTime', helper::FILTER_BOOLEAN)) {
|
||||
case false:
|
||||
// Cookie de session
|
||||
setcookie('ZWII_USER_ID', $userId, $expire, helper::baseUrl(false, false), '', helper::isHttps(), true);
|
||||
//setcookie('ZWII_USER_PASSWORD', $this->getData(['user', $userId, 'password']), $expire, helper::baseUrl(false, false), '', helper::isHttps(), true);
|
||||
|
||||
// Connexion par clé
|
||||
setcookie('ZWII_AUTH_KEY', $authKey, $expire, helper::baseUrl(false, false), '', helper::isHttps(), true);
|
||||
break;
|
||||
default:
|
||||
// Cookie persistant
|
||||
setcookie('ZWII_USER_ID', $userId, $expire, helper::baseUrl(false, false));
|
||||
//setcookie('ZWII_USER_PASSWORD', $this->getData(['user', $userId, 'password']), $expire, helper::baseUrl(false, false));
|
||||
|
||||
// Connexion par clé
|
||||
setcookie('ZWII_AUTH_KEY', $authKey, $expire, helper::baseUrl(false, false));
|
||||
break;
|
||||
}
|
||||
|
||||
$pageId = $this->getUrl(2);
|
||||
if ($this->getData(['config', 'page404']) === $pageId
|
||||
|| $this->getData(['config', 'page403']) === $pageId
|
||||
if (
|
||||
$this->getData(['config', 'page404']) === $pageId
|
||||
|| $this->getData(['config', 'page403']) === $pageId
|
||||
) {
|
||||
$pageId = '';
|
||||
}
|
||||
$redirect = ($pageId && strpos($pageId, 'user_reset') !== 0) ? helper::baseUrl() . str_replace('_', '/', str_replace('__', '#', $pageId)) : helper::baseUrl();
|
||||
$redirect = ($pageId && strpos($pageId, 'user_reset') !== 0) ? helper::baseUrl() . $authRedirect . str_replace('_', '/', str_replace('__', '#', $pageId)) : helper::baseUrl() . $authRedirect;
|
||||
// Valeurs en sortie
|
||||
$this->addOutput([
|
||||
'notification' => sprintf(helper::translate('Bienvenue %s %s'), $this->getData(['user', $userId, 'firstname']), $this->getData(['user', $userId, 'lastname'])),
|
||||
@ -1079,12 +1383,12 @@ class user extends common
|
||||
$notification = helper::translate('Captcha, identifiant ou mot de passe incorrects');
|
||||
$logStatus = $captcha === true ? 'Erreur de mot de passe' : 'Erreur de captcha';
|
||||
// Cas 1 le nombre de connexions est inférieur aux tentatives autorisées : incrément compteur d'échec
|
||||
if ($this->getData(['user', $userId, 'connectFail']) < $this->getData(['config', 'connect', 'attempt'])) {
|
||||
$this->setData(['user', $userId, 'connectFail', $this->getdata(['user', $userId, 'connectFail']) + 1]);
|
||||
if ($this->getData(['user', $userId, 'connectFail']) < $this->getData(['config', 'connect', 'attempt'], false)) {
|
||||
$this->setData(['user', $userId, 'connectFail', $this->getdata(['user', $userId, 'connectFail']) + 1], false);
|
||||
}
|
||||
// Cas 2 la limite du nombre de connexion est atteinte : placer le timer
|
||||
if ($this->getdata(['user', $userId, 'connectFail']) == $this->getData(['config', 'connect', 'attempt'])) {
|
||||
$this->setData(['user', $userId, 'connectTimeout', time()]);
|
||||
$this->setData(['user', $userId, 'connectTimeout', time()], false);
|
||||
}
|
||||
// Cas 3 le délai de bloquage court
|
||||
if ($this->getData(['user', $userId, 'connectTimeout']) + $this->getData(['config', 'connect', 'timeout']) > time()) {
|
||||
@ -1097,6 +1401,8 @@ class user extends common
|
||||
]);
|
||||
}
|
||||
}
|
||||
// Force la sauvegarde
|
||||
$this->saveDB('user');
|
||||
}
|
||||
// Journalisation
|
||||
$this->saveLog($logStatus);
|
||||
@ -1113,15 +1419,108 @@ class user extends common
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* Validation de la connexion par email
|
||||
* @return void
|
||||
*/
|
||||
public function auth()
|
||||
{
|
||||
// Soumission du formulaire
|
||||
if (
|
||||
$this->isPost()
|
||||
) {
|
||||
// Vérifier la clé saisie
|
||||
$targetKey = $this->getData(['user', $this->getUser('id'), 'authKey']);
|
||||
$inputKey = $this->getInput('userAuthKey', helper::FILTER_INT);
|
||||
if (
|
||||
$targetKey === $inputKey &&
|
||||
$this->getData(['user', $this->getUser('id'), 'connectTimeout']) + 3600 >= time()
|
||||
) {
|
||||
$pageId = $this->getUrl(2);
|
||||
// La fiche de l'utilisateur contient la clé d'authentification
|
||||
$this->setData(['user', $this->getUser('id'), 'authKey', $this->getInput('ZWII_AUTH_KEY')]);
|
||||
$redirect = ($pageId && strpos($pageId, 'user_reset') !== 0) ? helper::baseUrl() . str_replace('_', '/', str_replace('__', '#', $pageId)) : helper::baseUrl();
|
||||
// Journalisation
|
||||
$this->saveLog('Connexion réussie');
|
||||
// Réinitialiser le compteur de temps
|
||||
$this->setData(['user', $this->getUser('id'), 'connectTimeout', 0]);
|
||||
// Valeurs en sortie
|
||||
$this->addOutput([
|
||||
'redirect' => $redirect,
|
||||
'notification' => helper::translate('Connexion réussie'),
|
||||
'state' => true
|
||||
]);
|
||||
} else {
|
||||
|
||||
// Supprime la clé stockée et le temps limite
|
||||
$this->deleteData(['user', $this->getUser('id'), 'authKey']);
|
||||
// Réinitialiser le compteur de temps
|
||||
$this->setData(['user', $this->getUser('id'), 'connectTimeout', 0]);
|
||||
|
||||
// Détruit les cookies d'authenfication
|
||||
helper::deleteCookie('ZWII_USER_ID');
|
||||
helper::deleteCookie('ZWII_AUTH_KEY');
|
||||
|
||||
// Détruit la session
|
||||
session_destroy();
|
||||
|
||||
// Journalisation
|
||||
$this->saveLog('Erreur de vérification de la clé envoyée par email ' . $this->getUser('id'));
|
||||
|
||||
// Valeurs en sortie
|
||||
$this->addOutput([
|
||||
'redirect' => helper::baseUrl(),
|
||||
'notification' => helper::translate('La clé est incorrecte'),
|
||||
'state' => false
|
||||
]);
|
||||
}
|
||||
} else {
|
||||
/**
|
||||
* Envoi d'un email contenant une clé
|
||||
* Stockage de la clé dans le compte de l'utilisateur
|
||||
*/
|
||||
// La clé est envoyée une seule fois
|
||||
$sent = false;
|
||||
if (
|
||||
$this->getData(['user', $this->getUser('id'), 'authKey'])
|
||||
&& $this->getData(['user', $this->getUser('id'), 'connectTimeout']) === 0
|
||||
) {
|
||||
$sent = $this->sendMail(
|
||||
$this->getUser('mail'),
|
||||
'Tentative de connexion à votre',
|
||||
//'Bonjour <strong>' . $item['prenom'] . ' ' . $item['nom'] . '</strong>,<br><br>' .
|
||||
'<p>Clé de validation à saisir dans le formulaire :</p>' .
|
||||
'<h1><center>' . $this->getData(['user', $this->getUser('id'), 'authKey']) . '</center></h1>',
|
||||
null,
|
||||
$this->getData(['config', 'smtp', 'from'])
|
||||
);
|
||||
// Stocker l'envoi de l'email
|
||||
$this->setData(['user', $this->getUser('id'), 'connectTimeout', time()]);
|
||||
}
|
||||
|
||||
// Message envoyé sinon la connexion est réalisée pour ne pas bloquer.
|
||||
if ($sent === false) {
|
||||
|
||||
}
|
||||
// Valeurs en sortie
|
||||
$this->addOutput([
|
||||
'title' => helper::translate('Double authentification'),
|
||||
'view' => 'auth',
|
||||
'display' => self::DISPLAY_LAYOUT_LIGHT,
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Déconnexion
|
||||
*/
|
||||
public function logout()
|
||||
{
|
||||
// Détruit les cookies d'authenfication
|
||||
helper::deleteCookie('ZWII_USER_ID');
|
||||
helper::deleteCookie('ZWII_USER_PASSWORD');
|
||||
|
||||
helper::deleteCookie('ZWII_AUTH_KEY');
|
||||
// Détruit la session
|
||||
session_destroy();
|
||||
|
||||
@ -1145,13 +1544,29 @@ class user extends common
|
||||
// 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)])))
|
||||
or $this->getUrl(3) !== md5(json_encode($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'])))
|
||||
);
|
||||
// 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()
|
||||
? ' Temps dépassé '
|
||||
: $message;
|
||||
$message = $this->getUrl(3) !== md5(json_encode($this->getData(['user', $this->getUrl(2)])))
|
||||
? ' 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 !'),
|
||||
'notification' => helper::translate('Impossible de réinitialiser le mot de passe de ce compte !') . $message,
|
||||
'state' => false
|
||||
//'access' => false
|
||||
]);
|
||||
@ -1174,12 +1589,14 @@ class user extends common
|
||||
$newPassword = $this->getInput('userResetNewPassword', helper::FILTER_PASSWORD, true);
|
||||
}
|
||||
// Modifie le mot de passe
|
||||
$this->setData(['user', $this->getUrl(2), 'password', $newPassword]);
|
||||
$this->setData(['user', $this->getUrl(2), 'password', $newPassword], false);
|
||||
// Réinitialise la date de la demande
|
||||
$this->setData(['user', $this->getUrl(2), 'forgot', 0]);
|
||||
$this->setData(['user', $this->getUrl(2), 'forgot', 0], false);
|
||||
// Réinitialise le blocage
|
||||
$this->setData(['user', $this->getUrl(2), 'connectFail', 0]);
|
||||
$this->setData(['user', $this->getUrl(2), 'connectTimeout', 0]);
|
||||
$this->setData(['user', $this->getUrl(2), 'connectFail', 0], false);
|
||||
$this->setData(['user', $this->getUrl(2), 'connectTimeout', 0], false);
|
||||
// Sauvegarde la base manuellement
|
||||
$this->saveDB('user');
|
||||
// Valeurs en sortie
|
||||
$this->addOutput([
|
||||
'notification' => helper::translate('Nouveau mot de passe enregistré'),
|
||||
@ -1293,7 +1710,7 @@ class user extends common
|
||||
"accessCsrf" => null,
|
||||
'tags' => $item['tags']
|
||||
]
|
||||
]);
|
||||
], false);
|
||||
// Icône de notification
|
||||
$item['notification'] = $create ? template::ico('check') : template::ico('cancel');
|
||||
// Envoi du mail
|
||||
@ -1334,6 +1751,8 @@ class user extends common
|
||||
}
|
||||
|
||||
}
|
||||
// Sauvegarde la base manuellement
|
||||
$this->saveDB(module: 'user');
|
||||
if (empty(self::$users)) {
|
||||
$notification = helper::translate('Rien à importer, erreur de format ou fichier incorrect');
|
||||
$success = false;
|
||||
@ -1375,6 +1794,154 @@ class user extends common
|
||||
|
||||
}
|
||||
|
||||
public function tag()
|
||||
{
|
||||
// Contenu sélectionné
|
||||
$courseId = $this->getUrl(2);
|
||||
|
||||
// Accès limité aux admins, à l'auteur ou éditeurs inscrits
|
||||
if (
|
||||
$this->getUser('permission', __CLASS__, __FUNCTION__) !== true
|
||||
) {
|
||||
// Valeurs en sortie
|
||||
$this->addOutput([
|
||||
'access' => false
|
||||
]);
|
||||
}
|
||||
|
||||
// Inscription des utilisateurs cochés
|
||||
if (
|
||||
isset($_POST['usersTagSubmit'])
|
||||
) {
|
||||
$notification = helper::translate('Modification de %s étiquette(s)');
|
||||
$success = true;
|
||||
$count = 0;
|
||||
$newTags = $this->getInput('usersTagLabel', null, true);
|
||||
foreach ($_POST as $keyPost => $valuePost) {
|
||||
// Exclure les variables post qui ne sont pas des userId et ne traiter que les non inscrits
|
||||
if (
|
||||
$this->getData(['user', $keyPost]) !== null
|
||||
) {
|
||||
$this->setData(['user', $keyPost, 'tags', $newTags], false);
|
||||
$count += 1;
|
||||
}
|
||||
}
|
||||
// Sauvegarde la base manuellement
|
||||
$this->saveDB(module: 'user');
|
||||
// Valeurs en sortie
|
||||
$this->addOutput([
|
||||
'redirect' => helper::baseUrl() . 'user/tag',
|
||||
'notification' => sprintf($count > 1 ? $notification . 's' : $notification, $count),
|
||||
'state' => $success
|
||||
]);
|
||||
|
||||
}
|
||||
|
||||
|
||||
// Liste des groupes et des profils
|
||||
$usersGroups = $this->getData(['profil']);
|
||||
|
||||
foreach ($usersGroups as $groupId => $groupValue) {
|
||||
switch ($groupId) {
|
||||
case "-1":
|
||||
case "0":
|
||||
break;
|
||||
case "3":
|
||||
self::$usersGroups['30'] = 'Administrateur';
|
||||
$profils['30'] = 0;
|
||||
break;
|
||||
case "1":
|
||||
case "2":
|
||||
foreach ($groupValue as $profilId => $profilValue) {
|
||||
if ($profilId) {
|
||||
self::$usersGroups[$groupId . $profilId] = sprintf(helper::translate('Groupe %s - Profil %s'), self::$groupPublics[$groupId], $profilValue['name']);
|
||||
$profils[$groupId . $profilId] = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Liste alphabétique
|
||||
self::$alphabet = range('A', 'Z');
|
||||
$alphabet = range('A', 'Z');
|
||||
self::$alphabet = array_combine($alphabet, self::$alphabet);
|
||||
self::$alphabet = array_merge(['all' => 'Tout'], self::$alphabet);
|
||||
|
||||
// Liste des inscrits dans le contenu sélectionné.
|
||||
$users = $this->getData(['user']);
|
||||
if (is_array($users)) {
|
||||
// Tri du tableau par défaut par $userId
|
||||
ksort($users);
|
||||
foreach ($users as $userId => $userValue) {
|
||||
|
||||
// Compte les rôles
|
||||
if (isset($profils[$this->getData(['user', $userId, 'group']) . $this->getData(['user', $userId, 'profil'])])) {
|
||||
$profils[$this->getData(['user', $userId, 'group']) . $this->getData(['user', $userId, 'profil'])]++;
|
||||
}
|
||||
|
||||
// Filtres
|
||||
if (
|
||||
isset($_POST['usersFilterGroup'])
|
||||
|| isset($_POST['usersFilterFirstName'])
|
||||
|| isset($_POST['usersFilterLastName'])
|
||||
) {
|
||||
|
||||
// Groupe et profils
|
||||
$group = (string) $this->getData(['user', $userId, 'group']);
|
||||
$profil = (string) $this->getData(['user', $userId, 'profil']);
|
||||
$firstName = $this->getData(['user', $userId, 'firstname']);
|
||||
$lastName = $this->getData(['user', $userId, 'lastname']);
|
||||
if (
|
||||
$this->getInput('usersFilterGroup', helper::FILTER_INT) > 0
|
||||
&& $this->getInput('usersFilterGroup', helper::FILTER_STRING_SHORT) !== $group . $profil
|
||||
)
|
||||
continue;
|
||||
// Première lettre du prénom
|
||||
if (
|
||||
$this->getInput('usersFilterFirstName', helper::FILTER_STRING_SHORT) !== 'all'
|
||||
&& $this->getInput('usersFilterFirstName', helper::FILTER_STRING_SHORT) !== strtoupper(substr($firstName, 0, 1))
|
||||
)
|
||||
continue;
|
||||
// Première lettre du nom
|
||||
if (
|
||||
$this->getInput('usersFilterLastName', helper::FILTER_STRING_SHORT) !== 'all'
|
||||
&& $this->getInput('usersFilterLastName', helper::FILTER_STRING_SHORT) !== strtoupper(substr($lastName, 0, 1))
|
||||
)
|
||||
continue;
|
||||
}
|
||||
|
||||
// Construction du tableau
|
||||
self::$users[] = [
|
||||
template::checkbox($userId, true, '', ['class' => 'checkboxSelect']),
|
||||
$userId,
|
||||
$this->getData(['user', $userId, 'firstname']),
|
||||
$this->getData(['user', $userId, 'lastname']),
|
||||
$this->getData(['user', $userId, 'tags']),
|
||||
];
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
// Ajoute les effectifs aux profils du sélecteur
|
||||
foreach (self::$usersGroups as $groupId => $groupValue) {
|
||||
if ($groupId === 'all') {
|
||||
self::$usersGroups['all'] = self::$usersGroups['all'] . ' (' . array_sum($profils) . ')';
|
||||
} else {
|
||||
self::$usersGroups[$groupId] = self::$usersGroups[$groupId] . ' (' . $profils[$groupId] . ')';
|
||||
}
|
||||
}
|
||||
|
||||
// Valeurs en sortie
|
||||
$this->addOutput([
|
||||
'view' => 'tag',
|
||||
'title' => 'Étiquettes',
|
||||
'vendor' => [
|
||||
'datatables'
|
||||
]
|
||||
]);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Liste les dossier contenus dans RFM
|
||||
*/
|
||||
|
51
core/module/user/view/auth/auth.css
Normal file
51
core/module/user/view/auth/auth.css
Normal file
@ -0,0 +1,51 @@
|
||||
/**
|
||||
* This file is part of Zwii.
|
||||
*
|
||||
* For full copyright and license information, please see the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*
|
||||
* @author Rémi Jean <remi.jean@outlook.com>
|
||||
* @copyright Copyright (C) 2008-2018, Rémi Jean
|
||||
* @author Frédéric Tempez <frederic.tempez@outlook.com>
|
||||
* @copyright Copyright (C) 2018-2024, Frédéric Tempez
|
||||
* @license CC Attribution-NonCommercial-NoDerivatives 4.0 International
|
||||
* @link http://zwiicms.fr/
|
||||
*/
|
||||
|
||||
/** @import url("site/data/admin.css"); */
|
||||
|
||||
/** NE PAS EFFACER
|
||||
* admin.css
|
||||
*/
|
||||
|
||||
@media screen and (max-width: 768px) {
|
||||
#buttonsContainer {
|
||||
display: grid;
|
||||
}
|
||||
#loginContainer {
|
||||
order: 1;
|
||||
}
|
||||
#backContainer{
|
||||
order: 2;
|
||||
}
|
||||
}
|
||||
|
||||
#userAuthKey {
|
||||
text-align: center;
|
||||
font-size: 2rem;
|
||||
border: none; /* Supprime toutes les bordures */
|
||||
border-bottom: 2px solid #000; /* Ajoute uniquement une bordure inférieure */
|
||||
padding: 5px 0; /* Ajoute un peu d'espace au-dessus et en dessous */
|
||||
margin-top: 10px; /* Ajoute un espacement au-dessus du champ */
|
||||
outline: none; /* Supprime l'effet de focus par défaut */
|
||||
letter-spacing: 6px; /* Ajoute un espacement de 2 pixels */
|
||||
}
|
||||
|
||||
#userAuthKey:focus {
|
||||
border-bottom-color: #007bff; /* Change la couleur du cadre bas lorsqu'on clique */
|
||||
border-bottom-width: 3px; /* Accentue la bordure inférieure */
|
||||
}
|
||||
|
||||
.container.light {
|
||||
filter: drop-shadow(5px 5px 10px rgba(0, 0, 0, 0.2));
|
||||
}
|
23
core/module/user/view/auth/auth.php
Normal file
23
core/module/user/view/auth/auth.php
Normal file
@ -0,0 +1,23 @@
|
||||
<?php echo template::formOpen('userAuthForm'); ?>
|
||||
<div class="row">
|
||||
<div class="col4 offset4">
|
||||
<?php echo template::text('userAuthKey', [
|
||||
'label' => helper::translate('Clé reçue par couriel')
|
||||
]); ?>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row" id="buttonsContainer">
|
||||
<div class="col2" id="backContainer">
|
||||
<?php echo template::button('userAuthBack', [
|
||||
'href' => $this->getUrl(2) ? helper::baseUrl() . ' user/login' . str_replace('_', '/', str_replace('__', '#', $this->getUrl(2))) : helper::baseUrl() . ' user/login',
|
||||
'value' => template::ico('left')
|
||||
]); ?>
|
||||
</div>
|
||||
<div class="col2 offset8" id="loginContainer">
|
||||
<?php echo template::submit('userLoginSubmit', [
|
||||
'value' => template::ico('check'),
|
||||
'ico' => '',
|
||||
]); ?>
|
||||
</div>
|
||||
</div>
|
||||
<?php echo template::formClose(); ?>
|
@ -77,7 +77,7 @@
|
||||
<div class="col12">
|
||||
<?php echo template::text('userEditTags', [
|
||||
'label' => 'Étiquettes',
|
||||
'disabled' => $this->getUser('group') > self::GROUP_EDITOR ? false : true,
|
||||
'readonly' => $this->getUser('group') > self::GROUP_EDITOR ? false : true,
|
||||
'value' => $this->getData(['user', $this->getUrl(2), 'tags']),
|
||||
'help' => 'Les étiquettes sont séparées par des espaces'
|
||||
]); ?>
|
||||
|
@ -22,12 +22,14 @@ $(document).ready((function () {
|
||||
$("#userFilterGroup, #userFilterFirstName, #userFilterLastName").change(function () {
|
||||
$("#userFilterUserForm").submit();
|
||||
});
|
||||
|
||||
$.fn.dataTable.moment( 'DD/MM/YYYY' );
|
||||
$('#dataTables').DataTable({
|
||||
language: {
|
||||
url: "core/vendor/datatables/french.json"
|
||||
},
|
||||
locale: 'fr',
|
||||
stateSave: true,
|
||||
"lengthMenu": [[10, 25, 50, -1], [10, 25, 50, "Tout"]],
|
||||
"columnDefs": [
|
||||
{
|
||||
target: 5,
|
||||
|
@ -6,27 +6,35 @@
|
||||
'value' => template::ico('home')
|
||||
]); ?>
|
||||
</div>
|
||||
<div class="col1">
|
||||
<?php /**echo template::button('userHelp', [
|
||||
'href' => 'https://doc.zwiicms.fr/gestion-des-utilisateurs',
|
||||
'target' => '_blank',
|
||||
'value' => template::ico('help'),
|
||||
'class' => 'buttonHelp',
|
||||
'help' => 'Consulter l\'aide en ligne'
|
||||
]);*/?>
|
||||
</div>
|
||||
<div class="col1 offset7">
|
||||
<div class="col2 offset2">
|
||||
<?php echo template::button('userImport', [
|
||||
'href' => helper::baseUrl() . 'user/import',
|
||||
'value' => template::ico('upload'),
|
||||
'help' => 'Importer des utilisateurs en masse'
|
||||
'ico' => 'users',
|
||||
'value' => 'Importer en masse'
|
||||
]); ?>
|
||||
</div>
|
||||
<div class="col1">
|
||||
<div class="col2">
|
||||
<?php echo template::button('userDeleteAll', [
|
||||
'class' => 'userDeleteAll buttonRed',
|
||||
'href' => helper::baseUrl() . 'user/usersDelete/' . $this->getUrl(2),
|
||||
'ico' => 'users',
|
||||
'value' => 'Désinscrire en masse',
|
||||
]) ?>
|
||||
</div>
|
||||
<div class="col2">
|
||||
<?php echo template::button('userTag', [
|
||||
'href' => helper::baseUrl() . 'user/tag',
|
||||
'ico' => 'tags',
|
||||
'value' => 'Étiquettes',
|
||||
'help' => 'Filtrer les utilisateurs avec des tags'
|
||||
]); ?>
|
||||
</div>
|
||||
<div class="col2">
|
||||
<?php echo template::button('userGroup', [
|
||||
'href' => helper::baseUrl() . 'user/profil',
|
||||
'value' => template::ico('lock'),
|
||||
'help' => 'Profils'
|
||||
'ico' => 'lock',
|
||||
'value' => 'Profils',
|
||||
'help' => 'Permissions par profils'
|
||||
]); ?>
|
||||
</div>
|
||||
<div class="col1">
|
||||
@ -60,4 +68,4 @@
|
||||
</div>
|
||||
</div>
|
||||
<?php echo template::formClose(); ?>
|
||||
<?php echo template::table([2, 2, 2, 2, 2, 1, 1], $module::$users, ['Identifiant', 'Nom', 'Groupe', 'Profil', 'Étiquettes', '', ''], ['id' => 'dataTables']); ?>
|
||||
<?php echo template::table([3, 2, 2, 2, 2, 1, 1], $module::$users, ['Nom', 'Groupe', 'Profil', 'Étiquettes', 'Date dernière vue', '', ''], ['id' => 'dataTables']); ?>
|
@ -33,3 +33,23 @@
|
||||
order: 2;
|
||||
}
|
||||
}
|
||||
|
||||
#userAuthKey {
|
||||
text-align: center;
|
||||
font-size: 2rem;
|
||||
border: none; /* Supprime toutes les bordures */
|
||||
border-bottom: 2px solid #000; /* Ajoute uniquement une bordure inférieure */
|
||||
padding: 5px 0; /* Ajoute un peu d'espace au-dessus et en dessous */
|
||||
margin-top: 10px; /* Ajoute un espacement au-dessus du champ */
|
||||
outline: none; /* Supprime l'effet de focus par défaut */
|
||||
letter-spacing: 6px; /* Ajoute un espacement de 2 pixels */
|
||||
}
|
||||
|
||||
#userAuthKey:focus {
|
||||
border-bottom-color: #007bff; /* Change la couleur du cadre bas lorsqu'on clique */
|
||||
border-bottom-width: 3px; /* Accentue la bordure inférieure */
|
||||
}
|
||||
|
||||
.container.light {
|
||||
filter: drop-shadow(5px 5px 10px rgba(0, 0, 0, 0.2));
|
||||
}
|
@ -8,4 +8,32 @@
|
||||
* @license CC Attribution-NonCommercial-NoDerivatives 4.0 International
|
||||
* @link http://zwiicms.fr/
|
||||
*/
|
||||
$(document).ready((function(){$(".zwiico-eye").mouseenter((function(){$("#userLoginPassword").attr("type","text")})),$(".zwiico-eye").mouseleave((function(){$("#userLoginPassword").attr("type","password")}))}));
|
||||
$(document).ready((function() {
|
||||
$("#userLoginId").on("change keydown keyup", function (event) {
|
||||
var userId = $(this).val();
|
||||
if (
|
||||
event.keyCode !== 8 // BACKSPACE
|
||||
&& event.keyCode !== 37 // LEFT
|
||||
&& event.keyCode !== 39 // RIGHT
|
||||
&& event.keyCode !== 46 // DELETE
|
||||
&& window.getSelection().toString() !== userId // Texte sélectionné
|
||||
) {
|
||||
var searchReplace = {
|
||||
"á": "a", "à": "a", "â": "a", "ä": "a", "ã": "a", "å": "a", "ç": "c", "é": "e", "è": "e", "ê": "e", "ë": "e", "í": "i", "ì": "i", "î": "i", "ï": "i", "ñ": "n", "ó": "o", "ò": "o", "ô": "o", "ö": "o", "õ": "o", "ú": "u", "ù": "u", "û": "u", "ü": "u", "ý": "y", "ÿ": "y",
|
||||
"Á": "A", "À": "A", "Â": "A", "Ä": "A", "Ã": "A", "Å": "A", "Ç": "C", "É": "E", "È": "E", "Ê": "E", "Ë": "E", "Í": "I", "Ì": "I", "Î": "I", "Ï": "I", "Ñ": "N", "Ó": "O", "Ò": "O", "Ô": "O", "Ö": "O", "Õ": "O", "Ú": "U", "Ù": "U", "Û": "U", "Ü": "U", "Ý": "Y", "Ÿ": "Y",
|
||||
"'": "-", "\"": "-", " ": "-"
|
||||
};
|
||||
userId = userId.replace(/[áàâäãåçéèêëíìîïñóòôöõúùûüýÿ'" ]/ig, function (match) {
|
||||
return searchReplace[match];
|
||||
});
|
||||
userId = userId.replace(/[^a-z0-9-]/ig, "");
|
||||
$(this).val(userId);
|
||||
}
|
||||
});
|
||||
|
||||
$(".zwiico-eye").mouseenter((function() {
|
||||
$("#userLoginPassword").attr("type", "text")
|
||||
})), $(".zwiico-eye").mouseleave((function() {
|
||||
$("#userLoginPassword").attr("type", "password")
|
||||
}))
|
||||
}));
|
@ -45,10 +45,10 @@
|
||||
'value' => template::ico('left')
|
||||
]); ?>
|
||||
</div>
|
||||
<div class="col3 offset7" id="loginContainer">
|
||||
<div class="col2 offset8" id="loginContainer">
|
||||
<?php echo template::submit('userLoginSubmit', [
|
||||
'value' => 'Connexion',
|
||||
'ico' => ''
|
||||
'value' => template::ico('check'),
|
||||
'ico' => '',
|
||||
]); ?>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -44,47 +44,6 @@
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row containerPage">
|
||||
<div class="col12">
|
||||
<div class="block">
|
||||
<h4>
|
||||
<?php echo helper::translate('Permissions sur les pages'); ?>
|
||||
</h4>
|
||||
<div class="row">
|
||||
<div class="col3">
|
||||
<?php echo template::checkbox('profilAddPageAdd', true, 'Ajouter'); ?>
|
||||
</div>
|
||||
<div class="col3">
|
||||
<?php echo template::checkbox('profilAddPageEdit', true, 'Éditer'); ?>
|
||||
</div>
|
||||
<div class="col3">
|
||||
<?php echo template::checkbox('profilAddPageDelete', true, 'Effacer'); ?>
|
||||
</div>
|
||||
<div class="col3">
|
||||
<?php echo template::checkbox('profilAddPageDuplicate', true, 'Dupliquer'); ?>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col3">
|
||||
<?php echo template::checkbox('profilAddPageModule', true, 'Module'); ?>
|
||||
</div>
|
||||
<div class="col3">
|
||||
<?php echo template::checkbox('profilAddPagecssEditor', true, 'Éditeur CSS'); ?>
|
||||
</div>
|
||||
<div class="col3">
|
||||
<?php echo template::checkbox('profilAddPagejsEditor', true, 'Éditeur JS'); ?>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="containerModule">
|
||||
<?php foreach (user::$listModules as $moduleId): ?>
|
||||
<?php if (file_exists('module/' . $moduleId . '/profil/view/add.inc.php')) {
|
||||
include('module/' . $moduleId . '/profil/view/add.inc.php');
|
||||
} ?>
|
||||
<?php endforeach; ?>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col12">
|
||||
<div class="block">
|
||||
@ -109,11 +68,16 @@
|
||||
<div class="col3">
|
||||
<?php echo template::checkbox('profilAddFileManager', true, 'Autorisé'); ?>
|
||||
</div>
|
||||
<div class="col6">
|
||||
<?php echo template::select('profilAddPath', $module::$sharePath, [
|
||||
'label' => 'Dossier',
|
||||
<div class="col5">
|
||||
<?php echo template::select('profilAddCoursePath', $module::$sharePath, [
|
||||
'label' => 'Dossier depuis un espace',
|
||||
'class' => 'filemanager',
|
||||
]); ?>
|
||||
</div>
|
||||
<div class="col5">
|
||||
<?php echo template::select('profilAddHomePath', $module::$sharePath, [
|
||||
'label' => 'Dossier depuis l\'accueil',
|
||||
'class' => 'filemanager',
|
||||
'help' => 'Chaque espace dispose d\'un dossier spécifique, le choix "Dossier de l\'espace actif" le sélectionne automatiquement.'
|
||||
]); ?>
|
||||
</div>
|
||||
</div>
|
||||
@ -195,4 +159,101 @@
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row containerPage">
|
||||
<div class="col12">
|
||||
<div class="block">
|
||||
<h4>
|
||||
<?php echo helper::translate('Gestion des espaces'); ?>
|
||||
</h4>
|
||||
<div class="row">
|
||||
<div class="col6">
|
||||
<?php echo template::checkbox('profilAddCourseTutor', true, 'Gère les espaces comme auteur et participant'); ?>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col3">
|
||||
<?php echo template::checkbox('profilAddCourseEdit', true, 'Éditer un espace'); ?>
|
||||
</div>
|
||||
<div class="col3">
|
||||
<?php echo template::checkbox('profilAddCourseBackup', true, 'Sauvegarder un espace'); ?>
|
||||
</div>
|
||||
<div class="col3">
|
||||
<?php echo template::checkbox('profilAddCourseRestore', true, 'Restaurer un espace'); ?>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col3">
|
||||
<?php echo template::checkbox('profilAddCourseUsers', true, 'Gérer les participants'); ?>
|
||||
</div>
|
||||
<div class="col3">
|
||||
<?php echo template::checkbox('profilAddCourseExport', true, 'Exporter un espace en html'); ?>
|
||||
</div>
|
||||
</div>
|
||||
<div id="courseContainer">
|
||||
<div class="row">
|
||||
<div class="col3">
|
||||
<?php echo template::checkbox('profilAddCourseUserHistory', true, 'Voir historique d\'un participant'); ?>
|
||||
</div>
|
||||
<div class="col3">
|
||||
<?php echo template::checkbox('profilAddCourseuserReportExport', true, 'Exporter historique d\'un participant'); ?>
|
||||
</div>
|
||||
<div class="col3">
|
||||
<?php echo template::checkbox('profilAddCourseUserDelete', true, 'Désinscrire un participant'); ?>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col3">
|
||||
<?php echo template::checkbox('profilAddCourseUsersAdd', true, 'Inscrire en masse'); ?>
|
||||
</div>
|
||||
<div class="col3">
|
||||
<?php echo template::checkbox('profilAddCourseUsersDelete', true, 'Désinscrire en masse'); ?>
|
||||
</div>
|
||||
<div class="col3">
|
||||
<?php echo template::checkbox('profilAddCourseReset', true, 'Réinitialiser un espace'); ?>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col12">
|
||||
<div class="block">
|
||||
<h4>
|
||||
<?php echo helper::translate('Permissions sur les pages'); ?>
|
||||
</h4>
|
||||
<div class="row">
|
||||
<div class="col3">
|
||||
<?php echo template::checkbox('profilAddPageAdd', true, 'Ajouter'); ?>
|
||||
</div>
|
||||
<div class="col3">
|
||||
<?php echo template::checkbox('profilAddPageEdit', true, 'Éditer'); ?>
|
||||
</div>
|
||||
<div class="col3">
|
||||
<?php echo template::checkbox('profilAddPageDelete', true, 'Effacer'); ?>
|
||||
</div>
|
||||
<div class="col3">
|
||||
<?php echo template::checkbox('profilAddPageDuplicate', true, 'Dupliquer'); ?>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col3">
|
||||
<?php echo template::checkbox('profilAddPageModule', true, 'Module'); ?>
|
||||
</div>
|
||||
<div class="col3">
|
||||
<?php echo template::checkbox('profilAddPagecssEditor', true, 'Éditeur CSS'); ?>
|
||||
</div>
|
||||
<div class="col3">
|
||||
<?php echo template::checkbox('profilAddPagejsEditor', true, 'Éditeur JS'); ?>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="containerModule">
|
||||
<?php foreach (user::$listModules as $moduleId): ?>
|
||||
<?php if (file_exists('module/' . $moduleId . '/profil/view/add.inc.php')) {
|
||||
include('module/' . $moduleId . '/profil/view/add.inc.php');
|
||||
} ?>
|
||||
<?php endforeach; ?>
|
||||
</div>
|
||||
<?php echo template::formClose(); ?>
|
@ -54,6 +54,19 @@ $(document).ready(function () {
|
||||
$(".containerModule").slideDown();
|
||||
}
|
||||
|
||||
if ($('#profilEditCourseUsers').is(':checked')) {
|
||||
// Activer les autres checkboxes
|
||||
$('#profilEditCourseUserHistory, #profilEditCourseuserReportExport, #profilEditCourseUserDelete, #profilEditCourseUsersAdd, #profilEditCourseUsersDelete, #profilEditCourseReset').prop('disabled', false);
|
||||
} else {
|
||||
// Désactiver les autres checkboxes
|
||||
$('#profilEditCourseUserHistory, #profilEditCourseuserReportExport, #profilEditCourseUserDelete, #profilEditCourseUsersAdd, #profilEditCourseUsersDelete, #profilEditCourseReset').prop('checked', false).prop('disabled', true);
|
||||
// Désactiver les modules et tout décocher
|
||||
$(".courseContainer").slideUp();
|
||||
$('.courseContainer input[type="checkbox"]').prop('checked', false);
|
||||
}
|
||||
|
||||
// EVENEMENTS
|
||||
|
||||
// À chaque inversion de l'état du checkbox avec l'id "profilEditFileManager", désactive ou active tous les éléments de la classe "filemanager" en fonction de l'état
|
||||
$("#profilEditFileManager").change(function () {
|
||||
if (!$(this).is(':checked')) {
|
||||
@ -68,7 +81,7 @@ $(document).ready(function () {
|
||||
if (!$(this).is(':checked')) {
|
||||
$(".blogEditCommentOptions").slideUp();
|
||||
} else {
|
||||
$('.blogEditCommentOptions input[type="checkbox"]').prop('checked', false);
|
||||
$('.blogEditCommentOptions input[type="checkbox"]').prop("disabled", true);
|
||||
$(".blogEditCommentOptions").slideDown();
|
||||
}
|
||||
});
|
||||
@ -118,4 +131,20 @@ $(document).ready(function () {
|
||||
}
|
||||
});
|
||||
|
||||
// Gérer l’évènement de modification de la checkbox #profilEditCourse
|
||||
$('#profilEditCourseUsers').change(function () {
|
||||
if ($(this).is(':checked')) {
|
||||
// Activer les autres checkboxes
|
||||
$('#profilEditCourseUserHistory, #profilEditCourseuserReportExport, #profilEditCourseUserDelete, #profilEditCourseUsersAdd, #profilEditCourseUsersDelete, #profilEditCourseReset').prop('disabled', false);
|
||||
|
||||
} else {
|
||||
// Désactiver les autres checkboxes
|
||||
$('#profilEditCourseUserHistory, #profilEditCourseuserReportExport, #profilEditCourseUserDelete, #profilEditCourseUsersAdd, #profilEditCourseUsersDelete, #profilEditCourseReset').prop('checked', false).prop('disabled', true);
|
||||
// Désactiver les modules et tout décocher
|
||||
$(".courseContainer").slideUp();
|
||||
$('.courseContainer input[type="checkbox"]').prop('checked', false);
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
});
|
||||
|
@ -27,9 +27,9 @@
|
||||
'label' => 'Nom du profil',
|
||||
'value' => helper::translate($this->getData(['profil', $this->getUrl(2), $this->getUrl(3), 'name']))
|
||||
]); ?>
|
||||
</div>
|
||||
<div class="col6">
|
||||
<?php echo template::select('profilEditProfil', $module::$profils, [
|
||||
</div>
|
||||
<div class="col6">
|
||||
<?php echo template::select('profilEditProfil', $module::$profils, [
|
||||
'label' => 'Hiérarchie',
|
||||
'help' => 'Rang 9 > rang 1. Le profil de rang 1 n\'est pas modifiable.',
|
||||
'selected' => $this->getUrl(3),
|
||||
@ -63,63 +63,6 @@
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<?php if ($this->getUrl(2) >= self::GROUP_EDITOR): ?>
|
||||
<div class="row">
|
||||
<div class="col12">
|
||||
<div class="block">
|
||||
<h4>
|
||||
<?php echo helper::translate('Permissions sur les pages'); ?>
|
||||
</h4>
|
||||
<div class="row">
|
||||
<div class="col3">
|
||||
<?php echo template::checkbox('profilEditPageAdd', true, 'Ajouter', [
|
||||
'checked' => $this->getData(['profil', $this->getUrl(2), $this->getUrl(3), 'page', 'add'])
|
||||
]); ?>
|
||||
</div>
|
||||
<div class="col3">
|
||||
<?php echo template::checkbox('profilEditPageEdit', true, 'Éditer', [
|
||||
'checked' => $this->getData(['profil', $this->getUrl(2), $this->getUrl(3), 'page', 'edit'])
|
||||
]); ?>
|
||||
</div>
|
||||
<div class="col3">
|
||||
<?php echo template::checkbox('profilEditPageDelete', true, 'Effacer', [
|
||||
'checked' => $this->getData(['profil', $this->getUrl(2), $this->getUrl(3), 'page', 'delete'])
|
||||
]); ?>
|
||||
</div>
|
||||
<div class="col3">
|
||||
<?php echo template::checkbox('profilEditPageDuplicate', true, 'Dupliquer', [
|
||||
'checked' => $this->getData(['profil', $this->getUrl(2), $this->getUrl(3), 'page', 'duplicate'])
|
||||
]); ?>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col3">
|
||||
<?php echo template::checkbox('profilEditPageModule', true, 'Module', [
|
||||
'checked' => $this->getData(['profil', $this->getUrl(2), $this->getUrl(3), 'page', 'module'])
|
||||
]); ?>
|
||||
</div>
|
||||
<div class="col3">
|
||||
<?php echo template::checkbox('profilEditPagecssEditor', true, 'Éditeur CSS', [
|
||||
'checked' => $this->getData(['profil', $this->getUrl(2), $this->getUrl(3), 'page', 'cssEditor'])
|
||||
]); ?>
|
||||
</div>
|
||||
<div class="col3">
|
||||
<?php echo template::checkbox('profilEditPagejsEditor', true, 'Éditeur JS', [
|
||||
'checked' => $this->getData(['profil', $this->getUrl(2), $this->getUrl(3), 'page', 'jsEditor'])
|
||||
]); ?>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="containerModule">
|
||||
<?php foreach (user::$listModules as $moduleId): ?>
|
||||
<?php if (file_exists('module/' . $moduleId . '/profil/view/edit.inc.php')) {
|
||||
include('module/' . $moduleId . '/profil/view/edit.inc.php');
|
||||
} ?>
|
||||
<?php endforeach; ?>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
<div class="row">
|
||||
<div class="col12">
|
||||
<div class="block">
|
||||
@ -136,6 +79,7 @@
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
<div class="col12">
|
||||
<div class="block">
|
||||
@ -143,17 +87,28 @@
|
||||
<?php echo helper::translate('Gestionnaire de fichiers'); ?>
|
||||
</h4>
|
||||
<div class="row">
|
||||
<div class="col3">
|
||||
<div class="col2">
|
||||
<?php echo template::checkbox('profilEditFileManager', true, 'Autorisé', [
|
||||
'checked' => $this->getData(['profil', $this->getUrl(2), $this->getUrl(3), 'filemanager'])
|
||||
]); ?>
|
||||
</div>
|
||||
<div class="col6">
|
||||
<?php echo template::select('profilEditPath', $module::$sharePath, [
|
||||
'label' => 'Dossier',
|
||||
<div class="col5">
|
||||
<?php echo template::select('profilEditCoursePath', $module::$sharePath, [
|
||||
'label' => 'Dossier depuis un espace',
|
||||
'class' => 'filemanager',
|
||||
'selected' => '.' . $this->getData(['profil', $this->getUrl(2), $this->getUrl(3), 'folder', 'path']),
|
||||
'help' => 'Chaque espace dispose d\'un dossier spécifique, le choix \'Dossier de l\'espace actif\' le sélectionne automatiquement.'
|
||||
/*
|
||||
* 'none' interdit l'accès au gestionnaire de fichier
|
||||
* Ce n'est pas un chemin donc on n'ajoute pas le .
|
||||
*/
|
||||
'selected' => $this->getData(['profil', $this->getUrl(2), $this->getUrl(3), 'folder', 'coursePath'])
|
||||
]); ?>
|
||||
</div>
|
||||
<div class="col5">
|
||||
<?php echo template::select('profilEditHomePath', $module::$sharePath, [
|
||||
'label' => 'Dossier depuis l\'accueil',
|
||||
'class' => 'filemanager',
|
||||
// 'none' interdit l'accès au gestionnaire de fichier au niveau de l'accueil
|
||||
'selected' => $this->getData(['profil', $this->getUrl(2), $this->getUrl(3), 'folder', 'homePath'])
|
||||
]); ?>
|
||||
</div>
|
||||
</div>
|
||||
@ -284,4 +239,143 @@
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<?php if ($this->getUrl(2) >= self::GROUP_EDITOR): ?>
|
||||
<div class="row">
|
||||
<div class="col12">
|
||||
<div class="block">
|
||||
<h4>
|
||||
<?php echo helper::translate('Gestion des espaces'); ?>
|
||||
</h4>
|
||||
<div class="row">
|
||||
<div class="col6">
|
||||
<?php echo template::checkbox('profilEditCourseTutor', true, 'Gère les espaces comme auteur et participant', [
|
||||
'checked' => $this->getData(['profil', $this->getUrl(2), $this->getUrl(3), 'course', 'tutor'])
|
||||
]); ?>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
<div class="col3">
|
||||
<?php echo template::checkbox('profilEditCourseEdit', true, 'Éditer un espace', [
|
||||
'checked' => $this->getData(['profil', $this->getUrl(2), $this->getUrl(3), 'course', 'edit']),
|
||||
]); ?>
|
||||
</div>
|
||||
<div class="col3">
|
||||
<?php echo template::checkbox('profilEditCourseBackup', true, 'Sauvegarder un espace', [
|
||||
'checked' => $this->getData(['profil', $this->getUrl(2), $this->getUrl(3), 'course', 'backup']),
|
||||
]); ?>
|
||||
</div>
|
||||
<div class="col3">
|
||||
<?php echo template::checkbox('profilEditCourseRestore', true, 'Restaurer un espace', [
|
||||
'checked' => $this->getData(['profil', $this->getUrl(2), $this->getUrl(3), 'course', 'restore']),
|
||||
]); ?>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col3">
|
||||
<?php echo template::checkbox('profilEditCourseUsers', true, 'Gérer les participants', [
|
||||
'checked' => $this->getData(['profil', $this->getUrl(2), $this->getUrl(3), 'course', 'users']),
|
||||
]); ?>
|
||||
</div>
|
||||
<div class="col3">
|
||||
<?php echo template::checkbox('profilEditCourseExport', true, 'Exporter un espace en html', [
|
||||
'checked' => $this->getData(['profil', $this->getUrl(2), $this->getUrl(3), 'course', 'export']),
|
||||
]); ?>
|
||||
</div>
|
||||
</div>
|
||||
<div id="courseContainer">
|
||||
<div class="row">
|
||||
<div class="col3">
|
||||
<?php echo template::checkbox('profilEditCourseUserHistory', true, 'Voir historique d\'un participant', [
|
||||
'checked' => $this->getData(['profil', $this->getUrl(2), $this->getUrl(3), 'course', 'userHistory']),
|
||||
]); ?>
|
||||
</div>
|
||||
<div class="col3">
|
||||
<?php echo template::checkbox('profilEditCourseuserReportExport', true, 'Exporter historique d\'un participant', [
|
||||
'checked' => $this->getData(['profil', $this->getUrl(2), $this->getUrl(3), 'course', 'userReportExport']),
|
||||
]); ?>
|
||||
</div>
|
||||
<div class="col3">
|
||||
<?php echo template::checkbox('profilEditCourseUserDelete', true, 'Désinscrire un participant', [
|
||||
'checked' => $this->getData(['profil', $this->getUrl(2), $this->getUrl(3), 'course', 'userDelete']),
|
||||
]); ?>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col3">
|
||||
<?php echo template::checkbox('profilEditCourseUsersAdd', true, 'Inscrire en masse', [
|
||||
'checked' => $this->getData(['profil', $this->getUrl(2), $this->getUrl(3), 'course', 'usersAdd']),
|
||||
]); ?>
|
||||
</div>
|
||||
<div class="col3">
|
||||
<?php echo template::checkbox('profilEditCourseUsersDelete', true, 'Désinscrire en masse', [
|
||||
'checked' => $this->getData(['profil', $this->getUrl(2), $this->getUrl(3), 'course', 'usersDelete']),
|
||||
]); ?>
|
||||
</div>
|
||||
<div class="col3">
|
||||
<?php echo template::checkbox('profilEditCourseReset', true, 'Réinitialiser un espace', [
|
||||
'checked' => $this->getData(['profil', $this->getUrl(2), $this->getUrl(3), 'course', 'reset']),
|
||||
]); ?>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col12">
|
||||
<div class="block">
|
||||
<h4>
|
||||
<?php echo helper::translate('Permissions sur les pages'); ?>
|
||||
</h4>
|
||||
<div class="row">
|
||||
<div class="col3">
|
||||
<?php echo template::checkbox('profilEditPageAdd', true, 'Ajouter', [
|
||||
'checked' => $this->getData(['profil', $this->getUrl(2), $this->getUrl(3), 'page', 'add'])
|
||||
]); ?>
|
||||
</div>
|
||||
<div class="col3">
|
||||
<?php echo template::checkbox('profilEditPageEdit', true, 'Éditer', [
|
||||
'checked' => $this->getData(['profil', $this->getUrl(2), $this->getUrl(3), 'page', 'edit'])
|
||||
]); ?>
|
||||
</div>
|
||||
<div class="col3">
|
||||
<?php echo template::checkbox('profilEditPageDelete', true, 'Effacer', [
|
||||
'checked' => $this->getData(['profil', $this->getUrl(2), $this->getUrl(3), 'page', 'delete'])
|
||||
]); ?>
|
||||
</div>
|
||||
<div class="col3">
|
||||
<?php echo template::checkbox('profilEditPageDuplicate', true, 'Dupliquer', [
|
||||
'checked' => $this->getData(['profil', $this->getUrl(2), $this->getUrl(3), 'page', 'duplicate'])
|
||||
]); ?>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col3">
|
||||
<?php echo template::checkbox('profilEditPageModule', true, 'Module', [
|
||||
'checked' => $this->getData(['profil', $this->getUrl(2), $this->getUrl(3), 'page', 'module'])
|
||||
]); ?>
|
||||
</div>
|
||||
<div class="col3">
|
||||
<?php echo template::checkbox('profilEditPagecssEditor', true, 'Éditeur CSS', [
|
||||
'checked' => $this->getData(['profil', $this->getUrl(2), $this->getUrl(3), 'page', 'cssEditor'])
|
||||
]); ?>
|
||||
</div>
|
||||
<div class="col3">
|
||||
<?php echo template::checkbox('profilEditPagejsEditor', true, 'Éditeur JS', [
|
||||
'checked' => $this->getData(['profil', $this->getUrl(2), $this->getUrl(3), 'page', 'jsEditor'])
|
||||
]); ?>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="containerModule">
|
||||
<?php foreach (user::$listModules as $moduleId): ?>
|
||||
<?php if (file_exists('module/' . $moduleId . '/profil/view/edit.inc.php')) {
|
||||
include('module/' . $moduleId . '/profil/view/edit.inc.php');
|
||||
} ?>
|
||||
<?php endforeach; ?>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
<?php echo template::formClose(); ?>
|
18
core/module/user/view/tag/tag.css
Normal file
18
core/module/user/view/tag/tag.css
Normal file
@ -0,0 +1,18 @@
|
||||
/**
|
||||
* This file is part of Zwii.
|
||||
*
|
||||
* For full copyright and license information, please see the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*
|
||||
* @author Rémi Jean <remi.jean@outlook.com>
|
||||
* @copyright Copyright (C) 2008-2018, Rémi Jean
|
||||
* @author Frédéric Tempez <frederic.tempez@outlook.com>
|
||||
* @copyright Copyright (C) 2018-2024, Frédéric Tempez
|
||||
* @license CC Attribution-NonCommercial-NoDerivatives 4.0 International
|
||||
* @link http://zwiicms.fr/
|
||||
*/
|
||||
|
||||
|
||||
/** NE PAS EFFACER
|
||||
* admin.css
|
||||
*/
|
101
core/module/user/view/tag/tag.js.php
Normal file
101
core/module/user/view/tag/tag.js.php
Normal file
@ -0,0 +1,101 @@
|
||||
/**
|
||||
* This file is part of Zwii.
|
||||
* For full copyright and license information, please see the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*
|
||||
* @author Rémi Jean <remi.jean@outlook.com>
|
||||
* @copyright Copyright (C) 2008-2018, Rémi Jean
|
||||
* @author Frédéric Tempez <frederic.tempez@outlook.com>
|
||||
* @copyright Copyright (C) 2018-2024, Frédéric Tempez
|
||||
* @license CC Attribution-NonCommercial-NoDerivatives 4.0 International
|
||||
* @link http://zwiicms.fr/
|
||||
*/
|
||||
|
||||
$(document).ready((function () {
|
||||
|
||||
$('tr').click(function () {
|
||||
// Cochez ou décochez la case à cocher dans cette ligne
|
||||
$(this).find('input[type="checkbox"]').prop('checked', function (i, val) {
|
||||
return !val; // Inverse l'état actuel de la case à cocher
|
||||
});
|
||||
});
|
||||
|
||||
$('#usersTagSelectAll').on('click', function () {
|
||||
$('.checkboxSelect').prop('checked', true);
|
||||
saveCheckboxState();
|
||||
});
|
||||
$('#usersTagSelectNone').on('click', function () {
|
||||
$('.checkboxSelect').prop('checked', false);
|
||||
saveCheckboxState();
|
||||
});
|
||||
|
||||
$("#usersFilterGroup, #usersFilterFirstName, #usersFilterLastName").change(function () {
|
||||
saveCheckboxState();
|
||||
$("#usersTagForm").submit();
|
||||
});
|
||||
|
||||
var table = $('#dataTables').DataTable({
|
||||
language: {
|
||||
url: "core/vendor/datatables/french.json"
|
||||
},
|
||||
locale: 'fr',
|
||||
"lengthMenu": [[10, 25, 50, 100, 299, -1], [10, 25, 50, 100, 200, "Tout"]],
|
||||
"columnDefs": [
|
||||
{
|
||||
target: 0,
|
||||
orderable: false,
|
||||
searchable: false,
|
||||
}
|
||||
]
|
||||
});
|
||||
|
||||
// Handle checkbox change event
|
||||
$('.checkboxSelect').on('change', function () {
|
||||
// Save checkbox state to cookies or local storage
|
||||
saveCheckboxState();
|
||||
});
|
||||
|
||||
// Handle checkbox state on DataTables draw event
|
||||
table.on('draw', function () {
|
||||
// Restore checkbox state from cookies or local storage
|
||||
restoreCheckboxState();
|
||||
});
|
||||
|
||||
// Empty local storage after submit
|
||||
$("#usersTagSubmit").on("click", function () {
|
||||
localStorage.setItem('checkboxState', JSON.stringify({}));
|
||||
});
|
||||
|
||||
// Restore checkbox state on page load
|
||||
restoreCheckboxState();
|
||||
|
||||
function saveCheckboxState() {
|
||||
|
||||
// Récupérer d'abord les données existantes dans le localStorage
|
||||
var existingData = JSON.parse(localStorage.getItem('checkboxState')) || {};
|
||||
|
||||
// Ajouter ou mettre à jour les données actuelles
|
||||
$('.checkboxSelect').each(function () {
|
||||
var checkboxId = $(this).attr('id');
|
||||
var checked = $(this).prop('checked');
|
||||
existingData[checkboxId] = checked;
|
||||
});
|
||||
|
||||
// Sauvegarder les données mises à jour dans le localStorage
|
||||
localStorage.setItem('checkboxState', JSON.stringify(existingData));
|
||||
}
|
||||
|
||||
// Function to restore checkbox state
|
||||
function restoreCheckboxState() {
|
||||
var checkboxState = JSON.parse(localStorage.getItem('checkboxState')) || {};
|
||||
// console.log(checkboxState);
|
||||
for (var checkboxId in checkboxState) {
|
||||
if (checkboxState.hasOwnProperty(checkboxId)) {
|
||||
var checked = checkboxState[checkboxId];
|
||||
// Update checkbox state based on stored information
|
||||
$('#' + checkboxId).prop('checked', checked);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}));
|
65
core/module/user/view/tag/tag.php
Normal file
65
core/module/user/view/tag/tag.php
Normal file
@ -0,0 +1,65 @@
|
||||
<?php echo template::formOpen('usersTagForm'); ?>
|
||||
<div class="row">
|
||||
<div class="col1">
|
||||
<?php echo template::button('userDeleteBack', [
|
||||
'class' => 'buttonGrey',
|
||||
'href' => helper::baseUrl() . 'user/' . $this->getUrl(2),
|
||||
'value' => template::ico('left')
|
||||
]); ?>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col12">
|
||||
<div class="block">
|
||||
<h4>Étiquette de remplacement</h4>
|
||||
<div class="row">
|
||||
<div class="col8">
|
||||
<?php echo template::text('usersTagLabel', [
|
||||
'placeholder' => 'Les étiquettes saisis remplaceront celles existantes. Les étiquettes sont séparées par des espaces'
|
||||
]); ?>
|
||||
</div>
|
||||
<div class="col2 offset2 verticalAlignBottom">
|
||||
<?php echo template::submit('usersTagSubmit'); ?>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row" id="Bfrtip">
|
||||
<div class="col3">
|
||||
<?php echo template::select('usersFilterGroup', $module::$usersGroups, [
|
||||
'label' => 'Groupes / Profils',
|
||||
'selected' => isset($_POST['usersFilterGroup']) ? $_POST['usersFilterGroup'] : 'all',
|
||||
]); ?>
|
||||
</div>
|
||||
<div class="col3">
|
||||
<?php echo template::select('usersFilterFirstName', $module::$alphabet, [
|
||||
'label' => 'Prénom commence par',
|
||||
'selected' => isset($_POST['usersFilterFirstName']) ? $_POST['usersFilterFirstName'] : 'all',
|
||||
]); ?>
|
||||
</div>
|
||||
<div class="col3">
|
||||
<?php echo template::select('usersFilterLastName', $module::$alphabet, [
|
||||
'label' => 'Nom commence par',
|
||||
'selected' => isset($_POST['usersFilterLastName']) ? $_POST['usersFilterLastName'] : 'all',
|
||||
]); ?>
|
||||
</div>
|
||||
<div class="col1 offset1 verticalAlignBottom">
|
||||
<?php echo template::button('usersTagSelectAll', [
|
||||
'value' => template::ico('square-check'),
|
||||
'help' => 'Tout sélectionner'
|
||||
]); ?>
|
||||
</div>
|
||||
<div class="col1 verticalAlignBottom">
|
||||
<?php echo template::button('usersTagSelectNone', [
|
||||
'value' => template::ico('square-check-empty'),
|
||||
'help' => 'Tout désélectionner'
|
||||
]); ?>
|
||||
</div>
|
||||
</div>
|
||||
<?php if ($module::$users): ?>
|
||||
<?php echo template::table([1, 2, 3, 3, 3], $module::$users, ['', 'Id', 'Prénom', 'Nom', 'Étiquettes'], ['id' => 'dataTables']); ?>
|
||||
<?php else: ?>
|
||||
<?php echo template::speech('Aucun inscrit'); ?>
|
||||
<?php endif; ?>
|
||||
<?php echo template::formClose(); ?>
|
26
core/module/user/view/usersDelete/usersDelete.css
Normal file
26
core/module/user/view/usersDelete/usersDelete.css
Normal file
@ -0,0 +1,26 @@
|
||||
/**
|
||||
* This file is part of Zwii.
|
||||
*
|
||||
* For full copyright and license information, please see the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*
|
||||
* @author Rémi Jean <remi.jean@outlook.com>
|
||||
* @copyright Copyright (C) 2008-2018, Rémi Jean
|
||||
* @author Frédéric Tempez <frederic.tempez@outlook.com>
|
||||
* @copyright Copyright (C) 2018-2024, Frédéric Tempez
|
||||
* @license CC Attribution-NonCommercial-NoDerivatives 4.0 International
|
||||
* @link http://zwiicms.fr/
|
||||
*/
|
||||
|
||||
|
||||
/** NE PAS EFFACER
|
||||
* admin.css
|
||||
*/
|
||||
|
||||
#usersDeleteSubmit {
|
||||
background-color: rgba(217, 95, 78, 1);
|
||||
}
|
||||
|
||||
tr {
|
||||
cursor: pointer;
|
||||
}
|
101
core/module/user/view/usersDelete/usersDelete.js.php
Normal file
101
core/module/user/view/usersDelete/usersDelete.js.php
Normal file
@ -0,0 +1,101 @@
|
||||
/**
|
||||
* This file is part of Zwii.
|
||||
* For full copyright and license information, please see the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*
|
||||
* @author Rémi Jean <remi.jean@outlook.com>
|
||||
* @copyright Copyright (C) 2008-2018, Rémi Jean
|
||||
* @author Frédéric Tempez <frederic.tempez@outlook.com>
|
||||
* @copyright Copyright (C) 2018-2024, Frédéric Tempez
|
||||
* @license CC Attribution-NonCommercial-NoDerivatives 4.0 International
|
||||
* @link http://zwiicms.fr/
|
||||
*/
|
||||
|
||||
$(document).ready((function () {
|
||||
|
||||
$('tr').click(function () {
|
||||
// Cochez ou décochez la case à cocher dans cette ligne
|
||||
$(this).find('input[type="checkbox"]').prop('checked', function (i, val) {
|
||||
return !val; // Inverse l'état actuel de la case à cocher
|
||||
});
|
||||
});
|
||||
|
||||
$('#usersDeleteSelectAll').on('click', function () {
|
||||
$('.checkboxSelect').prop('checked', true);
|
||||
saveCheckboxState();
|
||||
});
|
||||
$('#usersDeleteSelectNone').on('click', function () {
|
||||
$('.checkboxSelect').prop('checked', false);
|
||||
saveCheckboxState();
|
||||
});
|
||||
|
||||
$("#usersFilterGroup, #usersFilterFirstName, #usersFilterLastName").change(function () {
|
||||
saveCheckboxState();
|
||||
$("#usersDeleteForm").submit();
|
||||
});
|
||||
|
||||
var table = $('#dataTables').DataTable({
|
||||
language: {
|
||||
url: "core/vendor/datatables/french.json"
|
||||
},
|
||||
locale: 'fr',
|
||||
"lengthMenu": [[10, 25, 50, 100, 299, -1], [10, 25, 50, 100, 200, "Tout"]],
|
||||
"columnDefs": [
|
||||
{
|
||||
target: 0,
|
||||
orderable: false,
|
||||
searchable: false,
|
||||
}
|
||||
]
|
||||
});
|
||||
|
||||
// Handle checkbox change event
|
||||
$('.checkboxSelect').on('change', function () {
|
||||
// Save checkbox state to cookies or local storage
|
||||
saveCheckboxState();
|
||||
});
|
||||
|
||||
// Handle checkbox state on DataTables draw event
|
||||
table.on('draw', function () {
|
||||
// Restore checkbox state from cookies or local storage
|
||||
restoreCheckboxState();
|
||||
});
|
||||
|
||||
// Empty local storage after submit
|
||||
$("#usersDeleteSubmit").on("click", function () {
|
||||
localStorage.setItem('checkboxState', JSON.stringify({}));
|
||||
});
|
||||
|
||||
// Restore checkbox state on page load
|
||||
restoreCheckboxState();
|
||||
|
||||
function saveCheckboxState() {
|
||||
|
||||
// Récupérer d'abord les données existantes dans le localStorage
|
||||
var existingData = JSON.parse(localStorage.getItem('checkboxState')) || {};
|
||||
|
||||
// Ajouter ou mettre à jour les données actuelles
|
||||
$('.checkboxSelect').each(function () {
|
||||
var checkboxId = $(this).attr('id');
|
||||
var checked = $(this).prop('checked');
|
||||
existingData[checkboxId] = checked;
|
||||
});
|
||||
|
||||
// Sauvegarder les données mises à jour dans le localStorage
|
||||
localStorage.setItem('checkboxState', JSON.stringify(existingData));
|
||||
}
|
||||
|
||||
// Function to restore checkbox state
|
||||
function restoreCheckboxState() {
|
||||
var checkboxState = JSON.parse(localStorage.getItem('checkboxState')) || {};
|
||||
// console.log(checkboxState);
|
||||
for (var checkboxId in checkboxState) {
|
||||
if (checkboxState.hasOwnProperty(checkboxId)) {
|
||||
var checked = checkboxState[checkboxId];
|
||||
// Update checkbox state based on stored information
|
||||
$('#' + checkboxId).prop('checked', checked);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}));
|
55
core/module/user/view/usersDelete/usersDelete.php
Normal file
55
core/module/user/view/usersDelete/usersDelete.php
Normal file
@ -0,0 +1,55 @@
|
||||
<?php echo template::formOpen('usersDeleteForm'); ?>
|
||||
<div class="row">
|
||||
<div class="col1">
|
||||
<?php echo template::button('userDeleteBack', [
|
||||
'class' => 'buttonGrey',
|
||||
'href' => helper::baseUrl() . 'user/' . $this->getUrl(2),
|
||||
'value' => template::ico('left')
|
||||
]); ?>
|
||||
</div>
|
||||
<div class="col1 offset10">
|
||||
<?php echo template::submit('usersDeleteSubmit', [
|
||||
'class' => 'buttonRed',
|
||||
'ico' => '',
|
||||
'value' => template::ico('minus'),
|
||||
]); ?>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row" id="Bfrtip">
|
||||
<div class="col3">
|
||||
<?php echo template::select('usersFilterGroup', $module::$usersGroups, [
|
||||
'label' => 'Groupes / Profils',
|
||||
'selected' => isset($_POST['usersFilterGroup']) ? $_POST['usersFilterGroup'] : 'all',
|
||||
]); ?>
|
||||
</div>
|
||||
<div class="col3">
|
||||
<?php echo template::select('usersFilterFirstName', $module::$alphabet, [
|
||||
'label' => 'Prénom commence par',
|
||||
'selected' => isset($_POST['usersFilterFirstName']) ? $_POST['usersFilterFirstName'] : 'all',
|
||||
]); ?>
|
||||
</div>
|
||||
<div class="col3">
|
||||
<?php echo template::select('usersFilterLastName', $module::$alphabet, [
|
||||
'label' => 'Nom commence par',
|
||||
'selected' => isset($_POST['usersFilterLastName']) ? $_POST['usersFilterLastName'] : 'all',
|
||||
]); ?>
|
||||
</div>
|
||||
<div class="col1 offset1 verticalAlignBottom">
|
||||
<?php echo template::button('usersDeleteSelectAll', [
|
||||
'value' => template::ico('square-check'),
|
||||
'help' => 'Tout sélectionner'
|
||||
]); ?>
|
||||
</div>
|
||||
<div class="col1 verticalAlignBottom">
|
||||
<?php echo template::button('usersDeleteSelectNone', [
|
||||
'value' => template::ico('square-check-empty'),
|
||||
'help' => 'Tout désélectionner'
|
||||
]); ?>
|
||||
</div>
|
||||
</div>
|
||||
<?php if ($module::$users): ?>
|
||||
<?php echo template::table([1, 2, 3, 3, 3], $module::$users, ['', 'Id', 'Prénom', 'Nom', 'Étiquettes'], ['id' => 'dataTables']); ?>
|
||||
<?php else: ?>
|
||||
<?php echo template::speech('Aucun inscrit'); ?>
|
||||
<?php endif; ?>
|
||||
<?php echo template::formClose(); ?>
|
13
core/vendor/datatables/datatables.custom.css
vendored
Normal file
13
core/vendor/datatables/datatables.custom.css
vendored
Normal file
@ -0,0 +1,13 @@
|
||||
.dataTables_length {
|
||||
margin-bottom: 10px;
|
||||
width: 250px;
|
||||
}
|
||||
|
||||
.dataTables_length label {
|
||||
float: left;
|
||||
}
|
||||
|
||||
.dataTables_length select {
|
||||
margin-left: 5px;
|
||||
width: 80px;
|
||||
}
|
71
core/vendor/datatables/datetime.min.js
vendored
Normal file
71
core/vendor/datatables/datetime.min.js
vendored
Normal file
@ -0,0 +1,71 @@
|
||||
/**
|
||||
* This plug-in for DataTables represents the ultimate option in extensibility
|
||||
* for sorting date / time strings correctly. It uses
|
||||
* [Moment.js](http://momentjs.com) to create automatic type detection and
|
||||
* sorting plug-ins for DataTables based on a given format. This way, DataTables
|
||||
* will automatically detect your temporal information and sort it correctly.
|
||||
*
|
||||
* For usage instructions, please see the DataTables blog
|
||||
* post that [introduces it](//datatables.net/blog/2014-12-18).
|
||||
*
|
||||
* @name Ultimate Date / Time sorting
|
||||
* @summary Sort date and time in any format using Moment.js
|
||||
* @author [Allan Jardine](//datatables.net)
|
||||
* @depends DataTables 1.10+, Moment.js 1.7+
|
||||
* @deprecated
|
||||
*
|
||||
* @example
|
||||
* $.fn.dataTable.moment( 'HH:mm MMM D, YY' );
|
||||
* $.fn.dataTable.moment( 'dddd, MMMM Do, YYYY' );
|
||||
*
|
||||
* $('#example').DataTable();
|
||||
*/
|
||||
|
||||
(function (factory) {
|
||||
if (typeof define === "function" && define.amd) {
|
||||
define(["jquery", "moment", "datatables.net"], factory);
|
||||
} else {
|
||||
factory(jQuery, moment);
|
||||
}
|
||||
}(function ($, moment) {
|
||||
|
||||
function strip (d) {
|
||||
if ( typeof d === 'string' ) {
|
||||
// Strip HTML tags and newline characters if possible
|
||||
d = d.replace(/(<.*?>)|(\r?\n|\r)/g, '');
|
||||
|
||||
// Strip out surrounding white space
|
||||
d = d.trim();
|
||||
}
|
||||
|
||||
return d;
|
||||
}
|
||||
|
||||
$.fn.dataTable.moment = function ( format, locale, reverseEmpties ) {
|
||||
var types = $.fn.dataTable.ext.type;
|
||||
|
||||
// Add type detection
|
||||
types.detect.unshift( function ( d ) {
|
||||
d = strip(d);
|
||||
|
||||
// Null and empty values are acceptable
|
||||
if ( d === '' || d === null ) {
|
||||
return 'moment-'+format;
|
||||
}
|
||||
|
||||
return moment( d, format, locale, true ).isValid() ?
|
||||
'moment-'+format :
|
||||
null;
|
||||
} );
|
||||
|
||||
// Add sorting method - use an integer for the sorting
|
||||
types.order[ 'moment-'+format+'-pre' ] = function ( d ) {
|
||||
d = strip(d);
|
||||
|
||||
return !moment(d, format, locale, true).isValid() ?
|
||||
(reverseEmpties ? -Infinity : Infinity) :
|
||||
parseInt( moment( d, format, locale, true ).format( 'x' ), 10 );
|
||||
};
|
||||
};
|
||||
|
||||
}));
|
2
core/vendor/datatables/french.json
vendored
2
core/vendor/datatables/french.json
vendored
@ -1,7 +1,7 @@
|
||||
{
|
||||
"processing": "Traitement en cours...",
|
||||
"search": "Rechercher :",
|
||||
"lengthMenu": "Éléments par page _MENU_",
|
||||
"lengthMenu": "Éléments par page : _MENU_",
|
||||
"info": "Affichage de l'élement _START_ à _END_ sur _TOTAL_ éléments",
|
||||
"infoEmpty": "Affichage de l'élement 0 à 0 sur 0 éléments",
|
||||
"infoFiltered": "(filtré de _MAX_ éléments au total)",
|
||||
|
5
core/vendor/datatables/inc.json
vendored
5
core/vendor/datatables/inc.json
vendored
@ -1,4 +1,7 @@
|
||||
[
|
||||
"datatables.min.js",
|
||||
"datatables.min.css"
|
||||
"moment.min.js",
|
||||
"datetime.min.js",
|
||||
"datatables.min.css",
|
||||
"datatables.custom.css"
|
||||
]
|
7
core/vendor/datatables/moment.min.js
vendored
Normal file
7
core/vendor/datatables/moment.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
5
core/vendor/filemanager/UploadHandler.php
vendored
5
core/vendor/filemanager/UploadHandler.php
vendored
@ -1506,8 +1506,9 @@ class UploadHandler
|
||||
}
|
||||
|
||||
|
||||
|
||||
$thumbResult = create_img($targetFile, $targetFileThumb, 122, 91);
|
||||
$newWidth = 640;
|
||||
$newHeight = 480;
|
||||
$thumbResult = create_img($targetFile, $targetFileThumb, $newWidth, $newHeight);
|
||||
|
||||
if ( $thumbResult!==true)
|
||||
{
|
||||
|
349
core/vendor/filemanager/config/config.php
vendored
349
core/vendor/filemanager/config/config.php
vendored
@ -14,12 +14,12 @@ ob_start('mb_output_handler');
|
||||
date_default_timezone_set('Europe/Paris');
|
||||
|
||||
// Lire la langue installée
|
||||
$lang = isset($_GET['lang']) ? $_GET['lang'] : 'en';
|
||||
$lang = isset($_GET['lang']) ? $_GET['lang'] : 'fr_FR';
|
||||
setlocale(LC_CTYPE, $lang);
|
||||
|
||||
/* Lecture du groupe de l'utilisateur connecté pour attribuer les droits et les dossiers */
|
||||
$userId = $_COOKIE['ZWII_USER_ID'];
|
||||
$courseId = $_COOKIE['ZWII_SITE_CONTENT'];
|
||||
$courseId = $_GET['fldr'];
|
||||
$u = json_decode(file_get_contents('../../../site/data/user.json'), true);
|
||||
$g = json_decode(file_get_contents('../../../site/data/profil.json'), true);
|
||||
|
||||
@ -52,37 +52,42 @@ if (!is_null($u) && !is_null($g) && !is_null($userId)) {
|
||||
case 1:
|
||||
// Accès contrôlés par le profil
|
||||
$profil = $u['user'][$userId]['profil'];
|
||||
if ($g['profil'][$group][$profil]['filemanager'] === false)
|
||||
exit('Accès interdit');
|
||||
// lecture du profil
|
||||
if (!is_null($profil)) {
|
||||
$file = $g['profil'][$group][$profil]['file'];
|
||||
$folder = $g['profil'][$group][$profil]['folder'];
|
||||
$uploadDir = './site/file/source/';
|
||||
// Pointe vers le dossier du cours
|
||||
if (
|
||||
isset($courseId)
|
||||
&& $courseId != 'home'
|
||||
&& $g['profil'][$group][$profil]['folder']['path'] === ''
|
||||
) {
|
||||
$uploadDir = './site/file/source/' . $courseId . '/';
|
||||
} else {
|
||||
$uploadDir = $g['profil'][$group][$profil]['folder']['path'];
|
||||
}
|
||||
|
||||
$currentPath = '../../../' . $uploadDir;
|
||||
if (!is_dir($currentPath)) {
|
||||
mkdir($currentPath);
|
||||
}
|
||||
break;
|
||||
$file = $g['profil'][$group][$profil]['file'];
|
||||
$folder = $g['profil'][$group][$profil]['folder'];
|
||||
// membre sans profil déclaré ou accès interdit, pas d'accès
|
||||
if (
|
||||
is_null($profil)
|
||||
|| $g['profil'][$group][$profil]['filemanager'] === false
|
||||
) {
|
||||
exit("<h1 style='color: red'>Accès interdit au gestionnaire de fichiers !</h1>");
|
||||
}
|
||||
|
||||
// Détermine la variable du dossier partagé dans le profil
|
||||
$sharedPathKey = ($courseId === 'home') ? 'homePath' : 'coursePath';
|
||||
$sharedPath = isset($folder[$sharedPathKey]) ? $folder[$sharedPathKey] : 'none';
|
||||
// Interdit un accès non partagé
|
||||
if (
|
||||
$folder[$sharedPathKey] === 'none'
|
||||
) {
|
||||
exit("<h1 style='color: red'>Accès interdit au gestionnaire de fichiers !</h1>");
|
||||
}
|
||||
|
||||
// Un dossier renvoie vers le dossier confiné
|
||||
$uploadDir = $sharedPath === '' ? '/site/file/source/' . $courseId . '/' : $sharedPath;
|
||||
$currentPath = '../../../' . $uploadDir;
|
||||
|
||||
// Affiche un message d'erreur du le dossier partagé a été supprimé.
|
||||
if (is_dir($currentPath) == false) {
|
||||
exit("<h1 style='color: red'>Le dossier partagé est inexistant, contactez l'administrateur.</h1>");
|
||||
}
|
||||
|
||||
break;
|
||||
default:
|
||||
// Pas d'autorisation d'accès au gestionnaire de fichiers
|
||||
exit('Accès interdit');
|
||||
exit("<h1 style='color: red'>Accès interdit au gestionnaire de fichiers !</h1>");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* Fin lecture du groupe de l'utilisateur connecté pour attribuer les droits et les dossiers */
|
||||
|
||||
/*
|
||||
@ -133,77 +138,77 @@ define('DEBUG_ERROR_MESSAGE', false); // TRUE or FALSE
|
||||
$config = array(
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| DON'T TOUCH (base url (only domain) of site).
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| without final / (DON'T TOUCH)
|
||||
|
|
||||
*/
|
||||
|--------------------------------------------------------------------------
|
||||
| DON'T TOUCH (base url (only domain) of site).
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| without final / (DON'T TOUCH)
|
||||
|
|
||||
*/
|
||||
'base_url' => ((isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] && !in_array(strtolower($_SERVER['HTTPS']), array('off', 'no'))) ? 'https' : 'http') . '://' . $_SERVER['HTTP_HOST'] . rtrim(str_replace('/core/vendor/filemanager', '', pathinfo($_SERVER['PHP_SELF'])['dirname']), ' /'),
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| path from base_url to base of upload folder
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| with start and final /
|
||||
|
|
||||
*/
|
||||
|--------------------------------------------------------------------------
|
||||
| path from base_url to base of upload folder
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| with start and final /
|
||||
|
|
||||
*/
|
||||
'upload_dir' => $uploadDir,
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| relative path from filemanager folder to upload folder
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| with final /
|
||||
|
|
||||
*/
|
||||
|--------------------------------------------------------------------------
|
||||
| relative path from filemanager folder to upload folder
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| with final /
|
||||
|
|
||||
*/
|
||||
'current_path' => $currentPath,
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| relative path from filemanager folder to thumbs folder
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| with final /
|
||||
| DO NOT put inside upload folder
|
||||
|
|
||||
*/
|
||||
|--------------------------------------------------------------------------
|
||||
| relative path from filemanager folder to thumbs folder
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| with final /
|
||||
| DO NOT put inside upload folder
|
||||
|
|
||||
*/
|
||||
'thumbs_base_path' => '../../../site/file/thumb/',
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| path from base_url to base of thumbs folder
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| with final /
|
||||
| DO NOT put inside upload folder
|
||||
|
|
||||
*/
|
||||
|--------------------------------------------------------------------------
|
||||
| path from base_url to base of thumbs folder
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| with final /
|
||||
| DO NOT put inside upload folder
|
||||
|
|
||||
*/
|
||||
'thumbs_upload_dir' => '/thumb/',
|
||||
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| mime file control to define files extensions
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| If you want to be forced to assign the extension starting from the mime type
|
||||
|
|
||||
*/
|
||||
|--------------------------------------------------------------------------
|
||||
| mime file control to define files extensions
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| If you want to be forced to assign the extension starting from the mime type
|
||||
|
|
||||
*/
|
||||
'mime_extension_rename' => false,
|
||||
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| FTP configuration BETA VERSION
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| If you want enable ftp use write these parametres otherwise leave empty
|
||||
| Remember to set base_url properly to point in the ftp server domain and
|
||||
| upload dir will be ftp_base_folder + upload_dir so without final /
|
||||
|
|
||||
*/
|
||||
|--------------------------------------------------------------------------
|
||||
| FTP configuration BETA VERSION
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| If you want enable ftp use write these parametres otherwise leave empty
|
||||
| Remember to set base_url properly to point in the ftp server domain and
|
||||
| upload dir will be ftp_base_folder + upload_dir so without final /
|
||||
|
|
||||
*/
|
||||
'ftp_host' => false,
|
||||
//put the FTP host
|
||||
'ftp_user' => "user",
|
||||
@ -213,52 +218,52 @@ $config = array(
|
||||
// Directory where place files before to send to FTP with final /
|
||||
'ftp_temp_folder' => "../temp/",
|
||||
/*
|
||||
|---------------------------------------------------------------------------
|
||||
| path from ftp_base_folder to base of thumbs folder with start and final /
|
||||
|---------------------------------------------------------------------------
|
||||
*/
|
||||
|---------------------------------------------------------------------------
|
||||
| path from ftp_base_folder to base of thumbs folder with start and final /
|
||||
|---------------------------------------------------------------------------
|
||||
*/
|
||||
'ftp_thumbs_dir' => '/thumbs/',
|
||||
'ftp_ssl' => false,
|
||||
'ftp_port' => 21,
|
||||
|
||||
/* EXAMPLE
|
||||
'ftp_host' => "host.com",
|
||||
'ftp_user' => "test@host.com",
|
||||
'ftp_pass' => "pass.1",
|
||||
'ftp_base_folder' => "",
|
||||
'ftp_base_url' => "http://host.com/testFTP",
|
||||
*/
|
||||
'ftp_host' => "host.com",
|
||||
'ftp_user' => "test@host.com",
|
||||
'ftp_pass' => "pass.1",
|
||||
'ftp_base_folder' => "",
|
||||
'ftp_base_url' => "http://host.com/testFTP",
|
||||
*/
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Multiple files selection
|
||||
|--------------------------------------------------------------------------
|
||||
| The user can delete multiple files, select all files , deselect all files
|
||||
*/
|
||||
|--------------------------------------------------------------------------
|
||||
| Multiple files selection
|
||||
|--------------------------------------------------------------------------
|
||||
| The user can delete multiple files, select all files , deselect all files
|
||||
*/
|
||||
'multiple_selection' => true,
|
||||
/*
|
||||
|
|
||||
| The user can have a select button that pass a json to external input or pass the first file selected to editor
|
||||
| If you use responsivefilemanager tinymce extension can copy into editor multiple object like images, videos, audios, links in the same time
|
||||
|
|
||||
*/
|
||||
|
|
||||
| The user can have a select button that pass a json to external input or pass the first file selected to editor
|
||||
| If you use responsivefilemanager tinymce extension can copy into editor multiple object like images, videos, audios, links in the same time
|
||||
|
|
||||
*/
|
||||
'multiple_selection_action_button' => true,
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Access keys
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| add access keys eg: array('myPrivateKey', 'someoneElseKey');
|
||||
| keys should only containt (a-z A-Z 0-9 \ . _ -) characters
|
||||
| if you are integrating lets say to a cms for admins, i recommend making keys randomized something like this:
|
||||
| $username = 'Admin';
|
||||
| $salt = 'dsflFWR9u2xQa' (a hard coded string)
|
||||
| $akey = md5($username.$salt);
|
||||
| DO NOT use 'key' as access key!
|
||||
| Keys are CASE SENSITIVE!
|
||||
|
|
||||
*/
|
||||
|--------------------------------------------------------------------------
|
||||
| Access keys
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| add access keys eg: array('myPrivateKey', 'someoneElseKey');
|
||||
| keys should only containt (a-z A-Z 0-9 \ . _ -) characters
|
||||
| if you are integrating lets say to a cms for admins, i recommend making keys randomized something like this:
|
||||
| $username = 'Admin';
|
||||
| $salt = 'dsflFWR9u2xQa' (a hard coded string)
|
||||
| $akey = md5($username.$salt);
|
||||
| DO NOT use 'key' as access key!
|
||||
| Keys are CASE SENSITIVE!
|
||||
|
|
||||
*/
|
||||
|
||||
'access_keys' => array($privateKey),
|
||||
|
||||
@ -267,51 +272,51 @@ $config = array(
|
||||
//--------------------------------------------------------------------------------------------------------
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Maximum size of all files in source folder
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| in Megabytes
|
||||
|
|
||||
*/
|
||||
|--------------------------------------------------------------------------
|
||||
| Maximum size of all files in source folder
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| in Megabytes
|
||||
|
|
||||
*/
|
||||
'MaxSizeTotal' => false,
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Maximum upload size
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| in Megabytes
|
||||
|
|
||||
*/
|
||||
|--------------------------------------------------------------------------
|
||||
| Maximum upload size
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| in Megabytes
|
||||
|
|
||||
*/
|
||||
'MaxSizeUpload' => 20000,
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| File and Folder permission
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
*/
|
||||
'filePermission' => 0755,
|
||||
|--------------------------------------------------------------------------
|
||||
| File and Folder permission
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
*/
|
||||
'filePermission' => 0644,
|
||||
'folderPermission' => 0777,
|
||||
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| default language file name
|
||||
|--------------------------------------------------------------------------
|
||||
*/
|
||||
|--------------------------------------------------------------------------
|
||||
| default language file name
|
||||
|--------------------------------------------------------------------------
|
||||
*/
|
||||
'default_language' => 'fr_FR',
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Icon theme
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| Default available: ico and ico_dark
|
||||
| Can be set to custom icon inside filemanager/img
|
||||
|
|
||||
*/
|
||||
|--------------------------------------------------------------------------
|
||||
| Icon theme
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| Default available: ico and ico_dark
|
||||
| Can be set to custom icon inside filemanager/img
|
||||
|
|
||||
*/
|
||||
'icon_theme' => "ico",
|
||||
|
||||
|
||||
@ -349,12 +354,12 @@ $config = array(
|
||||
'image_max_height' => 0,
|
||||
'image_max_mode' => 'auto',
|
||||
/*
|
||||
# $option: 0 / exact = defined size;
|
||||
# 1 / portrait = keep aspect set height;
|
||||
# 2 / landscape = keep aspect set width;
|
||||
# 3 / auto = auto;
|
||||
# 4 / crop= resize and crop;
|
||||
*/
|
||||
# $option: 0 / exact = defined size;
|
||||
# 1 / portrait = keep aspect set height;
|
||||
# 2 / landscape = keep aspect set width;
|
||||
# 3 / auto = auto;
|
||||
# 4 / crop= resize and crop;
|
||||
*/
|
||||
|
||||
//Automatic resizing //
|
||||
// If you set $image_resizing to TRUE the script converts all uploaded images exactly to image_resizing_width x image_resizing_height dimension
|
||||
@ -489,13 +494,13 @@ $config = array(
|
||||
'empty_filename' => false,
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| accept files without extension
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| If you want to accept files without extension, remember to add '' extension on allowed extension
|
||||
|
|
||||
*/
|
||||
|--------------------------------------------------------------------------
|
||||
| accept files without extension
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| If you want to accept files without extension, remember to add '' extension on allowed extension
|
||||
|
|
||||
*/
|
||||
'files_without_extension' => false,
|
||||
|
||||
/******************
|
||||
@ -603,7 +608,7 @@ $config = array(
|
||||
// path_from_filemanager/test/test1/
|
||||
// PS if there isn't write permission in your destination folder you must set it
|
||||
//
|
||||
'fixed_image_creation' => true,
|
||||
'fixed_image_creation' => false,
|
||||
//activate or not the creation of one or more image resized with fixed path from filemanager folder
|
||||
'fixed_path_from_filemanager' => array('../../../site/file/thumb/'),
|
||||
//fixed path of the image folder from the current position on upload folder
|
||||
@ -616,12 +621,12 @@ $config = array(
|
||||
'fixed_image_creation_height' => array(480),
|
||||
//height of image
|
||||
/*
|
||||
# $option: 0 / exact = defined size;
|
||||
# 1 / portrait = keep aspect set height;
|
||||
# 2 / landscape = keep aspect set width;
|
||||
# 3 / auto = auto;
|
||||
# 4 / crop= resize and crop;
|
||||
*/
|
||||
# $option: 0 / exact = defined size;
|
||||
# 1 / portrait = keep aspect set height;
|
||||
# 2 / landscape = keep aspect set width;
|
||||
# 3 / auto = auto;
|
||||
# 4 / crop= resize and crop;
|
||||
*/
|
||||
'fixed_image_creation_option' => array('auto', 'crop'),
|
||||
//set the type of the crop
|
||||
|
||||
@ -644,12 +649,12 @@ $config = array(
|
||||
'relative_image_creation_height' => array(200, 300),
|
||||
//height of image
|
||||
/*
|
||||
# $option: 0 / exact = defined size;
|
||||
# 1 / portrait = keep aspect set height;
|
||||
# 2 / landscape = keep aspect set width;
|
||||
# 3 / auto = auto;
|
||||
# 4 / crop= resize and crop;
|
||||
*/
|
||||
# $option: 0 / exact = defined size;
|
||||
# 1 / portrait = keep aspect set height;
|
||||
# 2 / landscape = keep aspect set width;
|
||||
# 3 / auto = auto;
|
||||
# 4 / crop= resize and crop;
|
||||
*/
|
||||
'relative_image_creation_option' => array('crop', 'crop'),
|
||||
//set the type of the crop
|
||||
|
||||
|
38
core/vendor/filemanager/dialog.php
vendored
38
core/vendor/filemanager/dialog.php
vendored
@ -864,50 +864,54 @@ if ($config['upload_files']) { ?>
|
||||
|
||||
switch ($sort_by) {
|
||||
case 'date':
|
||||
//usort($sorted, 'dateSort');
|
||||
usort($sorted, function($x, $y) use ($descending) {
|
||||
if ($x['is_dir'] !== $y['is_dir']) {
|
||||
return $y['is_dir'] ? 1 : -1;
|
||||
} else {
|
||||
return ($descending)
|
||||
? $x['size'] < $y['size']
|
||||
: $x['size'] >= $y['size'];
|
||||
if ($descending) {
|
||||
return ($x['size'] < $y['size']) ? -1 : ($x['size'] > $y['size'] ? 1 : 0);
|
||||
} else {
|
||||
return ($x['size'] > $y['size']) ? -1 : ($x['size'] < $y['size'] ? 1 : 0);
|
||||
}
|
||||
}
|
||||
});
|
||||
break;
|
||||
case 'size':
|
||||
//usort($sorted, 'sizeSort');
|
||||
usort($sorted, function($x, $y) use ($descending) {
|
||||
if ($x['is_dir'] !== $y['is_dir']) {
|
||||
return $y['is_dir'] ? 1 : -1;
|
||||
} else {
|
||||
return ($descending)
|
||||
? $x['date'] < $y['date']
|
||||
: $x['date'] >= $y['date'];
|
||||
if ($descending) {
|
||||
return ($x['date'] < $y['date']) ? -1 : ($x['date'] > $y['date'] ? 1 : 0);
|
||||
} else {
|
||||
return ($x['date'] > $y['date']) ? -1 : ($x['date'] < $y['date'] ? 1 : 0);
|
||||
}
|
||||
}
|
||||
});
|
||||
break;
|
||||
case 'extension':
|
||||
//usort($sorted, 'extensionSort');
|
||||
usort($sorted, function($x, $y) use ($descending) {
|
||||
if ($x['is_dir'] !== $y['is_dir']) {
|
||||
return $y['is_dir'] ? 1 : -1;
|
||||
} else {
|
||||
return ($descending)
|
||||
? ($x['extension'] < $y['extension'] ? 1 : 0)
|
||||
: ($x['extension'] >= $y['extension'] ? 1 : 0);
|
||||
if ($descending) {
|
||||
return strcasecmp($x['extension'], $y['extension']);
|
||||
} else {
|
||||
return -strcasecmp($x['extension'], $y['extension']);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
break;
|
||||
default:
|
||||
// usort($sorted, 'filenameSort');
|
||||
usort($sorted, function($x, $y) use ($descending) {
|
||||
if ($x['is_dir'] !== $y['is_dir']) {
|
||||
return $y['is_dir'] ? 1 : -1;
|
||||
} else {
|
||||
return ($descending)
|
||||
? ($x['file_lcase'] < $y['file_lcase'] ? 1 : ($x['file_lcase'] == $y['file_lcase'] ? 0 : -1))
|
||||
: ($x['file_lcase'] >= $y['file_lcase'] ? 1 : ($x['file_lcase'] == $y['file_lcase'] ? 0 : -1));
|
||||
if ($descending) {
|
||||
return strcasecmp($x['file_lcase'], $y['file_lcase']);
|
||||
} else {
|
||||
return -strcasecmp($x['file_lcase'], $y['file_lcase']);
|
||||
}
|
||||
}
|
||||
});
|
||||
break;
|
||||
|
8
core/vendor/imagemap/image-map.min.js
vendored
8
core/vendor/imagemap/image-map.min.js
vendored
@ -1,8 +0,0 @@
|
||||
/**
|
||||
* Copyright (c) 2018, Travis Clarke (https://www.travismclarke.com/)
|
||||
*
|
||||
* This source code is licensed under the Apache-2.0 license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
!function(e,t){"object"==typeof exports&&"undefined"!=typeof module?module.exports=t(require("jquery")):"function"==typeof define&&define.amd?define(["jquery"],t):e.ImageMap=t(e.$)}(this,function(e){"use strict";function t(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}function n(e,t){for(var n=0;n<t.length;n++){var r=t[n];r.enumerable=r.enumerable||!1,r.configurable=!0,"value"in r&&(r.writable=!0),Object.defineProperty(e,r.key,r)}}function r(e,t,r){return t&&n(e.prototype,t),r&&n(e,r),e}function o(e){return i(e)||a(e)||u()}function i(e){if(Array.isArray(e)){for(var t=0,n=Array(e.length);t<e.length;t++)n[t]=e[t];return n}}function a(e){if(Symbol.iterator in Object(e)||"[object Arguments]"===Object.prototype.toString.call(e))return Array.from(e)}function u(){throw new TypeError("Invalid attempt to spread non-iterable instance")}function c(e,t){return new s(e,t)}e=e&&e.hasOwnProperty("default")?e.default:e;var d="resize",f="load",l="complete",s=function(){function e(n,r){t(this,e),this.selector=n instanceof Array?n:o(document.querySelectorAll(n)),document.readyState!==l?window.addEventListener(f,this.update.bind(this)):this.update(),window.addEventListener(d,this.debounce(this.update,r).bind(this))}return r(e,[{key:"update",value:function(){var e=this;this.selector.forEach(function(t){if(void 0!==t.getAttribute("usemap")){t.cloneNode().addEventListener(f,e.handleImageLoad(t.offsetWidth,t.offsetHeight))}})}},{key:"debounce",value:function(e){var t,n=this,r=arguments.length>1&&void 0!==arguments[1]?arguments[1]:500;return function(){for(var o=arguments.length,i=Array(o),a=0;a<o;a++)i[a]=arguments[a];window.clearTimeout(t),t=window.setTimeout(function(t){return e.apply(t,i)},r,n)}}},{key:"handleImageLoad",value:function(){var t=arguments.length>0&&void 0!==arguments[0]?arguments[0]:0,n=arguments.length>1&&void 0!==arguments[1]?arguments[1]:0;return function(r){var i=r.target.width,a=r.target.height,u=t/100,c=n/100,d=r.target.getAttribute("usemap").replace(/^#/,"")
|
||||
;o(document.querySelectorAll(e.genAreaSelector(d))).forEach(function(e){var t=e.dataset.coords=e.dataset.coords||e.getAttribute("coords"),n=t.split(",");e.setAttribute("coords",""+n.map(function(e,t){return t%2==0?+(n[t]/i*100*u):+(n[t]/a*100*c)}))})}}}],[{key:"genAreaSelector",value:function(e){return'map[name="'.concat(e,'"] area')}}]),e}();return void 0!==e&&e.fn&&(e.fn.imageMap=function(e){return new s(this.toArray(),e)}),c.VERSION="1.1.5",c});
|
4
core/vendor/imagemap/inc.json
vendored
4
core/vendor/imagemap/inc.json
vendored
@ -1,4 +0,0 @@
|
||||
[
|
||||
"image-map.min.js",
|
||||
"init.js"
|
||||
]
|
6
core/vendor/imagemap/init.js
vendored
6
core/vendor/imagemap/init.js
vendored
@ -1,6 +0,0 @@
|
||||
/**
|
||||
* Initialisation du redimensionner de mapf
|
||||
*/
|
||||
$(function() {
|
||||
$('img[usemap]').imageMap();
|
||||
});
|
2
core/vendor/imagemap/read.me
vendored
2
core/vendor/imagemap/read.me
vendored
@ -1,2 +0,0 @@
|
||||
Article https://blog.travismclarke.com/project/imagemap/
|
||||
Générateur : https://www.image-map.net/
|
271
core/vendor/plotly/README.md
vendored
Normal file
271
core/vendor/plotly/README.md
vendored
Normal file
@ -0,0 +1,271 @@
|
||||
# Using distributed files
|
||||
|
||||
All plotly.js bundles inject an object `Plotly` into the global scope.
|
||||
|
||||
Import plotly.js as:
|
||||
|
||||
```html
|
||||
<script src="plotly.min.js"></script>
|
||||
```
|
||||
|
||||
or the un-minified version as:
|
||||
|
||||
```html
|
||||
<script src="plotly.js" charset="utf-8"></script>
|
||||
```
|
||||
|
||||
### To include localization
|
||||
|
||||
Plotly.js defaults to US English (en-US) and includes British English (en) in the standard bundle.
|
||||
Many other localizations are available - here is an example using Swiss-German (de-CH),
|
||||
see the contents of this directory for the full list.
|
||||
Note that the file names are all lowercase, even though the region is uppercase when you apply a locale.
|
||||
|
||||
*After* the plotly.js script tag, add:
|
||||
|
||||
```html
|
||||
<script src="plotly-locale-de-ch.js"></script>
|
||||
<script>Plotly.setPlotConfig({locale: 'de-CH'})</script>
|
||||
```
|
||||
|
||||
The first line loads and registers the locale definition with plotly.js, the second sets it as the default for all Plotly plots.
|
||||
You can also include multiple locale definitions and apply them to each plot separately as a `config` parameter:
|
||||
|
||||
```js
|
||||
Plotly.newPlot(graphDiv, data, layout, {locale: 'de-CH'})
|
||||
```
|
||||
|
||||
# Bundle information
|
||||
|
||||
The main plotly.js bundle includes all trace modules.
|
||||
|
||||
The main plotly.js bundles weight in at:
|
||||
|
||||
| plotly.js | plotly.min.js | plotly.min.js + gzip | plotly-with-meta.js |
|
||||
|-----------|---------------|----------------------|---------------------|
|
||||
| 8.2 MB | 3.5 MB | 1 MB | 8.5 MB |
|
||||
|
||||
#### CDN links
|
||||
> https://cdn.plot.ly/plotly-2.29.0.js
|
||||
|
||||
> https://cdn.plot.ly/plotly-2.29.0.min.js
|
||||
|
||||
|
||||
#### npm packages
|
||||
> [plotly.js](https://www.npmjs.com/package/plotly.js)
|
||||
|
||||
> [plotly.js-dist](https://www.npmjs.com/package/plotly.js-dist)
|
||||
|
||||
> [plotly.js-dist-min](https://www.npmjs.com/package/plotly.js-dist-min)
|
||||
|
||||
#### Meta information
|
||||
> If you would like to have access to the attribute meta information (including attribute descriptions as on the [schema reference page](https://plotly.com/javascript/reference/)), use dist file `dist/plotly-with-meta.js`
|
||||
---
|
||||
|
||||
## Partial bundles
|
||||
|
||||
plotly.js also ships with several _partial_ bundles:
|
||||
|
||||
- [basic](#plotlyjs-basic)
|
||||
- [cartesian](#plotlyjs-cartesian)
|
||||
- [geo](#plotlyjs-geo)
|
||||
- [gl3d](#plotlyjs-gl3d)
|
||||
- [gl2d](#plotlyjs-gl2d)
|
||||
- [mapbox](#plotlyjs-mapbox)
|
||||
- [finance](#plotlyjs-finance)
|
||||
- [strict](#plotlyjs-strict)
|
||||
|
||||
> Each plotly.js partial bundle has a corresponding npm package with no dependencies.
|
||||
|
||||
> The minified version of each partial bundle is also published to npm in a separate "dist-min" package.
|
||||
|
||||
> The strict bundle now includes all traces, but the regl-based traces are built differently to avoid function constructors. This results in about a 10% larger bundle size, which is why this method is not used by default. Over time we intend to use the strict bundle to work on other strict CSP issues such as inline CSS.
|
||||
|
||||
---
|
||||
|
||||
### plotly.js basic
|
||||
|
||||
The `basic` partial bundle contains trace modules `bar`, `pie` and `scatter`.
|
||||
|
||||
#### Stats
|
||||
|
||||
| Raw size | Minified size | Minified + gzip size |
|
||||
|------|-----------------|------------------------|
|
||||
| 2.6 MB | 984.6 kB | 329.6 kB |
|
||||
|
||||
#### CDN links
|
||||
> https://cdn.plot.ly/plotly-basic-2.29.0.js
|
||||
|
||||
> https://cdn.plot.ly/plotly-basic-2.29.0.min.js
|
||||
|
||||
|
||||
#### npm packages
|
||||
> [plotly.js-basic-dist](https://www.npmjs.com/package/plotly.js-basic-dist)
|
||||
|
||||
> [plotly.js-basic-dist-min](https://www.npmjs.com/package/plotly.js-basic-dist-min)
|
||||
|
||||
---
|
||||
|
||||
### plotly.js cartesian
|
||||
|
||||
The `cartesian` partial bundle contains trace modules `bar`, `box`, `contour`, `heatmap`, `histogram`, `histogram2d`, `histogram2dcontour`, `image`, `pie`, `scatter`, `scatterternary` and `violin`.
|
||||
|
||||
#### Stats
|
||||
|
||||
| Raw size | Minified size | Minified + gzip size |
|
||||
|------|-----------------|------------------------|
|
||||
| 3.3 MB | 1.2 MB | 417 kB |
|
||||
|
||||
#### CDN links
|
||||
> https://cdn.plot.ly/plotly-cartesian-2.29.0.js
|
||||
|
||||
> https://cdn.plot.ly/plotly-cartesian-2.29.0.min.js
|
||||
|
||||
|
||||
#### npm packages
|
||||
> [plotly.js-cartesian-dist](https://www.npmjs.com/package/plotly.js-cartesian-dist)
|
||||
|
||||
> [plotly.js-cartesian-dist-min](https://www.npmjs.com/package/plotly.js-cartesian-dist-min)
|
||||
|
||||
---
|
||||
|
||||
### plotly.js geo
|
||||
|
||||
The `geo` partial bundle contains trace modules `choropleth`, `scatter` and `scattergeo`.
|
||||
|
||||
#### Stats
|
||||
|
||||
| Raw size | Minified size | Minified + gzip size |
|
||||
|------|-----------------|------------------------|
|
||||
| 3.1 MB | 1.1 MB | 372.3 kB |
|
||||
|
||||
#### CDN links
|
||||
> https://cdn.plot.ly/plotly-geo-2.29.0.js
|
||||
|
||||
> https://cdn.plot.ly/plotly-geo-2.29.0.min.js
|
||||
|
||||
|
||||
#### npm packages
|
||||
> [plotly.js-geo-dist](https://www.npmjs.com/package/plotly.js-geo-dist)
|
||||
|
||||
> [plotly.js-geo-dist-min](https://www.npmjs.com/package/plotly.js-geo-dist-min)
|
||||
|
||||
---
|
||||
|
||||
### plotly.js gl3d
|
||||
|
||||
The `gl3d` partial bundle contains trace modules `cone`, `isosurface`, `mesh3d`, `scatter`, `scatter3d`, `streamtube`, `surface` and `volume`.
|
||||
|
||||
#### Stats
|
||||
|
||||
| Raw size | Minified size | Minified + gzip size |
|
||||
|------|-----------------|------------------------|
|
||||
| 3.6 MB | 1.5 MB | 493.1 kB |
|
||||
|
||||
#### CDN links
|
||||
> https://cdn.plot.ly/plotly-gl3d-2.29.0.js
|
||||
|
||||
> https://cdn.plot.ly/plotly-gl3d-2.29.0.min.js
|
||||
|
||||
|
||||
#### npm packages
|
||||
> [plotly.js-gl3d-dist](https://www.npmjs.com/package/plotly.js-gl3d-dist)
|
||||
|
||||
> [plotly.js-gl3d-dist-min](https://www.npmjs.com/package/plotly.js-gl3d-dist-min)
|
||||
|
||||
---
|
||||
|
||||
### plotly.js gl2d
|
||||
|
||||
The `gl2d` partial bundle contains trace modules `heatmapgl`, `parcoords`, `pointcloud`, `scatter`, `scattergl` and `splom`.
|
||||
|
||||
#### Stats
|
||||
|
||||
| Raw size | Minified size | Minified + gzip size |
|
||||
|------|-----------------|------------------------|
|
||||
| 4.4 MB | 1.9 MB | 599.6 kB |
|
||||
|
||||
#### CDN links
|
||||
> https://cdn.plot.ly/plotly-gl2d-2.29.0.js
|
||||
|
||||
> https://cdn.plot.ly/plotly-gl2d-2.29.0.min.js
|
||||
|
||||
|
||||
#### npm packages
|
||||
> [plotly.js-gl2d-dist](https://www.npmjs.com/package/plotly.js-gl2d-dist)
|
||||
|
||||
> [plotly.js-gl2d-dist-min](https://www.npmjs.com/package/plotly.js-gl2d-dist-min)
|
||||
|
||||
---
|
||||
|
||||
### plotly.js mapbox
|
||||
|
||||
The `mapbox` partial bundle contains trace modules `choroplethmapbox`, `densitymapbox`, `scatter` and `scattermapbox`.
|
||||
|
||||
#### Stats
|
||||
|
||||
| Raw size | Minified size | Minified + gzip size |
|
||||
|------|-----------------|------------------------|
|
||||
| 4.4 MB | 1.7 MB | 531.2 kB |
|
||||
|
||||
#### CDN links
|
||||
> https://cdn.plot.ly/plotly-mapbox-2.29.0.js
|
||||
|
||||
> https://cdn.plot.ly/plotly-mapbox-2.29.0.min.js
|
||||
|
||||
|
||||
#### npm packages
|
||||
> [plotly.js-mapbox-dist](https://www.npmjs.com/package/plotly.js-mapbox-dist)
|
||||
|
||||
> [plotly.js-mapbox-dist-min](https://www.npmjs.com/package/plotly.js-mapbox-dist-min)
|
||||
|
||||
---
|
||||
|
||||
### plotly.js finance
|
||||
|
||||
The `finance` partial bundle contains trace modules `bar`, `candlestick`, `funnel`, `funnelarea`, `histogram`, `indicator`, `ohlc`, `pie`, `scatter` and `waterfall`.
|
||||
|
||||
#### Stats
|
||||
|
||||
| Raw size | Minified size | Minified + gzip size |
|
||||
|------|-----------------|------------------------|
|
||||
| 2.8 MB | 1 MB | 358.7 kB |
|
||||
|
||||
#### CDN links
|
||||
> https://cdn.plot.ly/plotly-finance-2.29.0.js
|
||||
|
||||
> https://cdn.plot.ly/plotly-finance-2.29.0.min.js
|
||||
|
||||
|
||||
#### npm packages
|
||||
> [plotly.js-finance-dist](https://www.npmjs.com/package/plotly.js-finance-dist)
|
||||
|
||||
> [plotly.js-finance-dist-min](https://www.npmjs.com/package/plotly.js-finance-dist-min)
|
||||
|
||||
---
|
||||
|
||||
### plotly.js strict
|
||||
|
||||
The `strict` partial bundle contains trace modules `bar`, `barpolar`, `box`, `candlestick`, `carpet`, `choropleth`, `choroplethmapbox`, `cone`, `contour`, `contourcarpet`, `densitymapbox`, `funnel`, `funnelarea`, `heatmap`, `heatmapgl`, `histogram`, `histogram2d`, `histogram2dcontour`, `icicle`, `image`, `indicator`, `isosurface`, `mesh3d`, `ohlc`, `parcats`, `parcoords`, `pie`, `pointcloud`, `sankey`, `scatter`, `scattergl`, `scatter3d`, `scattercarpet`, `scattergeo`, `scattermapbox`, `scatterpolar`, `scatterpolargl`, `scattersmith`, `scatterternary`, `splom`, `streamtube`, `sunburst`, `surface`, `table`, `treemap`, `violin`, `volume` and `waterfall`.
|
||||
|
||||
#### Stats
|
||||
|
||||
| Raw size | Minified size | Minified + gzip size |
|
||||
|------|-----------------|------------------------|
|
||||
| 8.7 MB | 3.8 MB | 1.1 MB |
|
||||
|
||||
#### CDN links
|
||||
> https://cdn.plot.ly/plotly-strict-2.29.0.js
|
||||
|
||||
> https://cdn.plot.ly/plotly-strict-2.29.0.min.js
|
||||
|
||||
|
||||
#### npm packages
|
||||
> [plotly.js-strict-dist](https://www.npmjs.com/package/plotly.js-strict-dist)
|
||||
|
||||
> [plotly.js-strict-dist-min](https://www.npmjs.com/package/plotly.js-strict-dist-min)
|
||||
|
||||
---
|
||||
|
||||
|
||||
_This file is auto-generated by `npm run stats`. Please do not edit this file directly._
|
4
core/vendor/plotly/inc.json
vendored
Normal file
4
core/vendor/plotly/inc.json
vendored
Normal file
@ -0,0 +1,4 @@
|
||||
[
|
||||
"plotly.min.js",
|
||||
"plotly-locale-fr-ch.js"
|
||||
]
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user