Compare commits

..

7 Commits

Author SHA1 Message Date
13a603b1f9 fonction getReport ajoutée à tester 2024-04-04 16:13:54 +02:00
ab34cb1953 Fonctions pour récupérer les données des rapports 2024-04-04 15:36:05 +02:00
65029fb191 Ecriture dans report sauf dans course à venir 2024-04-04 13:14:43 +02:00
e58ce9cda0 update :
creation des bases de données report dans les espaces avec les historiques des utilisateurs
2024-04-04 11:27:48 +02:00
0b14519567 Interface de gestion des abonnements 2024-04-03 18:22:05 +02:00
0eede10300 readme 2024-04-03 17:46:04 +02:00
5dc51a62ce 1.8.00 initialise avec la création des bases dans les espaces WIP 2024-04-03 16:59:04 +02:00
119 changed files with 462 additions and 1062 deletions

View File

@ -32,13 +32,5 @@ Options -Indexes
Options -MultiViews Options -MultiViews
</IfModule> </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 ! # ne pas supprimer la ligne URL rewriting !
# URL rewriting # URL rewriting

View File

@ -1,4 +1,4 @@
# ZwiiCampus 1.10.04 # ZwiiCampus 1.8.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é. 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,7 +68,6 @@ 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] module.json Données des modules de pages
[F] theme.css Thème de ce contenu [F] theme.css Thème de ce contenu
[F] theme.json 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 [R] content Dossier des contenus de page
[F] accueil.html Exemple contenu de la page d'accueil [F] accueil.html Exemple contenu de la page d'accueil
[R] fonts Dossier contenant les fontes installées [R] fonts Dossier contenant les fontes installées
@ -85,7 +84,7 @@ A l'occasion de l'installation d'une version majeure, il est recommandé de réa
[F] core.json Configuration du noyau [F] core.json Configuration du noyau
[F] course.json Données de contenus [F] course.json Données de contenus
[F] custom.css Feuille de style de la personnalisation avancée [F] custom.css Feuille de style de la personnalisation avancée
[F] enrolment.json Inscriptions dans les espaces, dernière page vue et timetamp [F] enrolment.json Données des inscriptions et des statistiques par contenu
[F] font.json Descripteur des fontes personnalisées [F] font.json Descripteur des fontes personnalisées
[F] journal.log Journalisation des activités [F] journal.log Journalisation des activités
[F] language.json Langues de l'interface [F] language.json Langues de l'interface

View File

@ -338,12 +338,13 @@ class helper
{ {
// N'interroge que le serveur Apache // N'interroge que le serveur Apache
if (strpos($_SERVER["SERVER_SOFTWARE"], 'Apache') > 0) { if (strpos($_SERVER["SERVER_SOFTWARE"], 'Apache') > 0) {
self::$rewriteStatus = false; self::$rewriteStatus === false;
} else { } elseif (self::$rewriteStatus === null) {
// Ouvre et scinde le fichier .htaccess // Ouvre et scinde le fichier .htaccess
$htaccess = explode('# URL rewriting', file_get_contents('.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 // Retourne un boolean en fonction du contenu de la partie réservée à l'URL rewriting
self::$rewriteStatus = (strpos($htaccess[1], 'RewriteEngine on') !== false); //self::$rewriteStatus = (empty($htaccess[1]) === false);
self::$rewriteStatus = (strpos($htaccess[1], 'RewriteEngine on') > 0) ? true : false;
} }
return self::$rewriteStatus; return self::$rewriteStatus;
} }

View File

@ -129,9 +129,9 @@ class JsonDb extends \Prowebcraft\Dot
} }
} }
$this->data = json_decode(file_get_contents($this->db), true); $this->data = json_decode(file_get_contents($this->db), true);
if (!$this->data === null && json_last_error() !== JSON_ERROR_NONE) { if (!$this->data === null) {
throw new \InvalidArgumentException('Le fichier ' . $this->db throw new \InvalidArgumentException('Database file ' . $this->db
. ' contient des données invalides.'); . ' contains invalid json object. Please validate or remove file');
} }
} }
return $this->data; return $this->data;
@ -142,38 +142,20 @@ class JsonDb extends \Prowebcraft\Dot
*/ */
public function save() public function save()
{ {
// Encode les données au format JSON avec les options spécifiées $v = json_encode($this->data, JSON_UNESCAPED_UNICODE | JSON_FORCE_OBJECT );
$encoded_data = json_encode($this->data, JSON_UNESCAPED_UNICODE | JSON_FORCE_OBJECT | JSON_PRETTY_PRINT); $l = strlen($v);
$t = 0;
// Vérifie la longueur de la chaîne JSON encodée while ($t < 5) {
$encoded_length = strlen($encoded_data); $w = file_put_contents($this->db, $v); // Multi user get a locker
if ($w == $l) {
// 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
// Vérifie si l'écriture a réussi
if ($write_result === $encoded_length) {
// Sort de la boucle si l'écriture a réussi
break; break;
} }
$t++;
// Incrémente le compteur de tentatives
$attempt++;
} }
if ($w !== $l) {
// 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.'); 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.'); exit('Erreur d\'écriture, les données n\'ont pas été sauvegardées.');
} }
}
}
} }

View File

@ -151,7 +151,7 @@ class layout extends common
} }
echo '</div>'; echo '</div>';
} }
echo '</section></main>'; echo '</main></section>';
} }
/** /**
@ -1001,7 +1001,7 @@ class layout extends common
// Bouton Ajouter une page // Bouton Ajouter une page
if ($this->getUser('permission', 'page', 'add')) { if ($this->getUser('permission', 'page', 'add')) {
$leftItems .= '<li>' . template::ico('plus', [ $leftItems .= '<li>' . template::ico('plus', [
'href' => helper::baseUrl() . 'page/add/' . self::$siteContent, 'href' => helper::baseUrl() . 'page/add',
'help' => 'Nouvelle page ou barre latérale' 'help' => 'Nouvelle page ou barre latérale'
]) . '</li>'; ]) . '</li>';
} }
@ -1018,20 +1018,16 @@ class layout extends common
or $this->getUrl(0) === '' or $this->getUrl(0) === ''
) { ) {
// Bouton Editer une page // Bouton Editer une page
if ( if ($this->getUser('permission', 'page', 'edit')) {
$this->getUser('permission', 'page', 'edit')
and $this->geturl(1) !== 'edit'
) {
$leftItems .= '<li>' . template::ico('pencil', [ $leftItems .= '<li>' . template::ico('pencil', [
'href' => helper::baseUrl() . 'page/edit/' . $this->getUrl(0) . '/' . self::$siteContent, 'href' => helper::baseUrl() . 'page/edit/' . $this->getUrl(0),
'help' => 'Éditer la page' 'help' => 'Éditer la page'
]) . '</li>'; ]) . '</li>';
} }
// Bouton Editer le module d'une page // Bouton Editer le module d'une page
if ( if (
$this->getUser('permission', 'page', 'module') $this->getUser('permission', 'page', 'module')
and $this->geturl(1) !== 'edit' && $this->getData(['page', $this->getUrl(0), 'moduleId'])
and $this->getData(['page', $this->getUrl(0), 'moduleId'])
) { ) {
$leftItems .= '<li>' . template::ico('gear', [ $leftItems .= '<li>' . template::ico('gear', [
'href' => helper::baseUrl() . $this->getUrl(0) . '/config', 'href' => helper::baseUrl() . $this->getUrl(0) . '/config',
@ -1041,10 +1037,9 @@ class layout extends common
// Bouton dupliquer une page // Bouton dupliquer une page
if ( if (
$this->getUser('permission', 'page', 'duplicate') $this->getUser('permission', 'page', 'duplicate')
and $this->geturl(1) !== 'edit'
) { ) {
$leftItems .= '<li>' . template::ico('clone', [ $leftItems .= '<li>' . template::ico('clone', [
'href' => helper::baseUrl() . 'page/duplicate/' . $this->getUrl(0) . '/' . self::$siteContent, 'href' => helper::baseUrl() . 'page/duplicate/' . $this->getUrl(0),
'help' => 'Dupliquer la page' 'help' => 'Dupliquer la page'
]) ])
. '</li>'; . '</li>';
@ -1052,11 +1047,9 @@ class layout extends common
// Bouton Effacer une page // Bouton Effacer une page
if ( if (
$this->getUser('permission', 'page', 'delete') $this->getUser('permission', 'page', 'delete')
and $this->geturl(1) !== 'edit'
) { ) {
$leftItems .= '<li>' . template::ico('trash', [ $leftItems .= '<li>' . template::ico('trash', [
'href' => helper::baseUrl() . 'page/delete/' . $this->getUrl(0) . '/' . self::$siteContent, 'href' => helper::baseUrl() . 'page/delete/' . $this->getUrl(0),
'help' => 'Supprimer la page', 'help' => 'Supprimer la page',
'id' => 'pageDelete' 'id' => 'pageDelete'
]) ])

View File

@ -15,12 +15,12 @@ class core extends common
} }
// Fuseau horaire // Fuseau horaire
common::$timezone = $this->getData(['config', 'timezone']); // Utile pour transmettre le timezone à la classe helper self::$timezone = $this->getData(['config', 'timezone']); // Utile pour transmettre le timezone à la classe helper
date_default_timezone_set(common::$timezone); date_default_timezone_set(self::$timezone);
// Supprime les fichiers temporaires // Supprime les fichiers temporaires
$lastClearTmp = mktime(0, 0, 0); $lastClearTmp = mktime(0, 0, 0);
if ($lastClearTmp > $this->getData(['core', 'lastClearTmp']) + 86400) { if ($lastClearTmp > $this->getData(['core', 'lastClearTmp']) + 86400) {
$iterator = new DirectoryIterator(common::TEMP_DIR); $iterator = new DirectoryIterator(self::TEMP_DIR);
foreach ($iterator as $fileInfos) { foreach ($iterator as $fileInfos) {
if ( if (
$fileInfos->isFile() && $fileInfos->isFile() &&
@ -43,11 +43,11 @@ class core extends common
and $this->getData(['user']) // Pas de backup pendant l'installation and $this->getData(['user']) // Pas de backup pendant l'installation
) { ) {
// Copie des fichier de données // Copie des fichier de données
helper::autoBackup(common::BACKUP_DIR, ['backup', 'tmp', 'file']); helper::autoBackup(self::BACKUP_DIR, ['backup', 'tmp', 'file']);
// Date du dernier backup // Date du dernier backup
$this->setData(['core', 'lastBackup', $lastBackup]); $this->setData(['core', 'lastBackup', $lastBackup]);
// Supprime les backups de plus de 30 jours // Supprime les backups de plus de 30 jours
$iterator = new DirectoryIterator(common::BACKUP_DIR); $iterator = new DirectoryIterator(self::BACKUP_DIR);
foreach ($iterator as $fileInfos) { foreach ($iterator as $fileInfos) {
if ( if (
$fileInfos->isFile() $fileInfos->isFile()
@ -60,23 +60,23 @@ class core extends common
} }
// Crée le fichier de personnalisation avancée // Crée le fichier de personnalisation avancée
if (file_exists(common::DATA_DIR . 'custom.css') === false) { if (file_exists(self::DATA_DIR . 'custom.css') === false) {
file_put_contents(common::DATA_DIR . 'custom.css', ('core/module/theme/resource/custom.css')); file_put_contents(self::DATA_DIR . 'custom.css', ('core/module/theme/resource/custom.css'));
chmod(common::DATA_DIR . 'custom.css', 0755); chmod(self::DATA_DIR . 'custom.css', 0755);
} }
// Crée le fichier de personnalisation // Crée le fichier de personnalisation
if (file_exists(common::DATA_DIR . common::$siteContent . '/theme.css') === false) { if (file_exists(self::DATA_DIR . self::$siteContent . '/theme.css') === false) {
file_put_contents(common::DATA_DIR . common::$siteContent . '/theme.css', ''); file_put_contents(self::DATA_DIR . self::$siteContent . '/theme.css', '');
chmod(common::DATA_DIR . common::$siteContent . '/theme.css', 0755); chmod(self::DATA_DIR . self::$siteContent . '/theme.css', 0755);
} }
// Crée le fichier de personnalisation de l'administration // Crée le fichier de personnalisation de l'administration
if (file_exists(common::DATA_DIR . 'admin.css') === false) { if (file_exists(self::DATA_DIR . 'admin.css') === false) {
file_put_contents(common::DATA_DIR . 'admin.css', ''); file_put_contents(self::DATA_DIR . 'admin.css', '');
chmod(common::DATA_DIR . 'admin.css', 0755); chmod(self::DATA_DIR . 'admin.css', 0755);
} }
// Check la version rafraichissement du theme // Check la version rafraichissement du theme
$cssVersion = preg_split('/\*+/', file_get_contents(common::DATA_DIR . common::$siteContent . '/theme.css')); $cssVersion = preg_split('/\*+/', file_get_contents(self::DATA_DIR . self::$siteContent . '/theme.css'));
if (empty($cssVersion[1]) or $cssVersion[1] !== md5(json_encode($this->getData(['theme'])))) { if (empty($cssVersion[1]) or $cssVersion[1] !== md5(json_encode($this->getData(['theme'])))) {
// Version // Version
$css = '/*' . md5(json_encode($this->getData(['theme']))) . '*/'; $css = '/*' . md5(json_encode($this->getData(['theme']))) . '*/';
@ -92,7 +92,7 @@ class core extends common
// Fonts disponibles // Fonts disponibles
$fontsAvailable['files'] = $this->getData(['font', 'files']); $fontsAvailable['files'] = $this->getData(['font', 'files']);
$fontsAvailable['imported'] = $this->getData(['font', 'imported']); $fontsAvailable['imported'] = $this->getData(['font', 'imported']);
$fontsAvailable['websafe'] = common::$fontsWebSafe; $fontsAvailable['websafe'] = self::$fontsWebSafe;
// Fontes installées // Fontes installées
$fonts = [ $fonts = [
@ -273,7 +273,7 @@ class core extends common
$css .= '#footerCopyright{text-align:' . $this->getData(['theme', 'footer', 'copyrightAlign']) . '}'; $css .= '#footerCopyright{text-align:' . $this->getData(['theme', 'footer', 'copyrightAlign']) . '}';
// Enregistre la personnalisation // Enregistre la personnalisation
file_put_contents(common::DATA_DIR . common::$siteContent . '/theme.css', $css); file_put_contents(self::DATA_DIR . self::$siteContent . '/theme.css', $css);
// Effacer le cache pour tenir compte de la couleur de fond TinyMCE // Effacer le cache pour tenir compte de la couleur de fond TinyMCE
header("Expires: Tue, 01 Jan 2000 00:00:00 GMT"); 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 // Check la version rafraichissement du theme admin
$cssVersion = preg_split('/\*+/', file_get_contents(common::DATA_DIR . 'admin.css')); $cssVersion = preg_split('/\*+/', file_get_contents(self::DATA_DIR . 'admin.css'));
if (empty($cssVersion[1]) or $cssVersion[1] !== md5(json_encode($this->getData(['admin'])))) { if (empty($cssVersion[1]) or $cssVersion[1] !== md5(json_encode($this->getData(['admin'])))) {
// Version // Version
@ -293,7 +293,7 @@ class core extends common
// Fonts disponibles // Fonts disponibles
$fontsAvailable['files'] = $this->getData(['font', 'files']); $fontsAvailable['files'] = $this->getData(['font', 'files']);
$fontsAvailable['imported'] = $this->getData(['font', 'imported']); $fontsAvailable['imported'] = $this->getData(['font', 'imported']);
$fontsAvailable['websafe'] = common::$fontsWebSafe; $fontsAvailable['websafe'] = self::$fontsWebSafe;
/** /**
* Import des polices de caractères * Import des polices de caractères
@ -368,7 +368,7 @@ class core extends common
// Bordure du contour TinyMCE // Bordure du contour TinyMCE
$css .= '.mce-tinymce{border: 1px solid ' . $this->getData(['admin', 'borderBlockColor']) . '!important;}'; $css .= '.mce-tinymce{border: 1px solid ' . $this->getData(['admin', 'borderBlockColor']) . '!important;}';
// Enregistre la personnalisation // Enregistre la personnalisation
file_put_contents(common::DATA_DIR . 'admin.css', $css); file_put_contents(self::DATA_DIR . 'admin.css', $css);
} }
} }
/** /**
@ -384,8 +384,8 @@ class core extends common
require 'core/module/' . $classPath; require 'core/module/' . $classPath;
} }
// Module // Module
elseif (is_readable(common::MODULE_DIR . $classPath)) { elseif (is_readable(self::MODULE_DIR . $classPath)) {
require common::MODULE_DIR . $classPath; require self::MODULE_DIR . $classPath;
} }
// Librairie // Librairie
elseif (is_readable('core/vendor/' . $classPath)) { elseif (is_readable('core/vendor/' . $classPath)) {
@ -414,23 +414,22 @@ class core extends common
// Sauvegarde la dernière page visitée par l'utilisateur connecté et enregistre l'historique des consultations // Sauvegarde la dernière page visitée par l'utilisateur connecté et enregistre l'historique des consultations
if ( if (
$this->getUser('id') $this->getUser('id')
&& common::$siteContent !== 'home' && self::$siteContent !== 'home'
&& in_array($this->getUrl(0), array_keys($this->getData(['page']))) && in_array($this->getUrl(0), array_keys($this->getData(['page'])))
// Le userId n'est pas celui d'un admis ni le prof du contenu // Le userId n'est pas celui d'un admis ni le prof du contenu
&& ( && (
$this->getUser('group') < common::GROUP_ADMIN $this->getUser('group') < self::GROUP_ADMIN
|| $this->getUser('id') !== $this->getData(['course', common::$siteContent, 'author']) || $this->getUser('id') !== $this->getData(['course', self::$siteContent, 'author'])
) )
) { ) {
// Stocke l'historique des pages vues
$data = is_array($this->getData(['report', $this->getUser('id'), $this->getUrl(0)]))
? array_merge([time()], $this->getData(['report', $this->getUser('id'),$this->getUrl(0)]))
: [time()];
$this->setData(['report', $this->getUser('id'), $this->getUrl(0), $data]);
// Stocke la dernière page vue et sa date de consultation // Stocke la dernière page vue et sa date de consultation
$this->setData(['enrolment', common::$siteContent, $this->getUser('id'), 'lastPageView', $this->getUrl(0)]); $this->setData(['enrolment', self::$siteContent, $this->getUser('id'), 'lastPageView', $this->getUrl(0)]);
$this->setData(['enrolment', common::$siteContent, $this->getUser('id'), 'datePageView', time()]); $this->setData(['enrolment', self::$siteContent, $this->getUser('id'), 'datePageView', time()]);
// Stocke le rapport en CSV
$file = fopen(common::DATA_DIR . common::$siteContent . '/report.csv', 'a+');
fputcsv($file, [$this->getUser('id'), $this->getUrl(0), time()], ';');
fclose($file);
} }
// Journalisation // Journalisation
@ -439,7 +438,7 @@ class core extends common
// Force la déconnexion des membres bannis ou d'une seconde session // Force la déconnexion des membres bannis ou d'une seconde session
if ( if (
$this->getUser('password') === $this->getInput('ZWII_USER_PASSWORD') $this->getUser('password') === $this->getInput('ZWII_USER_PASSWORD')
and ($this->getUser('group') === common::GROUP_BANNED and ($this->getUser('group') === self::GROUP_BANNED
or ($_SESSION['csrf'] !== $this->getData(['user', $this->getUser('id'), 'accessCsrf']) or ($_SESSION['csrf'] !== $this->getData(['user', $this->getUser('id'), 'accessCsrf'])
and $this->getData(['config', 'connect', 'autoDisconnect']) === true) and $this->getData(['config', 'connect', 'autoDisconnect']) === true)
) )
@ -454,7 +453,7 @@ class core extends common
and $this->getUrl(1) !== 'login' and $this->getUrl(1) !== 'login'
and ($this->getUser('password') !== $this->getInput('ZWII_USER_PASSWORD') and ($this->getUser('password') !== $this->getInput('ZWII_USER_PASSWORD')
or ($this->getUser('password') === $this->getInput('ZWII_USER_PASSWORD') or ($this->getUser('password') === $this->getInput('ZWII_USER_PASSWORD')
and $this->getUser('group') < common::GROUP_ADMIN and $this->getUser('group') < self::GROUP_ADMIN
) )
) )
) { ) {
@ -467,11 +466,31 @@ class core extends common
exit(); 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 // Check l'accès à la page
$access = null; $access = null;
if ($this->getData(['page', $this->getUrl(0)]) !== null) { if ($this->getData(['page', $this->getUrl(0)]) !== null) {
if ( if (
$this->getData(['page', $this->getUrl(0), 'group']) === common::GROUP_VISITOR $this->getData(['page', $this->getUrl(0), 'group']) === self::GROUP_VISITOR
or ($this->getUser('password') === $this->getInput('ZWII_USER_PASSWORD') or ($this->getUser('password') === $this->getInput('ZWII_USER_PASSWORD')
// and $this->getUser('group') >= $this->getData(['page', $this->getUrl(0), 'group']) // and $this->getUser('group') >= $this->getData(['page', $this->getUrl(0), 'group'])
// Modification qui tient compte du profil de la page // Modification qui tient compte du profil de la page
@ -492,19 +511,11 @@ class core extends common
and $this->getUser('password') !== $this->getInput('ZWII_USER_PASSWORD') and $this->getUser('password') !== $this->getInput('ZWII_USER_PASSWORD')
) or ($this->getData(['page', $this->getUrl(0), 'disable']) === true ) or ($this->getData(['page', $this->getUrl(0), 'disable']) === true
and $this->getUser('password') === $this->getInput('ZWII_USER_PASSWORD') and $this->getUser('password') === $this->getInput('ZWII_USER_PASSWORD')
and $this->getUser('group') < common::GROUP_EDITOR and $this->getUser('group') < self::GROUP_EDITOR
) )
) { ) {
$access = false; $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;
}
} }
/** /**
@ -526,9 +537,9 @@ class core extends common
$this->getUser('id') && $this->getUser('id') &&
$userId !== $this->getUser('id') && $userId !== $this->getUser('id') &&
$this->getData(['user', $userId, 'accessUrl']) === $this->getUrl() && $this->getData(['user', $userId, 'accessUrl']) === $this->getUrl() &&
array_intersect($t, common::$concurrentAccess) && array_intersect($t, self::$concurrentAccess) &&
//array_intersect($t, common::$accessExclude) !== false && //array_intersect($t, self::$accessExclude) !== false &&
time() < $this->getData(['user', $userId, 'accessTimer']) + common::ACCESS_TIMER time() < $this->getData(['user', $userId, 'accessTimer']) + self::ACCESS_TIMER
) { ) {
$access = false; $access = false;
$accessInfo['userName'] = $this->getData(['user', $userId, 'lastname']) . ' ' . $this->getData(['user', $userId, 'firstname']); $accessInfo['userName'] = $this->getData(['user', $userId, 'lastname']) . ' ' . $this->getData(['user', $userId, 'firstname']);
@ -565,10 +576,10 @@ class core extends common
$inlineScript[] = $this->getData(['page', $this->getUrl(0), 'js']) === null ? '' : $this->getData(['page', $this->getUrl(0), 'js']); $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 // 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']), common::$siteContent) : ''; $contentRight = $this->getData(['page', $this->getUrl(0), 'barRight']) ? $this->getPage($this->getData(['page', $this->getUrl(0), 'barRight']), self::$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']); $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']); $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']), common::$siteContent) : ''; $contentLeft = $this->getData(['page', $this->getUrl(0), 'barLeft']) ? $this->getPage($this->getData(['page', $this->getUrl(0), 'barLeft']), self::$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']); $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']); $inlineScript[] = $this->getData(['page', $this->getData(['page', $this->getUrl(0), 'barLeft']), 'js']) === null ? '' : $this->getData(['page', $this->getData(['page', $this->getUrl(0), 'barLeft']), 'js']);
@ -586,7 +597,7 @@ class core extends common
$this->addOutput([ $this->addOutput([
'title' => $title, 'title' => $title,
'content' => $this->getPage($this->getUrl(0), common::$siteContent), 'content' => $this->getPage($this->getUrl(0), self::$siteContent),
'metaDescription' => $this->getData(['page', $this->getUrl(0), 'metaDescription']), 'metaDescription' => $this->getData(['page', $this->getUrl(0), 'metaDescription']),
'metaTitle' => $this->getData(['page', $this->getUrl(0), 'metaTitle']), 'metaTitle' => $this->getData(['page', $this->getUrl(0), 'metaTitle']),
'typeMenu' => $this->getData(['page', $this->getUrl(0), 'typeMenu']), 'typeMenu' => $this->getData(['page', $this->getUrl(0), 'typeMenu']),
@ -612,7 +623,7 @@ class core extends common
: $this->getData(['page', $this->getUrl(0), 'metaDescription']); : $this->getData(['page', $this->getUrl(0), 'metaDescription']);
// Importe le CSS de la page principale // Importe le CSS de la page principale
$pageContent = $this->getPage($this->getUrl(0), common::$siteContent); $pageContent = $this->getPage($this->getUrl(0), self::$siteContent);
$this->addOutput([ $this->addOutput([
'title' => $title, 'title' => $title,
@ -657,7 +668,7 @@ class core extends common
$output = $module->output; $output = $module->output;
// Check le groupe de l'utilisateur // Check le groupe de l'utilisateur
if ( if (
($module::$actions[$action] === common::GROUP_VISITOR ($module::$actions[$action] === self::GROUP_VISITOR
or ($this->getUser('password') === $this->getInput('ZWII_USER_PASSWORD') or ($this->getUser('password') === $this->getInput('ZWII_USER_PASSWORD')
and $this->getUser('group') >= $module::$actions[$action] and $this->getUser('group') >= $module::$actions[$action]
and $this->getUser('permission', $moduleId, $action) and $this->getUser('permission', $moduleId, $action)
@ -670,10 +681,10 @@ class core extends common
foreach ($_POST as $postId => $postValue) { foreach ($_POST as $postId => $postValue) {
if (is_array($postValue)) { if (is_array($postValue)) {
foreach ($postValue as $subPostId => $subPostValue) { foreach ($postValue as $subPostId => $subPostValue) {
common::$inputBefore[$postId . '_' . $subPostId] = $subPostValue; self::$inputBefore[$postId . '_' . $subPostId] = $subPostValue;
} }
} else { } else {
common::$inputBefore[$postId] = $postValue; self::$inputBefore[$postId] = $postValue;
} }
} }
} }
@ -713,9 +724,9 @@ class core extends common
// Contenu par vue // Contenu par vue
elseif ($output['view']) { elseif ($output['view']) {
// Chemin en fonction d'un module du coeur ou d'un module // Chemin en fonction d'un module du coeur ou d'un module
$modulePath = in_array($moduleId, common::$coreModuleIds) ? 'core/' : ''; $modulePath = in_array($moduleId, self::$coreModuleIds) ? 'core/' : '';
// CSS // CSS
$stylePath = $modulePath . common::MODULE_DIR . $moduleId . '/view/' . $output['view'] . '/' . $output['view'] . '.css'; $stylePath = $modulePath . self::MODULE_DIR . $moduleId . '/view/' . $output['view'] . '/' . $output['view'] . '.css';
if (file_exists($stylePath)) { if (file_exists($stylePath)) {
$this->addOutput([ $this->addOutput([
'style' => file_get_contents($stylePath) 'style' => file_get_contents($stylePath)
@ -728,7 +739,7 @@ class core extends common
} }
// JS // JS
$scriptPath = $modulePath . common::MODULE_DIR . $moduleId . '/view/' . $output['view'] . '/' . $output['view'] . '.js.php'; $scriptPath = $modulePath . self::MODULE_DIR . $moduleId . '/view/' . $output['view'] . '/' . $output['view'] . '.js.php';
if (file_exists($scriptPath)) { if (file_exists($scriptPath)) {
ob_start(); ob_start();
include $scriptPath; include $scriptPath;
@ -737,7 +748,7 @@ class core extends common
]); ]);
} }
// Vue // Vue
$viewPath = $modulePath . common::MODULE_DIR . $moduleId . '/view/' . $output['view'] . '/' . $output['view'] . '.php'; $viewPath = $modulePath . self::MODULE_DIR . $moduleId . '/view/' . $output['view'] . '/' . $output['view'] . '.php';
if (file_exists($viewPath)) { if (file_exists($viewPath)) {
ob_start(); ob_start();
include $viewPath; include $viewPath;
@ -806,7 +817,7 @@ class core extends common
if ($accessInfo['userName']) { if ($accessInfo['userName']) {
$this->addOutput([ $this->addOutput([
'title' => 'Accès verrouillé', '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 { } else {
if ( if (
@ -818,49 +829,22 @@ class core extends common
} else { } else {
$this->addOutput([ $this->addOutput([
'title' => 'Accès interdit', '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'] === '') { } 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); http_response_code(404);
if ( if (
// une page est définie dans la configuration mais dans home
$this->getData(['config', 'page404']) !== 'none' $this->getData(['config', 'page404']) !== 'none'
//and $this->getData(['page', $this->getData(['config', 'page404'])])
) { ) {
// Bascule sur l'acccueil et rediriger
$_SESSION['ZWII_SITE_CONTENT'] = 'home'; $_SESSION['ZWII_SITE_CONTENT'] = 'home';
header('Location:' . helper::baseUrl() . $this->getData(['config', 'page404'])); header('Location:' . helper::baseUrl() . $this->getData(['config', 'page404']));
} else { } else {
// Page par défaut
$this->addOutput([ $this->addOutput([
'title' => 'Page indisponible', '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>')
]); ]);
} }
} }
@ -883,25 +867,25 @@ class core extends common
} }
switch ($this->output['display']) { switch ($this->output['display']) {
// Layout brut // Layout brut
case common::DISPLAY_RAW: case self::DISPLAY_RAW:
echo $this->output['content']; echo $this->output['content'];
break; break;
// Layout vide // Layout vide
case common::DISPLAY_LAYOUT_BLANK: case self::DISPLAY_LAYOUT_BLANK:
require 'core/layout/blank.php'; require 'core/layout/blank.php';
break; break;
// Affichage en JSON // Affichage en JSON
case common::DISPLAY_JSON: case self::DISPLAY_JSON:
header('Content-Type: application/json'); header('Content-Type: application/json');
echo json_encode($this->output['content']); echo json_encode($this->output['content']);
break; break;
// RSS feed // RSS feed
case common::DISPLAY_RSS: case self::DISPLAY_RSS:
header('Content-type: application/rss+xml; charset=UTF-8'); header('Content-type: application/rss+xml; charset=UTF-8');
echo $this->output['content']; echo $this->output['content'];
break; break;
// Layout allégé // Layout allégé
case common::DISPLAY_LAYOUT_LIGHT: case self::DISPLAY_LAYOUT_LIGHT:
ob_start(); ob_start();
require 'core/layout/light.php'; require 'core/layout/light.php';
$content = ob_get_clean(); $content = ob_get_clean();
@ -912,7 +896,7 @@ class core extends common
echo $content; echo $content;
break; break;
// Layout principal // Layout principal
case common::DISPLAY_LAYOUT_MAIN: case self::DISPLAY_LAYOUT_MAIN:
ob_start(); ob_start();
require 'core/layout/main.php'; require 'core/layout/main.php';
$content = ob_get_clean(); $content = ob_get_clean();

View File

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

View File

@ -51,7 +51,7 @@ class common
const ACCESS_TIMER = 1800; const ACCESS_TIMER = 1800;
// Numéro de version // Numéro de version
const ZWII_VERSION = '1.10.04'; const ZWII_VERSION = '1.8.00';
// URL autoupdate // URL autoupdate
const ZWII_UPDATE_URL = 'https://forge.chapril.org/ZwiiCMS-Team/campus-update/raw/branch/master/'; const ZWII_UPDATE_URL = 'https://forge.chapril.org/ZwiiCMS-Team/campus-update/raw/branch/master/';
@ -176,7 +176,6 @@ class common
public static $i18nUI = 'fr_FR'; public static $i18nUI = 'fr_FR';
// Langues de contenu // Langues de contenu
public static $siteContent = 'home'; public static $siteContent = 'home';
public static $languages = [ public static $languages = [
'de' => 'Deutsch', 'de' => 'Deutsch',
'en_EN' => 'English', 'en_EN' => 'English',
@ -225,14 +224,15 @@ class common
'user' => '', 'user' => '',
'language' => '', 'language' => '',
'profil' => '', 'profil' => '',
'enrolment' => '',
'category' => '', 'category' => '',
'enrolment' => '',
]; ];
private $contentFiles = [ private $contentFiles = [
'page' => '', 'page' => '',
'module' => '', 'module' => '',
'theme' => '', 'theme' => '',
'report' => '',
]; ];
public static $fontsWebSafe = [ public static $fontsWebSafe = [
@ -333,7 +333,6 @@ class common
// Déterminé par la session présente // Déterminé par la session présente
self::$siteContent = $_SESSION['ZWII_SITE_CONTENT']; self::$siteContent = $_SESSION['ZWII_SITE_CONTENT'];
} }
// Instanciation de la classe des entrées / sorties // Instanciation de la classe des entrées / sorties
// Les fichiers de configuration // Les fichiers de configuration
foreach ($this->configFiles as $module => $value) { foreach ($this->configFiles as $module => $value) {
@ -344,6 +343,7 @@ class common
$this->initDB($module, self::$siteContent); $this->initDB($module, self::$siteContent);
} }
// Installation fraîche, initialisation de la configuration inexistante // Installation fraîche, initialisation de la configuration inexistante
// Nécessaire pour le constructeur // Nécessaire pour le constructeur
if ($this->user === []) { if ($this->user === []) {
@ -596,9 +596,126 @@ class common
public function setPage($page, $value, $path) public function setPage($page, $value, $path)
{ {
return $this->secure_file_put_contents(self::DATA_DIR . $path . '/content/' . $page . '.html', $value); return file_put_contents(self::DATA_DIR . $path . '/content/' . $page . '.html', $value);
} }
/**
* Fonction pour obtenir les statistiques d'un utilisateur ou d'une page spécifique à partir d'un fichier JSON.
*
* @param string $courseId Identifiant du cours.
* @param string|null $user Nom de l'utilisateur (facultatif).
* @param string|null $page Nom de la page (facultatif).
* @return mixed Statistiques demandées ou null si non trouvées.
*/
public function getReport($courseId, $user = null, $page = null)
{
// Lire les données du fichier JSON
$data = json_decode(file_get_contents(self::DATA_DIR . $courseId . '/report.json'), true);
// Si aucun utilisateur n'est spécifié, retourner toutes les statistiques
if ($user === null) {
return $data['report'];
}
// Si un utilisateur est spécifié mais pas de page, retourner les statistiques de cet utilisateur
if ($page === null) {
return isset($data['report'][$user]) ? $data['report'][$user] : null;
}
// Si à la fois un utilisateur et une page sont spécifiés, retourner les statistiques de cette page pour cet utilisateur
return isset($data['report'][$user][$page]) ? $data['report'][$user][$page] : null;
}
/**
* Fonction pour écrire les données de statistiques dans un fichier JSON.
*
* @param string $courseId Identifiant du cours.
* @param string $user Nom de l'utilisateur.
* @param string $page Nom de la page.
* @param int|null $timestamp Timestamp de la visite (facultatif).
* @return int|false Le nombre d'octets écrits ou false en cas d'erreur.
*/
public function setReport($courseId, $user, $page, $timestamp = null)
{
// Lire les données existantes du fichier
$data = json_decode(file_get_contents(self::DATA_DIR . $courseId . '/report.json'), true);
// Pointeur pour naviguer dans la structure
$pointer =& $data['report'];
// Si la clé utilisateur n'existe pas, la créer
if (!isset($pointer[$user])) {
$pointer[$user] = [];
}
// Si une date est fournie, l'ajouter, sinon ajouter une visite sans date
if ($timestamp !== null) {
// Ajouter la visite avec la date
$pointer[$user][$page][] = $timestamp;
} else {
// Ajouter une visite sans date
$pointer[$user][$page][] = time(); // Timestamp actuel
}
// Écrire les données modifiées dans le fichier
return file_put_contents(self::DATA_DIR . $courseId . '/report.json', json_encode($data, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES));
}
/**
* Fonction pour supprimer toutes les statistiques, les statistiques d'un utilisateur spécifique
* ou les statistiques d'une page spécifique pour tous les utilisateurs.
*
* @param string $courseId Identifiant du cours.
* @param string|null $user Nom de l'utilisateur à supprimer (facultatif).
* @param string|null $page Nom de la page à supprimer (facultatif).
* @return bool Retourne true si les statistiques ont été supprimées avec succès, sinon false.
*/
public function deleteReport($courseId, $user = null, $page = null)
{
// Lire les données existantes du fichier
$data = json_decode(file_get_contents(self::DATA_DIR . $courseId . '/report.json'), true);
$deleted = false; // Variable pour suivre si des statistiques ont été supprimées
// Si aucun utilisateur ni page n'est spécifié, supprimer toutes les statistiques
if ($user === null && $page === null) {
unset($data['report']);
$deleted = true;
} elseif ($user !== null && $page === null) {
// Si un utilisateur est spécifié mais pas de page, supprimer les statistiques de cet utilisateur
if (isset($data['report'][$user])) {
unset($data['report'][$user]);
$deleted = true;
}
} elseif ($user !== null && $page !== null) {
// Si à la fois un utilisateur et une page sont spécifiés, supprimer la page pour cet utilisateur
if (isset($data['report'][$user][$page])) {
unset($data['report'][$user][$page]);
$deleted = true;
}
} elseif ($user === null && $page !== null) {
// Si une page est spécifiée mais pas d'utilisateur, supprimer la page pour tous les utilisateurs
foreach ($data['report'] as $username => &$userStats) {
if (isset($userStats[$page])) {
unset($userStats[$page]);
// Si l'utilisateur n'a plus de pages, le supprimer également
if (empty($userStats)) {
unset($data['report'][$username]);
}
$deleted = true;
}
}
}
// Écrire les données modifiées dans le fichier si au moins une statistique a été supprimée
if ($deleted) {
return file_put_contents(self::DATA_DIR . $courseId . '/report.json', json_encode($data, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES)) !== false;
}
return false; // Aucun utilisateur ou page spécifié, aucune action réalisée
}
/** /**
@ -612,54 +729,13 @@ class common
} }
/**
* Écrit les données dans un fichier avec plusieurs tentatives d'écriture et verrouillage
*
* @param string $filename Le nom du fichier
* @param array $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;
// Convertit les données en chaîne de caractères
$serialized_data = serialize($data);
// Vérifie la longueur des données
$data_length = strlen($serialized_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);
// 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
return true;
}
// Incrémente le compteur de tentatives
$attempts++;
}
// Échec de l'écriture après plusieurs tentatives
return false;
}
public function initDB($module, $path = '') public function initDB($module, $path = '')
{ {
// Instanciation de la classe des entrées / sorties // Instanciation de la classe des entrées / sorties
// Constructeur JsonDB; // Constructeur JsonDB;
$this->dataFiles[$module] = new \Prowebcraft\JsonDb([ $this->dataFiles[$module] = new \Prowebcraft\JsonDb([
'name' => $module . '.json', 'name' => $module . '.json',
'dir' => empty($path) ? self::DATA_DIR : self::DATA_DIR . $path . '/', 'dir' => self::DATA_DIR . $path . '/',
'backup' => file_exists('site/data/.backup') 'backup' => file_exists('site/data/.backup')
]); ]);
@ -1105,9 +1181,8 @@ class common
} }
// Articles du blog // Articles du blog
if ( if (
$this->getData(['page', $parentPageId, 'moduleId']) === 'blog' $this->getData(['page', $parentPageId, 'moduleId']) === 'blog' &&
&& !empty($this->getData(['module', $parentPageId])) !empty($this->getData(['module', $parentPageId]))
&& $this->getData(['module', $parentPageId, 'posts'])
) { ) {
foreach ($this->getData(['module', $parentPageId, 'posts']) as $articleId => $article) { foreach ($this->getData(['module', $parentPageId, 'posts']) as $articleId => $article) {
if ($this->getData(['module', $parentPageId, 'posts', $articleId, 'state']) === true) { if ($this->getData(['module', $parentPageId, 'posts', $articleId, 'state']) === true) {

View File

@ -22,27 +22,29 @@ if (
$this->setData(['core', 'dataVersion', 1700]); $this->setData(['core', 'dataVersion', 1700]);
} }
// Déplacement des
if ( if (
$this->getData(['core', 'dataVersion']) < 1800 $this->getData(['core', 'dataVersion']) < 1800
) { ) {
// Parcourir la structure pour écrire dans les fichiers CSV // Déplace les historiques dans les dossiers des esapaces
foreach ($this->getData(['enrolment']) as $courseId => $users) { // Parcourir les espaces
$filename = self::DATA_DIR . $courseId . '/report.csv'; foreach ($this->getData(['course']) as $courseId => $courseValues) {
$fp = fopen($filename, 'w'); $data = [];
foreach ($users as $userId => $userData) { //Parcourir les participants
$history = array_key_exists('history', $userData) ? $userData['history'] : null; foreach ($this->getData(['user']) as $userId => $userValues) {
// Un historique existe pour ce participant
if (is_array($history)) { $report = $this->getData(['enrolment', $courseId, $userId, 'history']);
foreach ($history as $pageId => $timestamps) { if ( is_array($report)
foreach ($timestamps as $timestamp) { ) {
fputcsv($fp, [$userId, $pageId, $timestamp], ';'); // Ecriture dans un fichier report dans le dossier de l'espace
} $data = array_merge($data, [$userId => $report]);
} // Nettoyage du fichier des inscriptions
} // Ce fichier ne contient que l'id du participant et de la date et de l'id de la dernière page vue
$this->deleteData(['enrolment', $courseId, $userId, 'history']); $this->deleteData(['enrolment', $courseId, $userId, 'history']);
} }
fclose($fp); }
file_put_contents(self::DATA_DIR . $courseId . '/report.json', json_encode(['report' => $data], JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES), LOCK_EX);
} }
$this->setData(['core', 'dataVersion', 1800]); $this->setData(['core', 'dataVersion', 1800]);
} }

View File

@ -556,7 +556,7 @@ class config extends common
) { ) {
// Ajout des lignes dans le .htaccess // Ajout des lignes dans le .htaccess
$fileContent = file_get_contents('.htaccess'); $fileContent = file_get_contents('.htaccess');
$rewriteData = $rewriteData = PHP_EOL .
'# URL rewriting' . PHP_EOL . '# URL rewriting' . PHP_EOL .
'<IfModule mod_rewrite.c>' . PHP_EOL . '<IfModule mod_rewrite.c>' . PHP_EOL .
"\tRewriteEngine on" . PHP_EOL . "\tRewriteEngine on" . PHP_EOL .
@ -565,7 +565,7 @@ class config extends common
"\tRewriteCond %{REQUEST_FILENAME} !-d" . PHP_EOL . "\tRewriteCond %{REQUEST_FILENAME} !-d" . PHP_EOL .
"\tRewriteRule ^(.*)$ index.php?$1 [L]" . PHP_EOL . "\tRewriteRule ^(.*)$ index.php?$1 [L]" . PHP_EOL .
'</IfModule>' . PHP_EOL . '</IfModule>' . PHP_EOL .
'# URL rewriting'; '# URL rewriting' . PHP_EOL;
$fileContent = str_replace('# URL rewriting', $rewriteData, $fileContent); $fileContent = str_replace('# URL rewriting', $rewriteData, $fileContent);
file_put_contents( file_put_contents(
'.htaccess', '.htaccess',
@ -957,19 +957,4 @@ 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') 'value' => template::ico('left')
]); ?> ]); ?>
</div> </div>
<div class="col2 offset9"> <div class="col2 offset8">
<?php echo template::submit('configManageSubmit', [ <?php echo template::submit('configManageSubmit', [
'value' => 'Valider', 'value' => 'Valider',
'ico' => 'check' 'ico' => 'check'

View File

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

View File

@ -26,13 +26,12 @@ class course extends common
'users' => self::GROUP_EDITOR, // fait 'users' => self::GROUP_EDITOR, // fait
'usersAdd' => self::GROUP_EDITOR, //Fait 'usersAdd' => self::GROUP_EDITOR, //Fait
'usersDelete' => self::GROUP_EDITOR, //Fait 'usersDelete' => self::GROUP_EDITOR, //Fait
'usersReportExport' => self::GROUP_EDITOR, //fait 'usersHistoryExport' => self::GROUP_EDITOR, //fait
'userDelete' => self::GROUP_EDITOR, //Fait 'userDelete' => self::GROUP_EDITOR, //Fait
'userReport' => self::GROUP_EDITOR, //Fait 'userReport' => self::GROUP_EDITOR, //Fait
'userReportExport' => self::GROUP_EDITOR, //Fait 'userReportExport' => self::GROUP_EDITOR, //Fait
'backup' => self::GROUP_EDITOR, // Fait 'backup' => self::GROUP_EDITOR, // Fait
'restore' => self::GROUP_EDITOR, //Fait 'restore' => self::GROUP_EDITOR, //Fait
'reset' => self::GROUP_EDITOR,
'clone' => self::GROUP_ADMIN, 'clone' => self::GROUP_ADMIN,
'add' => self::GROUP_ADMIN, 'add' => self::GROUP_ADMIN,
'delete' => self::GROUP_ADMIN, 'delete' => self::GROUP_ADMIN,
@ -105,26 +104,19 @@ class course extends common
? sprintf('%s %s', $this->getData(['user', $this->getData(['course', $courseId, 'author']), 'firstname']), $this->getData(['user', $this->getData(['course', $courseId, 'author']), 'lastname'])) ? sprintf('%s %s', $this->getData(['user', $this->getData(['course', $courseId, 'author']), 'firstname']), $this->getData(['user', $this->getData(['course', $courseId, 'author']), 'lastname']))
: ''; : '';
$categorieUrl = helper::baseUrl() . 'course/swap/' . $courseId; $categorieUrl = helper::baseUrl() . 'course/swap/' . $courseId;
$info = sprintf(' <a href="%s">%s</a><br />Auteur : %s<br />Id : %s<br />', $categorieUrl, $this->getData(['course', $courseId, 'title']), $author, $courseId, ); $info = sprintf(' <a href="%s" target="_blank">%s</a><br />Auteur : %s<br />Id : %s<br />', $categorieUrl, $this->getData(['course', $courseId, 'title']), $author, $courseId, );
$enrolment = sprintf( $enrolment = sprintf(
'Accès : %s<br />Inscription : %s<br />', 'Accès : %s<br />Inscription : %s<br />',
self::$courseAccess[$this->getData(['course', $courseId, 'access'])], self::$courseAccess[$this->getData(['course', $courseId, 'access'])],
self::$courseEnrolment[$this->getData(['course', $courseId, 'enrolment'])] 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[] = [ self::$courses[] = [
$info, $info,
$this->getData(['course', $courseId, 'description']), $this->getData(['course', $courseId, 'description']),
$enrolment, $enrolment,
$users,
template::button('categoryUser' . $courseId, [ template::button('categoryUser' . $courseId, [
'href' => helper::baseUrl() . 'course/manage/' . $courseId, 'href' => helper::baseUrl() . 'course/manage/' . $courseId,
'value' => template::ico('sliders'), 'value' => template::ico('eye'),
'help' => 'Gérer' 'help' => 'Gérer'
]) ])
]; ];
@ -647,10 +639,9 @@ class course extends common
} }
} }
// Liste des inscrits dans le contenu sélectionné. // Liste des inscrits dans le contenu sélectionné.
$users = $this->getData(['enrolment', $courseId]); $users = $this->getData(['enrolment', $courseId]);
// Récupère l'historique des participants
$reports = $this->getReport($courseId); $reports = $this->getReport($courseId);
if (is_array($users)) { if (is_array($users)) {
@ -659,7 +650,7 @@ class course extends common
foreach ($users as $userId => $userValue) { foreach ($users as $userId => $userValue) {
// Compte les rôles valides // Compte les rôles valides
if (isset($profils[$this->getData(['user', $userId, 'group']) . $this->getData(['user', $userId, 'profil'])])) { if (isset ($profils[$this->getData(['user', $userId, 'group']) . $this->getData(['user', $userId, 'profil'])])) {
$profils[$this->getData(['user', $userId, 'group']) . $this->getData(['user', $userId, 'profil'])]++; $profils[$this->getData(['user', $userId, 'group']) . $this->getData(['user', $userId, 'profil'])]++;
} }
@ -690,28 +681,28 @@ class course extends common
} }
// Progression // Progression
$viewPages = array_key_exists($userId, $reports) ? $viewPages = $this->getReport($courseId, $userId) !== null ?
count($reports[$userId]) : count(array_keys($this->getReport($courseId, $userId))) :
0; 0;
// Construction du tableau // Construction du tableau
self::$courseUsers[] = [ self::$courseUsers[] = [
//$userId, //$userId,
$this->getData(['user', $userId, 'firstname']) . ' ' . $this->getData(['user', $userId, 'lastname']), $this->getData(['user', $userId, 'firstname']) . ' ' . $this->getData(['user', $userId, 'lastname']),
array_key_exists('lastPageView', $userValue) && isset($pages[$userValue['lastPageView']]['title']) isset ($pages[$this->getData(['enrolment', $courseId, $userId, 'lastPageView'])]['title'])
? $pages[$userValue['lastPageView']]['title'] ? $pages[$this->getData(['enrolment', $courseId, $userId, 'lastPageView'])]['title']
: '', : '',
array_key_exists('lastPageView', $userValue) $this->getData(['enrolment', $courseId, $userId, 'datePageView'])
? helper::dateUTF8('%d/%m/%Y', $userValue['datePageView']) ? helper::dateUTF8('%d/%m/%Y', $this->getData(['enrolment', $courseId, $userId, 'datePageView']))
: '', : '',
array_key_exists('datePageView', $userValue) $this->getData(['enrolment', $courseId, $userId, 'datePageView'])
? helper::dateUTF8('%H:%M', $userValue['datePageView']) ? helper::dateUTF8('%H:%M', $this->getData(['enrolment', $courseId, $userId, 'datePageView']))
: '', : '',
$this->getData(['user', $userId, 'tags']), $this->getData(['user', $userId, 'tags']),
template::button('userReport' . $userId, [ template::button('userReport' . $userId, [
'href' => helper::baseUrl() . 'course/userReport/' . $courseId . '/' . $userId, 'href' => helper::baseUrl() . 'course/userReport/' . $courseId . '/' . $userId,
'value' => $viewPages ? min(round(($viewPages * 100) / $sumPages, 1), 100) . ' %' : '0%', 'value' => !empty ($reports[$userId]) ? min(round(($viewPages * 100) / $sumPages, 1), 100) . ' %' : '0%',
'disable' => empty($viewPages) 'disable' => empty ($reports[$userId])
]), ]),
template::button('userDelete' . $userId, [ template::button('userDelete' . $userId, [
'class' => 'userDelete buttonRed', 'class' => 'userDelete buttonRed',
@ -761,7 +752,7 @@ class course extends common
// Inscription des utilisateurs cochés // Inscription des utilisateurs cochés
if ( if (
isset($_POST['courseUsersAddSubmit']) isset ($_POST['courseUsersAddSubmit'])
) { ) {
foreach ($_POST as $keyPost => $valuePost) { foreach ($_POST as $keyPost => $valuePost) {
// Exclure les variables post qui ne sont pas des userId et ne traiter que les non inscrits // Exclure les variables post qui ne sont pas des userId et ne traiter que les non inscrits
@ -769,7 +760,7 @@ class course extends common
$this->getData(['user', $keyPost]) !== null $this->getData(['user', $keyPost]) !== null
&& $this->getData(['enrolment', $courseId, $keyPost]) === null && $this->getData(['enrolment', $courseId, $keyPost]) === null
) { ) {
$this->setData(['enrolment', $courseId, $keyPost, 'history', array()]); $this->setData(['enrolment', $courseId, $keyPost, array()]);
} }
} }
} }
@ -817,15 +808,15 @@ class course extends common
foreach ($users as $userId => $userValue) { foreach ($users as $userId => $userValue) {
// Compte les rôles // Compte les rôles
if (isset($profils[$this->getData(['user', $userId, 'group']) . $this->getData(['user', $userId, 'profil'])])) { if (isset ($profils[$this->getData(['user', $userId, 'group']) . $this->getData(['user', $userId, 'profil'])])) {
$profils[$this->getData(['user', $userId, 'group']) . $this->getData(['user', $userId, 'profil'])]++; $profils[$this->getData(['user', $userId, 'group']) . $this->getData(['user', $userId, 'profil'])]++;
} }
// Filtres // Filtres
if ( if (
isset($_POST['courseFilterGroup']) isset ($_POST['courseFilterGroup'])
|| isset($_POST['courseFilterFirstName']) || isset ($_POST['courseFilterFirstName'])
|| isset($_POST['courseFilterLastName']) || isset ($_POST['courseFilterLastName'])
) { ) {
// Groupe et profils // Groupe et profils
@ -911,7 +902,6 @@ class course extends common
/** /**
* Désinscription de tous les utilisateurs * Désinscription de tous les utilisateurs
* Les désinscriptions ne suppriment pas les historiques
*/ */
public function usersDelete() public function usersDelete()
{ {
@ -931,7 +921,7 @@ class course extends common
// Inscription des utilisateurs cochés // Inscription des utilisateurs cochés
if ( if (
isset($_POST['courseUsersDeleteSubmit']) isset ($_POST['courseUsersDeleteSubmit'])
) { ) {
foreach ($_POST as $keyPost => $valuePost) { foreach ($_POST as $keyPost => $valuePost) {
// Exclure les variables post qui ne sont pas des userId et ne traiter que les non inscrits // Exclure les variables post qui ne sont pas des userId et ne traiter que les non inscrits
@ -981,15 +971,15 @@ class course extends common
foreach ($users as $userId => $userValue) { foreach ($users as $userId => $userValue) {
// Compte les rôles // Compte les rôles
if (isset($profils[$this->getData(['user', $userId, 'group']) . $this->getData(['user', $userId, 'profil'])])) { if (isset ($profils[$this->getData(['user', $userId, 'group']) . $this->getData(['user', $userId, 'profil'])])) {
$profils[$this->getData(['user', $userId, 'group']) . $this->getData(['user', $userId, 'profil'])]++; $profils[$this->getData(['user', $userId, 'group']) . $this->getData(['user', $userId, 'profil'])]++;
} }
// Filtres // Filtres
if ( if (
isset($_POST['courseFilterGroup']) isset ($_POST['courseFilterGroup'])
|| isset($_POST['courseFilterFirstName']) || isset ($_POST['courseFilterFirstName'])
|| isset($_POST['courseFilterLastName']) || isset ($_POST['courseFilterLastName'])
) { ) {
// Groupe et profils // Groupe et profils
@ -1047,47 +1037,6 @@ 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 * Traitement du changement de langue
*/ */
@ -1220,17 +1169,16 @@ class course extends common
$userId = $this->getUrl(3); $userId = $this->getUrl(3);
$h = $this->getReport($courseId, $userId); $h = $this->getReport($courseId, $userId);
$h = $h[$userId];
// Inversion des clés et des valeurs // Inversion des clés et des valeurs
$report = array(); $history = array();
foreach ($h as $key => $values) { foreach ($h as $key => $values) {
foreach ($values as $value) { foreach ($values as $value) {
$report[$value] = $key; $history[$value] = $key;
} }
} }
ksort($report); ksort($history);
// Liste des pages contenues dans cet espace et exclure les barres et les pages masquées // Liste des pages contenues dans cet espace et exclure les barres et les pages masquées
$p = json_decode(file_get_contents(self::DATA_DIR . $courseId . '/page.json'), true); $p = json_decode(file_get_contents(self::DATA_DIR . $courseId . '/page.json'), true);
@ -1246,8 +1194,8 @@ class course extends common
$topTime = 0; $topTime = 0;
$lastView = 0; $lastView = 0;
foreach ($report as $time => $pageId) { foreach ($history as $time => $pageId) {
if (isset($pages[$pageId]['title'])) { if (isset ($pages[$pageId]['title'])) {
$lastView = ($lastView === 0) ? $time : $lastView; $lastView = ($lastView === 0) ? $time : $lastView;
$diff = $time - $lastView; $diff = $time - $lastView;
self::$userReport[] = [ self::$userReport[] = [
@ -1263,8 +1211,8 @@ class course extends common
]; ];
} }
$lastView = $time; $lastView = $time;
$floorTime = isset($floorTime) && $floorTime < $time ? $floorTime : $time; $floorTime = isset ($floorTime) && $floorTime < $time ? $floorTime : $time;
$topTime = isset($topTime) && $topTime > $time ? $topTime : $time; $topTime = isset ($topTime) && $topTime > $time ? $topTime : $time;
} }
} }
@ -1304,7 +1252,7 @@ class course extends common
} }
public function usersReportExport() public function usersHistoryExport()
{ {
$courseId = $this->getUrl(2); $courseId = $this->getUrl(2);
@ -1349,34 +1297,21 @@ class course extends common
mkdir(self::FILE_DIR . 'source/' . $courseId . '/export/'); mkdir(self::FILE_DIR . 'source/' . $courseId . '/export/');
} }
$filename = self::FILE_DIR . 'source/' . $courseId . '/export/' . '/synthèse' . helper::dateUTF8('%Y%m%d', time()) . '.csv'; $filename = self::FILE_DIR . 'source/' . $courseId . '/export/' . '/synthèse' . helper::dateUTF8('%Y%m%d', time()) . '.csv';
$reports = $this->getReport($courseId);
foreach ($users as $userId => $userValue) { foreach ($users as $userId => $userValue) {
// Date et heure de la dernière page vue
// Compatibilité anciennes versions
if (
$this->getData(['enrolment', $courseId, $userId, 'lastPageView']) === null
or $this->getData(['enrolment', $courseId, $userId, 'datePageView']) === null
) {
if (!empty($userValue['history'])) {
$maxTime = max($userValue['history']);
$lastPageId = array_search($maxTime, $userValue['history']);
$this->setData(['enrolment', $courseId, $userId, 'lastPageView', $lastPageId]);
$this->setData(['enrolment', $courseId, $userId, 'datePageView', $maxTime]);
}
}
// Progression // Progression
$viewPages = $this->getData(['enrolment', $courseId, $userId, 'history']) !== null ? $viewPages = $reports[$userId] != null
count(array_keys($this->getData(['enrolment', $courseId, $userId, 'history']))) : ? count($reports[$userId])
0; : 0;
// Construction du tableau // Construction du tableau
self::$courseUsers[] = [ self::$courseUsers[] = [
$userId, $userId,
$this->getData(['user', $userId, 'firstname']), $this->getData(['user', $userId, 'firstname']),
$this->getData(['user', $userId, 'lastname']), $this->getData(['user', $userId, 'lastname']),
isset($pages[$this->getData(['enrolment', $courseId, $userId, 'lastPageView'])]) isset ($pages[$this->getData(['enrolment', $courseId, $userId, 'lastPageView'])])
? $pages[$this->getData(['enrolment', $courseId, $userId, 'lastPageView'])] ? $pages[$this->getData(['enrolment', $courseId, $userId, 'lastPageView'])]
: $this->getData(['enrolment', $courseId, $userId, 'lastPageView']) . ' (supprimée)', : $this->getData(['enrolment', $courseId, $userId, 'lastPageView']) . ' (supprimée)',
helper::dateUTF8('%d/%d/%Y', $this->getData(['enrolment', $courseId, $userId, 'datePageView'])), helper::dateUTF8('%d/%d/%Y', $this->getData(['enrolment', $courseId, $userId, 'datePageView'])),
@ -1427,18 +1362,17 @@ class course extends common
} }
// Traitement de l'historique // Traitement de l'historique
$h = $this->getReport($courseId); $h = $this->getReport($courseId, $userId);
$h = $h[$userId];
// Inversion des clés et des valeurs // Inversion des clés et des valeurs
$report = array(); $history = array();
foreach ($h as $key => $values) { foreach ($h as $key => $values) {
foreach ($values as $value) { foreach ($values as $value) {
$report[$value] = $key; $history[$value] = $key;
} }
} }
ksort($report); ksort($history);
// Liste des pages contenues dans cet espace et exclure les barres et les pages masquées // Liste des pages contenues dans cet espace et exclure les barres et les pages masquées
$p = json_decode(file_get_contents(self::DATA_DIR . $courseId . '/page.json'), true); $p = json_decode(file_get_contents(self::DATA_DIR . $courseId . '/page.json'), true);
@ -1452,8 +1386,8 @@ class course extends common
$lastView = 0; $lastView = 0;
foreach ($report as $time => $pageId) { foreach ($history as $time => $pageId) {
if (isset($pages[$pageId]['title'])) { if (isset ($pages[$pageId]['title'])) {
$lastView = ($lastView === 0) ? $time : $lastView; $lastView = ($lastView === 0) ? $time : $lastView;
$diff = $time - $lastView; $diff = $time - $lastView;
self::$userReport[] = [ self::$userReport[] = [
@ -1463,8 +1397,8 @@ class course extends common
($diff < 1800) ? sprintf("%d' %d''", floor($diff / 60), $diff % 60) : "Non significatif", ($diff < 1800) ? sprintf("%d' %d''", floor($diff / 60), $diff % 60) : "Non significatif",
]; ];
$lastView = $time; $lastView = $time;
$floorTime = isset($floorTime) && $floorTime < $time ? $floorTime : $time; $floorTime = isset ($floorTime) && $floorTime < $time ? $floorTime : $time;
$topTime = isset($topTime) && $topTime > $time ? $topTime : $time; $topTime = isset ($topTime) && $topTime > $time ? $topTime : $time;
} }
} }
@ -1591,7 +1525,6 @@ class course extends common
/** /**
* Désinscription d'un participant * Désinscription d'un participant
* La désinscription ne supprime pas les historiques,
*/ */
public function unsuscribe() public function unsuscribe()
{ {
@ -1638,17 +1571,17 @@ class course extends common
// Participants avec historiques // Participants avec historiques
$enrolment = $this->getData(['enrolment', $courseId]); $enrolment = $this->getData(['enrolment', $courseId]);
// Générer un fichier dans le dossier de l'espace // Générer un fichier dans le dossier de l'espace
$this->secure_file_put_contents(self::DATA_DIR . $courseId . '/enrolment.json', json_encode([$courseId => $enrolment], JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES | JSON_PRETTY_PRINT)); file_put_contents(self::DATA_DIR . $courseId . '/enrolment.json', json_encode([$courseId => $enrolment], JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES | JSON_PRETTY_PRINT));
// Idem pour les données du cours // Idem pour les données du cours
$course = $this->getData(['course', $courseId]); $course = $this->getData(['course', $courseId]);
// Générer un fichier dans le dossier de l'espace // Générer un fichier dans le dossier de l'espace
$this->secure_file_put_contents(self::DATA_DIR . $courseId . '/course.json', json_encode([$courseId => $course], JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES | JSON_PRETTY_PRINT)); file_put_contents(self::DATA_DIR . $courseId . '/course.json', json_encode([$courseId => $course], JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES | JSON_PRETTY_PRINT));
// Idem pour la catégorie // Idem pour la catégorie
$category = $this->getData(['category', $this->getData(['course', $courseId, 'category'])]); $category = $this->getData(['category', $this->getData(['course', $courseId, 'category'])]);
// Générer un fichier dans le dossier de l'espace // Générer un fichier dans le dossier de l'espace
$this->secure_file_put_contents(self::DATA_DIR . $courseId . '/category.json', json_encode([$this->getData(['course', $courseId, 'category']) => $category], JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES | JSON_PRETTY_PRINT)); file_put_contents(self::DATA_DIR . $courseId . '/category.json', json_encode([$this->getData(['course', $courseId, 'category']) => $category], JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES | JSON_PRETTY_PRINT));
// Génère une archive ZIP // Génère une archive ZIP
@ -1898,9 +1831,7 @@ class course extends common
'enrolment', 'enrolment',
$courseId, $courseId,
$userId, $userId,
[ []
'history' => [],
]
]); ]);
} }
@ -1936,50 +1867,6 @@ class course extends common
return $r; return $r;
} }
/**
* Lit le contenu des fichiers de traces au format CS et renvoie un tableau associatif
*/
private function getReport($courseId, $userId = null)
{
$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");
$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);
// Trier les timestamps
foreach ($data as &$userData) {
foreach ($userData as &$pageData) {
sort($pageData);
}
}
}
// Afficher le JSON;
return $data;
}
} }

View File

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

View File

@ -37,7 +37,7 @@
</div> </div>
</div> </div>
<?php if ($module::$courses): ?> <?php if ($module::$courses): ?>
<?php echo template::table([4, 3, 3, 1, 1], $module::$courses, ['Titre court', 'Description', 'Inscription', '', '',], ['id' => 'dataTables']); ?> <?php echo template::table([4, 4, 3, 1], $module::$courses, ['Titre court', 'Description', 'Inscription', '',], ['id' => 'dataTables']); ?>
<?php else: ?> <?php else: ?>
<?php echo template::speech('Aucun espace'); ?> <?php echo template::speech('Aucun espace'); ?>
<?php endif; ?> <?php endif; ?>

View File

@ -21,14 +21,3 @@ $(".courseDelete").on("click", function () {
$(location).attr("href", _this.attr("href")); $(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,16 +18,6 @@
]); ?> ]); ?>
</div> </div>
<?php endif; ?> <?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): ?> <?php if ($this->getUser('permission', 'course', 'backup') === true): ?>
<div class="col2"> <div class="col2">
<?php echo template::button('courseManageDownload' . $this->getUrl(2), [ <?php echo template::button('courseManageDownload' . $this->getUrl(2), [
@ -48,6 +38,7 @@
<?php endif; ?> <?php endif; ?>
<?php if ($this->getUser('permission', 'course', 'edit') === true): ?> <?php if ($this->getUser('permission', 'course', 'edit') === true): ?>
<div class="col2"> <div class="col2">
<?php echo template::button('courseManageEdit' . $this->getUrl(2), [ <?php echo template::button('courseManageEdit' . $this->getUrl(2), [
'href' => helper::baseUrl() . 'course/edit/' . $this->getUrl(2), 'href' => helper::baseUrl() . 'course/edit/' . $this->getUrl(2),
'value' => 'Éditer', 'value' => 'Éditer',
@ -55,8 +46,18 @@
]); ?> ]); ?>
</div> </div>
<?php endif; ?> <?php endif; ?>
</div> <?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"> <div class="row">
<div class="col12"> <div class="col12">
<div class="block"> <div class="block">

View File

@ -1,6 +1,6 @@
<div class="row"> <div class="row">
<div class="col1"> <div class="col1">
<?php echo template::button('courseUserHistoryBack', [ <?php echo template::button('courseuserReportBack', [
'class' => 'buttonGrey', 'class' => 'buttonGrey',
'href' => helper::baseUrl() . 'course/users/' . $this->getUrl(2), 'href' => helper::baseUrl() . 'course/users/' . $this->getUrl(2),
'value' => template::ico('left') 'value' => template::ico('left')
@ -8,7 +8,7 @@
</div> </div>
<div class="col1 offset10"> <div class="col1 offset10">
<?php echo template::button('userDeleteAll', [ <?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'), 'value' => template::ico('download'),
'help' => 'Exporter', 'help' => 'Exporter',
]) ?> ]) ?>

View File

@ -2,7 +2,7 @@
<div class="col1"> <div class="col1">
<?php echo template::button('courseUserBack', [ <?php echo template::button('courseUserBack', [
'class' => 'buttonGrey', 'class' => 'buttonGrey',
'href' => helper::baseUrl() . 'course/' . $this->getUrl(2), 'href' => helper::baseUrl() . 'course/manage/' . $this->getUrl(2),
'value' => template::ico('left') 'value' => template::ico('left')
]); ?> ]); ?>
</div> </div>

View File

@ -17,6 +17,10 @@
* admin.css * admin.css
*/ */
tr { #courseUserAddSelectAll {
cursor: pointer; color: lightgreen;
}
#courseUserAddSelectNone {
color: lightcoral;
} }

View File

@ -13,13 +13,6 @@
$(document).ready((function () { $(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() { $('#courseUserAddSelectAll').on('click', function() {
$('.checkboxSelect').prop('checked', true); $('.checkboxSelect').prop('checked', true);
saveCheckboxState(); saveCheckboxState();

View File

@ -9,13 +9,13 @@
</div> </div>
<div class="col1 offset8"> <div class="col1 offset8">
<?php echo template::button('courseUserAddSelectAll', [ <?php echo template::button('courseUserAddSelectAll', [
'value' => template::ico('square-check'), 'value' => template::ico('check'),
'help' => 'Tout sélectionner' 'help' => 'Tout sélectionner'
]); ?> ]); ?>
</div> </div>
<div class="col1"> <div class="col1">
<?php echo template::button('courseUserAddSelectNone', [ <?php echo template::button('courseUserAddSelectNone', [
'value' => template::ico('square-check-empty'), 'value' => template::ico('cancel'),
'help' => 'Tout désélectionner' 'help' => 'Tout désélectionner'
]); ?> ]); ?>
</div> </div>

View File

@ -21,6 +21,10 @@
background-color: rgba(217, 95, 78, 1); background-color: rgba(217, 95, 78, 1);
} }
tr { #courseUserDeleteSelectAll {
cursor: pointer; color: lightgreen;
}
#courseUserDeleteSelectNone {
color: lightcoral;
} }

View File

@ -13,13 +13,6 @@
$(document).ready((function () { $(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
});
});
$('#courseUserDeleteSelectAll').on('click', function () { $('#courseUserDeleteSelectAll').on('click', function () {
$('.checkboxSelect').prop('checked', true); $('.checkboxSelect').prop('checked', true);
saveCheckboxState(); saveCheckboxState();

View File

@ -9,13 +9,13 @@
</div> </div>
<div class="col1 offset8"> <div class="col1 offset8">
<?php echo template::button('courseUserDeleteSelectAll', [ <?php echo template::button('courseUserDeleteSelectAll', [
'value' => template::ico('square-check'), 'value' => template::ico('check'),
'help' => 'Tout sélectionner' 'help' => 'Tout sélectionner'
]); ?> ]); ?>
</div> </div>
<div class="col1"> <div class="col1">
<?php echo template::button('courseUserDeleteSelectNone', [ <?php echo template::button('courseUserDeleteSelectNone', [
'value' => template::ico('square-check-empty'), 'value' => template::ico('cancel'),
'help' => 'Tout désélectionner' 'help' => 'Tout désélectionner'
]); ?> ]); ?>
</div> </div>

View File

@ -387,7 +387,7 @@ class install extends common
'</IfModule>' . PHP_EOL . '</IfModule>' . PHP_EOL .
'# URL rewriting' . PHP_EOL; '# URL rewriting' . PHP_EOL;
$fileContent = str_replace('# URL rewriting', $rewriteData, $fileContent); $fileContent = str_replace('# URL rewriting', $rewriteData, $fileContent);
$success = $this->secure_file_put_contents( $success = file_put_contents(
'.htaccess', '.htaccess',
$fileContent $fileContent
); );

View File

@ -252,8 +252,7 @@ class init extends common
'usersDelete' => false, 'usersDelete' => false,
'edit' => false, 'edit' => false,
'backup' => false, 'backup' => false,
'restore' => false, 'restore' => false
'reset' => false,
], ],
'folder' => [ 'folder' => [
'create' => false, 'create' => false,
@ -349,8 +348,7 @@ class init extends common
'usersDelete' => false, 'usersDelete' => false,
'edit' => false, 'edit' => false,
'backup' => false, 'backup' => false,
'restore' => false, 'restore' => false
'reset' => false,
], ],
'folder' => [ 'folder' => [
'create' => false, 'create' => false,
@ -451,8 +449,7 @@ class init extends common
'usersDelete' => false, 'usersDelete' => false,
'edit' => false, 'edit' => false,
'backup' => false, 'backup' => false,
'restore' => false, 'restore' => false
'reset' => false,
], ],
'folder' => [ 'folder' => [
'create' => false, 'create' => false,
@ -549,8 +546,7 @@ class init extends common
'usersDelete' => true, 'usersDelete' => true,
'edit' => true, 'edit' => true,
'backup' => true, 'backup' => true,
'restore' => true, 'restore' => true
'reset' => true,
], ],
'folder' => [ 'folder' => [
'create' => true, 'create' => true,
@ -967,6 +963,7 @@ class init extends common
] ]
] ]
], ],
'report' => []
]; ];
public static $siteContent = [ public static $siteContent = [

View File

@ -99,7 +99,7 @@ class language extends common
is_array($descripteur['language'][$lang]) is_array($descripteur['language'][$lang])
) { ) {
if ($this->setData(['language', $lang, $descripteur['language'][$lang]])) { if ($this->setData(['language', $lang, $descripteur['language'][$lang]])) {
$success = $this->secure_file_put_contents(self::I18N_DIR . $lang . '.json', json_encode($languageData, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES | JSON_PRETTY_PRINT)); $success = 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; $success = is_int($success) ? true : false;
} }
} }

View File

@ -85,23 +85,12 @@ class page extends common
*/ */
public function duplicate() 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 // Adresse sans le token
$page = $this->getUrl(2); $page = $this->getUrl(2);
// La page n'existe pas // La page n'existe pas
if ( if (
$this->getUser('permission', __CLASS__, __FUNCTION__) !== true $this->getUser('permission', __CLASS__, __FUNCTION__) !== true ||
|| $this->getData(['page', $page]) === null $this->getData(['page', $page]) === null
) { ) {
// Valeurs en sortie // Valeurs en sortie
$this->addOutput([ $this->addOutput([
@ -129,7 +118,7 @@ class page extends common
// Valeurs en sortie // Valeurs en sortie
$this->addOutput([ $this->addOutput([
'redirect' => helper::baseUrl() . 'page/edit/' . $pageId . '/' . self::$siteContent, 'redirect' => helper::baseUrl() . 'page/edit/' . $pageId,
'notification' => $notification, 'notification' => $notification,
'state' => true 'state' => true
]); ]);
@ -142,19 +131,7 @@ class page extends common
*/ */
public function add() public function add()
{ {
// La session ne correspond pas au site ouvert dans cet onglet if ($this->getUser('permission', __CLASS__, __FUNCTION__) !== true) {
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 // Valeurs en sortie
$this->addOutput([ $this->addOutput([
'access' => false 'access' => false
@ -221,24 +198,12 @@ class page extends common
*/ */
public function delete() 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 // $url prend l'adresse sans le token
$page = $this->getUrl(2); $page = $this->getUrl(2);
// La page n'existe pas // La page n'existe pas
if ( if (
$this->getUser('permission', __CLASS__, __FUNCTION__) !== true $this->getUser('permission', __CLASS__, __FUNCTION__) !== true ||
|| $this->getData(['page', $page]) === null $this->getData(['page', $page]) === null
) { ) {
// Valeurs en sortie // Valeurs en sortie
$this->addOutput([ $this->addOutput([
@ -299,7 +264,7 @@ class page extends common
elseif ($this->getHierarchy($page, null)) { elseif ($this->getHierarchy($page, null)) {
// Valeurs en sortie // Valeurs en sortie
$this->addOutput([ $this->addOutput([
'redirect' => helper::baseUrl() . 'page/edit/' . $page . '/' . self::$siteContent, 'redirect' => helper::baseUrl() . 'page/edit/' . $page,
'notification' => helper::translate('Impossible de supprimer une page contenant des pages enfants') 'notification' => helper::translate('Impossible de supprimer une page contenant des pages enfants')
]); ]);
} }
@ -339,24 +304,10 @@ class page extends common
*/ */
public function edit() 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 // La page n'existe pas
if ( if (
$this->getUser('permission', __CLASS__, __FUNCTION__) !== true $this->getUser('permission', __CLASS__, __FUNCTION__) !== true ||
|| $this->getData(['page', $this->getUrl(2)]) === null $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 // Valeurs en sortie
$this->addOutput([ $this->addOutput([
@ -409,16 +360,16 @@ class page extends common
} }
} }
// Met à jour les historiques des utilisateurs // Met à jour les historiques des utilisateurs
foreach ($this->getData(['enrolment', self::$siteContent]) as $userId => $userData) { foreach ($this->getReport(self::$siteContent) as $userId => $userData) {
// Vérifier si l'utilisateur a un historique // Vérifier si l'utilisateur a un historique
if ( if (
isset($userData["history"]) is_array($userData)
&& isset($userData['history'][$this->getUrl(2)]) && array_key_exists($userId, $userData)
) { ) {
// Remplacer l'ancienne ID par la nouvelle // Remplacer l'ancienne ID par la nouvelle
$datas = $this->getData(['enrolment', self::$siteContent, $userId, 'history', $this->getUrl(2)]); $datas = $this->getReport(self::$siteContent, $userId, $this->getUrl(2));
$this->setData(['enrolment', self::$siteContent, $userId, 'history', $pageId, $datas]); $this->setReport(self::$siteContent, $userId, $pageId, $datas);
$this->deleteData(['enrolment', self::$siteContent, $userId, 'history', $this->getUrl(2)]); $this->deleteReport(self::$siteContent, $userId, $this->getUrl(2));
} }
// Mettre à jour la dernière page vue si nécessaire // Mettre à jour la dernière page vue si nécessaire
if ($this->getData(['enrolment', self::$siteContent, $userId, 'lastPageView']) === $this->getUrl(2)) { if ($this->getData(['enrolment', self::$siteContent, $userId, 'lastPageView']) === $this->getUrl(2)) {
@ -683,7 +634,7 @@ class page extends common
// Valeurs en sortie // Valeurs en sortie
$this->addOutput([ $this->addOutput([
'notification' => helper::translate('Modifications enregistrées'), 'notification' => helper::translate('Modifications enregistrées'),
'redirect' => helper::baseUrl() . 'page/edit/' . $this->getUrl(2) . '/' . self::$siteContent, 'redirect' => helper::baseUrl() . 'page/edit/' . $this->getUrl(2),
'state' => true 'state' => true
]); ]);
} }
@ -718,7 +669,7 @@ class page extends common
// Valeurs en sortie // Valeurs en sortie
$this->addOutput([ $this->addOutput([
'notification' => helper::translate('Modifications enregistrées'), 'notification' => helper::translate('Modifications enregistrées'),
'redirect' => helper::baseUrl() . 'page/edit/' . $this->getUrl(2) . '/' . self::$siteContent, 'redirect' => helper::baseUrl() . 'page/edit/' . $this->getUrl(2),
'state' => true 'state' => true
]); ]);
} }
@ -734,16 +685,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 * 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 string tableau associatif des pages dans le menu * @return array tableau associatif des pages dans le menu
*/ */
public function getPageInfo() public function getPageInfo()
{ {
$p = $this->getData(['page']); $p = $this->getData(['page']);
$d = array_map(function ($d) { $d = array_map(function ($d) {
unset ($d["css"], $d["js"]); unset($d["css"], $d["js"]);
return $d; return $d;
}, $p); }, $p);
return json_encode($d); return json_encode($d);
}
}
} }

View File

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

View File

@ -19,14 +19,14 @@
<div class="col1 offset6"> <div class="col1 offset6">
<?php echo template::button('pageEditDelete', [ <?php echo template::button('pageEditDelete', [
'class' => 'buttonRed', 'class' => 'buttonRed',
'href' => helper::baseUrl() . 'page/delete/' . $this->getUrl(2) . '/' . self::$siteContent, 'href' => helper::baseUrl() . 'page/delete/' . $this->getUrl(2),
'value' => template::ico('trash'), 'value' => template::ico('trash'),
'help' => 'Effacer la page' 'help' => 'Effacer la page'
]); ?> ]); ?>
</div> </div>
<div class="col1"> <div class="col1">
<?php echo template::button('pageEditDuplicate', [ <?php echo template::button('pageEditDuplicate', [
'href' => helper::baseUrl() . 'page/duplicate/' . $this->getUrl(2) . '/' . self::$siteContent, 'href' => helper::baseUrl() . 'page/duplicate/' . $this->getUrl(2),
'value' => template::ico('clone'), 'value' => template::ico('clone'),
'help' => 'Dupliquer la page' 'help' => 'Dupliquer la page'
]); ?> ]); ?>

View File

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

View File

@ -19,7 +19,6 @@ class user extends common
public static $actions = [ public static $actions = [
'add' => self::GROUP_ADMIN, 'add' => self::GROUP_ADMIN,
'delete' => self::GROUP_ADMIN, 'delete' => self::GROUP_ADMIN,
'usersDelete' => self::GROUP_ADMIN,
'import' => self::GROUP_ADMIN, 'import' => self::GROUP_ADMIN,
'index' => self::GROUP_ADMIN, 'index' => self::GROUP_ADMIN,
'template' => self::GROUP_ADMIN, 'template' => self::GROUP_ADMIN,
@ -230,145 +229,6 @@ 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 * Édition
*/ */
@ -851,28 +711,8 @@ class user extends common
// Droit d'intervenir sur tous les espaces // Droit d'intervenir sur tous les espaces
'tutor' => $this->getInput('profilEditCourseTutor', helper::FILTER_BOOLEAN), 'tutor' => $this->getInput('profilEditCourseTutor', helper::FILTER_BOOLEAN),
// Droit d'accéder à la fenêtre de gestion pour tous les éditeurs et plus // Droit d'accéder à la fenêtre de gestion pour tous les éditeurs et plus
'index' => $this->getInput('profilEditCourseUsers', helper::FILTER_BOOLEAN) 'index' => $this->getUser('group') >= self::GROUP_EDITOR,
|| $this->getInput('profilEditCourseUserHistory', helper::FILTER_BOOLEAN) 'manage' => $this->getUser('group') >= self::GROUP_EDITOR,
|| $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 // Droits spécifiques
'users' => $this->getInput('profilEditCourseUsers', helper::FILTER_BOOLEAN), 'users' => $this->getInput('profilEditCourseUsers', helper::FILTER_BOOLEAN),
'userHistory' => $this->getInput('profilEditCourseUserHistory', helper::FILTER_BOOLEAN), 'userHistory' => $this->getInput('profilEditCourseUserHistory', helper::FILTER_BOOLEAN),
@ -884,7 +724,6 @@ class user extends common
'edit' => $this->getInput('profilEditCourseEdit', helper::FILTER_BOOLEAN), 'edit' => $this->getInput('profilEditCourseEdit', helper::FILTER_BOOLEAN),
'backup' => $this->getInput('profilEditCourseBackup', helper::FILTER_BOOLEAN), 'backup' => $this->getInput('profilEditCourseBackup', helper::FILTER_BOOLEAN),
'restore' => $this->getInput('profilEditCourseRestore', helper::FILTER_BOOLEAN), 'restore' => $this->getInput('profilEditCourseRestore', helper::FILTER_BOOLEAN),
'reset' => $this->getInput('profilEditCourseReset', helper::FILTER_BOOLEAN),
] ]
]; ];
@ -1066,8 +905,7 @@ class user extends common
|| $this->getInput('profilAddCourseUsersDelete', helper::FILTER_BOOLEAN) || $this->getInput('profilAddCourseUsersDelete', helper::FILTER_BOOLEAN)
|| $this->getInput('profilAddCourseEdit', helper::FILTER_BOOLEAN) || $this->getInput('profilAddCourseEdit', helper::FILTER_BOOLEAN)
|| $this->getInput('profilAddCourseBackup', 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 // La suite
'users' => $this->getInput('profilAddCourseUsers', helper::FILTER_BOOLEAN), 'users' => $this->getInput('profilAddCourseUsers', helper::FILTER_BOOLEAN),
'userHistory' => $this->getInput('profilAddCourseUserHistory', helper::FILTER_BOOLEAN), 'userHistory' => $this->getInput('profilAddCourseUserHistory', helper::FILTER_BOOLEAN),
@ -1079,7 +917,6 @@ class user extends common
'edit' => $this->getInput('profilAddCourseEdit', helper::FILTER_BOOLEAN), 'edit' => $this->getInput('profilAddCourseEdit', helper::FILTER_BOOLEAN),
'backup' => $this->getInput('profilAddCourseBackup', helper::FILTER_BOOLEAN), 'backup' => $this->getInput('profilAddCourseBackup', helper::FILTER_BOOLEAN),
'restore' => $this->getInput('profilAddCourseRestore', helper::FILTER_BOOLEAN), 'restore' => $this->getInput('profilAddCourseRestore', helper::FILTER_BOOLEAN),
'reset' => $this->getInput('profilAddCourseReset', helper::FILTER_BOOLEAN),
] ]
]; ];

View File

@ -13,23 +13,15 @@
'value' => template::ico('help'), 'value' => template::ico('help'),
'class' => 'buttonHelp', 'class' => 'buttonHelp',
'help' => 'Consulter l\'aide en ligne' 'help' => 'Consulter l\'aide en ligne'
]);*/ ?> ]);*/?>
</div> </div>
<div class="col1 offset6"> <div class="col1 offset7">
<?php echo template::button('userImport', [ <?php echo template::button('userImport', [
'href' => helper::baseUrl() . 'user/import', 'href' => helper::baseUrl() . 'user/import',
'value' => template::ico('users'), 'value' => template::ico('upload'),
'help' => 'Importer des utilisateurs en masse' 'help' => 'Importer des utilisateurs en masse'
]); ?> ]); ?>
</div> </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"> <div class="col1">
<?php echo template::button('userGroup', [ <?php echo template::button('userGroup', [
'href' => helper::baseUrl() . 'user/profil', 'href' => helper::baseUrl() . 'user/profil',
@ -68,4 +60,4 @@
</div> </div>
</div> </div>
<?php echo template::formClose(); ?> <?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,9 +205,6 @@
<div class="col3"> <div class="col3">
<?php echo template::checkbox('profilAddCourseUsersDelete', true, 'Désinscrire en masse'); ?> <?php echo template::checkbox('profilAddCourseUsersDelete', true, 'Désinscrire en masse'); ?>
</div> </div>
<div class="col3">
<?php echo template::checkbox('profilAddCourseReset', true, 'Réinitialiser un espace'); ?>
</div>
</div> </div>
</div> </div>
</div> </div>

View File

@ -54,19 +54,6 @@ $(document).ready(function () {
$(".containerModule").slideDown(); $(".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 // À 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 () { $("#profilEditFileManager").change(function () {
if (!$(this).is(':checked')) { if (!$(this).is(':checked')) {
@ -131,20 +118,4 @@ $(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,11 +307,6 @@
'checked' => $this->getData(['profil', $this->getUrl(2), $this->getUrl(3), 'course', 'usersDelete']), 'checked' => $this->getData(['profil', $this->getUrl(2), $this->getUrl(3), 'course', 'usersDelete']),
]); ?> ]); ?>
</div> </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>

View File

@ -1,26 +0,0 @@
/**
* 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

@ -1,100 +0,0 @@
/**
* 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

@ -1,55 +0,0 @@
<?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

@ -1,7 +1,6 @@
@charset "UTF-8"; @charset "UTF-8";
.zwiico-plus-circled:before { content: '\2191'; } /* '↑' */ .zwiico-plus-circled:before { content: '\2191'; } /* '↑' */
.zwiico-square-check:before { content: '\e800'; } /* '' */
.zwiico-plus:before { content: '\e801'; } /* '' */ .zwiico-plus:before { content: '\e801'; } /* '' */
.zwiico-cancel:before { content: '\e802'; } /* '' */ .zwiico-cancel:before { content: '\e802'; } /* '' */
.zwiico-help:before { content: '\e803'; } /* '' */ .zwiico-help:before { content: '\e803'; } /* '' */
@ -49,7 +48,6 @@
.zwiico-right-dir:before { content: '\e82d'; } /* '' */ .zwiico-right-dir:before { content: '\e82d'; } /* '' */
.zwiico-chart-line:before { content: '\e82e'; } /* '' */ .zwiico-chart-line:before { content: '\e82e'; } /* '' */
.zwiico-book:before { content: '\e82f'; } /* '' */ .zwiico-book:before { content: '\e82f'; } /* '' */
.zwiico-square-check-empty:before { content: '\e830'; } /* '' */
.zwiico-spin:before { content: '\e831'; } /* '' */ .zwiico-spin:before { content: '\e831'; } /* '' */
.zwiico-twitter:before { content: '\f099'; } /* '' */ .zwiico-twitter:before { content: '\f099'; } /* '' */
.zwiico-facebook:before { content: '\f09a'; } /* '' */ .zwiico-facebook:before { content: '\f09a'; } /* '' */

File diff suppressed because one or more lines are too long

View File

@ -1,6 +1,5 @@
.zwiico-plus-circled { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#x2191;&nbsp;'); } .zwiico-plus-circled { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#x2191;&nbsp;'); }
.zwiico-square-check { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xe800;&nbsp;'); }
.zwiico-plus { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xe801;&nbsp;'); } .zwiico-plus { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xe801;&nbsp;'); }
.zwiico-cancel { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xe802;&nbsp;'); } .zwiico-cancel { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xe802;&nbsp;'); }
.zwiico-help { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xe803;&nbsp;'); } .zwiico-help { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xe803;&nbsp;'); }
@ -48,7 +47,6 @@
.zwiico-right-dir { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xe82d;&nbsp;'); } .zwiico-right-dir { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xe82d;&nbsp;'); }
.zwiico-chart-line { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xe82e;&nbsp;'); } .zwiico-chart-line { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xe82e;&nbsp;'); }
.zwiico-book { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xe82f;&nbsp;'); } .zwiico-book { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xe82f;&nbsp;'); }
.zwiico-square-check-empty { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xe830;&nbsp;'); }
.zwiico-spin { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xe831;&nbsp;'); } .zwiico-spin { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xe831;&nbsp;'); }
.zwiico-twitter { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf099;&nbsp;'); } .zwiico-twitter { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf099;&nbsp;'); }
.zwiico-facebook { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf09a;&nbsp;'); } .zwiico-facebook { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf09a;&nbsp;'); }

View File

@ -11,7 +11,6 @@
} }
.zwiico-plus-circled { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#x2191;&nbsp;'); } .zwiico-plus-circled { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#x2191;&nbsp;'); }
.zwiico-square-check { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xe800;&nbsp;'); }
.zwiico-plus { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xe801;&nbsp;'); } .zwiico-plus { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xe801;&nbsp;'); }
.zwiico-cancel { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xe802;&nbsp;'); } .zwiico-cancel { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xe802;&nbsp;'); }
.zwiico-help { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xe803;&nbsp;'); } .zwiico-help { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xe803;&nbsp;'); }
@ -59,7 +58,6 @@
.zwiico-right-dir { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xe82d;&nbsp;'); } .zwiico-right-dir { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xe82d;&nbsp;'); }
.zwiico-chart-line { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xe82e;&nbsp;'); } .zwiico-chart-line { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xe82e;&nbsp;'); }
.zwiico-book { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xe82f;&nbsp;'); } .zwiico-book { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xe82f;&nbsp;'); }
.zwiico-square-check-empty { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xe830;&nbsp;'); }
.zwiico-spin { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xe831;&nbsp;'); } .zwiico-spin { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xe831;&nbsp;'); }
.zwiico-twitter { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf099;&nbsp;'); } .zwiico-twitter { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf099;&nbsp;'); }
.zwiico-facebook { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf09a;&nbsp;'); } .zwiico-facebook { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf09a;&nbsp;'); }

View File

@ -1,12 +1,12 @@
@charset "UTF-8"; @charset "UTF-8";
@font-face { @font-face {
font-family: 'zwiico'; font-family: 'zwiico';
src: url('../font/zwiico.eot?58081754'); src: url('../font/zwiico.eot?8645815');
src: url('../font/zwiico.eot?58081754#iefix') format('embedded-opentype'), src: url('../font/zwiico.eot?8645815#iefix') format('embedded-opentype'),
url('../font/zwiico.woff2?58081754') format('woff2'), url('../font/zwiico.woff2?8645815') format('woff2'),
url('../font/zwiico.woff?58081754') format('woff'), url('../font/zwiico.woff?8645815') format('woff'),
url('../font/zwiico.ttf?58081754') format('truetype'), url('../font/zwiico.ttf?8645815') format('truetype'),
url('../font/zwiico.svg?58081754#zwiico') format('svg'); url('../font/zwiico.svg?8645815#zwiico') format('svg');
font-weight: normal; font-weight: normal;
font-style: normal; font-style: normal;
} }
@ -16,7 +16,7 @@
@media screen and (-webkit-min-device-pixel-ratio:0) { @media screen and (-webkit-min-device-pixel-ratio:0) {
@font-face { @font-face {
font-family: 'zwiico'; font-family: 'zwiico';
src: url('../font/zwiico.svg?58081754#zwiico') format('svg'); src: url('../font/zwiico.svg?8645815#zwiico') format('svg');
} }
} }
*/ */
@ -56,7 +56,6 @@
} }
.zwiico-plus-circled:before { content: '\2191'; } /* '↑' */ .zwiico-plus-circled:before { content: '\2191'; } /* '↑' */
.zwiico-square-check:before { content: '\e800'; } /* '' */
.zwiico-plus:before { content: '\e801'; } /* '' */ .zwiico-plus:before { content: '\e801'; } /* '' */
.zwiico-cancel:before { content: '\e802'; } /* '' */ .zwiico-cancel:before { content: '\e802'; } /* '' */
.zwiico-help:before { content: '\e803'; } /* '' */ .zwiico-help:before { content: '\e803'; } /* '' */
@ -104,7 +103,6 @@
.zwiico-right-dir:before { content: '\e82d'; } /* '' */ .zwiico-right-dir:before { content: '\e82d'; } /* '' */
.zwiico-chart-line:before { content: '\e82e'; } /* '' */ .zwiico-chart-line:before { content: '\e82e'; } /* '' */
.zwiico-book:before { content: '\e82f'; } /* '' */ .zwiico-book:before { content: '\e82f'; } /* '' */
.zwiico-square-check-empty:before { content: '\e830'; } /* '' */
.zwiico-spin:before { content: '\e831'; } /* '' */ .zwiico-spin:before { content: '\e831'; } /* '' */
.zwiico-twitter:before { content: '\f099'; } /* '' */ .zwiico-twitter:before { content: '\f099'; } /* '' */
.zwiico-facebook:before { content: '\f09a'; } /* '' */ .zwiico-facebook:before { content: '\f09a'; } /* '' */

Binary file not shown.

View File

@ -8,8 +8,6 @@
<missing-glyph horiz-adv-x="1000" /> <missing-glyph horiz-adv-x="1000" />
<glyph glyph-name="plus-circled" unicode="&#x2191;" d="M420 770q174 0 297-123t123-297-123-297-297-123-297 123-123 297 123 297 297 123z m52-470l200 0 0 102-200 0 0 202-102 0 0-202-202 0 0-102 202 0 0-202 102 0 0 202z" horiz-adv-x="840" /> <glyph glyph-name="plus-circled" unicode="&#x2191;" d="M420 770q174 0 297-123t123-297-123-297-297-123-297 123-123 297 123 297 297 123z m52-470l200 0 0 102-200 0 0 202-102 0 0-202-202 0 0-102 202 0 0-202 102 0 0 202z" horiz-adv-x="840" />
<glyph glyph-name="square-check" unicode="&#xe800;" d="M0-150l0 1000 646 0-164-164-318 0 0-672 672 0 0 319 164 164 0-647-1000 0z m234 623l133 131 129-129 361 363 133-132-361-364-133-133z" horiz-adv-x="1000" />
<glyph glyph-name="plus" unicode="&#xe801;" d="M786 439v-107q0-22-16-38t-38-15h-232v-233q0-22-16-37t-38-16h-107q-22 0-38 16t-15 37v233h-232q-23 0-38 15t-16 38v107q0 23 16 38t38 16h232v232q0 22 15 38t38 16h107q23 0 38-16t16-38v-232h232q23 0 38-16t16-38z" horiz-adv-x="785.7" /> <glyph glyph-name="plus" unicode="&#xe801;" d="M786 439v-107q0-22-16-38t-38-15h-232v-233q0-22-16-37t-38-16h-107q-22 0-38 16t-15 37v233h-232q-23 0-38 15t-16 38v107q0 23 16 38t38 16h232v232q0 22 15 38t38 16h107q23 0 38-16t16-38v-232h232q23 0 38-16t16-38z" horiz-adv-x="785.7" />
<glyph glyph-name="cancel" unicode="&#xe802;" d="M724 112q0-22-15-38l-76-76q-16-15-38-15t-38 15l-164 165-164-165q-16-15-38-15t-38 15l-76 76q-16 16-16 38t16 38l164 164-164 164q-16 16-16 38t16 38l76 76q16 16 38 16t38-16l164-164 164 164q16 16 38 16t38-16l76-76q15-15 15-38t-15-38l-164-164 164-164q15-15 15-38z" horiz-adv-x="785.7" /> <glyph glyph-name="cancel" unicode="&#xe802;" d="M724 112q0-22-15-38l-76-76q-16-15-38-15t-38 15l-164 165-164-165q-16-15-38-15t-38 15l-76 76q-16 16-16 38t16 38l164 164-164 164q-16 16-16 38t16 38l76 76q16 16 38 16t38-16l164-164 164 164q16 16 38 16t38-16l76-76q15-15 15-38t-15-38l-164-164 164-164q15-15 15-38z" horiz-adv-x="785.7" />
@ -104,8 +102,6 @@
<glyph glyph-name="book" unicode="&#xe82f;" d="M915 583q22-31 10-72l-154-505q-10-36-42-60t-69-25h-515q-43 0-83 30t-55 74q-14 37-1 71 0 2 1 15t3 20q0 5-2 12t-2 11q1 6 5 12t9 13 9 13q13 21 25 51t17 51q2 6 0 17t0 16q2 6 9 15t10 13q12 20 23 51t14 51q1 5-1 17t0 16q2 7 12 17t13 13q10 14 23 47t16 54q0 4-2 14t-1 15q1 4 5 10t10 13 10 11q4 7 9 17t8 20 9 20 11 18 15 13 20 6 26-3l0-1q21 5 28 5h425q41 0 64-32t10-72l-153-506q-20-66-40-85t-72-20h-485q-15 0-21-8-6-9-1-24 14-39 81-39h515q16 0 31 9t20 23l167 550q4 13 3 32 21-8 33-24z m-594-1q-2-7 1-12t11-6h339q8 0 15 6t9 12l12 36q2 7-1 12t-12 6h-339q-7 0-14-6t-9-12z m-46-143q-3-7 1-12t11-6h339q7 0 14 6t10 12l11 36q3 7-1 13t-11 5h-339q-7 0-14-5t-10-13z" horiz-adv-x="928.6" /> <glyph glyph-name="book" unicode="&#xe82f;" d="M915 583q22-31 10-72l-154-505q-10-36-42-60t-69-25h-515q-43 0-83 30t-55 74q-14 37-1 71 0 2 1 15t3 20q0 5-2 12t-2 11q1 6 5 12t9 13 9 13q13 21 25 51t17 51q2 6 0 17t0 16q2 6 9 15t10 13q12 20 23 51t14 51q1 5-1 17t0 16q2 7 12 17t13 13q10 14 23 47t16 54q0 4-2 14t-1 15q1 4 5 10t10 13 10 11q4 7 9 17t8 20 9 20 11 18 15 13 20 6 26-3l0-1q21 5 28 5h425q41 0 64-32t10-72l-153-506q-20-66-40-85t-72-20h-485q-15 0-21-8-6-9-1-24 14-39 81-39h515q16 0 31 9t20 23l167 550q4 13 3 32 21-8 33-24z m-594-1q-2-7 1-12t11-6h339q8 0 15 6t9 12l12 36q2 7-1 12t-12 6h-339q-7 0-14-6t-9-12z m-46-143q-3-7 1-12t11-6h339q7 0 14 6t10 12l11 36q3 7-1 13t-11 5h-339q-7 0-14-5t-10-13z" horiz-adv-x="928.6" />
<glyph glyph-name="square-check-empty" unicode="&#xe830;" d="M0-150l0 1000 1000 0 0-1000-1000 0z m164 164l672 0 0 672-672 0 0-672z" horiz-adv-x="1000" />
<glyph glyph-name="spin" unicode="&#xe831;" d="M46 144l0 0c0 0-1 0-1 0-8 18-15 37-21 55-6 19-11 38-15 58-19 99-8 203 35 298 3 6 10 8 15 5 1 0 2 0 2-1l0 0 80-59c5-3 6-9 4-14-5-12-9-25-12-37-4-13-7-26-9-40-11-67-3-137 23-201 2-5 0-10-4-13l0 0-80-56c-5-4-12-2-16 3-1 0-1 1-1 2l0 0z m120 574l0 0c0 1 0 1 0 1 15 13 30 25 46 37 16 11 33 22 51 31 89 50 192 72 297 60 6-1 10-6 10-13 0-1-1-1-1-2l0 0-31-94c-2-5-8-8-13-7-13 0-27 0-40 0-14-1-27-2-40-4-68-11-133-40-186-84-4-3-10-3-14 0l0 0-79 58c-5 3-6 11-2 16 0 0 1 1 2 1l0 0z m588 65l0 0c0 0 1 0 1 0 17-10 34-21 50-32 16-12 31-25 46-38 74-69 127-160 148-262 2-6-2-12-9-13-1 0-1 0-2 0l0 0-100 1c-5 0-10 4-11 9-3 13-8 26-12 38-5 12-10 25-17 36-31 61-78 113-137 150-5 3-6 8-5 13l0 0 31 92c2 6 9 9 15 7 1 0 2-1 2-1l0 0z m244-535l0 0c0 0 0 0 0 0-4-20-9-39-15-57-7-19-14-37-22-55-44-92-114-170-205-221-6-3-13-1-16 4 0 1-1 2-1 2l0 0-30 94c-2 6 1 12 6 14 11 7 22 15 32 23 11 9 21 18 30 27 49 48 84 109 101 176 2 5 6 8 11 8l0 0 98-1c6 0 11-5 11-11 0-1 0-2 0-3l0 0z m-438-395l0 0c0 0 0 0 0 0-20-2-40-3-60-3-20 0-40 1-59 4-102 12-198 54-276 125-5 4-5 11 0 16 0 0 1 1 1 1l0 0 81 58c5 3 12 2 16-2 10-8 20-16 32-23 11-7 22-14 34-20 62-31 131-45 200-41 6 0 10-3 12-8l0 0 29-92c2-6-1-12-7-14-1-1-2-1-3-1l0 0z" horiz-adv-x="1000" /> <glyph glyph-name="spin" unicode="&#xe831;" d="M46 144l0 0c0 0-1 0-1 0-8 18-15 37-21 55-6 19-11 38-15 58-19 99-8 203 35 298 3 6 10 8 15 5 1 0 2 0 2-1l0 0 80-59c5-3 6-9 4-14-5-12-9-25-12-37-4-13-7-26-9-40-11-67-3-137 23-201 2-5 0-10-4-13l0 0-80-56c-5-4-12-2-16 3-1 0-1 1-1 2l0 0z m120 574l0 0c0 1 0 1 0 1 15 13 30 25 46 37 16 11 33 22 51 31 89 50 192 72 297 60 6-1 10-6 10-13 0-1-1-1-1-2l0 0-31-94c-2-5-8-8-13-7-13 0-27 0-40 0-14-1-27-2-40-4-68-11-133-40-186-84-4-3-10-3-14 0l0 0-79 58c-5 3-6 11-2 16 0 0 1 1 2 1l0 0z m588 65l0 0c0 0 1 0 1 0 17-10 34-21 50-32 16-12 31-25 46-38 74-69 127-160 148-262 2-6-2-12-9-13-1 0-1 0-2 0l0 0-100 1c-5 0-10 4-11 9-3 13-8 26-12 38-5 12-10 25-17 36-31 61-78 113-137 150-5 3-6 8-5 13l0 0 31 92c2 6 9 9 15 7 1 0 2-1 2-1l0 0z m244-535l0 0c0 0 0 0 0 0-4-20-9-39-15-57-7-19-14-37-22-55-44-92-114-170-205-221-6-3-13-1-16 4 0 1-1 2-1 2l0 0-30 94c-2 6 1 12 6 14 11 7 22 15 32 23 11 9 21 18 30 27 49 48 84 109 101 176 2 5 6 8 11 8l0 0 98-1c6 0 11-5 11-11 0-1 0-2 0-3l0 0z m-438-395l0 0c0 0 0 0 0 0-20-2-40-3-60-3-20 0-40 1-59 4-102 12-198 54-276 125-5 4-5 11 0 16 0 0 1 1 1 1l0 0 81 58c5 3 12 2 16-2 10-8 20-16 32-23 11-7 22-14 34-20 62-31 131-45 200-41 6 0 10-3 12-8l0 0 29-92c2-6-1-12-7-14-1-1-2-1-3-1l0 0z" horiz-adv-x="1000" />
<glyph glyph-name="twitter" unicode="&#xf099;" d="M904 622q-37-54-90-93 0-8 0-23 0-73-21-145t-64-139-103-117-144-82-181-30q-151 0-276 81 19-2 43-2 126 0 224 77-59 1-105 36t-64 89q19-3 34-3 24 0 48 6-63 13-104 62t-41 115v2q38-21 82-23-37 25-59 64t-22 86q0 49 25 91 68-83 164-133t208-55q-5 21-5 41 0 75 53 127t127 53q79 0 132-57 61 12 115 44-21-64-80-100 52 6 104 28z" horiz-adv-x="928.6" /> <glyph glyph-name="twitter" unicode="&#xf099;" d="M904 622q-37-54-90-93 0-8 0-23 0-73-21-145t-64-139-103-117-144-82-181-30q-151 0-276 81 19-2 43-2 126 0 224 77-59 1-105 36t-64 89q19-3 34-3 24 0 48 6-63 13-104 62t-41 115v2q38-21 82-23-37 25-59 64t-22 86q0 49 25 91 68-83 164-133t208-55q-5 21-5 41 0 75 53 127t127 53q79 0 132-57 61 12 115 44-21-64-80-100 52 6 104 28z" horiz-adv-x="928.6" />

Before

Width:  |  Height:  |  Size: 34 KiB

After

Width:  |  Height:  |  Size: 33 KiB

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

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

View File

@ -1,8 +1,3 @@
# 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 # Version 7.6
- Mise à jour RSS Feed - Mise à jour RSS Feed
# Version 7.5 # Version 7.5

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

Before

Width:  |  Height:  |  Size: 652 B

After

Width:  |  Height:  |  Size: 652 B

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

View File

@ -1,5 +1,3 @@
# 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 # Version 4.2
- Termes des commandes de profils - Termes des commandes de profils
# Version 4.1 # Version 4.1

View File

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

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

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

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

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

View File

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

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

View File

@ -1,5 +1,3 @@
# 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 # Version 4.1
- Termes des commandes de profils - Termes des commandes de profils
# Version 4.0 # Version 4.0

View File

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

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

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

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

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

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

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

View File

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

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

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

Some files were not shown because too many files have changed in this diff Show More