<?php
/*
 * Contenu d'une page statique pour téléverser un thème sur le site.
 *
 * Il faut avoir un compte sur le site.
 *
 * Ne pas enregistrer cette page statique avec l'éditeur de PluXml,
 * sinon les caractères anti-slash seront supprimés.
 *
 * chr(92) pour remplacer le caractère antislash
 * updated on 2022-11-22
 * */

const REQUIRED_FILES = array(
	'infos\.xml',
	'preview\.(?:jpe?g|png|webp)',
	'home\.php',
	'article\.php',
	'categorie\.php',
	'static\.php',
);

const XML_HEADER = "<?xml version='1.0' encoding='".PLX_CHARSET."'?>" . PHP_EOL;

include PLX_ROOT . 'core/lib/class.plx.token.php';

# From core/admin/parametres_themes.php
function getInfos($filename) {
	$result = array(
		'title'			=> '',
		'author'		=> '',
		'version'		=> '',
		'date'			=> '',
		'site'			=> '',
		'description'	=> '',
	);
	if(is_file($filename)) {
		$data = implode('',file($filename));
		$parser = xml_parser_create(PLX_CHARSET);
		xml_parser_set_option($parser,XML_OPTION_CASE_FOLDING,0);
		xml_parser_set_option($parser,XML_OPTION_SKIP_WHITE,0);
		xml_parse_into_struct($parser,$data,$values,$iTags);
		xml_parser_free($parser);

		foreach($iTags as $k=>$v) {
			if(array_key_exists($k, $result)) {
				$w = $v[0];
				if(isset($values[$w]['value'])) {
					$result[$k] = $values[$w]['value'];
				}
			}
		}
	}

	return $result;
}

# From core/lib/class.plx.admin.php
function nextIdArticle($aKeys) {
		if(is_array($aKeys) and count($aKeys) > 0) {
			rsort($aKeys);
			return str_pad(intval($aKeys['0']) + 1, 4, '0', STR_PAD_LEFT);
		} else {
			return '0001';
		}
	}

$plxMotor = $this->plxMotor;

$target = dirname($_SERVER['SCRIPT_FILENAME']) . '/' . $plxMotor->aConf['racine_themes'];

if(!empty($_FILES['theme'])) {
	plxToken::validateFormToken($_POST);
	$login = filter_input(INPUT_POST,'login', FILTER_SANITIZE_STRIPPED);
	$password = filter_input(INPUT_POST,'password', FILTER_SANITIZE_STRIPPED);
	$archive = $_FILES['theme'];
	$fileinfo = finfo_open(FILEINFO_MIME_TYPE);
	if(
		$archive['error'] == 0 and
		$fileinfo !== false and
		$fileinfo->file($archive['tmp_name']) == 'application/zip' and
		$archive['size'] > 1024
	) {
		$connected = false;
		if(!empty($login) and !empty($password)) {
			# On valide l'utilisateur
			foreach ($plxMotor->aUsers as $userid => $user) {
				if(
					$user['login'] and
					sha1($user['salt'] . md5($_POST['password'])) === $user['password'] and # utiliser fileinfo
					$user['active'] and
					!$user['delete']
				) {
					$author = $userid;
					$login = $user['login'];
					$connected = true;
					break;
				}
			}
		}

		if ($connected) {
			$zip = new ZipArchive();
			if ($zip->open($archive['tmp_name'])) {
				$ok = Array();
				$pattern = '#^/?(\w[^/]+)/(' . implode('|', REQUIRED_FILES) . ')$#';
				$theme = '';
				for($i=0; $i<$zip->numFiles; $i++) {
					# On parcoure toutes les entrées pour vérifier qu'il n'y a qu'un dossier racine
					$entry = $zip->getNameIndex($i);
					if(preg_match($pattern, $entry, $matches)) {
						if(empty($theme)) {
							$theme = $matches[1];
							# tester si le dossier existe déjà
							if(is_dir($target . $theme)) {
								$message = 'Le thème ' . $theme . ' existe déjà';
								break;
							}
						} elseif($theme != $matches[1]) {
							$message = 'Mauvais dossier racine de l\'archive';
							break;
						}

						$required = pathinfo($matches[2],  PATHINFO_FILENAME);
						$ok[$required] = true;
						if($required == 'preview') {
							$thumbnail = $plxMotor->aConf['racine_themes'] . ltrim($entry, '/');
						}
					}
				}

				if(empty($message))
				{
					if(count($ok) == count(REQUIRED_FILES)) {
						if($zip->extractTo($target)) {
							$message = 'Bravo, votre thème ' . $theme . ' est installé sur ce site.';

							# Création d'un article
                            # Impossible d'utiliser plxAdmin::getInstance qui crée un objet plxMotor dans ce contexte
							$artId = nextIdArticle(array_keys($plxMotor->plxGlob_arts->aFiles)); # nouvel article
							# Parse infos.xml for $theme
							$infos = getInfos(PLX_ROOT . $plxMotor->aConf['racine_themes'] . $theme . '/infos.xml');
							$chapo = <<< EOT
<div class="theme chapo">
	<p><a href="{$infos['site']}" target="_blank">{$infos['author']}</a></p>
	<p>Version : {$infos['version']}</p>
	<p>Date {$infos['date']}</p>
</div>
EOT;
							$today = date('YmdHi');
							$pattern = '#^\s*(?:th.mes?|' . $login . '|' . trim($infos['author']) . ')\s*$#i';
							# les urls n'ont pas d'accents !!
							$tmp = array_filter($plxMotor->aCats, function ($value) use($pattern) {
								return preg_match($pattern, $value['name']) or preg_match($pattern, $value['url']);
							});
							$catIds = !empty($tmp) ? array_keys($tmp) : array('000');
							$url = plxUtils::urlify($infos['title']);

							# Mimics plxAdmin::editArticle() from core/lib/class.plx.admin
							ob_start();
?>
<document>
	<title><![CDATA[<?= plxUtils::cdataCheck(trim($infos['title'])) ?>]]></title>
	<allow_com><?= $plxMotor->aConf['allow_com'] ?></allow_com>
	<template>article.php</template>
	<chapo><![CDATA[<?= $chapo ?>]]></chapo>
	<content><![CDATA[<div class="theme content"><?= plxUtils::cdataCheck(trim($infos['description'])) ?></div>]]></content>
	<tags></tags>
	<meta_description></meta_description>
	<meta_keywords><![CDATA[theme,pluxml,cms]]></meta_keywords>
	<title_htmltag><![CDATA[ thème <?= plxUtils::cdataCheck(trim($theme)) ?>]]></title_htmltag>
	<thumbnail><![CDATA[<?= plxUtils::cdataCheck($thumbnail) ?>]]></thumbnail>
	<thumbnail_alt>Aperçu du thème</thumbnail_alt>
	<thumbnail_title><![CDATA[Aperçu du thème <?= plxUtils::cdataCheck(trim($theme)) ?>']]></thumbnail_title>
	<date_creation><?= $today?></date_creation>
	<date_update><?= $today?></date_update>
</document>
<?php
							$filename = PLX_ROOT . $plxMotor->aConf['racine_articles'] . implode('.', array(
								$artId,
								implode(',', $catIds),
								$author,
								$today,
								$url
							)) . '.xml';
							# Écriture du fichier de l'article
							if(plxUtils::write(XML_HEADER . ob_get_clean(), $filename)) {
								# Création de la miniature de l'aperçu du thème
								$thumName = plxUtils::thumbName($thumbnail);
								$success = plxUtils::makeThumb($thumbnail, $thumName, $plxMotor->aConf['miniatures_l'], $plxMotor->aConf['miniatures_l'], 80);
							}
						} else {
							$message ='L\'extraction de l\'archive a mal finie.';
						}
					} else {
						$message = 'Il manque ' . (count(REQUIRED_FILES) - count($ok)) . ' fichier(s) dans le thème ' . $theme . '.';
						$missingFiles = true;
					}
				}
				$zip->close();
			}
		} else {
			$message = 'Login ou mot de passe incorrect';
		}
	} else {
		$message = 'Archive zip non valide';
	}
} else {
	$login = '';
	$password = '';
}
?>
<style>
	.upload-theme {
		margin: 1rem;
		padding: 0.5rem 2rem;
		border: 1px solid wheat;
		background-color: ivory;
		color: blue;
	}
	.upload-theme.alert {
		color: red;
	}
	#upload-theme-form {
		margin: 1rem auto;
		padding: 0.5rem 1rem;
		background-color: #eee;
		color: #222;
		border: 1px solid #888;
		border-radius: 1rem;
	}
	#upload-theme-form input {
		margin: 0.5rem 0;
	}
	.themes-list {
		column-count: 4;
	}

	.theme-wrapper {
		display: grid;
		grid-template-columns: 1fr 1fr;
		column-gap: 5%;
	}
</style>
<?php
if (!empty($message)) {
?>
<div class="upload-theme <?= empty($success) ? 'alert' : '' ?>">
	<?= $message ?>
</div>
<?php
if($success) {
?>
    <div><a href="index.php"><button>Continuer</button></a></div>
<?php
}

} else {
?>
<div>
	<p>Si vous avez un compte sur ce site, vous pouvez installer un thème, sauf s'il existe déjà.</p>
	<h3>Dossiers des thèmes déjà installés :</h3>
	<ul class="themes-list">
<?php
$pattern = $target . '*/infos.xml';
foreach(glob($pattern) as $filename) {
	$folder = preg_replace('@^.*/(\w[^/]*)/infos.xml$@', '$1', $filename);
?>
		<li><?= $folder ?></li>
<?php
	}
?>
	</ul>
</div>
<?php
}

if (empty($success)) {
    # On affiche un formulaire pour téléverser un thème sous forme d'archive Zip
?>
<div class="theme-wrapper">
	<div>
		<div>Les fichiers suivants sont obligatoires dans l'archive zip du thème :</div>
		<ul>
<?php
foreach(REQUIRED_FILES as $f) {
	$caption = strtr($f, array(
		'\.' => '.',
		'(?:jpe?g|png|webp)' => '*',
	));
	if(!empty($missingFiles)) {
		$tag = array_key_exists(pathinfo($caption,  PATHINFO_FILENAME), $ok) ? '✅' : '❌';
	} else {
		$tag = '';
	}
?>
			<li><?= $tag ?> <?= $caption ?></li>
<?php
}
?>
		</ul>
	</div>
	<form id="upload-theme-form" method="post"  enctype="multipart/form-data" >
		<?= plxToken::getTokenPostMethod() ?>
		<input type="text" name="login" value="<?= $login ?>"placeholder="Login de connexion" required />
		<input type="password" name="password" value="<?= $password ?>" placeholder="Mot de passe" required />
		<input type="file" name="theme" accept="*.zip,application/zip" placeholder="archive zip du thème" required />
		<input type="submit" />
	</form>
</div>
<?php
}
