Compare commits

...

42 Commits

Author SHA1 Message Date
8131162dae Vérification de la réécriture 2024-06-09 02:51:55 +02:00
72655aec3d Page de configuration des modules inactives 2024-06-07 20:47:25 +02:00
08ed4075c7 Chargement lassif des images 2024-06-07 09:57:23 +02:00
6d5ddf1f8d Corrige le bug de FF 2024-06-07 09:47:20 +02:00
8b354ff40e Corrige la détection de serveur 2024-06-07 09:42:57 +02:00
5be3d0b1a7 Layout d'édition : supprime tous les boutons de gestion de page comme pour les pages avec module 2024-06-07 09:32:52 +02:00
f0c4ea6bd0 Lorsque des éléments inutiles sont ajoutés à l'adresse d'une page, une erreur 403 est levée. 2024-06-04 22:21:10 +02:00
cbe06426bb ** Corrections :**
- Dans la configuration, l'option Apache URL intelligentes ne s'active que si le serveur est Apache et que le module Rewriter est actif. Ce qui exclue les autres serveurs non compatibles comme Nginx, Caddy etc.
2024-06-02 15:07:55 +02:00
adac7395cc Lignes vides en trop dans htaccess 2024-06-02 14:40:38 +02:00
2c459a03d4 nouvel htaccess 2024-06-02 14:33:59 +02:00
751bc450b5 1.10.04
** Corrections :**
- L'ajout d'un slash en fin d'adresse avec la réécriture active provoquait une mauvaise détermination des adresses des images dans TinyMCE. Résolution : une directive htaccess supprime tous les slash en fin d'adresse.
- Lorsque la page est ouverte en édition, un clic sur le bouton édition dans la barre d'administration affiche une erreur, le lien étant incorrect. Afin d'éviter cette erreur et une redondance, le bouton d'édition est masqué lorsque la page est éditée.
2024-06-01 21:20:41 +02:00
6c8d9097f6 Readme version 2024-05-20 14:15:03 +02:00
b0814d50dc 1.10.03 Workshop Tri des espaces par titre 2024-05-18 18:47:06 +02:00
a7a2424d93 1.10.02 2024-05-16 09:26:23 +02:00
43b15987d6 Suivi Zwii 13.3.02 2024-05-16 09:25:40 +02:00
e100a580ad Mise à jour des modules 1.10.01 2024-05-08 18:47:43 +02:00
397bdee655 Merge branch '1902-isole-les-commandes-sur-les-espaces' 2024-04-23 18:13:06 +02:00
78b2d87ec1 supprime sync.db ! 2024-04-23 18:09:55 +02:00
8dedb39a33 Déplace les boutons de gestion des utilisateurs dans la liste des espaces. 2024-04-23 18:09:28 +02:00
7cee16389f commentaire 2024-04-23 17:25:50 +02:00
04b2877c48 1.10.00 2024-04-23 14:58:01 +02:00
f6c7e5f954 Dans router self devient common
Nouveau routage en cas de changement d'espace en évitant une 404
2024-04-23 14:57:10 +02:00
b5ea22021b redirige vers la page ouverte 2024-04-23 11:54:50 +02:00
3ee1398e2f supprime un commentaire 2024-04-23 11:54:32 +02:00
cfb07b81d5 Id non fourni 2024-04-22 21:46:41 +02:00
0da23149db 2.0.0 corrige le warning blog vide + transmet tn paramètre sécurisant l'édition des espaces dans plusieurs onglets 2024-04-22 15:40:35 +02:00
1322cb4eb0 Revert "section par main"
This reverts commit 271ee347a8.
2024-04-22 14:19:47 +02:00
167ad06dde Revert "section par main"
This reverts commit 271ee347a8.
2024-04-22 14:16:12 +02:00
271ee347a8 section par main 2024-04-22 10:56:49 +02:00
04a6d86999 1.9.01 supprime la balise section 2024-04-21 15:54:15 +02:00
05e6ff8f9b init 2024-04-18 14:52:13 +02:00
6e53ca8766 readme 2024-04-18 10:37:56 +02:00
dda93cf3d3 Merge branch 'master' of https://forge.chapril.org/fredtempez/ZwiiLMS 2024-04-18 10:37:19 +02:00
075e4afa1c changes 2024-04-18 10:37:11 +02:00
fd144d55f0 changes 2024-04-18 10:32:27 +02:00
b595120227 1.9 Désincription en masse de la plateforme 2024-04-18 10:27:33 +02:00
b0b3b34bde 1.8.01 alignement de boutons 2024-04-17 16:42:03 +02:00
2f592e2818 1.8.01
Corrige :
- Mauvais initialisation d'un profil
Modifie :
- Ajoute des effets de sélection dans la gestion des profils des espaces (add and edit)
2024-04-17 10:53:02 +02:00
8c9bc40a02 1.8.01
Corrige :
 - tableau de stats vides affichant une erreur
 - correction relative au rapport d'un participant
Nouvelle fonctionnalité :
- Bouton de réinitialisation d'un espace, efface les historiques et les inscriptions, les désinscriptions des participants et par autorité ne suppriment plus les historiques.
2024-04-17 10:33:00 +02:00
37f77b3d50 readme 2024-04-13 10:13:48 +02:00
a5130e1d9f readme 2024-04-13 10:13:13 +02:00
256da35d53 1.8.00 user report in csv 2024-04-13 10:07:47 +02:00
98 changed files with 816 additions and 243 deletions

View File

@ -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

View File

@ -1,4 +1,4 @@
# ZwiiCampus 1.7.09
# ZwiiCampus 1.10.04
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é.
@ -68,6 +68,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 +85,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

View File

@ -338,13 +338,12 @@ class helper
{
// N'interroge que le serveur Apache
if (strpos($_SERVER["SERVER_SOFTWARE"], 'Apache') > 0) {
self::$rewriteStatus === false;
} elseif (self::$rewriteStatus === null) {
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;
}

View File

@ -151,7 +151,7 @@ class layout extends common
}
echo '</div>';
}
echo '</main></section>';
echo '</section></main>';
}
/**
@ -1001,7 +1001,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>';
}
@ -1016,46 +1016,53 @@ class layout extends common
)
// Sur une page d'accueil
or $this->getUrl(0) === ''
) {
// Bouton Editer une page
if ($this->getUser('permission', 'page', 'edit')) {
$leftItems .= '<li>' . template::ico('pencil', [
'href' => helper::baseUrl() . 'page/edit/' . $this->getUrl(0),
'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'])
) {
$leftItems .= '<li>' . template::ico('gear', [
'href' => helper::baseUrl() . $this->getUrl(0) . '/config',
'help' => 'Module de la page'
]) . '</li>';
// Bouton Editer une page
if (
$this->getUser('permission', 'page', 'edit')
and $this->geturl(1) !== 'edit'
) {
$leftItems .= '<li>' . template::ico('pencil', [
'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')
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',
'help' => 'Module de la page'
]) . '</li>';
}
// 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) . '/' . self::$siteContent,
'help' => 'Dupliquer la page'
])
. '</li>';
}
// 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) . '/' . self::$siteContent,
'help' => 'Supprimer la page',
'id' => 'pageDelete'
])
. '</li>';
}
}
// Bouton dupliquer une page
if (
$this->getUser('permission', 'page', 'duplicate')
) {
$leftItems .= '<li>' . template::ico('clone', [
'href' => helper::baseUrl() . 'page/duplicate/' . $this->getUrl(0),
'help' => 'Dupliquer la page'
])
. '</li>';
}
// Bouton Effacer une page
if (
$this->getUser('permission', 'page', 'delete')
) {
$leftItems .= '<li>' . template::ico('trash', [
'href' => helper::baseUrl() . 'page/delete/' . $this->getUrl(0),
'help' => 'Supprimer la page',
'id' => 'pageDelete'
])
. '</li>';
}
}
}
// Items de droite
$rightItems = '';

View File

@ -15,12 +15,12 @@ class core extends common
}
// 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() &&
@ -43,11 +43,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 +60,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 +92,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 +273,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 +284,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 +293,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 +368,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 +384,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)) {
@ -414,29 +414,21 @@ class core extends common
// Sauvegarde la dernière page visitée par l'utilisateur connecté et enregistre l'historique des consultations
if (
$this->getUser('id')
&& self::$siteContent !== 'home'
&& common::$siteContent !== 'home'
&& in_array($this->getUrl(0), array_keys($this->getData(['page'])))
// Le userId n'est pas celui d'un admis ni le prof du contenu
&& (
$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]);
*/
// 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()]);
$this->setData(['enrolment', common::$siteContent, $this->getUser('id'), 'lastPageView', $this->getUrl(0)]);
$this->setData(['enrolment', common::$siteContent, $this->getUser('id'), 'datePageView', time()]);
// Stocke le rapport en CSV
$file = fopen(self::DATA_DIR . self::$siteContent . '/report.csv', 'a+');
fputcsv($file, [ $this->getUser('id'), $this->getUrl(0) ,time()], ';');
$file = fopen(common::DATA_DIR . common::$siteContent . '/report.csv', 'a+');
fputcsv($file, [$this->getUser('id'), $this->getUrl(0), time()], ';');
fclose($file);
}
@ -447,7 +439,7 @@ 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
and ($this->getUser('group') === common::GROUP_BANNED
or ($_SESSION['csrf'] !== $this->getData(['user', $this->getUser('id'), 'accessCsrf'])
and $this->getData(['config', 'connect', 'autoDisconnect']) === true)
)
@ -462,7 +454,7 @@ class core extends common
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->getUser('group') < common::GROUP_ADMIN
)
)
) {
@ -475,31 +467,11 @@ 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
$this->getData(['page', $this->getUrl(0), 'group']) === common::GROUP_VISITOR
or ($this->getUser('password') === $this->getInput('ZWII_USER_PASSWORD')
// and $this->getUser('group') >= $this->getData(['page', $this->getUrl(0), 'group'])
// Modification qui tient compte du profil de la page
@ -520,11 +492,19 @@ class core extends common
and $this->getUser('password') !== $this->getInput('ZWII_USER_PASSWORD')
) 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->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;
}
}
/**
@ -546,9 +526,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']);
@ -585,10 +565,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']);
@ -606,7 +586,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']),
@ -632,7 +612,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,
@ -677,7 +657,7 @@ class core extends common
$output = $module->output;
// Check le groupe de l'utilisateur
if (
($module::$actions[$action] === self::GROUP_VISITOR
($module::$actions[$action] === common::GROUP_VISITOR
or ($this->getUser('password') === $this->getInput('ZWII_USER_PASSWORD')
and $this->getUser('group') >= $module::$actions[$action]
and $this->getUser('permission', $moduleId, $action)
@ -690,10 +670,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;
}
}
}
@ -733,9 +713,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)
@ -748,7 +728,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;
@ -757,7 +737,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;
@ -826,7 +806,7 @@ 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 (
@ -838,22 +818,49 @@ class core extends common
} 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>')
]);
}
}
@ -876,25 +883,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();
@ -905,7 +912,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();

View File

@ -462,7 +462,7 @@ $(document).ready(function () {
/**
* Chargement paresseux des images et des iframes
*/
$("img,picture,iframe").attr("loading", "lazy");
$("img").attr("loading", "lazy");
/**
* Effet accordéon

View File

@ -51,7 +51,7 @@ class common
const ACCESS_TIMER = 1800;
// Numéro de version
const ZWII_VERSION = '1.8.00-dev';
const ZWII_VERSION = '1.10.04';
// URL autoupdate
const ZWII_UPDATE_URL = 'https://forge.chapril.org/ZwiiCMS-Team/campus-update/raw/branch/master/';
@ -1105,8 +1105,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) {

View File

@ -490,7 +490,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'),
@ -556,7 +556,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 .
@ -565,7 +565,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',
@ -957,4 +957,19 @@ 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';
}
}
}

View File

@ -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'

View File

@ -48,7 +48,7 @@
<?php echo template::checkbox('configRewrite', true, 'Apache URL intelligentes', [
'checked' => helper::checkRewrite(),
'help' => 'Supprime le point d\'interrogation dans les URL, l\'option est indisponible avec les autres serveurs Web',
'disabled' => stripos($_SERVER["SERVER_SOFTWARE"], 'nginx')
'disabled' => stripos($_SERVER["SERVER_SOFTWARE"], 'Apache') === false and $module->isModRewriteEnabled()
]); ?>
</div>
</div>

View File

@ -32,6 +32,7 @@ class course extends common
'userReportExport' => self::GROUP_EDITOR, //Fait
'backup' => self::GROUP_EDITOR, // Fait
'restore' => self::GROUP_EDITOR, //Fait
'reset' => self::GROUP_EDITOR,
'clone' => self::GROUP_ADMIN,
'add' => self::GROUP_ADMIN,
'delete' => self::GROUP_ADMIN,
@ -110,13 +111,20 @@ class course extends common
self::$courseAccess[$this->getData(['course', $courseId, 'access'])],
self::$courseEnrolment[$this->getData(['course', $courseId, 'enrolment'])]
);
if ($this->getUser('permission', 'course', 'users') === true) {
$users = template::button('categoryUser' . $this->getUrl(2), [
'href' => helper::baseUrl() . 'course/users/' . $courseId,
'value' => template::ico('users'),
]);
}
self::$courses[] = [
$info,
$this->getData(['course', $courseId, 'description']),
$enrolment,
$users,
template::button('categoryUser' . $courseId, [
'href' => helper::baseUrl() . 'course/manage/' . $courseId,
'value' => template::ico('eye'),
'value' => template::ico('sliders'),
'help' => 'Gérer'
])
];
@ -690,13 +698,13 @@ class course extends common
self::$courseUsers[] = [
//$userId,
$this->getData(['user', $userId, 'firstname']) . ' ' . $this->getData(['user', $userId, 'lastname']),
isset($pages[$userValue['lastPageView']]['title'])
array_key_exists('lastPageView', $userValue) && isset($pages[$userValue['lastPageView']]['title'])
? $pages[$userValue['lastPageView']]['title']
: '',
$userValue['datePageView']
array_key_exists('lastPageView', $userValue)
? helper::dateUTF8('%d/%m/%Y', $userValue['datePageView'])
: '',
$userValue['datePageView']
array_key_exists('datePageView', $userValue)
? helper::dateUTF8('%H:%M', $userValue['datePageView'])
: '',
$this->getData(['user', $userId, 'tags']),
@ -903,6 +911,7 @@ class course extends common
/**
* Désinscription de tous les utilisateurs
* Les désinscriptions ne suppriment pas les historiques
*/
public function usersDelete()
{
@ -1038,6 +1047,47 @@ class course extends common
]);
}
/**
* Désincription de tous les utilisateurs hors les éditeurs
* Effacement des historiques
*/
public function reset()
{
// Contenu sélectionné
$courseId = $this->getUrl(2);
// Accès limité aux admins, à l'auteur ou éditeurs inscrits
if (
$this->permissionControl(__FUNCTION__, $courseId) === false
) {
// Valeurs en sortie
$this->addOutput([
'access' => false
]);
}
// Active l'accueil
$_SESSION['ZWII_SITE_CONTENT'] = 'home';
// Efface les inscriptions
$success = $this->setData(['enrolment', $courseId, []]);
// Efface les rapports
if (file_exists(self::DATA_DIR . $courseId . '/report.csv')) {
unlink(self::DATA_DIR . $courseId . '/report.csv');
}
// Valeurs en sortie
$this->addOutput([
'redirect' => helper::baseUrl() . 'course',
'notification' => helper::translate('Espace réinitialisé'),
'state' => true
]);
}
/*
* Traitement du changement de langue
*/
@ -1377,7 +1427,7 @@ class course extends common
}
// Traitement de l'historique
$h = $this->getReport($courseId, $userId);
$h = $this->getReport($courseId);
$h = $h[$userId];
// Inversion des clés et des valeurs
@ -1541,6 +1591,7 @@ class course extends common
/**
* Désinscription d'un participant
* La désinscription ne supprime pas les historiques,
*/
public function unsuscribe()
{
@ -1890,34 +1941,38 @@ class course extends common
*/
private function getReport($courseId, $userId = null)
{
// Remplacez 'chemin/vers/votre/fichier.csv' par le chemin réel de votre fichier CSV
$file = fopen(self::DATA_DIR . $courseId . '/report.csv', "r");
$data = array();
$data = [];
if (file_exists(self::DATA_DIR . $courseId . '/report.csv')) {
// Remplacez 'chemin/vers/votre/fichier.csv' par le chemin réel de votre fichier CSV
$file = fopen(self::DATA_DIR . $courseId . '/report.csv', "r");
// Lire ligne par ligne
while (($line = fgetcsv($file, 1000, ";")) !== false) {
$name = $line[0];
$pageId = $line[1];
$timestamp = $line[2];
// Filtre userId
// if (!is_null($userId) && $name === $userId) {
$data = array();
// Lire ligne par ligne
while (($line = fgetcsv($file, 1000, ";")) !== false) {
$name = $line[0];
$pageId = $line[1];
$timestamp = $line[2];
// Filtre userId
// if (!is_null($userId) && $name === $userId) {
// Initialiser le tableau si nécessaire
if (!isset($data[$name][$pageId])) {
$data[$name][$pageId] = array();
}
// Ajouter le timestamp
$data[$name][$pageId][] = $timestamp;
// }
}
//}
}
// Fermer le fichier
fclose($file);
// Fermer le fichier
fclose($file);
// Trier les timestamps
foreach ($data as &$userData) {
foreach ($userData as &$pageData) {
sort($pageData);
// Trier les timestamps
foreach ($data as &$userData) {
foreach ($userData as &$pageData) {
sort($pageData);
}
}
}

View File

@ -23,6 +23,16 @@ $(document).ready(function () {
target: 2,
orderable: false,
searchable: false
},
{
target: 3,
orderable: false,
searchable: false
},
{
target: 4,
orderable: false,
searchable: false
}
]
});

View File

@ -37,7 +37,7 @@
</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; ?>

View File

@ -20,4 +20,15 @@ $(".courseDelete").on("click", function () {
return core.confirm(message, 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"));
});
});

View File

@ -18,6 +18,16 @@
]); ?>
</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'
]); ?>
</div>
<?php endif; ?>
<?php if ($this->getUser('permission', 'course', 'backup') === true): ?>
<div class="col2">
<?php echo template::button('courseManageDownload' . $this->getUrl(2), [
@ -38,7 +48,6 @@
<?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',
@ -46,17 +55,6 @@
]); ?>
</div>
<?php endif; ?>
<?php if ($this->getUser('permission', 'course', 'users') === true): ?>
<div class="col2">
<?php echo template::button('categoryUser' . $this->getUrl(2), [
'href' => helper::baseUrl() . 'course/users/' . $this->getUrl(2),
'value' => 'Participants',
'ico' => 'users'
]); ?>
</div>
<?php endif; ?>
</div>
<div class="row">

View File

@ -2,7 +2,7 @@
<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>

View File

@ -252,7 +252,8 @@ class init extends common
'usersDelete' => false,
'edit' => false,
'backup' => false,
'restore' => false
'restore' => false,
'reset' => false,
],
'folder' => [
'create' => false,
@ -348,7 +349,8 @@ class init extends common
'usersDelete' => false,
'edit' => false,
'backup' => false,
'restore' => false
'restore' => false,
'reset' => false,
],
'folder' => [
'create' => false,
@ -449,7 +451,8 @@ class init extends common
'usersDelete' => false,
'edit' => false,
'backup' => false,
'restore' => false
'restore' => false,
'reset' => false,
],
'folder' => [
'create' => false,
@ -546,7 +549,8 @@ class init extends common
'usersDelete' => true,
'edit' => true,
'backup' => true,
'restore' => true
'restore' => true,
'reset' => true,
],
'folder' => [
'create' => true,

View File

@ -85,12 +85,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([
@ -118,7 +129,7 @@ class page extends common
// 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 +142,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
@ -198,12 +221,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([
@ -215,9 +250,9 @@ class page extends common
// Valeurs en sortie
$this->addOutput([
'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')
'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
@ -264,7 +299,7 @@ class page extends common
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')
]);
}
@ -304,10 +339,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([
@ -634,7 +683,7 @@ class page extends common
// 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
]);
}
@ -669,7 +718,7 @@ class page extends common
// 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
]);
}
@ -685,16 +734,16 @@ 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()
{
$p = $this->getData(['page']);
$d = array_map(function ($d) {
unset($d["css"], $d["js"]);
unset ($d["css"], $d["js"]);
return $d;
}, $p);
return json_encode($d);
}
}

View File

@ -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>

View File

@ -19,14 +19,14 @@
<div class="col1 offset6">
<?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'
]); ?>

View File

@ -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>

View File

@ -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,
@ -229,6 +230,145 @@ 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'])
) {
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->getData(['user', $keyPost]) !== null
) {
$this->deleteData(['user', $keyPost]);
}
}
}
// 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
*/
@ -711,8 +851,28 @@ class user extends common
// 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->getUser('group') >= self::GROUP_EDITOR,
'manage' => $this->getUser('group') >= self::GROUP_EDITOR,
'index' => $this->getInput('profilEditCourseUsers', helper::FILTER_BOOLEAN)
|| $this->getInput('profilEditCourseUserHistory', helper::FILTER_BOOLEAN)
|| $this->getInput('profilEditCourseUserExport', 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('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),
@ -724,6 +884,7 @@ class user extends common
'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),
]
];
@ -905,7 +1066,8 @@ class user extends common
|| $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('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),
@ -917,6 +1079,7 @@ class user extends common
'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),
]
];

View File

@ -8,20 +8,28 @@
</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'
]);*/?>
'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="col1 offset6">
<?php echo template::button('userImport', [
'href' => helper::baseUrl() . 'user/import',
'value' => template::ico('upload'),
'value' => template::ico('users'),
'help' => 'Importer des utilisateurs en masse'
]); ?>
</div>
<div class="col1">
<?php echo template::button('userDeleteAll', [
'class' => 'userDeleteAll buttonRed',
'href' => helper::baseUrl() . 'user/usersDelete/' . $this->getUrl(2),
'value' => template::ico('users'),
'help' => 'Désinscrire en masse',
]) ?>
</div>
<div class="col1">
<?php echo template::button('userGroup', [
'href' => helper::baseUrl() . 'user/profil',
@ -60,4 +68,4 @@
</div>
</div>
<?php echo template::formClose(); ?>
<?php echo template::table([3, 2, 2, 2, 2, 1, 1], $module::$users, [ 'Nom', 'Groupe', 'Profil', 'Étiquettes', 'Date dernière vue', '', ''], ['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']); ?>

View File

@ -205,6 +205,9 @@
<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>

View File

@ -54,6 +54,19 @@ $(document).ready(function () {
$(".containerModule").slideDown();
}
if ($('#profilEditCourseUsers').is(':checked')) {
// Activer les autres checkboxes
$('#profilEditCourseUserHistory, #profilEditCourseUserHistoryExport, #profilEditCourseUserDelete, #profilEditCourseUsersAdd, #profilEditCourseUsersDelete, #profilEditCourseReset').prop('disabled', false);
} else {
// Désactiver les autres checkboxes
$('#profilEditCourseUserHistory, #profilEditCourseUserHistoryExport, #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')) {
@ -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, #profilEditCourseUserHistoryExport, #profilEditCourseUserDelete, #profilEditCourseUsersAdd, #profilEditCourseUsersDelete, #profilEditCourseReset').prop('disabled', false);
} else {
// Désactiver les autres checkboxes
$('#profilEditCourseUserHistory, #profilEditCourseUserHistoryExport, #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);
}
});
});

View File

@ -307,6 +307,11 @@
'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>

View 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;
}

View File

@ -0,0 +1,100 @@
/**
* 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',
"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);
}
}
}
}));

View 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 offset8">
<?php echo template::button('usersDeleteSelectAll', [
'value' => template::ico('square-check'),
'help' => 'Tout sélectionner'
]); ?>
</div>
<div class="col1">
<?php echo template::button('usersDeleteSelectNone', [
'value' => template::ico('square-check-empty'),
'help' => 'Tout désélectionner'
]); ?>
</div>
<div class="col1">
<?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>
<?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(); ?>

View File

@ -16,7 +16,7 @@
class blog extends common
{
const VERSION = '7.6';
const VERSION = '7.9';
const REALNAME = 'Blog';
const DELETE = true;
const UPDATE = '0.0';
@ -196,9 +196,11 @@ class blog extends common
$feeds = new \FeedWriter\RSS2();
// En-tête
$feeds->setTitle($this->getData(['page', $this->getUrl(0), 'title']));
$feeds->setTitle($this->getData(['page', $this->getUrl(0), 'title']) ? $this->getData(['page', $this->getUrl(0), 'title']): '');
$feeds->setLink(helper::baseUrl() . $this->getUrl(0));
$feeds->setDescription($this->getData(['page', $this->getUrl(0), 'metaDescription']));
if ($this->getData(['page', $this->getUrl(0), 'metaDescription'])) {
$feeds->setDescription($this->getData(['page', $this->getUrl(0), 'metaDescription']));
}
$feeds->setChannelElement('language', 'fr-FR');
$feeds->setDate(date('r', time()));
$feeds->addGenerator();
@ -361,7 +363,7 @@ class blog extends common
self::$dateFormat = $this->getData(['module', $this->getUrl(0), 'config', 'dateFormat']);
self::$timeFormat = $this->getData(['module', $this->getUrl(0), 'config', 'timeFormat']);
self::$comments[] = [
helper::dateUTF8(self::$dateFormat, $comment['createdOn']) . ' - ' . helper::dateUTF8(self::$timeFormat, $comment['createdOn']),
helper::dateUTF8(self::$dateFormat, $comment['createdOn'], self::$i18nUI) . ' - ' . helper::dateUTF8(self::$timeFormat, $comment['createdOn'], self::$i18nUI),
$comment['content'],
$comment['userId'] ? $this->getData(['user', $comment['userId'], 'firstname']) . ' ' . $this->getData(['user', $comment['userId'], 'lastname']) : $comment['author'],
$buttonApproval,
@ -530,7 +532,7 @@ class blog extends common
'<a href="' . helper::baseurl() . $this->getUrl(0) . '/' . $articleIds[$i] . '" target="_blank" >' .
$this->getData(['module', $this->getUrl(0), 'posts', $articleIds[$i], 'title']) .
'</a>',
helper::dateUTF8(self::$dateFormat, $this->getData(['module', $this->getUrl(0), 'posts', $articleIds[$i], 'publishedOn'])) . ' - ' . helper::dateUTF8(self::$timeFormat, $this->getData(['module', $this->getUrl(0), 'posts', $articleIds[$i], 'publishedOn'])),
helper::dateUTF8(self::$dateFormat, $this->getData(['module', $this->getUrl(0), 'posts', $articleIds[$i], 'publishedOn']), self::$i18nUI) . ' - ' . helper::dateUTF8(self::$timeFormat, $this->getData(['module', $this->getUrl(0), 'posts', $articleIds[$i], 'publishedOn']), self::$i18nUI),
self::$states[$this->getData(['module', $this->getUrl(0), 'posts', $articleIds[$i], 'state'])],
// Bouton pour afficher les commentaires de l'article
template::button('blogConfigComment' . $articleIds[$i], [

View File

@ -1,3 +1,8 @@
# Versions 7.8 - 7.9
- Le flux RSS ne fonctionne pas si les méta de la page sont vides.
# Version 7.7
- Contrôle de la variable de session liée au contenu. Evite des erreurs lorsque plusieurs onglets sont ouverts.
# Version 7.6
- Mise à jour RSS Feed
# Version 7.5

0
module/blog/ressource/feed-icon-16.gif Normal file → Executable file
View File

Before

Width:  |  Height:  |  Size: 652 B

After

Width:  |  Height:  |  Size: 652 B

0
module/blog/vendor/FeedWriter/ATOM.php vendored Normal file → Executable file
View File

0
module/blog/vendor/FeedWriter/Feed.php vendored Normal file → Executable file
View File

0
module/blog/vendor/FeedWriter/InvalidOperationException.php vendored Normal file → Executable file
View File

0
module/blog/vendor/FeedWriter/Item.php vendored Normal file → Executable file
View File

0
module/blog/vendor/FeedWriter/README.md vendored Normal file → Executable file
View File

0
module/blog/vendor/FeedWriter/RSS1.php vendored Normal file → Executable file
View File

0
module/blog/vendor/FeedWriter/RSS2.php vendored Normal file → Executable file
View File

0
module/blog/vendor/furl/LICENSE vendored Normal file → Executable file
View File

0
module/blog/vendor/furl/README.md vendored Normal file → Executable file
View File

0
module/blog/vendor/furl/inc.json vendored Normal file → Executable file
View File

0
module/blog/vendor/furl/jquery.furl.js vendored Normal file → Executable file
View File

0
module/blog/view/add/add.css Normal file → Executable file
View File

0
module/blog/view/add/add.js.php Normal file → Executable file
View File

0
module/blog/view/add/add.php Normal file → Executable file
View File

0
module/blog/view/article/article.css Normal file → Executable file
View File

0
module/blog/view/article/article.js.php Normal file → Executable file
View File

0
module/blog/view/comment/comment.css Normal file → Executable file
View File

0
module/blog/view/comment/comment.js.php Normal file → Executable file
View File

0
module/blog/view/comment/comment.php Normal file → Executable file
View File

0
module/blog/view/config/config.css Normal file → Executable file
View File

0
module/blog/view/config/config.js.php Normal file → Executable file
View File

2
module/blog/view/config/config.php Normal file → Executable file
View File

@ -3,7 +3,7 @@
<div class="col1">
<?php echo template::button('blogConfigBack', [
'class' => 'buttonGrey',
'href' => helper::baseUrl() . 'page/edit/' . $this->getUrl(0), 'posts',
'href' => helper::baseUrl() . 'page/edit/' . $this->getUrl(0) . '/' . self::$siteContent,
'value' => template::ico('left')
]); ?>
</div>

0
module/blog/view/edit/edit.css Normal file → Executable file
View File

0
module/blog/view/edit/edit.js.php Normal file → Executable file
View File

0
module/blog/view/edit/edit.php Normal file → Executable file
View File

0
module/blog/view/index/index.css Normal file → Executable file
View File

0
module/blog/view/option/option.css Normal file → Executable file
View File

0
module/blog/view/rss/rss.php Normal file → Executable file
View File

View File

@ -1,3 +1,5 @@
# Version 4.3
- Contrôle de la variable de session liée au contenu. Evite des erreurs lorsque plusieurs onglets sont ouverts.
# Version 4.2
- Termes des commandes de profils
# Version 4.1

View File

@ -17,7 +17,7 @@
class form extends common
{
const VERSION = '4.2';
const VERSION = '4.3';
const REALNAME = 'Formulaire';
const DATADIRECTORY = ''; // Contenu localisé inclus par défaut (page.json et module.json)

0
module/form/vendor/html-sortable/html-sortable.min.js vendored Normal file → Executable file
View File

0
module/form/vendor/html-sortable/inc.json vendored Normal file → Executable file
View File

0
module/form/vendor/html-sortable/lisezmoi.txt vendored Normal file → Executable file
View File

0
module/form/view/config/config.css Normal file → Executable file
View File

View File

@ -53,7 +53,7 @@
<div class="col1">
<?php echo template::button('formConfigBack', [
'class' => 'buttonGrey',
'href' => helper::baseUrl() . 'page/edit/' . $this->getUrl(0),
'href' => helper::baseUrl() . 'page/edit/' . $this->getUrl(0) . '/' . self::$siteContent,
'value' => template::ico('left')
]); ?>
</div>

0
module/form/view/data/data.css Normal file → Executable file
View File

View File

@ -1,3 +1,5 @@
# Version 4.2
- Contrôle de la variable de session liée au contenu. Evite des erreurs lorsque plusieurs onglets sont ouverts.
# Version 4.1
- Termes des commandes de profils
# Version 4.0

View File

@ -18,7 +18,7 @@ class gallery extends common
{
const VERSION = '4.1';
const VERSION = '4.2';
const REALNAME = 'Galerie';
const DATADIRECTORY = self::DATA_DIR . 'gallery/';

0
module/gallery/ressource/theme.css Normal file → Executable file
View File

0
module/gallery/ressource/vartheme.css Normal file → Executable file
View File

0
module/gallery/vendor/tablednd/inc.json vendored Normal file → Executable file
View File

0
module/gallery/vendor/tablednd/lisez-moi.txt vendored Normal file → Executable file
View File

0
module/gallery/vendor/tablednd/tablednd.min.js vendored Normal file → Executable file
View File

0
module/gallery/view/config/config.css Normal file → Executable file
View File

View File

@ -3,7 +3,7 @@
<div class="col1">
<?php echo template::button('galleryConfigBack', [
'class' => 'buttonGrey',
'href' => helper::baseUrl() . 'page/edit/' . $this->getUrl(0),
'href' => helper::baseUrl() . 'page/edit/' . $this->getUrl(0) . '/' . self::$siteContent,
'value' => template::ico('left')
]); ?>
</div>

0
module/gallery/view/edit/edit.css Normal file → Executable file
View File

0
module/gallery/view/theme/theme.css Normal file → Executable file
View File

View File

@ -1,3 +1,7 @@
# Versions 5.7 - 5.8
- Le flux RSS ne fonctionne pas si les méta de la page sont vides.
# Version 5.6
- Contrôle de la variable de session liée au contenu. Evite des erreurs lorsque plusieurs onglets sont ouverts.
# Version 5.5
- Mise à jour RSS Feed
# Version 5.4

View File

@ -16,7 +16,7 @@
class news extends common
{
const VERSION = '5.5';
const VERSION = '5.8';
const REALNAME = 'News';
const DATADIRECTORY = self::DATA_DIR . 'news/';
@ -124,9 +124,11 @@ class news extends common
$feeds = new \FeedWriter\RSS2();
// En-tête
$feeds->setTitle($this->getData(['page', $this->getUrl(0), 'title']));
$feeds->setTitle($this->getData(['page', $this->getUrl(0), 'title']) ? $this->getData(['page', $this->getUrl(0), 'title']): '');
$feeds->setLink(helper::baseUrl() . $this->getUrl(0));
$feeds->setDescription($this->getData(['page', $this->getUrl(0), 'metaDescription']));
if ($this->getData(['page', $this->getUrl(0), 'metaDescription'])) {
$feeds->setDescription($this->getData(['page', $this->getUrl(0), 'metaDescription']));
};
$feeds->setChannelElement('language', 'fr-FR');
$feeds->setDate(date('r', time()));
$feeds->addGenerator();

View File

@ -3,7 +3,7 @@
<div class="col1">
<?php echo template::button('newsConfigBack', [
'class' => 'buttonGrey',
'href' => helper::baseUrl() . 'page/edit/' . $this->getUrl(0),'posts',
'href' => helper::baseUrl() . 'page/edit/' . $this->getUrl(0) . '/' . self::$siteContent,
'value' => template::ico('left')
]); ?>
</div>

View File

@ -1,3 +1,5 @@
# Version 2.2
- Contrôle de la variable de session liée au contenu. Evite des erreurs lorsque plusieurs onglets sont ouverts.
# Version 2.1
- Edition du module ou de la page impossible.
# Version 2.0

View File

@ -16,7 +16,7 @@
class redirection extends common
{
const VERSION = '2.1';
const VERSION = '2.2';
const REALNAME = 'Redirection';
const DATADIRECTORY = ''; // Contenu localisé inclus par défaut (page.json et module.json)

0
module/redirection/view/config/config.css Normal file → Executable file
View File

View File

@ -3,7 +3,7 @@
<div class="col1">
<?php echo template::button('redirectionConfigBack', [
'class' => 'buttonGrey',
'href' => helper::baseUrl() . 'page/edit/' . $this->getUrl(0),
'href' => helper::baseUrl() . 'page/edit/' . $this->getUrl(0) . '/' . self::$siteContent,
'value' => template::ico('left')
]); ?>
</div>

0
module/redirection/view/index/index.css Normal file → Executable file
View File

View File

@ -1,3 +1,5 @@
# Version 3.2
- Contrôle de la variable de session liée au contenu. Evite des erreurs lorsque plusieurs onglets sont ouverts.
# Version 3.1
- Initialise un module installé dans une page sans avoir ouvert la page de configuration sans lancer de mise à jour.
# Version 3.0

View File

@ -20,7 +20,7 @@
class search extends common
{
const VERSION = '3.1';
const VERSION = '3.2';
const REALNAME = 'Recherche';
const DATADIRECTORY = self::DATA_DIR . 'search/';

0
module/search/view/config/config.css Normal file → Executable file
View File

View File

@ -3,7 +3,7 @@
<div class="col1">
<?php echo template::button('searchConfigBack', [
'class' => 'buttonGrey',
'href' => helper::baseUrl() . 'page/edit/' . $this->getUrl(0),
'href' => helper::baseUrl() . 'page/edit/' . $this->getUrl(0) . '/' . self::$siteContent,
'value' => template::ico('left')
]); ?>
</div>

0
module/search/view/index/index.css Normal file → Executable file
View File

View File

@ -1,3 +1,5 @@
# Version 6.5
- Contrôle de la variable de session liée au contenu. Evite des erreurs lorsque plusieurs onglets sont ouverts.
# Version 6.4
- Corrige plusieurs bugs dans les fonctions de tri
# Version 6.3

View File

@ -3,7 +3,7 @@
<div class="col1">
<?php echo template::button('galleryConfigBack', [
'class' => 'buttonGrey',
'href' => helper::baseUrl() . 'page/edit/' . $this->getUrl(0),
'href' => helper::baseUrl() . 'page/edit/' . $this->getUrl(0) . '/' . self::$siteContent,
'value' => template::ico('left')
]); ?>
</div>

View File

@ -4,7 +4,7 @@
<div class="col2">
<?php echo template::button('registrationConfigBack', [
'class' => '',
'href' => helper::baseUrl() .'page/edit/' . $this->getUrl(0) ,
'href' => helper::baseUrl() .'page/edit/' . $this->getUrl(0) . '/' . self::$siteContent,
'ico' => 'left',
'value' => 'Retour'
]); ?>

View File

@ -3,7 +3,7 @@
<div class="col1">
<?php echo template::button('coursesConfigBack', [
'class' => 'buttonGrey',
'href' => helper::baseUrl() . 'page/edit/' . $this->getUrl(0),
'href' => helper::baseUrl() . 'page/edit/' . $this->getUrl(0) . '/' . self::$siteContent,
'value' => template::ico('left')
]); ?>
</div>

View File

@ -1,5 +1,8 @@
<?php $startRow = 0; ?>
<?php foreach ($this->getData(['course']) as $courseId => $courseValue): ?>
<?php $c = $this->getData(['course']);?>
<?php $titles = array_column($c, 'title'); ?>
<?php array_multisort($titles, SORT_ASC, $c); ?>
<?php foreach ($c as $courseId => $courseValue): ?>
<!-- Filtre de catégorie -->
<?php if (
$this->getData(['module', $this->getUrl(0), 'config', 'category']) !== 'all' &&

View File

@ -153,13 +153,6 @@ class workshop extends common
'view' => 'index'
]);
// Valeurs en sortie
$this->addOutput([
'showBarEditButton' => true,
'showPageContent' => true,
'view' => 'index',
]);
}
// Initialise avec des valeurs par défaut