diff --git a/CHANGES.md b/CHANGES.md index ce1eda4e..819296f9 100755 --- a/CHANGES.md +++ b/CHANGES.md @@ -1,8 +1,14 @@ # Changelog +## Version 12.0.00 +- Modifications : + - Module addon refondu et renommé plugin. + - Réorganisation massive des modules afin d'éviter de faire cohabiter des formulaires avec des champs d'information. + - Désormais, les URL internes seront relatives, cela signifie qu'elles ne contiendront plus le domaine et le chemin d'accès au site. Cela permettra le déplacement d'un site d'un hébergement à un autre, d'un dossier d'hébergement à un autre, sans avoir à convertir les adresses internes. Les données d'un site mis à jour et importées d'une version antérieures sont automatiquement converties. En conséquence, le bloc de conversion de la fenêtre d'import est supprimé. + ## Version 11.3.00 -- Corrections : +Corrections : - Thème / site : problème d'aperçu du body ; police du thème admin non chargées. - Bugs avec les aperçus des sélecteurs de fontes. - Notice générée par l'effacement d'une page sans module. @@ -30,9 +36,8 @@ - Thème ; pied de page ; option pied de page fixe inopérante. - Edition des pages orphelines : "Ne pas afficher" une page contenant des sous-pages provoquait un bug d'affichage dans le menu, la page était malgré tout affichée en fin de menu. Ce problème était causé par les pages enfants dont l'affichage n'était pas modifié. Le correctif cascade l'option "Ne pas afficher" aux sous-pages. La réciproque n'est pas appliquée, il faudra rendre visible les sous-pages d'une page parente qui devient à nouveau visible. - Modifications : - - Addons (gestion des modules), le bouton d'accès au store est déplacé à la page de gestion des modules. Quelques étiquettes de boutons sont modifiés. - - Thème ; pied de page ; options pied de page fixe et alignement avec le contenu déplacées dans les paramètres. - Mise à jour en ligne, contrôle de la clé MD5 de l'archive update.tar.gz. + - Thème ; pied de page ; options pied de page fixe et alignement avec le contenu déplacées dans les paramètres. ## Version 11.2.02 - Correction : diff --git a/README.md b/README.md index c2d81a2d..5fbb8cc7 100755 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ -# ZwiiCMS 11.3.0 +# ZwiiCMS 12.0.00 Zwii est un CMS sans base de données (flat-file) qui permet de créer et gérer facilement un site web sans aucune connaissance en programmation. diff --git a/core/class/helper.class.php b/core/class/helper.class.php index 3c3f7271..f966a387 100644 --- a/core/class/helper.class.php +++ b/core/class/helper.class.php @@ -281,7 +281,7 @@ class helper { if($version = helper::getOnlineVersion()) { //return (trim($version) !== common::ZWII_VERSION); - return ((version_compare(common::ZWII_VERSION,$version,'<')) === -1); + return ((version_compare(common::ZWII_VERSION,$version)) === -1); } else { return false; diff --git a/core/class/template.class.php b/core/class/template.class.php index d246b719..1e9aea0f 100644 --- a/core/class/template.class.php +++ b/core/class/template.class.php @@ -19,15 +19,17 @@ class template { 'name' => $nameId, 'target' => '', 'uniqueSubmission' => false, - 'value' => 'Bouton' + 'value' => 'Bouton', + 'help' => '' ], $attributes); // Retourne le html return sprintf( - '%s', + '%s', helper::sprintAttributes($attributes, ['class', 'disabled', 'ico', 'value']), $attributes['disabled'] ? 'disabled' : '', $attributes['class'], $attributes['uniqueSubmission'] ? 'uniqueSubmission' : '', + $attributes['help'] ? ' title="' . $attributes['help'] . '" ': '', ($attributes['ico'] ? template::ico($attributes['ico'], 'right') : '') . $attributes['value'] ); } diff --git a/core/core.js.php b/core/core.js.php index afceb326..e97e0bf7 100644 --- a/core/core.js.php +++ b/core/core.js.php @@ -490,26 +490,6 @@ $(document).ready(function(){ }; }); - /** - * Active le système d'aide interne - * - */ - - $(".buttonHelp").click(function() { - $(".helpDisplayContent").slideToggle(); - /** - if( $(".buttonHelp").css('opacity') > '0.75'){ - $(".buttonHelp").css('opacity','0.5'); - } - else{ - $(".buttonHelp").css('opacity','1'); - } - */ - }); - - $(".helpDisplayContent").click(function() { - $(".helpDisplayContent").slideToggle(); - }); /** * Remove ID Facebook from URL diff --git a/core/core.php b/core/core.php index b96cde06..dba24540 100644 --- a/core/core.php +++ b/core/core.php @@ -45,8 +45,8 @@ class common { // Numéro de version const ZWII_UPDATE_URL = 'https://forge.chapril.org/ZwiiCMS-Team/update/raw/branch/master/'; - const ZWII_VERSION = '11.3.00'; - const ZWII_UPDATE_CHANNEL = "v11"; + const ZWII_VERSION = '12.0.00'; + const ZWII_UPDATE_CHANNEL = "test"; public static $actions = []; public static $coreModuleIds = [ @@ -58,7 +58,7 @@ class common { 'theme', 'user', 'translate', - 'addon' + 'plugin' ]; public static $accessList = [ 'user', @@ -538,6 +538,8 @@ class common { } + + /** * Effacer les données de la page * @param string pageId @@ -547,7 +549,8 @@ class common { return unlink(self::DATA_DIR . $lang . '/content/' . $this->getData(['page', $page, 'content'])); - } + } + /** * Sauvegarde des données @@ -1179,13 +1182,34 @@ class common { } + /** + * Fonction de parcours des données de module + * @param string $find donnée à rechercher + * @param string $replace donnée à remplacer + * @param array tableau à analyser + * @param int count nombres d'occurrences + * @return array avec les valeurs remplacées. + */ + public function recursive_array_replace ($find, $replace, $array, &$count) { + if (!is_array($array)) { + return str_replace($find, $replace, $array, $count); + } + + $newArray = []; + foreach ($array as $key => $value) { + $newArray[$key] = $this->recursive_array_replace($find, $replace, $value,$c); + $count += $c; + } + return $newArray; + } + /** * Génère une archive d'un dossier et des sous-dossiers * @param string fileName path et nom de l'archive * @param string folder path à zipper * @param array filter dossiers à exclure */ - public function makeZip ($fileName, $folder, $filter ) { + public function makeZip ($fileName, $folder, $filter = [] ) { $zip = new ZipArchive(); $zip->open($fileName, ZipArchive::CREATE | ZipArchive::OVERWRITE); //$directory = 'site/'; @@ -2067,7 +2091,7 @@ class common { } if($this->getUser('group') >= self::GROUP_ADMIN) { $rightItems .= '
  • ' . template::ico('brush') . '
  • '; - $rightItems .= '
  • ' . template::ico('puzzle') . '
  • '; + $rightItems .= '
  • ' . template::ico('puzzle') . '
  • '; if ($this->getData(['config', 'i18n', 'enable']) === true) { $rightItems .= '
  • ' . template::ico('flag') . '
  • '; } diff --git a/core/include/update.inc.php b/core/include/update.inc.php index c0229786..ac8171bc 100644 --- a/core/include/update.inc.php +++ b/core/include/update.inc.php @@ -741,6 +741,55 @@ if ($this->getData(['core', 'dataVersion']) < 11202) { $this->setData(['core', 'dataVersion', 11202]); } +// Version 11.2.03 +if ($this->getData(['core', 'dataVersion']) < 11203) { + // Supprimer l'information de redirection + $old = str_replace('?','',$this->getData(['core', 'baseUrl'])); + $new = ''; + $c3 = 0; + $success = false ; + // Boucler sur les pages + foreach($this->getHierarchy(null,null,null) as $parentId => $childIds) { + $content = $this->getPage($parentId, self::$i18n); + $titre = $this->getData(['page', $parentId, 'title']); + $content = $titre . ' ' . $content ; + $replace = str_replace( 'href="' . $old , 'href="'. $new , stripslashes($content),$c1) ; + $replace = str_replace( 'src="' . $old , 'src="'. $new , stripslashes($replace),$c2) ; + + if ($c1 > 0 || $c2 > 0) { + $success = true; + $this->setPage($parentId, $replace, self::$i18n); + $c3 += $c1 + $c2; + } + foreach($childIds as $childId) { + $content = $this->getPage($childId, self::$i18n); + $content = $titre . ' ' . $content ; + $replace = str_replace( 'href="' . $old , 'href="'. $new , stripslashes($content),$c1) ; + $replace = str_replace( 'src="' . $old , 'src="'. $new , stripslashes($replace),$c2) ; + if ($c1 > 0 || $c2 > 0) { + $success = true; + $this->setPage($childId, $replace, self::$i18n); + $c3 += $c1 + $c2; + } + } + } + // Traiter les modules dont la redirection + $content = $this->getdata(['module']); + $replace = $this->recursive_array_replace('href="' . $old , 'href="'. $new, $content, $c1); + $replace = $this->recursive_array_replace('src="' . $old , 'src="'. $new, $replace, $c2); + if ($content !== $replace) { + $this->setdata(['module',$replace]); + $c3 += $c1 + $c2; + $success = true; + } + + // Effacer la baseUrl + $this->deleteData(['core', 'baseUrl']); + + // Mise à jour + $this->setData(['core', 'dataVersion', 11203]); +} + // Version 11.3.00 if ($this->getData(['core', 'dataVersion']) < 11300) { @@ -790,4 +839,14 @@ if ($this->getData(['core', 'dataVersion']) < 11300) { // Mise à jour $this->setData(['core', 'dataVersion', 11300]); -} \ No newline at end of file +} + +// Version 12.0.00 +if ($this->getData(['core', 'dataVersion']) < 12000) { + + // Effacer le dossier + $this->removeDir('core/module/addon'); + + // Mise à jour + $this->setData(['core', 'dataVersion', 12000]); +} diff --git a/core/layout/common.css b/core/layout/common.css index 451a10d0..16550540 100755 --- a/core/layout/common.css +++ b/core/layout/common.css @@ -1744,22 +1744,6 @@ th.col12 { width: 60%; } -/* Système d'aide */ - -.helpDisplayContent { - display: none; - width: 100%; - padding: 10px 10px; - -webkit-box-shadow: 5px 5px 11px 0px #222222; - box-shadow: 5px 5px 11px 0px #222222; - border-radius: 5px; - z-index: 30; -} - -.helpDisplayContent, .helpDisplayButton { - cursor: pointer; -} - /* Bannière masquable en petit écran*/ @media screen and (max-width: 768px) { .bannerDisplay{ diff --git a/core/module/addon/addon.php b/core/module/addon/addon.php deleted file mode 100644 index 2aff2f7a..00000000 --- a/core/module/addon/addon.php +++ /dev/null @@ -1,594 +0,0 @@ - - * @copyright Copyright (C) 2008-2018, Rémi Jean - * @author Frédéric Tempez - * @copyright Copyright (C) 2018-2022, Frédéric Tempez - * @author Sylvain Lelièvre - * @copyright Copyright (C) 2020-2021, Sylvain Lelièvre - * @license GNU General Public License, version 3 - * @link http://zwiicms.fr/ - */ - -class addon extends common { - - public static $actions = [ - 'index' => self::GROUP_ADMIN, - 'delete' => self::GROUP_ADMIN, - 'export' => self::GROUP_ADMIN, - 'import' => self::GROUP_ADMIN, - 'store' => self::GROUP_ADMIN, - 'item' => self::GROUP_ADMIN, - 'upload' => self::GROUP_ADMIN, - 'uploadItem'=> self::GROUP_ADMIN - ]; - - // URL des modules - const BASEURL_STORE = 'https://store.zwiicms.fr/'; - const MODULE_STORE = '?modules/'; - - // Gestion des modules - public static $modInstal = []; - - // pour tests - public static $valeur = []; - - // le catalogue - public static $storeList = []; - public static $storeItem = []; - - - /* - * Effacement d'un module installé et non utilisé - */ - public function delete() { - - // Jeton incorrect - if ($this->getUrl(3) !== $_SESSION['csrf']) { - // Valeurs en sortie - $this->addOutput([ - 'redirect' => helper::baseUrl() . 'addon', - 'state' => false, - 'notification' => 'Action non autorisée' - ]); - } - else{ - // Suppression des dossiers - $infoModules = helper::getModules(); - $module = $this->getUrl(2); - //Liste des dossiers associés au module non effacés - if( $this->removeDir('./module/'.$module ) === true ){ - $success = true; - $notification = 'Module '. $module .' désinstallé'; - if(($infoModules[$this->getUrl(2)]['dataDirectory']) ) { - if ( - is_dir($infoModules[$this->getUrl(2)]['dataDirectory']) - && !$this->removeDir($infoModules[$this->getUrl(2)]['dataDirectory']) - ){ - $notification = 'Module '.$module .' désinstallé, il reste des données dans ' . $infoModules[$this->getUrl(2)]['dataDirectory']; - } - } - } - else{ - $success = false; - $notification = 'La suppression a échouée'; - } - // Valeurs en sortie - $this->addOutput([ - 'redirect' => helper::baseUrl() . 'addon', - 'notification' => $notification, - 'state' => $success - ]); - } - } - - /*** - * Installation d'un module - * Fonction utilisée par upload et storeUpload - */ - private function install ($moduleName, $checkValid){ - $tempFolder = 'datamodules';//uniqid(); - $zip = new ZipArchive(); - if ($zip->open($moduleName) === TRUE) { - $notification = 'Archive ouverte'; - mkdir (self::TEMP_DIR . $tempFolder, 0755); - $zip->extractTo(self::TEMP_DIR . $tempFolder ); - // Archive de module ? - $success = false; - $notification = 'Ce n\'est pas l\'archive d\'un module !'; - $moduleDir = self::TEMP_DIR . $tempFolder . '/module'; - $moduleName = ''; - if ( is_dir( $moduleDir )) { - // Lire le nom du module - if ($dh = opendir( $moduleDir )) { - while ( false !== ($file = readdir($dh)) ) { - if ($file != "." && $file != "..") { - $moduleName = $file; - } - } - closedir($dh); - } - // Module normalisé ? - if( is_file( $moduleDir.'/'.$moduleName.'/'.$moduleName.'.php' ) AND is_file( $moduleDir.'/'.$moduleName.'/view/index/index.php' ) ){ - - // Lecture de la version et de la validation d'update du module pour validation de la mise à jour - // Pour une version <= version installée l'utilisateur doit cocher 'Mise à jour forcée' - $version = '0.0'; - $update = '0.0'; - $valUpdate = false; - $file = file_get_contents( $moduleDir.'/'.$moduleName.'/'.$moduleName.'.php'); - $file = str_replace(' ','',$file); - $file = str_replace("\t",'',$file); - $pos1 = strpos($file, 'constVERSION'); - if( $pos1 !== false){ - $posdeb = strpos($file, "'", $pos1); - $posend = strpos($file, "'", $posdeb + 1); - $version = substr($file, $posdeb + 1, $posend - $posdeb - 1); - } - $pos1 = strpos($file, 'constUPDATE'); - if( $pos1 !== false){ - $posdeb = strpos($file, "'", $pos1); - $posend = strpos($file, "'", $posdeb + 1); - $update = substr($file, $posdeb + 1, $posend - $posdeb - 1); - } - // Si version actuelle >= version indiquée dans UPDATE la mise à jour est validée - $infoModules = helper::getModules(); - if( $infoModules[$moduleName]['update'] >= $update ) $valUpdate = true; - - // Module déjà installé ? - $moduleInstal = false; - foreach($infoModules as $key=>$value ){ - if($moduleName === $key){ - $moduleInstal = true; - } - } - - // Validation de la maj si autorisation du concepteur du module ET - // ( Version plus récente OU Check de forçage ) - $valNewVersion = floatval($version); - $valInstalVersion = floatval( $infoModules[$moduleName]['version'] ); - $newVersion = false; - if( $valNewVersion > $valInstalVersion ) $newVersion = true; - $validMaj = $valUpdate && ( $newVersion || $checkValid); - - // Nouvelle installation ou mise à jour du module - if( ! $moduleInstal || $validMaj ){ - // Copie récursive des dossiers - $this->copyDir( self::TEMP_DIR . $tempFolder, './' ); - $success = true; - if( ! $moduleInstal ){ - $notification = 'Module '.$moduleName.' installé'; - } - else{ - $notification = 'Module '.$moduleName.' mis à jour'; - } - } - else{ - $success = false; - if( $valNewVersion == $valInstalVersion){ - $notification = ' Version détectée '.$version.' = à celle installée '.$infoModules[$moduleName]['version']; - } - else{ - $notification = ' Version détectée '.$version.' < à celle installée '.$infoModules[$moduleName]['version']; - } - if( $valUpdate === false){ - if( $infoModules[$moduleName]['update'] === $update ){ - $notification = ' Mise à jour par ce procédé interdite par le concepteur du module'; - } - else{ - $notification = ' Mise à jour par ce procédé interdite, votre version est trop ancienne'; - } - } - } - } - } - // Supprimer le dossier temporaire même si le module est invalide - $this->removeDir(self::TEMP_DIR . $tempFolder); - $zip->close(); - } else { - // erreur à l'ouverture - $success = false; - $notification = 'Impossible d\'ouvrir l\'archive'; - } - return(['success' => $success, - 'notification'=> $notification - ]); - } - - /*** - * Installation d'un module à partir du gestionnaire de fichier - */ - public function upload() { - // Soumission du formulaire - if($this->isPost()) { - // Installation d'un module - $checkValidMaj = $this->getInput('configModulesCheck', helper::FILTER_BOOLEAN); - $zipFilename = $this->getInput('configModulesInstallation', helper::FILTER_STRING_SHORT); - if( $zipFilename !== ''){ - $success = [ - 'success' => false, - 'notification'=> '' - ]; - $state = $this->install(self::FILE_DIR.'source/'.$zipFilename, $checkValidMaj); - } - $this->addOutput([ - 'redirect' => helper::baseUrl() . $this->getUrl(), - 'notification' => $state['notification'], - 'state' => $state['success'] - ]); - } - // Valeurs en sortie - $this->addOutput([ - 'title' => 'Téléverser un module', - 'view' => 'upload' - ]); - } - - /*** - * Installation d'un module par le catalogue - */ - public function uploadItem() { - // Jeton incorrect - if ($this->getUrl(3) !== $_SESSION['csrf']) { - // Valeurs en sortie - $this->addOutput([ - 'redirect' => helper::baseUrl() . 'store', - 'state' => false, - 'notification' => 'Action non autorisée' - ]); - } else { - // Récupérer le module en ligne - $moduleName = $this->getUrl(2); - // Informations sur les module en ligne - $store = json_decode(helper::getUrlContents(self::BASEURL_STORE . self::MODULE_STORE . 'list'), true); - // Url du module à télécharger - $moduleFilePath = $store[$moduleName]['file']; - // Télécharger le fichier - $moduleData = helper::getUrlContents(self::BASEURL_STORE . self::FILE_DIR . 'source/' . $moduleFilePath); - // Extraire de l'arborescence - $d = explode('/',$moduleFilePath); - $moduleFile = $d[count($d)-1]; - // Créer le dossier modules - if (!is_dir(self::FILE_DIR . 'source/modules')) { - mkdir (self::FILE_DIR . 'source/modules', 0755); - } - // Sauver les données du fichiers - file_put_contents(self::FILE_DIR . 'source/modules/' . $moduleFile, $moduleData); - - /** - * $if( $moduleFile !== ''){ - * $success = [ - * 'success' => false, - * 'notification'=> '' - * ]; - * $state = $this->install(self::FILE_DIR.'source/modules/'.$moduleFile, false); - *} - */ - $this->addOutput([ - 'redirect' => helper::baseUrl() . 'addon/store', - 'notification' => $moduleFile . ' téléchargé dans le dossier modules du gestionnaire de fichiers', - 'state' => true - ]); - - } - // Valeurs en sortie - $this->addOutput([ - 'title' => 'Catalogue de modules', - 'view' => 'store' - ]); - } - - /** - * Catalogue des modules sur le site ZwiiCMS.fr - */ - public function store() { - $store = json_decode(helper::getUrlContents(self::BASEURL_STORE . self::MODULE_STORE . 'list'), true); - if ($store) { - // Modules installés - $infoModules = helper::getModules(); - // Clés moduleIds dans les pages - $inPages = helper::arrayCollumn($this->getData(['page']),'moduleId', 'SORT_DESC'); - foreach( $inPages as $key=>$value){ - $inPagesTitle[ $this->getData(['page', $key, 'title' ]) ] = $value; - } - // Parcourir les données des modules - foreach ($store as $key=>$value) { - // Module non installé - $ico = template::ico('download'); - $class = ''; - // Le module est installé - if (array_key_exists($key,$infoModules) === true) { - $class = 'buttonGreen'; - $ico = template::ico('update'); - } - // Le module est installé et utilisé - if (in_array($key,$inPages) === true) { - $class = 'buttonRed'; - $ico = template::ico('update'); - } - self::$storeList [] = [ - $store[$key]['category'], - ''.$store[$key]['title'].'', - $store[$key]['version'], - mb_detect_encoding(strftime('%d %B %Y', $store[$key]['versionDate']), 'UTF-8', true) - ? strftime('%d %B %Y', $store[$key]['versionDate']) - : utf8_encode(strftime('%d %B %Y', $store[$key]['versionDate'])), - implode(', ', array_keys($inPagesTitle,$key)), - template::button('moduleExport' . $key, [ - 'class' => $class, - 'href' => helper::baseUrl(). $this->getUrl(0) . '/uploadItem/' . $key.'/' . $_SESSION['csrf'],// appel de fonction vaut exécution, utiliser un paramètre - 'value' => $ico - ]) - ]; - } - } - - // Valeurs en sortie - $this->addOutput([ - 'title' => 'Catalogue de modules en ligne', - 'view' => 'store' - ]); - } - - /** - * Détail d'un objet du catalogue - */ - public function item() { - $store = json_decode(helper::getUrlContents(self::BASEURL_STORE . self::MODULE_STORE . 'list'), true); - self::$storeItem = $store [$this->getUrl(2)] ; - self::$storeItem ['fileDate'] = mb_detect_encoding(strftime('%d %B %Y',self::$storeItem ['fileDate']), 'UTF-8', true) - ? strftime('%d %B %Y', self::$storeItem ['fileDate']) - : utf8_encode(strftime('%d %B %Y', self::$storeItem ['fileDate'])); - // Valeurs en sortie - $this->addOutput([ - 'title' =>'Module ' . self::$storeItem['title'], - 'view' => 'item' - ]); - } - - /** - * Gestion des modules - */ - public function index() { - - // Lister les modules - // $infoModules[nom_module]['realName'], ['version'], ['update'], ['delete'], ['dataDirectory'] - $infoModules = helper::getModules(); - - // Clés moduleIds dans les pages - $inPages = helper::arrayCollumn($this->getData(['page']),'moduleId', 'SORT_DESC'); - foreach( $inPages as $key=>$value){ - $inPagesTitle[ $this->getData(['page', $key, 'title' ]) ] = $value; - } - - // Parcourir les données des modules - foreach ($infoModules as $key=>$value) { - // Construire le tableau de sortie - self::$modInstal[] = [ - $key, - $infoModules[$key]['realName'], - $infoModules[$key]['version'], - implode(', ', array_keys($inPagesTitle,$key)), - //|| ('delete',$infoModules[$key]) && $infoModules[$key]['delete'] === true && implode(', ',array_keys($inPages,$key)) === '' - $infoModules[$key]['delete'] === true && implode(', ',array_keys($inPages,$key)) === '' - ? template::button('moduleDelete' . $key, [ - 'class' => 'moduleDelete buttonRed', - 'href' => helper::baseUrl() . $this->getUrl(0) . '/delete/' . $key . '/' . $_SESSION['csrf'], - 'value' => template::ico('cancel') - ]) - : '', - implode(', ',array_keys($inPages,$key)) !== '' - ? template::button('moduleExport' . $key, [ - 'href' => helper::baseUrl(). $this->getUrl(0) . '/export/' . $key . '/' . $_SESSION['csrf'],// appel de fonction vaut exécution, utiliser un paramètre - 'value' => template::ico('download') - ]) - : '', - implode(', ',array_keys($inPages,$key)) === '' - ? template::button('moduleExport' . $key, [ - 'href' => helper::baseUrl(). $this->getUrl(0) . '/import/' . $key . '/' . $_SESSION['csrf'],// appel de fonction vaut exécution, utiliser un paramètre - 'value' => template::ico('upload') - ]) - : '' - ]; - } - - // Valeurs en sortie - $this->addOutput([ - 'title' => 'Gestion des modules', - 'view' => 'index' - ]); - } - - /* - * Export des données d'un module externes ou interne à module.json - */ - public function export(){ - // Jeton incorrect - if ($this->getUrl(3) !== $_SESSION['csrf']) { - // Valeurs en sortie - $this->addOutput([ - 'redirect' => helper::baseUrl() . 'addon', - 'state' => false, - 'notification' => 'Action non autorisée' - ]); - } - else { - // Lire les données du module - $infoModules = helper::getModules(); - // Créer un dossier par défaut - $tmpFolder = self::TEMP_DIR . uniqid(); - //$tmpFolder = self::TEMP_DIR . 'test'; - if (!is_dir($tmpFolder)) { - mkdir($tmpFolder, 0755); - } - // Clés moduleIds dans les pages - $inPages = helper::arrayCollumn($this->getData(['page']),'moduleId', 'SORT_DESC'); - // Parcourir les pages utilisant le module - foreach (array_keys($inPages,$this->getUrl(2)) as $pageId) { - // Export des pages hébergeant le module - $pageParam[$pageId] = $this->getData(['page',$pageId]); - // Export du contenu de la page - //$pageContent[$pageId] = file_get_contents(self::DATA_DIR . self::$i18n . '/content/' . $this->getData(['page', $pageId, 'content'])); - $pageContent[$pageId] = $this->getPage($pageId, self::$i18n); - // Export de fr/module.json - $moduleId = 'fr/module.json'; - $moduleDir = str_replace('site/data/','',$infoModules[$this->getUrl(2)]['dataDirectory']); - // Création de l'arborescence des langues - // Pas de nom dossier de langue - dossier par défaut - $t = explode ('/',$moduleId); - if ( is_array($t)) { - $lang = 'fr'; - } else { - $lang = $t[0]; - } - // Créer le dossier temporaire si inexistant sinon le nettoie et le créer - if (!is_dir($tmpFolder . '/' . $lang)) { - mkdir ($tmpFolder . '/' . $lang, 0755, true); - } else { - $this->removeDir($tmpFolder . '/' . $lang); - mkdir ($tmpFolder . '/' . $lang, 0755, true); - } - // Créer le dossier temporaire des données du module - if ($infoModules[$this->getUrl(2)]['dataDirectory']) { - if (!is_dir($tmpFolder . '/' . $moduleDir)) { - mkdir ($tmpFolder . '/' . $moduleDir, 0755, true) ; - } - } - // Sauvegarde si données non vides - $tmpData [$pageId] = $this->getData(['module',$pageId ]); - if ($tmpData [$pageId] !== null) { - file_put_contents($tmpFolder . '/' . $moduleId, json_encode($tmpData)); - } - // Export des données localisées dans le dossier de données du module - if ($infoModules[$this->getUrl(2)]['dataDirectory'] && - is_dir($infoModules[$this->getUrl(2)]['dataDirectory'])) { - $this->copyDir ($infoModules[$this->getUrl(2)]['dataDirectory'], $tmpFolder . '/' . $moduleDir); - } - } - // Enregistrement des pages dans le dossier de langue identique à module - if (!file_exists($tmpFolder . '/' . $lang . '/page.json')) { - file_put_contents($tmpFolder . '/' . $lang . '/page.json', json_encode($pageParam)); - mkdir ($tmpFolder . '/' . $lang . '/content', 0755); - file_put_contents($tmpFolder . '/' . $lang . '/content/' . $this->getData(['page', $pageId, 'content']), $pageContent); - } - // création du zip - $fileName = $this->getUrl(2) . '.zip'; - $this->makeZip ($fileName, $tmpFolder, []); - if (file_exists($fileName)) { - ob_start(); - header('Content-Type: application/octet-stream'); - header('Content-Disposition: attachment; filename="' . $fileName . '"'); - header('Content-Length: ' . filesize($fileName)); - ob_clean(); - ob_end_flush(); - readfile( $fileName); - unlink($fileName); - $this->removeDir($tmpFolder); - exit(); - } else { - // Valeurs en sortie - $this->addOutput([ - 'redirect' => helper::baseUrl() . 'addon', - 'notification' => 'Quelque chose s\'est mal passé', - 'state' => false - ]); - } - } - } - - /* - * Importer des données d'un module externes ou interne à module.json - */ - public function import(){ - // Jeton incorrect - if ($this->getUrl(3) !== $_SESSION['csrf']) { - // Valeurs en sortie - $this->addOutput([ - 'redirect' => helper::baseUrl() . 'addon', - 'state' => false, - 'notification' => 'Action non autorisée' - ]); - } - else { - // Soumission du formulaire - if($this->isPost()) { - // Récupérer le fichier et le décompacter - $zipFilename = $this->getInput('addonImportFile', helper::FILTER_STRING_SHORT, true); - $tempFolder = uniqid(); - mkdir (self::TEMP_DIR . $tempFolder, 0755); - $zip = new ZipArchive(); - if ($zip->open(self::FILE_DIR . 'source/' . $zipFilename) === TRUE) { - $zip->extractTo(self::TEMP_DIR . $tempFolder ); - } - // Import des données localisées page.json et module.json - // Pour chaque dossier localisé - $dataTarget = array(); - $dataSource = array(); - // Liste des pages de même nom dans l'archive et le site - $list = ''; - foreach (self::$i18nList as $key=>$value) { - // Les Pages et les modules - foreach (['page','module'] as $fileTarget){ - if (file_exists(self::TEMP_DIR . $tempFolder . '/' .$key . '/' . $fileTarget . '.json')) { - // Le dossier de langue existe - // faire la fusion - $dataSource = json_decode(file_get_contents(self::TEMP_DIR . $tempFolder . '/' .$key . '/' . $fileTarget . '.json'), true); - // Des pages de même nom que celles de l'archive existent - if( $fileTarget === 'page' ){ - foreach( $dataSource as $keydataSource=>$valuedataSource ){ - foreach( $this->getData(['page']) as $keypage=>$valuepage ){ - if( $keydataSource === $keypage){ - $list === '' ? $list .= ' '.$this->getData(['page', $keypage, 'title']) : $list .= ', '.$this->getData(['page', $keypage, 'title']); - } - } - } - } - $dataTarget = json_decode(file_get_contents(self::DATA_DIR . $key . '/' . $fileTarget . '.json'), true); - $data [$fileTarget] = array_merge($dataTarget[$fileTarget], $dataSource); - if( $list === ''){ - file_put_contents(self::DATA_DIR . '/' .$key . '/' . $fileTarget . '.json', json_encode( $data ,JSON_UNESCAPED_UNICODE|JSON_PRETTY_PRINT|LOCK_EX) ); - } - // copie du contenu de la page - $this->copyDir (self::TEMP_DIR . $tempFolder . '/' .$key . '/content', self::DATA_DIR . '/' .$key . '/content'); - // Supprimer les fichiers importés - unlink (self::TEMP_DIR . $tempFolder . '/' .$key . '/' . $fileTarget . '.json'); - } - } - } - - // Import des fichiers placés ailleurs que dans les dossiers localisés. - $this->copyDir (self::TEMP_DIR . $tempFolder,self::DATA_DIR ); - - // Supprimer le dossier temporaire - $this->removeDir(self::TEMP_DIR . $tempFolder); - $zip->close(); - if( $list !== '' ){ - $success = false; - strpos( $list, ',') === false ? $notification = 'Import impossible la page suivante doit être renommée :'.$list : $notification = 'Import impossible les pages suivantes doivent être renommées :'.$list; - } - else{ - $success = true; - $notification = 'Import réussi'; - } - // Valeurs en sortie - $this->addOutput([ - 'redirect' => helper::baseUrl() . 'addon', - 'state' => $success, - 'notification' => $notification - ]); - } - // Valeurs en sortie - $this->addOutput([ - 'title' => 'Importer des données de module', - 'view' => 'import' - ]); - } - } - -} diff --git a/core/module/addon/view/import/import.php b/core/module/addon/view/import/import.php deleted file mode 100644 index 7cc41dac..00000000 --- a/core/module/addon/view/import/import.php +++ /dev/null @@ -1,31 +0,0 @@ - -
    -
    - 'buttonGrey', - 'href' => helper::baseUrl() . 'addon', - 'ico' => 'left', - 'value' => 'Retour' - ]); ?> -
    -
    - 'Appliquer' - ]); ?> -
    -
    -
    -
    -
    -

    Installer des données de module

    -
    -
    - 'Archive ZIP :', - 'type' => 2 - ]); ?> -
    -
    -
    -
    -
    \ No newline at end of file diff --git a/core/module/addon/view/index/index.help.html b/core/module/addon/view/index/index.help.html deleted file mode 100644 index 8af49c96..00000000 --- a/core/module/addon/view/index/index.help.html +++ /dev/null @@ -1,8 +0,0 @@ -

    MODULES INSTALLES

    -Les modules installés sont listés dans le tableau avec leur nom usuel (alias) et leur numéro de version. -Si le module est utilisé le nom de la page ou des pages apparaît, dans le cas contraire une icône permet de le supprimer. -

    EXPORTER IMPORTER

    -

    Exporter produit une archive au nom du module contenant les pages concernées ainsi que les données et ressources utilisées par le module dans ces pages.

    -

    Vous pouvez vous en servir comme d'une sauvegarde partielle ou pour transférer les pages et les données du module vers un autre site.

    -

    Une fois le module installé l'import permet de restaurer les pages et les données sauvegardées. Vous devrez avoir au préalable transféré le fichier zip d'un export sur votre serveur par 'Gérer les fichiers'. -Si une page de même nom existe sur votre site vous serez invité à modifier son nom.

    diff --git a/core/module/addon/view/index/index.php b/core/module/addon/view/index/index.php deleted file mode 100644 index e1e9c61f..00000000 --- a/core/module/addon/view/index/index.php +++ /dev/null @@ -1,40 +0,0 @@ -
    -
    - 'buttonGrey', - 'href' => helper::baseUrl(), - 'ico' => 'left', - 'value' => 'Retour' - ]); ?> -
    -
    - 'https://doc.zwiicms.fr/les-modules', - 'target' => '_blank', - 'ico' => 'help', - 'value' => 'Aide', - 'class' => 'buttonHelp' - ]); ?> -
    -
    - helper::baseUrl() . 'addon/store', - 'value' => 'Catalogue en ligne' - ]); ?> -
    -
    - helper::baseUrl() . 'addon/upload', - 'value' => 'Installer' - ]); ?> -
    -
    - -
    - -
    - - - - - diff --git a/core/module/addon/view/store/store.php b/core/module/addon/view/store/store.php deleted file mode 100644 index e1324a6a..00000000 --- a/core/module/addon/view/store/store.php +++ /dev/null @@ -1,15 +0,0 @@ -
    -
    - 'buttonGrey', - 'href' => helper::baseUrl() . 'addon/upload', - 'ico' => 'left', - 'value' => 'Retour' - ]); ?> -
    -
    - - Mettre à jour']); ?> - - - \ No newline at end of file diff --git a/core/module/addon/view/upload/upload.help.html b/core/module/addon/view/upload/upload.help.html deleted file mode 100644 index fbf87085..00000000 --- a/core/module/addon/view/upload/upload.help.html +++ /dev/null @@ -1,6 +0,0 @@ -

    INSTALLER OU METTRE A JOUR

    -

    Avant de choisir le fichier ZIP du module à installer vous devez le télécharger sur votre serveur en utilisant le 'Catalogue en ligne'.

    -

    D'autres modules sont également disponibles sur le forum de ZwiiCMS, -téléversez les sur votre serveur avec 'Gérer les fichiers'.

    -

    Lors d'une mise à jour Zwii contrôle la version du module à installer, pour réinstaller un module de même numéro de version vous devez cocher 'Mise à jour forcée'. - Il est déconseillé d'installer un module plus ancien.

    diff --git a/core/module/config/config.php b/core/module/config/config.php index f274265d..526604a8 100644 --- a/core/module/config/config.php +++ b/core/module/config/config.php @@ -19,6 +19,7 @@ class config extends common { public static $actions = [ 'backup' => self::GROUP_ADMIN, 'copyBackups'=> self::GROUP_ADMIN, + 'delBackups'=> self::GROUP_ADMIN, 'configMetaImage' => self::GROUP_ADMIN, 'generateFiles' => self::GROUP_ADMIN, 'index' => self::GROUP_ADMIN, @@ -383,6 +384,15 @@ class config extends common { $this->setData(['user',$users]); } } + // Conversion vers des Url relatives + if ($this->getData(['core', 'baseUrl'])) { + $url = str_replace('?','',$this->getData(['core', 'baseUrl'])); + // Suppresion de la base Url + $this->updateBaseUrl($url); + // Effacer la baseUrl + $this->deleteData(['core', 'baseUrl']); + } + // Message de notification $notification = $success === true ? 'Restaurer effectuée avec succès' : 'Erreur inconnue'; $redirect = $this->getInput('configRestoreImportUser', helper::FILTER_BOOLEAN) === true ? helper::baseUrl() . 'config/restore' : helper::baseUrl() . 'user/login/'; @@ -584,7 +594,7 @@ class config extends common { $this->generateFiles(); // Valeurs en sortie $this->addOutput([ - 'title' => 'Configuration', + 'title' => 'Configuration du site', 'view' => 'index', 'notification' => 'Modifications enregistrées ' , 'state' => true @@ -616,7 +626,7 @@ class config extends common { // Valeurs en sortie $this->addOutput([ - 'title' => 'Configuration', + 'title' => 'Configuration du site', 'view' => 'index' ]); } @@ -655,10 +665,8 @@ class config extends common { /** * Met à jour les données de site avec l'adresse transmise */ - public function updateBaseUrl () { + public function updateBaseUrl ($url) { // Supprimer l'information de redirection - $old = str_replace('?','',$this->getData(['core', 'baseUrl'])); - $new = helper::baseUrl(false,false); $c3 = 0; $success = false ; // Boucler sur les pages @@ -666,8 +674,8 @@ class config extends common { $content = $this->getPage($parentId, self::$i18n); $titre = $this->getData(['page', $parentId, 'title']); $content = $titre . ' ' . $content ; - $replace = str_replace( 'href="' . $old , 'href="'. $new , stripslashes($content),$c1) ; - $replace = str_replace( 'src="' . $old , 'src="'. $new , stripslashes($replace),$c2) ; + $replace = str_replace( 'href="' . $url , 'href="'. '' , stripslashes($content),$c1) ; + $replace = str_replace( 'src="' . $url , 'src="'. '' , stripslashes($replace),$c2) ; if ($c1 > 0 || $c2 > 0) { $success = true; @@ -677,8 +685,8 @@ class config extends common { foreach($childIds as $childId) { $content = $this->getPage($childId, self::$i18n); $content = $titre . ' ' . $content ; - $replace = str_replace( 'href="' . $old , 'href="'. $new , stripslashes($content),$c1) ; - $replace = str_replace( 'src="' . $old , 'src="'. $new , stripslashes($replace),$c2) ; + $replace = str_replace( 'href="' . $url , 'href="'. '' , stripslashes($content),$c1) ; + $replace = str_replace( 'src="' . $url , 'src="'. '' , stripslashes($replace),$c2) ; if ($c1 > 0 || $c2 > 0) { $success = true; $this->setPage($childId, $replace, self::$i18n); @@ -688,8 +696,8 @@ class config extends common { } // Traiter les modules dont la redirection $content = $this->getdata(['module']); - $replace = $this->recursive_array_replace('href="' . $old , 'href="'. $new, $content, $c1); - $replace = $this->recursive_array_replace('src="' . $old , 'src="'. $new, $replace, $c2); + $replace = $this->recursive_array_replace('href="' . $url , 'href="'. '', $content, $c1); + $replace = $this->recursive_array_replace('src="' . $url , 'src="'. '', $replace, $c2); if ($content !== $replace) { $this->setdata(['module',$replace]); $c3 += $c1 + $c2; @@ -718,7 +726,7 @@ class config extends common { file_put_contents(self::DATA_DIR . 'journal.log',$d); // Valeurs en sortie $this->addOutput([ - 'title' => 'Configuration', + 'title' => 'Configuration du site', 'view' => 'index', 'notification' => 'Journal réinitialisé avec succès', 'state' => true @@ -726,7 +734,7 @@ class config extends common { } else { // Valeurs en sortie $this->addOutput([ - 'title' => 'Configuration', + 'title' => 'Configuration du site', 'view' => 'index', 'notification' => 'Aucun journal à effacer', 'state' => false @@ -754,7 +762,7 @@ class config extends common { } else { // Valeurs en sortie $this->addOutput([ - 'title' => 'Configuration', + 'title' => 'Configuration du site', 'view' => 'index', 'notification' => 'Aucun fichier journal à télécharger', 'state' => false @@ -791,7 +799,7 @@ class config extends common { } else { // Valeurs en sortie $this->addOutput([ - 'title' => 'Configuration', + 'title' => 'Configuration du site', 'view' => 'index', 'notification' => 'Aucune liste noire à télécharger', 'state' => false @@ -808,7 +816,7 @@ class config extends common { $this->setData(['blacklist',[]]); // Valeurs en sortie $this->addOutput([ - 'title' => 'Configuration', + 'title' => 'Configuration du site', 'view' => 'index', 'notification' => 'Liste noire réinitialisée avec succès', 'state' => true @@ -816,7 +824,7 @@ class config extends common { } else { // Valeurs en sortie $this->addOutput([ - 'title' => 'Configuration', + 'title' => 'Configuration du site', 'view' => 'index', 'notification' => 'Pas de liste à effacer', 'state' => false @@ -835,32 +843,37 @@ class config extends common { $this->copyDir(self::BACKUP_DIR, self::FILE_DIR . 'source/backup' ); // Valeurs en sortie $this->addOutput([ - 'title' => 'Configuration', + 'title' => 'Configuration du site', 'view' => 'index', 'notification' => 'Copie terminée', 'state' => true ]); } - /** - * Fonction de parcours des données de module - * @param string $find donnée à rechercher - * @param string $replace donnée à remplacer - * @param array tableau à analyser - * @param int count nombres d'occurrences - * @return array avec les valeurs remplacées. + * Vider le dosser des sauvegardes automatisées */ - private function recursive_array_replace ($find, $replace, $array, &$count) { - if (!is_array($array)) { - return str_replace($find, $replace, $array, $count); + public function delBackups() { + $path = realpath(self::BACKUP_DIR); + $success = $fail = 0; + foreach (new RecursiveIteratorIterator(new RecursiveDirectoryIterator($path)) as $filename) + { + if (strpos($filename,'.zip')) { + + $r = unlink($filename); + $success = $r === true ? $succes + 1 : $success; + $fail = $r === false ? $fail + 1 : $fail; + } } - - $newArray = []; - foreach ($array as $key => $value) { - $newArray[$key] = $this->recursive_array_replace($find, $replace, $value,$c); - $count += $c; - } - return $newArray; + // Valeurs en sortie + $this->addOutput([ + 'title' => 'Configuration du site', + 'view' => 'index', + 'notification' => 'Suppression terminée :
    ' . $success . ' fichiers effacé(s)
    ' . $fail . ' échec(s)', + 'state' => true + ]); } + + + } diff --git a/core/module/config/view/backup/backup.php b/core/module/config/view/backup/backup.php index 070ab2cd..25071a93 100644 --- a/core/module/config/view/backup/backup.php +++ b/core/module/config/view/backup/backup.php @@ -1,14 +1,13 @@
    -
    +
    'buttonGrey', 'href' => helper::baseUrl() . 'config', - 'ico' => 'left', - 'value' => 'Retour' + 'value' => template::ico('left') ]); ?>
    -
    +
    'Sauvegarder', 'uniqueSubmission' => true diff --git a/core/module/config/view/index/index.js.php b/core/module/config/view/index/index.js.php index ee94b0e5..b50acb6d 100644 --- a/core/module/config/view/index/index.js.php +++ b/core/module/config/view/index/index.js.php @@ -10,7 +10,17 @@ * @link http://zwiicms.fr/ */ -$( document).ready(function() { +$(document).ready(function () { + + /** + * Confirmation de suppression + */ + $("#configBackupDelButton").on("click", function () { + var _this = $(this); + return core.confirm("Êtes-vous sûr de vouloir supprimer les sauvegardes automatisées ?", function () { + $(location).attr("href", _this.attr("href")); + }); + }); // Positionnement inital des options //----------------------------------------------------------------------------------------------------- @@ -45,36 +55,36 @@ $( document).ready(function() { $("#connectCaptchaStrongWrapper").addClass("disabled"); $("#connectCaptchaStrongWrapper").slideDown(); $("#connectCaptchaTypeWrapper").addClass("disabled"); - $("#connectCaptchaTypeWrapper").slideDown(); + $("#connectCaptchaTypeWrapper").slideDown(); } else { $("#connectCaptchaStrongWrapper").removeClass("disabled"); $("#connectCaptchaStrongWrapper").slideUp(); $("#connectCaptchaTypeWrapper").removeClass("disabled"); $("#connectCaptchaTypeWrapper").slideUp(); - $( "#connectCaptchaStrong" ).prop( "checked", false ); + $("#connectCaptchaStrong").prop("checked", false); } var configLayout = getCookie("configLayout"); if (configLayout == null) { configLayout = "setup"; - setCookie("configLayout","setup"); + setCookie("configLayout", "setup"); } $("#localeContainer").hide(); $("#socialContainer").hide(); $("#connectContainer").hide(); $("#networkContainer").hide(); $("#setupContainer").hide(); - $("#" + configLayout + "Container" ).show(); + $("#" + configLayout + "Container").show(); $("#config" + capitalizeFirstLetter(configLayout) + "Button").addClass("activeButton"); // Gestion des événements //--------------------------------------------------------------------------------------------------------------------- - /** + /** * Afficher et masquer options smtp */ - $("input[name=smtpEnable]").on("change", function() { + $("input[name=smtpEnable]").on("change", function () { if ($("input[name=smtpEnable]").is(':checked')) { $("#smtpParam").addClass("disabled"); $("#smtpParam").slideDown(); @@ -88,7 +98,7 @@ $( document).ready(function() { * Afficher et masquer options Auth */ - $("select[name=smtpAuth]").on("change", function() { + $("select[name=smtpAuth]").on("change", function () { if ($("select[name=smtpAuth]").val() == true) { $("#smtpAuthParam").addClass("disabled"); $("#smtpAuthParam").slideDown(); @@ -102,7 +112,7 @@ $( document).ready(function() { * Options de blocage de connexions * Contrôle la cohérence des sélections et interdit une seule valeur Aucune */ - $("select[name=connectAttempt]").on("change", function() { + $("select[name=connectAttempt]").on("change", function () { if ($("select[name=connectAttempt]").val() === "999") { $("select[name=connectTimeout]").val(0); } else { @@ -111,7 +121,7 @@ $( document).ready(function() { } } }); - $("select[name=connectTimeout]").on("change", function() { + $("select[name=connectTimeout]").on("change", function () { if ($("select[name=connectTimeout]").val() === "0") { $("select[name=connectAttempt]").val(999); } else { @@ -124,20 +134,20 @@ $( document).ready(function() { /** * Captcha strong si captcha sélectionné */ - $("input[name=connectCaptcha]").on("change", function() { - + $("input[name=connectCaptcha]").on("change", function () { + if ($("input[name=connectCaptcha]").is(':checked')) { $("#connectCaptchaStrongWrapper").addClass("disabled"); $("#connectCaptchaStrongWrapper").slideDown(); $("#connectCaptchaTypeWrapper").addClass("disabled"); - $("#connectCaptchaTypeWrapper").slideDown(); - + $("#connectCaptchaTypeWrapper").slideDown(); + } else { $("#connectCaptchaStrongWrapper").removeClass("disabled"); $("#connectCaptchaStrongWrapper").slideUp(); $("#connectCaptchaTypeWrapper").removeClass("disabled"); $("#connectCaptchaTypeWrapper").slideUp(); - $( "#connectCaptchaStrong" ).prop( "checked", false ); + $("#connectCaptchaStrong").prop("checked", false); } }); @@ -145,7 +155,7 @@ $( document).ready(function() { /** * Sélection de la page de configuration à afficher */ - $("#configSetupButton").on("click", function() { + $("#configSetupButton").on("click", function () { $("#localeContainer").hide(); $("#socialContainer").hide(); $("#connectContainer").hide(); @@ -156,9 +166,9 @@ $( document).ready(function() { $("#configSocialButton").removeClass("activeButton"); $("#configConnectButton").removeClass("activeButton"); $("#configNetworkButton").removeClass("activeButton"); - setCookie("configLayout","setup"); + setCookie("configLayout", "setup"); }); - $("#configLocaleButton").on("click", function() { + $("#configLocaleButton").on("click", function () { $("#setupContainer").hide(); $("#socialContainer").hide(); $("#connectContainer").hide(); @@ -169,9 +179,9 @@ $( document).ready(function() { $("#configSocialButton").removeClass("activeButton"); $("#configConnectButton").removeClass("activeButton"); $("#configNetworkButton").removeClass("activeButton"); - setCookie("configLayout","locale"); + setCookie("configLayout", "locale"); }); - $("#configSocialButton").on("click", function() { + $("#configSocialButton").on("click", function () { $("#connectContainer").hide(); $("#setupContainer").hide(); $("#localeContainer").hide(); @@ -182,9 +192,9 @@ $( document).ready(function() { $("#configSocialButton").addClass("activeButton"); $("#configConnectButton").removeClass("activeButton"); $("#configNetworkButton").removeClass("activeButton"); - setCookie("configLayout","social"); + setCookie("configLayout", "social"); }); - $("#configConnectButton").on("click", function() { + $("#configConnectButton").on("click", function () { $("#setupContainer").hide(); $("#localeContainer").hide(); $("#socialContainer").hide(); @@ -195,9 +205,9 @@ $( document).ready(function() { $("#configSocialButton").removeClass("activeButton"); $("#configConnectButton").addClass("activeButton"); $("#configNetworkButton").removeClass("activeButton"); - setCookie("configLayout","connect"); + setCookie("configLayout", "connect"); }); - $("#configNetworkButton").on("click", function() { + $("#configNetworkButton").on("click", function () { $("#setupContainer").hide(); $("#localeContainer").hide(); $("#socialContainer").hide(); @@ -208,49 +218,49 @@ $( document).ready(function() { $("#configSocialButton").removeClass("activeButton"); $("#configConnectButton").removeClass("activeButton"); $("#configNetworkButton").addClass("activeButton"); - setCookie("configLayout","network"); + setCookie("configLayout", "network"); }); - + /** * Aspect de la souris - */ - $("#socialMetaImage, #socialSiteMap, #configBackupCopyButton").click(function(event) { + */ + $("#socialMetaImage, #socialSiteMap, #configBackupCopyButton").click(function (event) { $('body, .button').css('cursor', 'wait'); }); // Mise en évidence des erreurs de saisie dans les boutons de sélection var containers = ["setup", "locale", "social", "connect", "network"]; - $.each( containers, function( index, value ){ + $.each(containers, function (index, value) { var a = $("div#" + value + "Container").find("input.notice").not(".displayNone"); if (a.length > 0) { - $("#config" + capitalizeFirstLetter(value) + "Button").addClass("buttonNotice"); + $("#config" + capitalizeFirstLetter(value) + "Button").addClass("buttonNotice"); } else { - $("#config" + capitalizeFirstLetter(value) + "Button").removeClass("buttonNotice"); + $("#config" + capitalizeFirstLetter(value) + "Button").removeClass("buttonNotice"); } }); }); -function setCookie(name,value,days) { +function setCookie(name, value, days) { var expires = ""; if (days) { var date = new Date(); - date.setTime(date.getTime() + (days*24*60*60*1000)); + date.setTime(date.getTime() + (days * 24 * 60 * 60 * 1000)); expires = "; expires=" + date.toUTCString(); } - document.cookie = name + "=" + (value || "") + expires + "; path=/; samesite=lax"; + document.cookie = name + "=" + (value || "") + expires + "; path=/; samesite=lax"; } function getCookie(name) { var nameEQ = name + "="; var ca = document.cookie.split(';'); - for(var i=0;i < ca.length;i++) { + for (var i = 0; i < ca.length; i++) { var c = ca[i]; - while (c.charAt(0)==' ') c = c.substring(1,c.length); - if (c.indexOf(nameEQ) == 0) return c.substring(nameEQ.length,c.length); + while (c.charAt(0) == ' ') c = c.substring(1, c.length); + if (c.indexOf(nameEQ) == 0) return c.substring(nameEQ.length, c.length); } return null; } diff --git a/core/module/config/view/index/index.php b/core/module/config/view/index/index.php index 3738b0e0..b7cb0008 100644 --- a/core/module/config/view/index/index.php +++ b/core/module/config/view/index/index.php @@ -1,23 +1,22 @@
    -
    +
    'buttonGrey', 'href' => helper::baseUrl(false), - 'ico' => 'home', - 'value' => 'Accueil' + 'value' => template::ico('home') ]); ?>
    -
    +
    'buttonHelp', 'href' => 'https://doc.zwiicms.fr/configuration-du-site', 'target' => '_blank', - 'ico' => 'help', - 'value' => 'Aide' + 'value' => template::ico('help'), + 'help' => 'Consulter l\'aide en ligne' ]); ?>
    -
    +
    diff --git a/core/module/config/view/restore/restore.php b/core/module/config/view/restore/restore.php index 22a63cc1..5e4ff26d 100644 --- a/core/module/config/view/restore/restore.php +++ b/core/module/config/view/restore/restore.php @@ -38,46 +38,4 @@
    -
    -
    -
    -

    Conversion après la restauration

    -
    -
    - getData(['core', 'baseUrl'])) ) { - $baseUrlValue = 'Pas de donnée dans la sauvegarde'; - $buttonClass = 'disabled'; - } elseif ($this->getData(['core', 'baseUrl']) === '') { - $baseUrlValue = '/'; - $buttonClass = helper::baseUrl(false,false) !== $this->getData(['core', 'baseUrl']) ? '' : 'disabled'; - } else { - $baseUrlValue = str_replace('?','',$this->getData(['core', 'baseUrl'])); - $buttonClass = helper::baseUrl(false,false) !== $baseUrlValue ? '' : 'disabled'; - } - echo template::text('configRestoreBaseURLToConvert', [ - 'label' => 'Dossier de l\'archive' , - 'value' => $baseUrlValue, - 'readonly' => true, - 'help' => 'Le dossier de base du site est stockée dans la sauvegarde.' - ]); ?> -
    -
    - 'Dossier du site actuel', - 'value' => helper::baseUrl(false,false), - 'readonly' => true - ]); ?> -
    -
    - helper::baseUrl() . 'config/updateBaseUrl', - 'class' => $buttonClass, - 'value' => 'convertir' - ]); ?> -
    -
    -
    -
    -
    diff --git a/core/module/config/view/setup/setup.php b/core/module/config/view/setup/setup.php index 97c603c0..20e7e1ff 100644 --- a/core/module/config/view/setup/setup.php +++ b/core/module/config/view/setup/setup.php @@ -118,26 +118,36 @@ ]); ?>
    -
    -
    +
    +
    helper::baseUrl() . 'config/backup', - 'value' => 'Sauvegarder', + 'value' => 'Sauvegarder les données du site', 'ico' => 'download-cloud' ]); ?>
    -
    +
    helper::baseUrl() . 'config/restore', - 'value' => 'Restaurer', + 'value' => 'Restaurer les données du site', 'ico' => 'upload-cloud' ]); ?>
    -
    +
    +
    +
    helper::baseUrl() . 'config/copyBackups', - 'value' => 'Copie sauvegardes auto', - 'ico' => 'download-cloud' + 'value' => 'Copier sauvegardes auto', + 'ico' => 'docs' + ]); ?> +
    +
    + helper::baseUrl() . 'config/delBackups', + 'value' => 'Vider dossier sauvegardes auto', + 'ico' => 'cancel', + 'class' => 'buttonRed' ]); ?>
    diff --git a/core/module/install/ressource/defaultdata.php b/core/module/install/ressource/defaultdata.php index 197d69b5..832c7a26 100644 --- a/core/module/install/ressource/defaultdata.php +++ b/core/module/install/ressource/defaultdata.php @@ -56,7 +56,7 @@ class init extends common { ] ], 'core' => [ - 'dataVersion' => 11300, + 'dataVersion' => 12000, 'lastBackup' => 0, 'lastClearTmp' => 0, 'lastAutoUpdate' => 0, diff --git a/core/module/page/view/edit/edit.php b/core/module/page/view/edit/edit.php index e6a1fa82..abf02ab3 100644 --- a/core/module/page/view/edit/edit.php +++ b/core/module/page/view/edit/edit.php @@ -1,37 +1,36 @@
    -
    +
    getUrl(2); ?> getData(['page', $this->getUrl(2), 'moduleId']) === 'redirection' || 'code')$href = helper::baseUrl(); ?> 'buttonGrey', 'href' => $href, - 'ico' => 'left', - 'value' => 'Retour' + 'value' => template::ico('home') ]); ?>
    -
    +
    'https://doc.zwiicms.fr/edition-des-pages', 'target' => '_blank', - 'ico' => 'help', - 'value' => 'Aide', - 'class' => 'buttonHelp' + 'value' => template::ico('help'), + 'class' => 'buttonHelp', + 'help' => 'Consulter l\'aide en ligne' ]); ?>
    -
    - helper::baseUrl() . 'page/duplicate/' . $this->getUrl(2) . '&csrf=' . $_SESSION['csrf'], - 'value' => 'Dupliquer', - 'ico' => 'clone' - ]); ?> -
    -
    +
    'buttonRed', 'href' => helper::baseUrl() . 'page/delete/' . $this->getUrl(2) . '&csrf=' . $_SESSION['csrf'], - 'value' => 'Supprimer', - 'ico' => 'cancel' + 'value' => template::ico('cancel'), + 'help' => 'Effacer la page' + ]); ?> +
    +
    + helper::baseUrl() . 'page/duplicate/' . $this->getUrl(2) . '&csrf=' . $_SESSION['csrf'], + 'value' => template::ico('clone'), + 'help' => 'Dupliquer la page' ]); ?>
    diff --git a/core/module/plugin/plugin.php b/core/module/plugin/plugin.php new file mode 100644 index 00000000..436d3e37 --- /dev/null +++ b/core/module/plugin/plugin.php @@ -0,0 +1,750 @@ + + * @copyright Copyright (C) 2008-2018, Rémi Jean + * @author Frédéric Tempez + * @copyright Copyright (C) 2020-2021, Sylvain Lelièvre + * @copyright Copyright (C) 2018-2022, Frédéric Tempez + * @author Sylvain Lelièvre + * @license GNU General Public License, version 3 + * @link http://zwiicms.fr/ + */ + +class plugin extends common { + + public static $actions = [ + 'index' => self::GROUP_ADMIN, + 'delete' => self::GROUP_ADMIN, + 'save' => self::GROUP_ADMIN, // Sauvegarde le module dans un fichier ZIP ou dans le gestionnaire + 'dataExport' => self::GROUP_ADMIN, // Fonction muette d'exportation + 'dataImport' => self::GROUP_ADMIN, // les données d'un module + 'dataDelete' => self::GROUP_ADMIN, + 'store' => self::GROUP_ADMIN, + 'item' => self::GROUP_ADMIN, // détail d'un objet + 'upload' => self::GROUP_ADMIN, // Téléverser catalogue + 'uploadItem'=> self::GROUP_ADMIN // Téléverser par archive + ]; + + // URL des modules + const BASEURL_STORE = 'https://store.zwiicms.fr/'; + const MODULE_STORE = '?modules/'; + + // Gestion des modules + public static $modulesData = []; + public static $modulesOrphan = []; + public static $modulesInstalled = []; + + // pour tests + public static $valeur = []; + + // le catalogue + public static $storeList = []; + public static $storeItem = []; + + // Liste de pages + public static $pagesList = []; + + + /* + * Effacement d'un module installé et non utilisé + */ + public function delete() { + + // Jeton incorrect + if ($this->getUrl(3) !== $_SESSION['csrf']) { + // Valeurs en sortie + $this->addOutput([ + 'redirect' => helper::baseUrl() . 'plugin', + 'state' => false, + 'notification' => 'Action non autorisée' + ]); + } + else{ + // Suppression des dossiers + $infoModules = helper::getModules(); + $module = $this->getUrl(2); + //Liste des dossiers associés au module non effacés + if( $this->removeDir('./module/'.$module ) === true ){ + $success = true; + $notification = 'Module '. $module .' désinstallé'; + if(($infoModules[$this->getUrl(2)]['dataDirectory']) ) { + if ( + is_dir($infoModules[$this->getUrl(2)]['dataDirectory']) + && !$this->removeDir($infoModules[$this->getUrl(2)]['dataDirectory']) + ){ + $notification = 'Module '.$module .' désinstallé, il reste des données dans ' . $infoModules[$this->getUrl(2)]['dataDirectory']; + } + } + } + else{ + $success = false; + $notification = 'La suppression a échouée'; + } + + // Valeurs en sortie + $this->addOutput([ + 'redirect' => helper::baseUrl() . 'plugin', + 'notification' => $notification, + 'state' => $success + ]); + } + } + + /*** + * Installation d'un module + * Fonction utilisée par upload et storeUpload + */ + private function install ($moduleName, $checkValid){ + $tempFolder = 'datamodules';//uniqid(); + $zip = new ZipArchive(); + if ($zip->open($moduleName) === TRUE) { + $notification = 'Archive ouverte'; + mkdir (self::TEMP_DIR . $tempFolder, 0755); + $zip->extractTo(self::TEMP_DIR . $tempFolder ); + // Archive de module ? + $success = false; + $notification = 'Ce n\'est pas l\'archive d\'un module !'; + $moduleDir = self::TEMP_DIR . $tempFolder . '/module'; + $moduleName = ''; + if ( is_dir( $moduleDir )) { + // Lire le nom du module + if ($dh = opendir( $moduleDir )) { + while ( false !== ($file = readdir($dh)) ) { + if ($file != "." && $file != "..") { + $moduleName = $file; + } + } + closedir($dh); + } + // Module normalisé ? + if( is_file( $moduleDir.'/'.$moduleName.'/'.$moduleName.'.php' ) AND is_file( $moduleDir.'/'.$moduleName.'/view/index/index.php' ) ){ + + // Lecture de la version et de la validation d'update du module pour validation de la mise à jour + // Pour une version <= version installée l'utilisateur doit cocher 'Mise à jour forcée' + $version = '0.0'; + $update = '0.0'; + $valUpdate = false; + $file = file_get_contents( $moduleDir.'/'.$moduleName.'/'.$moduleName.'.php'); + $file = str_replace(' ','',$file); + $file = str_replace("\t",'',$file); + $pos1 = strpos($file, 'constVERSION'); + if( $pos1 !== false){ + $posdeb = strpos($file, "'", $pos1); + $posend = strpos($file, "'", $posdeb + 1); + $version = substr($file, $posdeb + 1, $posend - $posdeb - 1); + } + $pos1 = strpos($file, 'constUPDATE'); + if( $pos1 !== false){ + $posdeb = strpos($file, "'", $pos1); + $posend = strpos($file, "'", $posdeb + 1); + $update = substr($file, $posdeb + 1, $posend - $posdeb - 1); + } + // Si version actuelle >= version indiquée dans UPDATE la mise à jour est validée + $infoModules = helper::getModules(); + if( $infoModules[$moduleName]['update'] >= $update ) $valUpdate = true; + + // Module déjà installé ? + $moduleInstal = false; + foreach($infoModules as $key=>$value ){ + if($moduleName === $key){ + $moduleInstal = true; + } + } + + // Validation de la maj si autorisation du concepteur du module ET + // ( Version plus récente OU Check de forçage ) + $valNewVersion = floatval($version); + $valInstalVersion = floatval( $infoModules[$moduleName]['version'] ); + $newVersion = false; + if( $valNewVersion > $valInstalVersion ) $newVersion = true; + $validMaj = $valUpdate && ( $newVersion || $checkValid); + + // Nouvelle installation ou mise à jour du module + if( ! $moduleInstal || $validMaj ){ + // Copie récursive des dossiers + $this->copyDir( self::TEMP_DIR . $tempFolder, './' ); + $success = true; + if( ! $moduleInstal ){ + $notification = 'Module '.$moduleName.' installé'; + } + else{ + $notification = 'Module '.$moduleName.' mis à jour'; + } + } + else{ + $success = false; + if( $valNewVersion == $valInstalVersion){ + $notification = ' Version détectée '.$version.' = à celle installée '.$infoModules[$moduleName]['version']; + } + else{ + $notification = ' Version détectée '.$version.' < à celle installée '.$infoModules[$moduleName]['version']; + } + if( $valUpdate === false){ + if( $infoModules[$moduleName]['update'] === $update ){ + $notification = ' Mise à jour par ce procédé interdite par le concepteur du module'; + } + else{ + $notification = ' Mise à jour par ce procédé interdite, votre version est trop ancienne'; + } + } + } + } + } + // Supprimer le dossier temporaire même si le module est invalide + $this->removeDir(self::TEMP_DIR . $tempFolder); + $zip->close(); + } else { + // erreur à l'ouverture + $success = false; + $notification = 'Impossible d\'ouvrir l\'archive'; + } + return(['success' => $success, + 'notification'=> $notification + ]); + } + + /*** + * Installation d'un module à partir du gestionnaire de fichier + */ + public function upload() { + // Soumission du formulaire + if($this->isPost()) { + // Installation d'un module + $checkValidMaj = $this->getInput('configModulesCheck', helper::FILTER_BOOLEAN); + $zipFilename = $this->getInput('configModulesInstallation', helper::FILTER_STRING_SHORT); + if( $zipFilename !== ''){ + $success = [ + 'success' => false, + 'notification'=> '' + ]; + $state = $this->install(self::FILE_DIR.'source/'.$zipFilename, $checkValidMaj); + } + $this->addOutput([ + 'redirect' => helper::baseUrl() . 'plugin', + 'notification' => $state['notification'], + 'state' => $state['success'] + ]); + } + // Valeurs en sortie + $this->addOutput([ + 'title' => 'Téléverser un module', + 'view' => 'upload' + ]); + } + + /*** + * Installation d'un module depuis le catalogue + */ + public function uploadItem() { + // Jeton incorrect + if ($this->getUrl(3) !== $_SESSION['csrf']) { + // Valeurs en sortie + $this->addOutput([ + 'redirect' => helper::baseUrl() . 'store', + 'state' => false, + 'notification' => 'Action non autorisée' + ]); + } else { + // Récupérer le module en ligne + $moduleName = $this->getUrl(2); + // Informations sur les module en ligne + $store = json_decode(helper::urlGetContents(self::BASEURL_STORE . self::MODULE_STORE . 'list'), true); + // Url du module à télécharger + $moduleFilePath = $store[$moduleName]['file']; + // Télécharger le fichier + $moduleData = helper::urlGetContents(self::BASEURL_STORE . self::FILE_DIR . 'source/' . $moduleFilePath); + // Extraire de l'arborescence + $d = explode('/',$moduleFilePath); + $moduleFile = $d[count($d)-1]; + // Créer le dossier modules + if (!is_dir(self::FILE_DIR . 'source/modules')) { + mkdir (self::FILE_DIR . 'source/modules', 0755); + } + // Sauver les données du fichiers + file_put_contents(self::FILE_DIR . 'source/modules/' . $moduleFile, $moduleData); + + /** + * $if( $moduleFile !== ''){ + * $success = [ + * 'success' => false, + * 'notification'=> '' + * ]; + * $state = $this->install(self::FILE_DIR.'source/modules/'.$moduleFile, false); + *} + */ + $this->addOutput([ + 'redirect' => helper::baseUrl() . 'plugin/store', + 'notification' => $moduleFile . ' téléchargé dans le dossier modules du gestionnaire de fichiers', + 'state' => true + ]); + + } + // Valeurs en sortie + $this->addOutput([ + 'title' => 'Catalogue de modules', + 'view' => 'store' + ]); + } + + /** + * Catalogue des modules sur le site ZwiiCMS.fr + */ + public function store() { + $store = json_decode(helper::urlGetContents(self::BASEURL_STORE . self::MODULE_STORE . 'list'), true); + if ($store) { + // Modules installés + $infoModules = helper::getModules(); + // Clés moduleIds dans les pages + $inPages = helper::arrayCollumn($this->getData(['page']),'moduleId', 'SORT_DESC'); + foreach( $inPages as $key=>$value){ + $pagesInfos[ $this->getData(['page', $key, 'title' ]) ] = $value; + } + // Parcourir les données des modules + foreach ($store as $key=>$value) { + // Module non installé + $ico = template::ico('download'); + $class = ''; + $help = 'Télécharger le module'; + // Le module est installé + if (array_key_exists($key,$infoModules) === true) { + $class = 'buttonGreen'; + $ico = template::ico('update'); + $help = 'Mettre à jour ce module'; + } + // Le module est installé et utilisé + if (in_array($key,$inPages) === true) { + $class = 'buttonRed'; + $ico = template::ico('update'); + $help = 'Mettre à jour le module'; + } + self::$storeList [] = [ + $store[$key]['category'], + ''.$store[$key]['title'].'', + $store[$key]['version'], + mb_detect_encoding(strftime('%d %B %Y', $store[$key]['versionDate']), 'UTF-8', true) + ? strftime('%d %B %Y', $store[$key]['versionDate']) + : utf8_encode(strftime('%d %B %Y', $store[$key]['versionDate'])), + implode(', ', array_keys($pagesInfos,$key)), + template::button('moduleExport' . $key, [ + 'class' => $class, + 'href' => helper::baseUrl(). $this->getUrl(0) . '/uploadItem/' . $key.'/' . $_SESSION['csrf'],// appel de fonction vaut exécution, utiliser un paramètre + 'value' => $ico, + 'help' => $help + ]) + ]; + } + } + + // Valeurs en sortie + $this->addOutput([ + 'title' => 'Catalogue de modules en ligne', + 'view' => 'store' + ]); + } + + /** + * Détail d'un objet du catalogue + */ + public function item() { + $store = json_decode(helper::urlGetContents(self::BASEURL_STORE . self::MODULE_STORE . 'list'), true); + self::$storeItem = $store [$this->getUrl(2)] ; + self::$storeItem ['fileDate'] = mb_detect_encoding(strftime('%d %B %Y',self::$storeItem ['fileDate']), 'UTF-8', true) + ? strftime('%d %B %Y', self::$storeItem ['fileDate']) + : utf8_encode(strftime('%d %B %Y', self::$storeItem ['fileDate'])); + // Valeurs en sortie + $this->addOutput([ + 'title' =>'Module ' . self::$storeItem['title'], + 'view' => 'item' + ]); + } + + /** + * Gestion des modules + */ + public function index() { + + // Tableau des langues rédigées + foreach (self::$i18nList as $key => $value) { + if ($this->getData(['config','i18n', $key]) === 'site' || + $key === 'fr') { + $i18nSites[$key] = $value; + } + } + // Lister les modules installés + $infoModules = helper::getModules(); + + // Parcourir les langues du site traduit et recherche les modules affectés à des pages + foreach ($i18nSites as $keyi18n=>$valuei18n) { + + // Clés moduleIds dans les pages de la langue + $pages = json_decode(file_get_contents(self::DATA_DIR . $keyi18n . '/' . 'page.json'), true); + + // Extraire les clés des modules + $pagesModules [$keyi18n] = array_filter(helper::arrayCollumn($pages['page'],'moduleId', 'SORT_DESC'), 'strlen'); + + // Générer ls liste des pages avec module pour la sauvegarde ou le backup + foreach( $pagesModules [$keyi18n] as $key=>$value ) { + if (!empty($value)) { + $pagesInfos [$keyi18n] [$key] ['pageId'] = $key ; + $pagesInfos [$keyi18n] [$key] ['title'] = $this->getData(['page', $key, 'title' ]) ; + $pagesInfos [$keyi18n] [$key] ['moduleId'] = $value; + } + } + } + + + // Recherche des modules orphelins dans toutes les langues + $orphans = $installed = array_flip(array_keys ($infoModules)); + foreach ($i18nSites as $keyi18n=>$valuei18n) { + // Générer la liste des modules orphelins + foreach ($infoModules as $key=>$value) { + // Supprimer les éléments affectés + if (array_search($key, $pagesModules[$keyi18n]) ) { + unset($orphans [$key]); + } + + } + } + $orphans = array_flip($orphans); + + // Mise en forme du tableau des modules orphelins + if (isset($orphans)) { + foreach ($orphans as $key) { + // Construire le tableau de sortie + self::$modulesOrphan [] = [ + $infoModules [$key] ['realName'], + $key, + $infoModules [$key] ['version'], + '', + $infoModules[$key] ['delete'] === true + ? template::button('moduleDelete' . $key, [ + 'class' => 'moduleDelete buttonRed', + 'href' => helper::baseUrl() . $this->getUrl(0) . '/delete/' .$key . '/' . $_SESSION['csrf'], + 'value' => template::ico('cancel'), + 'help' => 'Supprimer le module' + ]) + : '', + + ]; + } + } + + // Modules installés non orphelins + // Mise en forme du tableau des modules utilisés + if (isset($installed)) { + foreach (array_flip($installed) as $key) { + // Construire le tableau de sortie + self::$modulesInstalled [] = [ + $infoModules [$key] ['realName'], + $key, + $infoModules [$key] ['version'], + '', + template::button('moduleSave' . $key, [ + 'href' => helper::baseUrl() . $this->getUrl(0) . '/save/filemanager/' .$key . '/' . $_SESSION['csrf'], + 'value' => template::ico('download-cloud'), + 'help' => 'Sauvegarder le module dans le gestionnaire de fichiers' + ]), + template::button('moduleDownload' . $key, [ + 'href' => helper::baseUrl() . $this->getUrl(0) . '/save/download/' .$key . '/' . $_SESSION['csrf'], + 'value' => template::ico('download'), + 'help' => 'Sauvegarder et télécharger le module' + ]) + + ]; + } + } + + + // Mise en forme du tableau des modules employés dans les pages + // Avec les commandes de sauvegarde et de restauration + //foreach ($pagesInfos as $keyi18n=>$valueI18n) { + + $keyi18n = self::$i18n; + $valueI18n = $pagesInfos[self::$i18n]; + foreach ($valueI18n as $keyPage=>$value) { + // Construire le tableau de sortie + self::$modulesData[] = [ + $infoModules[$pagesInfos[$keyi18n][$keyPage]['moduleId']] ['realName'], + $pagesInfos[$keyi18n][$keyPage]['moduleId'], + $infoModules[$pagesInfos [$keyi18n][$keyPage]['moduleId']] ['version'], + //template::flag($keyi18n, '20px'), + '' . $pagesInfos [$keyi18n][$keyPage]['title'] . ' (' .$keyPage . ')', + template::button('dataExport' . $keyPage, [ + 'href' => helper::baseUrl(). $this->getUrl(0) . '/dataExport/' . $keyi18n . '/' . $pagesInfos[$keyi18n][$keyPage]['moduleId'] . '/' . $keyPage . '/' . $_SESSION['csrf'],// appel de fonction vaut exécution, utiliser un paramètre + 'value' => template::ico('download'), + 'help' => 'Exporter les données du module' + ]), + template::button('dataDelete' . $keyPage, [ + 'href' => helper::baseUrl(). $this->getUrl(0) . '/dataDelete/' . $keyi18n . '/' . $pagesInfos[$keyi18n][$keyPage]['moduleId'] . '/' . $keyPage . '/' . $_SESSION['csrf'],// appel de fonction vaut exécution, utiliser un paramètre + 'value' => template::ico('cancel'), + 'class' => 'buttonRed dataDelete', + 'help' => 'Détacher le module de la page', + ]) + + ]; + } + + //} + + // Valeurs en sortie + $this->addOutput([ + 'title' => 'Gestion des modules', + 'view' => 'index' + ]); + } + + + /** + * Sauvegarde un module sans les données + */ + + public function save() { + // Jeton incorrect + if ($this->getUrl(4) !== $_SESSION['csrf']) { + // Valeurs en sortie + $this->addOutput([ + 'redirect' => helper::baseUrl() . 'plugin', + 'state' => false, + 'notification' => 'Action non autorisée' + ]); + } else { + + // Créer un dossier temporaire + $tmpFolder = self::TEMP_DIR . uniqid(); + if (!is_dir($tmpFolder)) { + mkdir($tmpFolder, 0755); + } + + //Nom de l'archive + $fileName = $this->getUrl(3) . '.zip'; + $this->makeZip ($tmpFolder . '/' . $fileName, 'module/' . $this->getUrl(3)); + + switch ($this->getUrl(2)) { + case 'filemanager': + if (!file_exists(self::FILE_DIR . 'source/modules')) { + mkdir(self::FILE_DIR . 'source/modules'); + } + $success = copy($tmpFolder . '/' . $fileName , self::FILE_DIR . 'source/modules/' . $this->getUrl(3) . '.zip' ); + + // Valeurs en sortie + $this->addOutput([ + 'redirect' => helper::baseUrl() . 'plugin', + 'notification' => $success ? $this->getUrl(3) . '.zip copié dans le dossier Module du gestionnaire de fichier' : 'Erreur de copie', + 'state' => $success + ]); + break; + case 'download': + default: + header('Content-Type: application/octet-stream'); + header('Content-Disposition: attachment; filename="' . $fileName . '"'); + header('Content-Length: ' . filesize($tmpFolder . '/' . $fileName)); + ob_clean(); + ob_end_flush(); + readfile( $tmpFolder . '/' .$fileName); + exit(); + break; + } + // Nettoyage + unlink($tmpFolder . '/' . $fileName); + $this->removeDir($tmpFolder); + } + } + + + /* + * Détacher un module d'une page en supprimant les données du module + * 2 : i18n id + * 3 : moduleId + * 4 : pageId + * 5 : CSRF + */ + public function dataDelete() { + // Jeton incorrect + if ($this->getUrl(5) !== $_SESSION['csrf']) { + // Valeurs en sortie + $this->addOutput([ + 'redirect' => helper::baseUrl() . 'plugin', + 'state' => false, + 'notification' => 'Action non autorisée' + ]); + } else { + $this->setData(['page', $this->getUrl(4), 'moduleId', '']); + $this->deleteData(['module', $this->getUrl(4)]); + // Valeurs en sortie + $this->addOutput([ + 'redirect' => helper::baseUrl() . 'plugin', + 'notification' => 'Le module ' . $this->getUrl(3) . ' de la page '. $this->getUrl(4) . ' a été supprimé.', + 'state' => true + ]); + } + + + } + + + /* + * Export des données d'un module + * Structure de l'adresse reçue + * 2 : i18n id + * 3 : moduleId + * 4 : pageId + * 5 : CSRF + */ + public function dataExport() { + // Jeton incorrect + if ($this->getUrl(5) !== $_SESSION['csrf']) { + // Valeurs en sortie + $this->addOutput([ + 'redirect' => helper::baseUrl() . 'plugin', + 'state' => false, + 'notification' => 'Action non autorisée' + ]); + } else { + + // Créer un dossier temporaire + $tmpFolder = self::TEMP_DIR . uniqid(); + if (!is_dir($tmpFolder)) { + mkdir($tmpFolder, 0755); + } + + + // Copie des infos sur le module + $modulesData = json_decode(file_get_contents(self::DATA_DIR . $this->getUrl(2) . '/module.json' ), true); + $moduleData = $modulesData['module'] [$this->getUrl(4)]; + $success = file_put_contents ($tmpFolder . '/module.json', json_encode($moduleData)); + + // Le dossier du module s'il existe + if (is_dir(self::DATA_DIR . $this->getUrl(3) . '/' . $this->getUrl(4) ) ) { + // Copier le dossier des données + $success .= $this->copyDir(self::DATA_DIR . $this->getUrl(3) . '/' . $this->getUrl(4), $tmpFolder); + } + + // Descripteur de l'archive + $infoModule = helper::getModules(); + $success .= file_put_contents ($tmpFolder . '/descripteur.json', json_encode( [$this->getUrl(3) => $infoModule [$this->getUrl(3)]] )); + + + // création du zip + if ($success) + { + $fileName = $this->getUrl(2) . '-' . $this->getUrl(3) . '-' . $this->getUrl(4) . '.zip'; + $this->makeZip ($fileName, $tmpFolder); + if (file_exists($fileName)) { + ob_start(); + header('Content-Type: application/octet-stream'); + header('Content-Disposition: attachment; filename="' . $fileName . '"'); + header('Content-Length: ' . filesize($fileName)); + ob_clean(); + ob_end_flush(); + readfile( $fileName); + unlink($fileName); + $this->removeDir($tmpFolder); + exit(); + } + } else { + // Valeurs en sortie + $this->addOutput([ + 'redirect' => helper::baseUrl() . 'plugin', + 'notification' => 'Quelque chose s\'est mal passé', + 'state' => false + ]); + } + } + } + + /* + * Importer des données d'un module externes ou interne à module.json + */ + public function dataImport(){ + + // Soumission du formulaire d'importation du module dans une page libre + if($this->isPost()) { + // Récupérer le fichier et le décompacter + $zipFilename = $this->getInput('pluginImportFile', helper::FILTER_STRING_SHORT, true); + $targetPage = $this->getInput('pluginImportPage', helper::FILTER_STRING_SHORT, true); + $tempFolder = uniqid(); + + // Extraction dans un dossier temporaire + mkdir (self::TEMP_DIR . $tempFolder, 0755); + $zip = new ZipArchive(); + if ($zip->open(self::FILE_DIR . 'source/' . $zipFilename) === TRUE) { + $zip->extractTo(self::TEMP_DIR . $tempFolder ); + } + + // Lire le descripteur + $descripteur = json_decode(file_get_contents(self::TEMP_DIR . $tempFolder . '/descripteur.json'), true); + + // Lecture des données du module + $moduleData = json_decode(file_get_contents(self::TEMP_DIR . $tempFolder . '/module.json'), true ); + // Chargement des données du module importé + $this->setData(['module', $targetPage, $moduleData ]); + // Intégration des données du module importé dans la page + $this->setData(['page', $targetPage ,'moduleId', array_key_first($descripteur) ]); + + // Supprimer le dossier temporaire + $this->removeDir(self::TEMP_DIR . $tempFolder); + $zip->close(); + + + + // Valeurs en sortie + $this->addOutput([ + 'redirect' => helper::baseUrl() . 'plugin', + 'state' => true, + 'notification' => 'Import des données effectué' + ]); + } + // Bouton d'importation des données d'un module spécifique + if (count(explode('/',$this->getUrl())) === 6) { + // Jeton incorrect + if ($this->getUrl(3) !== $_SESSION['csrf']) { + // Valeurs en sortie + $this->addOutput([ + 'redirect' => helper::baseUrl() . 'plugin', + 'state' => false, + 'notification' => 'Action non autorisée' + ]); + } + + // Traitement + + // Valeurs en sortie + $this->addOutput([ + 'redirect' => helper::baseUrl() . 'plugin', + 'state' => true, + 'notification' => 'Okay' + ]); + } + + + /** + * Liste des pages sans module + * et ne sont pas des barres latérales + */ + self::$pagesList = $this->getHierarchy(null, null, null); + foreach(self::$pagesList as $page => $pageId) { + if ($this->getData(['page',$page,'block']) === 'bar' || + //$this->getData(['page',$page,'disable']) === true || + $this->getData(['page',$page,'moduleId']) !== '' + ) { + unset(self::$pagesList[$page]); + } + } + self::$pagesList = array_keys(self::$pagesList); + + // Valeurs en sortie + $this->addOutput([ + 'title' => 'Importer des données de module', + 'view' => 'dataImport' + ]); + } + + + +} diff --git a/core/module/addon/view/import/import.css b/core/module/plugin/view/dataImport/dataImport.css similarity index 100% rename from core/module/addon/view/import/import.css rename to core/module/plugin/view/dataImport/dataImport.css diff --git a/core/module/plugin/view/dataImport/dataImport.php b/core/module/plugin/view/dataImport/dataImport.php new file mode 100644 index 00000000..43b00552 --- /dev/null +++ b/core/module/plugin/view/dataImport/dataImport.php @@ -0,0 +1,35 @@ + +
    +
    + 'buttonGrey', + 'href' => helper::baseUrl() . 'plugin', + 'value' => template::ico('left') + ]); ?> +
    +
    + 'Appliquer' + ]); ?> +
    +
    +
    +
    +
    +

    Installer des données de module

    +
    +
    + 'Archive ZIP :', + 'type' => 2 + ]); ?> +
    +
    + 'Importer le module dans la page ' . template::flag('site', '20px') + ]); ?> +
    +
    +
    +
    +
    \ No newline at end of file diff --git a/core/module/addon/view/index/index.js.php b/core/module/plugin/view/index/index.css similarity index 64% rename from core/module/addon/view/index/index.js.php rename to core/module/plugin/view/index/index.css index 4dd572cc..fdb57b6f 100644 --- a/core/module/addon/view/index/index.js.php +++ b/core/module/plugin/view/index/index.css @@ -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,12 +12,11 @@ * @link http://zwiicms.fr/ */ -/** - * Confirmation de suppression - */ -$(".moduleDelete").on("click", function() { - var _this = $(this); - return core.confirm("Êtes-vous sûr de vouloir supprimer ce module ?", function() { - $(location).attr("href", _this.attr("href")); - }); -}); \ No newline at end of file + +/** NE PAS EFFACER +* admin.css +*/ + +.activeButton { + filter : brightness(150%); +} \ No newline at end of file diff --git a/core/module/plugin/view/index/index.js.php b/core/module/plugin/view/index/index.js.php new file mode 100644 index 00000000..060d7e18 --- /dev/null +++ b/core/module/plugin/view/index/index.js.php @@ -0,0 +1,50 @@ +/** + * 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 + * @copyright Copyright (C) 2008-2018, Rémi Jean + * @author Frédéric Tempez + * @copyright Copyright (C) 2018-2022, Frédéric Tempez + * @license GNU General Public License, version 3 + * @link http://zwiicms.fr/ + */ + +/** + * Confirmation de suppression + */ +$(".moduleDelete").on("click", function() { + var _this = $(this); + return core.confirm("Êtes-vous sûr de vouloir désinstaller ce module ?", function() { + $(location).attr("href", _this.attr("href")); + }); +}); + +/** + * Confirmation de suppression + */ + $(".dataDelete").on("click", function() { + var _this = $(this); + return core.confirm("Êtes-vous sûr de vouloir supprimer le module de cette page ?", function() { + $(location).attr("href", _this.attr("href")); + }); +}); + +// Sélecteur de fonctions + +$("#configManageModuleButton").on("click", function () { + console.log("clic"); + $("#manageDatas").hide(); + $("#manageModules").show(); + $("#configManageModuleButton").addClass("activeButton"); + $("#configManageDatasButton").removeClass("activeButton"); + setCookie("pluginLayout", "module"); +}); +$("#configManageDatasButton").on("click", function () { + $("#manageModules").hide(); + $("#manageDatas").show(); + $("#configManageModuleButton").removeClass("activeButton"); + $("#configManageDatasButton").addClass("activeButton"); + setCookie("pluginLayout", "data"); +}); diff --git a/core/module/plugin/view/index/index.php b/core/module/plugin/view/index/index.php new file mode 100644 index 00000000..24ca3fe7 --- /dev/null +++ b/core/module/plugin/view/index/index.php @@ -0,0 +1,105 @@ +
    +
    + 'buttonGrey', + 'href' => helper::baseUrl(), + 'value' => template::ico('left') + ]); ?> +
    +
    + 'https://doc.zwiicms.fr/gestion-des-modules', + 'target' => '_blank', + 'value' => template::ico('help'), + 'class' => 'buttonHelp', + 'help' => 'Consulter l\'aide en ligne' + ]); ?> +
    +
    +
    +
    +
    +
    + 'Modules installés', + 'class' => 'activeButton' + ]); ?> +
    +
    + 'Données des modules' + ]); ?> +
    +
    +
    +
    +
    +
    +
    +
    +

    Installation / mise à jour d'un module

    +
    +
    + helper::baseUrl() . 'plugin/store', + 'value' => template::ico('shopping-basket') . ' Catalogue en ligne' + ]); ?> +
    +
    + helper::baseUrl() . 'plugin/upload', + 'value' => template::ico('upload') . ' Depuis une archive ZIP' + ]); ?> +
    +
    +
    +
    +
    + +
    +
    +
    +

    Sauvegarde des modules installés

    + +
    +
    +
    + + + + +
    +
    +
    +

    Désinstallation des modules orphelins

    + +
    +
    +
    + +
    +
    + +
    +
    +
    +

    Modules configurés

    +
    +
    + helper::baseUrl() . 'plugin/dataImport', + 'value' => template::ico('upload'), + "help" => 'Importer des données de module dans une page libre' + ]); ?> +
    +
    +
    +
    + +
    +
    +
    +
    +
    + +
    \ No newline at end of file diff --git a/core/module/addon/view/item/item.css b/core/module/plugin/view/item/item.css similarity index 100% rename from core/module/addon/view/item/item.css rename to core/module/plugin/view/item/item.css diff --git a/core/module/addon/view/item/item.php b/core/module/plugin/view/item/item.php similarity index 100% rename from core/module/addon/view/item/item.php rename to core/module/plugin/view/item/item.php diff --git a/core/module/addon/view/store/store.css b/core/module/plugin/view/store/store.css similarity index 100% rename from core/module/addon/view/store/store.css rename to core/module/plugin/view/store/store.css diff --git a/core/module/plugin/view/store/store.php b/core/module/plugin/view/store/store.php new file mode 100644 index 00000000..f06bf536 --- /dev/null +++ b/core/module/plugin/view/store/store.php @@ -0,0 +1,14 @@ +
    +
    + 'buttonGrey', + 'href' => helper::baseUrl() . 'plugin', + 'value' => template::ico('left') + ]); ?> +
    +
    + + + + + \ No newline at end of file diff --git a/core/module/addon/view/upload/upload.css b/core/module/plugin/view/upload/upload.css similarity index 100% rename from core/module/addon/view/upload/upload.css rename to core/module/plugin/view/upload/upload.css diff --git a/core/module/addon/view/upload/upload.php b/core/module/plugin/view/upload/upload.php similarity index 70% rename from core/module/addon/view/upload/upload.php rename to core/module/plugin/view/upload/upload.php index 016418c6..c4104450 100644 --- a/core/module/addon/view/upload/upload.php +++ b/core/module/plugin/view/upload/upload.php @@ -1,30 +1,27 @@
    -
    +
    'buttonGrey', - 'href' => helper::baseUrl() . 'addon', - 'ico' => 'left', - 'value' => 'Retour' + 'href' => helper::baseUrl() . 'plugin', + 'value' => template::ico('left') ]); ?>
    -
    - + 'https://doc.zwiicms.fr/installation-d-un-module', + 'target' => '_blank', 'class' => 'buttonHelp', - 'ico' => 'help', - 'value' => 'Aide' + 'value' => template::ico('help'), + 'help' => 'Consulter l\'aide en ligne' ]); ?>
    -
    +
    'Valider', 'ico' => 'check' ]); ?>
    -
    - -
    -
    diff --git a/core/module/theme/view/fonts/fonts.php b/core/module/theme/view/fonts/fonts.php index ea71d1bf..be517eb6 100644 --- a/core/module/theme/view/fonts/fonts.php +++ b/core/module/theme/view/fonts/fonts.php @@ -19,4 +19,4 @@ - \ No newline at end of file + diff --git a/core/module/translate/view/copy/copy.php b/core/module/translate/view/copy/copy.php index 4cb9e1fd..890128b8 100644 --- a/core/module/translate/view/copy/copy.php +++ b/core/module/translate/view/copy/copy.php @@ -1,15 +1,16 @@
    -
    +
    'buttonGrey', 'href' => helper::baseUrl() . 'translate', - 'ico' => 'left', - 'value' => 'Retour' + 'value' => template::ico('left') ]); ?>
    -
    - +
    + 'Copier' + ]); ?>
    diff --git a/core/module/translate/view/index/index.php b/core/module/translate/view/index/index.php index 69821aaa..fabc4e6a 100644 --- a/core/module/translate/view/index/index.php +++ b/core/module/translate/view/index/index.php @@ -1,28 +1,27 @@
    -
    +
    'buttonGrey', 'href' => helper::baseUrl(), - 'ico' => 'left', - 'value' => 'Retour' + 'value' => template::ico('left') ]); ?>
    -
    +
    'https://doc.zwiicms.fr/prise-en-charge-des-langues-etrangeres', 'target' => '_blank', - 'ico' => 'help', - 'value' => 'Aide', - 'class' => 'buttonHelp' + 'value' => template::ico('help'), + 'class' => 'buttonHelp', + 'help' => 'Consulter l\'aide en ligne' ]); ?>
    -
    +
    helper::baseUrl() . 'translate/copy', - 'value' => 'Utilitaire de copie', - 'ico' => 'cog-alt', - 'disabled' => $module::$siteTranslate + 'value' => template::ico('docs'), + 'disabled' => $module::$siteTranslate, + 'help' => 'Copie de sites inter-langues' ]); ?>
    diff --git a/core/module/user/user.php b/core/module/user/user.php index 82a22882..dab81c76 100644 --- a/core/module/user/user.php +++ b/core/module/user/user.php @@ -346,12 +346,14 @@ class user extends common { self::$groups[$this->getData(['user', $userId, 'group'])], template::button('userEdit' . $userId, [ 'href' => helper::baseUrl() . 'user/edit/' . $userId . '/back/'. $_SESSION['csrf'], - 'value' => template::ico('pencil') + 'value' => template::ico('pencil'), + 'help' => 'Editer ' . $userId ]), template::button('userDelete' . $userId, [ 'class' => 'userDelete buttonRed', 'href' => helper::baseUrl() . 'user/delete/' . $userId. '/' . $_SESSION['csrf'], - 'value' => template::ico('cancel') + 'value' => template::ico('cancel'), + 'help' => 'Supprimer ' . $userId ]) ]; } diff --git a/core/module/user/view/add/add.php b/core/module/user/view/add/add.php index d84c8ed1..bd806a49 100644 --- a/core/module/user/view/add/add.php +++ b/core/module/user/view/add/add.php @@ -1,14 +1,13 @@
    -
    +
    'buttonGrey', 'href' => helper::baseUrl() . 'user', - 'ico' => 'left', - 'value' => 'Retour' + 'value' => template::ico('left') ]); ?>
    -
    +
    diff --git a/core/module/user/view/edit/edit.php b/core/module/user/view/edit/edit.php index aa739b33..30a91c97 100644 --- a/core/module/user/view/edit/edit.php +++ b/core/module/user/view/edit/edit.php @@ -1,23 +1,21 @@
    -
    - getUser('group') === self::GROUP_ADMIN): ?> +
    + getUser('group') === self::GROUP_ADMIN): ?> 'buttonGrey', 'href' => helper::baseUrl() . 'user', - 'ico' => 'left', - 'value' => 'Retour' + 'value' => template::ico('left') ]); ?> 'buttonGrey', 'href' => helper::baseUrl(false), - 'ico' => 'home', - 'value' => 'Accueil' + 'value' => template::ico('home') ]); ?>
    -
    +
    diff --git a/core/module/user/view/forgot/forgot.php b/core/module/user/view/forgot/forgot.php index 29dc17e8..3e163deb 100644 --- a/core/module/user/view/forgot/forgot.php +++ b/core/module/user/view/forgot/forgot.php @@ -3,11 +3,10 @@ 'label' => 'Identifiant' ]); ?>
    -
    +
    helper::baseUrl() . 'user/login/' . $this->getUrl(2), - 'ico' => 'left', - 'value' => 'Retour' + 'value' => template::ico('left') ]); ?>
    diff --git a/core/module/user/view/import/import.help.html b/core/module/user/view/import/import.help.html deleted file mode 100644 index 0be5e2dd..00000000 --- a/core/module/user/view/import/import.help.html +++ /dev/null @@ -1,4 +0,0 @@ -

    IMPORT

    -

    Pour réaliser un fichier CSV d'utilisateurs les en-têtes obligatoires sont : id, nom, prenom, email et groupe ( 1 : membre - 2 : éditeur - 3 : administrateur )

    -

    Voir ce modèle à compléter avec un tableur.

    -

    Enregistrez au format CSV, séparateur ; ou , ou : puis téléversez votre fichier avec 'Gérer les fichiers'.

    diff --git a/core/module/user/view/import/import.php b/core/module/user/view/import/import.php index 81e6a929..e6d1ee43 100644 --- a/core/module/user/view/import/import.php +++ b/core/module/user/view/import/import.php @@ -1,23 +1,22 @@
    -
    +
    'buttonGrey', 'href' => helper::baseUrl() . 'user', - 'ico' => 'left', - 'value' => 'Retour' + 'value' => template::ico('left') ]); ?>
    -
    +
    'https://doc.zwiicms.fr/importation-d-une-liste-d-utilisateurs', 'target' => '_blank', - 'ico' => 'help', - 'value' => 'Aide', - 'class' => 'buttonHelp' + 'value' => template::ico('help'), + 'class' => 'buttonHelp', + 'help' => 'Consulter l\'aide en ligne' ]); ?>
    -
    +
    'Importer' ]); ?> @@ -28,7 +27,7 @@

    Importation de fichier plat CSV

    -
    +
    'Liste d\'utilisateurs :' ]); ?> diff --git a/core/module/user/view/index/index.php b/core/module/user/view/index/index.php index 98fc2388..1a89a67e 100644 --- a/core/module/user/view/index/index.php +++ b/core/module/user/view/index/index.php @@ -1,33 +1,32 @@
    -
    +
    'buttonGrey', 'href' => helper::baseUrl(false), - 'ico' => 'home', - 'value' => 'Accueil' + 'value' => template::ico('home') ]); ?>
    -
    +
    'https://doc.zwiicms.fr/gestion-des-utilisateurs', 'target' => '_blank', - 'ico' => 'help', - 'value' => 'Aide', - 'class' => 'buttonHelp' + 'value' => template::ico('help'), + 'class' => 'buttonHelp', + 'help' => 'Consulter l\'aide en ligne' ]); ?>
    -
    +
    helper::baseUrl() . 'user/import', - 'ico' => 'plus', - 'value' => 'Importation' + 'value' => template::ico('upload') , + 'help' => 'Importer des utilisateurs en masse' ]); ?>
    -
    +
    helper::baseUrl() . 'user/add', - 'ico' => 'plus', - 'value' => 'Utilisateur' + 'value' => template::ico('plus'), + 'help' => 'Ajouter un utilisateur' ]); ?>
    diff --git a/core/vendor/tinymce/init.js b/core/vendor/tinymce/init.js index 6daa4b89..b4d3bad3 100755 --- a/core/vendor/tinymce/init.js +++ b/core/vendor/tinymce/init.js @@ -114,7 +114,7 @@ tinymce.init({ // Active l'onglet avancé lors de l'ajout d'une image image_advtab: true, // Urls absolues - relative_urls: false, + relative_urls: true, // Url de base document_base_url: baseUrl, // Gestionnaire de fichiers @@ -294,7 +294,7 @@ tinymce.init({ // Active l'onglet avancé lors de l'ajout d'une image image_advtab: true, // Urls absolues - relative_urls: false, + relative_urls: true, // Url de base document_base_url: baseUrl, // Contenu du bouton formats diff --git a/core/vendor/tippy/init.js b/core/vendor/tippy/init.js index 976da1e6..210a5f14 100755 --- a/core/vendor/tippy/init.js +++ b/core/vendor/tippy/init.js @@ -1,38 +1,49 @@ /** * Initialisation de Tippy */ -$(document).ready(function() { - // Tooltip des aides - tippy(".helpButton", { - arrow: true, - arrowType: "round", - placement: "top" - }); - // Tooltip des attributs title - tippy("[data-tippy-content]", { - arrow: true, - placement: "top" - }); - // Pour les images map, pas de flèche, bulle haut suivant le curseur - - tippy('img[title], a[title], area[title]', { - - content(reference) { - const title = reference.getAttribute('title') - reference.removeAttribute('title') - return title - }, - - placement: "top", - followCursor: true, - animation: "fade", - animateFill: true - }); - // Pour les images map, pas de flèche, bulle haut suivant le curseur - tippy("#image-map", { - placement: "top", - followCursor: true, - animation: "fade", - animateFill: true - }); -}); +$(document).ready(function () { + + // Tooltip des attributs title + tippy("[data-tippy-content]", { + arrow: true, + placement: "top" + }); + + // Pour les images map, pas de flèche, bulle haut suivant le curseur + tippy('img[title], a[title]:not(.button), area[title]', { + + content(reference) { + const title = reference.getAttribute('title') + reference.removeAttribute('title') + return title + }, + + placement: "top", + followCursor: true, + animation: "fade", + animateFill: true + }); + + // Tooltip des aides + tippy('a.button[title]', { + content(reference) { + const title = reference.getAttribute('title') + reference.removeAttribute('title') + return title + }, + delay: [1000,250], + placement: "bottom", + followCursor: false, + arrow: true, + animateFill: true, + arrowType: "round", + }); + + // Pour les images map, pas de flèche, bulle haut suivant le curseur + tippy("#image-map", { + placement: "top", + followCursor: true, + animation: "fade", + animateFill: true + }); +}); \ No newline at end of file diff --git a/module/blog/blog.php b/module/blog/blog.php index 333a93dc..b25c4b0f 100644 --- a/module/blog/blog.php +++ b/module/blog/blog.php @@ -15,7 +15,7 @@ class blog extends common { - const VERSION = '5.1'; + const VERSION = '6.0'; const REALNAME = 'Blog'; const DELETE = true; const UPDATE = '0.0'; @@ -32,6 +32,7 @@ class blog extends common { 'commentDelete' => self::GROUP_MODERATOR, 'commentDeleteAll' => self::GROUP_MODERATOR, 'config' => self::GROUP_MODERATOR, + 'option' => self::GROUP_MODERATOR, 'delete' => self::GROUP_MODERATOR, 'edit' => self::GROUP_MODERATOR, 'index' => self::GROUP_VISITOR, @@ -100,6 +101,9 @@ class blog extends common { self::EDIT_OWNER => 'Propriétaire' ]; + // Nombre d'articles dans la page de config: + public static $itemsperPage = 8; + public static $users = []; @@ -398,103 +402,116 @@ class blog extends common { * Configuration */ public function config() { + + // Ids des articles par ordre de publication + $articleIds = array_keys(helper::arrayCollumn($this->getData(['module', $this->getUrl(0), 'posts']), 'publishedOn', 'SORT_DESC')); + // Gestion des droits d'accès + $filterData=[]; + foreach ($articleIds as $key => $value) { + if ( + ( // Propriétaire + $this->getData(['module', $this->getUrl(0), 'posts', $value,'editConsent']) === self::EDIT_OWNER + AND ( $this->getData(['module', $this->getUrl(0), 'posts', $value,'userId']) === $this->getUser('id') + OR $this->getUser('group') === self::GROUP_ADMIN ) + ) + + OR ( + // Groupe + $this->getData(['module', $this->getUrl(0), 'posts', $value,'editConsent']) !== self::EDIT_OWNER + AND $this->getUser('group') >= $this->getData(['module',$this->getUrl(0), 'posts', $value,'editConsent']) + ) + OR ( + // Tout le monde + $this->getData(['module', $this->getUrl(0), 'posts', $value,'editConsent']) === self::EDIT_ALL + ) + ) { + $filterData[] = $value; + } + } + $articleIds = $filterData; + // Pagination + $pagination = helper::pagination($articleIds, $this->getUrl(),self::$itemsperPage); + // Liste des pages + self::$pages = $pagination['pages']; + // Articles en fonction de la pagination + for($i = $pagination['first']; $i < $pagination['last']; $i++) { + // Nombre de commentaires à approuver et approuvés + $approvals = helper::arrayCollumn($this->getData(['module', $this->getUrl(0), 'posts', $articleIds[$i], 'comment' ]),'approval', 'SORT_DESC'); + if ( is_array($approvals) ) { + $a = array_values($approvals); + $toApprove = count(array_keys($a,false)); + $approved = count(array_keys($a,true)); + } else { + $toApprove = 0; + $approved = count($this->getData(['module', $this->getUrl(0), 'posts', $articleIds[$i],'comment'])); + } + // Met en forme le tableau + $date = mb_detect_encoding(strftime('%d %B %Y', $this->getData(['module', $this->getUrl(0), 'posts', $articleIds[$i], 'publishedOn'])), 'UTF-8', true) + ? strftime('%d %B %Y', $this->getData(['module', $this->getUrl(0), 'posts', $articleIds[$i], 'publishedOn'])) + : utf8_encode(strftime('%d %B %Y', $this->getData(['module', $this->getUrl(0), 'posts', $articleIds[$i], 'publishedOn']))); + $heure = mb_detect_encoding(strftime('%H:%M', $this->getData(['module', $this->getUrl(0), 'posts', $articleIds[$i], 'publishedOn'])), 'UTF-8', true) + ? strftime('%H:%M', $this->getData(['module', $this->getUrl(0), 'posts', $articleIds[$i], 'publishedOn'])) + : utf8_encode(strftime('%H:%M', $this->getData(['module', $this->getUrl(0), 'posts', $articleIds[$i], 'publishedOn']))); + self::$articles[] = [ + '' . + $this->getData(['module', $this->getUrl(0), 'posts', $articleIds[$i], 'title']) . + '', + $date .' à '. $heure, + 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], [ + 'class' => ($toApprove || $approved ) > 0 ? '' : 'buttonGrey' , + 'href' => ($toApprove || $approved ) > 0 ? helper::baseUrl() . $this->getUrl(0) . '/comment/' . $articleIds[$i] : '', + 'value' => $toApprove > 0 ? $toApprove . '/' . $approved : $approved, + 'help' => ($toApprove || $approved ) > 0 ? 'Editer / Approuver les commentaires' : '' + ]), + template::button('blogConfigEdit' . $articleIds[$i], [ + 'href' => helper::baseUrl() . $this->getUrl(0) . '/edit/' . $articleIds[$i] . '/' . $_SESSION['csrf'], + 'value' => template::ico('pencil'), + 'help' => 'Editer l\'article' + ]), + template::button('blogConfigDelete' . $articleIds[$i], [ + 'class' => 'blogConfigDelete buttonRed', + 'href' => helper::baseUrl() . $this->getUrl(0) . '/delete/' . $articleIds[$i] . '/' . $_SESSION['csrf'], + 'value' => template::ico('cancel'), + 'help' => 'Effacer l\'article' + ]) + ]; + } + // Valeurs en sortie + $this->addOutput([ + 'title' => 'Configuration du module', + 'view' => 'config' + ]); + } + + public function option() { // Mise à jour des données de module $this->update(); // Soumission du formulaire if($this->isPost()) { $this->setData(['module', $this->getUrl(0), 'config',[ - 'feeds' => $this->getInput('blogConfigShowFeeds',helper::FILTER_BOOLEAN), - 'feedsLabel' => $this->getInput('blogConfigFeedslabel',helper::FILTER_STRING_SHORT), - 'itemsperPage' => $this->getInput('blogConfigItemsperPage', helper::FILTER_INT,true), + 'feeds' => $this->getInput('blogOptionShowFeeds',helper::FILTER_BOOLEAN), + 'feedsLabel' => $this->getInput('blogOptionFeedslabel',helper::FILTER_STRING_SHORT), + 'itemsperPage' => $this->getInput('blogOptionItemsperPage', helper::FILTER_INT,true), 'versionData' => $this->getData(['module', $this->getUrl(0), 'config', 'versionData']) ]]); // Valeurs en sortie $this->addOutput([ - 'redirect' => helper::baseUrl() . $this->getUrl(0) . '/config', + 'redirect' => helper::baseUrl() . $this->getUrl(0) . '/option', 'notification' => 'Modifications enregistrées', 'state' => true ]); } else { - // Ids des articles par ordre de publication - $articleIds = array_keys(helper::arrayCollumn($this->getData(['module', $this->getUrl(0), 'posts']), 'publishedOn', 'SORT_DESC')); - // Gestion des droits d'accès - $filterData=[]; - foreach ($articleIds as $key => $value) { - if ( - ( // Propriétaire - $this->getData(['module', $this->getUrl(0), 'posts', $value,'editConsent']) === self::EDIT_OWNER - AND ( $this->getData(['module', $this->getUrl(0), 'posts', $value,'userId']) === $this->getUser('id') - OR $this->getUser('group') === self::GROUP_ADMIN ) - ) - - OR ( - // Groupe - $this->getData(['module', $this->getUrl(0), 'posts', $value,'editConsent']) !== self::EDIT_OWNER - AND $this->getUser('group') >= $this->getData(['module',$this->getUrl(0), 'posts', $value,'editConsent']) - ) - OR ( - // Tout le monde - $this->getData(['module', $this->getUrl(0), 'posts', $value,'editConsent']) === self::EDIT_ALL - ) - ) { - $filterData[] = $value; - } - } - $articleIds = $filterData; - // Pagination - $pagination = helper::pagination($articleIds, $this->getUrl(),$this->getData(['module', $this->getUrl(0),'config', 'itemsperPage'])); - // Liste des pages - self::$pages = $pagination['pages']; - // Articles en fonction de la pagination - for($i = $pagination['first']; $i < $pagination['last']; $i++) { - // Nombre de commentaires à approuver et approuvés - $approvals = helper::arrayCollumn($this->getData(['module', $this->getUrl(0), 'posts', $articleIds[$i], 'comment' ]),'approval', 'SORT_DESC'); - if ( is_array($approvals) ) { - $a = array_values($approvals); - $toApprove = count(array_keys($a,false)); - $approved = count(array_keys($a,true)); - } else { - $toApprove = 0; - $approved = count($this->getData(['module', $this->getUrl(0), 'posts', $articleIds[$i],'comment'])); - } - // Met en forme le tableau - $date = mb_detect_encoding(strftime('%d %B %Y', $this->getData(['module', $this->getUrl(0), 'posts', $articleIds[$i], 'publishedOn'])), 'UTF-8', true) - ? strftime('%d %B %Y', $this->getData(['module', $this->getUrl(0), 'posts', $articleIds[$i], 'publishedOn'])) - : utf8_encode(strftime('%d %B %Y', $this->getData(['module', $this->getUrl(0), 'posts', $articleIds[$i], 'publishedOn']))); - $heure = mb_detect_encoding(strftime('%H:%M', $this->getData(['module', $this->getUrl(0), 'posts', $articleIds[$i], 'publishedOn'])), 'UTF-8', true) - ? strftime('%H:%M', $this->getData(['module', $this->getUrl(0), 'posts', $articleIds[$i], 'publishedOn'])) - : utf8_encode(strftime('%H:%M', $this->getData(['module', $this->getUrl(0), 'posts', $articleIds[$i], 'publishedOn']))); - self::$articles[] = [ - '' . - $this->getData(['module', $this->getUrl(0), 'posts', $articleIds[$i], 'title']) . - '', - $date .' à '. $heure, - 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], [ - 'class' => ($toApprove || $approved ) > 0 ? '' : 'buttonGrey' , - 'href' => ($toApprove || $approved ) > 0 ? helper::baseUrl() . $this->getUrl(0) . '/comment/' . $articleIds[$i] : '', - 'value' => $toApprove > 0 ? $toApprove . '/' . $approved : $approved - ]), - template::button('blogConfigEdit' . $articleIds[$i], [ - 'href' => helper::baseUrl() . $this->getUrl(0) . '/edit/' . $articleIds[$i] . '/' . $_SESSION['csrf'], - 'value' => template::ico('pencil') - ]), - template::button('blogConfigDelete' . $articleIds[$i], [ - 'class' => 'blogConfigDelete buttonRed', - 'href' => helper::baseUrl() . $this->getUrl(0) . '/delete/' . $articleIds[$i] . '/' . $_SESSION['csrf'], - 'value' => template::ico('cancel') - ]) - ]; - } // Valeurs en sortie $this->addOutput([ - 'title' => 'Configuration du module', - 'view' => 'config' + 'title' => 'Options de configuration', + 'view' => 'option' ]); } } + /** * Suppression */ diff --git a/module/blog/changes.md b/module/blog/changes.md new file mode 100644 index 00000000..6a7d7be0 --- /dev/null +++ b/module/blog/changes.md @@ -0,0 +1,2 @@ +# version 6 + - mise à la norme avec le module news : le formulaire est sorti de l'écran principal \ No newline at end of file diff --git a/module/blog/view/add/add.php b/module/blog/view/add/add.php index 7f50b45e..22e51de4 100644 --- a/module/blog/view/add/add.php +++ b/module/blog/view/add/add.php @@ -1,17 +1,16 @@
    -
    +
    'buttonGrey', 'href' => helper::baseUrl() . $this->getUrl(0) . '/config', - 'ico' => 'left', - 'value' => 'Retour' + 'value' => template::ico('left') ]); ?>
    -
    +
    true, - 'value' => 'Enregistrer en brouillon' + 'value' => 'Brouillon' ]); ?> true diff --git a/module/blog/view/config/config.php b/module/blog/view/config/config.php index 736151c9..df44db80 100644 --- a/module/blog/view/config/config.php +++ b/module/blog/view/config/config.php @@ -1,51 +1,27 @@
    -
    +
    'buttonGrey', 'href' => helper::baseUrl() . 'page/edit/' . $this->getUrl(0), 'posts', - 'ico' => 'left', - 'value' => 'Retour' + 'value' => template::ico('left') ]); ?>
    -
    +
    + helper::baseUrl() . $this->getUrl(0) . '/option', + 'value' => template::ico('sliders'), + 'help' => 'Options de configuration' + ]); ?> + +
    +
    helper::baseUrl() . $this->getUrl(0) . '/add', - 'ico' => 'plus', - 'value' => 'Article' + 'value' => template::ico('plus'), + 'help' => 'Rédiger un article' ]); ?>
    -
    - -
    -
    -
    -
    -
    -

    Paramètres du module

    -
    -
    - $this->getData(['module', $this->getUrl(0), 'config', 'feeds']), - ]); ?> -
    -
    - 'Texte de l\'étiquette', - 'value' => $this->getData(['module', $this->getUrl(0), 'config', 'feedsLabel']) - ]); ?> -
    -
    -
    -
    - 'Articles par page', - 'selected' => $this->getData(['module', $this->getUrl(0),'config', 'itemsperPage']) - ]); ?> -
    -
    -
    -
    diff --git a/module/blog/view/edit/edit.php b/module/blog/view/edit/edit.php index 404467b8..b60da969 100644 --- a/module/blog/view/edit/edit.php +++ b/module/blog/view/edit/edit.php @@ -1,17 +1,16 @@
    -
    +
    'buttonGrey', 'href' => helper::baseUrl() . $this->getUrl(0) . '/config', - 'ico' => 'left', - 'value' => 'Retour' + 'value' => template::ico('left') ]); ?>
    -
    +
    true, - 'value' => 'Enregistrer en brouillon' + 'value' => 'Brouillon' ]); ?> true diff --git a/core/module/addon/view/index/index.css b/module/blog/view/option/option.css similarity index 100% rename from core/module/addon/view/index/index.css rename to module/blog/view/option/option.css diff --git a/module/blog/view/option/option.php b/module/blog/view/option/option.php new file mode 100644 index 00000000..721eb6a7 --- /dev/null +++ b/module/blog/view/option/option.php @@ -0,0 +1,46 @@ + +
    +
    + 'buttonGrey', + 'href' => helper::baseUrl() . $this->getUrl(0) . '/config', + 'value' => template::ico('left') + ]); ?> +
    +
    + +
    +
    +
    +
    +
    +

    Paramètres du module

    +
    +
    + $this->getData(['module', $this->getUrl(0), 'config', 'feeds']), + ]); ?> +
    +
    + 'Texte de l\'étiquette', + 'value' => $this->getData(['module', $this->getUrl(0), 'config', 'feedsLabel']) + ]); ?> +
    +
    +
    +
    + 'Articles par page', + 'selected' => $this->getData(['module', $this->getUrl(0),'config', 'itemsperPage']) + ]); ?> +
    +
    +
    +
    +
    + +
    Version n° + +
    + diff --git a/module/form/changes.md b/module/form/changes.md new file mode 100644 index 00000000..c8442301 --- /dev/null +++ b/module/form/changes.md @@ -0,0 +1,3 @@ +# Version 3 + - Déplacement des options de formulaires + - Gabarit du formulaire sur la page \ No newline at end of file diff --git a/module/form/form.php b/module/form/form.php index 627ad4da..496272ba 100644 --- a/module/form/form.php +++ b/module/form/form.php @@ -16,7 +16,7 @@ class form extends common { - const VERSION = '2.11'; + const VERSION = '3.0'; const REALNAME = 'Formulaire'; const DELETE = true; const UPDATE = '0.0'; @@ -24,6 +24,7 @@ class form extends common { public static $actions = [ 'config' => self::GROUP_MODERATOR, + 'option' => self::GROUP_MODERATOR, 'data' => self::GROUP_MODERATOR, 'delete' => self::GROUP_MODERATOR, 'deleteall' => self::GROUP_MODERATOR, @@ -38,6 +39,9 @@ class form extends common { public static $pagination; + // Nombre d'articles dans la page de config: + public static $itemperPage = 20; + // Objets const TYPE_MAIL = 'mail'; @@ -75,38 +79,35 @@ class form extends common { '100' => '100%' ]; + public static $optionOffset = [ + 0 => 'Aucune', + 1 => 'Une colonne', + 2 => 'Deux colonnes' + ]; + + public static $optionWidth = [ + 6 => 'Six colonnes', + 7 => 'Sept colonnes', + 8 => 'Huit colonnes', + 9 => 'Neuf colonnes', + 10 => 'Dix colonnes', + 11 => 'Onze colonnes', + 12 => 'Douze colonnes', + ]; + + public static $optionAlign = [ + '' => 'A gauche', + 'textAlignCenter' => 'Au centre', + 'textAlignRight' => 'A droite' + ]; + + /** * Configuration */ public function config() { - // Liste des utilisateurs - $userIdsFirstnames = helper::arrayCollumn($this->getData(['user']), 'firstname'); - ksort($userIdsFirstnames); - self::$listUsers [] = ''; - foreach($userIdsFirstnames as $userId => $userFirstname) { - self::$listUsers [] = $userId; - } // Soumission du formulaire if($this->isPost()) { - // Configuration - $this->setData([ - 'module', - $this->getUrl(0), - 'config', - [ - 'button' => $this->getInput('formConfigButton'), - 'captcha' => $this->getInput('formConfigCaptcha', helper::FILTER_BOOLEAN), - 'group' => $this->getInput('formConfigGroup', helper::FILTER_INT), - 'user' => self::$listUsers [$this->getInput('formConfigUser', helper::FILTER_INT)], - 'mail' => $this->getInput('formConfigMail') , - 'pageId' => $this->getInput('formConfigPageIdToggle', helper::FILTER_BOOLEAN) === true ? $this->getInput('formConfigPageId', helper::FILTER_ID) : '', - 'subject' => $this->getInput('formConfigSubject'), - 'replyto' => $this->getInput('formConfigMailReplyTo', helper::FILTER_BOOLEAN), - 'signature' => $this->getInput('formConfigSignature'), - 'logoUrl' => $this->getInput('formConfigLogo'), - 'logoWidth' => $this->getInput('formConfigLogoWidth') - ] - ]); // Génération des données vides if ($this->getData(['module', $this->getUrl(0), 'data']) === null) { $this->setData(['module', $this->getUrl(0), 'data', []]); @@ -148,6 +149,75 @@ class form extends common { ]); } + + public function option() { + // Liste des utilisateurs + $userIdsFirstnames = helper::arrayCollumn($this->getData(['user']), 'firstname'); + ksort($userIdsFirstnames); + self::$listUsers [] = ''; + foreach ($userIdsFirstnames as $userId => $userFirstname) { + self::$listUsers [] = $userId; + } + // Soumission du formulaire + if ($this->isPost()) { + // Débordement + $width = $this->getInput('formOptionWidth'); + if ($this->getInput('formOptionWidth',helper::FILTER_INT) + $this->getInput('formOptionOffset',helper::FILTER_INT) > 12 ) { + $width = (string) $this->getInput('formOptionWidth',helper::FILTER_INT) - $this->getInput('formOptionOffset',helper::FILTER_INT); + } + + // Configuration + $this->setData([ + 'module', + $this->getUrl(0), + 'config', + [ + 'button' => $this->getInput('formOptionButton'), + 'captcha' => $this->getInput('formOptionCaptcha', helper::FILTER_BOOLEAN), + 'group' => $this->getInput('formOptionGroup', helper::FILTER_INT), + 'user' => self::$listUsers [$this->getInput('formOptionUser', helper::FILTER_INT)], + 'mail' => $this->getInput('formOptionMail') , + 'pageId' => $this->getInput('formOptionPageIdToggle', helper::FILTER_BOOLEAN) === true ? $this->getInput('formOptionPageId', helper::FILTER_ID) : '', + 'subject' => $this->getInput('formOptionSubject'), + 'replyto' => $this->getInput('formOptionMailReplyTo', helper::FILTER_BOOLEAN), + 'signature' => $this->getInput('formOptionSignature'), + 'logoUrl' => $this->getInput('formOptionLogo'), + 'logoWidth' => $this->getInput('formOptionLogoWidth'), + 'offset' =>$this->getInput('formOptionOffset'), + 'width' =>$width, + 'align' =>$this->getInput('formOptionAlign'), + ] + ]); + // Génération des données vides + if ($this->getData(['module', $this->getUrl(0), 'data']) === null) { + $this->setData(['module', $this->getUrl(0), 'data', []]); + } + // Valeurs en sortie + $this->addOutput([ + 'notification' => 'Modifications enregistrées' , + 'redirect' => helper::baseUrl() . $this->getUrl(), + 'state' => true + ]); + } else { + // Liste des pages + foreach($this->getHierarchy(null, false) as $parentPageId => $childrenPageIds) { + self::$pages[$parentPageId] = $this->getData(['page', $parentPageId, 'title']); + foreach($childrenPageIds as $childKey) { + self::$pages[$childKey] = '    ' . $this->getData(['page', $childKey, 'title']); + } + } + // Valeurs en sortie + $this->addOutput([ + 'title' => 'Options de configuration', + 'vendor' => [ + 'html-sortable', + 'flatpickr' + ], + 'view' => 'option' + ]); + } + } + /** * Données enregistrées */ @@ -155,7 +225,7 @@ class form extends common { $data = $this->getData(['module', $this->getUrl(0), 'data']); if($data) { // Pagination - $pagination = helper::pagination($data, $this->getUrl(),self::ITEMSPAGE); + $pagination = helper::pagination($data, $this->getUrl(), self::$itemsperPages); // Liste des pages self::$pages = $pagination['pages']; // Inverse l'ordre du tableau diff --git a/module/form/view/config/config.js.php b/module/form/view/config/config.js.php index 1522ee3d..2d64a2aa 100644 --- a/module/form/view/config/config.js.php +++ b/module/form/view/config/config.js.php @@ -54,6 +54,15 @@ function add(inputUid, input) { position(); } +/** + * Afficher/cacher les options supplémentaires + */ + $(document).on("click", ".formConfigMoreToggle", function() { + + $(this).parents(".formConfigInput").find(".formConfigMore").slideToggle(); + $(this).parents(".formConfigInput").find(".formConfigMoreLabel").slideToggle(); +}); + /** * Calcul des positions */ @@ -76,14 +85,6 @@ if(inputs) { }); } -/** - * Afficher/cacher les options supplémentaires - */ -$(document).on("click", ".formConfigMoreToggle", function() { - - $(this).parents(".formConfigInput").find(".formConfigMore").slideToggle(); - $(this).parents(".formConfigInput").find(".formConfigMoreLabel").slideToggle(); -}); /** * Crée un nouveau champ à partir des champs cachés @@ -96,6 +97,12 @@ $("#formConfigAdd").on("click", function() { /** * Actions sur les champs */ + +// Validation auto après ajout d'un champ +$("a#formConfigAdd.button").click(function () { + $("#formConfigForm").submit(); +}); + // Tri entre les champs sortable("#formConfigInputs", { forcePlaceholderSize: true, @@ -143,73 +150,3 @@ $("#formConfigInputs") }); // Simule un changement de type au chargement de la page $(".formConfigType").trigger("change"); - -/** - * Affiche/cache les options de la case à cocher du mail - */ -$("#formConfigMailOptionsToggle").on("change", function() { - if($(this).is(":checked")) { - $("#formConfigMailOptions").slideDown(); - } - else { - $("#formConfigMailOptions").slideUp(function() { - $("#formConfigGroup").val(""); - $("#formConfigSubject").val(""); - $("#formConfigMail").val(""); - $("#formConfigUser").val(""); - }); - } -}).trigger("change"); - -/** - * Affiche/cache les options de la case à cocher de la redirection - */ -$("#formConfigPageIdToggle").on("change", function() { - if($(this).is(":checked")) { - $("#formConfigPageIdWrapper").slideDown(); - } - else { - $("#formConfigPageIdWrapper").slideUp(function() { - $("#formConfigPageId").val(""); - }); - } -}).trigger("change"); - -/** -* Paramètres par défaut au chargement -*/ -$( document ).ready(function() { - - /** - * Masquer ou afficher la sélection du logo - */ - if ($("#formConfigSignature").val() !== "text") { - $("#formConfigLogoWrapper").addClass("disabled"); - $("#formConfigLogoWrapper").slideDown(); - $("#formConfigLogoWidthWrapper").addClass("disabled"); - $("#formConfigLogoWidthWrapper").slideDown(); - } else { - $("#formConfigLogoWrapper").removeClass("disabled"); - $("#formConfigLogoWrapper").slideUp(); - $("#formConfigLogoWidthWrapper").removeClass("disabled"); - $("#formConfigLogoWidthWrapper").slideUp(); - } -}); - -/** - * Masquer ou afficher la sélection du logo - */ -var formConfigSignatureDOM = $("#formConfigSignature"); -formConfigSignatureDOM.on("change", function() { - if ($(this).val() !== "text") { - $("#formConfigLogoWrapper").addClass("disabled"); - $("#formConfigLogoWrapper").slideDown(); - $("#formConfigLogoWidthWrapper").addClass("disabled"); - $("#formConfigLogoWidthWrapper").slideDown(); - } else { - $("#formConfigLogoWrapper").removeClass("disabled"); - $("#formConfigLogoWrapper").slideUp(); - $("#formConfigLogoWidthWrapper").removeClass("disabled"); - $("#formConfigLogoWidthWrapper").slideUp(); - } -}); diff --git a/module/form/view/config/config.php b/module/form/view/config/config.php index 6631a20a..49050a8d 100644 --- a/module/form/view/config/config.php +++ b/module/form/view/config/config.php @@ -49,140 +49,48 @@
    -
    -
    - 'buttonGrey', - 'href' => helper::baseUrl() . 'page/edit/' . $this->getUrl(0), - 'ico' => 'left', - 'value' => 'Retour' - ]); ?> -
    -
    - helper::baseUrl() . $this->getUrl(0) . '/data', - 'value' => 'Gérer les données' - ]); ?> -
    -
    +
    +
    + 'buttonGrey', + 'href' => helper::baseUrl() . 'page/edit/' . $this->getUrl(0), + 'value' => template::ico('left') + ]); ?> +
    +
    + helper::baseUrl() . $this->getUrl(0) . '/data', + 'value' => template::ico('code'), + 'help' => 'Voir et exporter les données du formulaire' + ]); ?> +
    +
    + helper::baseUrl() . $this->getUrl(0) . '/option', + 'value' => template::ico('sliders'), + 'help' => 'Options de configuration' + ]); ?> +
    +
    +
    +
    +

    Liste des champs

    +
    +
    +
    -
    -
    -

    Configuration

    - 'Laissez vide afin de conserver le texte par défaut.', - 'label' => 'Texte du bouton de soumission', - 'value' => $this->getData(['module', $this->getUrl(0), 'config', 'button']) - ]); ?> - (bool) $this->getData(['module', $this->getUrl(0), 'config', 'group']) || - !empty($this->getData(['module', $this->getUrl(0), 'config', 'user'])) || - !empty($this->getData(['module', $this->getUrl(0), 'config', 'mail'])), - 'help' => 'Sélectionnez au moins un groupe, un utilisateur ou saississez un email. Votre serveur doit autoriser les envois de mail.' - ]); ?> -
    -
    -
    - 'Laissez vide afin de conserver le texte par défaut.', - 'label' => 'Sujet du mail', - 'value' => $this->getData(['module', $this->getUrl(0), 'config', 'subject']) - ]); ?> -
    -
    - -
    -
    - 'Aux groupes à partir de', - 'selected' => $this->getData(['module', $this->getUrl(0), 'config', 'group']), - 'help' => 'Editeurs = éditeurs + administrateurs
    Membres = membres + éditeurs + administrateurs' - ]); ?> -
    -
    - 'A un membre', - 'selected' => array_search($this->getData(['module', $this->getUrl(0), 'config', 'user']),$module::$listUsers) - ]); ?> -
    -
    - 'A une adresse email', - 'value' => $this->getData(['module', $this->getUrl(0), 'config', 'mail']), - 'help' => 'Un email ou une liste de diffusion' - ]); ?> -
    -
    -
    -
    - (bool) $this->getData(['module', $this->getUrl(0), 'config', 'replyto']), - 'help' => 'Cette option permet de réponse drectement à l\'expéditeur du message si celui-ci a indiqué un email valide.' - ]); ?> -
    -
    -
    -
    -
    - 'Sélectionner le type de signature', - 'selected' => $this->getData(['module', $this->getUrl(0), 'config', 'signature']) - ]); ?> -
    -
    - 'Sélectionnez le logo du site', - 'label' => 'Logo', - 'value' => $this->getData(['module', $this->getUrl(0), 'config', 'logoUrl']) - ]); ?> -
    -
    - 'Sélectionner la largeur du logo', - 'selected' => $this->getData(['module', $this->getUrl(0), 'config', 'logoWidth']) - ]); ?> -
    -
    -
    -
    - (bool) $this->getData(['module', $this->getUrl(0), 'config', 'pageId']) - ]); ?> -
    -
    - 'displayNone', - 'label' => 'Sélectionner une page du site :', - 'selected' => $this->getData(['module', $this->getUrl(0), 'config', 'pageId']) - ]); ?> -
    -
    - $this->getData(['module', $this->getUrl(0), 'config', 'captcha']) - ]); ?> -
    -
    -

    Liste des champs

    -
    - -
    -
    -
    -
    - template::ico('plus') - ]); ?> -
    -
    -
    +
    + template::ico('plus'), + 'class' => 'buttonGreen' + ]); ?>
    +
    +
    Version n° diff --git a/module/form/view/data/data.php b/module/form/view/data/data.php index d0a22868..147548a7 100644 --- a/module/form/view/data/data.php +++ b/module/form/view/data/data.php @@ -1,25 +1,24 @@
    -
    +
    'buttonGrey', 'href' => helper::baseUrl() . $this->getUrl(0) . '/config', - 'ico' => 'left', - 'value' => 'Retour' + 'value' => template::ico('left') ]); ?>
    -
    +
    'formDataDeleteAll buttonRed', 'href' => helper::baseUrl() . $this->getUrl(0) . '/deleteall' . '/' . $_SESSION['csrf'], - 'ico' => 'cancel', - 'value' => 'Tout effacer' + 'value' => template::ico('cancel'), + 'help' => 'Effacer toutes les données' ]); ?>
    -
    +
    helper::baseUrl() . $this->getUrl(0) . '/export2csv' . '/' . $_SESSION['csrf'], - 'ico' => 'download', - 'value' => 'Export CSV' + 'value' => template::ico('download'), + 'help' => 'Exporter toutes les données' ]); ?>
    diff --git a/module/form/view/index/index.php b/module/form/view/index/index.php index 6eba5cc9..c2251225 100644 --- a/module/form/view/index/index.php +++ b/module/form/view/index/index.php @@ -1,67 +1,75 @@ getData(['module', $this->getUrl(0), 'input'])): ?> - - getData(['module', $this->getUrl(0), 'input']) as $index => $input): ?> - - 'formInput_' . $index, - 'label' => $input['name'] - ]); ?> - - $key) { - $values[$value] = trim($value); - } - ?> - 'formInput_' . $index, - 'label' => $input['name'] - ]); ?> - - 'formInput_' . $index, - 'label' => $input['name'] - ]); ?> - - 'formInput_' . $index, - 'label' => $input['name'] - ]); ?> - - 'formInput_' . $index, - 'label' => $input['name'], - 'vendor' => 'flatpickr' - ]); ?> - - - -

    - -
    -

    +
    +
    + + getData(['module', $this->getUrl(0), 'input']) as $index => $input): ?> + + 'formInput_' . $index, + 'label' => $input['name'] + ]); ?> + + $key) { + $values[$value] = trim($value); + } + ?> + 'formInput_' . $index, + 'label' => $input['name'] + ]); ?> + + 'formInput_' . $index, + 'label' => $input['name'] + ]); ?> + + 'formInput_' . $index, + 'label' => $input['name'] + ]); ?> + + 'formInput_' . $index, + 'label' => $input['name'], + 'vendor' => 'flatpickr' + ]); ?> + + + +

    + +
    +

    + + + getData(['module', $this->getUrl(0), 'config', 'captcha'])): ?> +
    +
    + $this->getData(['config','connect', 'captchaStrong']), + 'type' => $this->getData(['config','connect', 'captchaType']) + ]); ?> +
    +
    - - getData(['module', $this->getUrl(0), 'config', 'captcha'])): ?>
    -
    - $this->getData(['config','connect', 'captchaStrong']), - 'type' => $this->getData(['config','connect', 'captchaType']) +
    + $this->getData(['module', $this->getUrl(0), 'config', 'button']) ? $this->getData(['module', $this->getUrl(0), 'config', 'button']) : 'Envoyer', + 'ico' => '' ]); ?>
    - -
    -
    - $this->getData(['module', $this->getUrl(0), 'config', 'button']) ? $this->getData(['module', $this->getUrl(0), 'config', 'button']) : 'Envoyer', - 'ico' => '' - ]); ?> -
    - +
    +
    + \ No newline at end of file diff --git a/module/form/view/option/option.css b/module/form/view/option/option.css new file mode 100644 index 00000000..52709ea6 --- /dev/null +++ b/module/form/view/option/option.css @@ -0,0 +1,18 @@ +/** + * This file is part of Zwii. + * + * For full copyright and license information, please see the LICENSE + * file that was distributed with this source code. + * + * @author Rémi Jean + * @copyright Copyright (C) 2008-2018, Rémi Jean + * @author Frédéric Tempez + * @copyright Copyright (C) 2018-2022, Frédéric Tempez + * @license GNU General Public License, version 3 + * @link http://zwiicms.fr/ + */ + + +/** NE PAS EFFACER +* admin.css +*/ \ No newline at end of file diff --git a/module/form/view/option/option.js.php b/module/form/view/option/option.js.php new file mode 100644 index 00000000..2148e0c6 --- /dev/null +++ b/module/form/view/option/option.js.php @@ -0,0 +1,72 @@ + + + +/* +* Affiche/cache les options de la case à cocher du mail +*/ +$("#formOptionMailOptionsToggle").on("change", function() { + if($(this).is(":checked")) { + $("#formOptionMailOptions").slideDown(); + } + else { + $("#formOptionMailOptions").slideUp(function() { + $("#formOptionGroup").val(""); + $("#formOptionSubject").val(""); + $("#formOptionMail").val(""); + $("#formOptionUser").val(""); + }); + } +}).trigger("change"); + +/** +* Affiche/cache les options de la case à cocher de la redirection +*/ +$("#formOptionPageIdToggle").on("change", function() { + if($(this).is(":checked")) { + $("#formOptionPageIdWrapper").slideDown(); + } + else { + $("#formOptionPageIdWrapper").slideUp(function() { + $("#formOptionPageId").val(""); + }); + } +}).trigger("change"); + +/** +* Paramètres par défaut au chargement +*/ +$( document ).ready(function() { + + /** + * Masquer ou afficher la sélection du logo + */ + if ($("#formOptionSignature").val() !== "text") { + $("#formOptionLogoWrapper").addClass("disabled"); + $("#formOptionLogoWrapper").slideDown(); + $("#formOptionLogoWidthWrapper").addClass("disabled"); + $("#formOptionLogoWidthWrapper").slideDown(); + } else { + $("#formOptionLogoWrapper").removeClass("disabled"); + $("#formOptionLogoWrapper").slideUp(); + $("#formOptionLogoWidthWrapper").removeClass("disabled"); + $("#formOptionLogoWidthWrapper").slideUp(); + } +}); + +/** +* Masquer ou afficher la sélection du logo +*/ +var formOptionSignatureDOM = $("#formOptionSignature"); +formOptionSignatureDOM.on("change", function() { + if ($(this).val() !== "text") { + $("#formOptionLogoWrapper").addClass("disabled"); + $("#formOptionLogoWrapper").slideDown(); + $("#formOptionLogoWidthWrapper").addClass("disabled"); + $("#formOptionLogoWidthWrapper").slideDown(); + } else { + $("#formOptionLogoWrapper").removeClass("disabled"); + $("#formOptionLogoWrapper").slideUp(); + $("#formOptionLogoWidthWrapper").removeClass("disabled"); + $("#formOptionLogoWidthWrapper").slideUp(); + } +}); \ No newline at end of file diff --git a/module/form/view/option/option.php b/module/form/view/option/option.php new file mode 100644 index 00000000..fe479465 --- /dev/null +++ b/module/form/view/option/option.php @@ -0,0 +1,157 @@ + +
    +
    + 'buttonGrey', + 'href' => helper::baseUrl() . $this->getUrl(0) . '/config', + 'value' => template::ico('left') + ]); ?> +
    +
    + +
    +
    +
    +
    +
    +

    Validation du formulaire

    +
    +
    + $this->getData(['module', $this->getUrl(0), 'config', 'captcha']) + ]); ?> +
    +
    + 'Laissez vide afin de conserver le texte par défaut.', + 'label' => 'Etiquette du bouton de soumission', + 'value' => $this->getData(['module', $this->getUrl(0), 'config', 'button']) + ]); ?> +
    +
    +
    +
    + (bool) $this->getData(['module', $this->getUrl(0), 'config', 'pageId']) + ]); ?> +
    +
    + 'displayNone', + 'label' => 'Page du site :', + 'selected' => $this->getData(['module', $this->getUrl(0), 'config', 'pageId']) + ]); ?> +
    +
    +
    +
    +
    +
    +
    +
    +

    Gabarit

    +
    +
    + 'Alignement du formulaire', + 'selected' => $this->getData(['module', $this->getUrl(0), 'config', 'align']) + ]); ?> +
    +
    +
    +
    + 'Décalage à gauche', + 'selected' => $this->getData(['module', $this->getUrl(0), 'config', 'offset']) + ]); ?> +
    +
    + 'Largeur', + 'selected' => $this->getData(['module', $this->getUrl(0), 'config', 'width']) + ]); ?> +
    +
    +
    +
    +
    +
    +
    +
    +

    Courriel

    + (bool) $this->getData(['module', $this->getUrl(0), 'config', 'group']) || + !empty($this->getData(['module', $this->getUrl(0), 'config', 'user'])) || + !empty($this->getData(['module', $this->getUrl(0), 'config', 'mail'])), + 'help' => 'Sélectionnez au moins un groupe, un utilisateur ou saisissez un email. Votre serveur doit autoriser les envois de mail.' + ]); ?> +
    +
    +
    + 'Laissez vide afin de conserver le texte par défaut.', + 'label' => 'Sujet du mail', + 'value' => $this->getData(['module', $this->getUrl(0), 'config', 'subject']) + ]); ?> +
    +
    + +
    +
    + 'Aux groupes à partir de', + 'selected' => $this->getData(['module', $this->getUrl(0), 'config', 'group']), + 'help' => 'Editeurs = éditeurs + administrateurs
    Membres = membres + éditeurs + administrateurs' + ]); ?> +
    +
    + 'A un membre', + 'selected' => array_search($this->getData(['module', $this->getUrl(0), 'config', 'user']),$module::$listUsers) + ]); ?> +
    +
    + 'A une adresse email', + 'value' => $this->getData(['module', $this->getUrl(0), 'config', 'mail']), + 'help' => 'Un email ou une liste de diffusion' + ]); ?> +
    +
    +
    +
    + 'Sélectionner le type de signature', + 'selected' => $this->getData(['module', $this->getUrl(0), 'config', 'signature']) + ]); ?> +
    +
    + 'Sélectionnez le logo du site', + 'label' => 'Logo', + 'value' => $this->getData(['module', $this->getUrl(0), 'config', 'logoUrl']) + ]); ?> +
    +
    + 'Sélectionner la largeur du logo', + 'selected' => $this->getData(['module', $this->getUrl(0), 'config', 'logoWidth']) + ]); ?> +
    +
    +
    +
    + (bool) $this->getData(['module', $this->getUrl(0), 'config', 'replyto']), + 'help' => 'Cette option permet de réponse directement à l\'expéditeur du message si celui-ci a indiqué un email valide.' + ]); ?> +
    +
    +
    +
    +
    +
    +
    \ No newline at end of file diff --git a/module/gallery/changes.md b/module/gallery/changes.md new file mode 100644 index 00000000..5eaca775 --- /dev/null +++ b/module/gallery/changes.md @@ -0,0 +1,2 @@ +# version 3.4 + - Changement de nom du bouton Thème devient mise en page \ No newline at end of file diff --git a/module/gallery/gallery.php b/module/gallery/gallery.php index 37a8a0df..e2d99e61 100644 --- a/module/gallery/gallery.php +++ b/module/gallery/gallery.php @@ -17,7 +17,7 @@ class gallery extends common { - const VERSION = '3.3'; + const VERSION = '3.4'; const REALNAME = 'Galerie'; const DELETE = true; const UPDATE = '0.0'; @@ -346,12 +346,14 @@ class gallery extends common { $gallery['config']['directory'], template::button('galleryConfigEdit' . $galleryId , [ 'href' => helper::baseUrl() . $this->getUrl(0) . '/edit/' . $galleryId . '/' . $_SESSION['csrf'], - 'value' => template::ico('pencil') + 'value' => template::ico('pencil'), + 'help' => 'Configuration de la galerie ' ]), template::button('galleryConfigDelete' . $galleryId, [ 'class' => 'galleryConfigDelete buttonRed', 'href' => helper::baseUrl() . $this->getUrl(0) . '/delete/' . $galleryId . '/' . $_SESSION['csrf'], - 'value' => template::ico('cancel') + 'value' => template::ico('cancel'), + 'help' => 'Supprimer cette galerie' ]) ]; // Tableau des id des galleries pour le drag and drop diff --git a/module/gallery/view/config/config.php b/module/gallery/view/config/config.php index 91400a98..5f1fc67f 100644 --- a/module/gallery/view/config/config.php +++ b/module/gallery/view/config/config.php @@ -1,17 +1,17 @@
    -
    +
    'buttonGrey', 'href' => helper::baseUrl() . 'page/edit/' . $this->getUrl(0), - 'ico' => 'left', - 'value' => 'Retour' + 'value' => template::ico('left') ]); ?>
    -
    +
    helper::baseUrl() . $this->getUrl(0) . '/theme/' . $_SESSION['csrf'], - 'value' => template::ico('brush','right') . 'Thème' + 'value' => template::ico('sliders'), + 'help' => 'Options de configuration' ]); ?>
    diff --git a/module/gallery/view/edit/edit.php b/module/gallery/view/edit/edit.php index df001bf7..240c85fa 100644 --- a/module/gallery/view/edit/edit.php +++ b/module/gallery/view/edit/edit.php @@ -1,14 +1,13 @@
    -
    +
    'buttonGrey', 'href' => helper::baseUrl() . $this->getUrl(0) . '/config', - 'ico' => 'left', - 'value' => 'Retour' + 'value' => template::ico('left') ]); ?>
    -
    +
    diff --git a/module/gallery/view/gallery/gallery.php b/module/gallery/view/gallery/gallery.php index 9e617583..235aac0d 100644 --- a/module/gallery/view/gallery/gallery.php +++ b/module/gallery/view/gallery/gallery.php @@ -1,10 +1,9 @@
    -
    +
    'buttonGrey', 'href' => helper::baseUrl() . $this->getUrl(0), - 'ico' => 'left', - 'value' => 'Retour' + 'value' => template::ico('left') ]); ?>
    diff --git a/module/gallery/view/theme/theme.php b/module/gallery/view/theme/theme.php index 8da3639e..a66c589d 100644 --- a/module/gallery/view/theme/theme.php +++ b/module/gallery/view/theme/theme.php @@ -1,15 +1,14 @@
    -
    +
    'buttonGrey', 'href' => helper::baseUrl() . $this->getUrl(0) . '/config', - 'ico' => 'left', - 'value' => 'Retour' + 'value' => template::ico('left') ]); ?>
    -
    +
    diff --git a/module/news/changes.md b/module/news/changes.md new file mode 100644 index 00000000..ea0c25f1 --- /dev/null +++ b/module/news/changes.md @@ -0,0 +1,6 @@ +# Version 4 + - Config : le nombre d'objet est fixe, constante dans news.php + - Ecran layout réservé à la configuration et au thème + - Bug avec l'initialisation, fichier css déclaré mais absent + + A faire partie CSS à amléiorer au niveau des options \ No newline at end of file diff --git a/module/news/news.php b/module/news/news.php index c2dbdabd..0f7a2aac 100644 --- a/module/news/news.php +++ b/module/news/news.php @@ -15,7 +15,7 @@ class news extends common { - const VERSION = '3.7'; + const VERSION = '4.0'; const REALNAME = 'News'; const DELETE = true; const UPDATE = '0.0'; @@ -23,7 +23,8 @@ class news extends common { public static $actions = [ 'add' => self::GROUP_MODERATOR, - 'config' => self::GROUP_MODERATOR, + 'config' => self::GROUP_MODERATOR, // Edition des news + 'option' => self::GROUP_MODERATOR, // paramétrage des news 'delete' => self::GROUP_MODERATOR, 'edit' => self::GROUP_MODERATOR, 'index' => self::GROUP_VISITOR, @@ -88,7 +89,8 @@ class news extends common { // Signature de l'article public static $articleSignature = ''; - + // Nombre d'articles dans la page de config: + public static $itemsperPage = 8; /** * Flux RSS @@ -189,10 +191,65 @@ class news extends common { // Mise à jour des données de module $this->update(); + // Ids des news par ordre de publication + $newsIds = array_keys(helper::arrayCollumn($this->getData(['module', $this->getUrl(0), 'posts']), 'publishedOn', 'SORT_DESC')); + // Pagination fixe + $pagination = helper::pagination($newsIds, $this->getUrl(),self::$itemsperPage ); + // Liste des pages + self::$pages = $pagination['pages']; + // News en fonction de la pagination + for($i = $pagination['first']; $i < $pagination['last']; $i++) { + // Met en forme le tableau + $dateOn = mb_detect_encoding(strftime('%d %B %Y', $this->getData(['module', $this->getUrl(0),'posts', $newsIds[$i], 'publishedOn'])), 'UTF-8', true) + ? strftime('%d %B %Y', $this->getData(['module', $this->getUrl(0),'posts', $newsIds[$i], 'publishedOn'])) + : utf8_encode(strftime('%d %B %Y', $this->getData(['module', $this->getUrl(0),'posts', $newsIds[$i], 'publishedOn']))); + $dateOn .= ' à '; + $dateOn .= mb_detect_encoding(strftime('%H:%M', $this->getData(['module', $this->getUrl(0),'posts', $newsIds[$i], 'publishedOn'])), 'UTF-8', true) + ? strftime('%H:%M', $this->getData(['module', $this->getUrl(0),'posts', $newsIds[$i], 'publishedOn'])) + : utf8_encode(strftime('%H:%M', $this->getData(['module', $this->getUrl(0),'posts', $newsIds[$i], 'publishedOn']))); + if ($this->getData(['module', $this->getUrl(0),'posts', $newsIds[$i], 'publishedOff'])) { + $dateOff = mb_detect_encoding(strftime('%d %B %Y', $this->getData(['module', $this->getUrl(0),'posts', $newsIds[$i], 'publishedOff'])), 'UTF-8', true) + ? strftime('%d %B %Y', $this->getData(['module', $this->getUrl(0),'posts', $newsIds[$i], 'publishedOff'])) + : utf8_encode(strftime('%d %B %Y', $this->getData(['module', $this->getUrl(0),'posts', $newsIds[$i], 'publishedOff']))); + $dateOff .= ' à '; + $dateOff .= mb_detect_encoding(strftime('%H:%M', $this->getData(['module', $this->getUrl(0),'posts', $newsIds[$i], 'publishedOff'])), 'UTF-8', true) + ? strftime('%H:%M', $this->getData(['module', $this->getUrl(0),'posts', $newsIds[$i], 'publishedOff'])) + : utf8_encode(strftime('%H:%M', $this->getData(['module', $this->getUrl(0),'posts', $newsIds[$i], 'publishedOff']))); + } else { + $dateOff = 'Permanent'; + } + self::$news[] = [ + $this->getData(['module', $this->getUrl(0),'posts', $newsIds[$i], 'title']), + $dateOn, + $dateOff, + self::$states[$this->getData(['module', $this->getUrl(0),'posts', $newsIds[$i], 'state'])], + template::button('newsConfigEdit' . $newsIds[$i], [ + 'href' => helper::baseUrl() . $this->getUrl(0) . '/edit/' . $newsIds[$i]. '/' . $_SESSION['csrf'], + 'value' => template::ico('pencil'), + 'help' => 'Editer cette nouvelle' + ]), + template::button('newsConfigDelete' . $newsIds[$i], [ + 'class' => 'newsConfigDelete buttonRed', + 'href' => helper::baseUrl() . $this->getUrl(0) . '/delete/' . $newsIds[$i] . '/' . $_SESSION['csrf'], + 'value' => template::ico('cancel'), + 'help' => 'Effacer cette nouvelle' + ]) + ]; + } + // Valeurs en sortie + $this->addOutput([ + 'title' => 'Configuration du module', + 'view' => 'config', + 'vendor' => [ + 'tinycolorpicker' + ] + ]); + } + + public function option() { // Soumission du formulaire if($this->isPost()) { - // Générer la feuille de CSS $style = '.newsFrame {'; $style .= 'border:' . $this->getInput('newsThemeBorderStyle',helper::FILTER_STRING_SHORT) . ' ' . $this->getInput('newsThemeBorderColor') . ' ' . $this->getInput('newsThemeBorderWidth',helper::FILTER_STRING_SHORT) . ';'; @@ -217,69 +274,26 @@ class news extends common { ]]); $this->setData(['module', $this->getUrl(0), 'config',[ - 'feeds' => $this->getInput('newsConfigShowFeeds',helper::FILTER_BOOLEAN), - 'feedsLabel' => $this->getInput('newsConfigFeedslabel',helper::FILTER_STRING_SHORT), - 'itemsperPage' => $this->getInput('newsConfigItemsperPage', helper::FILTER_INT,true), - 'itemsperCol' => $this->getInput('newsConfigItemsperCol', helper::FILTER_INT,true), - 'height' => $this->getInput('newsConfigHeight', helper::FILTER_INT,true), + 'feeds' => $this->getInput('newsOptionShowFeeds',helper::FILTER_BOOLEAN), + 'feedsLabel' => $this->getInput('newsOptionFeedslabel',helper::FILTER_STRING_SHORT), + 'itemsperPage' => $this->getInput('newsOptionItemsperPage', helper::FILTER_INT,true), + 'itemsperCol' => $this->getInput('newsOptionItemsperCol', helper::FILTER_INT,true), + 'height' => $this->getInput('newsOptionHeight', helper::FILTER_INT,true), 'versionData' => $this->getData(['module', $this->getUrl(0), 'config', 'versionData']) ]]); // Valeurs en sortie $this->addOutput([ - 'redirect' => helper::baseUrl() . $this->getUrl(0) . '/config', + 'redirect' => helper::baseUrl() . $this->getUrl(0) . '/option', 'notification' => 'Modifications enregistrées', 'state' => true ]); } else { - // Ids des news par ordre de publication - $newsIds = array_keys(helper::arrayCollumn($this->getData(['module', $this->getUrl(0), 'posts']), 'publishedOn', 'SORT_DESC')); - // Pagination - $pagination = helper::pagination($newsIds, $this->getUrl(),$this->getData(['module', $this->getUrl(0), 'config', 'itemsperPage']) ); - // Liste des pages - self::$pages = $pagination['pages']; - // News en fonction de la pagination - for($i = $pagination['first']; $i < $pagination['last']; $i++) { - // Met en forme le tableau - $dateOn = mb_detect_encoding(strftime('%d %B %Y', $this->getData(['module', $this->getUrl(0),'posts', $newsIds[$i], 'publishedOn'])), 'UTF-8', true) - ? strftime('%d %B %Y', $this->getData(['module', $this->getUrl(0),'posts', $newsIds[$i], 'publishedOn'])) - : utf8_encode(strftime('%d %B %Y', $this->getData(['module', $this->getUrl(0),'posts', $newsIds[$i], 'publishedOn']))); - $dateOn .= ' à '; - $dateOn .= mb_detect_encoding(strftime('%H:%M', $this->getData(['module', $this->getUrl(0),'posts', $newsIds[$i], 'publishedOn'])), 'UTF-8', true) - ? strftime('%H:%M', $this->getData(['module', $this->getUrl(0),'posts', $newsIds[$i], 'publishedOn'])) - : utf8_encode(strftime('%H:%M', $this->getData(['module', $this->getUrl(0),'posts', $newsIds[$i], 'publishedOn']))); - if ($this->getData(['module', $this->getUrl(0),'posts', $newsIds[$i], 'publishedOff'])) { - $dateOff = mb_detect_encoding(strftime('%d %B %Y', $this->getData(['module', $this->getUrl(0),'posts', $newsIds[$i], 'publishedOff'])), 'UTF-8', true) - ? strftime('%d %B %Y', $this->getData(['module', $this->getUrl(0),'posts', $newsIds[$i], 'publishedOff'])) - : utf8_encode(strftime('%d %B %Y', $this->getData(['module', $this->getUrl(0),'posts', $newsIds[$i], 'publishedOff']))); - $dateOff .= ' à '; - $dateOff .= mb_detect_encoding(strftime('%H:%M', $this->getData(['module', $this->getUrl(0),'posts', $newsIds[$i], 'publishedOff'])), 'UTF-8', true) - ? strftime('%H:%M', $this->getData(['module', $this->getUrl(0),'posts', $newsIds[$i], 'publishedOff'])) - : utf8_encode(strftime('%H:%M', $this->getData(['module', $this->getUrl(0),'posts', $newsIds[$i], 'publishedOff']))); - } else { - $dateOff = 'Permanent'; - } - self::$news[] = [ - $this->getData(['module', $this->getUrl(0),'posts', $newsIds[$i], 'title']), - $dateOn, - $dateOff, - self::$states[$this->getData(['module', $this->getUrl(0),'posts', $newsIds[$i], 'state'])], - template::button('newsConfigEdit' . $newsIds[$i], [ - 'href' => helper::baseUrl() . $this->getUrl(0) . '/edit/' . $newsIds[$i]. '/' . $_SESSION['csrf'], - 'value' => template::ico('pencil') - ]), - template::button('newsConfigDelete' . $newsIds[$i], [ - 'class' => 'newsConfigDelete buttonRed', - 'href' => helper::baseUrl() . $this->getUrl(0) . '/delete/' . $newsIds[$i] . '/' . $_SESSION['csrf'], - 'value' => template::ico('cancel') - ]) - ]; - } // Valeurs en sortie $this->addOutput([ - 'title' => 'Configuration du module', - 'view' => 'config', + 'title' => 'Options de configuration', + 'view' => 'option', 'vendor' => [ 'tinycolorpicker' ] @@ -435,8 +449,7 @@ class news extends common { $newsIds[] = $newsId; } } - // Pagination - //$pagination = helper::pagination($newsIds, $this->getUrl(),$this->getData(['config','itemsperPage'])); + // Pagination selon le layout $pagination = helper::pagination($newsIds, $this->getUrl(),$this->getData(['module', $this->getUrl(0),'config', 'itemsperPage'])); // Nombre de colonnes self::$nbrCol = $this->getData(['module', $this->getUrl(0),'config', 'itemsperCol']); diff --git a/module/news/view/add/add.php b/module/news/view/add/add.php index b4427b96..59e3b9da 100644 --- a/module/news/view/add/add.php +++ b/module/news/view/add/add.php @@ -1,17 +1,16 @@
    -
    +
    'buttonGrey', 'href' => helper::baseUrl() . $this->getUrl(0) . '/config', - 'ico' => 'left', - 'value' => 'Retour' + 'value' => template::ico('left') ]); ?>
    -
    +
    true, - 'value' => 'Enregistrer en brouillon' + 'value' => 'Brouillon' ]); ?> true diff --git a/module/news/view/config/config.php b/module/news/view/config/config.php index 873c9a66..5527854a 100644 --- a/module/news/view/config/config.php +++ b/module/news/view/config/config.php @@ -1,102 +1,28 @@
    -
    +
    'buttonGrey', 'href' => helper::baseUrl() . 'page/edit/' . $this->getUrl(0),'posts', - 'ico' => 'left', - 'value' => 'Retour' + 'value' => template::ico('left') ]); ?>
    -
    +
    + helper::baseUrl() . $this->getUrl(0) . '/option', + 'value' => template::ico('sliders'), + 'help' => 'Options de configuration' + ]); ?> +
    +
    helper::baseUrl() . $this->getUrl(0) . '/add', - 'ico' => 'plus', - 'value' => 'News' + 'value' => template::ico('plus'), + 'help' => 'Rédiger une news' ]); ?>
    -
    - -
    -
    -
    -
    -
    -

    Paramètres du module

    -
    -
    - $this->getData(['module', $this->getUrl(0), 'config', 'feeds']), - 'help' => 'Flux limité aux articles de la première page.' - ]); ?> -
    -
    - 'Etiquette RSS', - 'value' => $this->getData(['module', $this->getUrl(0), 'config', 'feedsLabel']) - ]); ?> -
    -
    -
    -
    - 'Nombre de colonnes', - 'selected' => $this->getData(['module', $this->getUrl(0),'config', 'itemsperCol']) - ]); ?> -
    -
    - 'Articles par page', - 'selected' => $this->getData(['module', $this->getUrl(0),'config', 'itemsperPage']) - ]); ?> -
    -
    - 'Abrégé de l\'article', - 'selected' => $this->getData(['module', $this->getUrl(0),'config', 'height']) - ]); ?> -
    -
    -
    -
    -
    -
    -
    -
    -

    Thème du module

    -
    -
    - 'Bordure', - 'selected' => $this->getData(['module', $this->getUrl(0),'theme', 'borderStyle']) - ]); ?> -
    -
    - 'Epaisseur', - 'selected' => $this->getData(['module', $this->getUrl(0),'theme', 'borderWidth']) - ]); ?> -
    -
    - 'colorPicker', - 'help' => 'Couleur visible en l\'absence d\'une image.
    Le curseur horizontal règle le niveau de transparence.', - 'label' => 'Couleur de la bordure', - 'value' => $this->getData(['module', $this->getUrl(0),'theme', 'borderColor']) - ]); ?> -
    -
    - 'colorPicker', - 'help' => 'Couleur visible en l\'absence d\'une image.
    Le curseur horizontal règle le niveau de transparence.', - 'label' => 'Couleur du fond', - 'value' => $this->getData(['module', $this->getUrl(0),'theme', 'backgroundColor']) - ]); ?> -
    -
    -
    -
    + diff --git a/module/news/view/edit/edit.php b/module/news/view/edit/edit.php index 927be92d..2cc71bc0 100644 --- a/module/news/view/edit/edit.php +++ b/module/news/view/edit/edit.php @@ -4,14 +4,13 @@ 'buttonGrey', 'href' => helper::baseUrl() . $this->getUrl(0) . '/config', - 'ico' => 'left', - 'value' => 'Retour' + 'value' => template::ico('left') ]); ?>
    -
    +
    true, - 'value' => 'Enregistrer en brouillon' + 'value' => 'Brouillon' ]); ?> true diff --git a/module/news/view/option/option.css b/module/news/view/option/option.css new file mode 100644 index 00000000..52709ea6 --- /dev/null +++ b/module/news/view/option/option.css @@ -0,0 +1,18 @@ +/** + * This file is part of Zwii. + * + * For full copyright and license information, please see the LICENSE + * file that was distributed with this source code. + * + * @author Rémi Jean + * @copyright Copyright (C) 2008-2018, Rémi Jean + * @author Frédéric Tempez + * @copyright Copyright (C) 2018-2022, Frédéric Tempez + * @license GNU General Public License, version 3 + * @link http://zwiicms.fr/ + */ + + +/** NE PAS EFFACER +* admin.css +*/ \ No newline at end of file diff --git a/module/news/view/option/option.php b/module/news/view/option/option.php new file mode 100644 index 00000000..463439ec --- /dev/null +++ b/module/news/view/option/option.php @@ -0,0 +1,95 @@ + +
    +
    + 'buttonGrey', + 'href' => helper::baseUrl() . $this->getUrl(0) . '/config', + 'value' => template::ico('left') + ]); ?> +
    +
    + +
    +
    +
    +
    +
    +

    Paramètres du module

    +
    +
    + $this->getData(['module', $this->getUrl(0), 'config', 'feeds']), + 'help' => 'Flux limité aux articles de la première page.' + ]); ?> +
    +
    + 'Etiquette RSS', + 'value' => $this->getData(['module', $this->getUrl(0), 'config', 'feedsLabel']) + ]); ?> +
    +
    +
    +
    + 'Nombre de colonnes', + 'selected' => $this->getData(['module', $this->getUrl(0),'config', 'itemsperCol']) + ]); ?> +
    +
    + 'Articles par page', + 'selected' => $this->getData(['module', $this->getUrl(0),'config', 'itemsperPage']) + ]); ?> +
    +
    + 'Abrégé de l\'article', + 'selected' => $this->getData(['module', $this->getUrl(0),'config', 'height']) + ]); ?> +
    +
    +
    +
    +
    +
    +
    +
    +

    Thème du module

    +
    +
    + 'Bordure', + 'selected' => $this->getData(['module', $this->getUrl(0),'theme', 'borderStyle']) + ]); ?> +
    +
    + 'Epaisseur', + 'selected' => $this->getData(['module', $this->getUrl(0),'theme', 'borderWidth']) + ]); ?> +
    +
    + 'colorPicker', + 'help' => 'Couleur visible en l\'absence d\'une image.
    Le curseur horizontal règle le niveau de transparence.', + 'label' => 'Couleur de la bordure', + 'value' => $this->getData(['module', $this->getUrl(0),'theme', 'borderColor']) + ]); ?> +
    +
    + 'colorPicker', + 'help' => 'Couleur visible en l\'absence d\'une image.
    Le curseur horizontal règle le niveau de transparence.', + 'label' => 'Couleur du fond', + 'value' => $this->getData(['module', $this->getUrl(0),'theme', 'backgroundColor']) + ]); ?> +
    +
    +
    +
    +
    + +
    Version n° + +
    \ No newline at end of file diff --git a/module/redirection/view/config/config.php b/module/redirection/view/config/config.php index ff421b39..b786dbf1 100644 --- a/module/redirection/view/config/config.php +++ b/module/redirection/view/config/config.php @@ -1,14 +1,13 @@
    -
    +
    'buttonGrey', 'href' => helper::baseUrl() . 'page/edit/' . $this->getUrl(0), - 'ico' => 'left', - 'value' => 'Retour' + 'value' => template::ico('left') ]); ?>
    -
    +
    diff --git a/module/search/view/config/config.php b/module/search/view/config/config.php index 68b6ab8f..ac8bcfc5 100644 --- a/module/search/view/config/config.php +++ b/module/search/view/config/config.php @@ -1,14 +1,13 @@
    -
    +
    'buttonGrey', 'href' => helper::baseUrl() . 'page/edit/' . $this->getUrl(0), - 'ico' => 'left', - 'value' => 'Retour' + 'value' => template::ico('left') ]); ?>
    -
    +