From 1fd680518613e6a54015ecd52092fcd196636030 Mon Sep 17 00:00:00 2001 From: fredtempez Date: Sat, 5 Jun 2021 16:40:16 +0200 Subject: [PATCH] =?UTF-8?q?Addon=20version=20actualis=C3=A9e?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- core/module/addon/addon.php | 416 ++++++++++++------ core/module/addon/view/index/index.php | 85 ++-- core/module/addon/view/item/item.css | 14 + core/module/addon/view/item/item.php | 41 ++ core/module/addon/view/store/store.css | 18 + core/module/addon/view/store/store.php | 15 + core/module/addon/view/upload/upload.css | 18 + .../module/addon/view/upload/upload.help.html | 6 + core/module/addon/view/upload/upload.php | 52 +++ 9 files changed, 483 insertions(+), 182 deletions(-) create mode 100644 core/module/addon/view/item/item.css create mode 100644 core/module/addon/view/item/item.php create mode 100644 core/module/addon/view/store/store.css create mode 100644 core/module/addon/view/store/store.php create mode 100644 core/module/addon/view/upload/upload.css create mode 100644 core/module/addon/view/upload/upload.help.html create mode 100644 core/module/addon/view/upload/upload.php diff --git a/core/module/addon/addon.php b/core/module/addon/addon.php index b88539ea..7899ffea 100644 --- a/core/module/addon/addon.php +++ b/core/module/addon/addon.php @@ -20,21 +20,33 @@ class addon extends common { public static $actions = [ 'index' => self::GROUP_ADMIN, - 'moduleDelete' => self::GROUP_ADMIN, + 'delete' => self::GROUP_ADMIN, 'export' => self::GROUP_ADMIN, - 'import' => self::GROUP_ADMIN + 'import' => self::GROUP_ADMIN, + 'store' => self::GROUP_ADMIN, + 'item' => self::GROUP_ADMIN, + 'upload' => self::GROUP_ADMIN, + 'uploadItem'=> self::GROUP_ADMIN ]; + const URL_STORE = 'http://zwiicms.fr/?modules/'; + const BASEURL_STORE = 'http://zwiicms.fr/'; + // 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 moduleDelete() { + public function delete() { // Jeton incorrect if ($this->getUrl(3) !== $_SESSION['csrf']) { @@ -72,6 +84,270 @@ class addon extends common { } } + /*** + * 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); + $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::urlGetContents(self::URL_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'); + } + // 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::urlGetContents(self::URL_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]['title'].'', + $store[$key]['fileVersion'], + mb_detect_encoding(strftime('%d %B %Y', $store[$key]['fileDate']), 'UTF-8', true) + ? strftime('%d %B %Y', $store[$key]['fileDate']) + : utf8_encode(strftime('%d %B %Y', $store[$key]['fileDate'])), + 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::urlGetContents(self::URL_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 @@ -96,11 +372,11 @@ class addon extends common { $infoModules[$key]['realName'], $infoModules[$key]['version'], implode(', ', array_keys($inPagesTitle,$key)), - //array_key_exists('delete',$infoModules[$key]) && $infoModules[$key]['delete'] === true && implode(', ',array_keys($inPages,$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) . '/moduleDelete/' . $key . '/' . $_SESSION['csrf'], + 'href' => helper::baseUrl() . $this->getUrl(0) . '/delete/' . $key . '/' . $_SESSION['csrf'], 'value' => template::ico('cancel') ]) : '', @@ -119,127 +395,9 @@ class addon extends common { ]; } - // Retour du formulaire ? - if($this->isPost()) { - // Installation d'un module - $success = true; - $checkValidMaj = $this->getInput('configModulesCheck', helper::FILTER_BOOLEAN); - $zipFilename = $this->getInput('configModulesInstallation', helper::FILTER_STRING_SHORT); - if( $zipFilename !== ''){ - $tempFolder = 'datamodules';//uniqid(); - $zip = new ZipArchive(); - if ($zip->open(self::FILE_DIR.'source/'.$zipFilename) === TRUE) { - $notification = 'Archive ouverte'; - mkdir (self::TEMP_DIR . $tempFolder); - $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 - if( $infoModules[$moduleName]['update'] >= $update ) $valUpdate = true; - - // Module déjà installé ? - $moduleInstal = false; - foreach( self::$modInstal as $key=>$value){ - if($moduleName === $value[0]){ - $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 || $checkValidMaj); - - // 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'; - } - } - - $this->addOutput([ - 'redirect' => helper::baseUrl() . $this->getUrl(), - 'notification' => $notification, - 'state' => $success - ]); - } - // Valeurs en sortie $this->addOutput([ - 'title' => 'Gestion des modules', + 'title' => 'Modules installés', 'view' => 'index' ]); } @@ -315,14 +473,13 @@ class addon extends common { $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); - // Valeurs en sortie - $this->addOutput([ - 'display' => self::DISPLAY_RAW - ]); unlink($fileName); $this->removeDir($tmpFolder); exit(); @@ -350,7 +507,7 @@ class addon extends common { 'notification' => 'Action non autorisée' ]); } - else{ + else { // Soumission du formulaire if($this->isPost()) { // Récupérer le fichier et le décompacter @@ -423,4 +580,5 @@ class addon extends common { ]); } } + } diff --git a/core/module/addon/view/index/index.php b/core/module/addon/view/index/index.php index deadb2d6..5b868422 100644 --- a/core/module/addon/view/index/index.php +++ b/core/module/addon/view/index/index.php @@ -1,57 +1,36 @@ - -
-
- 'buttonGrey', - 'href' => helper::baseUrl(), - 'ico' => 'left', - 'value' => 'Retour' - ]); ?> -
-
- 'buttonHelp', - 'ico' => 'help', - 'value' => 'Aide' - ]); ?> -
-
- 'Valider', - 'ico' => 'check' - ]); ?> -
-
- - -
- -
- -
-
-
-

Installer ou mettre à jour un module

-
-
- 'Archive ZIP :', - 'type' => 2 - ]); ?> -
-
-
-
- false, - 'help' => 'Permet de forcer une mise à jour même si la version du module est inférieure ou égale à celle du module installé.', - ]); ?> -
-
-
-
+
+
+ 'buttonGrey', + 'href' => helper::baseUrl(), + 'ico' => 'left', + 'value' => 'Retour' + ]); ?>
- +
+ 'buttonHelp', + 'ico' => 'help', + 'value' => 'Aide' + ]); ?> +
+
+ helper::baseUrl() . 'addon/upload', + 'value' => 'Téléverser un module' + ]); ?> +
+
+ helper::baseUrl() . 'addon/store', + 'value' => 'Catalogue en ligne' + ]); ?> +
+
+ +
+ +
diff --git a/core/module/addon/view/item/item.css b/core/module/addon/view/item/item.css new file mode 100644 index 00000000..35422ddd --- /dev/null +++ b/core/module/addon/view/item/item.css @@ -0,0 +1,14 @@ +/** + * 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-2021, Frédéric Tempez + * @license GNU General Public License, version 3 + * @link http://zwiicms.fr/ + */ + diff --git a/core/module/addon/view/item/item.php b/core/module/addon/view/item/item.php new file mode 100644 index 00000000..196e6529 --- /dev/null +++ b/core/module/addon/view/item/item.php @@ -0,0 +1,41 @@ +
+
+
+
+ +
+
+
+
+
+ '; + ?> +
+
+
+
+ +
+
+
+
+ +
+
+
+
+ Auteur : + + +
+
+
+
+ Licence : + + +
+
+
\ No newline at end of file diff --git a/core/module/addon/view/store/store.css b/core/module/addon/view/store/store.css new file mode 100644 index 00000000..5a91e7a7 --- /dev/null +++ b/core/module/addon/view/store/store.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-2021, 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/core/module/addon/view/store/store.php b/core/module/addon/view/store/store.php new file mode 100644 index 00000000..803f5712 --- /dev/null +++ b/core/module/addon/view/store/store.php @@ -0,0 +1,15 @@ +
+
+ 'buttonGrey', + 'href' => helper::baseUrl() . 'addon', + 'ico' => 'left', + 'value' => 'Retour' + ]); ?> +
+
+ + + + + \ No newline at end of file diff --git a/core/module/addon/view/upload/upload.css b/core/module/addon/view/upload/upload.css new file mode 100644 index 00000000..5a91e7a7 --- /dev/null +++ b/core/module/addon/view/upload/upload.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-2021, 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/core/module/addon/view/upload/upload.help.html b/core/module/addon/view/upload/upload.help.html new file mode 100644 index 00000000..227af154 --- /dev/null +++ b/core/module/addon/view/upload/upload.help.html @@ -0,0 +1,6 @@ +

IMPORTER OU METTRE A JOUR

+

Vous avez au préalable chargé le fichier zip du module sur votre serveur en utilisant le 'Catalogue en ligne', écran précédent.

+

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/addon/view/upload/upload.php b/core/module/addon/view/upload/upload.php new file mode 100644 index 00000000..5fcd7cdc --- /dev/null +++ b/core/module/addon/view/upload/upload.php @@ -0,0 +1,52 @@ + +
+
+ 'buttonGrey', + 'href' => helper::baseUrl() . 'addon', + 'ico' => 'left', + 'value' => 'Retour' + ]); ?> +
+
+ 'buttonHelp', + 'ico' => 'help', + 'value' => 'Aide' + ]); ?> +
+
+ 'Valider', + 'ico' => 'check' + ]); ?> +
+
+ +
+ +
+
+
+
+

Installer ou mettre à jour un module

+
+
+ 'Archive ZIP :', + 'type' => 2 + ]); ?> +
+
+
+
+ false, + 'help' => 'Permet de forcer une mise à jour même si la version du module est inférieure ou égale à celle du module installé.', + ]); ?> +
+
+
+
+
+