Compare commits
219 Commits
Author | SHA1 | Date |
---|---|---|
Fred Tempez | cbe06426bb | |
Fred Tempez | adac7395cc | |
Fred Tempez | 2c459a03d4 | |
Fred Tempez | 751bc450b5 | |
Fred Tempez | 6c8d9097f6 | |
Fred Tempez | b0814d50dc | |
Fred Tempez | a7a2424d93 | |
Fred Tempez | 43b15987d6 | |
Fred Tempez | e100a580ad | |
Fred Tempez | 397bdee655 | |
Fred Tempez | 78b2d87ec1 | |
Fred Tempez | 8dedb39a33 | |
Fred Tempez | 7cee16389f | |
Fred Tempez | 04b2877c48 | |
Fred Tempez | f6c7e5f954 | |
Fred Tempez | b5ea22021b | |
Fred Tempez | 3ee1398e2f | |
Fred Tempez | cfb07b81d5 | |
Fred Tempez | 0da23149db | |
Fred Tempez | 1322cb4eb0 | |
Fred Tempez | 167ad06dde | |
Fred Tempez | 271ee347a8 | |
Fred Tempez | 04a6d86999 | |
Fred Tempez | 05e6ff8f9b | |
Fred Tempez | 6e53ca8766 | |
Fred Tempez | dda93cf3d3 | |
Fred Tempez | 075e4afa1c | |
Fred Tempez | fd144d55f0 | |
Fred Tempez | b595120227 | |
Fred Tempez | b0b3b34bde | |
Fred Tempez | 2f592e2818 | |
Fred Tempez | 8c9bc40a02 | |
Fred Tempez | 37f77b3d50 | |
Fred Tempez | a5130e1d9f | |
Fred Tempez | 256da35d53 | |
Fred Tempez | bb93b1b313 | |
Fred Tempez | 195ed682f6 | |
Fred Tempez | ae71b9649d | |
Fred Tempez | 71418548e7 | |
Fred Tempez | 03c7e0a7fa | |
Fred Tempez | 6bc8636692 | |
Fred Tempez | c0d14596a7 | |
Fred Tempez | 6a72676c7c | |
Fred Tempez | 44c4997436 | |
Fred Tempez | cce73886a2 | |
Fred Tempez | b9733d7391 | |
Fred Tempez | 56ff0580a1 | |
Fred Tempez | 5b9f86fb38 | |
Fred Tempez | d43a78d307 | |
Fred Tempez | deedb002e8 | |
Fred Tempez | 6d7c2f725d | |
Fred Tempez | 5ede9b71c2 | |
Fred Tempez | 04f4c7be6d | |
Fred Tempez | 0c94b2f546 | |
Fred Tempez | 8b72ae01dc | |
Fred Tempez | 1ca77b89ce | |
Fred Tempez | 0934bf847d | |
Fred Tempez | 2a152a9a1d | |
Fred Tempez | bc8fbc17b8 | |
Fred Tempez | a8635f0c8a | |
Fred Tempez | ca875f9f05 | |
Fred Tempez | b4258fe496 | |
Fred Tempez | 509c95a680 | |
Fred Tempez | 2027c5918f | |
Fred Tempez | 3593e853d8 | |
Fred Tempez | cb13d2b0c9 | |
Fred Tempez | 0f55df8d31 | |
Fred Tempez | 939cb8d53f | |
Fred Tempez | 730e4ac9c4 | |
Fred Tempez | d3d96f795a | |
Fred Tempez | e68f58fad1 | |
Fred Tempez | 6c0f34ae71 | |
Fred Tempez | 9373880239 | |
Fred Tempez | a35036e0fa | |
Fred Tempez | 19246a59c9 | |
Fred Tempez | 15c4d1edd3 | |
Fred Tempez | 24f679d531 | |
Fred Tempez | 56f8f03581 | |
Fred Tempez | ae1f15e8b8 | |
Fred Tempez | 7544bb9862 | |
Fred Tempez | ebd078848a | |
Fred Tempez | e8e4f98be0 | |
Fred Tempez | c8c74d9be3 | |
Fred Tempez | 63541cf83a | |
Fred Tempez | 1cb54d46b1 | |
Fred Tempez | cf3936b7c0 | |
Fred Tempez | 84df59c52b | |
Fred Tempez | c75b71f217 | |
Fred Tempez | 269abc5699 | |
Fred Tempez | 638ddadb61 | |
Fred Tempez | 10f8340e76 | |
Fred Tempez | 7c0feae8ee | |
Fred Tempez | 25889b0759 | |
Fred Tempez | 1e0cca8685 | |
Fred Tempez | a02a796f4a | |
Fred Tempez | e640aa327e | |
Fred Tempez | ed34728f5e | |
Fred Tempez | b6e4b39e78 | |
Fred Tempez | 64f19f0f96 | |
Fred Tempez | b6fb2d75b4 | |
Fred Tempez | 7138c07a89 | |
Fred Tempez | 137c151e19 | |
Fred Tempez | 548daad047 | |
Fred Tempez | c8abde012c | |
Fred Tempez | caa348a571 | |
Fred Tempez | 8e1488b86f | |
Fred Tempez | 1d4f8405b1 | |
Fred Tempez | 0fece8c7ca | |
Fred Tempez | 0deec384bc | |
Fred Tempez | 7452faab55 | |
Fred Tempez | e9ed55b065 | |
Fred Tempez | d35010f100 | |
Fred Tempez | 14683133c8 | |
Fred Tempez | 4e174124fe | |
Fred Tempez | 64594e23ff | |
Fred Tempez | 7d5d6edf25 | |
Fred Tempez | 74fabce177 | |
Fred Tempez | e64e819d48 | |
Fred Tempez | 2dd835593a | |
Fred Tempez | 9664ce49b7 | |
Fred Tempez | 3502d78632 | |
Fred Tempez | 65a121cb0a | |
Fred Tempez | e6c52c29ee | |
Fred Tempez | 31994d33e0 | |
Fred Tempez | cfb0d8a0e9 | |
Fred Tempez | 5a8fc68049 | |
Fred Tempez | 8988e2e130 | |
Fred Tempez | 724d391d00 | |
Fred Tempez | 78102b96b4 | |
Fred Tempez | 0535556b68 | |
Fred Tempez | db0637ca1c | |
Fred Tempez | 6d42f792e4 | |
Fred Tempez | dd194e2488 | |
Fred Tempez | fc197b647d | |
Fred Tempez | d2dc4c64c0 | |
Fred Tempez | f65fe62da7 | |
Fred Tempez | 372db6dc3a | |
Fred Tempez | fd5aabd910 | |
Fred Tempez | 36604a1ee4 | |
Fred Tempez | 4dfd73453e | |
Fred Tempez | 2eab0090d1 | |
Fred Tempez | f74c7fd6f7 | |
Fred Tempez | 2bdb09b958 | |
Fred Tempez | 0407bd082d | |
Fred Tempez | d42ce3c733 | |
Fred Tempez | 260098d0a5 | |
Fred Tempez | 52fb225650 | |
Fred Tempez | b5693abbf5 | |
Fred Tempez | a8f1387c96 | |
Fred Tempez | 083d819597 | |
Fred Tempez | d829f57582 | |
Fred Tempez | 31986d138e | |
Fred Tempez | 3b77452bbe | |
Fred Tempez | c6358b4c63 | |
Fred Tempez | 084471aa3b | |
Fred Tempez | 97a782eb4d | |
Fred Tempez | 3884573de9 | |
Fred Tempez | 572f0206a8 | |
Fred Tempez | d3675f62f4 | |
Fred Tempez | 8e9c356188 | |
Fred Tempez | 3b5ddb5a3f | |
Fred Tempez | 91e4a4047c | |
Fred Tempez | caf193611d | |
Fred Tempez | ee4fc93afe | |
Fred Tempez | 3c76bcdf4c | |
Fred Tempez | e9e39f5a03 | |
Fred Tempez | b5382fa5f2 | |
Fred Tempez | cd69635448 | |
Fred Tempez | 0c8569f7cf | |
Fred Tempez | 13227a5cd4 | |
Fred Tempez | c43ce394e4 | |
Fred Tempez | 6c2c6a1acb | |
Fred Tempez | 656d6e557e | |
Fred Tempez | 9bf135337e | |
Fred Tempez | 6d77995439 | |
Fred Tempez | 9a3de92678 | |
Fred Tempez | 7b5f182be4 | |
Fred Tempez | 98f68f284c | |
Fred Tempez | 3ebb305cae | |
Fred Tempez | e80564c106 | |
Fred Tempez | e90929ea3b | |
Fred Tempez | ac8d3016c7 | |
Fred Tempez | ffb872fd03 | |
Fred Tempez | 08fb2d25fd | |
Fred Tempez | 63f7767460 | |
Fred Tempez | 17b76e1a0f | |
Fred Tempez | a4164e4a2d | |
Fred Tempez | 595d068de2 | |
Fred Tempez | cc92c90403 | |
Fred Tempez | 6da8223209 | |
Fred Tempez | 3bedbed4ef | |
Fred Tempez | 023ba99c0b | |
Fred Tempez | b8123b0534 | |
Fred Tempez | 931b56f6a3 | |
Fred Tempez | fcee5a8cde | |
Fred Tempez | 25d1c2400e | |
Fred Tempez | 48725b8703 | |
Fred Tempez | 9bea40ed08 | |
Fred Tempez | 01d6300d90 | |
Fred Tempez | ac28fe496f | |
Fred Tempez | ef371092a0 | |
Fred Tempez | 21afc43656 | |
Fred Tempez | cd03316a9b | |
Fred Tempez | 7ce30078f6 | |
Fred Tempez | ded7bb5c81 | |
Fred Tempez | 87bfe71d9d | |
Fred Tempez | 36537c4b17 | |
Fred Tempez | 13b5adffac | |
Fred Tempez | 28ee5e46a5 | |
Fred Tempez | 0ce3f0d1cb | |
Fred Tempez | f6019714b9 | |
Fred Tempez | e2316dc129 | |
Fred Tempez | fbbf671289 | |
Fred Tempez | 9126d2887b | |
Fred Tempez | 052f4ac035 | |
Fred Tempez | 0f7e271a28 | |
Fred Tempez | 451174cdcf | |
Fred Tempez | 8b8480b444 | |
Fred Tempez | eac4746e8a |
|
@ -9,3 +9,4 @@ site/i18n/*.json
|
|||
core/vendor/tinymce/link_list.json
|
||||
robots.txt
|
||||
sitemap.xml
|
||||
core/module/config/tool/data.key
|
|
@ -32,5 +32,13 @@ Options -Indexes
|
|||
Options -MultiViews
|
||||
</IfModule>
|
||||
|
||||
# Enlever le slash final des URL
|
||||
RewriteCond %{REQUEST_FILENAME} !-f
|
||||
RewriteCond %{REQUEST_FILENAME} !-d
|
||||
RewriteCond %{REQUEST_URI} ^(.+)/$
|
||||
RewriteRule ^ %1 [R=301,L]
|
||||
|
||||
# ne pas supprimer la ligne URL rewriting !
|
||||
|
||||
# URL rewriting
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
# ZwiiCampus 1.4.14
|
||||
# ZwiiCampus 1.10.04
|
||||
|
||||
ZwiiCampus (Learning Management System) est logiciel auteur destiné à mettre en ligne des tutoriels. Il dispose de plusieurs modalités d'ouverture et d'accès des contenus. Basé sur la version 13 du CMS Zwii, la structure logicielle est solide, le framework de Zwii est éprouvé.
|
||||
|
||||
|
@ -68,6 +68,7 @@ A l'occasion de l'installation d'une version majeure, il est recommandé de réa
|
|||
[F] module.json Données des modules de pages
|
||||
[F] theme.css Thème de ce contenu
|
||||
[F] theme.json Thème de ce contenu
|
||||
[F] report.csv Rapport de participation
|
||||
[R] content Dossier des contenus de page
|
||||
[F] accueil.html Exemple contenu de la page d'accueil
|
||||
[R] fonts Dossier contenant les fontes installées
|
||||
|
@ -84,7 +85,7 @@ A l'occasion de l'installation d'une version majeure, il est recommandé de réa
|
|||
[F] core.json Configuration du noyau
|
||||
[F] course.json Données de contenus
|
||||
[F] custom.css Feuille de style de la personnalisation avancée
|
||||
[F] enrolment.json Données des inscriptions et des statistiques par contenu
|
||||
[F] enrolment.json Inscriptions dans les espaces, dernière page vue et timetamp
|
||||
[F] font.json Descripteur des fontes personnalisées
|
||||
[F] journal.log Journalisation des activités
|
||||
[F] language.json Langues de l'interface
|
||||
|
|
|
@ -193,7 +193,7 @@ class helper
|
|||
{
|
||||
// Creation du ZIP
|
||||
$baseName = str_replace('/', '', helper::baseUrl(false, false));
|
||||
$baseName = empty($baseName) ? 'ZwiiCMS' : $baseName;
|
||||
$baseName = empty($baseName) ? 'Campus' : $baseName;
|
||||
$fileName = $baseName . '-backup-' . date('Y-m-d-H-i-s', time()) . '.zip';
|
||||
$zip = new ZipArchive();
|
||||
$zip->open($folder . $fileName, ZipArchive::CREATE | ZipArchive::OVERWRITE);
|
||||
|
@ -368,7 +368,7 @@ class helper
|
|||
$version = helper::getOnlineVersion($channel);
|
||||
$update = false;
|
||||
if (!empty($version)) {
|
||||
$update = version_compare(common::ZWII_VERSION, $version) === -1;
|
||||
$update = version_compare(common::ZWII_VERSION, $version) == -1;
|
||||
}
|
||||
return $update;
|
||||
}
|
||||
|
|
|
@ -101,7 +101,7 @@ class Dot implements \ArrayAccess, \Iterator, \Countable
|
|||
}
|
||||
} else {
|
||||
// Iterate path
|
||||
$keys = explode('.', (string)$key);
|
||||
$keys = explode('.', (string) $key);
|
||||
if ($pop === true) {
|
||||
array_pop($keys);
|
||||
}
|
||||
|
@ -141,7 +141,7 @@ class Dot implements \ArrayAccess, \Iterator, \Countable
|
|||
} elseif (is_array($key)) {
|
||||
// Iterate array of paths
|
||||
foreach ($key as $k) {
|
||||
self::delete($k);
|
||||
self::deleteValue($array, $k);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -199,7 +199,7 @@ class Dot implements \ArrayAccess, \Iterator, \Countable
|
|||
*/
|
||||
public function has($key)
|
||||
{
|
||||
$keys = explode('.', (string)$key);
|
||||
$keys = explode('.', (string) $key);
|
||||
$data = &$this->data;
|
||||
foreach ($keys as $key) {
|
||||
if (!isset($data[$key])) {
|
||||
|
@ -371,7 +371,7 @@ class Dot implements \ArrayAccess, \Iterator, \Countable
|
|||
*/
|
||||
public function isEmpty(): bool
|
||||
{
|
||||
return !(bool)count($this->data);
|
||||
return !(bool) count($this->data);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -391,7 +391,7 @@ class Dot implements \ArrayAccess, \Iterator, \Countable
|
|||
*/
|
||||
public function toJson()
|
||||
{
|
||||
return json_encode($this->data, JSON_UNESCAPED_UNICODE|JSON_PRETTY_PRINT);
|
||||
return json_encode($this->data, JSON_UNESCAPED_UNICODE | JSON_PRETTY_PRINT);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -121,17 +121,17 @@ class JsonDb extends \Prowebcraft\Dot
|
|||
} else {
|
||||
if ($this->config['backup']) {
|
||||
try {
|
||||
//todo make backup of database
|
||||
copy($this->config['dir'] . DIRECTORY_SEPARATOR . $this->config['name'], $this->config['dir'] . DIRECTORY_SEPARATOR . $this->config['name'] . '.backup');
|
||||
} catch (\Exception $e) {
|
||||
|
||||
error_log('Erreur de chargement : ' . $e);
|
||||
exit('Erreur de chargement : ' . $e);
|
||||
}
|
||||
}
|
||||
}
|
||||
$this->data = json_decode(file_get_contents($this->db), true);
|
||||
if (!$this->data === null) {
|
||||
throw new \InvalidArgumentException('Database file ' . $this->db
|
||||
. ' contains invalid json object. Please validate or remove file');
|
||||
if (!$this->data === null && json_last_error() !== JSON_ERROR_NONE) {
|
||||
throw new \InvalidArgumentException('Le fichier ' . $this->db
|
||||
. ' contient des données invalides.');
|
||||
}
|
||||
}
|
||||
return $this->data;
|
||||
|
@ -142,20 +142,38 @@ class JsonDb extends \Prowebcraft\Dot
|
|||
*/
|
||||
public function save()
|
||||
{
|
||||
//$v = json_encode($this->data, JSON_UNESCAPED_UNICODE );
|
||||
$v = json_encode($this->data, JSON_UNESCAPED_UNICODE | JSON_FORCE_OBJECT);
|
||||
$l = strlen($v);
|
||||
$t = 0;
|
||||
while ($t < 5) {
|
||||
$w = file_put_contents($this->db, $v); // Multi user get a locker
|
||||
if ($w == $l) {
|
||||
// Encode les données au format JSON avec les options spécifiées
|
||||
$encoded_data = json_encode($this->data, JSON_UNESCAPED_UNICODE | JSON_FORCE_OBJECT | JSON_PRETTY_PRINT);
|
||||
|
||||
// Vérifie la longueur de la chaîne JSON encodée
|
||||
$encoded_length = strlen($encoded_data);
|
||||
|
||||
// Initialise le compteur de tentatives
|
||||
$attempt = 0;
|
||||
|
||||
// Tente d'encoder les données en JSON et de les sauvegarder jusqu'à 5 fois en cas d'échec
|
||||
while ($attempt < 5) {
|
||||
// Essaye d'écrire les données encodées dans le fichier de base de données
|
||||
$write_result = file_put_contents($this->db, $encoded_data, LOCK_EX); // Les utilisateurs multiples obtiennent un verrou
|
||||
|
||||
// Vérifie si l'écriture a réussi
|
||||
if ($write_result === $encoded_length) {
|
||||
// Sort de la boucle si l'écriture a réussi
|
||||
break;
|
||||
}
|
||||
$t++;
|
||||
}
|
||||
if ($w !== $l) {
|
||||
exit('Erreur d\'écriture, les données n\'ont pas été sauvegardées');
|
||||
|
||||
// Incrémente le compteur de tentatives
|
||||
$attempt++;
|
||||
}
|
||||
|
||||
// Vérifie si l'écriture a échoué même après plusieurs tentatives
|
||||
if ($write_result !== $encoded_length) {
|
||||
// Enregistre un message d'erreur dans le journal des erreurs
|
||||
error_log('Erreur d\'écriture, les données n\'ont pas été sauvegardées.');
|
||||
|
||||
// Affiche un message d'erreur et termine le script
|
||||
exit('Erreur d\'écriture, les données n\'ont pas été sauvegardées.');
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -151,7 +151,7 @@ class layout extends common
|
|||
}
|
||||
echo '</div>';
|
||||
}
|
||||
echo '</main></section>';
|
||||
echo '</section></main>';
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -352,10 +352,11 @@ class layout extends common
|
|||
$items .= $this->getData(['theme', 'footer', 'displaymemberAccount']) === false ? ' class="displayNone">' : '>';
|
||||
$items .= '<wbr> | ';
|
||||
if (
|
||||
$this->getUser('permission', 'filemanager') === true
|
||||
$this->getUser('permission', 'filemanager') === true
|
||||
&& $this->getUser('permission', 'folder', (self::$siteContent === 'home' ? 'homePath' : 'coursePath')) !== 'none'
|
||||
) {
|
||||
$items .= '<wbr>' . template::ico('folder', [
|
||||
'href' => helper::baseUrl(false) . 'core/vendor/filemanager/dialog.php?type=0&akey=' . md5_file(self::DATA_DIR . 'core.json') . '&lang=' . $this->getData(['user', $this->getUser('id'), 'language']),
|
||||
'href' => helper::baseUrl(false) . 'core/vendor/filemanager/dialog.php?type=0&akey=' . md5_file(self::DATA_DIR . 'core.json') . '&lang=' . $this->getData(['user', $this->getUser('id'), 'language']) . '&fldr=/' . self::$siteContent,
|
||||
'margin' => 'all',
|
||||
'attr' => 'data-lity',
|
||||
'help' => 'Fichiers du site'
|
||||
|
@ -496,19 +497,53 @@ class layout extends common
|
|||
* Affichage du sélecteur d'espaces
|
||||
*/
|
||||
if (
|
||||
$this->getUser('group') >= self::GROUP_MEMBER
|
||||
$this->getUser('group') === self::GROUP_MEMBER
|
||||
&& $this->getData(['theme', 'menu', 'selectSpace']) === true
|
||||
) {
|
||||
if ($this->getCoursesByUser()) {
|
||||
if ($this->getCoursesByProfil()) {
|
||||
$itemsRight .= '<li><select id="menuSelectCourse" >';
|
||||
$itemsRight .= '<option name="' . helper::translate('Accueil') . '" value="' . helper::baseUrl(true) . 'course/swap/home" ' . ('home' === self::$siteContent ? 'selected' : '') . '>' . helper::translate('Accueil') . '</option>';
|
||||
foreach ($this->getCoursesByUser() as $courseId => $value) {
|
||||
foreach ($this->getCoursesByProfil() as $courseId => $value) {
|
||||
$itemsRight .= '<option name="' . $this->getData(['course', $courseId, 'title']) . '" value="' . helper::baseUrl(true) . 'course/swap/' . $courseId . '" ' . ($courseId === self::$siteContent ? 'selected' : '') . '>' . $this->getData(['course', $courseId, 'title']) . '</option>';
|
||||
}
|
||||
$itemsRight .= '</select></li>';
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Commandes pour les membres simples
|
||||
* Affichage des boutons gestionnaire de fichiers et mon compte
|
||||
*/
|
||||
if (
|
||||
$this->getUser('group') === self::GROUP_MEMBER
|
||||
&& $this->getData(['theme', 'menu', 'memberBar']) === true
|
||||
) {
|
||||
|
||||
// Affiche l'icône RFM
|
||||
if ($this->getUser('permission', 'filemanager') === true
|
||||
&& $this->getUser('permission', 'folder', (self::$siteContent === 'home' ? 'homePath' : 'coursePath')) !== 'none') {
|
||||
$itemsRight .= '<li>' . template::ico('folder', [
|
||||
'href' => helper::baseUrl(false) . 'core/vendor/filemanager/dialog.php?type=0&akey=' . md5_file(self::DATA_DIR . 'core.json') . '&lang=' . $this->getData(['user', $this->getUser('id'), 'language']) . '&fldr=/' . self::$siteContent,
|
||||
'attr' => 'data-lity',
|
||||
'help' => 'Fichiers du site'
|
||||
]) . '</li>';
|
||||
}
|
||||
// Affiche l'icône d'édition du compte
|
||||
if ($this->getUser('permission', 'user', 'edit') === true) {
|
||||
$itemsRight .= '<li>' . template::ico('user', [
|
||||
'help' => 'Mon compte',
|
||||
'margin' => 'right',
|
||||
'href' => helper::baseUrl() . 'user/edit/' . $this->getUser('id')
|
||||
]) . '</li>';
|
||||
}
|
||||
$itemsRight .= '<li>' .
|
||||
template::ico('logout', [
|
||||
'help' => 'Déconnecter',
|
||||
'href' => helper::baseUrl() . 'user/logout',
|
||||
'id' => 'barLogout'
|
||||
]) . '</li>';
|
||||
}
|
||||
|
||||
// Lien de connexion
|
||||
if (
|
||||
($this->getData(['theme', 'menu', 'loginLink'])
|
||||
|
@ -523,41 +558,7 @@ class layout extends common
|
|||
]) .
|
||||
'</li>';
|
||||
}
|
||||
/**
|
||||
* Commandes pour les membres simples
|
||||
* Affichage des boutons gestionnaire de fichiers et mon compte
|
||||
*/
|
||||
if (
|
||||
$this->getUser('group') === self::GROUP_MEMBER
|
||||
&& $this->getData(['theme', 'menu', 'memberBar']) === true
|
||||
) {
|
||||
|
||||
if (
|
||||
($this->getUser('group') >= self::GROUP_MEMBER &&
|
||||
$this->getUser('permission', 'filemanager') === true)
|
||||
) {
|
||||
$itemsRight .= '<li>' . template::ico('folder', [
|
||||
'href' => helper::baseUrl(false) . 'core/vendor/filemanager/dialog.php?type=0&akey=' . md5_file(self::DATA_DIR . 'core.json') . '&lang=' . $this->getData(['user', $this->getUser('id'), 'language']),
|
||||
'attr' => 'data-lity',
|
||||
'help' => 'Fichiers du site'
|
||||
]) . '</li>';
|
||||
}
|
||||
if (
|
||||
$this->getUser('permission', 'user', 'edit') === true
|
||||
) {
|
||||
$itemsRight .= '<li>' . template::ico('user', [
|
||||
'help' => 'Mon compte',
|
||||
'margin' => 'right',
|
||||
'href' => helper::baseUrl() . 'user/edit/' . $this->getUser('id')
|
||||
]) . '</li>';
|
||||
}
|
||||
$itemsRight .= '<li>' .
|
||||
template::ico('logout', [
|
||||
'help' => 'Déconnecter',
|
||||
'href' => helper::baseUrl() . 'user/logout',
|
||||
'id' => 'barLogout'
|
||||
]) . '</li>';
|
||||
}
|
||||
// Retourne les items du menu
|
||||
echo '<ul class="navMain" id="menuLeft">' . $itemsLeft . '</ul><ul class="navMain" id="menuRight">' . $itemsRight;
|
||||
echo '</ul>';
|
||||
|
@ -918,21 +919,22 @@ class layout extends common
|
|||
$leftItems = '';
|
||||
// Sélecteur de contenu
|
||||
/**
|
||||
* Les admins voient tousles contenus
|
||||
* Les admins voient tous les contenus
|
||||
* Les enseignants les contenus dont ils sont auteurs
|
||||
*/
|
||||
if ($this->getUser('group') >= self::GROUP_EDITOR) {
|
||||
if ($this->getCoursesByUser()) {
|
||||
if (is_array($this->getCoursesByProfil())) {
|
||||
$leftItems .= '<li><select id="barSelectCourse" >';
|
||||
$leftItems .= '<option name="' . helper::translate('Accueil') . '" value="' . helper::baseUrl(true) . 'course/swap/home" ' . ('home' === self::$siteContent ? 'selected' : '') . '>' . helper::translate('Accueil') . '</option>';
|
||||
foreach ($this->getCoursesByUser() as $courseId => $value) {
|
||||
foreach ($this->getCoursesByProfil() as $courseId => $value) {
|
||||
$leftItems .= '<option name="' . $this->getData(['course', $courseId, 'title']) . '" value="' . helper::baseUrl(true) . 'course/swap/' . $courseId . '" ' . ($courseId === self::$siteContent ? 'selected' : '') . '>' . $this->getData(['course', $courseId, 'title']) . '</option>';
|
||||
}
|
||||
$leftItems .= '</select></li>';
|
||||
}
|
||||
|
||||
$leftItems .= '<li>' . template::ico('cubes', [
|
||||
'href' => helper::baseUrl() . 'course',
|
||||
'help' => 'Espaces'
|
||||
'help' => 'Gérer les espaces'
|
||||
]) . '</li>';
|
||||
}
|
||||
if ($this->getUser('group') >= self::GROUP_ADMIN) {
|
||||
|
@ -941,8 +943,11 @@ class layout extends common
|
|||
'href' => helper::baseUrl() . 'theme'
|
||||
]) . '</li>';
|
||||
}
|
||||
// Liste des pages
|
||||
if ($this->getUser('group') >= self::GROUP_EDITOR) {
|
||||
// Liste des pages et bouton de gestion interdit pour l'accueil sauf admin
|
||||
if (
|
||||
($this->getUser('group') === self::GROUP_EDITOR && self::$siteContent != 'home')
|
||||
|| $this->getUser('group') === self::GROUP_ADMIN
|
||||
) {
|
||||
$leftItems .= '<li><select id="barSelectPage">';
|
||||
$leftItems .= '<option value="">' . helper::translate('Pages du site') . '</option>';
|
||||
$leftItems .= '<optgroup label="' . helper::translate('Pages orphelines') . '">';
|
||||
|
@ -996,7 +1001,7 @@ class layout extends common
|
|||
// Bouton Ajouter une page
|
||||
if ($this->getUser('permission', 'page', 'add')) {
|
||||
$leftItems .= '<li>' . template::ico('plus', [
|
||||
'href' => helper::baseUrl() . 'page/add',
|
||||
'href' => helper::baseUrl() . 'page/add/' . self::$siteContent,
|
||||
'help' => 'Nouvelle page ou barre latérale'
|
||||
]) . '</li>';
|
||||
}
|
||||
|
@ -1013,9 +1018,9 @@ class layout extends common
|
|||
or $this->getUrl(0) === ''
|
||||
) {
|
||||
// Bouton Editer une page
|
||||
if ($this->getUser('permission', 'page', 'edit')) {
|
||||
if ($this->getUser('permission', 'page', 'edit') and $this->geturl(1) !== 'edit') {
|
||||
$leftItems .= '<li>' . template::ico('pencil', [
|
||||
'href' => helper::baseUrl() . 'page/edit/' . $this->getUrl(0),
|
||||
'href' => helper::baseUrl() . 'page/edit/' . $this->getUrl(0) . '/' . self::$siteContent,
|
||||
'help' => 'Éditer la page'
|
||||
]) . '</li>';
|
||||
}
|
||||
|
@ -1034,7 +1039,7 @@ class layout extends common
|
|||
$this->getUser('permission', 'page', 'duplicate')
|
||||
) {
|
||||
$leftItems .= '<li>' . template::ico('clone', [
|
||||
'href' => helper::baseUrl() . 'page/duplicate/' . $this->getUrl(0),
|
||||
'href' => helper::baseUrl() . 'page/duplicate/' . $this->getUrl(0) . '/' . self::$siteContent,
|
||||
'help' => 'Dupliquer la page'
|
||||
])
|
||||
. '</li>';
|
||||
|
@ -1044,7 +1049,7 @@ class layout extends common
|
|||
$this->getUser('permission', 'page', 'delete')
|
||||
) {
|
||||
$leftItems .= '<li>' . template::ico('trash', [
|
||||
'href' => helper::baseUrl() . 'page/delete/' . $this->getUrl(0),
|
||||
'href' => helper::baseUrl() . 'page/delete/' . $this->getUrl(0) . '/' . self::$siteContent,
|
||||
'help' => 'Supprimer la page',
|
||||
'id' => 'pageDelete'
|
||||
])
|
||||
|
@ -1056,18 +1061,15 @@ class layout extends common
|
|||
$rightItems = '';
|
||||
if (
|
||||
(
|
||||
// ZwiiCampus ------
|
||||
self::$siteContent !== 'home'
|
||||
// ZwiiCampus ------
|
||||
&& $this->getUser('group') >= self::GROUP_MEMBER
|
||||
&& $this->getUser('permission', 'filemanager')
|
||||
|
||||
$this->getUser('group') === self::GROUP_EDITOR
|
||||
&& $this->getUser('permission', 'filemanager') === true
|
||||
&& $this->getUser('permission', 'folder', (self::$siteContent === 'home' ? 'homePath' : 'coursePath')) !== 'none'
|
||||
)
|
||||
|| $this->getUser('group') == self::GROUP_ADMIN
|
||||
|| $this->getUser('group') === self::GROUP_ADMIN
|
||||
) {
|
||||
$rightItems .= '<li>' . template::ico('folder', [
|
||||
'help' => 'Fichiers',
|
||||
'href' => helper::baseUrl(false) . 'core/vendor/filemanager/dialog.php?type=0&akey=' . md5_file(self::DATA_DIR . 'core.json') . '&lang=' . $this->getData(['user', $this->getUser('id'), 'language']),
|
||||
'href' => helper::baseUrl(false) . 'core/vendor/filemanager/dialog.php?type=0&akey=' . md5_file(self::DATA_DIR . 'core.json') . '&lang=' . $this->getData(['user', $this->getUser('id'), 'language']) . '&fldr=/' . self::$siteContent,
|
||||
'attr' => 'data-lity'
|
||||
]) . '</li>';
|
||||
}
|
||||
|
|
|
@ -15,12 +15,12 @@ class core extends common
|
|||
}
|
||||
|
||||
// Fuseau horaire
|
||||
self::$timezone = $this->getData(['config', 'timezone']); // Utile pour transmettre le timezone à la classe helper
|
||||
date_default_timezone_set(self::$timezone);
|
||||
common::$timezone = $this->getData(['config', 'timezone']); // Utile pour transmettre le timezone à la classe helper
|
||||
date_default_timezone_set(common::$timezone);
|
||||
// Supprime les fichiers temporaires
|
||||
$lastClearTmp = mktime(0, 0, 0);
|
||||
if ($lastClearTmp > $this->getData(['core', 'lastClearTmp']) + 86400) {
|
||||
$iterator = new DirectoryIterator(self::TEMP_DIR);
|
||||
$iterator = new DirectoryIterator(common::TEMP_DIR);
|
||||
foreach ($iterator as $fileInfos) {
|
||||
if (
|
||||
$fileInfos->isFile() &&
|
||||
|
@ -43,11 +43,11 @@ class core extends common
|
|||
and $this->getData(['user']) // Pas de backup pendant l'installation
|
||||
) {
|
||||
// Copie des fichier de données
|
||||
helper::autoBackup(self::BACKUP_DIR, ['backup', 'tmp', 'file']);
|
||||
helper::autoBackup(common::BACKUP_DIR, ['backup', 'tmp', 'file']);
|
||||
// Date du dernier backup
|
||||
$this->setData(['core', 'lastBackup', $lastBackup]);
|
||||
// Supprime les backups de plus de 30 jours
|
||||
$iterator = new DirectoryIterator(self::BACKUP_DIR);
|
||||
$iterator = new DirectoryIterator(common::BACKUP_DIR);
|
||||
foreach ($iterator as $fileInfos) {
|
||||
if (
|
||||
$fileInfos->isFile()
|
||||
|
@ -60,23 +60,23 @@ class core extends common
|
|||
}
|
||||
|
||||
// Crée le fichier de personnalisation avancée
|
||||
if (file_exists(self::DATA_DIR . 'custom.css') === false) {
|
||||
file_put_contents(self::DATA_DIR . 'custom.css', ('core/module/theme/resource/custom.css'));
|
||||
chmod(self::DATA_DIR . 'custom.css', 0755);
|
||||
if (file_exists(common::DATA_DIR . 'custom.css') === false) {
|
||||
file_put_contents(common::DATA_DIR . 'custom.css', ('core/module/theme/resource/custom.css'));
|
||||
chmod(common::DATA_DIR . 'custom.css', 0755);
|
||||
}
|
||||
// Crée le fichier de personnalisation
|
||||
if (file_exists(self::DATA_DIR . self::$siteContent . '/theme.css') === false) {
|
||||
file_put_contents(self::DATA_DIR . self::$siteContent . '/theme.css', '');
|
||||
chmod(self::DATA_DIR . self::$siteContent . '/theme.css', 0755);
|
||||
if (file_exists(common::DATA_DIR . common::$siteContent . '/theme.css') === false) {
|
||||
file_put_contents(common::DATA_DIR . common::$siteContent . '/theme.css', '');
|
||||
chmod(common::DATA_DIR . common::$siteContent . '/theme.css', 0755);
|
||||
}
|
||||
// Crée le fichier de personnalisation de l'administration
|
||||
if (file_exists(self::DATA_DIR . 'admin.css') === false) {
|
||||
file_put_contents(self::DATA_DIR . 'admin.css', '');
|
||||
chmod(self::DATA_DIR . 'admin.css', 0755);
|
||||
if (file_exists(common::DATA_DIR . 'admin.css') === false) {
|
||||
file_put_contents(common::DATA_DIR . 'admin.css', '');
|
||||
chmod(common::DATA_DIR . 'admin.css', 0755);
|
||||
}
|
||||
|
||||
// Check la version rafraichissement du theme
|
||||
$cssVersion = preg_split('/\*+/', file_get_contents(self::DATA_DIR . self::$siteContent . '/theme.css'));
|
||||
$cssVersion = preg_split('/\*+/', file_get_contents(common::DATA_DIR . common::$siteContent . '/theme.css'));
|
||||
if (empty($cssVersion[1]) or $cssVersion[1] !== md5(json_encode($this->getData(['theme'])))) {
|
||||
// Version
|
||||
$css = '/*' . md5(json_encode($this->getData(['theme']))) . '*/';
|
||||
|
@ -92,7 +92,7 @@ class core extends common
|
|||
// Fonts disponibles
|
||||
$fontsAvailable['files'] = $this->getData(['font', 'files']);
|
||||
$fontsAvailable['imported'] = $this->getData(['font', 'imported']);
|
||||
$fontsAvailable['websafe'] = self::$fontsWebSafe;
|
||||
$fontsAvailable['websafe'] = common::$fontsWebSafe;
|
||||
|
||||
// Fontes installées
|
||||
$fonts = [
|
||||
|
@ -273,7 +273,7 @@ class core extends common
|
|||
$css .= '#footerCopyright{text-align:' . $this->getData(['theme', 'footer', 'copyrightAlign']) . '}';
|
||||
|
||||
// Enregistre la personnalisation
|
||||
file_put_contents(self::DATA_DIR . self::$siteContent . '/theme.css', $css);
|
||||
file_put_contents(common::DATA_DIR . common::$siteContent . '/theme.css', $css);
|
||||
|
||||
// Effacer le cache pour tenir compte de la couleur de fond TinyMCE
|
||||
header("Expires: Tue, 01 Jan 2000 00:00:00 GMT");
|
||||
|
@ -284,7 +284,7 @@ class core extends common
|
|||
}
|
||||
|
||||
// Check la version rafraichissement du theme admin
|
||||
$cssVersion = preg_split('/\*+/', file_get_contents(self::DATA_DIR . 'admin.css'));
|
||||
$cssVersion = preg_split('/\*+/', file_get_contents(common::DATA_DIR . 'admin.css'));
|
||||
if (empty($cssVersion[1]) or $cssVersion[1] !== md5(json_encode($this->getData(['admin'])))) {
|
||||
|
||||
// Version
|
||||
|
@ -293,7 +293,7 @@ class core extends common
|
|||
// Fonts disponibles
|
||||
$fontsAvailable['files'] = $this->getData(['font', 'files']);
|
||||
$fontsAvailable['imported'] = $this->getData(['font', 'imported']);
|
||||
$fontsAvailable['websafe'] = self::$fontsWebSafe;
|
||||
$fontsAvailable['websafe'] = common::$fontsWebSafe;
|
||||
|
||||
/**
|
||||
* Import des polices de caractères
|
||||
|
@ -368,7 +368,7 @@ class core extends common
|
|||
// Bordure du contour TinyMCE
|
||||
$css .= '.mce-tinymce{border: 1px solid ' . $this->getData(['admin', 'borderBlockColor']) . '!important;}';
|
||||
// Enregistre la personnalisation
|
||||
file_put_contents(self::DATA_DIR . 'admin.css', $css);
|
||||
file_put_contents(common::DATA_DIR . 'admin.css', $css);
|
||||
}
|
||||
}
|
||||
/**
|
||||
|
@ -384,8 +384,8 @@ class core extends common
|
|||
require 'core/module/' . $classPath;
|
||||
}
|
||||
// Module
|
||||
elseif (is_readable(self::MODULE_DIR . $classPath)) {
|
||||
require self::MODULE_DIR . $classPath;
|
||||
elseif (is_readable(common::MODULE_DIR . $classPath)) {
|
||||
require common::MODULE_DIR . $classPath;
|
||||
}
|
||||
// Librairie
|
||||
elseif (is_readable('core/vendor/' . $classPath)) {
|
||||
|
@ -414,22 +414,23 @@ class core extends common
|
|||
// Sauvegarde la dernière page visitée par l'utilisateur connecté et enregistre l'historique des consultations
|
||||
if (
|
||||
$this->getUser('id')
|
||||
&& self::$siteContent !== 'home'
|
||||
&& common::$siteContent !== 'home'
|
||||
&& in_array($this->getUrl(0), array_keys($this->getData(['page'])))
|
||||
// Le userId n'est pas celui d'un admis ni le prof du contenu
|
||||
&& (
|
||||
$this->getUser('group') < self::GROUP_ADMIN
|
||||
|| $this->getUser('id') !== $this->getData(['course', self::$siteContent, 'author'])
|
||||
$this->getUser('group') < common::GROUP_ADMIN
|
||||
|| $this->getUser('id') !== $this->getData(['course', common::$siteContent, 'author'])
|
||||
)
|
||||
) {
|
||||
// Stocke l'historique des pages vues
|
||||
$data = is_array($this->getData(['enrolment', self::$siteContent, $this->getUser('id'), 'history', $this->getUrl(0)]))
|
||||
? array_merge([time()], $this->getData(['enrolment', self::$siteContent, $this->getUser('id'), 'history', $this->getUrl(0)]))
|
||||
: [time()];
|
||||
$this->setData(['enrolment', self::$siteContent, $this->getUser('id'), 'history', $this->getUrl(0), $data]);
|
||||
// Stocke la dernière page vue et sa date de consultation
|
||||
$this->setData(['enrolment', self::$siteContent, $this->getUser('id'), 'lastPageView', $this->getUrl(0)]);
|
||||
$this->setData(['enrolment', self::$siteContent, $this->getUser('id'), 'datePageView', time()]);
|
||||
$this->setData(['enrolment', common::$siteContent, $this->getUser('id'), 'lastPageView', $this->getUrl(0)]);
|
||||
$this->setData(['enrolment', common::$siteContent, $this->getUser('id'), 'datePageView', time()]);
|
||||
|
||||
// Stocke le rapport en CSV
|
||||
$file = fopen(common::DATA_DIR . common::$siteContent . '/report.csv', 'a+');
|
||||
fputcsv($file, [ $this->getUser('id'), $this->getUrl(0) ,time()], ';');
|
||||
fclose($file);
|
||||
|
||||
}
|
||||
|
||||
// Journalisation
|
||||
|
@ -438,7 +439,7 @@ class core extends common
|
|||
// Force la déconnexion des membres bannis ou d'une seconde session
|
||||
if (
|
||||
$this->getUser('password') === $this->getInput('ZWII_USER_PASSWORD')
|
||||
and ($this->getUser('group') === self::GROUP_BANNED
|
||||
and ($this->getUser('group') === common::GROUP_BANNED
|
||||
or ($_SESSION['csrf'] !== $this->getData(['user', $this->getUser('id'), 'accessCsrf'])
|
||||
and $this->getData(['config', 'connect', 'autoDisconnect']) === true)
|
||||
)
|
||||
|
@ -453,7 +454,7 @@ class core extends common
|
|||
and $this->getUrl(1) !== 'login'
|
||||
and ($this->getUser('password') !== $this->getInput('ZWII_USER_PASSWORD')
|
||||
or ($this->getUser('password') === $this->getInput('ZWII_USER_PASSWORD')
|
||||
and $this->getUser('group') < self::GROUP_ADMIN
|
||||
and $this->getUser('group') < common::GROUP_ADMIN
|
||||
)
|
||||
)
|
||||
) {
|
||||
|
@ -466,31 +467,11 @@ class core extends common
|
|||
exit();
|
||||
}
|
||||
|
||||
// Pour éviter une 404 sur une langue étrangère, bascule dans la langue correcte.
|
||||
if (is_null($this->getData(['page', $this->getUrl(0)]))) {
|
||||
foreach ($this->getData(['course']) as $key => $value) {;
|
||||
if (
|
||||
is_dir(self::DATA_DIR . $key) &&
|
||||
file_exists(self::DATA_DIR . $key . '/page.json')
|
||||
) {
|
||||
$pagesId = json_decode(file_get_contents(self::DATA_DIR . $key . '/page.json'), true);
|
||||
if (
|
||||
is_array($pagesId['page']) &&
|
||||
array_key_exists($this->getUrl(0), $pagesId['page'])
|
||||
) {
|
||||
//$_SESSION['ZWII_SITE_CONTENT'] = $key;
|
||||
header('Refresh:0; url=' . helper::baseUrl() . 'course/swap/' . $key . '/' . $this->getUrl(0));
|
||||
exit();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Check l'accès à la page
|
||||
$access = null;
|
||||
if ($this->getData(['page', $this->getUrl(0)]) !== null) {
|
||||
if (
|
||||
$this->getData(['page', $this->getUrl(0), 'group']) === self::GROUP_VISITOR
|
||||
$this->getData(['page', $this->getUrl(0), 'group']) === common::GROUP_VISITOR
|
||||
or ($this->getUser('password') === $this->getInput('ZWII_USER_PASSWORD')
|
||||
// and $this->getUser('group') >= $this->getData(['page', $this->getUrl(0), 'group'])
|
||||
// Modification qui tient compte du profil de la page
|
||||
|
@ -511,7 +492,7 @@ class core extends common
|
|||
and $this->getUser('password') !== $this->getInput('ZWII_USER_PASSWORD')
|
||||
) or ($this->getData(['page', $this->getUrl(0), 'disable']) === true
|
||||
and $this->getUser('password') === $this->getInput('ZWII_USER_PASSWORD')
|
||||
and $this->getUser('group') < self::GROUP_EDITOR
|
||||
and $this->getUser('group') < common::GROUP_EDITOR
|
||||
)
|
||||
) {
|
||||
$access = false;
|
||||
|
@ -537,9 +518,9 @@ class core extends common
|
|||
$this->getUser('id') &&
|
||||
$userId !== $this->getUser('id') &&
|
||||
$this->getData(['user', $userId, 'accessUrl']) === $this->getUrl() &&
|
||||
array_intersect($t, self::$concurrentAccess) &&
|
||||
//array_intersect($t, self::$accessExclude) !== false &&
|
||||
time() < $this->getData(['user', $userId, 'accessTimer']) + self::ACCESS_TIMER
|
||||
array_intersect($t, common::$concurrentAccess) &&
|
||||
//array_intersect($t, common::$accessExclude) !== false &&
|
||||
time() < $this->getData(['user', $userId, 'accessTimer']) + common::ACCESS_TIMER
|
||||
) {
|
||||
$access = false;
|
||||
$accessInfo['userName'] = $this->getData(['user', $userId, 'lastname']) . ' ' . $this->getData(['user', $userId, 'firstname']);
|
||||
|
@ -576,10 +557,10 @@ class core extends common
|
|||
$inlineScript[] = $this->getData(['page', $this->getUrl(0), 'js']) === null ? '' : $this->getData(['page', $this->getUrl(0), 'js']);
|
||||
|
||||
// Importe le contenu, le CSS et le script des barres
|
||||
$contentRight = $this->getData(['page', $this->getUrl(0), 'barRight']) ? $this->getPage($this->getData(['page', $this->getUrl(0), 'barRight']), self::$siteContent) : '';
|
||||
$contentRight = $this->getData(['page', $this->getUrl(0), 'barRight']) ? $this->getPage($this->getData(['page', $this->getUrl(0), 'barRight']), common::$siteContent) : '';
|
||||
$inlineStyle[] = $this->getData(['page', $this->getData(['page', $this->getUrl(0), 'barRight']), 'css']) === null ? '' : $this->getData(['page', $this->getData(['page', $this->getUrl(0), 'barRight']), 'css']);
|
||||
$inlineScript[] = $this->getData(['page', $this->getData(['page', $this->getUrl(0), 'barRight']), 'js']) === null ? '' : $this->getData(['page', $this->getData(['page', $this->getUrl(0), 'barRight']), 'js']);
|
||||
$contentLeft = $this->getData(['page', $this->getUrl(0), 'barLeft']) ? $this->getPage($this->getData(['page', $this->getUrl(0), 'barLeft']), self::$siteContent) : '';
|
||||
$contentLeft = $this->getData(['page', $this->getUrl(0), 'barLeft']) ? $this->getPage($this->getData(['page', $this->getUrl(0), 'barLeft']), common::$siteContent) : '';
|
||||
$inlineStyle[] = $this->getData(['page', $this->getData(['page', $this->getUrl(0), 'barLeft']), 'css']) === null ? '' : $this->getData(['page', $this->getData(['page', $this->getUrl(0), 'barLeft']), 'css']);
|
||||
$inlineScript[] = $this->getData(['page', $this->getData(['page', $this->getUrl(0), 'barLeft']), 'js']) === null ? '' : $this->getData(['page', $this->getData(['page', $this->getUrl(0), 'barLeft']), 'js']);
|
||||
|
||||
|
@ -597,7 +578,7 @@ class core extends common
|
|||
|
||||
$this->addOutput([
|
||||
'title' => $title,
|
||||
'content' => $this->getPage($this->getUrl(0), self::$siteContent),
|
||||
'content' => $this->getPage($this->getUrl(0), common::$siteContent),
|
||||
'metaDescription' => $this->getData(['page', $this->getUrl(0), 'metaDescription']),
|
||||
'metaTitle' => $this->getData(['page', $this->getUrl(0), 'metaTitle']),
|
||||
'typeMenu' => $this->getData(['page', $this->getUrl(0), 'typeMenu']),
|
||||
|
@ -623,7 +604,7 @@ class core extends common
|
|||
: $this->getData(['page', $this->getUrl(0), 'metaDescription']);
|
||||
|
||||
// Importe le CSS de la page principale
|
||||
$pageContent = $this->getPage($this->getUrl(0), self::$siteContent);
|
||||
$pageContent = $this->getPage($this->getUrl(0), common::$siteContent);
|
||||
|
||||
$this->addOutput([
|
||||
'title' => $title,
|
||||
|
@ -668,7 +649,7 @@ class core extends common
|
|||
$output = $module->output;
|
||||
// Check le groupe de l'utilisateur
|
||||
if (
|
||||
($module::$actions[$action] === self::GROUP_VISITOR
|
||||
($module::$actions[$action] === common::GROUP_VISITOR
|
||||
or ($this->getUser('password') === $this->getInput('ZWII_USER_PASSWORD')
|
||||
and $this->getUser('group') >= $module::$actions[$action]
|
||||
and $this->getUser('permission', $moduleId, $action)
|
||||
|
@ -681,10 +662,10 @@ class core extends common
|
|||
foreach ($_POST as $postId => $postValue) {
|
||||
if (is_array($postValue)) {
|
||||
foreach ($postValue as $subPostId => $subPostValue) {
|
||||
self::$inputBefore[$postId . '_' . $subPostId] = $subPostValue;
|
||||
common::$inputBefore[$postId . '_' . $subPostId] = $subPostValue;
|
||||
}
|
||||
} else {
|
||||
self::$inputBefore[$postId] = $postValue;
|
||||
common::$inputBefore[$postId] = $postValue;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -724,9 +705,9 @@ class core extends common
|
|||
// Contenu par vue
|
||||
elseif ($output['view']) {
|
||||
// Chemin en fonction d'un module du coeur ou d'un module
|
||||
$modulePath = in_array($moduleId, self::$coreModuleIds) ? 'core/' : '';
|
||||
$modulePath = in_array($moduleId, common::$coreModuleIds) ? 'core/' : '';
|
||||
// CSS
|
||||
$stylePath = $modulePath . self::MODULE_DIR . $moduleId . '/view/' . $output['view'] . '/' . $output['view'] . '.css';
|
||||
$stylePath = $modulePath . common::MODULE_DIR . $moduleId . '/view/' . $output['view'] . '/' . $output['view'] . '.css';
|
||||
if (file_exists($stylePath)) {
|
||||
$this->addOutput([
|
||||
'style' => file_get_contents($stylePath)
|
||||
|
@ -739,7 +720,7 @@ class core extends common
|
|||
}
|
||||
|
||||
// JS
|
||||
$scriptPath = $modulePath . self::MODULE_DIR . $moduleId . '/view/' . $output['view'] . '/' . $output['view'] . '.js.php';
|
||||
$scriptPath = $modulePath . common::MODULE_DIR . $moduleId . '/view/' . $output['view'] . '/' . $output['view'] . '.js.php';
|
||||
if (file_exists($scriptPath)) {
|
||||
ob_start();
|
||||
include $scriptPath;
|
||||
|
@ -748,7 +729,7 @@ class core extends common
|
|||
]);
|
||||
}
|
||||
// Vue
|
||||
$viewPath = $modulePath . self::MODULE_DIR . $moduleId . '/view/' . $output['view'] . '/' . $output['view'] . '.php';
|
||||
$viewPath = $modulePath . common::MODULE_DIR . $moduleId . '/view/' . $output['view'] . '/' . $output['view'] . '.php';
|
||||
if (file_exists($viewPath)) {
|
||||
ob_start();
|
||||
include $viewPath;
|
||||
|
@ -822,8 +803,9 @@ class core extends common
|
|||
} else {
|
||||
if (
|
||||
$this->getData(['config', 'page403']) !== 'none'
|
||||
and $this->getData(['page', $this->getData(['config', 'page403'])])
|
||||
//and $this->getData(['page', $this->getData(['config', 'page403'])])
|
||||
) {
|
||||
$_SESSION['ZWII_SITE_CONTENT'] = 'home';
|
||||
header('Location:' . helper::baseUrl() . $this->getData(['config', 'page403']));
|
||||
} else {
|
||||
$this->addOutput([
|
||||
|
@ -833,13 +815,40 @@ class core extends common
|
|||
}
|
||||
}
|
||||
} elseif ($this->output['content'] === '') {
|
||||
|
||||
// Pour éviter une 404, bascule dans l'espace correct si la page existe dans cet espace.
|
||||
// Parcourir les espaces y compris l'accueil
|
||||
foreach (array_merge(['home'=> []], $this->getData(['course'])) as $courseId => $value) {;
|
||||
if (
|
||||
// l'espace existe
|
||||
is_dir(common::DATA_DIR . $courseId) &&
|
||||
file_exists(common::DATA_DIR . $courseId . '/page.json')
|
||||
) {
|
||||
// Lire les données des pages
|
||||
$pagesId = json_decode(file_get_contents(common::DATA_DIR . $courseId . '/page.json'), true);
|
||||
if (
|
||||
// La page existe
|
||||
is_array($pagesId['page']) &&
|
||||
array_key_exists($this->getUrl(0), $pagesId['page'])
|
||||
) {
|
||||
// Basculer
|
||||
$_SESSION['ZWII_SITE_CONTENT'] = $courseId;
|
||||
header('Refresh:0; url=' . helper::baseUrl() . $this->getUrl());
|
||||
exit();
|
||||
}
|
||||
}
|
||||
}
|
||||
// La page n'existe pas dans les esapces, on génére une erreur 404
|
||||
http_response_code(404);
|
||||
if (
|
||||
// une page est définie dans la configuration mais dans home
|
||||
$this->getData(['config', 'page404']) !== 'none'
|
||||
and $this->getData(['page', $this->getData(['config', 'page404'])])
|
||||
) {
|
||||
// Bascule sur l'acccueil et rediriger
|
||||
$_SESSION['ZWII_SITE_CONTENT'] = 'home';
|
||||
header('Location:' . helper::baseUrl() . $this->getData(['config', 'page404']));
|
||||
} else {
|
||||
// Page par défaut
|
||||
$this->addOutput([
|
||||
'title' => 'Page indisponible',
|
||||
'content' => template::speech('<p>' . helper::translate('La page demandée n\'existe pas ou est introuvable (erreur 404)') . '</p><p><a style="color:inherit" href="javascript:history.back()">'. helper::translate('Retour') . '</a></p>')
|
||||
|
@ -865,25 +874,25 @@ class core extends common
|
|||
}
|
||||
switch ($this->output['display']) {
|
||||
// Layout brut
|
||||
case self::DISPLAY_RAW:
|
||||
case common::DISPLAY_RAW:
|
||||
echo $this->output['content'];
|
||||
break;
|
||||
// Layout vide
|
||||
case self::DISPLAY_LAYOUT_BLANK:
|
||||
case common::DISPLAY_LAYOUT_BLANK:
|
||||
require 'core/layout/blank.php';
|
||||
break;
|
||||
// Affichage en JSON
|
||||
case self::DISPLAY_JSON:
|
||||
case common::DISPLAY_JSON:
|
||||
header('Content-Type: application/json');
|
||||
echo json_encode($this->output['content']);
|
||||
break;
|
||||
// RSS feed
|
||||
case self::DISPLAY_RSS:
|
||||
case common::DISPLAY_RSS:
|
||||
header('Content-type: application/rss+xml; charset=UTF-8');
|
||||
echo $this->output['content'];
|
||||
break;
|
||||
// Layout allégé
|
||||
case self::DISPLAY_LAYOUT_LIGHT:
|
||||
case common::DISPLAY_LAYOUT_LIGHT:
|
||||
ob_start();
|
||||
require 'core/layout/light.php';
|
||||
$content = ob_get_clean();
|
||||
|
@ -894,7 +903,7 @@ class core extends common
|
|||
echo $content;
|
||||
break;
|
||||
// Layout principal
|
||||
case self::DISPLAY_LAYOUT_MAIN:
|
||||
case common::DISPLAY_LAYOUT_MAIN:
|
||||
ob_start();
|
||||
require 'core/layout/main.php';
|
||||
$content = ob_get_clean();
|
||||
|
|
|
@ -291,7 +291,7 @@ core.start = function () {
|
|||
});
|
||||
// Confirmation de mise à jour
|
||||
$("#barUpdate").on("click", function () {
|
||||
message = "<?php echo helper::translate('Mettre à jour') . ' ?';?>";
|
||||
message = "<?php echo helper::translate('Mise à jour') . ' ?';?>";
|
||||
return core.confirm(message, function () {
|
||||
$(location).attr("href", $("#barUpdate").attr("href"));
|
||||
});
|
||||
|
|
121
core/core.php
121
core/core.php
|
@ -51,7 +51,7 @@ class common
|
|||
const ACCESS_TIMER = 1800;
|
||||
|
||||
// Numéro de version
|
||||
const ZWII_VERSION = '1.4.14';
|
||||
const ZWII_VERSION = '1.10.04';
|
||||
|
||||
// URL autoupdate
|
||||
const ZWII_UPDATE_URL = 'https://forge.chapril.org/ZwiiCMS-Team/campus-update/raw/branch/master/';
|
||||
|
@ -148,24 +148,24 @@ class common
|
|||
self::GROUP_BANNED => 'Banni',
|
||||
self::GROUP_VISITOR => 'Visiteur',
|
||||
self::GROUP_MEMBER => 'Étudiant',
|
||||
self::GROUP_EDITOR => 'Enseignant',
|
||||
self::GROUP_EDITOR => 'Formateur',
|
||||
self::GROUP_ADMIN => 'Administrateur'
|
||||
];
|
||||
public static $groupEdits = [
|
||||
self::GROUP_BANNED => 'Banni',
|
||||
self::GROUP_MEMBER => 'Étudiant',
|
||||
self::GROUP_EDITOR => 'Enseignant',
|
||||
self::GROUP_EDITOR => 'Formateur',
|
||||
self::GROUP_ADMIN => 'Administrateur'
|
||||
];
|
||||
public static $groupNews = [
|
||||
self::GROUP_MEMBER => 'Étudiant',
|
||||
self::GROUP_EDITOR => 'Enseignant',
|
||||
self::GROUP_EDITOR => 'Formateur',
|
||||
self::GROUP_ADMIN => 'Administrateur'
|
||||
];
|
||||
public static $groupPublics = [
|
||||
self::GROUP_VISITOR => 'Visiteur',
|
||||
self::GROUP_MEMBER => 'Étudiant',
|
||||
self::GROUP_EDITOR => 'Enseignant',
|
||||
self::GROUP_EDITOR => 'Formateur',
|
||||
self::GROUP_ADMIN => 'Administrateur'
|
||||
];
|
||||
|
||||
|
@ -176,6 +176,7 @@ class common
|
|||
public static $i18nUI = 'fr_FR';
|
||||
// Langues de contenu
|
||||
public static $siteContent = 'home';
|
||||
|
||||
public static $languages = [
|
||||
'de' => 'Deutsch',
|
||||
'en_EN' => 'English',
|
||||
|
@ -327,14 +328,12 @@ class common
|
|||
$this->input['_COOKIE'] = $_COOKIE;
|
||||
}
|
||||
|
||||
// Extraction de la sesion
|
||||
// $this->input['_SESSION'] = $_SESSION;
|
||||
|
||||
// Déterminer le contenu du site
|
||||
if (isset($_SESSION['ZWII_SITE_CONTENT'])) {
|
||||
// Déterminé par la session présente
|
||||
self::$siteContent = $_SESSION['ZWII_SITE_CONTENT'];
|
||||
}
|
||||
|
||||
// Instanciation de la classe des entrées / sorties
|
||||
// Les fichiers de configuration
|
||||
foreach ($this->configFiles as $module => $value) {
|
||||
|
@ -345,7 +344,6 @@ class common
|
|||
$this->initDB($module, self::$siteContent);
|
||||
}
|
||||
|
||||
|
||||
// Installation fraîche, initialisation de la configuration inexistante
|
||||
// Nécessaire pour le constructeur
|
||||
if ($this->user === []) {
|
||||
|
@ -450,7 +448,7 @@ class common
|
|||
}
|
||||
|
||||
// Mise à jour des données core
|
||||
include('core/include/update.inc.php');
|
||||
include ('core/include/update.inc.php');
|
||||
|
||||
}
|
||||
|
||||
|
@ -598,7 +596,7 @@ class common
|
|||
public function setPage($page, $value, $path)
|
||||
{
|
||||
|
||||
return file_put_contents(self::DATA_DIR . $path . '/content/' . $page . '.html', $value);
|
||||
return $this->secure_file_put_contents(self::DATA_DIR . $path . '/content/' . $page . '.html', $value);
|
||||
}
|
||||
|
||||
|
||||
|
@ -614,13 +612,54 @@ 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 = '')
|
||||
{
|
||||
// Instanciation de la classe des entrées / sorties
|
||||
// Constructeur JsonDB;
|
||||
$this->dataFiles[$module] = new \Prowebcraft\JsonDb([
|
||||
'name' => $module . '.json',
|
||||
'dir' => self::DATA_DIR . $path . '/',
|
||||
'dir' => empty($path) ? self::DATA_DIR : self::DATA_DIR . $path . '/',
|
||||
'backup' => file_exists('site/data/.backup')
|
||||
]);
|
||||
|
||||
|
@ -637,7 +676,7 @@ class common
|
|||
{
|
||||
|
||||
// Tableau avec les données vierges
|
||||
require_once('core/module/install/ressource/defaultdata.php');
|
||||
require_once ('core/module/install/ressource/defaultdata.php');
|
||||
|
||||
// L'arborescence
|
||||
if (!file_exists(self::DATA_DIR . $path)) {
|
||||
|
@ -672,7 +711,7 @@ class common
|
|||
public function saveConfig($module)
|
||||
{
|
||||
// Tableau avec les données vierges
|
||||
require_once('core/module/install/ressource/defaultdata.php');
|
||||
require_once ('core/module/install/ressource/defaultdata.php');
|
||||
// Installation des données des autres modules cad theme profil font config, admin et core
|
||||
$this->setData([$module, init::$defaultData[$module]]);
|
||||
common::$coreNotices[] = $module;
|
||||
|
@ -716,7 +755,7 @@ class common
|
|||
foreach ($pages as $pageId => $pagePosition) {
|
||||
if (
|
||||
// Page parent
|
||||
$this->getData(['page', $pageId, 'parentPageId']) === ''
|
||||
$this->getData(['page', $pageId, 'parentPageId']) === ""
|
||||
// Ignore les pages dont l'utilisateur n'a pas accès
|
||||
and ($this->getData(['page', $pageId, 'group']) === self::GROUP_VISITOR
|
||||
or ($this->getUser('password') === $this->getInput('ZWII_USER_PASSWORD')
|
||||
|
@ -738,21 +777,21 @@ class common
|
|||
}
|
||||
// Enfants
|
||||
foreach ($pages as $pageId => $pagePosition) {
|
||||
|
||||
if (
|
||||
// Page parent
|
||||
$parentId = $this->getData(['page', $pageId, 'parentPageId'])
|
||||
// Ignore les pages dont l'utilisateur n'a pas accès
|
||||
and (
|
||||
($this->getData(['page', $pageId, 'group']) === self::GROUP_VISITOR
|
||||
and $this->getData(['page', $parentId, 'group']) === self::GROUP_VISITOR
|
||||
(
|
||||
$this->getData(['page', $pageId, 'group']) === self::GROUP_VISITOR
|
||||
and
|
||||
$this->getData(['page', $parentId, 'group']) === self::GROUP_VISITOR
|
||||
)
|
||||
or ($this->getUser('password') === $this->getInput('ZWII_USER_PASSWORD')
|
||||
//and $this->getUser('group') >= $this->getData(['page', $parentId, 'group'])
|
||||
//and $this->getUser('group') >= $this->getData(['page', $pageId, 'group'])
|
||||
|
||||
// Modification qui tient compte du profil de la page
|
||||
and ($this->getUser('group') * self::MAX_PROFILS + $this->getUser('profil')) >= ($this->getData(['page', $this->$parentId, 'group']) * self::MAX_PROFILS + $this->getData(['page', $this->$parentId, 'profil']))
|
||||
and ($this->getUser('group') * self::MAX_PROFILS + $this->getUser('profil')) >= ($this->getData(['page', $this->$pageId, 'group']) * self::MAX_PROFILS + $this->getData(['page', $pageId, 'profil']))
|
||||
or (
|
||||
$this->getUser('password') === $this->getInput('ZWII_USER_PASSWORD')
|
||||
and
|
||||
$this->getUser('group') * self::MAX_PROFILS + $this->getUser('profil')) >= ($this->getData(['page', $pageId, 'group']) * self::MAX_PROFILS + $this->getData(['page', $pageId, 'profil'])
|
||||
|
||||
)
|
||||
)
|
||||
|
@ -1066,8 +1105,9 @@ class common
|
|||
}
|
||||
// Articles du blog
|
||||
if (
|
||||
$this->getData(['page', $parentPageId, 'moduleId']) === 'blog' &&
|
||||
!empty($this->getData(['module', $parentPageId]))
|
||||
$this->getData(['page', $parentPageId, 'moduleId']) === 'blog'
|
||||
&& !empty($this->getData(['module', $parentPageId]))
|
||||
&& $this->getData(['module', $parentPageId, 'posts'])
|
||||
) {
|
||||
foreach ($this->getData(['module', $parentPageId, 'posts']) as $articleId => $article) {
|
||||
if ($this->getData(['module', $parentPageId, 'posts', $articleId, 'state']) === true) {
|
||||
|
@ -1405,7 +1445,7 @@ class common
|
|||
public function saveLog($message = '')
|
||||
{
|
||||
// Journalisation
|
||||
$dataLog = helper::dateUTF8('%Y%m%d', time(), self::$siteContent) . ';' . helper::dateUTF8('%H:%M', time(), self::$siteContent) . ';';
|
||||
$dataLog = helper::dateUTF8('%Y%m%d', time(), self::$i18nUI) . ';' . helper::dateUTF8('%H:%M', time(), self::$i18nUI) . ';';
|
||||
$dataLog .= helper::getIp($this->getData(['config', 'connect', 'anonymousIp'])) . ';';
|
||||
$dataLog .= empty($this->getUser('id')) ? 'visitor;' : $this->getUser('id') . ';';
|
||||
$dataLog .= $message ? $this->getUrl() . ';' . $message : $this->getUrl();
|
||||
|
@ -1422,39 +1462,39 @@ class common
|
|||
* @param string $userId identifiant
|
||||
* @param string $serStatus teacher ou student ou admin
|
||||
*
|
||||
* CETTE FONCTION N'EST PAS UTILISEE
|
||||
* CETTE FONCTION EST UTILISEE PAR LAYOUT
|
||||
*
|
||||
*/
|
||||
public function getCoursesByUser()
|
||||
public function getCoursesByProfil()
|
||||
{
|
||||
$courses = $this->getData([('course')]);
|
||||
$courses = helper::arraycolumn($courses, 'title', 'SORT_ASC');
|
||||
$filter = array();
|
||||
$userId = $this->getUser('id');
|
||||
switch ($this->getUser('group')) {
|
||||
case self::GROUP_ADMIN:
|
||||
// Affiche tout
|
||||
return $courses;
|
||||
case self::GROUP_EDITOR:
|
||||
foreach ($courses as $courseId => $value) {
|
||||
$students = $this->getData(['enrolment', $courseId]);
|
||||
// Affiche les espaces gérés par l'éditeur, les espaces où il participe et les espaces ouverts
|
||||
// Affiche les espaces gérés par l'éditeur, les espaces où il participe et les espaces anonymes
|
||||
if (
|
||||
isset($students[$userId]) === true ||
|
||||
$this->getData(['course', $courseId, 'author']) === $userId ||
|
||||
$this->getData(['course', $courseId, 'enrolment']) === self::COURSE_ENROLMENT_GUEST
|
||||
// le membre est inscrit
|
||||
($this->getData(['enrolment', $courseId]) && array_key_exists($this->getUser('id'), $this->getData(['enrolment', $courseId])))
|
||||
// Il est l'auteur
|
||||
|| $this->getUser('id') === $this->getData(['course', $courseId, 'author'])
|
||||
// Le cours est ouvert
|
||||
|| $this->getData(['course', $courseId, 'enrolment']) === self::COURSE_ENROLMENT_GUEST
|
||||
) {
|
||||
$filter[$courseId] = $courses[$courseId];
|
||||
}
|
||||
}
|
||||
return $courses;
|
||||
return $filter;
|
||||
case self::GROUP_MEMBER:
|
||||
foreach ($courses as $courseId => $value) {
|
||||
// Affiche les espaces du participant et les espaces anonymes
|
||||
$students = $this->getData(['enrolment', $courseId]);
|
||||
// Affiche les espaces du participant et les espaces anonymes
|
||||
if (
|
||||
isset($students[$userId]) === true ||
|
||||
$this->getData(['course', $courseId, 'enrolment']) === self::COURSE_ENROLMENT_GUEST
|
||||
($this->getData(['enrolment', $courseId]) && array_key_exists($this->getUser('id'), $this->getData(['enrolment', $courseId])))
|
||||
|| $this->getData(['course', $courseId, 'enrolment']) === self::COURSE_ENROLMENT_GUEST
|
||||
) {
|
||||
$filter[$courseId] = $courses[$courseId];
|
||||
}
|
||||
|
@ -1464,7 +1504,6 @@ class common
|
|||
foreach ($courses as $courseId => $value) {
|
||||
// Affiche les espaces anonymes
|
||||
if ($this->getData(['course', $courseId, 'enrolment']) === self::COURSE_ENROLMENT_GUEST) {
|
||||
echo $this->getData(['course', $courseId, 'access']) ;
|
||||
$filter[$courseId] = $courses[$courseId];
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,5 +1,48 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* Mises à jour suivant les versions de Zwii
|
||||
* Mises à jour suivant les versions de ZwiiCampus
|
||||
*/
|
||||
|
||||
|
||||
if (
|
||||
$this->getData(['core', 'dataVersion']) < 1700
|
||||
) {
|
||||
// Supprime la variable path des profils, seul l'accès à l'espace et autorisé.
|
||||
foreach (['1', '2'] as $group) {
|
||||
foreach (array_keys($this->getData(['profil', $group])) as $profil) {
|
||||
if (is_null($this->getData(['profil', $group, $profil, 'folder', 'path'])) === false) {
|
||||
$path = $this->getData(['profil', $group, $profil, 'folder', 'path']);
|
||||
$this->setData(['profil', $group, $profil, 'folder', 'homePath', $path]);
|
||||
$this->setData(['profil', $group, $profil, 'folder', 'coursePath', $path]);
|
||||
$this->deleteData(['profil', $group, $profil, 'folder', 'path']);
|
||||
}
|
||||
}
|
||||
}
|
||||
$this->setData(['core', 'dataVersion', 1700]);
|
||||
}
|
||||
|
||||
|
||||
if (
|
||||
$this->getData(['core', 'dataVersion']) < 1800
|
||||
) {
|
||||
// Parcourir la structure pour écrire dans les fichiers CSV
|
||||
foreach ($this->getData(['enrolment']) as $courseId => $users) {
|
||||
$filename = self::DATA_DIR . $courseId . '/report.csv';
|
||||
$fp = fopen($filename, 'w');
|
||||
foreach ($users as $userId => $userData) {
|
||||
$history = array_key_exists('history', $userData) ? $userData['history'] : null;
|
||||
|
||||
if (is_array($history)) {
|
||||
foreach ($history as $pageId => $timestamps) {
|
||||
foreach ($timestamps as $timestamp) {
|
||||
fputcsv($fp, [$userId, $pageId, $timestamp], ';');
|
||||
}
|
||||
}
|
||||
}
|
||||
$this->deleteData(['enrolment', $courseId, $userId, 'history']);
|
||||
}
|
||||
fclose($fp);
|
||||
}
|
||||
$this->setData(['core', 'dataVersion', 1800]);
|
||||
}
|
|
@ -118,7 +118,7 @@ h3 {
|
|||
font-size: 1.4em;
|
||||
}
|
||||
|
||||
h4 {
|
||||
h4, details {
|
||||
font-size: 1.0em;
|
||||
}
|
||||
|
||||
|
@ -161,7 +161,8 @@ h4,
|
|||
p,
|
||||
hr,
|
||||
ul,
|
||||
ol {
|
||||
ol,
|
||||
details {
|
||||
margin: 15px 0;
|
||||
}
|
||||
|
||||
|
@ -618,6 +619,8 @@ nav #menuSelectCourse {
|
|||
font-size: 1em;
|
||||
background-color: rgba(255, 255, 255, 1);
|
||||
line-height: 45px;
|
||||
padding: 5px 10px;
|
||||
margin: 0px 10px;
|
||||
}
|
||||
|
||||
|
||||
|
@ -1125,7 +1128,7 @@ footer #footerSocials .zwiico-twitch:hover {
|
|||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
.block h4 {
|
||||
.block h4, details {
|
||||
margin: -20px -20px 10px -20px;
|
||||
padding: 10px;
|
||||
/* background: #ECEFF1;*/
|
||||
|
|
|
@ -429,6 +429,17 @@ class config extends common
|
|||
*/
|
||||
public function index()
|
||||
{
|
||||
|
||||
// Action interdite hors de l'espace accueil
|
||||
if (
|
||||
self::$siteContent !== 'home'
|
||||
) {
|
||||
// Valeurs en sortie
|
||||
$this->addOutput([
|
||||
'access' => false
|
||||
]);
|
||||
}
|
||||
|
||||
// Soumission du formulaire
|
||||
if (
|
||||
$this->getUser('permission', __CLASS__, __FUNCTION__) === true &&
|
||||
|
@ -479,7 +490,7 @@ class config extends common
|
|||
'cookiesFooterText' => $this->getInput('configLocaleCookiesFooterText', helper::FILTER_STRING_SHORT, $this->getInput('configCookieConsent', helper::FILTER_BOOLEAN)),
|
||||
'buttonValidLabel' => $this->getInput('configLocaleCookiesButtonText', helper::FILTER_STRING_SHORT, $this->getInput('configCookieConsent', helper::FILTER_BOOLEAN)),
|
||||
],
|
||||
'social' => [
|
||||
'social' => [
|
||||
'facebookId' => $this->getInput('socialFacebookId'),
|
||||
'linkedinId' => $this->getInput('socialLinkedinId'),
|
||||
'instagramId' => $this->getInput('socialInstagramId'),
|
||||
|
@ -545,7 +556,7 @@ class config extends common
|
|||
) {
|
||||
// Ajout des lignes dans le .htaccess
|
||||
$fileContent = file_get_contents('.htaccess');
|
||||
$rewriteData = PHP_EOL .
|
||||
$rewriteData =
|
||||
'# URL rewriting' . PHP_EOL .
|
||||
'<IfModule mod_rewrite.c>' . PHP_EOL .
|
||||
"\tRewriteEngine on" . PHP_EOL .
|
||||
|
@ -554,7 +565,7 @@ class config extends common
|
|||
"\tRewriteCond %{REQUEST_FILENAME} !-d" . PHP_EOL .
|
||||
"\tRewriteRule ^(.*)$ index.php?$1 [L]" . PHP_EOL .
|
||||
'</IfModule>' . PHP_EOL .
|
||||
'# URL rewriting' . PHP_EOL;
|
||||
'# URL rewriting';
|
||||
$fileContent = str_replace('# URL rewriting', $rewriteData, $fileContent);
|
||||
file_put_contents(
|
||||
'.htaccess',
|
||||
|
@ -607,7 +618,7 @@ class config extends common
|
|||
|
||||
// Variable de version
|
||||
if (helper::checkNewVersion(common::ZWII_UPDATE_CHANNEL)) {
|
||||
self::$updateButtonText = helper::translate('Mettre à jour');
|
||||
self::$updateButtonText = helper::translate('Mise à jour');
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -0,0 +1,4 @@
|
|||
<Files "data.key">
|
||||
Order Allow,Deny
|
||||
Deny from all
|
||||
</Files>
|
|
@ -0,0 +1,68 @@
|
|||
<?php
|
||||
|
||||
/*
|
||||
Ce script PHP est conçu pour être appelé via une requête HTTP GET avec une clé spécifique pour déclencher la création d'une archive ZIP de sauvegarde.
|
||||
|
||||
Exemple d'appel dans une URL :
|
||||
http://example.com/chemin/vers/autobackup.php?key=your_secret_key&filter=site
|
||||
|
||||
La clé doit être fournie en tant que paramètre "key" dans l'URL et correspondre à celle stockée dans le fichier "data.key" pour que la création de l'archive soit autorisée. Si la clé est valide, le script parcourt le répertoire spécifié en fonction du paramètre "filter" et ajoute les fichiers à l'archive ZIP. Si la clé est invalide ou absente, le script renvoie une réponse avec le code d'erreur 401 Unauthorized.
|
||||
|
||||
Le paramètre "filter" en GET permet de spécifier le filtre à appliquer lors de la création de l'archive. Sa valeur peut être "file" ou "data". Si le paramètre n'est pas spécifié, le filtre est vide par défaut, ce qui signifie que tous les fichiers seront inclus dans l'archive.
|
||||
|
||||
*/
|
||||
|
||||
// Vérification de la clé
|
||||
if (isset($_GET['key'])) {
|
||||
$key = $_GET['key'];
|
||||
$storedKey = file_get_contents('data.key');
|
||||
if ($key !== $storedKey) {
|
||||
http_response_code(401); // Clé invalide, renvoie une réponse avec le code d'erreur 401 Unauthorized
|
||||
echo 'Clé incorrecte';
|
||||
exit;
|
||||
}
|
||||
|
||||
// Définition du filtre par défaut
|
||||
$filter = ['backup', 'tmp', 'i18n'];
|
||||
|
||||
// Tableau de correspondance entre les valeurs de "filter" et les répertoires à inclure
|
||||
$filterDirectories = [
|
||||
'file' => ['backup', 'tmp', 'file'],
|
||||
'data' => ['backup', 'tmp', 'data'],
|
||||
];
|
||||
|
||||
// Vérification et traitement du paramètre "filter" en GET
|
||||
if (isset($_GET['filter']) && isset($filterDirectories[$_GET['filter']])) {
|
||||
$filter = $filterDirectories[$_GET['filter']];
|
||||
}
|
||||
|
||||
// Création du ZIP
|
||||
$fileName = date('Y-m-d-H-i-s', time()) . '-rolling-backup.zip';
|
||||
$zip = new ZipArchive();
|
||||
$zip->open('../../../../site/backup/' . $fileName, ZipArchive::CREATE | ZipArchive::OVERWRITE);
|
||||
$directory = '../../../../site';
|
||||
$files = new RecursiveIteratorIterator(
|
||||
new RecursiveCallbackFilterIterator(
|
||||
new RecursiveDirectoryIterator(
|
||||
$directory,
|
||||
RecursiveDirectoryIterator::SKIP_DOTS
|
||||
),
|
||||
function ($fileInfo, $key, $iterator) use ($filter) {
|
||||
return $fileInfo->isFile() || !in_array($fileInfo->getBaseName(), $filter);
|
||||
}
|
||||
)
|
||||
);
|
||||
foreach ($files as $name => $file) {
|
||||
if (!$file->isDir()) {
|
||||
$filePath = $file->getRealPath();
|
||||
$relativePath = substr($filePath, strlen(realpath($directory)) + 1);
|
||||
$zip->addFile($filePath, $relativePath);
|
||||
}
|
||||
}
|
||||
$zip->close();
|
||||
|
||||
http_response_code(201); // Création de l'archive réussie, renvoie une réponse avec le code 201 Created
|
||||
echo 'Sauvegarde terminée';
|
||||
exit;
|
||||
}
|
||||
?>
|
|
@ -0,0 +1,52 @@
|
|||
<?php
|
||||
|
||||
/*
|
||||
Ce script PHP est conçu pour supprimer les fichiers ayant l'extension 'tar.gz' dans un répertoire de sauvegarde si leur dernière modification remonte à un certain nombre de jours spécifié via une requête HTTP GET.
|
||||
|
||||
Exemple d'appel dans une URL avec le nombre de jours spécifié :
|
||||
http://example.com/chemin/vers/script.php?days=7&key=your_secret_key
|
||||
|
||||
Le script vérifie également la présence et la validité d'une clé spécifique pour déclencher son exécution. La clé doit être fournie en tant que paramètre "key" dans l'URL et correspondre à celle stockée dans le fichier "data.key" pour que la suppression des fichiers soit autorisée. Si la clé est invalide ou absente, le script affiche un message d'erreur et termine son exécution.
|
||||
|
||||
*/
|
||||
|
||||
// Vérification de la clé
|
||||
if (isset ($_GET['key'])) {
|
||||
// Récupération de la clé fournie en GET
|
||||
$key = $_GET['key'];
|
||||
|
||||
// Récupération de la clé stockée dans le fichier data.key
|
||||
$storedKey = file_get_contents('data.key');
|
||||
|
||||
// Vérification de correspondance entre les clés
|
||||
if ($key !== $storedKey) {
|
||||
http_response_code(401);
|
||||
echo 'Clé incorrecte';
|
||||
exit;
|
||||
}
|
||||
|
||||
// Récupère le nombre de jours à partir de la variable GET 'days'
|
||||
$days = isset ($_GET['days']) ? (int) $_GET['days'] : 1; // Par défaut à 1 si non spécifié
|
||||
|
||||
// Chemin vers le répertoire contenant les fichiers
|
||||
$directory = '../../../../site/backup/'; // Remplacez par le chemin réel
|
||||
|
||||
// Convertit le nombre de jours en secondes
|
||||
$timeLimit = strtotime("-$days days");
|
||||
|
||||
// Crée un nouvel objet DirectoryIterator
|
||||
foreach (new DirectoryIterator($directory) as $file) {
|
||||
// Vérifie si l'élément courant est un fichier et a l'extension 'tar.gz'
|
||||
if ($file->isFile() && $file->getExtension() === 'tar.gz') {
|
||||
// Vérifie si le fichier a été modifié avant la limite de temps
|
||||
if ($file->getMTime() < $timeLimit) {
|
||||
// Supprime le fichier
|
||||
unlink($file->getRealPath());
|
||||
}
|
||||
}
|
||||
}
|
||||
// Si la clé est manquante, affiche un message d'erreur et arrête l'exécution du script
|
||||
http_response_code(201);
|
||||
echo 'Sauvegarde terminée';
|
||||
exit;
|
||||
}
|
|
@ -7,7 +7,7 @@
|
|||
'value' => template::ico('left')
|
||||
]); ?>
|
||||
</div>
|
||||
<div class="col2 offset8">
|
||||
<div class="col2 offset9">
|
||||
<?php echo template::submit('configManageSubmit', [
|
||||
'value' => 'Valider',
|
||||
'ico' => 'check'
|
||||
|
|
|
@ -48,7 +48,7 @@
|
|||
<?php echo template::checkbox('configRewrite', true, 'Apache URL intelligentes', [
|
||||
'checked' => helper::checkRewrite(),
|
||||
'help' => 'Supprime le point d\'interrogation dans les URL, l\'option est indisponible avec les autres serveurs Web',
|
||||
'disabled' => stripos($_SERVER["SERVER_SOFTWARE"], 'nginx')
|
||||
'disabled' => !in_array('mod_rewrite',apache_get_modules())
|
||||
]); ?>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
@ -28,7 +28,7 @@
|
|||
</div>
|
||||
<div class="row">
|
||||
<div class="col10 textAlignCenter">
|
||||
<?php if( $module::$imageOpenGraph['type']): ?>
|
||||
<?php if( !empty($module::$imageOpenGraph['type']) ): ?>
|
||||
<p>
|
||||
<?php echo sprintf('%s : <span id="screenType">%s</span>', helper::translate('Format'), $module::$imageOpenGraph['type']); ?>
|
||||
</p>
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -106,4 +106,5 @@
|
|||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<?php echo template::formClose(); ?>
|
||||
</div>
|
||||
<?php echo template::formClose(); ?>
|
|
@ -17,11 +17,22 @@ $(document).ready(function () {
|
|||
url: "core/vendor/datatables/french.json"
|
||||
},
|
||||
locale: 'fr',
|
||||
stateSave: true,
|
||||
"columnDefs": [
|
||||
{
|
||||
target: 2,
|
||||
orderable: false,
|
||||
searchable: false
|
||||
},
|
||||
{
|
||||
target: 3,
|
||||
orderable: false,
|
||||
searchable: false
|
||||
},
|
||||
{
|
||||
target: 4,
|
||||
orderable: false,
|
||||
searchable: false
|
||||
}
|
||||
]
|
||||
});
|
||||
|
|
|
@ -6,41 +6,38 @@
|
|||
'value' => template::ico('home')
|
||||
]); ?>
|
||||
</div>
|
||||
<?php if ($this->getUser('group') === self::GROUP_ADMIN): ?>
|
||||
<div class="col1 offset8">
|
||||
<?php echo template::button('courseUpload', [
|
||||
'href' => helper::baseUrl() . 'course/restore/',
|
||||
'value' => template::ico('upload-cloud'),
|
||||
'help' => 'Restaurer'
|
||||
]); ?>
|
||||
</div>
|
||||
<div class="col1">
|
||||
<?php echo template::button('courseCategory', [
|
||||
'href' => helper::baseUrl() . 'course/category',
|
||||
'value' => template::ico('table'),
|
||||
'help' => 'Catégories'
|
||||
]); ?>
|
||||
</div>
|
||||
<div class="col1">
|
||||
<div class="col1 offset8">
|
||||
<?php if ($this->getUser('permission', 'course', 'add') === true): ?>
|
||||
<?php echo template::button('courseAdd', [
|
||||
'class' => 'buttonGreen',
|
||||
'href' => helper::baseUrl() . 'course/add',
|
||||
'value' => template::ico('plus'),
|
||||
'help' => 'Ajouter un espace'
|
||||
]); ?>
|
||||
</div>
|
||||
<?php else: ?>
|
||||
<div class="col1 offset10">
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
<div class="col1">
|
||||
<?php if ($this->getUser('permission', 'course', 'category') === true): ?>
|
||||
<?php echo template::button('courseCategory', [
|
||||
'href' => helper::baseUrl() . 'course/category',
|
||||
'value' => template::ico('table'),
|
||||
'help' => 'Catégories des espaces'
|
||||
]); ?>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
<div class="col1">
|
||||
<?php if ($this->getUser('permission', 'course', 'restore') === true): ?>
|
||||
<?php echo template::button('courseUpload', [
|
||||
'href' => helper::baseUrl() . 'course/restore/',
|
||||
'value' => template::ico('upload-cloud'),
|
||||
'help' => 'Restaurer depuis le dossier de l\'espace ' . self::$siteContent
|
||||
'help' => 'Restaurer un espace'
|
||||
]); ?>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
<?php endif; ?>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
<?php if ($module::$courses): ?>
|
||||
<?php echo template::table([4, 4, 3, 1 ], $module::$courses, ['Titre court', 'Description', 'Inscription', '',], ['id' => 'dataTables']); ?>
|
||||
<?php echo template::table([4, 3, 3, 1, 1], $module::$courses, ['Titre court', 'Description', 'Inscription', '', '',], ['id' => 'dataTables']); ?>
|
||||
<?php else: ?>
|
||||
<?php echo template::speech('Aucun espace'); ?>
|
||||
<?php endif; ?>
|
|
@ -20,4 +20,15 @@ $(".courseDelete").on("click", function () {
|
|||
return core.confirm(message, function () {
|
||||
$(location).attr("href", _this.attr("href"));
|
||||
});
|
||||
});
|
||||
|
||||
/**
|
||||
* Confirmation de suppression
|
||||
*/
|
||||
$(".courseReset").on("click", function () {
|
||||
var _this = $(this);
|
||||
var message = "<?php echo helper::translate('Réinitialiser cet espace ?'); ?>";
|
||||
return core.confirm(message, function () {
|
||||
$(location).attr("href", _this.attr("href"));
|
||||
});
|
||||
});
|
|
@ -7,149 +7,161 @@
|
|||
]); ?>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col2 offset1">
|
||||
<?php echo template::button('categoryUser' . $this->getUrl(2), [
|
||||
'href' => helper::baseUrl() . 'course/users/' . $this->getUrl(2),
|
||||
'value' => 'Participants',
|
||||
'ico' => 'users'
|
||||
]); ?>
|
||||
</div>
|
||||
<div class="col2">
|
||||
<?php echo template::button('courseManageEdit' . $this->getUrl(2), [
|
||||
'href' => helper::baseUrl() . 'course/edit/' . $this->getUrl(2),
|
||||
'value' => 'Éditer',
|
||||
'ico' => 'pencil'
|
||||
]); ?>
|
||||
</div>
|
||||
<div class="col2">
|
||||
<?php echo
|
||||
template::button('courseManageDuplicate' . $this->getUrl(2), [
|
||||
'href' => helper::baseUrl() . 'course/clone/' . $this->getUrl(2),
|
||||
'value' => 'Cloner',
|
||||
'ico' => 'clone'
|
||||
]); ?>
|
||||
</div>
|
||||
<div class="col2">
|
||||
<?php echo
|
||||
template::button('courseManageDownload' . $this->getUrl(2), [
|
||||
'href' => helper::baseUrl() . 'course/backup/' . $this->getUrl(2),
|
||||
'value' => 'Sauvegarder',
|
||||
'ico' => 'download-cloud'
|
||||
]); ?>
|
||||
</div>
|
||||
<div class="col2 ">
|
||||
<?php echo
|
||||
template::button('courseManageDelete' . $this->getUrl(2), [
|
||||
<div class="row textAlignCenter">
|
||||
<?php if ($this->getUser('permission', 'course', 'delete') === true): ?>
|
||||
<div class="col2 ">
|
||||
<?php echo template::button('courseManageDelete' . $this->getUrl(2), [
|
||||
'class' => 'courseDelete buttonRed',
|
||||
'href' => helper::baseUrl() . 'course/delete/' . $this->getUrl(2),
|
||||
'value' => 'Supprimer',
|
||||
'ico' => 'trash'
|
||||
]); ?>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col12">
|
||||
<div class="block">
|
||||
<h4>
|
||||
<?php echo helper::translate('Paramètres'); ?>
|
||||
</h4>
|
||||
<div class="row">
|
||||
<div class="col7">
|
||||
<?php echo template::text('courseManageShortTitle', [
|
||||
'label' => 'Titre',
|
||||
'value' => $this->getdata(['course', $this->getUrl(2), 'title']),
|
||||
'readonly' => true,
|
||||
]); ?>
|
||||
</div>
|
||||
<div class="col5">
|
||||
<?php echo template::select('courseManageAuthor', $module::$courseTeachers, [
|
||||
'label' => 'Auteur',
|
||||
'selected' => $this->getdata(['course', $this->getUrl(2), 'author']),
|
||||
'disabled' => true,
|
||||
]); ?>
|
||||
</div>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
<?php if ($this->getUser('permission', 'course', 'reset') === true): ?>
|
||||
<div class="col2 ">
|
||||
<?php echo template::button('courseManageReset' . $this->getUrl(2), [
|
||||
'class' => 'courseReset buttonRed',
|
||||
'href' => helper::baseUrl() . 'course/reset/' . $this->getUrl(2),
|
||||
'value' => 'Réinitaliser',
|
||||
'ico' => 'cancel'
|
||||
]); ?>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
<?php if ($this->getUser('permission', 'course', 'backup') === true): ?>
|
||||
<div class="col2">
|
||||
<?php echo template::button('courseManageDownload' . $this->getUrl(2), [
|
||||
'href' => helper::baseUrl() . 'course/backup/' . $this->getUrl(2),
|
||||
'value' => 'Sauvegarder',
|
||||
'ico' => 'download-cloud'
|
||||
]); ?>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
<?php if ($this->getUser('permission', 'course', 'clone') === true): ?>
|
||||
<div class="col2">
|
||||
<?php echo template::button('courseManageDuplicate' . $this->getUrl(2), [
|
||||
'href' => helper::baseUrl() . 'course/clone/' . $this->getUrl(2),
|
||||
'value' => 'Cloner',
|
||||
'ico' => 'clone'
|
||||
]); ?>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
<?php if ($this->getUser('permission', 'course', 'edit') === true): ?>
|
||||
<div class="col2">
|
||||
<?php echo template::button('courseManageEdit' . $this->getUrl(2), [
|
||||
'href' => helper::baseUrl() . 'course/edit/' . $this->getUrl(2),
|
||||
'value' => 'Éditer',
|
||||
'ico' => 'pencil'
|
||||
]); ?>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
<div class="col12">
|
||||
<div class="block">
|
||||
<h4>
|
||||
<?php echo helper::translate('Paramètres'); ?>
|
||||
</h4>
|
||||
<div class="row">
|
||||
<div class="col7">
|
||||
<?php echo template::text('courseManageShortTitle', [
|
||||
'label' => 'Titre',
|
||||
'value' => $this->getdata(['course', $this->getUrl(2), 'title']),
|
||||
'readonly' => true,
|
||||
]); ?>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col6">
|
||||
<?php echo template::select('courseManageHomePageId', helper::arrayColumn($module::$pagesList, 'title', 'SORT_ASC'), [
|
||||
'label' => 'Page d\'accueil',
|
||||
'selected' => $this->getdata(['course', $this->getUrl(2), 'homePageId']),
|
||||
'disabled' => true,
|
||||
]); ?>
|
||||
</div>
|
||||
<div class="col6">
|
||||
<?php echo template::select('courseManageCategorie', $module::$courseCategories, [
|
||||
'label' => 'Catégorie',
|
||||
'selected' => $this->getdata(['course', $this->getUrl(2), 'category']),
|
||||
'disabled' => true,
|
||||
]); ?>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col12">
|
||||
<?php echo template::textarea('courseManageDescription', [
|
||||
'label' => 'Description',
|
||||
'value' => $this->getdata(['course', $this->getUrl(2), 'description']),
|
||||
'readonly' => true,
|
||||
]); ?>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col4">
|
||||
<?php echo template::select('courseManageAccess', $module::$courseAccess, [
|
||||
'label' => 'Disponibilité',
|
||||
'selected' => $this->getdata(['course', $this->getUrl(2), 'access']),
|
||||
'disabled' => true,
|
||||
]); ?>
|
||||
</div>
|
||||
<div class="col4">
|
||||
<?php echo template::date('courseOpeningDate', [
|
||||
'type' => 'datetime-local',
|
||||
'label' => 'Ouverture',
|
||||
'value' => is_null($this->getdata(['course', $this->getUrl(2), 'openingDate'])) ? '' : floor($this->getdata(['course', $this->getUrl(2), 'openingDate']) / 60) * 60,
|
||||
'readonly' => true,
|
||||
]); ?>
|
||||
</div>
|
||||
<div class="col4">
|
||||
<?php echo template::date('courseClosingDate', [
|
||||
'type' => 'datetime-local',
|
||||
'label' => 'Fermeture',
|
||||
'value' => is_null($this->getdata(['course', $this->getUrl(2), 'closingDate'])) ? '' : floor($this->getdata(['course', $this->getUrl(2), 'closingDate']) / 60) * 60,
|
||||
]); ?>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col4">
|
||||
<?php echo template::select('courseManageEnrolment', $module::$courseEnrolment, [
|
||||
'label' => 'Participation',
|
||||
'selected' => $this->getdata(['course', $this->getUrl(2), 'enrolment']),
|
||||
'disabled' => true,
|
||||
]); ?>
|
||||
</div>
|
||||
<div class="col4">
|
||||
<?php echo template::text('courseManageEnrolmentKey', [
|
||||
'label' => 'Clé',
|
||||
'value' => $this->getdata(['course', $this->getUrl(2), 'enrolmentKey']),
|
||||
'readonly' => true,
|
||||
]); ?>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col4">
|
||||
<?php echo template::checkbox('courseManageEnrolmentLimit', true, 'Date de fin d\'inscription', [
|
||||
'checked' => $this->getdata(['course', $this->getUrl(2), 'limitEnrolment']),
|
||||
'help' => 'Ne s\'applique pas à l\'inscription anonyme',
|
||||
'disabled' => true,
|
||||
]); ?>
|
||||
</div>
|
||||
<div class="col4">
|
||||
<?php echo template::date('courseManageEnrolmentLimitDate', [
|
||||
'type' => 'datetime-local',
|
||||
'label' => 'Fermeture',
|
||||
'value' => is_null($this->getdata(['course', $this->getUrl(2), 'limitEnrolmentDate'])) ? '' : floor($this->getdata(['course', $this->getUrl(2), 'limitEnrolmentDate']) / 60) * 60,
|
||||
'readonly' => true,
|
||||
]); ?>
|
||||
</div>
|
||||
<div class="col5">
|
||||
<?php echo template::text('courseManageAuthor', [
|
||||
'label' => 'Auteur',
|
||||
'value' => $this->signature($this->getdata(['course', $this->getUrl(2), 'author'])),
|
||||
'readonly' => true,
|
||||
]); ?>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col6">
|
||||
<?php echo template::text('courseManageHomePageId', [
|
||||
'label' => 'Page d\'accueil',
|
||||
'value' => $module::$pagesList[$this->getdata(['course', $this->getUrl(2), 'homePageId'])]['shortTitle'],
|
||||
'readonly' => true,
|
||||
]); ?>
|
||||
</div>
|
||||
<div class="col6">
|
||||
<?php echo template::text('courseManageCategorie', [
|
||||
'label' => 'Catégorie',
|
||||
'value' => $module::$courseCategories[$this->getdata(['course', $this->getUrl(2), 'category'])],
|
||||
'readonly' => true,
|
||||
]); ?>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col12">
|
||||
<?php echo template::textarea('courseManageDescription', [
|
||||
'label' => 'Description',
|
||||
'value' => $this->getdata(['course', $this->getUrl(2), 'description']),
|
||||
'readonly' => true,
|
||||
]); ?>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col4">
|
||||
<?php echo template::text('courseManageAccess', [
|
||||
'label' => 'Disponibilité',
|
||||
'value' => $module::$courseAccess[$this->getdata(['course', $this->getUrl(2), 'access'])],
|
||||
'readonly' => true,
|
||||
]); ?>
|
||||
</div>
|
||||
<div class="col4">
|
||||
<?php echo template::date('courseOpeningDate', [
|
||||
'type' => 'datetime-local',
|
||||
'label' => 'Ouverture',
|
||||
'value' => is_null($this->getdata(['course', $this->getUrl(2), 'openingDate'])) ? '' : floor($this->getdata(['course', $this->getUrl(2), 'openingDate']) / 60) * 60,
|
||||
'readonly' => true,
|
||||
]); ?>
|
||||
</div>
|
||||
<div class="col4">
|
||||
<?php echo template::date('courseClosingDate', [
|
||||
'type' => 'datetime-local',
|
||||
'label' => 'Fermeture',
|
||||
'value' => is_null($this->getdata(['course', $this->getUrl(2), 'closingDate'])) ? '' : floor($this->getdata(['course', $this->getUrl(2), 'closingDate']) / 60) * 60,
|
||||
'readonly' => true,
|
||||
]); ?>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col4">
|
||||
<?php echo template::text('courseManageEnrolment', [
|
||||
'label' => 'Participation',
|
||||
'value' => $module::$courseEnrolment[$this->getdata(['course', $this->getUrl(2), 'enrolment'])],
|
||||
'readonly' => true,
|
||||
]); ?>
|
||||
</div>
|
||||
<div class="col4">
|
||||
<?php echo template::text('courseManageEnrolmentKey', [
|
||||
'label' => 'Clé',
|
||||
'value' => $this->getdata(['course', $this->getUrl(2), 'enrolmentKey']),
|
||||
'readonly' => true,
|
||||
]); ?>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col4">
|
||||
<?php echo template::checkbox('courseManageEnrolmentLimit', true, 'Date de fin d\'inscription', [
|
||||
'checked' => $this->getdata(['course', $this->getUrl(2), 'limitEnrolment']),
|
||||
'help' => 'Ne s\'applique pas à l\'inscription anonyme',
|
||||
'disabled' => true,
|
||||
]); ?>
|
||||
</div>
|
||||
<div class="col4">
|
||||
<?php echo template::date('courseManageEnrolmentLimitDate', [
|
||||
'type' => 'datetime-local',
|
||||
'label' => 'Fermeture',
|
||||
'value' => is_null($this->getdata(['course', $this->getUrl(2), 'limitEnrolmentDate'])) ? '' : floor($this->getdata(['course', $this->getUrl(2), 'limitEnrolmentDate']) / 60) * 60,
|
||||
'readonly' => true,
|
||||
]); ?>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
|
@ -1,5 +1,6 @@
|
|||
/**
|
||||
* This file is part of Zwii.
|
||||
*
|
||||
* For full copyright and license information, please see the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*
|
||||
|
@ -11,15 +12,11 @@
|
|||
* @link http://zwiicms.fr/
|
||||
*/
|
||||
|
||||
$(document).ready((function () {
|
||||
$('#dataTables').DataTable({
|
||||
language: {
|
||||
url: "core/vendor/datatables/french.json"
|
||||
},
|
||||
locale: 'fr',
|
||||
searching: false,
|
||||
pageLength: 100,
|
||||
lengthChange: false,
|
||||
paging: false
|
||||
});
|
||||
}));
|
||||
|
||||
/** NE PAS EFFACER
|
||||
* admin.css
|
||||
*/
|
||||
|
||||
table td {
|
||||
text-align: left;
|
||||
}
|
|
@ -0,0 +1,44 @@
|
|||
/**
|
||||
* This file is part of Zwii.
|
||||
* For full copyright and license information, please see the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*
|
||||
* @author Rémi Jean <remi.jean@outlook.com>
|
||||
* @copyright Copyright (C) 2008-2018, Rémi Jean
|
||||
* @author Frédéric Tempez <frederic.tempez@outlook.com>
|
||||
* @copyright Copyright (C) 2018-2024, Frédéric Tempez
|
||||
* @license CC Attribution-NonCommercial-NoDerivatives 4.0 International
|
||||
* @link http://zwiicms.fr/
|
||||
*/
|
||||
|
||||
$(document).ready((function () {
|
||||
|
||||
var dataX = <?php echo json_encode(array_map(function ($item) { return $item[0]; }, $module::$userGraph)); ?>;
|
||||
var dataY = <?php echo json_encode(array_map(function ($item) { return $item[1];}, $module::$userGraph)); ?>;
|
||||
var dataText = <?php echo json_encode(array_map(function ($item) { return $item[2];}, $module::$userGraph)); ?>;
|
||||
|
||||
var data = [{
|
||||
x: dataX,
|
||||
y: dataY,
|
||||
text: dataText,
|
||||
mode: 'markers', // Mode de tracé des points
|
||||
type: 'scatter' // Type de graphe
|
||||
}];
|
||||
|
||||
// Créer un objet layout et définir les propriétés du titre, des axes, etc.
|
||||
var layout = {
|
||||
title: 'Consultations par jour', // Titre du graphe
|
||||
xaxis: {
|
||||
title: 'Jours', // Titre de l'axe des abscisses
|
||||
type: 'date' // Type de l'axe des abscisses
|
||||
},
|
||||
yaxis: {
|
||||
title: 'Temps (en secondes)', // Titre de l'axe des ordonnées
|
||||
type: 'linear' // Type de l'axe des ordonnées
|
||||
}
|
||||
};
|
||||
|
||||
// Créer et afficher le graphe dans l'élément <div>
|
||||
Plotly.newPlot('graph', data, layout, {locale: 'fr-CH'});
|
||||
|
||||
}));
|
|
@ -14,25 +14,39 @@
|
|||
]) ?>
|
||||
</div>
|
||||
</div>
|
||||
<?php if ($module::$userHistory): ?>
|
||||
<div class="row">
|
||||
<div class="col10 offset1">
|
||||
<div id="graph">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<?php if ($module::$userReport): ?>
|
||||
<div class="row">
|
||||
<div class="col4 offset2">
|
||||
<?php if ($this->getData(['course', $this->getUrl(2), 'access']) === self::COURSE_ACCESS_DATE): ?>
|
||||
<p>Espace ouvert le :
|
||||
<?php echo helper::dateUTF8('%d %B %Y %H:%M', $this->getData(['course', $this->getUrl(2), 'openingDate'])); ?></p
|
||||
<?php echo helper::dateUTF8('%d %B %Y %H:%M', $this->getData(['course', $this->getUrl(2), 'openingDate'])); ?>
|
||||
</p>
|
||||
<p>Espace fermé le :
|
||||
<?php echo helper::dateUTF8('%d %B %Y %H:%M', $this->getData(['course', $this->getUrl(2), 'closingDate'])); ?></p>
|
||||
<?php endif;?>
|
||||
<?php echo helper::dateUTF8('%d %B %Y %H:%M', $this->getData(['course', $this->getUrl(2), 'closingDate'])); ?>
|
||||
</p>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
<div class="col4">
|
||||
<p>Commencé le : <?php echo $module::$userStat['floor'];?></p>
|
||||
<p>Terminé le : <?php echo $module::$userStat['top'];?></p>
|
||||
<p>Temps passé : <?php echo $module::$userStat['time'];?></p>
|
||||
<p>Commencé le :
|
||||
<?php echo $module::$userStat['floor']; ?>
|
||||
</p>
|
||||
<p>Terminé le :
|
||||
<?php echo $module::$userStat['top']; ?>
|
||||
</p>
|
||||
<p>Temps passé :
|
||||
<?php echo $module::$userStat['time']; ?>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row textAlignCenter">
|
||||
<div class="col8">
|
||||
<?php echo template::table([1, 6, 5], $module::$userHistory, ['Ordre', 'Page', 'Consultation'], ['id' => 'dataTables']);?>
|
||||
<?php echo template::table([6, 3, 3], $module::$userReport, ['Page', 'Début de Consultation', 'Temps consultation']); ?>
|
||||
</div>
|
||||
</div>
|
||||
<?php else: ?>
|
|
@ -21,12 +21,14 @@ $(document).ready((function () {
|
|||
$(location).attr("href", _this.attr("href"))
|
||||
}))
|
||||
}));
|
||||
|
||||
$.fn.dataTable.moment( 'DD/MM/YYYY' );
|
||||
$('#dataTables').DataTable({
|
||||
language: {
|
||||
url: "core/vendor/datatables/french.json"
|
||||
},
|
||||
order: [[3, 'desc']],
|
||||
locale: 'fr',
|
||||
stateSave: true,
|
||||
"columnDefs": [
|
||||
{
|
||||
target: 6,
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
<div class="col1">
|
||||
<?php echo template::button('courseUserBack', [
|
||||
'class' => 'buttonGrey',
|
||||
'href' => helper::baseUrl() . 'course/manage/' . $this->getUrl(2),
|
||||
'href' => helper::baseUrl() . 'course/' . $this->getUrl(2),
|
||||
'value' => template::ico('left')
|
||||
]); ?>
|
||||
</div>
|
||||
|
@ -53,7 +53,7 @@
|
|||
</div>
|
||||
<?php echo template::formClose(); ?>
|
||||
<?php if ($module::$courseUsers): ?>
|
||||
<?php echo template::table([2, 2, 2, 2, 2, 1, 1], $module::$courseUsers, ['Id', 'Nom Prénom', 'Dernière page vue', 'Date - Heure', 'Étiquettes', 'Progression', ''], ['id' => 'dataTables']); ?>
|
||||
<?php echo template::table([3, 4, 1, 1, 1, 1, 1], $module::$courseUsers, ['Nom Prénom', 'Dernière page vue', 'Date' , 'Heure', 'Étiquettes', 'Progression', ''], ['id' => 'dataTables']); ?>
|
||||
<?php else: ?>
|
||||
<?php echo template::speech('Aucun participant'); ?>
|
||||
<?php endif; ?>
|
|
@ -15,4 +15,8 @@
|
|||
|
||||
/** NE PAS EFFACER
|
||||
* admin.css
|
||||
*/
|
||||
*/
|
||||
|
||||
tr {
|
||||
cursor: pointer;
|
||||
}
|
|
@ -13,6 +13,13 @@
|
|||
|
||||
$(document).ready((function () {
|
||||
|
||||
$('tr').click(function(){
|
||||
// Cochez ou décochez la case à cocher dans cette ligne
|
||||
$(this).find('input[type="checkbox"]').prop('checked', function(i, val){
|
||||
return !val; // Inverse l'état actuel de la case à cocher
|
||||
});
|
||||
});
|
||||
|
||||
$('#courseUserAddSelectAll').on('click', function() {
|
||||
$('.checkboxSelect').prop('checked', true);
|
||||
saveCheckboxState();
|
||||
|
@ -32,6 +39,7 @@ $(document).ready((function () {
|
|||
url: "core/vendor/datatables/french.json"
|
||||
},
|
||||
locale: 'fr',
|
||||
stateSave: true,
|
||||
"columnDefs": [
|
||||
{
|
||||
target: 0,
|
||||
|
|
|
@ -7,19 +7,22 @@
|
|||
'value' => template::ico('left')
|
||||
]); ?>
|
||||
</div>
|
||||
<div class="col1 offset7">
|
||||
<div class="col1 offset8">
|
||||
<?php echo template::button('courseUserAddSelectAll', [
|
||||
'value' => 'Tout'
|
||||
'value' => template::ico('square-check'),
|
||||
'help' => 'Tout sélectionner'
|
||||
]); ?>
|
||||
</div>
|
||||
<div class="col1">
|
||||
<?php echo template::button('courseUserAddSelectNone', [
|
||||
'value' => 'Aucun'
|
||||
'value' => template::ico('square-check-empty'),
|
||||
'help' => 'Tout désélectionner'
|
||||
]); ?>
|
||||
</div>
|
||||
<div class="col2">
|
||||
<div class="col1">
|
||||
<?php echo template::submit('courseUsersAddSubmit', [
|
||||
'value' => 'Inscrire'
|
||||
'value' => '',
|
||||
'ico' => 'plus',
|
||||
]); ?>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
@ -15,4 +15,12 @@
|
|||
|
||||
/** NE PAS EFFACER
|
||||
* admin.css
|
||||
*/
|
||||
*/
|
||||
|
||||
#courseUsersDeleteSubmit {
|
||||
background-color: rgba(217, 95, 78, 1);
|
||||
}
|
||||
|
||||
tr {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
|
|
@ -13,11 +13,18 @@
|
|||
|
||||
$(document).ready((function () {
|
||||
|
||||
$('#courseUserDeleteSelectAll').on('click', function() {
|
||||
$('tr').click(function () {
|
||||
// Cochez ou décochez la case à cocher dans cette ligne
|
||||
$(this).find('input[type="checkbox"]').prop('checked', function (i, val) {
|
||||
return !val; // Inverse l'état actuel de la case à cocher
|
||||
});
|
||||
});
|
||||
|
||||
$('#courseUserDeleteSelectAll').on('click', function () {
|
||||
$('.checkboxSelect').prop('checked', true);
|
||||
saveCheckboxState();
|
||||
});
|
||||
$('#courseUserDeleteSelectNone').on('click', function() {
|
||||
$('#courseUserDeleteSelectNone').on('click', function () {
|
||||
$('.checkboxSelect').prop('checked', false);
|
||||
saveCheckboxState();
|
||||
});
|
||||
|
@ -80,7 +87,7 @@ $(document).ready((function () {
|
|||
// Function to restore checkbox state
|
||||
function restoreCheckboxState() {
|
||||
var checkboxState = JSON.parse(localStorage.getItem('checkboxState')) || {};
|
||||
// console.log(checkboxState);
|
||||
// console.log(checkboxState);
|
||||
for (var checkboxId in checkboxState) {
|
||||
if (checkboxState.hasOwnProperty(checkboxId)) {
|
||||
var checked = checkboxState[checkboxId];
|
||||
|
|
|
@ -7,20 +7,23 @@
|
|||
'value' => template::ico('left')
|
||||
]); ?>
|
||||
</div>
|
||||
<div class="col1 offset7">
|
||||
<div class="col1 offset8">
|
||||
<?php echo template::button('courseUserDeleteSelectAll', [
|
||||
'value' => 'Tout'
|
||||
'value' => template::ico('square-check'),
|
||||
'help' => 'Tout sélectionner'
|
||||
]); ?>
|
||||
</div>
|
||||
<div class="col1">
|
||||
<?php echo template::button('courseUserDeleteSelectNone', [
|
||||
'value' => 'Aucun'
|
||||
'value' => template::ico('square-check-empty'),
|
||||
'help' => 'Tout désélectionner'
|
||||
]); ?>
|
||||
</div>
|
||||
<div class="col2">
|
||||
<div class="col1">
|
||||
<?php echo template::submit('courseUsersDeleteSubmit', [
|
||||
'class' => 'buttonRed',
|
||||
'value' => 'Désinscrire'
|
||||
'ico' => '',
|
||||
'value' => template::ico('minus'),
|
||||
]); ?>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
@ -194,6 +194,11 @@ class install extends common
|
|||
mkdir(self::I18N_DIR);
|
||||
}
|
||||
|
||||
// Créer le dossier de l'accueil dans les fichiers
|
||||
if (is_dir(self::FILE_DIR . 'source/home') === false) {
|
||||
mkdir(self::FILE_DIR . 'source/home');
|
||||
}
|
||||
|
||||
// Créer la base de données des langues
|
||||
$this->copyDir('core/module/install/ressource/i18n', self::I18N_DIR);
|
||||
|
||||
|
@ -248,14 +253,18 @@ class install extends common
|
|||
$message = $success ? '' : 'Erreur de copie du fichier htaccess';
|
||||
}
|
||||
// Nettoyage des fichiers d'installation précédents
|
||||
if (file_exists(self::TEMP_DIR . 'update.tar.gz') && $success) {
|
||||
if ($success && file_exists(self::TEMP_DIR . 'update.tar.gz')) {
|
||||
$success = unlink(self::TEMP_DIR . 'update.tar.gz');
|
||||
$message = $success ? '' : 'Impossible d\'effacer la mise à jour précédente';
|
||||
}
|
||||
if (file_exists(self::TEMP_DIR . 'update.tar') && $success) {
|
||||
if ($success && file_exists(self::TEMP_DIR . 'update.tar')) {
|
||||
$success = unlink(self::TEMP_DIR . 'update.tar');
|
||||
$message = $success ? '' : 'Impossible d\'effacer la mise à jour précédente';
|
||||
}
|
||||
// Sauvegarde le message dans le journal
|
||||
if (!empty($message)) {
|
||||
$this->saveLog($message);
|
||||
}
|
||||
// Valeurs en sortie
|
||||
$this->addOutput([
|
||||
'display' => self::DISPLAY_JSON,
|
||||
|
@ -267,6 +276,8 @@ class install extends common
|
|||
break;
|
||||
// Téléchargement
|
||||
case 2:
|
||||
$success = true;
|
||||
$message = '';
|
||||
file_put_contents(self::TEMP_DIR . 'update.tar.gz', helper::getUrlContents(common::ZWII_UPDATE_URL . common::ZWII_UPDATE_CHANNEL . '/update.tar.gz'));
|
||||
$md5origin = helper::getUrlContents(common::ZWII_UPDATE_URL . common::ZWII_UPDATE_CHANNEL . '/update.md5');
|
||||
$md5origin = explode(' ', $md5origin);
|
||||
|
@ -277,27 +288,35 @@ class install extends common
|
|||
$message = "";
|
||||
} else {
|
||||
$success = false;
|
||||
$message = json_encode('Erreur de téléchargement ou de somme de contrôle', JSON_UNESCAPED_UNICODE);
|
||||
$message = 'Erreur de téléchargement ou de somme de contrôle';
|
||||
if (file_exists(self::TEMP_DIR . 'update.tar.gz')) {
|
||||
unlink(self::TEMP_DIR . 'update.tar.gz');
|
||||
http_response_code(500);
|
||||
}
|
||||
}
|
||||
|
||||
// Sauvegarde le message dans le journal
|
||||
if (!empty($message)) {
|
||||
$this->saveLog($message);
|
||||
}
|
||||
// Valeurs en sortie
|
||||
$this->addOutput([
|
||||
'display' => self::DISPLAY_JSON,
|
||||
'content' => [
|
||||
'success' => $success,
|
||||
'data' => $message
|
||||
'data' => json_encode($message, JSON_UNESCAPED_UNICODE)
|
||||
]
|
||||
]);
|
||||
break;
|
||||
// Installation
|
||||
case 3:
|
||||
$success = true;
|
||||
$message = '';
|
||||
|
||||
// Check la réécriture d'URL avant d'écraser les fichiers
|
||||
$rewrite = helper::checkRewrite();
|
||||
if (helper::checkRewrite()) {
|
||||
touch(self::DATA_DIR . '.rewrite');
|
||||
}
|
||||
|
||||
// Décompression et installation
|
||||
try {
|
||||
// Décompression dans le dossier de fichier temporaires
|
||||
|
@ -306,9 +325,11 @@ class install extends common
|
|||
// Installation
|
||||
$pharData->extractTo(__DIR__ . '/../../../', null, true);
|
||||
} catch (Exception $e) {
|
||||
$message = $e->getMessage();
|
||||
$success = false;
|
||||
http_response_code(500);
|
||||
}
|
||||
|
||||
// Nettoyage du dossier
|
||||
if (file_exists(self::TEMP_DIR . 'update.tar.gz')) {
|
||||
unlink(self::TEMP_DIR . 'update.tar.gz');
|
||||
|
@ -316,12 +337,16 @@ class install extends common
|
|||
if (file_exists(self::TEMP_DIR . 'update.tar')) {
|
||||
unlink(self::TEMP_DIR . 'update.tar');
|
||||
}
|
||||
// Sauvegarde le message dans le journal
|
||||
if (!empty($message)) {
|
||||
$this->saveLog($message);
|
||||
}
|
||||
// Valeurs en sortie
|
||||
$this->addOutput([
|
||||
'display' => self::DISPLAY_JSON,
|
||||
'content' => [
|
||||
'success' => $success,
|
||||
'data' => $rewrite
|
||||
'data' => json_encode($message, JSON_UNESCAPED_UNICODE)
|
||||
]
|
||||
]);
|
||||
break;
|
||||
|
@ -329,7 +354,6 @@ class install extends common
|
|||
case 4:
|
||||
$success = true;
|
||||
$message = '';
|
||||
$rewrite = $this->getInput('data');
|
||||
|
||||
/**
|
||||
* Restaure le fichier htaccess
|
||||
|
@ -350,7 +374,7 @@ class install extends common
|
|||
/**
|
||||
* Restaure la réécriture d'URL
|
||||
*/
|
||||
if ($rewrite === 'true') { // Ajout des lignes dans le .htaccess
|
||||
if (file_exists(self::DATA_DIR . '.rewrite')) { // Ajout des lignes dans le .htaccess
|
||||
$fileContent = file_get_contents('.htaccess');
|
||||
$rewriteData = PHP_EOL .
|
||||
'# URL rewriting' . PHP_EOL .
|
||||
|
@ -363,10 +387,11 @@ class install extends common
|
|||
'</IfModule>' . PHP_EOL .
|
||||
'# URL rewriting' . PHP_EOL;
|
||||
$fileContent = str_replace('# URL rewriting', $rewriteData, $fileContent);
|
||||
$success = file_put_contents(
|
||||
$success = $this->secure_file_put_contents(
|
||||
'.htaccess',
|
||||
$fileContent
|
||||
);
|
||||
unlink(self::DATA_DIR . '.rewrite');
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -378,7 +403,6 @@ class install extends common
|
|||
$defaultLanguages = init::$defaultData['language'];
|
||||
foreach ($installedLanguages as $key => $value) {
|
||||
|
||||
//var_dump( $defaultLanguages[$key]['date'] > $value['date'] );
|
||||
if (
|
||||
isset($defaultLanguages[$key]['date']) &&
|
||||
$defaultLanguages[$key]['date'] > $value['date'] &&
|
||||
|
@ -390,7 +414,10 @@ class install extends common
|
|||
$this->setData(['language', $key, $defaultLanguages[$key]]);
|
||||
}
|
||||
}
|
||||
|
||||
// Sauvegarde le message dans le journal
|
||||
if (!empty($message)) {
|
||||
$this->saveLog($message);
|
||||
}
|
||||
// Valeurs en sortie
|
||||
$this->addOutput([
|
||||
'display' => self::DISPLAY_JSON,
|
||||
|
@ -419,10 +446,13 @@ class install extends common
|
|||
} else {
|
||||
// Nouvelle version
|
||||
self::$newVersion = helper::getUrlContents(common::ZWII_UPDATE_URL . common::ZWII_UPDATE_CHANNEL . '/version');
|
||||
|
||||
// Variable de version
|
||||
if (helper::checkNewVersion(common::ZWII_UPDATE_CHANNEL)) {
|
||||
self::$updateButtonText = helper::translate('Mettre à jour');
|
||||
self::$updateButtonText = helper::translate('Mise à jour');
|
||||
}
|
||||
|
||||
|
||||
// Valeurs en sortie
|
||||
$this->addOutput([
|
||||
'display' => self::DISPLAY_LAYOUT_LIGHT,
|
||||
|
|
|
@ -64,7 +64,7 @@ class init extends common
|
|||
]
|
||||
],
|
||||
'core' => [
|
||||
'dataVersion' => 1000,
|
||||
'dataVersion' => 1700,
|
||||
'lastBackup' => 0,
|
||||
'lastClearTmp' => 0,
|
||||
'lastAutoUpdate' => 0,
|
||||
|
@ -240,6 +240,21 @@ class init extends common
|
|||
'copycut' => false,
|
||||
'chmod' => false
|
||||
],
|
||||
'course' => [
|
||||
'tutor' => false,
|
||||
'index' => false,
|
||||
'manage' => false,
|
||||
'users' => false,
|
||||
'userHistory' => false,
|
||||
'userHistoryExport' => false,
|
||||
'usersAdd' => false,
|
||||
'userDelete' => false,
|
||||
'usersDelete' => false,
|
||||
'edit' => false,
|
||||
'backup' => false,
|
||||
'restore' => false,
|
||||
'reset' => false,
|
||||
],
|
||||
'folder' => [
|
||||
'create' => false,
|
||||
'delete' => false,
|
||||
|
@ -247,7 +262,8 @@ class init extends common
|
|||
'copycut' => false,
|
||||
'chmod' => false,
|
||||
'share' => false,
|
||||
'path' => null,
|
||||
'coursePath' => 'none',
|
||||
'homePath' => 'none'
|
||||
],
|
||||
'page' => [
|
||||
'add' => false,
|
||||
|
@ -321,6 +337,21 @@ class init extends common
|
|||
'copycut' => false,
|
||||
'chmod' => false
|
||||
],
|
||||
'course' => [
|
||||
'tutor' => false,
|
||||
'index' => false,
|
||||
'manage' => false,
|
||||
'users' => false,
|
||||
'userHistory' => false,
|
||||
'userHistoryExport' => false,
|
||||
'usersAdd' => false,
|
||||
'userDelete' => false,
|
||||
'usersDelete' => false,
|
||||
'edit' => false,
|
||||
'backup' => false,
|
||||
'restore' => false,
|
||||
'reset' => false,
|
||||
],
|
||||
'folder' => [
|
||||
'create' => false,
|
||||
'delete' => false,
|
||||
|
@ -328,7 +359,8 @@ class init extends common
|
|||
'copycut' => false,
|
||||
'chmod' => false,
|
||||
'share' => true,
|
||||
'path' => '/site/file/source/partage/',
|
||||
'coursePath' => 'none',
|
||||
'homePath' => '/site/file/source/partage/'
|
||||
],
|
||||
'page' => [
|
||||
'add' => false,
|
||||
|
@ -407,6 +439,21 @@ class init extends common
|
|||
'copycut' => false,
|
||||
'chmod' => false
|
||||
],
|
||||
'course' => [
|
||||
'tutor' => true,
|
||||
'index' => true,
|
||||
'manage' => true,
|
||||
'users' => true,
|
||||
'userHistory' => true,
|
||||
'userHistoryExport' => true,
|
||||
'usersAdd' => true,
|
||||
'userDelete' => false,
|
||||
'usersDelete' => false,
|
||||
'edit' => false,
|
||||
'backup' => false,
|
||||
'restore' => false,
|
||||
'reset' => false,
|
||||
],
|
||||
'folder' => [
|
||||
'create' => false,
|
||||
'delete' => false,
|
||||
|
@ -414,7 +461,8 @@ class init extends common
|
|||
'copycut' => false,
|
||||
'chmod' => false,
|
||||
'share' => true,
|
||||
'path' => '',
|
||||
'coursePath' => '',
|
||||
'homePath' => '/site/file/source/partage/'
|
||||
],
|
||||
'page' => [
|
||||
'add' => false,
|
||||
|
@ -489,6 +537,21 @@ class init extends common
|
|||
'copycut' => true,
|
||||
'chmod' => true
|
||||
],
|
||||
'course' => [
|
||||
'tutor' => false,
|
||||
'index' => true,
|
||||
'manage' => true,
|
||||
'users' => true,
|
||||
'userHistory' => true,
|
||||
'userHistoryExport' => true,
|
||||
'usersAdd' => true,
|
||||
'userDelete' => true,
|
||||
'usersDelete' => true,
|
||||
'edit' => true,
|
||||
'backup' => true,
|
||||
'restore' => true,
|
||||
'reset' => true,
|
||||
],
|
||||
'folder' => [
|
||||
'create' => true,
|
||||
'delete' => true,
|
||||
|
@ -496,7 +559,8 @@ class init extends common
|
|||
'copycut' => true,
|
||||
'chmod' => true,
|
||||
'share' => true,
|
||||
'path' => '',
|
||||
'coursePath' => '',
|
||||
'homePath' => '/site/file/source/partage/'
|
||||
],
|
||||
'page' => [
|
||||
'add' => true,
|
||||
|
|
Binary file not shown.
|
@ -1,7 +1,7 @@
|
|||
function step(i, data) {
|
||||
var errors = ["<?php echo helper::translate('Préparation de la mise à jour'); ?>", "<?php echo helper::translate('Téléchargement et validation de l\'archive'); ?>", "<?php echo helper::translate('Installation'); ?>", "<?php echo helper::translate('Configuration'); ?>"];
|
||||
$(".installUpdateProgressText").hide(), $(".installUpdateProgressText[data-id=" + i + "]").show();
|
||||
|
||||
|
||||
$("body").css("cursor", "wait");
|
||||
|
||||
$.ajax({
|
||||
|
@ -12,11 +12,6 @@ function step(i, data) {
|
|||
data: data
|
||||
},
|
||||
success: function (result) {
|
||||
// if (result.success != "1") { // Vérification de la propriété "success"
|
||||
// Appel de la fonction de gestion d'erreur
|
||||
// showError(i, result, errors);
|
||||
// return;
|
||||
//}
|
||||
setTimeout((function () {
|
||||
if (4 === i) {
|
||||
$("#installUpdateSuccess").show();
|
||||
|
@ -60,10 +55,13 @@ function showError(step, message, errors) {
|
|||
const jsonData = JSON.parse(jsonString);
|
||||
|
||||
// Afficher les résultats
|
||||
$("#installUpdateErrorMessage").html("<strong>Détails de l'erreur :</strong><br> " +
|
||||
jsonData.data.replace(/^"(.*)"$/, '$1') +
|
||||
"<br>" +
|
||||
warningMessage.replace(/<[^p].*?>/g, ""));
|
||||
if (jsonData) {
|
||||
$("#installUpdateErrorMessage").html("<strong>Détails de l'erreur :</strong><br> " +
|
||||
jsonData.data.replace(/^"(.*)"$/, '$1') +
|
||||
"<br>" +
|
||||
warningMessage.replace(/<[^p].*?>/g, ""));
|
||||
}
|
||||
|
||||
} else {
|
||||
// Vous pouvez également faire quelque chose d'autre ici, par exemple, afficher un message à l'utilisateur, etc.
|
||||
$("#installUpdateErrorMessage").html(message);
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
<?php echo self::ZWII_VERSION; ?>
|
||||
<?php echo helper::translate('vers'); ?>
|
||||
|
||||
<?php echo $module::$newVersion; ?>.
|
||||
<?php echo $module::$newVersion; ?>
|
||||
</strong></p>
|
||||
<p>
|
||||
<?php echo helper::translate('Afin d\'assurer le bon fonctionnement de Zwii, veuillez ne pas fermer cette page avant la fin de l\'opération.'); ?>
|
||||
|
|
|
@ -99,7 +99,7 @@ class language extends common
|
|||
is_array($descripteur['language'][$lang])
|
||||
) {
|
||||
if ($this->setData(['language', $lang, $descripteur['language'][$lang]])) {
|
||||
$success = file_put_contents(self::I18N_DIR . $lang . '.json', json_encode($languageData, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES | JSON_PRETTY_PRINT));
|
||||
$success = $this->secure_file_put_contents(self::I18N_DIR . $lang . '.json', json_encode($languageData, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES | JSON_PRETTY_PRINT));
|
||||
$success = is_int($success) ? true : false;
|
||||
}
|
||||
}
|
||||
|
@ -271,7 +271,7 @@ class language extends common
|
|||
'class' => isset($storeUI[$file]['version']) && version_compare($installedUI[$file]['version'], $storeUI[$file]['version']) < 0 ? 'buttonGreen' : '',
|
||||
'href' => helper::baseUrl() . $this->getUrl(0) . '/update/' . $file,
|
||||
'value' => template::ico('update'),
|
||||
'help' => 'Mettre à jour',
|
||||
'help' => 'Mise à jour',
|
||||
]),
|
||||
template::button('translateContentLanguageUIDelete' . $file, [
|
||||
'class' => 'translateDelete buttonRed' . (in_array($file, $usersUI) ? ' disabled' : ''),
|
||||
|
|
|
@ -68,10 +68,10 @@ class page extends common
|
|||
public static $userProfils = [];
|
||||
|
||||
public static $navIconTemplate = [
|
||||
'dir' => 'Petit triangle',
|
||||
'open' => 'Grand triangle',
|
||||
'big' => 'Flèche',
|
||||
];
|
||||
'dir' => 'Petit triangle',
|
||||
'open' => 'Grand triangle',
|
||||
'big' => 'Flèche',
|
||||
];
|
||||
|
||||
public static $navIconPosition = [
|
||||
'none' => 'Masqué',
|
||||
|
@ -85,12 +85,23 @@ class page extends common
|
|||
*/
|
||||
public function duplicate()
|
||||
{
|
||||
// La session ne correspond pas au site ouvert dans cet onglet
|
||||
if (
|
||||
// Contrôle la présence de l'id d'espace uniquement si l'id est fourni afin de ne pas bloquer les modules non mis à jour
|
||||
$this->getUrl(3) && $this->getUrl(3) != self::$siteContent
|
||||
) {
|
||||
$_SESSION['ZWII_SITE_CONTENT'] = $this->getUrl(3);
|
||||
header('Refresh:0; url=' . helper::baseUrl() . $this->getUrl());
|
||||
exit();
|
||||
}
|
||||
|
||||
// Adresse sans le token
|
||||
$page = $this->getUrl(2);
|
||||
|
||||
// La page n'existe pas
|
||||
if (
|
||||
$this->getUser('permission', __CLASS__, __FUNCTION__) !== true ||
|
||||
$this->getData(['page', $page]) === null
|
||||
$this->getUser('permission', __CLASS__, __FUNCTION__) !== true
|
||||
|| $this->getData(['page', $page]) === null
|
||||
) {
|
||||
// Valeurs en sortie
|
||||
$this->addOutput([
|
||||
|
@ -118,7 +129,7 @@ class page extends common
|
|||
|
||||
// Valeurs en sortie
|
||||
$this->addOutput([
|
||||
'redirect' => helper::baseUrl() . 'page/edit/' . $pageId,
|
||||
'redirect' => helper::baseUrl() . 'page/edit/' . $pageId . '/' . self::$siteContent,
|
||||
'notification' => $notification,
|
||||
'state' => true
|
||||
]);
|
||||
|
@ -131,7 +142,19 @@ class page extends common
|
|||
*/
|
||||
public function add()
|
||||
{
|
||||
if ($this->getUser('permission', __CLASS__, __FUNCTION__) !== true) {
|
||||
// La session ne correspond pas au site ouvert dans cet onglet
|
||||
if (
|
||||
// Contrôle la présence de l'id d'espace uniquement si l'id est fourni afin de ne pas bloquer les modules non mis à jour
|
||||
$this->getUrl(3) && $this->getUrl(3) != self::$siteContent
|
||||
) {
|
||||
$_SESSION['ZWII_SITE_CONTENT'] = $this->getUrl(3);
|
||||
header('Refresh:0; url=' . helper::baseUrl() . $this->getUrl());
|
||||
exit();
|
||||
}
|
||||
|
||||
if (
|
||||
$this->getUser('permission', __CLASS__, __FUNCTION__) !== true
|
||||
) {
|
||||
// Valeurs en sortie
|
||||
$this->addOutput([
|
||||
'access' => false
|
||||
|
@ -198,12 +221,24 @@ class page extends common
|
|||
*/
|
||||
public function delete()
|
||||
{
|
||||
|
||||
// La session ne correspond pas au site ouvert dans cet onglet
|
||||
if (
|
||||
// Contrôle la présence de l'id d'espace uniquement si l'id est fourni afin de ne pas bloquer les modules non mis à jour
|
||||
$this->getUrl(3) && $this->getUrl(3) != self::$siteContent
|
||||
) {
|
||||
$_SESSION['ZWII_SITE_CONTENT'] = $this->getUrl(3);
|
||||
header('Refresh:0; url=' . helper::baseUrl() . $this->getUrl());
|
||||
exit();
|
||||
}
|
||||
|
||||
// $url prend l'adresse sans le token
|
||||
$page = $this->getUrl(2);
|
||||
|
||||
// La page n'existe pas
|
||||
if (
|
||||
$this->getUser('permission', __CLASS__, __FUNCTION__) !== true ||
|
||||
$this->getData(['page', $page]) === null
|
||||
$this->getUser('permission', __CLASS__, __FUNCTION__) !== true
|
||||
|| $this->getData(['page', $page]) === null
|
||||
) {
|
||||
// Valeurs en sortie
|
||||
$this->addOutput([
|
||||
|
@ -214,8 +249,10 @@ class page extends common
|
|||
elseif ($page === $this->homePageId()) {
|
||||
// Valeurs en sortie
|
||||
$this->addOutput([
|
||||
'redirect' => helper::baseUrl() . 'config',
|
||||
'notification' => helper::translate('Suppression interdite, page active dans la configuration de la langue du site')
|
||||
'redirect' => helper::baseUrl() . $this->homePageId(),
|
||||
'notification' => self::$siteContent === 'home'
|
||||
? helper::translate('Suppression interdite, cette page est définie comme page d\'accueil du site')
|
||||
: helper::translate('Suppression interdite, cette page est définie comme page d\'accueil d\'un espace')
|
||||
]);
|
||||
}
|
||||
// Impossible de supprimer la page affectée
|
||||
|
@ -223,7 +260,7 @@ class page extends common
|
|||
// Valeurs en sortie
|
||||
$this->addOutput([
|
||||
'redirect' => helper::baseUrl() . 'config',
|
||||
'notification' => helper::translate('Suppression interdite, page active dans la configuration de la langue du site')
|
||||
'notification' => helper::translate('Suppression interdite, page active dans la configuration du site')
|
||||
]);
|
||||
}
|
||||
// Impossible de supprimer la page affectée
|
||||
|
@ -231,7 +268,7 @@ class page extends common
|
|||
// Valeurs en sortie
|
||||
$this->addOutput([
|
||||
'redirect' => helper::baseUrl() . 'config',
|
||||
'notification' => helper::translate('Suppression interdite, page active dans la configuration de la langue du site')
|
||||
'notification' => helper::translate('Suppression interdite, page active dans la configuration du site')
|
||||
]);
|
||||
}
|
||||
// Impossible de supprimer la page affectée
|
||||
|
@ -239,7 +276,7 @@ class page extends common
|
|||
// Valeurs en sortie
|
||||
$this->addOutput([
|
||||
'redirect' => helper::baseUrl() . 'config',
|
||||
'notification' => helper::translate('Suppression interdite, page active dans la configuration de la langue du site')
|
||||
'notification' => helper::translate('Suppression interdite, page active dans la configuration du site')
|
||||
]);
|
||||
}
|
||||
// Impossible de supprimer la page affectée
|
||||
|
@ -247,7 +284,7 @@ class page extends common
|
|||
// Valeurs en sortie
|
||||
$this->addOutput([
|
||||
'redirect' => helper::baseUrl() . 'config',
|
||||
'notification' => helper::translate('Suppression interdite, page active dans la configuration de la langue du site')
|
||||
'notification' => helper::translate('Suppression interdite, page active dans la configuration du site')
|
||||
]);
|
||||
}
|
||||
// Impossible de supprimer la page affectée
|
||||
|
@ -255,14 +292,14 @@ class page extends common
|
|||
// Valeurs en sortie
|
||||
$this->addOutput([
|
||||
'redirect' => helper::baseUrl() . 'config',
|
||||
'notification' => helper::translate('Suppression interdite, page active dans la configuration de la langue du site')
|
||||
'notification' => helper::translate('Suppression interdite, page active dans la configuration du site')
|
||||
]);
|
||||
}
|
||||
// Impossible de supprimer une page contenant des enfants
|
||||
elseif ($this->getHierarchy($page, null)) {
|
||||
// Valeurs en sortie
|
||||
$this->addOutput([
|
||||
'redirect' => helper::baseUrl() . 'page/edit/' . $page,
|
||||
'redirect' => helper::baseUrl() . 'page/edit/' . $page . '/' . self::$siteContent,
|
||||
'notification' => helper::translate('Impossible de supprimer une page contenant des pages enfants')
|
||||
]);
|
||||
}
|
||||
|
@ -302,10 +339,24 @@ class page extends common
|
|||
*/
|
||||
public function edit()
|
||||
{
|
||||
// La session ne correspond pas au site ouvert dans cet onglet
|
||||
if (
|
||||
// Contrôle la présence de l'id d'espace uniquement si l'id est fourni afin de ne pas bloquer les modules non mis à jour
|
||||
$this->getUrl(3) && $this->getUrl(3) != self::$siteContent
|
||||
) {
|
||||
$_SESSION['ZWII_SITE_CONTENT'] = $this->getUrl(3);
|
||||
header('Refresh:0; url=' . helper::baseUrl() . $this->getUrl());
|
||||
exit();
|
||||
}
|
||||
// La page n'existe pas
|
||||
if (
|
||||
$this->getUser('permission', __CLASS__, __FUNCTION__) !== true ||
|
||||
$this->getData(['page', $this->getUrl(2)]) === null
|
||||
$this->getUser('permission', __CLASS__, __FUNCTION__) !== true
|
||||
|| $this->getData(['page', $this->getUrl(2)]) === null
|
||||
// Contrôle la présence de l'id d'espace uniquement si l'id est fourni afin de ne pas bloquer les modules non mis à jour
|
||||
|| (
|
||||
$this->getUrl(3)
|
||||
&& $this->getUrl(3) != self::$siteContent
|
||||
)
|
||||
) {
|
||||
// Valeurs en sortie
|
||||
$this->addOutput([
|
||||
|
@ -357,6 +408,28 @@ class page extends common
|
|||
$this->setData(['module', $pageId, 'theme', 'style', $modulesData[$moduleId]['dataDirectory'] . $pageId]);
|
||||
}
|
||||
}
|
||||
// Met à jour les historiques des utilisateurs
|
||||
foreach ($this->getData(['enrolment', self::$siteContent]) as $userId => $userData) {
|
||||
// Vérifier si l'utilisateur a un historique
|
||||
if (
|
||||
isset($userData["history"])
|
||||
&& isset($userData['history'][$this->getUrl(2)])
|
||||
) {
|
||||
// Remplacer l'ancienne ID par la nouvelle
|
||||
$datas = $this->getData(['enrolment', self::$siteContent, $userId, 'history', $this->getUrl(2)]);
|
||||
$this->setData(['enrolment', self::$siteContent, $userId, 'history', $pageId, $datas]);
|
||||
$this->deleteData(['enrolment', self::$siteContent, $userId, 'history', $this->getUrl(2)]);
|
||||
}
|
||||
// Mettre à jour la dernière page vue si nécessaire
|
||||
if ($this->getData(['enrolment', self::$siteContent, $userId, 'lastPageView']) === $this->getUrl(2)) {
|
||||
$this->setData(['enrolment', self::$siteContent, $userId, 'lastPageView', $pageId]);
|
||||
}
|
||||
}
|
||||
// Met à jour la homePage si nécessaire
|
||||
if ($this->getUrl(2) === $this->getData(['course', self::$siteContent, 'homePageId'])) {
|
||||
$this->setData(['course', self::$siteContent, 'homePageId', $pageId]);
|
||||
}
|
||||
|
||||
// Si la page correspond à la page d'accueil, change l'id dans la configuration du site
|
||||
if ($this->getData(['config', 'homePageId']) === $this->getUrl(2)) {
|
||||
$this->setData(['config', 'homePageId', $pageId]);
|
||||
|
@ -538,7 +611,7 @@ class page extends common
|
|||
}
|
||||
}
|
||||
// Construction du formulaire
|
||||
|
||||
|
||||
// Met à jour le sitemap
|
||||
$this->updateSitemap();
|
||||
|
||||
|
@ -602,14 +675,15 @@ class page extends common
|
|||
$css = $this->getInput('pageCssEditorContent', helper::FILTER_STRING_LONG) === null ? '' : $this->getInput('pageCssEditorContent', helper::FILTER_STRING_LONG);
|
||||
// Enregistre le CSS
|
||||
$this->setData([
|
||||
'page', $this->getUrl(2),
|
||||
'page',
|
||||
$this->getUrl(2),
|
||||
'css',
|
||||
$css
|
||||
]);
|
||||
// Valeurs en sortie
|
||||
$this->addOutput([
|
||||
'notification' => helper::translate('Modifications enregistrées'),
|
||||
'redirect' => helper::baseUrl() . 'page/edit/' . $this->getUrl(2),
|
||||
'redirect' => helper::baseUrl() . 'page/edit/' . $this->getUrl(2) . '/' . self::$siteContent,
|
||||
'state' => true
|
||||
]);
|
||||
}
|
||||
|
@ -636,14 +710,15 @@ class page extends common
|
|||
$js = $this->getInput('pageJsEditorContent', helper::FILTER_STRING_LONG) === null ? '' : $this->getInput('pageJsEditorContent', helper::FILTER_STRING_LONG);
|
||||
// Enregistre le JS
|
||||
$this->setData([
|
||||
'page', $this->getUrl(2),
|
||||
'page',
|
||||
$this->getUrl(2),
|
||||
'js',
|
||||
$js
|
||||
]);
|
||||
// Valeurs en sortie
|
||||
$this->addOutput([
|
||||
'notification' => helper::translate('Modifications enregistrées'),
|
||||
'redirect' => helper::baseUrl() . 'page/edit/' . $this->getUrl(2),
|
||||
'redirect' => helper::baseUrl() . 'page/edit/' . $this->getUrl(2) . '/' . self::$siteContent,
|
||||
'state' => true
|
||||
]);
|
||||
}
|
||||
|
@ -659,16 +734,16 @@ class page extends common
|
|||
|
||||
/**
|
||||
* Retourne les informations sur les pages en omettant les clés CSS et JS qui occasionnent des bugs d'affichage dans l'éditeur de page
|
||||
* @return array tableau associatif des pages dans le menu
|
||||
* @return string tableau associatif des pages dans le menu
|
||||
*/
|
||||
public function getPageInfo()
|
||||
{
|
||||
$p = $this->getData(['page']);
|
||||
$d = array_map(function ($d) {
|
||||
unset($d["css"], $d["js"]);
|
||||
unset ($d["css"], $d["js"]);
|
||||
return $d;
|
||||
}, $p);
|
||||
return json_encode($d);
|
||||
|
||||
}
|
||||
|
||||
}
|
|
@ -3,7 +3,7 @@
|
|||
<div class="col1">
|
||||
<?php echo template::button('pageCssEditorBack', [
|
||||
'class' => 'buttonGrey',
|
||||
'href' => helper::baseUrl() . 'page/edit/' . $this->getUrl(2),
|
||||
'href' => helper::baseUrl() . 'page/edit/' . $this->getUrl(2) . '/' . self::$siteContent,
|
||||
'value' => template::ico('left')
|
||||
]); ?>
|
||||
</div>
|
||||
|
|
|
@ -19,14 +19,14 @@
|
|||
<div class="col1 offset6">
|
||||
<?php echo template::button('pageEditDelete', [
|
||||
'class' => 'buttonRed',
|
||||
'href' => helper::baseUrl() . 'page/delete/' . $this->getUrl(2),
|
||||
'href' => helper::baseUrl() . 'page/delete/' . $this->getUrl(2) . '/' . self::$siteContent,
|
||||
'value' => template::ico('trash'),
|
||||
'help' => 'Effacer la page'
|
||||
]); ?>
|
||||
</div>
|
||||
<div class="col1">
|
||||
<?php echo template::button('pageEditDuplicate', [
|
||||
'href' => helper::baseUrl() . 'page/duplicate/' . $this->getUrl(2),
|
||||
'href' => helper::baseUrl() . 'page/duplicate/' . $this->getUrl(2) . '/' . self::$siteContent,
|
||||
'value' => template::ico('clone'),
|
||||
'help' => 'Dupliquer la page'
|
||||
]); ?>
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
<div class="col1">
|
||||
<?php echo template::button('pageJsEditorBack', [
|
||||
'class' => 'buttonGrey',
|
||||
'href' => helper::baseUrl() . 'page/edit/' . $this->getUrl(2),
|
||||
'href' => helper::baseUrl() . 'page/edit/' . $this->getUrl(2) . '/' . self::$siteContent,
|
||||
'value' => template::ico('left')
|
||||
]); ?>
|
||||
</div>
|
||||
|
|
|
@ -19,6 +19,7 @@ $('#dataTables').DataTable({
|
|||
url: "core/vendor/datatables/french.json",
|
||||
},
|
||||
locale: 'fr',
|
||||
stateSave: true,
|
||||
"columnDefs": [{
|
||||
target: 5,
|
||||
orderable: false,
|
||||
|
|
|
@ -19,6 +19,7 @@ class user extends common
|
|||
public static $actions = [
|
||||
'add' => self::GROUP_ADMIN,
|
||||
'delete' => self::GROUP_ADMIN,
|
||||
'usersDelete' => self::GROUP_ADMIN,
|
||||
'import' => self::GROUP_ADMIN,
|
||||
'index' => self::GROUP_ADMIN,
|
||||
'template' => self::GROUP_ADMIN,
|
||||
|
@ -61,7 +62,7 @@ class user extends common
|
|||
public static $languagesInstalled = [];
|
||||
|
||||
public static $sharePath = [
|
||||
'/site/file/source/'
|
||||
'site/file/source/'
|
||||
];
|
||||
|
||||
public static $groupProfils = [
|
||||
|
@ -229,6 +230,145 @@ class user extends common
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Désinscription de tous les utilisateurs
|
||||
* Les désinscriptions ne suppriment pas les historiques
|
||||
*/
|
||||
public function usersDelete()
|
||||
{
|
||||
|
||||
// Contenu sélectionné
|
||||
$courseId = $this->getUrl(2);
|
||||
|
||||
// Accès limité aux admins, à l'auteur ou éditeurs inscrits
|
||||
if (
|
||||
$this->getUser('permission', __CLASS__, __FUNCTION__) !== true
|
||||
) {
|
||||
// Valeurs en sortie
|
||||
$this->addOutput([
|
||||
'access' => false
|
||||
]);
|
||||
}
|
||||
|
||||
// Inscription des utilisateurs cochés
|
||||
if (
|
||||
isset($_POST['usersDeleteSubmit'])
|
||||
) {
|
||||
foreach ($_POST as $keyPost => $valuePost) {
|
||||
// Exclure les variables post qui ne sont pas des userId et ne traiter que les non inscrits
|
||||
if (
|
||||
$this->getData(['user', $keyPost]) !== null
|
||||
&& $this->getData(['user', $keyPost]) !== null
|
||||
) {
|
||||
$this->deleteData(['user', $keyPost]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Liste des groupes et des profils
|
||||
$usersGroups = $this->getData(['profil']);
|
||||
|
||||
foreach ($usersGroups as $groupId => $groupValue) {
|
||||
switch ($groupId) {
|
||||
case "-1":
|
||||
case "0":
|
||||
break;
|
||||
case "3":
|
||||
self::$usersGroups['30'] = 'Administrateur';
|
||||
$profils['30'] = 0;
|
||||
break;
|
||||
case "1":
|
||||
case "2":
|
||||
foreach ($groupValue as $profilId => $profilValue) {
|
||||
if ($profilId) {
|
||||
self::$usersGroups[$groupId . $profilId] = sprintf(helper::translate('Groupe %s - Profil %s'), self::$groupPublics[$groupId], $profilValue['name']);
|
||||
$profils[$groupId . $profilId] = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Liste alphabétique
|
||||
self::$alphabet = range('A', 'Z');
|
||||
$alphabet = range('A', 'Z');
|
||||
self::$alphabet = array_combine($alphabet, self::$alphabet);
|
||||
self::$alphabet = array_merge(['all' => 'Tout'], self::$alphabet);
|
||||
|
||||
// Liste des inscrits dans le contenu sélectionné.
|
||||
$users = $this->getData(['user']);
|
||||
if (is_array($users)) {
|
||||
// Tri du tableau par défaut par $userId
|
||||
ksort($users);
|
||||
foreach ($users as $userId => $userValue) {
|
||||
|
||||
// Compte les rôles
|
||||
if (isset($profils[$this->getData(['user', $userId, 'group']) . $this->getData(['user', $userId, 'profil'])])) {
|
||||
$profils[$this->getData(['user', $userId, 'group']) . $this->getData(['user', $userId, 'profil'])]++;
|
||||
}
|
||||
|
||||
// Filtres
|
||||
if (
|
||||
isset($_POST['usersFilterGroup'])
|
||||
|| isset($_POST['usersFilterFirstName'])
|
||||
|| isset($_POST['usersFilterLastName'])
|
||||
) {
|
||||
|
||||
// Groupe et profils
|
||||
$group = (string) $this->getData(['user', $userId, 'group']);
|
||||
$profil = (string) $this->getData(['user', $userId, 'profil']);
|
||||
$firstName = $this->getData(['user', $userId, 'firstname']);
|
||||
$lastName = $this->getData(['user', $userId, 'lastname']);
|
||||
if (
|
||||
$this->getInput('usersFilterGroup', helper::FILTER_INT) > 0
|
||||
&& $this->getInput('usersFilterGroup', helper::FILTER_STRING_SHORT) !== $group . $profil
|
||||
)
|
||||
continue;
|
||||
// Première lettre du prénom
|
||||
if (
|
||||
$this->getInput('usersFilterFirstName', helper::FILTER_STRING_SHORT) !== 'all'
|
||||
&& $this->getInput('usersFilterFirstName', helper::FILTER_STRING_SHORT) !== strtoupper(substr($firstName, 0, 1))
|
||||
)
|
||||
continue;
|
||||
// Première lettre du nom
|
||||
if (
|
||||
$this->getInput('usersFilterLastName', helper::FILTER_STRING_SHORT) !== 'all'
|
||||
&& $this->getInput('usersFilterLastName', helper::FILTER_STRING_SHORT) !== strtoupper(substr($lastName, 0, 1))
|
||||
)
|
||||
continue;
|
||||
}
|
||||
|
||||
// Construction du tableau
|
||||
self::$users[] = [
|
||||
template::checkbox($userId, true, '', ['class' => 'checkboxSelect']),
|
||||
$userId,
|
||||
$this->getData(['user', $userId, 'firstname']),
|
||||
$this->getData(['user', $userId, 'lastname']),
|
||||
$this->getData(['user', $userId, 'tags']),
|
||||
];
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
// Ajoute les effectifs aux profils du sélecteur
|
||||
foreach (self::$usersGroups as $groupId => $groupValue) {
|
||||
if ($groupId === 'all') {
|
||||
self::$usersGroups['all'] = self::$usersGroups['all'] . ' (' . array_sum($profils) . ')';
|
||||
} else {
|
||||
self::$usersGroups[$groupId] = self::$usersGroups[$groupId] . ' (' . $profils[$groupId] . ')';
|
||||
}
|
||||
}
|
||||
|
||||
// Valeurs en sortie
|
||||
$this->addOutput([
|
||||
'title' => helper::translate('Désincription en masse'),
|
||||
'view' => 'usersDelete',
|
||||
'vendor' => [
|
||||
'datatables'
|
||||
]
|
||||
]);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Édition
|
||||
*/
|
||||
|
@ -518,13 +658,15 @@ class user extends common
|
|||
|
||||
// Formatage de la liste
|
||||
self::$users[] = [
|
||||
$userId,
|
||||
//$userId,
|
||||
$this->getData(['user', $userId, 'firstname']) . ' ' . $userLastNames,
|
||||
helper::translate(self::$groups[(int) $this->getData(['user', $userId, 'group'])]),
|
||||
empty($this->getData(['profil', $this->getData(['user', $userId, 'group']), $this->getData(['user', $userId, 'profil']), 'name']))
|
||||
? helper::translate(self::$groups[(int) $this->getData(['user', $userId, 'group'])])
|
||||
: $this->getData(['profil', $this->getData(['user', $userId, 'group']), $this->getData(['user', $userId, 'profil']), 'name']),
|
||||
$this->getData(['user', $userId, 'tags']),
|
||||
helper::dateUTF8('%d/%m/%Y', $this->getData(['user', $userId, 'accessTimer']), self::$i18nUI),
|
||||
//helper::dateUTF8('%H:%M', $this->getData(['user', $userId, 'accessTimer']), self::$i18nUI),
|
||||
template::button('userEdit' . $userId, [
|
||||
'href' => helper::baseUrl() . 'user/edit/' . $userId,
|
||||
'value' => template::ico('pencil'),
|
||||
|
@ -554,9 +696,9 @@ class user extends common
|
|||
$this->addOutput([
|
||||
'title' => helper::translate('Utilisateurs'),
|
||||
'view' => 'index',
|
||||
'vendor' => [
|
||||
'datatables'
|
||||
]
|
||||
'vendor' => [
|
||||
'datatables'
|
||||
]
|
||||
]);
|
||||
}
|
||||
|
||||
|
@ -574,7 +716,7 @@ class user extends common
|
|||
// Stoppe si le profil est affecté
|
||||
foreach ($groups as $userId) {
|
||||
if ((string) $this->getData(['user', $userId, 'profil']) === $this->getUrl(3)) {
|
||||
$profilUsed= false;
|
||||
$profilUsed = false;
|
||||
}
|
||||
}
|
||||
foreach ($this->getData(['profil']) as $groupId => $groupData) {
|
||||
|
@ -690,7 +832,8 @@ class user extends common
|
|||
'rename' => $this->getInput('profilEditFolderRename', helper::FILTER_BOOLEAN),
|
||||
'copycut' => $this->getInput('profilEditFolderCopycut', helper::FILTER_BOOLEAN),
|
||||
'chmod' => $this->getInput('profilEditFolderChmod', helper::FILTER_BOOLEAN),
|
||||
'path' => preg_replace('/^\\./', '', $this->getInput('profilEditPath')), // Supprime le point pour préserver le chemin
|
||||
'coursePath' => $this->getInput('profilEditCoursePath'), // Supprime le point pour préserver le chemin
|
||||
'homePath' => $this->getInput('profilEditHomePath'), // Supprime le point pour préserver le chemin
|
||||
],
|
||||
'page' => [
|
||||
'add' => $this->getInput('profilEditPageAdd', helper::FILTER_BOOLEAN),
|
||||
|
@ -703,6 +846,45 @@ class user extends common
|
|||
],
|
||||
'user' => [
|
||||
'edit' => $this->getInput('profilEditUserEdit', helper::FILTER_BOOLEAN),
|
||||
],
|
||||
'course' => [
|
||||
// Droit d'intervenir sur tous les espaces
|
||||
'tutor' => $this->getInput('profilEditCourseTutor', helper::FILTER_BOOLEAN),
|
||||
// Droit d'accéder à la fenêtre de gestion pour tous les éditeurs et plus
|
||||
'index' => $this->getInput('profilEditCourseUsers', helper::FILTER_BOOLEAN)
|
||||
|| $this->getInput('profilEditCourseUserHistory', helper::FILTER_BOOLEAN)
|
||||
|| $this->getInput('profilEditCourseUserExport', helper::FILTER_BOOLEAN)
|
||||
|| $this->getInput('profilEditCourseUserAdd', helper::FILTER_BOOLEAN)
|
||||
|| $this->getInput('profilEditCourseUsersAdd', helper::FILTER_BOOLEAN)
|
||||
|| $this->getInput('profilEditCourseUserDelete', helper::FILTER_BOOLEAN)
|
||||
|| $this->getInput('profilEditCourseUsersDelete', helper::FILTER_BOOLEAN)
|
||||
|| $this->getInput('profilEditCourseEdit', helper::FILTER_BOOLEAN)
|
||||
|| $this->getInput('profilEditCourseBackup', helper::FILTER_BOOLEAN)
|
||||
|| $this->getInput('profilEditCourseRestore', helper::FILTER_BOOLEAN),
|
||||
|
||||
'manage' => $this->getInput('profilEditCourseUsers', helper::FILTER_BOOLEAN)
|
||||
|| $this->getInput('profilEditCourseUserHistory', helper::FILTER_BOOLEAN)
|
||||
|| $this->getInput('profilEditCourseUserExport', helper::FILTER_BOOLEAN)
|
||||
|| $this->getInput('profilEditCourseUserAdd', helper::FILTER_BOOLEAN)
|
||||
|| $this->getInput('profilEditCourseUsersAdd', helper::FILTER_BOOLEAN)
|
||||
|| $this->getInput('profilEditCourseUserDelete', helper::FILTER_BOOLEAN)
|
||||
|| $this->getInput('profilEditCourseUsersDelete', helper::FILTER_BOOLEAN)
|
||||
|| $this->getInput('profilEditCourseEdit', helper::FILTER_BOOLEAN)
|
||||
|| $this->getInput('profilEditCourseBackup', helper::FILTER_BOOLEAN)
|
||||
|| $this->getInput('profilEditCourseRestore', helper::FILTER_BOOLEAN)
|
||||
|| $this->getInput('profilEditCourseReset', helper::FILTER_BOOLEAN),
|
||||
// Droits spécifiques
|
||||
'users' => $this->getInput('profilEditCourseUsers', helper::FILTER_BOOLEAN),
|
||||
'userHistory' => $this->getInput('profilEditCourseUserHistory', helper::FILTER_BOOLEAN),
|
||||
'userHistoryExport' => $this->getInput('profilEditCourseUserHistoryExport', helper::FILTER_BOOLEAN),
|
||||
'userAdd' => $this->getInput('profilEditCourseUserAdd', helper::FILTER_BOOLEAN),
|
||||
'usersAdd' => $this->getInput('profilEditCourseUsersAdd', helper::FILTER_BOOLEAN),
|
||||
'userDelete' => $this->getInput('profilEditCourseUserDelete', helper::FILTER_BOOLEAN),
|
||||
'usersDelete' => $this->getInput('profilEditCourseUsersDelete', helper::FILTER_BOOLEAN),
|
||||
'edit' => $this->getInput('profilEditCourseEdit', helper::FILTER_BOOLEAN),
|
||||
'backup' => $this->getInput('profilEditCourseBackup', helper::FILTER_BOOLEAN),
|
||||
'restore' => $this->getInput('profilEditCourseRestore', helper::FILTER_BOOLEAN),
|
||||
'reset' => $this->getInput('profilEditCourseReset', helper::FILTER_BOOLEAN),
|
||||
]
|
||||
];
|
||||
|
||||
|
@ -736,11 +918,20 @@ class user extends common
|
|||
}
|
||||
|
||||
// Chemin vers les dossiers du gestionnaire de fichier
|
||||
self::$sharePath = $this->getSubdirectories('./site/file/source');
|
||||
self::$sharePath = $this->getSubdirectories('site/file/source');
|
||||
|
||||
// Exclure les espaces des cours
|
||||
foreach (array_keys($this->getData(['course'])) as $courseId) {
|
||||
self::$sharePath = array_filter(self::$sharePath, function ($key) use ($courseId) {
|
||||
return strpos($key, $courseId) === false;
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
self::$sharePath = array_flip(self::$sharePath);
|
||||
self::$sharePath = array_merge(['./site/file/source/' => 'Tous les dossiers'], self::$sharePath);
|
||||
//self::$sharePath = array_merge(['' => 'Aucun dossier'], self::$sharePath);
|
||||
self::$sharePath = array_merge(['' => 'Dossier de l\'espace actif'], self::$sharePath);
|
||||
self::$sharePath = array_merge(['none' => 'Aucun Accès'], self::$sharePath);
|
||||
self::$sharePath = array_merge(['' => 'Confiné dans le dossier de l\'espace ouvert'], self::$sharePath);
|
||||
self::$sharePath = array_merge(['site/file/source/' => 'Tout le gestionnaire de fichiers'], self::$sharePath);
|
||||
|
||||
// Liste des modules installés
|
||||
self::$listModules = helper::getModules();
|
||||
|
@ -838,7 +1029,8 @@ class user extends common
|
|||
'rename' => $this->getInput('profilAddFolderRename', helper::FILTER_BOOLEAN),
|
||||
'copycut' => $this->getInput('profilAddFolderCopycut', helper::FILTER_BOOLEAN),
|
||||
'chmod' => $this->getInput('profilAddFolderChmod', helper::FILTER_BOOLEAN),
|
||||
'path' => preg_replace('/^\\./', '', $this->getInput('profilEditPath')), // Supprime le point pour préserver le chemin,
|
||||
'coursePath' => $this->getInput('profilAddCoursePath'), // Supprime le point pour préserver le chemin
|
||||
'homePath' => $this->getInput('profilAddHomePath'), // Supprime le point pour préserver le chemin
|
||||
],
|
||||
'page' => [
|
||||
'add' => $this->getInput('profilAddPageAdd', helper::FILTER_BOOLEAN),
|
||||
|
@ -851,6 +1043,43 @@ class user extends common
|
|||
],
|
||||
'user' => [
|
||||
'edit' => $this->getInput('profilAddUserEdit', helper::FILTER_BOOLEAN),
|
||||
],
|
||||
'course' => [
|
||||
'tutor' => $this->getInput('profilAddCourseTutor', helper::FILTER_BOOLEAN),
|
||||
'index' => $this->getInput('profilAddCourseUsers', helper::FILTER_BOOLEAN)
|
||||
|| $this->getInput('profilAddCourseUserHistory', helper::FILTER_BOOLEAN)
|
||||
|| $this->getInput('profilAddCourseUserExport', helper::FILTER_BOOLEAN)
|
||||
|| $this->getInput('profilAddCourseUserAdd', helper::FILTER_BOOLEAN)
|
||||
|| $this->getInput('profilAddCourseUsersAdd', helper::FILTER_BOOLEAN)
|
||||
|| $this->getInput('profilAddCourseUserDelete', helper::FILTER_BOOLEAN)
|
||||
|| $this->getInput('profilAddCourseUsersDelete', helper::FILTER_BOOLEAN)
|
||||
|| $this->getInput('profilAddCourseEdit', helper::FILTER_BOOLEAN)
|
||||
|| $this->getInput('profilAddCourseBackup', helper::FILTER_BOOLEAN)
|
||||
|| $this->getInput('profilAddCourseRestore', helper::FILTER_BOOLEAN),
|
||||
|
||||
'manage' => $this->getInput('profilAddCourseUsers', helper::FILTER_BOOLEAN)
|
||||
|| $this->getInput('profilAddCourseUserHistory', helper::FILTER_BOOLEAN)
|
||||
|| $this->getInput('profilAddCourseUserExport', helper::FILTER_BOOLEAN)
|
||||
|| $this->getInput('profilAddCourseUserAdd', helper::FILTER_BOOLEAN)
|
||||
|| $this->getInput('profilAddCourseUsersAdd', helper::FILTER_BOOLEAN)
|
||||
|| $this->getInput('profilAddCourseUserDelete', helper::FILTER_BOOLEAN)
|
||||
|| $this->getInput('profilAddCourseUsersDelete', helper::FILTER_BOOLEAN)
|
||||
|| $this->getInput('profilAddCourseEdit', helper::FILTER_BOOLEAN)
|
||||
|| $this->getInput('profilAddCourseBackup', helper::FILTER_BOOLEAN)
|
||||
|| $this->getInput('profilAddCourseRestore', helper::FILTER_BOOLEAN)
|
||||
|| $this->getInput('profilAddCourseReset', helper::FILTER_BOOLEAN),
|
||||
// La suite
|
||||
'users' => $this->getInput('profilAddCourseUsers', helper::FILTER_BOOLEAN),
|
||||
'userHistory' => $this->getInput('profilAddCourseUserHistory', helper::FILTER_BOOLEAN),
|
||||
'userHistoryExport' => $this->getInput('profilAddCourseUserHistoryExport', helper::FILTER_BOOLEAN),
|
||||
'userAdd' => $this->getInput('profilAddCourseUserAdd', helper::FILTER_BOOLEAN),
|
||||
'usersAdd' => $this->getInput('profilAddCourseUsersAdd', helper::FILTER_BOOLEAN),
|
||||
'userDelete' => $this->getInput('profilAddCourseUserDelete', helper::FILTER_BOOLEAN),
|
||||
'usersDelete' => $this->getInput('profilAddCourseUsersDelete', helper::FILTER_BOOLEAN),
|
||||
'edit' => $this->getInput('profilAddCourseEdit', helper::FILTER_BOOLEAN),
|
||||
'backup' => $this->getInput('profilAddCourseBackup', helper::FILTER_BOOLEAN),
|
||||
'restore' => $this->getInput('profilAddCourseRestore', helper::FILTER_BOOLEAN),
|
||||
'reset' => $this->getInput('profilAddCourseReset', helper::FILTER_BOOLEAN),
|
||||
]
|
||||
];
|
||||
|
||||
|
@ -892,11 +1121,21 @@ class user extends common
|
|||
}
|
||||
|
||||
// Chemin vers les dossiers du gestionnaire de fichier
|
||||
self::$sharePath = $this->getSubdirectories('./site/file/source');
|
||||
self::$sharePath = $this->getSubdirectories('site/file/source');
|
||||
|
||||
// Exclure les espaces des cours
|
||||
/*
|
||||
foreach (array_keys($this->getData(['course'])) as $courseId) {
|
||||
self::$sharePath = array_filter(self::$sharePath, function ($key) use ($courseId) {
|
||||
return strpos($key, $courseId) === false;
|
||||
});
|
||||
}
|
||||
*/
|
||||
|
||||
self::$sharePath = array_flip(self::$sharePath);
|
||||
self::$sharePath = array_merge(['./site/file/source/' => 'Tous les dossiers'], self::$sharePath);
|
||||
//self::$sharePath = array_merge(['' => 'Aucun dossier'], self::$sharePath);
|
||||
self::$sharePath = array_merge(['' => 'Dossier de l\'espace actif'], self::$sharePath);
|
||||
self::$sharePath = array_merge(['none' => 'Aucun Accès'], self::$sharePath);
|
||||
self::$sharePath = array_merge(['' => 'Confiné dans le dossier de l\'espace ouvert'], self::$sharePath);
|
||||
self::$sharePath = array_merge(['site/file/source/' => 'Tout le gestionnaire de fichiers'], self::$sharePath);
|
||||
|
||||
// Liste des modules installés
|
||||
self::$listModules = helper::getModules();
|
||||
|
@ -932,11 +1171,11 @@ class user extends common
|
|||
// recherche les membres du groupe
|
||||
$groups = helper::arrayColumn($this->getData(['user']), 'group');
|
||||
$groups = array_keys($groups, $this->getUrl(2));
|
||||
$flag= true;
|
||||
$flag = true;
|
||||
// Stoppe si le profil est affecté
|
||||
foreach ($groups as $userId) {
|
||||
if ((string) $this->getData(['user', $userId, 'profil']) === $this->getUrl(3)) {
|
||||
$flag= false;
|
||||
$flag = false;
|
||||
}
|
||||
}
|
||||
if (
|
||||
|
@ -953,7 +1192,7 @@ class user extends common
|
|||
if ($flag) {
|
||||
$this->deleteData(['profil', $this->getUrl(2), $this->getUrl(3)]);
|
||||
}
|
||||
|
||||
|
||||
// Valeurs en sortie
|
||||
$this->addOutput([
|
||||
'redirect' => helper::baseUrl() . $this->getUrl(0) . '/profil',
|
||||
|
@ -1060,7 +1299,14 @@ class user extends common
|
|||
]);
|
||||
} else {
|
||||
$logStatus = 'Connexion réussie';
|
||||
$redirect = ($this->getUrl(2) && strpos($this->getUrl(2), 'user_reset') !== 0) ? helper::baseUrl() . str_replace('_', '/', str_replace('__', '#', $this->getUrl(2))) : helper::baseUrl();
|
||||
$pageId = $this->getUrl(2);
|
||||
if (
|
||||
$this->getData(['config', 'page404']) === $pageId
|
||||
|| $this->getData(['config', 'page403']) === $pageId
|
||||
) {
|
||||
$pageId = '';
|
||||
}
|
||||
$redirect = ($pageId && strpos($pageId, 'user_reset') !== 0) ? helper::baseUrl() . str_replace('_', '/', str_replace('__', '#', $pageId)) : helper::baseUrl();
|
||||
// Valeurs en sortie
|
||||
$this->addOutput([
|
||||
'notification' => sprintf(helper::translate('Bienvenue %s %s'), $this->getData(['user', $userId, 'firstname']), $this->getData(['user', $userId, 'lastname'])),
|
||||
|
|
|
@ -77,8 +77,9 @@
|
|||
<div class="col12">
|
||||
<?php echo template::text('userEditTags', [
|
||||
'label' => 'Étiquettes',
|
||||
'readonly' => $this->getUser('group') > self::GROUP_EDITOR ? false : true,
|
||||
'value' => $this->getData(['user', $this->getUrl(2), 'tags']),
|
||||
'help' => 'Le séparateur d\'étiquettes est l\'espace'
|
||||
'help' => 'Les étiquettes sont séparées par des espaces'
|
||||
]); ?>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
@ -22,12 +22,13 @@ $(document).ready((function () {
|
|||
$("#userFilterGroup, #userFilterFirstName, #userFilterLastName").change(function () {
|
||||
$("#userFilterUserForm").submit();
|
||||
});
|
||||
|
||||
$.fn.dataTable.moment( 'DD/MM/YYYY' );
|
||||
$('#dataTables').DataTable({
|
||||
language: {
|
||||
url: "core/vendor/datatables/french.json"
|
||||
},
|
||||
locale: 'fr',
|
||||
stateSave: true,
|
||||
"columnDefs": [
|
||||
{
|
||||
target: 5,
|
||||
|
|
|
@ -8,20 +8,28 @@
|
|||
</div>
|
||||
<div class="col1">
|
||||
<?php /**echo template::button('userHelp', [
|
||||
'href' => 'https://doc.zwiicms.fr/gestion-des-utilisateurs',
|
||||
'target' => '_blank',
|
||||
'value' => template::ico('help'),
|
||||
'class' => 'buttonHelp',
|
||||
'help' => 'Consulter l\'aide en ligne'
|
||||
]);*/?>
|
||||
'href' => 'https://doc.zwiicms.fr/gestion-des-utilisateurs',
|
||||
'target' => '_blank',
|
||||
'value' => template::ico('help'),
|
||||
'class' => 'buttonHelp',
|
||||
'help' => 'Consulter l\'aide en ligne'
|
||||
]);*/ ?>
|
||||
</div>
|
||||
<div class="col1 offset7">
|
||||
<div class="col1 offset6">
|
||||
<?php echo template::button('userImport', [
|
||||
'href' => helper::baseUrl() . 'user/import',
|
||||
'value' => template::ico('upload'),
|
||||
'value' => template::ico('users'),
|
||||
'help' => 'Importer des utilisateurs en masse'
|
||||
]); ?>
|
||||
</div>
|
||||
<div class="col1">
|
||||
<?php echo template::button('userDeleteAll', [
|
||||
'class' => 'userDeleteAll buttonRed',
|
||||
'href' => helper::baseUrl() . 'user/usersDelete/' . $this->getUrl(2),
|
||||
'value' => template::ico('users'),
|
||||
'help' => 'Désinscrire en masse',
|
||||
]) ?>
|
||||
</div>
|
||||
<div class="col1">
|
||||
<?php echo template::button('userGroup', [
|
||||
'href' => helper::baseUrl() . 'user/profil',
|
||||
|
@ -60,4 +68,4 @@
|
|||
</div>
|
||||
</div>
|
||||
<?php echo template::formClose(); ?>
|
||||
<?php echo template::table([2, 2, 2, 2, 2, 1, 1], $module::$users, ['Identifiant', 'Nom', 'Groupe', 'Profil', 'Étiquettes', '', ''], ['id' => 'dataTables']); ?>
|
||||
<?php echo template::table([3, 2, 2, 2, 2, 1, 1], $module::$users, ['Nom', 'Groupe', 'Profil', 'Étiquettes', 'Date dernière vue', '', ''], ['id' => 'dataTables']); ?>
|
|
@ -44,47 +44,6 @@
|
|||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row containerPage">
|
||||
<div class="col12">
|
||||
<div class="block">
|
||||
<h4>
|
||||
<?php echo helper::translate('Permissions sur les pages'); ?>
|
||||
</h4>
|
||||
<div class="row">
|
||||
<div class="col3">
|
||||
<?php echo template::checkbox('profilAddPageAdd', true, 'Ajouter'); ?>
|
||||
</div>
|
||||
<div class="col3">
|
||||
<?php echo template::checkbox('profilAddPageEdit', true, 'Éditer'); ?>
|
||||
</div>
|
||||
<div class="col3">
|
||||
<?php echo template::checkbox('profilAddPageDelete', true, 'Effacer'); ?>
|
||||
</div>
|
||||
<div class="col3">
|
||||
<?php echo template::checkbox('profilAddPageDuplicate', true, 'Dupliquer'); ?>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col3">
|
||||
<?php echo template::checkbox('profilAddPageModule', true, 'Module'); ?>
|
||||
</div>
|
||||
<div class="col3">
|
||||
<?php echo template::checkbox('profilAddPagecssEditor', true, 'Éditeur CSS'); ?>
|
||||
</div>
|
||||
<div class="col3">
|
||||
<?php echo template::checkbox('profilAddPagejsEditor', true, 'Éditeur JS'); ?>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="containerModule">
|
||||
<?php foreach (user::$listModules as $moduleId): ?>
|
||||
<?php if (file_exists('module/' . $moduleId . '/profil/view/add.inc.php')) {
|
||||
include('module/' . $moduleId . '/profil/view/add.inc.php');
|
||||
} ?>
|
||||
<?php endforeach; ?>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col12">
|
||||
<div class="block">
|
||||
|
@ -109,11 +68,16 @@
|
|||
<div class="col3">
|
||||
<?php echo template::checkbox('profilAddFileManager', true, 'Autorisé'); ?>
|
||||
</div>
|
||||
<div class="col6">
|
||||
<?php echo template::select('profilAddPath', $module::$sharePath, [
|
||||
'label' => 'Dossier',
|
||||
<div class="col5">
|
||||
<?php echo template::select('profilAddCoursePath', $module::$sharePath, [
|
||||
'label' => 'Dossier depuis un espace',
|
||||
'class' => 'filemanager',
|
||||
]); ?>
|
||||
</div>
|
||||
<div class="col5">
|
||||
<?php echo template::select('profilAddHomePath', $module::$sharePath, [
|
||||
'label' => 'Dossier depuis l\'accueil',
|
||||
'class' => 'filemanager',
|
||||
'help' => 'Chaque espace dispose d\'un dossier spécifique, le choix "Dossier de l\'espace actif" le sélectionne automatiquement.'
|
||||
]); ?>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -195,4 +159,97 @@
|
|||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row containerPage">
|
||||
<div class="col12">
|
||||
<div class="block">
|
||||
<h4>
|
||||
<?php echo helper::translate('Gestion des espaces'); ?>
|
||||
</h4>
|
||||
<div class="row">
|
||||
<div class="col6">
|
||||
<?php echo template::checkbox('profilAddCourseTutor', true, 'Gère les espaces comme auteur et participant'); ?>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col3">
|
||||
<?php echo template::checkbox('profilAddCourseEdit', true, 'Éditer un espace'); ?>
|
||||
</div>
|
||||
<div class="col3">
|
||||
<?php echo template::checkbox('profilAddCourseBackup', true, 'Sauvegarder un espace'); ?>
|
||||
</div>
|
||||
<div class="col3">
|
||||
<?php echo template::checkbox('profilAddCourseRestore', true, 'Restaurer un espace'); ?>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col6">
|
||||
<?php echo template::checkbox('profilAddCourseUsers', true, 'Gérer les participants'); ?>
|
||||
</div>
|
||||
</div>
|
||||
<div id="courseContainer">
|
||||
<div class="row">
|
||||
<div class="col3">
|
||||
<?php echo template::checkbox('profilAddCourseUserHistory', true, 'Voir historique d\'un participant'); ?>
|
||||
</div>
|
||||
<div class="col3">
|
||||
<?php echo template::checkbox('profilAddCourseUserHistoryExport', true, 'Exporter historique d\'un participant'); ?>
|
||||
</div>
|
||||
<div class="col3">
|
||||
<?php echo template::checkbox('profilAddCourseUserDelete', true, 'Désinscrire un participant'); ?>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col3">
|
||||
<?php echo template::checkbox('profilAddCourseUsersAdd', true, 'Inscrire en masse'); ?>
|
||||
</div>
|
||||
<div class="col3">
|
||||
<?php echo template::checkbox('profilAddCourseUsersDelete', true, 'Désinscrire en masse'); ?>
|
||||
</div>
|
||||
<div class="col3">
|
||||
<?php echo template::checkbox('profilAddCourseReset', true, 'Réinitialiser un espace'); ?>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col12">
|
||||
<div class="block">
|
||||
<h4>
|
||||
<?php echo helper::translate('Permissions sur les pages'); ?>
|
||||
</h4>
|
||||
<div class="row">
|
||||
<div class="col3">
|
||||
<?php echo template::checkbox('profilAddPageAdd', true, 'Ajouter'); ?>
|
||||
</div>
|
||||
<div class="col3">
|
||||
<?php echo template::checkbox('profilAddPageEdit', true, 'Éditer'); ?>
|
||||
</div>
|
||||
<div class="col3">
|
||||
<?php echo template::checkbox('profilAddPageDelete', true, 'Effacer'); ?>
|
||||
</div>
|
||||
<div class="col3">
|
||||
<?php echo template::checkbox('profilAddPageDuplicate', true, 'Dupliquer'); ?>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col3">
|
||||
<?php echo template::checkbox('profilAddPageModule', true, 'Module'); ?>
|
||||
</div>
|
||||
<div class="col3">
|
||||
<?php echo template::checkbox('profilAddPagecssEditor', true, 'Éditeur CSS'); ?>
|
||||
</div>
|
||||
<div class="col3">
|
||||
<?php echo template::checkbox('profilAddPagejsEditor', true, 'Éditeur JS'); ?>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="containerModule">
|
||||
<?php foreach (user::$listModules as $moduleId): ?>
|
||||
<?php if (file_exists('module/' . $moduleId . '/profil/view/add.inc.php')) {
|
||||
include('module/' . $moduleId . '/profil/view/add.inc.php');
|
||||
} ?>
|
||||
<?php endforeach; ?>
|
||||
</div>
|
||||
<?php echo template::formClose(); ?>
|
|
@ -54,6 +54,19 @@ $(document).ready(function () {
|
|||
$(".containerModule").slideDown();
|
||||
}
|
||||
|
||||
if ($('#profilEditCourseUsers').is(':checked')) {
|
||||
// Activer les autres checkboxes
|
||||
$('#profilEditCourseUserHistory, #profilEditCourseUserHistoryExport, #profilEditCourseUserDelete, #profilEditCourseUsersAdd, #profilEditCourseUsersDelete, #profilEditCourseReset').prop('disabled', false);
|
||||
} else {
|
||||
// Désactiver les autres checkboxes
|
||||
$('#profilEditCourseUserHistory, #profilEditCourseUserHistoryExport, #profilEditCourseUserDelete, #profilEditCourseUsersAdd, #profilEditCourseUsersDelete, #profilEditCourseReset').prop('checked', false).prop('disabled', true);
|
||||
// Désactiver les modules et tout décocher
|
||||
$(".courseContainer").slideUp();
|
||||
$('.courseContainer input[type="checkbox"]').prop('checked', false);
|
||||
}
|
||||
|
||||
// EVENEMENTS
|
||||
|
||||
// À chaque inversion de l'état du checkbox avec l'id "profilEditFileManager", désactive ou active tous les éléments de la classe "filemanager" en fonction de l'état
|
||||
$("#profilEditFileManager").change(function () {
|
||||
if (!$(this).is(':checked')) {
|
||||
|
@ -68,7 +81,7 @@ $(document).ready(function () {
|
|||
if (!$(this).is(':checked')) {
|
||||
$(".blogEditCommentOptions").slideUp();
|
||||
} else {
|
||||
$('.blogEditCommentOptions input[type="checkbox"]').prop('checked', false);
|
||||
$('.blogEditCommentOptions input[type="checkbox"]').prop("disabled", true);
|
||||
$(".blogEditCommentOptions").slideDown();
|
||||
}
|
||||
});
|
||||
|
@ -118,4 +131,20 @@ $(document).ready(function () {
|
|||
}
|
||||
});
|
||||
|
||||
// Gérer l’évènement de modification de la checkbox #profilEditCourse
|
||||
$('#profilEditCourseUsers').change(function () {
|
||||
if ($(this).is(':checked')) {
|
||||
// Activer les autres checkboxes
|
||||
$('#profilEditCourseUserHistory, #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);
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
});
|
||||
|
|
|
@ -27,9 +27,9 @@
|
|||
'label' => 'Nom du profil',
|
||||
'value' => helper::translate($this->getData(['profil', $this->getUrl(2), $this->getUrl(3), 'name']))
|
||||
]); ?>
|
||||
</div>
|
||||
<div class="col6">
|
||||
<?php echo template::select('profilEditProfil', $module::$profils, [
|
||||
</div>
|
||||
<div class="col6">
|
||||
<?php echo template::select('profilEditProfil', $module::$profils, [
|
||||
'label' => 'Hiérarchie',
|
||||
'help' => 'Rang 9 > rang 1. Le profil de rang 1 n\'est pas modifiable.',
|
||||
'selected' => $this->getUrl(3),
|
||||
|
@ -63,63 +63,6 @@
|
|||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<?php if ($this->getUrl(2) >= self::GROUP_EDITOR): ?>
|
||||
<div class="row">
|
||||
<div class="col12">
|
||||
<div class="block">
|
||||
<h4>
|
||||
<?php echo helper::translate('Permissions sur les pages'); ?>
|
||||
</h4>
|
||||
<div class="row">
|
||||
<div class="col3">
|
||||
<?php echo template::checkbox('profilEditPageAdd', true, 'Ajouter', [
|
||||
'checked' => $this->getData(['profil', $this->getUrl(2), $this->getUrl(3), 'page', 'add'])
|
||||
]); ?>
|
||||
</div>
|
||||
<div class="col3">
|
||||
<?php echo template::checkbox('profilEditPageEdit', true, 'Éditer', [
|
||||
'checked' => $this->getData(['profil', $this->getUrl(2), $this->getUrl(3), 'page', 'edit'])
|
||||
]); ?>
|
||||
</div>
|
||||
<div class="col3">
|
||||
<?php echo template::checkbox('profilEditPageDelete', true, 'Effacer', [
|
||||
'checked' => $this->getData(['profil', $this->getUrl(2), $this->getUrl(3), 'page', 'delete'])
|
||||
]); ?>
|
||||
</div>
|
||||
<div class="col3">
|
||||
<?php echo template::checkbox('profilEditPageDuplicate', true, 'Dupliquer', [
|
||||
'checked' => $this->getData(['profil', $this->getUrl(2), $this->getUrl(3), 'page', 'duplicate'])
|
||||
]); ?>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col3">
|
||||
<?php echo template::checkbox('profilEditPageModule', true, 'Module', [
|
||||
'checked' => $this->getData(['profil', $this->getUrl(2), $this->getUrl(3), 'page', 'module'])
|
||||
]); ?>
|
||||
</div>
|
||||
<div class="col3">
|
||||
<?php echo template::checkbox('profilEditPagecssEditor', true, 'Éditeur CSS', [
|
||||
'checked' => $this->getData(['profil', $this->getUrl(2), $this->getUrl(3), 'page', 'cssEditor'])
|
||||
]); ?>
|
||||
</div>
|
||||
<div class="col3">
|
||||
<?php echo template::checkbox('profilEditPagejsEditor', true, 'Éditeur JS', [
|
||||
'checked' => $this->getData(['profil', $this->getUrl(2), $this->getUrl(3), 'page', 'jsEditor'])
|
||||
]); ?>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="containerModule">
|
||||
<?php foreach (user::$listModules as $moduleId): ?>
|
||||
<?php if (file_exists('module/' . $moduleId . '/profil/view/edit.inc.php')) {
|
||||
include('module/' . $moduleId . '/profil/view/edit.inc.php');
|
||||
} ?>
|
||||
<?php endforeach; ?>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
<div class="row">
|
||||
<div class="col12">
|
||||
<div class="block">
|
||||
|
@ -136,6 +79,7 @@
|
|||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
<div class="col12">
|
||||
<div class="block">
|
||||
|
@ -143,17 +87,28 @@
|
|||
<?php echo helper::translate('Gestionnaire de fichiers'); ?>
|
||||
</h4>
|
||||
<div class="row">
|
||||
<div class="col3">
|
||||
<div class="col2">
|
||||
<?php echo template::checkbox('profilEditFileManager', true, 'Autorisé', [
|
||||
'checked' => $this->getData(['profil', $this->getUrl(2), $this->getUrl(3), 'filemanager'])
|
||||
]); ?>
|
||||
</div>
|
||||
<div class="col6">
|
||||
<?php echo template::select('profilEditPath', $module::$sharePath, [
|
||||
'label' => 'Dossier',
|
||||
<div class="col5">
|
||||
<?php echo template::select('profilEditCoursePath', $module::$sharePath, [
|
||||
'label' => 'Dossier depuis un espace',
|
||||
'class' => 'filemanager',
|
||||
'selected' => '.' . $this->getData(['profil', $this->getUrl(2), $this->getUrl(3), 'folder', 'path']),
|
||||
'help' => 'Chaque espace dispose d\'un dossier spécifique, le choix \'Dossier de l\'espace actif\' le sélectionne automatiquement.'
|
||||
/*
|
||||
* 'none' interdit l'accès au gestionnaire de fichier
|
||||
* Ce n'est pas un chemin donc on n'ajoute pas le .
|
||||
*/
|
||||
'selected' => $this->getData(['profil', $this->getUrl(2), $this->getUrl(3), 'folder', 'coursePath'])
|
||||
]); ?>
|
||||
</div>
|
||||
<div class="col5">
|
||||
<?php echo template::select('profilEditHomePath', $module::$sharePath, [
|
||||
'label' => 'Dossier depuis l\'accueil',
|
||||
'class' => 'filemanager',
|
||||
// 'none' interdit l'accès au gestionnaire de fichier au niveau de l'accueil
|
||||
'selected' => $this->getData(['profil', $this->getUrl(2), $this->getUrl(3), 'folder', 'homePath'])
|
||||
]); ?>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -284,4 +239,138 @@
|
|||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<?php if ($this->getUrl(2) >= self::GROUP_EDITOR): ?>
|
||||
<div class="row">
|
||||
<div class="col12">
|
||||
<div class="block">
|
||||
<h4>
|
||||
<?php echo helper::translate('Gestion des espaces'); ?>
|
||||
</h4>
|
||||
<div class="row">
|
||||
<div class="col6">
|
||||
<?php echo template::checkbox('profilEditCourseTutor', true, 'Gère les espaces comme auteur et participant', [
|
||||
'checked' => $this->getData(['profil', $this->getUrl(2), $this->getUrl(3), 'course', 'tutor'])
|
||||
]); ?>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
<div class="col3">
|
||||
<?php echo template::checkbox('profilEditCourseEdit', true, 'Éditer un espace', [
|
||||
'checked' => $this->getData(['profil', $this->getUrl(2), $this->getUrl(3), 'course', 'edit']),
|
||||
]); ?>
|
||||
</div>
|
||||
<div class="col3">
|
||||
<?php echo template::checkbox('profilEditCourseBackup', true, 'Sauvegarder un espace', [
|
||||
'checked' => $this->getData(['profil', $this->getUrl(2), $this->getUrl(3), 'course', 'backup']),
|
||||
]); ?>
|
||||
</div>
|
||||
<div class="col3">
|
||||
<?php echo template::checkbox('profilEditCourseRestore', true, 'Restaurer un espace', [
|
||||
'checked' => $this->getData(['profil', $this->getUrl(2), $this->getUrl(3), 'course', 'restore']),
|
||||
]); ?>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col6">
|
||||
<?php echo template::checkbox('profilEditCourseUsers', true, 'Gérer les participants', [
|
||||
'checked' => $this->getData(['profil', $this->getUrl(2), $this->getUrl(3), 'course', 'users']),
|
||||
]); ?>
|
||||
</div>
|
||||
</div>
|
||||
<div id="courseContainer">
|
||||
<div class="row">
|
||||
<div class="col3">
|
||||
<?php echo template::checkbox('profilEditCourseUserHistory', true, 'Voir historique d\'un participant', [
|
||||
'checked' => $this->getData(['profil', $this->getUrl(2), $this->getUrl(3), 'course', 'userHistory']),
|
||||
]); ?>
|
||||
</div>
|
||||
<div class="col3">
|
||||
<?php echo template::checkbox('profilEditCourseUserHistoryExport', true, 'Exporter historique d\'un participant', [
|
||||
'checked' => $this->getData(['profil', $this->getUrl(2), $this->getUrl(3), 'course', 'userHistoryExport']),
|
||||
]); ?>
|
||||
</div>
|
||||
<div class="col3">
|
||||
<?php echo template::checkbox('profilEditCourseUserDelete', true, 'Désinscrire un participant', [
|
||||
'checked' => $this->getData(['profil', $this->getUrl(2), $this->getUrl(3), 'course', 'userDelete']),
|
||||
]); ?>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col3">
|
||||
<?php echo template::checkbox('profilEditCourseUsersAdd', true, 'Inscrire en masse', [
|
||||
'checked' => $this->getData(['profil', $this->getUrl(2), $this->getUrl(3), 'course', 'usersAdd']),
|
||||
]); ?>
|
||||
</div>
|
||||
<div class="col3">
|
||||
<?php echo template::checkbox('profilEditCourseUsersDelete', true, 'Désinscrire en masse', [
|
||||
'checked' => $this->getData(['profil', $this->getUrl(2), $this->getUrl(3), 'course', 'usersDelete']),
|
||||
]); ?>
|
||||
</div>
|
||||
<div class="col3">
|
||||
<?php echo template::checkbox('profilEditCourseReset', true, 'Réinitialiser un espace', [
|
||||
'checked' => $this->getData(['profil', $this->getUrl(2), $this->getUrl(3), 'course', 'reset']),
|
||||
]); ?>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col12">
|
||||
<div class="block">
|
||||
<h4>
|
||||
<?php echo helper::translate('Permissions sur les pages'); ?>
|
||||
</h4>
|
||||
<div class="row">
|
||||
<div class="col3">
|
||||
<?php echo template::checkbox('profilEditPageAdd', true, 'Ajouter', [
|
||||
'checked' => $this->getData(['profil', $this->getUrl(2), $this->getUrl(3), 'page', 'add'])
|
||||
]); ?>
|
||||
</div>
|
||||
<div class="col3">
|
||||
<?php echo template::checkbox('profilEditPageEdit', true, 'Éditer', [
|
||||
'checked' => $this->getData(['profil', $this->getUrl(2), $this->getUrl(3), 'page', 'edit'])
|
||||
]); ?>
|
||||
</div>
|
||||
<div class="col3">
|
||||
<?php echo template::checkbox('profilEditPageDelete', true, 'Effacer', [
|
||||
'checked' => $this->getData(['profil', $this->getUrl(2), $this->getUrl(3), 'page', 'delete'])
|
||||
]); ?>
|
||||
</div>
|
||||
<div class="col3">
|
||||
<?php echo template::checkbox('profilEditPageDuplicate', true, 'Dupliquer', [
|
||||
'checked' => $this->getData(['profil', $this->getUrl(2), $this->getUrl(3), 'page', 'duplicate'])
|
||||
]); ?>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col3">
|
||||
<?php echo template::checkbox('profilEditPageModule', true, 'Module', [
|
||||
'checked' => $this->getData(['profil', $this->getUrl(2), $this->getUrl(3), 'page', 'module'])
|
||||
]); ?>
|
||||
</div>
|
||||
<div class="col3">
|
||||
<?php echo template::checkbox('profilEditPagecssEditor', true, 'Éditeur CSS', [
|
||||
'checked' => $this->getData(['profil', $this->getUrl(2), $this->getUrl(3), 'page', 'cssEditor'])
|
||||
]); ?>
|
||||
</div>
|
||||
<div class="col3">
|
||||
<?php echo template::checkbox('profilEditPagejsEditor', true, 'Éditeur JS', [
|
||||
'checked' => $this->getData(['profil', $this->getUrl(2), $this->getUrl(3), 'page', 'jsEditor'])
|
||||
]); ?>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="containerModule">
|
||||
<?php foreach (user::$listModules as $moduleId): ?>
|
||||
<?php if (file_exists('module/' . $moduleId . '/profil/view/edit.inc.php')) {
|
||||
include('module/' . $moduleId . '/profil/view/edit.inc.php');
|
||||
} ?>
|
||||
<?php endforeach; ?>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
<?php echo template::formClose(); ?>
|
|
@ -0,0 +1,26 @@
|
|||
/**
|
||||
* This file is part of Zwii.
|
||||
*
|
||||
* For full copyright and license information, please see the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*
|
||||
* @author Rémi Jean <remi.jean@outlook.com>
|
||||
* @copyright Copyright (C) 2008-2018, Rémi Jean
|
||||
* @author Frédéric Tempez <frederic.tempez@outlook.com>
|
||||
* @copyright Copyright (C) 2018-2024, Frédéric Tempez
|
||||
* @license CC Attribution-NonCommercial-NoDerivatives 4.0 International
|
||||
* @link http://zwiicms.fr/
|
||||
*/
|
||||
|
||||
|
||||
/** NE PAS EFFACER
|
||||
* admin.css
|
||||
*/
|
||||
|
||||
#usersDeleteSubmit {
|
||||
background-color: rgba(217, 95, 78, 1);
|
||||
}
|
||||
|
||||
tr {
|
||||
cursor: pointer;
|
||||
}
|
|
@ -0,0 +1,100 @@
|
|||
/**
|
||||
* This file is part of Zwii.
|
||||
* For full copyright and license information, please see the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*
|
||||
* @author Rémi Jean <remi.jean@outlook.com>
|
||||
* @copyright Copyright (C) 2008-2018, Rémi Jean
|
||||
* @author Frédéric Tempez <frederic.tempez@outlook.com>
|
||||
* @copyright Copyright (C) 2018-2024, Frédéric Tempez
|
||||
* @license CC Attribution-NonCommercial-NoDerivatives 4.0 International
|
||||
* @link http://zwiicms.fr/
|
||||
*/
|
||||
|
||||
$(document).ready((function () {
|
||||
|
||||
$('tr').click(function () {
|
||||
// Cochez ou décochez la case à cocher dans cette ligne
|
||||
$(this).find('input[type="checkbox"]').prop('checked', function (i, val) {
|
||||
return !val; // Inverse l'état actuel de la case à cocher
|
||||
});
|
||||
});
|
||||
|
||||
$('#usersDeleteSelectAll').on('click', function () {
|
||||
$('.checkboxSelect').prop('checked', true);
|
||||
saveCheckboxState();
|
||||
});
|
||||
$('#usersDeleteSelectNone').on('click', function () {
|
||||
$('.checkboxSelect').prop('checked', false);
|
||||
saveCheckboxState();
|
||||
});
|
||||
|
||||
$("#usersFilterGroup, #usersFilterFirstName, #usersFilterLastName").change(function () {
|
||||
saveCheckboxState();
|
||||
$("#usersDeleteForm").submit();
|
||||
});
|
||||
|
||||
var table = $('#dataTables').DataTable({
|
||||
language: {
|
||||
url: "core/vendor/datatables/french.json"
|
||||
},
|
||||
locale: 'fr',
|
||||
"columnDefs": [
|
||||
{
|
||||
target: 0,
|
||||
orderable: false,
|
||||
searchable: false,
|
||||
}
|
||||
]
|
||||
});
|
||||
|
||||
// Handle checkbox change event
|
||||
$('.checkboxSelect').on('change', function () {
|
||||
// Save checkbox state to cookies or local storage
|
||||
saveCheckboxState();
|
||||
});
|
||||
|
||||
// Handle checkbox state on DataTables draw event
|
||||
table.on('draw', function () {
|
||||
// Restore checkbox state from cookies or local storage
|
||||
restoreCheckboxState();
|
||||
});
|
||||
|
||||
// Empty local storage after submit
|
||||
$("#usersDeleteSubmit").on("click", function () {
|
||||
localStorage.setItem('checkboxState', JSON.stringify({}));
|
||||
});
|
||||
|
||||
// Restore checkbox state on page load
|
||||
restoreCheckboxState();
|
||||
|
||||
function saveCheckboxState() {
|
||||
|
||||
// Récupérer d'abord les données existantes dans le localStorage
|
||||
var existingData = JSON.parse(localStorage.getItem('checkboxState')) || {};
|
||||
|
||||
// Ajouter ou mettre à jour les données actuelles
|
||||
$('.checkboxSelect').each(function () {
|
||||
var checkboxId = $(this).attr('id');
|
||||
var checked = $(this).prop('checked');
|
||||
existingData[checkboxId] = checked;
|
||||
});
|
||||
|
||||
// Sauvegarder les données mises à jour dans le localStorage
|
||||
localStorage.setItem('checkboxState', JSON.stringify(existingData));
|
||||
}
|
||||
|
||||
// Function to restore checkbox state
|
||||
function restoreCheckboxState() {
|
||||
var checkboxState = JSON.parse(localStorage.getItem('checkboxState')) || {};
|
||||
// console.log(checkboxState);
|
||||
for (var checkboxId in checkboxState) {
|
||||
if (checkboxState.hasOwnProperty(checkboxId)) {
|
||||
var checked = checkboxState[checkboxId];
|
||||
// Update checkbox state based on stored information
|
||||
$('#' + checkboxId).prop('checked', checked);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}));
|
|
@ -0,0 +1,55 @@
|
|||
<?php echo template::formOpen('usersDeleteForm'); ?>
|
||||
<div class="row">
|
||||
<div class="col1">
|
||||
<?php echo template::button('userDeleteBack', [
|
||||
'class' => 'buttonGrey',
|
||||
'href' => helper::baseUrl() . 'user/' . $this->getUrl(2),
|
||||
'value' => template::ico('left')
|
||||
]); ?>
|
||||
</div>
|
||||
<div class="col1 offset8">
|
||||
<?php echo template::button('usersDeleteSelectAll', [
|
||||
'value' => template::ico('square-check'),
|
||||
'help' => 'Tout sélectionner'
|
||||
]); ?>
|
||||
</div>
|
||||
<div class="col1">
|
||||
<?php echo template::button('usersDeleteSelectNone', [
|
||||
'value' => template::ico('square-check-empty'),
|
||||
'help' => 'Tout désélectionner'
|
||||
]); ?>
|
||||
</div>
|
||||
<div class="col1">
|
||||
<?php echo template::submit('usersDeleteSubmit', [
|
||||
'class' => 'buttonRed',
|
||||
'ico' => '',
|
||||
'value' => template::ico('minus'),
|
||||
]); ?>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row" id="Bfrtip">
|
||||
<div class="col3">
|
||||
<?php echo template::select('usersFilterGroup', $module::$usersGroups, [
|
||||
'label' => 'Groupes / Profils',
|
||||
'selected' => isset($_POST['usersFilterGroup']) ? $_POST['usersFilterGroup'] : 'all',
|
||||
]); ?>
|
||||
</div>
|
||||
<div class="col3">
|
||||
<?php echo template::select('usersFilterFirstName', $module::$alphabet, [
|
||||
'label' => 'Prénom commence par',
|
||||
'selected' => isset($_POST['usersFilterFirstName']) ? $_POST['usersFilterFirstName'] : 'all',
|
||||
]); ?>
|
||||
</div>
|
||||
<div class="col3">
|
||||
<?php echo template::select('usersFilterLastName', $module::$alphabet, [
|
||||
'label' => 'Nom commence par',
|
||||
'selected' => isset($_POST['usersFilterLastName']) ? $_POST['usersFilterLastName'] : 'all',
|
||||
]); ?>
|
||||
</div>
|
||||
</div>
|
||||
<?php if ($module::$users): ?>
|
||||
<?php echo template::table([1, 2, 3, 3, 3], $module::$users, ['', 'Id', 'Prénom', 'Nom', 'Étiquettes'], ['id' => 'dataTables']); ?>
|
||||
<?php else: ?>
|
||||
<?php echo template::speech('Aucun inscrit'); ?>
|
||||
<?php endif; ?>
|
||||
<?php echo template::formClose(); ?>
|
|
@ -0,0 +1,71 @@
|
|||
/**
|
||||
* This plug-in for DataTables represents the ultimate option in extensibility
|
||||
* for sorting date / time strings correctly. It uses
|
||||
* [Moment.js](http://momentjs.com) to create automatic type detection and
|
||||
* sorting plug-ins for DataTables based on a given format. This way, DataTables
|
||||
* will automatically detect your temporal information and sort it correctly.
|
||||
*
|
||||
* For usage instructions, please see the DataTables blog
|
||||
* post that [introduces it](//datatables.net/blog/2014-12-18).
|
||||
*
|
||||
* @name Ultimate Date / Time sorting
|
||||
* @summary Sort date and time in any format using Moment.js
|
||||
* @author [Allan Jardine](//datatables.net)
|
||||
* @depends DataTables 1.10+, Moment.js 1.7+
|
||||
* @deprecated
|
||||
*
|
||||
* @example
|
||||
* $.fn.dataTable.moment( 'HH:mm MMM D, YY' );
|
||||
* $.fn.dataTable.moment( 'dddd, MMMM Do, YYYY' );
|
||||
*
|
||||
* $('#example').DataTable();
|
||||
*/
|
||||
|
||||
(function (factory) {
|
||||
if (typeof define === "function" && define.amd) {
|
||||
define(["jquery", "moment", "datatables.net"], factory);
|
||||
} else {
|
||||
factory(jQuery, moment);
|
||||
}
|
||||
}(function ($, moment) {
|
||||
|
||||
function strip (d) {
|
||||
if ( typeof d === 'string' ) {
|
||||
// Strip HTML tags and newline characters if possible
|
||||
d = d.replace(/(<.*?>)|(\r?\n|\r)/g, '');
|
||||
|
||||
// Strip out surrounding white space
|
||||
d = d.trim();
|
||||
}
|
||||
|
||||
return d;
|
||||
}
|
||||
|
||||
$.fn.dataTable.moment = function ( format, locale, reverseEmpties ) {
|
||||
var types = $.fn.dataTable.ext.type;
|
||||
|
||||
// Add type detection
|
||||
types.detect.unshift( function ( d ) {
|
||||
d = strip(d);
|
||||
|
||||
// Null and empty values are acceptable
|
||||
if ( d === '' || d === null ) {
|
||||
return 'moment-'+format;
|
||||
}
|
||||
|
||||
return moment( d, format, locale, true ).isValid() ?
|
||||
'moment-'+format :
|
||||
null;
|
||||
} );
|
||||
|
||||
// Add sorting method - use an integer for the sorting
|
||||
types.order[ 'moment-'+format+'-pre' ] = function ( d ) {
|
||||
d = strip(d);
|
||||
|
||||
return !moment(d, format, locale, true).isValid() ?
|
||||
(reverseEmpties ? -Infinity : Infinity) :
|
||||
parseInt( moment( d, format, locale, true ).format( 'x' ), 10 );
|
||||
};
|
||||
};
|
||||
|
||||
}));
|
|
@ -1,4 +1,6 @@
|
|||
[
|
||||
"datatables.min.js",
|
||||
"moment.min.js",
|
||||
"datetime.min.js",
|
||||
"datatables.min.css"
|
||||
]
|
File diff suppressed because one or more lines are too long
|
@ -52,33 +52,39 @@ if (!is_null($u) && !is_null($g) && !is_null($userId)) {
|
|||
case 1:
|
||||
// Accès contrôlés par le profil
|
||||
$profil = $u['user'][$userId]['profil'];
|
||||
if ($g['profil'][$group][$profil]['filemanager'] === false)
|
||||
exit('Accès interdit');
|
||||
// lecture du profil
|
||||
if (!is_null($profil)) {
|
||||
$file = $g['profil'][$group][$profil]['file'];
|
||||
$folder = $g['profil'][$group][$profil]['folder'];
|
||||
$uploadDir = './site/file/source/';
|
||||
// Pointe vers le dossier du cours
|
||||
if (
|
||||
isset($courseId)
|
||||
&& $courseId != 'home'
|
||||
&& $g['profil'][$group][$profil]['folder']['path'] === ''
|
||||
) {
|
||||
$uploadDir = './site/file/source/' . $courseId . '/';
|
||||
} else {
|
||||
$uploadDir = $g['profil'][$group][$profil]['folder']['path'];
|
||||
}
|
||||
|
||||
$currentPath = '../../../' . $uploadDir;
|
||||
if (!is_dir($currentPath)) {
|
||||
mkdir($currentPath);
|
||||
}
|
||||
break;
|
||||
$file = $g['profil'][$group][$profil]['file'];
|
||||
$folder = $g['profil'][$group][$profil]['folder'];
|
||||
// membre sans profil déclaré ou accès interdit, pas d'accès
|
||||
if (
|
||||
is_null($profil)
|
||||
|| $g['profil'][$group][$profil]['filemanager'] === false
|
||||
) {
|
||||
exit("<h1 style='color: red'>Accès interdit au gestionnaire de fichiers !</h1>");
|
||||
}
|
||||
|
||||
// Détermine la variable du dossier partagé dans le profil
|
||||
$sharedPathKey = ($courseId === 'home') ? 'homePath' : 'coursePath';
|
||||
$sharedPath = isset($folder[$sharedPathKey]) ? $folder[$sharedPathKey] : 'none';
|
||||
// Interdit un accès non partagé
|
||||
if (
|
||||
$folder[$sharedPathKey] === 'none'
|
||||
) {
|
||||
exit("<h1 style='color: red'>Accès interdit au gestionnaire de fichiers !</h1>");
|
||||
}
|
||||
|
||||
// Un dossier renvoie vers le dossier confiné
|
||||
$uploadDir = $sharedPath === '' ? '/site/file/source/' . $courseId . '/' : $sharedPath;
|
||||
$currentPath = '../../../' . $uploadDir;
|
||||
|
||||
// Affiche un message d'erreur du le dossier partagé a été supprimé.
|
||||
if (is_dir($currentPath) == false) {
|
||||
exit("<h1 style='color: red'>Le dossier partagé est inexistant, contactez l'administrateur.</h1>");
|
||||
}
|
||||
|
||||
break;
|
||||
default:
|
||||
// Pas d'autorisation d'accès au gestionnaire de fichiers
|
||||
exit('Accès interdit');
|
||||
exit("<h1 style='color: red'>Accès interdit au gestionnaire de fichiers !</h1>");
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -133,77 +139,77 @@ define('DEBUG_ERROR_MESSAGE', false); // TRUE or FALSE
|
|||
$config = array(
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| DON'T TOUCH (base url (only domain) of site).
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| without final / (DON'T TOUCH)
|
||||
|
|
||||
*/
|
||||
|--------------------------------------------------------------------------
|
||||
| DON'T TOUCH (base url (only domain) of site).
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| without final / (DON'T TOUCH)
|
||||
|
|
||||
*/
|
||||
'base_url' => ((isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] && !in_array(strtolower($_SERVER['HTTPS']), array('off', 'no'))) ? 'https' : 'http') . '://' . $_SERVER['HTTP_HOST'] . rtrim(str_replace('/core/vendor/filemanager', '', pathinfo($_SERVER['PHP_SELF'])['dirname']), ' /'),
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| path from base_url to base of upload folder
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| with start and final /
|
||||
|
|
||||
*/
|
||||
|--------------------------------------------------------------------------
|
||||
| path from base_url to base of upload folder
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| with start and final /
|
||||
|
|
||||
*/
|
||||
'upload_dir' => $uploadDir,
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| relative path from filemanager folder to upload folder
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| with final /
|
||||
|
|
||||
*/
|
||||
|--------------------------------------------------------------------------
|
||||
| relative path from filemanager folder to upload folder
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| with final /
|
||||
|
|
||||
*/
|
||||
'current_path' => $currentPath,
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| relative path from filemanager folder to thumbs folder
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| with final /
|
||||
| DO NOT put inside upload folder
|
||||
|
|
||||
*/
|
||||
|--------------------------------------------------------------------------
|
||||
| relative path from filemanager folder to thumbs folder
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| with final /
|
||||
| DO NOT put inside upload folder
|
||||
|
|
||||
*/
|
||||
'thumbs_base_path' => '../../../site/file/thumb/',
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| path from base_url to base of thumbs folder
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| with final /
|
||||
| DO NOT put inside upload folder
|
||||
|
|
||||
*/
|
||||
|--------------------------------------------------------------------------
|
||||
| path from base_url to base of thumbs folder
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| with final /
|
||||
| DO NOT put inside upload folder
|
||||
|
|
||||
*/
|
||||
'thumbs_upload_dir' => '/thumb/',
|
||||
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| mime file control to define files extensions
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| If you want to be forced to assign the extension starting from the mime type
|
||||
|
|
||||
*/
|
||||
|--------------------------------------------------------------------------
|
||||
| mime file control to define files extensions
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| If you want to be forced to assign the extension starting from the mime type
|
||||
|
|
||||
*/
|
||||
'mime_extension_rename' => false,
|
||||
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| FTP configuration BETA VERSION
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| If you want enable ftp use write these parametres otherwise leave empty
|
||||
| Remember to set base_url properly to point in the ftp server domain and
|
||||
| upload dir will be ftp_base_folder + upload_dir so without final /
|
||||
|
|
||||
*/
|
||||
|--------------------------------------------------------------------------
|
||||
| FTP configuration BETA VERSION
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| If you want enable ftp use write these parametres otherwise leave empty
|
||||
| Remember to set base_url properly to point in the ftp server domain and
|
||||
| upload dir will be ftp_base_folder + upload_dir so without final /
|
||||
|
|
||||
*/
|
||||
'ftp_host' => false,
|
||||
//put the FTP host
|
||||
'ftp_user' => "user",
|
||||
|
@ -213,52 +219,52 @@ $config = array(
|
|||
// Directory where place files before to send to FTP with final /
|
||||
'ftp_temp_folder' => "../temp/",
|
||||
/*
|
||||
|---------------------------------------------------------------------------
|
||||
| path from ftp_base_folder to base of thumbs folder with start and final /
|
||||
|---------------------------------------------------------------------------
|
||||
*/
|
||||
|---------------------------------------------------------------------------
|
||||
| path from ftp_base_folder to base of thumbs folder with start and final /
|
||||
|---------------------------------------------------------------------------
|
||||
*/
|
||||
'ftp_thumbs_dir' => '/thumbs/',
|
||||
'ftp_ssl' => false,
|
||||
'ftp_port' => 21,
|
||||
|
||||
/* EXAMPLE
|
||||
'ftp_host' => "host.com",
|
||||
'ftp_user' => "test@host.com",
|
||||
'ftp_pass' => "pass.1",
|
||||
'ftp_base_folder' => "",
|
||||
'ftp_base_url' => "http://host.com/testFTP",
|
||||
*/
|
||||
'ftp_host' => "host.com",
|
||||
'ftp_user' => "test@host.com",
|
||||
'ftp_pass' => "pass.1",
|
||||
'ftp_base_folder' => "",
|
||||
'ftp_base_url' => "http://host.com/testFTP",
|
||||
*/
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Multiple files selection
|
||||
|--------------------------------------------------------------------------
|
||||
| The user can delete multiple files, select all files , deselect all files
|
||||
*/
|
||||
|--------------------------------------------------------------------------
|
||||
| Multiple files selection
|
||||
|--------------------------------------------------------------------------
|
||||
| The user can delete multiple files, select all files , deselect all files
|
||||
*/
|
||||
'multiple_selection' => true,
|
||||
/*
|
||||
|
|
||||
| The user can have a select button that pass a json to external input or pass the first file selected to editor
|
||||
| If you use responsivefilemanager tinymce extension can copy into editor multiple object like images, videos, audios, links in the same time
|
||||
|
|
||||
*/
|
||||
|
|
||||
| The user can have a select button that pass a json to external input or pass the first file selected to editor
|
||||
| If you use responsivefilemanager tinymce extension can copy into editor multiple object like images, videos, audios, links in the same time
|
||||
|
|
||||
*/
|
||||
'multiple_selection_action_button' => true,
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Access keys
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| add access keys eg: array('myPrivateKey', 'someoneElseKey');
|
||||
| keys should only containt (a-z A-Z 0-9 \ . _ -) characters
|
||||
| if you are integrating lets say to a cms for admins, i recommend making keys randomized something like this:
|
||||
| $username = 'Admin';
|
||||
| $salt = 'dsflFWR9u2xQa' (a hard coded string)
|
||||
| $akey = md5($username.$salt);
|
||||
| DO NOT use 'key' as access key!
|
||||
| Keys are CASE SENSITIVE!
|
||||
|
|
||||
*/
|
||||
|--------------------------------------------------------------------------
|
||||
| Access keys
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| add access keys eg: array('myPrivateKey', 'someoneElseKey');
|
||||
| keys should only containt (a-z A-Z 0-9 \ . _ -) characters
|
||||
| if you are integrating lets say to a cms for admins, i recommend making keys randomized something like this:
|
||||
| $username = 'Admin';
|
||||
| $salt = 'dsflFWR9u2xQa' (a hard coded string)
|
||||
| $akey = md5($username.$salt);
|
||||
| DO NOT use 'key' as access key!
|
||||
| Keys are CASE SENSITIVE!
|
||||
|
|
||||
*/
|
||||
|
||||
'access_keys' => array($privateKey),
|
||||
|
||||
|
@ -267,51 +273,51 @@ $config = array(
|
|||
//--------------------------------------------------------------------------------------------------------
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Maximum size of all files in source folder
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| in Megabytes
|
||||
|
|
||||
*/
|
||||
|--------------------------------------------------------------------------
|
||||
| Maximum size of all files in source folder
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| in Megabytes
|
||||
|
|
||||
*/
|
||||
'MaxSizeTotal' => false,
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Maximum upload size
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| in Megabytes
|
||||
|
|
||||
*/
|
||||
|--------------------------------------------------------------------------
|
||||
| Maximum upload size
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| in Megabytes
|
||||
|
|
||||
*/
|
||||
'MaxSizeUpload' => 20000,
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| File and Folder permission
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
*/
|
||||
'filePermission' => 0755,
|
||||
|--------------------------------------------------------------------------
|
||||
| File and Folder permission
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
*/
|
||||
'filePermission' => 0644,
|
||||
'folderPermission' => 0777,
|
||||
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| default language file name
|
||||
|--------------------------------------------------------------------------
|
||||
*/
|
||||
|--------------------------------------------------------------------------
|
||||
| default language file name
|
||||
|--------------------------------------------------------------------------
|
||||
*/
|
||||
'default_language' => 'fr_FR',
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Icon theme
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| Default available: ico and ico_dark
|
||||
| Can be set to custom icon inside filemanager/img
|
||||
|
|
||||
*/
|
||||
|--------------------------------------------------------------------------
|
||||
| Icon theme
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| Default available: ico and ico_dark
|
||||
| Can be set to custom icon inside filemanager/img
|
||||
|
|
||||
*/
|
||||
'icon_theme' => "ico",
|
||||
|
||||
|
||||
|
@ -349,12 +355,12 @@ $config = array(
|
|||
'image_max_height' => 0,
|
||||
'image_max_mode' => 'auto',
|
||||
/*
|
||||
# $option: 0 / exact = defined size;
|
||||
# 1 / portrait = keep aspect set height;
|
||||
# 2 / landscape = keep aspect set width;
|
||||
# 3 / auto = auto;
|
||||
# 4 / crop= resize and crop;
|
||||
*/
|
||||
# $option: 0 / exact = defined size;
|
||||
# 1 / portrait = keep aspect set height;
|
||||
# 2 / landscape = keep aspect set width;
|
||||
# 3 / auto = auto;
|
||||
# 4 / crop= resize and crop;
|
||||
*/
|
||||
|
||||
//Automatic resizing //
|
||||
// If you set $image_resizing to TRUE the script converts all uploaded images exactly to image_resizing_width x image_resizing_height dimension
|
||||
|
@ -489,13 +495,13 @@ $config = array(
|
|||
'empty_filename' => false,
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| accept files without extension
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| If you want to accept files without extension, remember to add '' extension on allowed extension
|
||||
|
|
||||
*/
|
||||
|--------------------------------------------------------------------------
|
||||
| accept files without extension
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| If you want to accept files without extension, remember to add '' extension on allowed extension
|
||||
|
|
||||
*/
|
||||
'files_without_extension' => false,
|
||||
|
||||
/******************
|
||||
|
@ -616,12 +622,12 @@ $config = array(
|
|||
'fixed_image_creation_height' => array(480),
|
||||
//height of image
|
||||
/*
|
||||
# $option: 0 / exact = defined size;
|
||||
# 1 / portrait = keep aspect set height;
|
||||
# 2 / landscape = keep aspect set width;
|
||||
# 3 / auto = auto;
|
||||
# 4 / crop= resize and crop;
|
||||
*/
|
||||
# $option: 0 / exact = defined size;
|
||||
# 1 / portrait = keep aspect set height;
|
||||
# 2 / landscape = keep aspect set width;
|
||||
# 3 / auto = auto;
|
||||
# 4 / crop= resize and crop;
|
||||
*/
|
||||
'fixed_image_creation_option' => array('auto', 'crop'),
|
||||
//set the type of the crop
|
||||
|
||||
|
@ -644,12 +650,12 @@ $config = array(
|
|||
'relative_image_creation_height' => array(200, 300),
|
||||
//height of image
|
||||
/*
|
||||
# $option: 0 / exact = defined size;
|
||||
# 1 / portrait = keep aspect set height;
|
||||
# 2 / landscape = keep aspect set width;
|
||||
# 3 / auto = auto;
|
||||
# 4 / crop= resize and crop;
|
||||
*/
|
||||
# $option: 0 / exact = defined size;
|
||||
# 1 / portrait = keep aspect set height;
|
||||
# 2 / landscape = keep aspect set width;
|
||||
# 3 / auto = auto;
|
||||
# 4 / crop= resize and crop;
|
||||
*/
|
||||
'relative_image_creation_option' => array('crop', 'crop'),
|
||||
//set the type of the crop
|
||||
|
||||
|
|
|
@ -864,50 +864,54 @@ if ($config['upload_files']) { ?>
|
|||
|
||||
switch ($sort_by) {
|
||||
case 'date':
|
||||
//usort($sorted, 'dateSort');
|
||||
usort($sorted, function($x, $y) use ($descending) {
|
||||
if ($x['is_dir'] !== $y['is_dir']) {
|
||||
return $y['is_dir'] ? 1 : -1;
|
||||
} else {
|
||||
return ($descending)
|
||||
? $x['size'] < $y['size']
|
||||
: $x['size'] >= $y['size'];
|
||||
if ($descending) {
|
||||
return ($x['size'] < $y['size']) ? -1 : ($x['size'] > $y['size'] ? 1 : 0);
|
||||
} else {
|
||||
return ($x['size'] > $y['size']) ? -1 : ($x['size'] < $y['size'] ? 1 : 0);
|
||||
}
|
||||
}
|
||||
});
|
||||
break;
|
||||
case 'size':
|
||||
//usort($sorted, 'sizeSort');
|
||||
usort($sorted, function($x, $y) use ($descending) {
|
||||
if ($x['is_dir'] !== $y['is_dir']) {
|
||||
return $y['is_dir'] ? 1 : -1;
|
||||
} else {
|
||||
return ($descending)
|
||||
? $x['date'] < $y['date']
|
||||
: $x['date'] >= $y['date'];
|
||||
if ($descending) {
|
||||
return ($x['date'] < $y['date']) ? -1 : ($x['date'] > $y['date'] ? 1 : 0);
|
||||
} else {
|
||||
return ($x['date'] > $y['date']) ? -1 : ($x['date'] < $y['date'] ? 1 : 0);
|
||||
}
|
||||
}
|
||||
});
|
||||
break;
|
||||
case 'extension':
|
||||
//usort($sorted, 'extensionSort');
|
||||
usort($sorted, function($x, $y) use ($descending) {
|
||||
if ($x['is_dir'] !== $y['is_dir']) {
|
||||
return $y['is_dir'] ? 1 : -1;
|
||||
} else {
|
||||
return ($descending)
|
||||
? ($x['extension'] < $y['extension'] ? 1 : 0)
|
||||
: ($x['extension'] >= $y['extension'] ? 1 : 0);
|
||||
if ($descending) {
|
||||
return strcasecmp($x['extension'], $y['extension']);
|
||||
} else {
|
||||
return -strcasecmp($x['extension'], $y['extension']);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
break;
|
||||
default:
|
||||
// usort($sorted, 'filenameSort');
|
||||
usort($sorted, function($x, $y) use ($descending) {
|
||||
if ($x['is_dir'] !== $y['is_dir']) {
|
||||
return $y['is_dir'] ? 1 : -1;
|
||||
} else {
|
||||
return ($descending)
|
||||
? ($x['file_lcase'] < $y['file_lcase'] ? 1 : ($x['file_lcase'] == $y['file_lcase'] ? 0 : -1))
|
||||
: ($x['file_lcase'] >= $y['file_lcase'] ? 1 : ($x['file_lcase'] == $y['file_lcase'] ? 0 : -1));
|
||||
if ($descending) {
|
||||
return strcasecmp($x['file_lcase'], $y['file_lcase']);
|
||||
} else {
|
||||
return -strcasecmp($x['file_lcase'], $y['file_lcase']);
|
||||
}
|
||||
}
|
||||
});
|
||||
break;
|
||||
|
|
|
@ -1,8 +0,0 @@
|
|||
/**
|
||||
* Copyright (c) 2018, Travis Clarke (https://www.travismclarke.com/)
|
||||
*
|
||||
* This source code is licensed under the Apache-2.0 license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
!function(e,t){"object"==typeof exports&&"undefined"!=typeof module?module.exports=t(require("jquery")):"function"==typeof define&&define.amd?define(["jquery"],t):e.ImageMap=t(e.$)}(this,function(e){"use strict";function t(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}function n(e,t){for(var n=0;n<t.length;n++){var r=t[n];r.enumerable=r.enumerable||!1,r.configurable=!0,"value"in r&&(r.writable=!0),Object.defineProperty(e,r.key,r)}}function r(e,t,r){return t&&n(e.prototype,t),r&&n(e,r),e}function o(e){return i(e)||a(e)||u()}function i(e){if(Array.isArray(e)){for(var t=0,n=Array(e.length);t<e.length;t++)n[t]=e[t];return n}}function a(e){if(Symbol.iterator in Object(e)||"[object Arguments]"===Object.prototype.toString.call(e))return Array.from(e)}function u(){throw new TypeError("Invalid attempt to spread non-iterable instance")}function c(e,t){return new s(e,t)}e=e&&e.hasOwnProperty("default")?e.default:e;var d="resize",f="load",l="complete",s=function(){function e(n,r){t(this,e),this.selector=n instanceof Array?n:o(document.querySelectorAll(n)),document.readyState!==l?window.addEventListener(f,this.update.bind(this)):this.update(),window.addEventListener(d,this.debounce(this.update,r).bind(this))}return r(e,[{key:"update",value:function(){var e=this;this.selector.forEach(function(t){if(void 0!==t.getAttribute("usemap")){t.cloneNode().addEventListener(f,e.handleImageLoad(t.offsetWidth,t.offsetHeight))}})}},{key:"debounce",value:function(e){var t,n=this,r=arguments.length>1&&void 0!==arguments[1]?arguments[1]:500;return function(){for(var o=arguments.length,i=Array(o),a=0;a<o;a++)i[a]=arguments[a];window.clearTimeout(t),t=window.setTimeout(function(t){return e.apply(t,i)},r,n)}}},{key:"handleImageLoad",value:function(){var t=arguments.length>0&&void 0!==arguments[0]?arguments[0]:0,n=arguments.length>1&&void 0!==arguments[1]?arguments[1]:0;return function(r){var i=r.target.width,a=r.target.height,u=t/100,c=n/100,d=r.target.getAttribute("usemap").replace(/^#/,"")
|
||||
;o(document.querySelectorAll(e.genAreaSelector(d))).forEach(function(e){var t=e.dataset.coords=e.dataset.coords||e.getAttribute("coords"),n=t.split(",");e.setAttribute("coords",""+n.map(function(e,t){return t%2==0?+(n[t]/i*100*u):+(n[t]/a*100*c)}))})}}}],[{key:"genAreaSelector",value:function(e){return'map[name="'.concat(e,'"] area')}}]),e}();return void 0!==e&&e.fn&&(e.fn.imageMap=function(e){return new s(this.toArray(),e)}),c.VERSION="1.1.5",c});
|
|
@ -1,4 +0,0 @@
|
|||
[
|
||||
"image-map.min.js",
|
||||
"init.js"
|
||||
]
|
|
@ -1,6 +0,0 @@
|
|||
/**
|
||||
* Initialisation du redimensionner de mapf
|
||||
*/
|
||||
$(function() {
|
||||
$('img[usemap]').imageMap();
|
||||
});
|
|
@ -1,2 +0,0 @@
|
|||
Article https://blog.travismclarke.com/project/imagemap/
|
||||
Générateur : https://www.image-map.net/
|
|
@ -0,0 +1,271 @@
|
|||
# Using distributed files
|
||||
|
||||
All plotly.js bundles inject an object `Plotly` into the global scope.
|
||||
|
||||
Import plotly.js as:
|
||||
|
||||
```html
|
||||
<script src="plotly.min.js"></script>
|
||||
```
|
||||
|
||||
or the un-minified version as:
|
||||
|
||||
```html
|
||||
<script src="plotly.js" charset="utf-8"></script>
|
||||
```
|
||||
|
||||
### To include localization
|
||||
|
||||
Plotly.js defaults to US English (en-US) and includes British English (en) in the standard bundle.
|
||||
Many other localizations are available - here is an example using Swiss-German (de-CH),
|
||||
see the contents of this directory for the full list.
|
||||
Note that the file names are all lowercase, even though the region is uppercase when you apply a locale.
|
||||
|
||||
*After* the plotly.js script tag, add:
|
||||
|
||||
```html
|
||||
<script src="plotly-locale-de-ch.js"></script>
|
||||
<script>Plotly.setPlotConfig({locale: 'de-CH'})</script>
|
||||
```
|
||||
|
||||
The first line loads and registers the locale definition with plotly.js, the second sets it as the default for all Plotly plots.
|
||||
You can also include multiple locale definitions and apply them to each plot separately as a `config` parameter:
|
||||
|
||||
```js
|
||||
Plotly.newPlot(graphDiv, data, layout, {locale: 'de-CH'})
|
||||
```
|
||||
|
||||
# Bundle information
|
||||
|
||||
The main plotly.js bundle includes all trace modules.
|
||||
|
||||
The main plotly.js bundles weight in at:
|
||||
|
||||
| plotly.js | plotly.min.js | plotly.min.js + gzip | plotly-with-meta.js |
|
||||
|-----------|---------------|----------------------|---------------------|
|
||||
| 8.2 MB | 3.5 MB | 1 MB | 8.5 MB |
|
||||
|
||||
#### CDN links
|
||||
> https://cdn.plot.ly/plotly-2.29.0.js
|
||||
|
||||
> https://cdn.plot.ly/plotly-2.29.0.min.js
|
||||
|
||||
|
||||
#### npm packages
|
||||
> [plotly.js](https://www.npmjs.com/package/plotly.js)
|
||||
|
||||
> [plotly.js-dist](https://www.npmjs.com/package/plotly.js-dist)
|
||||
|
||||
> [plotly.js-dist-min](https://www.npmjs.com/package/plotly.js-dist-min)
|
||||
|
||||
#### Meta information
|
||||
> If you would like to have access to the attribute meta information (including attribute descriptions as on the [schema reference page](https://plotly.com/javascript/reference/)), use dist file `dist/plotly-with-meta.js`
|
||||
---
|
||||
|
||||
## Partial bundles
|
||||
|
||||
plotly.js also ships with several _partial_ bundles:
|
||||
|
||||
- [basic](#plotlyjs-basic)
|
||||
- [cartesian](#plotlyjs-cartesian)
|
||||
- [geo](#plotlyjs-geo)
|
||||
- [gl3d](#plotlyjs-gl3d)
|
||||
- [gl2d](#plotlyjs-gl2d)
|
||||
- [mapbox](#plotlyjs-mapbox)
|
||||
- [finance](#plotlyjs-finance)
|
||||
- [strict](#plotlyjs-strict)
|
||||
|
||||
> Each plotly.js partial bundle has a corresponding npm package with no dependencies.
|
||||
|
||||
> The minified version of each partial bundle is also published to npm in a separate "dist-min" package.
|
||||
|
||||
> The strict bundle now includes all traces, but the regl-based traces are built differently to avoid function constructors. This results in about a 10% larger bundle size, which is why this method is not used by default. Over time we intend to use the strict bundle to work on other strict CSP issues such as inline CSS.
|
||||
|
||||
---
|
||||
|
||||
### plotly.js basic
|
||||
|
||||
The `basic` partial bundle contains trace modules `bar`, `pie` and `scatter`.
|
||||
|
||||
#### Stats
|
||||
|
||||
| Raw size | Minified size | Minified + gzip size |
|
||||
|------|-----------------|------------------------|
|
||||
| 2.6 MB | 984.6 kB | 329.6 kB |
|
||||
|
||||
#### CDN links
|
||||
> https://cdn.plot.ly/plotly-basic-2.29.0.js
|
||||
|
||||
> https://cdn.plot.ly/plotly-basic-2.29.0.min.js
|
||||
|
||||
|
||||
#### npm packages
|
||||
> [plotly.js-basic-dist](https://www.npmjs.com/package/plotly.js-basic-dist)
|
||||
|
||||
> [plotly.js-basic-dist-min](https://www.npmjs.com/package/plotly.js-basic-dist-min)
|
||||
|
||||
---
|
||||
|
||||
### plotly.js cartesian
|
||||
|
||||
The `cartesian` partial bundle contains trace modules `bar`, `box`, `contour`, `heatmap`, `histogram`, `histogram2d`, `histogram2dcontour`, `image`, `pie`, `scatter`, `scatterternary` and `violin`.
|
||||
|
||||
#### Stats
|
||||
|
||||
| Raw size | Minified size | Minified + gzip size |
|
||||
|------|-----------------|------------------------|
|
||||
| 3.3 MB | 1.2 MB | 417 kB |
|
||||
|
||||
#### CDN links
|
||||
> https://cdn.plot.ly/plotly-cartesian-2.29.0.js
|
||||
|
||||
> https://cdn.plot.ly/plotly-cartesian-2.29.0.min.js
|
||||
|
||||
|
||||
#### npm packages
|
||||
> [plotly.js-cartesian-dist](https://www.npmjs.com/package/plotly.js-cartesian-dist)
|
||||
|
||||
> [plotly.js-cartesian-dist-min](https://www.npmjs.com/package/plotly.js-cartesian-dist-min)
|
||||
|
||||
---
|
||||
|
||||
### plotly.js geo
|
||||
|
||||
The `geo` partial bundle contains trace modules `choropleth`, `scatter` and `scattergeo`.
|
||||
|
||||
#### Stats
|
||||
|
||||
| Raw size | Minified size | Minified + gzip size |
|
||||
|------|-----------------|------------------------|
|
||||
| 3.1 MB | 1.1 MB | 372.3 kB |
|
||||
|
||||
#### CDN links
|
||||
> https://cdn.plot.ly/plotly-geo-2.29.0.js
|
||||
|
||||
> https://cdn.plot.ly/plotly-geo-2.29.0.min.js
|
||||
|
||||
|
||||
#### npm packages
|
||||
> [plotly.js-geo-dist](https://www.npmjs.com/package/plotly.js-geo-dist)
|
||||
|
||||
> [plotly.js-geo-dist-min](https://www.npmjs.com/package/plotly.js-geo-dist-min)
|
||||
|
||||
---
|
||||
|
||||
### plotly.js gl3d
|
||||
|
||||
The `gl3d` partial bundle contains trace modules `cone`, `isosurface`, `mesh3d`, `scatter`, `scatter3d`, `streamtube`, `surface` and `volume`.
|
||||
|
||||
#### Stats
|
||||
|
||||
| Raw size | Minified size | Minified + gzip size |
|
||||
|------|-----------------|------------------------|
|
||||
| 3.6 MB | 1.5 MB | 493.1 kB |
|
||||
|
||||
#### CDN links
|
||||
> https://cdn.plot.ly/plotly-gl3d-2.29.0.js
|
||||
|
||||
> https://cdn.plot.ly/plotly-gl3d-2.29.0.min.js
|
||||
|
||||
|
||||
#### npm packages
|
||||
> [plotly.js-gl3d-dist](https://www.npmjs.com/package/plotly.js-gl3d-dist)
|
||||
|
||||
> [plotly.js-gl3d-dist-min](https://www.npmjs.com/package/plotly.js-gl3d-dist-min)
|
||||
|
||||
---
|
||||
|
||||
### plotly.js gl2d
|
||||
|
||||
The `gl2d` partial bundle contains trace modules `heatmapgl`, `parcoords`, `pointcloud`, `scatter`, `scattergl` and `splom`.
|
||||
|
||||
#### Stats
|
||||
|
||||
| Raw size | Minified size | Minified + gzip size |
|
||||
|------|-----------------|------------------------|
|
||||
| 4.4 MB | 1.9 MB | 599.6 kB |
|
||||
|
||||
#### CDN links
|
||||
> https://cdn.plot.ly/plotly-gl2d-2.29.0.js
|
||||
|
||||
> https://cdn.plot.ly/plotly-gl2d-2.29.0.min.js
|
||||
|
||||
|
||||
#### npm packages
|
||||
> [plotly.js-gl2d-dist](https://www.npmjs.com/package/plotly.js-gl2d-dist)
|
||||
|
||||
> [plotly.js-gl2d-dist-min](https://www.npmjs.com/package/plotly.js-gl2d-dist-min)
|
||||
|
||||
---
|
||||
|
||||
### plotly.js mapbox
|
||||
|
||||
The `mapbox` partial bundle contains trace modules `choroplethmapbox`, `densitymapbox`, `scatter` and `scattermapbox`.
|
||||
|
||||
#### Stats
|
||||
|
||||
| Raw size | Minified size | Minified + gzip size |
|
||||
|------|-----------------|------------------------|
|
||||
| 4.4 MB | 1.7 MB | 531.2 kB |
|
||||
|
||||
#### CDN links
|
||||
> https://cdn.plot.ly/plotly-mapbox-2.29.0.js
|
||||
|
||||
> https://cdn.plot.ly/plotly-mapbox-2.29.0.min.js
|
||||
|
||||
|
||||
#### npm packages
|
||||
> [plotly.js-mapbox-dist](https://www.npmjs.com/package/plotly.js-mapbox-dist)
|
||||
|
||||
> [plotly.js-mapbox-dist-min](https://www.npmjs.com/package/plotly.js-mapbox-dist-min)
|
||||
|
||||
---
|
||||
|
||||
### plotly.js finance
|
||||
|
||||
The `finance` partial bundle contains trace modules `bar`, `candlestick`, `funnel`, `funnelarea`, `histogram`, `indicator`, `ohlc`, `pie`, `scatter` and `waterfall`.
|
||||
|
||||
#### Stats
|
||||
|
||||
| Raw size | Minified size | Minified + gzip size |
|
||||
|------|-----------------|------------------------|
|
||||
| 2.8 MB | 1 MB | 358.7 kB |
|
||||
|
||||
#### CDN links
|
||||
> https://cdn.plot.ly/plotly-finance-2.29.0.js
|
||||
|
||||
> https://cdn.plot.ly/plotly-finance-2.29.0.min.js
|
||||
|
||||
|
||||
#### npm packages
|
||||
> [plotly.js-finance-dist](https://www.npmjs.com/package/plotly.js-finance-dist)
|
||||
|
||||
> [plotly.js-finance-dist-min](https://www.npmjs.com/package/plotly.js-finance-dist-min)
|
||||
|
||||
---
|
||||
|
||||
### plotly.js strict
|
||||
|
||||
The `strict` partial bundle contains trace modules `bar`, `barpolar`, `box`, `candlestick`, `carpet`, `choropleth`, `choroplethmapbox`, `cone`, `contour`, `contourcarpet`, `densitymapbox`, `funnel`, `funnelarea`, `heatmap`, `heatmapgl`, `histogram`, `histogram2d`, `histogram2dcontour`, `icicle`, `image`, `indicator`, `isosurface`, `mesh3d`, `ohlc`, `parcats`, `parcoords`, `pie`, `pointcloud`, `sankey`, `scatter`, `scattergl`, `scatter3d`, `scattercarpet`, `scattergeo`, `scattermapbox`, `scatterpolar`, `scatterpolargl`, `scattersmith`, `scatterternary`, `splom`, `streamtube`, `sunburst`, `surface`, `table`, `treemap`, `violin`, `volume` and `waterfall`.
|
||||
|
||||
#### Stats
|
||||
|
||||
| Raw size | Minified size | Minified + gzip size |
|
||||
|------|-----------------|------------------------|
|
||||
| 8.7 MB | 3.8 MB | 1.1 MB |
|
||||
|
||||
#### CDN links
|
||||
> https://cdn.plot.ly/plotly-strict-2.29.0.js
|
||||
|
||||
> https://cdn.plot.ly/plotly-strict-2.29.0.min.js
|
||||
|
||||
|
||||
#### npm packages
|
||||
> [plotly.js-strict-dist](https://www.npmjs.com/package/plotly.js-strict-dist)
|
||||
|
||||
> [plotly.js-strict-dist-min](https://www.npmjs.com/package/plotly.js-strict-dist-min)
|
||||
|
||||
---
|
||||
|
||||
|
||||
_This file is auto-generated by `npm run stats`. Please do not edit this file directly._
|
|
@ -0,0 +1,4 @@
|
|||
[
|
||||
"plotly.min.js",
|
||||
"plotly-locale-fr-ch.js"
|
||||
]
|
|
@ -0,0 +1 @@
|
|||
var locale={moduleType:"locale",name:"fr-CH",dictionary:{},format:{days:["Dimanche","Lundi","Mardi","Mercredi","Jeudi","Vendredi","Samedi"],shortDays:["Dim","Lun","Mar","Mer","Jeu","Ven","Sam"],months:["Janvier","F\xe9vrier","Mars","Avril","Mai","Juin","Juillet","Ao\xfbt","Septembre","Octobre","Novembre","D\xe9cembre"],shortMonths:["Jan","F\xe9v","Mar","Avr","Mai","Jun","Jul","Ao\xfb","Sep","Oct","Nov","D\xe9c"],date:"%d.%m.%Y"}};"undefined"==typeof Plotly?(window.PlotlyLocales=window.PlotlyLocales||[],window.PlotlyLocales.push(locale)):Plotly.register(locale);
|
File diff suppressed because one or more lines are too long
|
@ -128,10 +128,10 @@ tinymce.init({
|
|||
image_dimensions: true,
|
||||
// Active l'onglet avancé lors de l'ajout d'une image
|
||||
image_advtab: true,
|
||||
// Urls absolues
|
||||
relative_urls: true,
|
||||
// Conversion des URLs
|
||||
convert_urls: false,
|
||||
// Urls relatives
|
||||
relative_urls: true, // Utiliser des URLs relatives
|
||||
remove_script_host: false, // Conserver le script host (domaine)
|
||||
convert_urls: true, // Convertir automatiquement les URLs
|
||||
// Url de base
|
||||
document_base_url: baseUrl,
|
||||
// Gestionnaire de fichiers
|
||||
|
@ -164,6 +164,11 @@ tinymce.init({
|
|||
],*/
|
||||
// Templates
|
||||
templates: [
|
||||
{
|
||||
title: "Bloc de texte",
|
||||
url: baseUrl + "core/vendor/tinymce/templates/block.html",
|
||||
description: "Bloc de texte avec un titre."
|
||||
},
|
||||
{
|
||||
title: "Lien de retour",
|
||||
url: baseUrl + "core/vendor/tinymce/templates/back_home.html",
|
||||
|
@ -174,16 +179,16 @@ tinymce.init({
|
|||
url: baseUrl + "core/vendor/tinymce/templates/unsuscribe.html",
|
||||
description: "Insère un lien de désinscription."
|
||||
},
|
||||
{
|
||||
title: "Bloc de texte",
|
||||
url: baseUrl + "core/vendor/tinymce/templates/block.html",
|
||||
description: "Bloc de texte avec un titre."
|
||||
},
|
||||
{
|
||||
title: "Effet accordéon",
|
||||
url: baseUrl + "core/vendor/tinymce/templates/accordion.html",
|
||||
description: "Bloc de texte avec effet accordéon."
|
||||
},
|
||||
{
|
||||
title: "Effet accordéon DHTML",
|
||||
url: baseUrl + "core/vendor/tinymce/templates/details.html",
|
||||
description: "Bloc de texte avec effet accordéon DHTML (details)."
|
||||
},
|
||||
{
|
||||
title: "Grille symétrique : 6 - 6",
|
||||
url: baseUrl + "core/vendor/tinymce/templates/col6.html",
|
||||
|
@ -331,10 +336,10 @@ tinymce.init({
|
|||
image_dimensions: true,
|
||||
// Active l'onglet avancé lors de l'ajout d'une image
|
||||
image_advtab: true,
|
||||
// Urls absolues
|
||||
relative_urls: true,
|
||||
// Conversion des URLs
|
||||
convert_urls: false,
|
||||
// Urls relatives
|
||||
relative_urls: true, // Utiliser des URLs relatives
|
||||
remove_script_host: false, // Conserver le script host (domaine)
|
||||
convert_urls: true, // Convertir automatiquement les URLs
|
||||
// Url de base
|
||||
document_base_url: baseUrl,
|
||||
max_height: 200,
|
||||
|
|
|
@ -0,0 +1,12 @@
|
|||
<details open>
|
||||
<summary>Premier bloc</summary>
|
||||
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nam interdum, neque non vulputate hendrerit, arcu turpis dapibus nisl, id scelerisque metus lectus vitae nisi. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos. Donec feugiat dolor et turpis finibus condimentum. Cras sit amet ligula sagittis justo.</p>
|
||||
</details>
|
||||
<details>
|
||||
<summary>Second bloc</summary>
|
||||
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nam interdum, neque non vulputate hendrerit, arcu turpis dapibus nisl, id scelerisque metus lectus vitae nisi. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos. Donec feugiat dolor et turpis finibus condimentum. Cras sit amet ligula sagittis justo.</p>
|
||||
</details>
|
||||
<details>
|
||||
<summary>Troisième bloc</summary>
|
||||
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nam interdum, neque non vulputate hendrerit, arcu turpis dapibus nisl, id scelerisque metus lectus vitae nisi. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos. Donec feugiat dolor et turpis finibus condimentum. Cras sit amet ligula sagittis justo.</p>
|
||||
</details>
|
|
@ -1,6 +1,7 @@
|
|||
@charset "UTF-8";
|
||||
|
||||
.zwiico-plus-circled:before { content: '\2191'; } /* '↑' */
|
||||
.zwiico-square-check:before { content: '\e800'; } /* '' */
|
||||
.zwiico-plus:before { content: '\e801'; } /* '' */
|
||||
.zwiico-cancel:before { content: '\e802'; } /* '' */
|
||||
.zwiico-help:before { content: '\e803'; } /* '' */
|
||||
|
@ -48,6 +49,7 @@
|
|||
.zwiico-right-dir:before { content: '\e82d'; } /* '' */
|
||||
.zwiico-chart-line:before { content: '\e82e'; } /* '' */
|
||||
.zwiico-book:before { content: '\e82f'; } /* '' */
|
||||
.zwiico-square-check-empty:before { content: '\e830'; } /* '' */
|
||||
.zwiico-spin:before { content: '\e831'; } /* '' */
|
||||
.zwiico-twitter:before { content: '\f099'; } /* '' */
|
||||
.zwiico-facebook:before { content: '\f09a'; } /* '' */
|
||||
|
|
File diff suppressed because one or more lines are too long
|
@ -1,5 +1,6 @@
|
|||
|
||||
.zwiico-plus-circled { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '↑ '); }
|
||||
.zwiico-square-check { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); }
|
||||
.zwiico-plus { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); }
|
||||
.zwiico-cancel { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); }
|
||||
.zwiico-help { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); }
|
||||
|
@ -47,6 +48,7 @@
|
|||
.zwiico-right-dir { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); }
|
||||
.zwiico-chart-line { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); }
|
||||
.zwiico-book { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); }
|
||||
.zwiico-square-check-empty { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); }
|
||||
.zwiico-spin { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); }
|
||||
.zwiico-twitter { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); }
|
||||
.zwiico-facebook { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); }
|
||||
|
|
|
@ -11,6 +11,7 @@
|
|||
}
|
||||
|
||||
.zwiico-plus-circled { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '↑ '); }
|
||||
.zwiico-square-check { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); }
|
||||
.zwiico-plus { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); }
|
||||
.zwiico-cancel { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); }
|
||||
.zwiico-help { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); }
|
||||
|
@ -58,6 +59,7 @@
|
|||
.zwiico-right-dir { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); }
|
||||
.zwiico-chart-line { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); }
|
||||
.zwiico-book { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); }
|
||||
.zwiico-square-check-empty { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); }
|
||||
.zwiico-spin { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); }
|
||||
.zwiico-twitter { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); }
|
||||
.zwiico-facebook { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); }
|
||||
|
|
|
@ -1,12 +1,12 @@
|
|||
@charset "UTF-8";
|
||||
@font-face {
|
||||
font-family: 'zwiico';
|
||||
src: url('../font/zwiico.eot?8645815');
|
||||
src: url('../font/zwiico.eot?8645815#iefix') format('embedded-opentype'),
|
||||
url('../font/zwiico.woff2?8645815') format('woff2'),
|
||||
url('../font/zwiico.woff?8645815') format('woff'),
|
||||
url('../font/zwiico.ttf?8645815') format('truetype'),
|
||||
url('../font/zwiico.svg?8645815#zwiico') format('svg');
|
||||
src: url('../font/zwiico.eot?58081754');
|
||||
src: url('../font/zwiico.eot?58081754#iefix') format('embedded-opentype'),
|
||||
url('../font/zwiico.woff2?58081754') format('woff2'),
|
||||
url('../font/zwiico.woff?58081754') format('woff'),
|
||||
url('../font/zwiico.ttf?58081754') format('truetype'),
|
||||
url('../font/zwiico.svg?58081754#zwiico') format('svg');
|
||||
font-weight: normal;
|
||||
font-style: normal;
|
||||
}
|
||||
|
@ -16,7 +16,7 @@
|
|||
@media screen and (-webkit-min-device-pixel-ratio:0) {
|
||||
@font-face {
|
||||
font-family: 'zwiico';
|
||||
src: url('../font/zwiico.svg?8645815#zwiico') format('svg');
|
||||
src: url('../font/zwiico.svg?58081754#zwiico') format('svg');
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
@ -56,6 +56,7 @@
|
|||
}
|
||||
|
||||
.zwiico-plus-circled:before { content: '\2191'; } /* '↑' */
|
||||
.zwiico-square-check:before { content: '\e800'; } /* '' */
|
||||
.zwiico-plus:before { content: '\e801'; } /* '' */
|
||||
.zwiico-cancel:before { content: '\e802'; } /* '' */
|
||||
.zwiico-help:before { content: '\e803'; } /* '' */
|
||||
|
@ -103,6 +104,7 @@
|
|||
.zwiico-right-dir:before { content: '\e82d'; } /* '' */
|
||||
.zwiico-chart-line:before { content: '\e82e'; } /* '' */
|
||||
.zwiico-book:before { content: '\e82f'; } /* '' */
|
||||
.zwiico-square-check-empty:before { content: '\e830'; } /* '' */
|
||||
.zwiico-spin:before { content: '\e831'; } /* '' */
|
||||
.zwiico-twitter:before { content: '\f099'; } /* '' */
|
||||
.zwiico-facebook:before { content: '\f09a'; } /* '' */
|
||||
|
|
Binary file not shown.
|
@ -8,6 +8,8 @@
|
|||
<missing-glyph horiz-adv-x="1000" />
|
||||
<glyph glyph-name="plus-circled" unicode="↑" 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="" 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="" 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="" 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" />
|
||||
|
@ -102,6 +104,8 @@
|
|||
|
||||
<glyph glyph-name="book" unicode="" 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="" 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="" 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="" 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: 33 KiB After Width: | Height: | Size: 34 KiB |
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
@ -16,7 +16,7 @@
|
|||
class blog extends common
|
||||
{
|
||||
|
||||
const VERSION = '7.5';
|
||||
const VERSION = '7.9';
|
||||
const REALNAME = 'Blog';
|
||||
const DELETE = true;
|
||||
const UPDATE = '0.0';
|
||||
|
@ -196,9 +196,11 @@ class blog extends common
|
|||
$feeds = new \FeedWriter\RSS2();
|
||||
|
||||
// En-tête
|
||||
$feeds->setTitle($this->getData(['page', $this->getUrl(0), 'title']));
|
||||
$feeds->setTitle($this->getData(['page', $this->getUrl(0), 'title']) ? $this->getData(['page', $this->getUrl(0), 'title']): '');
|
||||
$feeds->setLink(helper::baseUrl() . $this->getUrl(0));
|
||||
$feeds->setDescription($this->getData(['page', $this->getUrl(0), 'metaDescription']));
|
||||
if ($this->getData(['page', $this->getUrl(0), 'metaDescription'])) {
|
||||
$feeds->setDescription($this->getData(['page', $this->getUrl(0), 'metaDescription']));
|
||||
}
|
||||
$feeds->setChannelElement('language', 'fr-FR');
|
||||
$feeds->setDate(date('r', time()));
|
||||
$feeds->addGenerator();
|
||||
|
@ -361,7 +363,7 @@ class blog extends common
|
|||
self::$dateFormat = $this->getData(['module', $this->getUrl(0), 'config', 'dateFormat']);
|
||||
self::$timeFormat = $this->getData(['module', $this->getUrl(0), 'config', 'timeFormat']);
|
||||
self::$comments[] = [
|
||||
helper::dateUTF8(self::$dateFormat, $comment['createdOn']) . ' - ' . helper::dateUTF8(self::$timeFormat, $comment['createdOn']),
|
||||
helper::dateUTF8(self::$dateFormat, $comment['createdOn'], self::$i18nUI) . ' - ' . helper::dateUTF8(self::$timeFormat, $comment['createdOn'], self::$i18nUI),
|
||||
$comment['content'],
|
||||
$comment['userId'] ? $this->getData(['user', $comment['userId'], 'firstname']) . ' ' . $this->getData(['user', $comment['userId'], 'lastname']) : $comment['author'],
|
||||
$buttonApproval,
|
||||
|
@ -530,7 +532,7 @@ class blog extends common
|
|||
'<a href="' . helper::baseurl() . $this->getUrl(0) . '/' . $articleIds[$i] . '" target="_blank" >' .
|
||||
$this->getData(['module', $this->getUrl(0), 'posts', $articleIds[$i], 'title']) .
|
||||
'</a>',
|
||||
helper::dateUTF8(self::$dateFormat, $this->getData(['module', $this->getUrl(0), 'posts', $articleIds[$i], 'publishedOn'])) . ' - ' . helper::dateUTF8(self::$timeFormat, $this->getData(['module', $this->getUrl(0), 'posts', $articleIds[$i], 'publishedOn'])),
|
||||
helper::dateUTF8(self::$dateFormat, $this->getData(['module', $this->getUrl(0), 'posts', $articleIds[$i], 'publishedOn']), self::$i18nUI) . ' - ' . helper::dateUTF8(self::$timeFormat, $this->getData(['module', $this->getUrl(0), 'posts', $articleIds[$i], 'publishedOn']), self::$i18nUI),
|
||||
self::$states[$this->getData(['module', $this->getUrl(0), 'posts', $articleIds[$i], 'state'])],
|
||||
// Bouton pour afficher les commentaires de l'article
|
||||
template::button('blogConfigComment' . $articleIds[$i], [
|
||||
|
|
|
@ -1,3 +1,10 @@
|
|||
|
||||
# Versions 7.8 - 7.9
|
||||
- Le flux RSS ne fonctionne pas si les méta de la page sont vides.
|
||||
# Version 7.7
|
||||
- Contrôle de la variable de session liée au contenu. Evite des erreurs lorsque plusieurs onglets sont ouverts.
|
||||
# Version 7.6
|
||||
- Mise à jour RSS Feed
|
||||
# Version 7.5
|
||||
- Bug paramètre de localisation erroné
|
||||
# Version 7.4
|
||||
|
|
Before Width: | Height: | Size: 652 B After Width: | Height: | Size: 652 B |
|
@ -0,0 +1,74 @@
|
|||
# Change Log
|
||||
All notable changes to this project will be documented in this file.
|
||||
|
||||
The format is based on [Keep a Changelog](http://keepachangelog.com/) .
|
||||
|
||||
## [v1.1.2] - 2023-05-25
|
||||
### Changed
|
||||
- Throw an exception if required feed elements are set with ```NULL``` value. See issue #46.
|
||||
|
||||
## [v1.1.1] - 2016-11-19
|
||||
### Changed
|
||||
- Improved the documentation.
|
||||
- Changed to PSR-4 autoloader in composer.json.
|
||||
|
||||
### Fixed
|
||||
- Item::addElement did not method chain in error conditions.
|
||||
|
||||
## [v1.1.0] - 2016-11-08
|
||||
### Added
|
||||
- Support for multiple element values.
|
||||
- Support for a feed description in ATOM feeds.
|
||||
- Support for ATOM feeds without ```link``` elements.
|
||||
- Support for a feed image in RSS 1.0 and ATOM feeds.
|
||||
|
||||
### Changed
|
||||
- The script does now throw Exceptions instead of stopping the PHP interpreter on error conditions.
|
||||
- The unique identifier for ATOM feeds / entries use the feed / entry title for generating the ID (previously the feed / entry link).
|
||||
- Some URI schemes for ```Item::setId``` were wrongly allowed.
|
||||
- The parameter order of the ```Feed::setImage``` method was changed.
|
||||
|
||||
### Fixed
|
||||
- Fixed slow generation of the feed with huge amounts of feed entries (like 40k entries).
|
||||
- Fixed PHP warning when ```Feed::setChannelAbout``` for RSS 1.0 feeds was not called.
|
||||
- A feed element was generated twice if the element content & attribute value was ```NULL```.
|
||||
- The detection of twice the same link with ```rel=alternate```, ```hreflang``` & ```type``` did not work.
|
||||
|
||||
### Removed
|
||||
- The deprecated method ```Item::setEnclosure``` was removed. Use ```Item::addEnclosure``` instead.
|
||||
|
||||
## [v1.0.4] - 2016-04-17
|
||||
### Changed
|
||||
- The unique identifier for ATOM feed entries is now compliant to the ATOM standard.
|
||||
|
||||
### Fixed
|
||||
- Filter more invalid XML chars.
|
||||
- Fixed a PHP warning displayed if ```Feed::setTitle``` or ```Feed::setLink``` was not called.
|
||||
|
||||
## [v1.0.3] - 2015-11-11
|
||||
### Added
|
||||
- Method for removing tags which were CDATA encoded.
|
||||
|
||||
### Fixed
|
||||
- Fixed error when the filtering of invalid XML chars failed.
|
||||
- Fixed missing docblock documentation.
|
||||
|
||||
## [v1.0.2] - 2015-01-23
|
||||
### Fixed
|
||||
- Fixed a wrong docblock return data type.
|
||||
|
||||
## [v1.0.1] - 2014-09-21
|
||||
### Fixed
|
||||
- Filter invalid XML chars.
|
||||
|
||||
## v1.0 - 2014-09-14
|
||||
|
||||
|
||||
[Unreleased]: https://github.com/mibe/FeedWriter/compare/v1.1.2...HEAD
|
||||
[v1.1.2]: https://github.com/mibe/FeedWriter/compare/v1.1.1...v1.1.2
|
||||
[v1.1.1]: https://github.com/mibe/FeedWriter/compare/v1.1.0...v1.1.1
|
||||
[v1.1.0]: https://github.com/mibe/FeedWriter/compare/v1.0.4...v1.1.0
|
||||
[v1.0.4]: https://github.com/mibe/FeedWriter/compare/v1.0.3...v1.0.4
|
||||
[v1.0.3]: https://github.com/mibe/FeedWriter/compare/v1.0.2...v1.0.3
|
||||
[v1.0.2]: https://github.com/mibe/FeedWriter/compare/v1.0.1...v1.0.2
|
||||
[v1.0.1]: https://github.com/mibe/FeedWriter/compare/v1.0...v1.0.1
|
|
@ -2,10 +2,11 @@
|
|||
namespace FeedWriter;
|
||||
|
||||
use \DateTime;
|
||||
use \DateTimeInterface;
|
||||
|
||||
/*
|
||||
* Copyright (C) 2008 Anis uddin Ahmad <anisniit@gmail.com>
|
||||
* Copyright (C) 2010-2016 Michael Bemmerl <mail@mx-server.de>
|
||||
* Copyright (C) 2010-2016, 2022 Michael Bemmerl <mail@mx-server.de>
|
||||
*
|
||||
* This file is part of the "Universal Feed Writer" project.
|
||||
*
|
||||
|
@ -76,6 +77,13 @@ abstract class Feed
|
|||
*/
|
||||
private $version = null;
|
||||
|
||||
/**
|
||||
* Contains the encoding of this feed.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
private $encoding = 'utf-8';
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
|
@ -87,9 +95,6 @@ abstract class Feed
|
|||
{
|
||||
$this->version = $version;
|
||||
|
||||
// Setting default encoding
|
||||
$this->encoding = 'utf-8';
|
||||
|
||||
// Setting default value for essential channel element
|
||||
$this->setTitle($version . ' Feed');
|
||||
|
||||
|
@ -396,9 +401,13 @@ abstract class Feed
|
|||
* @access public
|
||||
* @param string $title value of 'title' channel tag
|
||||
* @return self
|
||||
* @throws \InvalidArgumentException if the title is empty or NULL.
|
||||
*/
|
||||
public function setTitle($title)
|
||||
{
|
||||
if (empty($title))
|
||||
throw new \InvalidArgumentException('The title may not be empty or NULL.');
|
||||
|
||||
return $this->setChannelElement('title', $title);
|
||||
}
|
||||
|
||||
|
@ -406,15 +415,15 @@ abstract class Feed
|
|||
* Set the date when the feed was lastly updated.
|
||||
*
|
||||
* This adds the 'updated' element to the feed. The value of the date parameter
|
||||
* can be either an instance of the DateTime class, an integer containing a UNIX
|
||||
* can be either a class implementing DateTimeInterface, an integer containing a UNIX
|
||||
* timestamp or a string which is parseable by PHP's 'strtotime' function.
|
||||
*
|
||||
* Not supported in RSS1 feeds.
|
||||
*
|
||||
* @access public
|
||||
* @param DateTime|int|string Date which should be used.
|
||||
* @param DateTimeInterface|int|string Date which should be used.
|
||||
* @return self
|
||||
* @throws \InvalidArgumentException if the given date is not an instance of DateTime, a UNIX timestamp or a date string.
|
||||
* @throws \InvalidArgumentException if the given date is not an implementation of DateTimeInterface, a UNIX timestamp or a date string.
|
||||
* @throws InvalidOperationException if this method is called on an RSS1 feed.
|
||||
*/
|
||||
public function setDate($date)
|
||||
|
@ -425,7 +434,7 @@ abstract class Feed
|
|||
// The feeds have different date formats.
|
||||
$format = $this->version == Feed::ATOM ? \DATE_ATOM : \DATE_RSS;
|
||||
|
||||
if ($date instanceof DateTime)
|
||||
if ($date instanceof DateTimeInterface || $date instanceof DateTime)
|
||||
$date = $date->format($format);
|
||||
else if(is_numeric($date) && $date >= 0)
|
||||
$date = date($format, $date);
|
||||
|
@ -438,7 +447,7 @@ abstract class Feed
|
|||
$date = date($format, $timestamp);
|
||||
}
|
||||
else
|
||||
throw new \InvalidArgumentException('The given date is not an instance of DateTime, a UNIX timestamp or a date string.');
|
||||
throw new \InvalidArgumentException('The given date is not an implementation of DateTimeInterface, a UNIX timestamp or a date string.');
|
||||
|
||||
if ($this->version == Feed::ATOM)
|
||||
$this->setChannelElement('updated', $date);
|
||||
|
@ -454,9 +463,13 @@ abstract class Feed
|
|||
* @access public
|
||||
* @param string $description Description of the feed.
|
||||
* @return self
|
||||
* @throws \InvalidArgumentException if the description is empty or NULL.
|
||||
*/
|
||||
public function setDescription($description)
|
||||
{
|
||||
if (empty($description))
|
||||
throw new \InvalidArgumentException('The description may not be empty or NULL.');
|
||||
|
||||
if ($this->version != Feed::ATOM)
|
||||
$this->setChannelElement('description', $description);
|
||||
else
|
||||
|
@ -471,9 +484,13 @@ abstract class Feed
|
|||
* @access public
|
||||
* @param string $link value of 'link' channel tag
|
||||
* @return self
|
||||
* @throws \InvalidArgumentException if the link is empty or NULL.
|
||||
*/
|
||||
public function setLink($link)
|
||||
{
|
||||
if (empty($link))
|
||||
throw new \InvalidArgumentException('The link may not be empty or NULL.');
|
||||
|
||||
if ($this->version == Feed::ATOM)
|
||||
$this->setAtomLink($link);
|
||||
else
|
||||
|
@ -667,7 +684,7 @@ abstract class Feed
|
|||
/**
|
||||
* Replace invalid XML characters.
|
||||
*
|
||||
* @link http://www.phpwact.org/php/i18n/charsets#xml See utf8_for_xml() function
|
||||
* @link https://web.archive.org/web/20160608013721/http://www.phpwact.org:80/php/i18n/charsets#xml See utf8_for_xml() function
|
||||
* @link http://www.w3.org/TR/REC-xml/#charsets
|
||||
* @link https://github.com/mibe/FeedWriter/issues/30
|
||||
*
|
||||
|
@ -906,7 +923,7 @@ abstract class Feed
|
|||
$out .= "</rdf:Seq>" . PHP_EOL . "</items>" . PHP_EOL . "</channel>" . PHP_EOL;
|
||||
|
||||
// An image has its own element after the channel elements.
|
||||
if (array_key_exists('image', $this->data))
|
||||
if (array_key_exists('Image', $this->data))
|
||||
$out .= $this->makeNode('image', $this->data['Image'], array('rdf:about' => $this->data['Image']['url']));
|
||||
} else if ($this->version == Feed::ATOM) {
|
||||
// ATOM feeds have a unique feed ID. Use the title channel element as key.
|
||||
|
|
0
module/blog/vendor/FeedWriter/InvalidOperationException.php
vendored
Normal file → Executable file
0
module/blog/vendor/FeedWriter/InvalidOperationException.php
vendored
Normal file → Executable file
|
@ -2,6 +2,7 @@
|
|||
namespace FeedWriter;
|
||||
|
||||
use \DateTime;
|
||||
use \DateTimeInterface;
|
||||
|
||||
/*
|
||||
* Copyright (C) 2008 Anis uddin Ahmad <anisniit@gmail.com>
|
||||
|
@ -217,19 +218,19 @@ class Item
|
|||
/**
|
||||
* Set the 'date' element of the feed item.
|
||||
*
|
||||
* The value of the date parameter can be either an instance of the
|
||||
* DateTime class, an integer containing a UNIX timestamp or a string
|
||||
* The value of the date parameter can be either a class implementing
|
||||
* DateTimeInterface, an integer containing a UNIX timestamp or a string
|
||||
* which is parseable by PHP's 'strtotime' function.
|
||||
*
|
||||
* @access public
|
||||
* @param DateTime|int|string $date Date which should be used.
|
||||
* @param DateTimeInterface|int|string $date Date which should be used.
|
||||
* @return self
|
||||
* @throws \InvalidArgumentException if the given date was not parseable.
|
||||
*/
|
||||
public function setDate($date)
|
||||
{
|
||||
if (!is_numeric($date)) {
|
||||
if ($date instanceof DateTime)
|
||||
if ($date instanceof DateTimeInterface || $date instanceof DateTime)
|
||||
$date = $date->getTimestamp();
|
||||
else {
|
||||
$date = strtotime($date);
|
||||
|
@ -277,7 +278,7 @@ class Item
|
|||
* Attach a external media to the feed item.
|
||||
* Not supported in RSS 1.0 feeds.
|
||||
*
|
||||
* See RFC 4288 for syntactical correct MIME types.
|
||||
* See RFC 6838 for syntactical correct MIME types.
|
||||
*
|
||||
* Note that you should avoid the use of more than one enclosure in one item,
|
||||
* since some RSS aggregators don't support it.
|
||||
|
@ -288,7 +289,8 @@ class Item
|
|||
* @param string $type The MIME type attribute of the media.
|
||||
* @param boolean $multiple Specifies if multiple enclosures are allowed
|
||||
* @return self
|
||||
* @link https://tools.ietf.org/html/rfc4288
|
||||
* @link https://tools.ietf.org/html/rfc6838
|
||||
* @link http://www.iana.org/assignments/media-types/media-types.xhtml
|
||||
* @throws \InvalidArgumentException if the length or type parameter is invalid.
|
||||
* @throws InvalidOperationException if this method is called on RSS1 feeds.
|
||||
*/
|
||||
|
@ -389,7 +391,7 @@ class Item
|
|||
// Check if the given ID is an valid URI scheme (see RFC 4287 4.2.6)
|
||||
// The list of valid schemes was generated from http://www.iana.org/assignments/uri-schemes
|
||||
// by using only permanent or historical schemes.
|
||||
$validSchemes = array('aaa', 'aaas', 'about', 'acap', 'acct', 'cap', 'cid', 'coap', 'coaps', 'crid', 'data', 'dav', 'dict', 'dns', 'example', 'fax', 'file', 'filesystem', 'ftp', 'geo', 'go', 'gopher', 'h323', 'http', 'https', 'iax', 'icap', 'im', 'imap', 'info', 'ipp', 'ipps', 'iris', 'iris.beep', 'iris.lwz', 'iris.xpc', 'iris.xpcs', 'jabber', 'ldap', 'mailserver', 'mailto', 'mid', 'modem', 'msrp', 'msrps', 'mtqp', 'mupdate', 'news', 'nfs', 'ni', 'nih', 'nntp', 'opaquelocktoken', 'pack', 'pkcs11', 'pop', 'pres', 'prospero', 'reload', 'rtsp', 'rtsps', 'rtspu', 'service', 'session', 'shttp', 'sieve', 'sip', 'sips', 'sms', 'snews', 'snmp', 'soap.beep', 'soap.beeps', 'stun', 'stuns', 'tag', 'tel', 'telnet', 'tftp', 'thismessage', 'tip', 'tn3270', 'turn', 'turns', 'tv', 'urn', 'vemmi', 'videotex', 'vnc', 'wais', 'ws', 'wss', 'xcon', 'xcon-userid', 'xmlrpc.beep', 'xmlrpc.beeps', 'xmpp', 'z39.50', 'z39.50r', 'z39.50s');
|
||||
$validSchemes = array('aaa', 'aaas', 'about', 'acap', 'acct', 'bb', 'cap', 'cid', 'coap', 'coap+tcp', 'coap+ws', 'coaps', 'coaps+tcp', 'coaps+ws', 'crid', 'data', 'dav', 'dict', 'dns', 'drop', 'dtn', 'example', 'fax', 'file', 'filesystem', 'ftp', 'geo', 'go', 'gopher', 'grd', 'h323', 'http', 'https', 'iax', 'icap', 'im', 'imap', 'info', 'ipn', 'ipp', 'ipps', 'iris', 'iris.beep', 'iris.lwz', 'iris.xpc', 'iris.xpcs', 'jabber', 'ldap', 'leaptofrogans', 'mailserver', 'mailto', 'mid', 'modem', 'msrp', 'msrps', 'mt', 'mtqp', 'mupdate', 'news', 'nfs', 'ni', 'nih', 'nntp', 'opaquelocktoken', 'p1', 'pack', 'pkcs11', 'pop', 'pres', 'prospero', 'reload', 'rtsp', 'rtsps', 'rtspu', 'service', 'session', 'shttp (OBSOLETE)', 'sieve', 'sip', 'sips', 'sms', 'snews', 'snmp', 'soap.beep', 'soap.beeps', 'stun', 'stuns', 'tag', 'tel', 'telnet', 'tftp', 'thismessage', 'tip', 'tn3270', 'turn', 'turns', 'tv', 'upt', 'urn', 'vemmi', 'videotex', 'vnc', 'wais', 'wpid', 'ws', 'wss', 'xcon', 'xcon-userid', 'xmlrpc.beep', 'xmlrpc.beeps', 'xmpp', 'z39.50', 'z39.50r', 'z39.50s');
|
||||
$found = FALSE;
|
||||
$checkId = strtolower($id);
|
||||
|
||||
|
|
|
@ -12,6 +12,11 @@ Once a feed is fully composed with its items, the feed class can generate the ne
|
|||
|
||||
If you don't have **PHP 5.3** available on your system there is a version supporting **PHP 5.0** and above. See the `legacy-php-5.0` branch.
|
||||
|
||||
## Installation
|
||||
You can install via [Composer](https://getcomposer.org/).
|
||||
|
||||
composer require mibe/feedwriter
|
||||
|
||||
## Documentation
|
||||
|
||||
The documentation can be found in the `gh-pages` branch, or on [GitHub Pages](https://mibe.github.io/FeedWriter/).
|
||||
|
@ -40,3 +45,6 @@ In chronological order:
|
|||
- Pavel Khakhlou
|
||||
- Daniel
|
||||
- Tino Goratsch
|
||||
- John
|
||||
- Özgür Görgülü
|
||||
- Jan Tojnar
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue