ZwiiCMS/core/module/install/install.php

479 lines
14 KiB
PHP
Raw Permalink Normal View History

2018-04-02 08:29:19 +02:00
<?php
/**
* This file is part of Zwii.
* For full copyright and license information, please see the LICENSE
* file that was distributed with this source code.
*
* @author Rémi Jean <remi.jean@outlook.com>
* @copyright Copyright (C) 2008-2018, Rémi Jean
2021-02-17 13:49:58 +01:00
* @author Frédéric Tempez <frederic.tempez@outlook.com>
2024-01-14 19:31:28 +01:00
* @copyright Copyright (C) 2018-2024, Frédéric Tempez
* @license CC Attribution-NonCommercial-NoDerivatives 4.0 International
* @link http://zwiicms.fr/
2018-04-02 08:29:19 +02:00
*/
2022-09-29 08:45:59 +02:00
class install extends common
{
2018-04-02 08:29:19 +02:00
public static $actions = [
'index' => self::GROUP_VISITOR,
2022-09-21 15:09:25 +02:00
"postinstall" => self::GROUP_VISITOR,
2018-04-02 08:29:19 +02:00
'steps' => self::GROUP_ADMIN,
'update' => self::GROUP_ADMIN
2018-04-02 08:29:19 +02:00
];
// Type de proxy
public static $proxyType = [
'tcp://' => 'TCP',
'http://' => 'HTTP'
];
public static $updateButtonText = 'Réinstaller';
2018-04-02 08:29:19 +02:00
public static $newVersion;
// Fichiers des Interface
2022-09-21 19:51:46 +02:00
public static $i18nFiles = [];
2022-09-21 16:02:06 +02:00
2018-04-02 08:29:19 +02:00
/**
2022-09-21 15:09:25 +02:00
* Pré-installation - choix de la langue
2018-04-02 08:29:19 +02:00
*/
2022-09-29 08:45:59 +02:00
public function index()
{
2022-09-21 15:09:25 +02:00
// Accès refusé
2022-09-29 08:45:59 +02:00
if ($this->getData(['user']) !== []) {
2022-09-21 15:09:25 +02:00
// Valeurs en sortie
$this->addOutput([
'access' => false
]);
}
2023-02-21 15:16:41 +01:00
// Soumission du formulaire
if (
2023-07-16 18:14:19 +02:00
//$this->getUser('permission', __CLASS__, __FUNCTION__) === true &&
$this->isPost()
) {
2023-04-24 22:28:53 +02:00
2023-02-21 15:16:41 +01:00
$lang = $this->getInput('installLanguage');
2023-04-12 21:38:12 +02:00
// Pour la suite de l'installation
// setcookie('ZWII_UI', $lang, time() + 3600, helper::baseUrl(false, false), '', false, false);
2023-04-26 21:40:09 +02:00
2023-04-12 21:38:12 +02:00
$_SESSION['ZWII_UI'] = $this->getInput('installLanguage');
2023-02-21 15:16:41 +01:00
// Valeurs en sortie
$this->addOutput([
2023-04-12 21:54:07 +02:00
'redirect' => helper::baseUrl() . 'install/postinstall'
2023-02-21 15:16:41 +01:00
]);
2022-09-21 15:09:25 +02:00
}
// Liste des langues UI disponibles
if (is_dir(self::I18N_DIR)) {
2023-03-01 15:50:41 +01:00
foreach ($this->getData(['language']) as $lang => $value) {
2023-02-20 15:22:58 +01:00
self::$i18nFiles[$lang] = self::$languages[$lang];
2022-09-21 15:09:25 +02:00
}
}
$this->addOutput([
'display' => self::DISPLAY_LAYOUT_LIGHT,
'title' => helper::translate('ZwiiCMS Installation'),
2022-09-21 15:09:25 +02:00
'view' => 'index'
]);
}
/**
* post Installation
*/
2022-09-29 08:45:59 +02:00
public function postInstall()
{
2018-04-02 08:29:19 +02:00
// Accès refusé
2022-09-29 08:45:59 +02:00
if ($this->getData(['user']) !== []) {
2018-04-02 08:29:19 +02:00
// Valeurs en sortie
$this->addOutput([
'access' => false
2018-04-02 08:29:19 +02:00
]);
}
// Accès autorisé
else {
// Soumission du formulaire
if (
2023-07-16 18:14:19 +02:00
//$this->getUser('permission', __CLASS__, __FUNCTION__) !== true &&
$this->isPost()
) {
2022-10-05 06:50:56 +02:00
2020-09-09 17:21:02 +02:00
$success = true;
2018-04-02 08:29:19 +02:00
// Double vérification pour le mot de passe
2022-09-29 08:45:59 +02:00
if ($this->getInput('installPassword', helper::FILTER_STRING_SHORT, true) !== $this->getInput('installConfirmPassword', helper::FILTER_STRING_SHORT, true)) {
2018-04-02 08:29:19 +02:00
self::$inputNotices['installConfirmPassword'] = 'Incorrect';
2020-09-09 17:21:02 +02:00
$success = false;
2018-04-02 08:29:19 +02:00
}
2020-09-09 17:21:02 +02:00
// Utilisateur
2018-04-02 08:29:19 +02:00
$userFirstname = $this->getInput('installFirstname', helper::FILTER_STRING_SHORT, true);
$userLastname = $this->getInput('installLastname', helper::FILTER_STRING_SHORT, true);
$userMail = $this->getInput('installMail', helper::FILTER_MAIL, true);
$userId = $this->getInput('installId', helper::FILTER_ID, true);
2022-02-26 14:46:43 +01:00
2023-06-13 20:58:39 +02:00
// Validation de la langue transmise
self::$i18nUI = $_SESSION['ZWII_UI'];
self::$i18nUI = array_key_exists(self::$i18nUI, self::$languages) ? self::$i18nUI : 'fr_FR';
// par défaut le contenu est la langue d'installation
$_SESSION['ZWII_CONTENT'] = self::$i18nUI;
// Création du dossier de langue avec le marqueur de langue par défaut
if (!is_dir(self::DATA_DIR . $_SESSION['ZWII_CONTENT'])) {
mkdir(self::DATA_DIR . $_SESSION['ZWII_CONTENT']);
touch(self::DATA_DIR . $_SESSION['ZWII_CONTENT'] . '/.default');
}
// Installation du site de test
if (
$this->getInput('installDefaultData', helper::FILTER_BOOLEAN) === false
&& $_SESSION['ZWII_CONTENT'] === 'fr_FR'
) {
$sample = true;
}
$this->initData('page', $_SESSION['ZWII_CONTENT'], $sample);
$this->initData('module', $_SESSION['ZWII_CONTENT'], $sample);
$this->initData('locale', $_SESSION['ZWII_CONTENT'], $sample);
2020-09-08 21:25:42 +02:00
// Création de l'utilisateur si les données sont complétées.
// success retour de l'enregistrement des données
2023-06-13 20:58:39 +02:00
$this->setData([
'user',
$userId,
[
'firstname' => $userFirstname,
'forgot' => 0,
'group' => self::GROUP_ADMIN,
'profil' => 0,
'lastname' => $userLastname,
2020-10-31 17:55:54 +01:00
'pseudo' => 'Admin',
'signature' => 1,
'mail' => $userMail,
'password' => $this->getInput('installPassword', helper::FILTER_PASSWORD, true),
2023-06-13 20:58:39 +02:00
'language' => $_SESSION['ZWII_CONTENT']
]
]);
2022-02-26 14:46:43 +01:00
2023-06-13 20:58:39 +02:00
// Envoie le mail
// Sent contient true si réussite sinon code erreur d'envoi en clair
$this->sendMail(
$userMail,
'Installation de votre site',
'Bonjour' . ' <strong>' . $userFirstname . ' ' . $userLastname . '</strong>,<br><br>' .
'Voici les détails de votre installation.<br><br>' .
'<strong>URL du site :</strong> <a href="' . helper::baseUrl(false) . '" target="_blank">' . helper::baseUrl(false) . '</a><br>' .
'<strong>Identifiant du compte :</strong> ' . $this->getInput('installId') . '<br>',
null,
2023-10-11 21:07:34 +02:00
'no-reply@localhost'
2023-06-13 20:58:39 +02:00
);
// Nettoyage fr par défaut
if (
$_SESSION['ZWII_CONTENT'] !== 'fr_FR'
) {
if (is_dir(self::DATA_DIR . 'fr_FR'))
2023-07-19 18:07:12 +02:00
$this->deleteDir(self::DATA_DIR . 'fr_FR');
2023-06-13 20:58:39 +02:00
}
2023-06-13 20:58:39 +02:00
// Sauvegarder la configuration du Proxy
$this->setData(['config', 'proxyType', $this->getInput('installProxyType')]);
$this->setData(['config', 'proxyUrl', $this->getInput('installProxyUrl')]);
$this->setData(['config', 'proxyPort', $this->getInput('installProxyPort', helper::FILTER_INT)]);
2023-06-12 21:08:33 +02:00
2023-06-13 20:58:39 +02:00
// Images exemples livrées dans tous les cas
try {
// Décompression dans le dossier de fichier temporaires
if (file_exists(self::TEMP_DIR . 'files.tar.gz')) {
unlink(self::TEMP_DIR . 'files.tar.gz');
}
2023-06-13 20:58:39 +02:00
if (file_exists(self::TEMP_DIR . 'files.tar')) {
unlink(self::TEMP_DIR . 'files.tar');
2022-09-29 08:45:59 +02:00
}
2023-06-13 20:58:39 +02:00
copy('core/module/install/ressource/files.tar.gz', self::TEMP_DIR . 'files.tar.gz');
$pharData = new PharData(self::TEMP_DIR . 'files.tar.gz');
$pharData->decompress();
// Installation
$pharData->extractTo(__DIR__ . '/../../../', null, true);
} catch (Exception $e) {
$success = $e->getMessage();
}
2022-09-29 08:45:59 +02:00
2023-06-13 20:58:39 +02:00
// Nettoyage
unlink(self::TEMP_DIR . 'files.tar.gz');
unlink(self::TEMP_DIR . 'files.tar');
2023-06-13 20:58:39 +02:00
// Créer le dossier des fontes
if (!is_dir(self::DATA_DIR . 'font')) {
mkdir(self::DATA_DIR . 'font');
}
2023-01-01 11:12:30 +01:00
2023-06-13 20:58:39 +02:00
// Copie des langues de l'UI et génération de la base de données
if (is_dir(self::I18N_DIR) === false) {
mkdir(self::I18N_DIR);
}
2022-09-29 08:45:59 +02:00
2023-06-13 20:58:39 +02:00
// Créer la base de données des langues
$this->copyDir('core/module/install/ressource/i18n', self::I18N_DIR);
2023-01-01 11:12:30 +01:00
2023-06-13 20:58:39 +02:00
// Fixe l'adresse from pour les envois d'email
$this->setData(['config', 'smtp', 'from', 'no-reply@' . str_replace('www.', '', $_SERVER['HTTP_HOST'])]);
2023-06-13 20:58:39 +02:00
// Valeurs en sortie
$this->addOutput([
'redirect' => helper::baseUrl(),
'notification' => helper::translate('Installation terminée'),
'state' => true
]);
2018-04-02 08:29:19 +02:00
}
2022-09-21 19:51:46 +02:00
2018-04-02 08:29:19 +02:00
// Valeurs en sortie
$this->addOutput([
'display' => self::DISPLAY_LAYOUT_LIGHT,
'title' => helper::translate('Installation'),
2022-09-21 15:09:25 +02:00
'view' => 'postinstall'
2018-04-02 08:29:19 +02:00
]);
}
}
/**
* Étapes de mise à jour
*/
2022-09-29 08:45:59 +02:00
public function steps()
{
2023-07-04 19:03:27 +02:00
// Action interdite
if (
$this->getUser('permission', __CLASS__, __FUNCTION__) !== true
) {
// Valeurs en sortie
$this->addOutput([
'access' => false
]);
} else {
switch ($this->getInput('step', helper::FILTER_INT)) {
// Préparation
case 1:
$success = true;
$message = '';
// RAZ la mise à jour auto
$this->setData(['core', 'updateAvailable', false]);
// Backup du dossier Data
helper::autoBackup(self::BACKUP_DIR, ['backup', 'tmp', 'file']);
// Sauvegarde htaccess
if ($this->getData(['config', 'autoUpdateHtaccess'])) {
$success = copy('.htaccess', '.htaccess' . '.bak');
$message = $success ? '' : 'Erreur de copie du fichier htaccess';
2023-07-04 19:03:27 +02:00
}
// Nettoyage des fichiers d'installation précédents
if ($success && file_exists(self::TEMP_DIR . 'update.tar.gz')) {
$success = unlink(self::TEMP_DIR . 'update.tar.gz');
2023-07-22 22:25:36 +02:00
$message = $success ? '' : 'Impossible d\'effacer la mise à jour précédente';
2023-07-04 19:03:27 +02:00
}
if ($success && file_exists(self::TEMP_DIR . 'update.tar')) {
$success = unlink(self::TEMP_DIR . 'update.tar');
$message = $success ? '' : 'Impossible d\'effacer la mise à jour précédente';
2023-07-04 19:03:27 +02:00
}
// Sauvegarde le message dans le journal
if (!empty($message)) {
$this->saveLog($message);
}
2023-07-04 19:03:27 +02:00
// Valeurs en sortie
$this->addOutput([
'display' => self::DISPLAY_JSON,
'content' => [
'success' => $success,
'data' => $success ? null : json_encode($message, JSON_UNESCAPED_UNICODE)
]
]);
break;
// Téléchargement
case 2:
$success = true;
$message = '';
$this->secure_file_put_contents(self::TEMP_DIR . 'update.tar.gz', helper::getUrlContents(common::ZWII_UPDATE_URL . common::ZWII_UPDATE_CHANNEL . '/update.tar.gz'));
2023-07-04 19:03:27 +02:00
$md5origin = helper::getUrlContents(common::ZWII_UPDATE_URL . common::ZWII_UPDATE_CHANNEL . '/update.md5');
$md5origin = explode(' ', $md5origin);
$md5target = md5_file(self::TEMP_DIR . 'update.tar.gz');
// Vérifier si les checksums correspondent
if ($md5origin[0] === $md5target) {
$success = true;
$message = "";
} else {
$success = false;
$message = 'Erreur de téléchargement ou de somme de contrôle';
if (file_exists(self::TEMP_DIR . 'update.tar.gz')) {
unlink(self::TEMP_DIR . 'update.tar.gz');
2023-07-23 18:41:15 +02:00
http_response_code(500);
}
}
// Sauvegarde le message dans le journal
if (!empty($message)) {
$this->saveLog($message);
}
2023-07-04 19:03:27 +02:00
// Valeurs en sortie
$this->addOutput([
'display' => self::DISPLAY_JSON,
'content' => [
'success' => $success,
'data' => json_encode($message, JSON_UNESCAPED_UNICODE)
2023-07-04 19:03:27 +02:00
]
]);
break;
// Installation
case 3:
$success = true;
$message = '';
2023-07-04 19:03:27 +02:00
// Check la réécriture d'URL avant d'écraser les fichiers
if (helper::checkRewrite()) {
touch(self::DATA_DIR . '.rewrite');
}
2023-07-04 19:03:27 +02:00
// Décompression et installation
try {
// Décompression dans le dossier de fichier temporaires
$pharData = new PharData(self::TEMP_DIR . 'update.tar.gz');
$pharData->decompress();
// Installation
$pharData->extractTo(__DIR__ . '/../../../', null, true);
} catch (Exception $e) {
$message = $e->getMessage();
$success = false;
http_response_code(500);
2023-07-04 19:03:27 +02:00
}
2023-07-04 19:03:27 +02:00
// Nettoyage du dossier
if (file_exists(self::TEMP_DIR . 'update.tar.gz')) {
unlink(self::TEMP_DIR . 'update.tar.gz');
}
if (file_exists(self::TEMP_DIR . 'update.tar')) {
unlink(self::TEMP_DIR . 'update.tar');
}
// Sauvegarde le message dans le journal
if (!empty($message)) {
$this->saveLog($message);
}
2023-07-04 19:03:27 +02:00
// Valeurs en sortie
$this->addOutput([
'display' => self::DISPLAY_JSON,
'content' => [
'success' => $success,
'data' => json_encode($message, JSON_UNESCAPED_UNICODE)
2023-07-04 19:03:27 +02:00
]
]);
break;
// Configuration
case 4:
$success = true;
2023-10-06 17:33:54 +02:00
$message = '';
2023-07-31 20:06:15 +02:00
/**
* Restaure le fichier htaccess
*/
2023-07-04 19:03:27 +02:00
// Recopie htaccess
if (
$this->getData(['config', 'autoUpdateHtaccess']) === true
2023-07-04 19:03:27 +02:00
) {
// L'écraser avec le backup
2023-10-06 17:33:54 +02:00
$success = copy('.htaccess.bak', '.htaccess');
if ($success === false) {
$message = helper::translate('La copie de sauvegarde du fichier htaccess n\'a pas été restaurée !');
http_response_code(500);
}
2023-07-04 19:03:27 +02:00
// Effacer le backup
unlink('.htaccess.bak');
2023-07-31 20:06:15 +02:00
} else {
/**
* Restaure la réécriture d'URL
*/
if (file_exists(self::DATA_DIR . '.rewrite')) { // Ajout des lignes dans le .htaccess
2023-07-31 20:06:15 +02:00
$fileContent = file_get_contents('.htaccess');
$rewriteData = PHP_EOL .
'# URL rewriting' . PHP_EOL .
'<IfModule mod_rewrite.c>' . PHP_EOL .
"\tRewriteEngine on" . PHP_EOL .
"\tRewriteBase " . helper::baseUrl(false, false) . PHP_EOL .
"\tRewriteCond %{REQUEST_FILENAME} !-f" . PHP_EOL .
"\tRewriteCond %{REQUEST_FILENAME} !-d" . PHP_EOL .
"\tRewriteRule ^(.*)$ index.php?$1 [L]" . PHP_EOL .
'</IfModule>' . PHP_EOL .
'# URL rewriting' . PHP_EOL;
$fileContent = str_replace('# URL rewriting', $rewriteData, $fileContent);
$success = $this->secure_file_put_contents(
2023-07-31 20:06:15 +02:00
'.htaccess',
$fileContent
);
unlink(self::DATA_DIR . '.rewrite');
2023-07-31 20:06:15 +02:00
}
2023-07-04 19:03:27 +02:00
}
2023-08-27 23:13:48 +02:00
/**
* Met à jour les dictionnaires des langues depuis les nouveaux modèles installés
*/
require_once('core/module/install/ressource/defaultdata.php');
$installedLanguages = $this->getData(['language']);
$defaultLanguages = init::$defaultData['language'];
foreach ($installedLanguages as $key => $value) {
if (
isset($defaultLanguages[$key]['date']) &&
$defaultLanguages[$key]['date'] > $value['date'] &&
isset($defaultLanguages[$key]['version']) &&
$defaultLanguages[$key]['version'] >= $value['version']
) {
copy('core/module/install/ressource/i18n/' . $key . '.json', self::I18N_DIR . $key . '.json');
$this->setData(['language', $key, $defaultLanguages[$key]]);
}
}
// Sauvegarde le message dans le journal
if (!empty($message)) {
$this->saveLog($message);
}
2023-07-04 19:03:27 +02:00
// Valeurs en sortie
$this->addOutput([
'display' => self::DISPLAY_JSON,
'content' => [
2023-10-06 17:33:54 +02:00
'success' => $success,
'data' => json_encode($message, JSON_UNESCAPED_UNICODE)
2023-07-04 19:03:27 +02:00
]
]);
}
2018-04-02 08:29:19 +02:00
}
}
/**
* Mise à jour
*/
2022-09-29 08:45:59 +02:00
public function update()
{
// Action interdite
if (
$this->getUser('permission', __CLASS__, __FUNCTION__) !== true
) {
// Valeurs en sortie
$this->addOutput([
'access' => false
]);
} else {
// Nouvelle version
self::$newVersion = helper::getUrlContents(common::ZWII_UPDATE_URL . common::ZWII_UPDATE_CHANNEL . '/version');
// Variable de version
if (helper::checkNewVersion(common::ZWII_UPDATE_CHANNEL)) {
self::$updateButtonText = helper::translate('Mise à jour');
}
// Valeurs en sortie
$this->addOutput([
'display' => self::DISPLAY_LAYOUT_LIGHT,
'title' => helper::translate(self::$updateButtonText),
'view' => 'update'
]);
}
2018-04-02 08:29:19 +02:00
}
2023-01-01 11:12:30 +01:00
}