Merge branch '10400' into module_i18n

This commit is contained in:
Fred Tempez 2020-11-14 16:09:57 +01:00
commit 3c4e1f1294
38 changed files with 1673 additions and 461 deletions

View File

@ -1,5 +1,21 @@
# Changelog
## version 10.4.00
- Modifications :
- Captcha arithmétique, activation recommandée dans la configuration.
- Module User
- Pour les articles de blog et de news, choix de la signature, nom+prenom ; nom+prenom ; id ; pseudo
- Importation d'un liste d'utilisateur dans un fichier plat (CSV).
- Module Blog :
- Texte du commentaire enrichi.
- Nombre maximal de caractère par commentaire.
- Gestion des commentaires article par article.
- Suppression des commentaires en masse.
- Limiter l'édition des articles et des commentaires à l'id de l'éditeur
- Approbation des commentaires
- Gestion des thèmes :
- Bouton de réinitialisation avec confirmation
## version 10.3.06
- Correction :
- Edition de page avec module, le changement de mise en page désactive le bouton d'option du module.
@ -40,11 +56,13 @@
- Barre de membre déplacée à droite de la barre de menu.
## version 10.3.02
- Correction :
- Corrections :
- Icône de pied de page github manquante.
- Mauvaise redirection après changement de mot de passe d'un membre.
- Modifications :
- Nouvelles images de captcha.
- Option de configuration, captcha demandé à la connexion.
- Méthode d'encodage UTF8.
## version 10.3.01

View File

@ -1,10 +1,10 @@
![](https://img.shields.io/github/last-commit/fredtempez/ZwiiCMS/master) ![](https://img.shields.io/github/release-date/fredtempez/ZwiiCMS)
# ZwiiCMS 10.3.05
# ZwiiCMS 10.4.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.
ZwiiCMS a été créé par un développeur de talent, [Rémi Jean](https://remijean.fr/). Il est désormais maintenu par Fred Tempez aidé de la communauté.
ZwiiCMS a été créé par un développeur de talent, [Rémi Jean](https://remijean.fr/). Il est désormais maintenu par Frédéric Tempez.
[Site](http://zwiicms.fr/) - [Forum](http://forum.zwiicms.com/) - [Version initiale](https://github.com/remijean/ZwiiCMS/) - [GitHub](https://github.com/fredtempez/ZwiiCMS)

View File

@ -32,7 +32,7 @@ class template {
);
}
/**
/**
* Crée un champ captcha
* @param string $nameId Nom et id du champ
* @param array $attributes Attributs ($key => $value)
@ -47,29 +47,85 @@ class template {
'id' => $nameId,
'name' => $nameId,
'value' => '',
'limit' => false
'limit' => false // captcha simple
], $attributes);
// Génère deux nombres pour le captcha
$numbers = array(0,1,2,3,4,5,6,7,8,9,10,12,13,14,15,16,17,18,19,20);
$letters = array('u','t','s','r','q','p','o','n','m','l','k','j','i','h','g','f','e','d','c','b','a');
$limit = $attributes['limit'] ? count($letters)-1 : 10 ;
mt_srand((float) microtime()*1000000);
$firstNumber = mt_rand ( 0 , $limit );
$secondNumber = mt_rand ( 0 , $limit );
$result = $firstNumber + $secondNumber;
// Captcha quatre opérations
// Limite addition et soustraction selon le type de captcha
$numbers = [0,1,2,3,4,5,6,7,8,9,10,12,13,14,15,16,17,18,19,20];
$letters = ['u','t','s','r','q','p','o','n','m','l','k','j','i','h','g','f','e','d','c','b','a'];
$limit = $attributes['limit'] ? count($letters)-1 : 10;
// Tirage de l'opération
mt_srand((float) microtime()*1000000);
// Captcha simple limité à l'addition
$operator = $attributes['limit'] ? mt_rand (1, 4) : 1;
// Limite si multiplication ou division
if ($operator > 2) {
$limit = 10;
}
// Tirage des nombres
mt_srand((float) microtime()*1000000);
$firstNumber = mt_rand (1, $limit);
mt_srand((float) microtime()*1000000);
$secondNumber = mt_rand (1, $limit);
// Permutation si addition ou soustraction
if (($operator < 3) and ($firstNumber < $secondNumber)) {
$temp = $firstNumber;
$firstNumber = $secondNumber;
$secondNumber = $temp;
}
// Icône de l'opérateur et calcul du résultat
switch ($operator) {
case 1:
$operator = template::ico('plus');
$result = $firstNumber + $secondNumber;
break;
case 2:
$operator = template::ico('minus');
$result = $firstNumber - $secondNumber;
break;
case 3:
$operator = template::ico('cancel');
$result = $firstNumber * $secondNumber;
break;
case 4:
$operator = template::ico('divide');
$limit2 = [10, 10, 6, 5, 4, 3, 2, 2, 2, 2];
for ($i = 1; $i <= $firstNumber; $i++) {
$limit = $limit2[$i-1];
}
mt_srand((float) microtime()*1000000);
$secondNumber = mt_rand(1, $limit);
$firstNumber = $firstNumber * $secondNumber;
$result = $firstNumber / $secondNumber;
break;
}
// Hashage du résultat
$result = password_hash($result, PASSWORD_BCRYPT);
// Codage des valeurs de l'opération
$firstLetter = uniqid();
$secondLetter = uniqid();
// Masquage image source
// Masquage image source pour éviter un décodage
copy ('core/vendor/zwiico/png/'.$letters[$firstNumber] . '.png', 'site/tmp/' . $firstLetter . '.png');
copy ('core/vendor/zwiico/png/'.$letters[$secondNumber] . '.png', 'site/tmp/' . $secondLetter . '.png');
// Début du wrapper
$html = '<div class="captcha" id="' . $attributes['id'] . 'Wrapper" class="inputWrapper ' . $attributes['classWrapper'] . '">';
// Label
$html .= self::label($attributes['id'],
'<img src="' . helper::baseUrl(false) . 'site/tmp/' . $firstLetter . '.png" />' . template::ico('plus') . '<img class="captchaNumber" src="' . helper::baseUrl(false) . 'site/tmp/' . $secondLetter . '.png" /> en chiffres ?', [
'<img src="' . helper::baseUrl(false) . 'site/tmp/' . $firstLetter . '.png" />&nbsp;<strong>' . $operator . '</strong>&nbsp;<img class="captchaNumber" src="' . helper::baseUrl(false) . 'site/tmp/' . $secondLetter . '.png" /> en chiffres ?', [
'help' => $attributes['help']
]);
// Notice
$notice = '';
if(array_key_exists($attributes['id'], common::$inputNotices)) {
@ -77,29 +133,22 @@ class template {
$attributes['class'] .= ' notice';
}
$html .= self::notice($attributes['id'], $notice);
// captcha
$html .= sprintf(
'<input type="text" %s>',
helper::sprintAttributes($attributes)
);
// Champ résultat caché
// Champ résultat codé
$html .= self::hidden($attributes['id'] . 'Result', [
'value' => $result,
'before' => false
]);
// Champs cachés contenant les nombres
/*
$html .= self::hidden($attributes['id'] . 'FirstNumber', [
'value' => $firstNumber,
'before' => false
]);
$html .= self::hidden($attributes['id'] . 'SecondNumber', [
'value' => $secondNumber,
'before' => false
]);
*/
// Fin du wrapper
$html .= '</div>';
// Retourne le html
return $html;
}

View File

@ -25,6 +25,10 @@ class common {
const GROUP_MEMBER = 1;
const GROUP_MODERATOR = 2;
const GROUP_ADMIN = 3;
const SIGNATURE_ID = 1;
const SIGNATURE_PSEUDO = 2;
const SIGNATURE_FIRSTLASTNAME = 3;
const SIGNATURE_LASTFIRSTNAME = 4;
// Dossier de travail
const BACKUP_DIR = 'site/backup/';
const DATA_DIR = 'site/data/';
@ -39,7 +43,7 @@ class common {
const ACCESS_TIMER = 1800;
// Numéro de version
const ZWII_VERSION = '10.3.06';
const ZWII_VERSION = '10.4.00';
const ZWII_UPDATE_CHANNEL = "v10";
public static $actions = [];
@ -53,15 +57,6 @@ class common {
'user',
'translate'
];
public static $dataStage = [
'config',
'core',
'module',
'page',
'user',
'theme',
'admin'
];
public static $accessList = [
'user',
'theme',
@ -148,9 +143,24 @@ class common {
private $url = '';
// Données de site
private $user = [];
private $core = [];
private $config = [];
private $page = [];
private $module = [];
// Descripteur de données Entrées / Sorties
// Liste ici tous les fichiers de données
private $dataFiles = [
'page' => '',
'module' => '',
'core' => '',
'config' => '',
'page' => '',
'user' => '',
'theme' => '',
'admin' => '',
'blacklist' => ''
];
/**
* Constructeur commun
@ -164,20 +174,32 @@ class common {
$this->input['_COOKIE'] = $_COOKIE;
}
// Instanciation de la classe des entrées / sorties
// Récupére les descripteurs
foreach ($this->dataFiles as $keys => $value) {
// Constructeur JsonDB
$this->dataFiles[$keys] = new \Prowebcraft\JsonDb([
'name' => $keys . '.json',
'dir' => $this->dirData ($keys,'fr')
]);;
}
// Import version 9
if (file_exists(self::DATA_DIR . 'core.json') === true &&
$this->getData(['core','dataVersion']) < 10000) {
$keepUsers = isset($_SESSION['KEEP_USERS']) ? $_SESSION['KEEP_USERS'] : false;
$this->importData($keepUsers);
unset ($_SESSION['KEEP_USERS']);
// Réinstaller htaccess
copy('core/module/install/ressource/.htaccess', self::DATA_DIR . '.htaccess');
common::$importNotices [] = "Importation réalisée avec succès" ;
//echo '<script>window.location.replace("' . helper::baseUrl() . $this->getData(['config','homePageId']) . '")</script>';
$this->getData(['core','dataVersion']) < 10000) {
$keepUsers = isset($_SESSION['KEEP_USERS']) ? $_SESSION['KEEP_USERS'] : false;
$this->importData($keepUsers);
unset ($_SESSION['KEEP_USERS']);
// Réinstaller htaccess
copy('core/module/install/ressource/.htaccess', self::DATA_DIR . '.htaccess');
common::$importNotices [] = "Importation réalisée avec succès" ;
//echo '<script>window.location.replace("' . helper::baseUrl() . $this->getData(['config','homePageId']) . '")</script>';
}
// Installation fraîche, initialisation des modules manquants
// La langue d'installation par défaut est fr
foreach (self::$dataStage as $stageId) {
foreach ($this->dataFiles as $stageId => $item) {
$folder = $this->dirData ($stageId, 'fr');
if (file_exists($folder . $stageId .'.json') === false) {
$this->initData($stageId,'fr');
@ -194,6 +216,7 @@ class common {
$this->page = $this->getCache('page');
$this->module = $this->getCache('module');
// Auto traduction
if ( $this->getData(['translate','active'])) {
// Lire la langue du navigateur
$lan = substr($_SERVER['HTTP_ACCEPT_LANGUAGE'], 0, 2);
@ -334,13 +357,9 @@ class common {
* @param array $keys Clé(s) des données
*/
public function deleteData($keys) {
//Retourne une chaine contenant le dossier à créer
$folder = $this->dirData ($keys[0],'fr');
// Constructeur JsonDB
$db = new \Prowebcraft\JsonDb([
'name' => $keys[0] . '.json',
'dir' => $folder
]);
// Descripteur
$db = $this->dataFiles[$keys[0]];
// Aiguillage
switch(count($keys)) {
case 1:
$db->delete($keys[0]);
@ -381,38 +400,10 @@ class common {
public function getData($keys = []) {
if (count($keys) >= 1) {
/**
* Lecture dans le cache, page et module
*/
if ($keys[0] === 'page' ||
$keys[0] === 'module' ) {
// Décent dans les niveaux de la variable $data
$data = array_merge ($this->page , $this->module);
foreach($keys as $key) {
// Si aucune donnée n'existe retourne null
if(isset($data[$key]) === false) {
return null;
}
// Sinon décent dans les niveaux
else {
$data = $data[$key];
}
}
// Retourne les données
return $data;
}
/**
* Lecture directe
*/
//Retourne une chaine contenant le dossier à créer
$folder = $this->dirData ($keys[0],'fr');
// Constructeur JsonDB
$db = new \Prowebcraft\JsonDb([
'name' => $keys[0] . '.json',
'dir' => $folder
]);
$db = $this->dataFiles[$keys[0]];
switch(count($keys)) {
case 1:
$tempData = $db->get($keys[0]);
@ -440,22 +431,6 @@ class common {
}
}
/**
* Lecture des fichiers de données de page et mise ne cache
* @param @return string données des pages
*/
public function getCache($data) {
$folder = $this->dirData ($data,'fr');
// Constructeur JsonDB
$db = new \Prowebcraft\JsonDb([
'name' => $data . '.json',
'dir' => $folder
]);
$tempData = $db->get($data);
return [$data => $tempData];
}
/*
* Dummy function
* Compatibilité des modules avec v8 et v9
@ -970,14 +945,10 @@ class common {
return false;
}
//Retourne une chaine contenant le dossier à créer
$folder = $this->dirData ($keys[0],'fr');
// Constructeur JsonDB
$db = new \Prowebcraft\JsonDb([
'name' => $keys[0] . '.json',
'dir' => $folder
]);
// Descripteur
$db = $this->dataFiles[$keys[0]];
// Aiguillage
switch(count($keys)) {
case 2:
$db->set($keys[0],$keys[1]);
@ -1022,12 +993,7 @@ class common {
if (!file_exists(self::DATA_DIR . '/' . $lang)) {
mkdir (self::DATA_DIR . '/' . $lang);
}
$folder = $this->dirData ($module,$lang);
// Constructeur JsonDB
$db = new \Prowebcraft\JsonDb([
'name' => $module . '.json',
'dir' => $folder
]);
$db = $this->dataFiles[$module];
if ($sampleSite === true) {
$db->set($module,init::$siteData[$module]);
} else {
@ -1463,6 +1429,51 @@ class common {
}
$this->setData(['core', 'dataVersion', 10304]);
}
// Version 10.4.00
if ($this->getData(['core', 'dataVersion']) < 10400) {
// Ajouter le prénom comme pseudo et le pseudo comme signature
foreach($this->getData(['user']) as $userId => $userIds){
$this->setData(['user',$userId,'pseudo',$this->getData(['user',$userId,'firstname'])]);
$this->setData(['user',$userId,'signature',2]);
}
// Ajouter les champs de blog v3
// Liste des pages dans pageList
$pageList = array();
foreach ($this->getHierarchy(null,null,null) as $parentKey=>$parentValue) {
$pageList [] = $parentKey;
foreach ($parentValue as $childKey) {
$pageList [] = $childKey;
}
}
// Parcourir pageList et rechercher les modules de blog
foreach ($pageList as $parentKey => $parent) {
//La page a une galerie
if ($this->getData(['page',$parent,'moduleId']) === 'blog' ) {
$articleIds = array_keys(helper::arrayCollumn($this->getData(['module',$parent]), 'publishedOn', 'SORT_DESC'));
foreach ($articleIds as $key => $article) {
// Droits les deux groupes
$this->setData(['module', $parent, $article,'editConsent', 3]);
// Limite de taille 500
$this->setData(['module', $parent, $article,'commentMaxlength', '500']);
// Pas d'approbation des commentaires
$this->setData(['module', $parent, $article,'commentApproved', false ]);
// pas de notification
$this->setData(['module', $parent, $article,'commentNotification', false ]);
// groupe de notification
$this->setData(['module', $parent, $article,'commentGroupNotification', 3 ]);
}
// Traitement des commentaires
if ( is_array($this->getData(['module', $parent, $article,'comment'])) ) {
foreach($this->getData(['module', $parent, $article,'comment']) as $commentId => $comment) {
// Approbation
$this->setData(['module', $parent, $article,'comment', $commentId, 'approval', true ]);
}
}
}
}
$this->setData(['core', 'dataVersion', 10400]);
}
}
}
@ -1566,7 +1577,7 @@ class core extends common {
//$css .= '.button.buttonGrey,.button.buttonGrey:hover{color:' . $this->getData(['theme', 'text', 'textColor']) . '}';
$css .= '.container{max-width:' . $this->getData(['theme', 'site', 'width']) . '}';
$margin = $this->getData(['theme', 'site', 'margin']) ? '0' : '20px';
$css .= $this->getData(['theme', 'site', 'width']) === '100%' ? '#site.light{margin:150px auto !important;}#site{margin:0 auto !important;} body{margin:0 auto !important;} #bar{margin:0 auto !important;} body > header{margin:0 auto !important;} body > nav {margin: 0 auto !important;} body > footer {margin:0 auto !important;}': "#site.light{margin: 100px auto !important;}#site{margin: " . $margin . " auto !important;} body{margin:0px 10px;} #bar{margin: 0 -10px;} body > header{margin: 0 -10px;} body > nav {margin: 0 -10px;} body > footer {margin: 0 -10px;} ";
$css .= $this->getData(['theme', 'site', 'width']) === '100%' ? '#site.light{margin:5% auto !important;}#site{margin:0 auto !important;} body{margin:0 auto !important;} #bar{margin:0 auto !important;} body > header{margin:0 auto !important;} body > nav {margin: 0 auto !important;} body > footer {margin:0 auto !important;}': "#site.light{margin: 5% auto !important;}#site{margin: " . $margin . " auto !important;} body{margin:0px 10px;} #bar{margin: 0 -10px;} body > header{margin: 0 -10px;} body > nav {margin: 0 -10px;} body > footer {margin: 0 -10px;} ";
$css .= $this->getData(['theme', 'site', 'width']) === '750px' ? '.button, button{font-size:0.8em;}' : '';
$css .= '#site{background-color:' . $this->getData(['theme', 'site', 'backgroundColor']) . ';border-radius:' . $this->getData(['theme', 'site', 'radius']) . ';box-shadow:' . $this->getData(['theme', 'site', 'shadow']) . ' #212223;}';
$css .= '.editorWysiwyg {background-color:' . $this->getData(['theme', 'site', 'backgroundColor']) . ';}';
@ -1700,7 +1711,7 @@ class core extends common {
$colors = helper::colorVariants($this->getData(['admin','backgroundColorButtonRed']));
$css .= '.button.buttonRed {background-color: ' . $colors['normal'] . ';color: ' . $colors['text'] . ';}.button.buttonRed:hover {background-color:' . $colors['darken'] . ';color:' . $colors['text'] . ';}.button.buttonRed:active {background-color:' . $colors['veryDarken'] . ';color:' . $colors['text'] . ';}';
$colors = helper::colorVariants($this->getData(['admin','backgroundColorButtonGreen']));
$css .= 'button[type=submit] {background-color: ' . $colors['normal'] . ';color: ' . $colors['text'] . ';}button[type=submit]:hover {background-color: ' . $colors['darken'] . ';color: ' . $colors['text'] .';}button[type=submit]:active {background-color: ' . $colors['darken'] . ';color: ' .$colors['text'] .';}';
$css .= '.button.buttonGreen, button[type=submit] {background-color: ' . $colors['normal'] . ';color: ' . $colors['text'] . ';}.button.buttonGreen:hover, button[type=submit]:hover {background-color: ' . $colors['darken'] . ';color: ' . $colors['text'] .';}.button.buttonGreen:active, button[type=submit]:active {background-color: ' . $colors['darken'] . ';color: ' .$colors['text'] .';}';
$colors = helper::colorVariants($this->getData(['admin','backgroundBlockColor']));
$css .= '.block {border: 1px solid ' . $this->getData(['admin','borderBlockColor']) . ';}.block h4 {background-color: ' . $colors['normal'] . ';color:' . $colors['text'] . ';}';
$css .= 'table tr,input[type=email],input[type=text],input[type=password],select:not(#barSelectPage),textarea:not(.editorWysiwyg),.inputFile{background-color: ' . $colors['normal'] . ';color:' . $colors['text'] . ';border: 1px solid ' . $this->getData(['admin','borderBlockColor']) . ';}';
@ -2868,4 +2879,4 @@ class layout extends common {
}
}
}
}
}

File diff suppressed because it is too large Load Diff

View File

@ -49,7 +49,7 @@
<?php echo template::textarea('configMetaDescription', [
'label' => 'Description du site',
'value' => $this->getData(['config', 'metaDescription']),
'help' => 'La description participe au référencement, n\'oubliez pas de personnaliser la description de chaque page sans un copié collé.'
'help' => 'La description d\'une page participe à son référencement, chaque page doit disposer d\'une description différente.'
]); ?>
</div>
</div>
@ -102,7 +102,7 @@
<div class="col4 verticalAlignBottom">
<?php echo template::checkbox('configCaptchaStrong', true, 'Captcha renforcé', [
'checked' => $this->getData(['config','captchaStrong']),
'help' => 'Option recommandée pour sécuriser la connexion. S\'applique à tous les captchas du site.'
'help' => 'Option recommandée pour sécuriser la connexion. S\'applique à tous les captchas du site. Le captcha simple se limite à une addition de nombres de 0 à 10. Le captcha renforcé utilise quatre opérations de nombres de 0 à 20.'
]); ?>
</div>
</div>

View File

@ -61,6 +61,8 @@ class install extends common {
'forgot' => 0,
'group' => self::GROUP_ADMIN,
'lastname' => $userLastname,
'pseudo' => 'Admin',
'signature' => 1,
'mail' => $userMail,
'password' => $this->getInput('installPassword', helper::FILTER_PASSWORD, true)
]

View File

@ -649,13 +649,13 @@ class init extends common {
'module' => [
'blog' => [
'mon-premier-article' => [
'closeComment' => false,
'comment' => [
'58e11d09e5aff' => [
'author' => 'Rémi',
'content' => 'Article bien rédigé et très pertinent, bravo !',
'createdOn' => 1421748000,
'userId' => ''
'userId' => '',
'approval' => true
]
],
'content' => '<p>Et eodem impetu Domitianum praecipitem per scalas itidem funibus constrinxerunt, eosque coniunctos per ampla spatia civitatis acri raptavere discursu. iamque artuum et membrorum divulsa conpage superscandentes corpora mortuorum ad ultimam truncata deformitatem velut exsaturati mox abiecerunt in flumen.</p><p>Ex his quidam aeternitati se commendari posse per statuas aestimantes eas ardenter adfectant quasi plus praemii de figmentis aereis sensu carentibus adepturi, quam ex conscientia honeste recteque factorum, easque auro curant inbracteari, quod Acilio Glabrioni delatum est primo, cum consiliis armisque regem superasset Antiochum. quam autem sit pulchrum exigua haec spernentem et minima ad ascensus verae gloriae tendere longos et arduos, ut memorat vates Ascraeus, Censorius Cato monstravit. qui interrogatus quam ob rem inter multos... statuam non haberet malo inquit ambigere bonos quam ob rem id non meruerim, quam quod est gravius cur inpetraverim mussitare.</p><p>Latius iam disseminata licentia onerosus bonis omnibus Caesar nullum post haec adhibens modum orientis latera cuncta vexabat nec honoratis parcens nec urbium primatibus nec plebeiis.</p>',
@ -665,10 +665,15 @@ class init extends common {
'publishedOn' => 1548790902,
'state' => true,
'title' => 'Mon premier article',
'userId' => '' // Géré au moment de l'installation
'userId' => '', // Géré au moment de l'installation
'editConsent' => 'all',
'commentMaxlength' => '500',
'commentApproved' => false,
'commentClose' => false,
'commentNotification' => false,
'commentGroupNotification' => 3
],
'mon-deuxieme-article' => [
'closeComment' => false,
'comment' => [],
'content' => '<p>Et prima post Osdroenam quam, ut dictum est, ab hac descriptione discrevimus, Commagena, nunc Euphratensis, clementer adsurgit, Hierapoli, vetere Nino et Samosata civitatibus amplis inlustris.</p><p>Ob haec et huius modi multa, quae cernebantur in paucis, omnibus timeri sunt coepta. et ne tot malis dissimulatis paulatimque serpentibus acervi crescerent aerumnarum, nobilitatis decreto legati mittuntur: Praetextatus ex urbi praefecto et ex vicario Venustus et ex consulari Minervius oraturi, ne delictis supplicia sint grandiora, neve senator quisquam inusitato et inlicito more tormentis exponeretur.</p><p>Sed ut tum ad senem senex de senectute, sic hoc libro ad amicum amicissimus scripsi de amicitia. Tum est Cato locutus, quo erat nemo fere senior temporibus illis, nemo prudentior; nunc Laelius et sapiens (sic enim est habitus) et amicitiae gloria excellens de amicitia loquetur. Tu velim a me animum parumper avertas, Laelium loqui ipsum putes. C. Fannius et Q. Mucius ad socerum veniunt post mortem Africani; ab his sermo oritur, respondet Laelius, cuius tota disputatio est de amicitia, quam legens te ipse cognosces.</p>',
'picture' => 'galerie/landscape/desert.jpg',
@ -677,10 +682,15 @@ class init extends common {
'publishedOn' => 1550432502,
'state' => true,
'title' => 'Mon deuxième article',
'userId' => '' // Géré au moment de l'installation
'userId' => '', // Géré au moment de l'installation
'editConsent' => 'all',
'commentMaxlength' => '500',
'commentApproved' => false,
'commentClose' => false,
'commentNotification' => false,
'commentGroupNotification' => 3
],
'mon-troisieme-article' => [
'closeComment' => true,
'comment' => [],
'content' => '<p>Rogatus ad ultimum admissusque in consistorium ambage nulla praegressa inconsiderate et leviter proficiscere inquit ut praeceptum est, Caesar sciens quod si cessaveris, et tuas et palatii tui auferri iubebo prope diem annonas. hocque solo contumaciter dicto subiratus abscessit nec in conspectum eius postea venit saepius arcessitus.</p><p>Proinde concepta rabie saeviore, quam desperatio incendebat et fames, amplificatis viribus ardore incohibili in excidium urbium matris Seleuciae efferebantur, quam comes tuebatur Castricius tresque legiones bellicis sudoribus induratae.</p><p>Inter has ruinarum varietates a Nisibi quam tuebatur accitus Vrsicinus, cui nos obsecuturos iunxerat imperiale praeceptum, dispicere litis exitialis certamina cogebatur abnuens et reclamans, adulatorum oblatrantibus turmis, bellicosus sane milesque semper et militum ductor sed forensibus iurgiis longe discretus, qui metu sui discriminis anxius cum accusatores quaesitoresque subditivos sibi consociatos ex isdem foveis cerneret emergentes, quae clam palamve agitabantur, occultis Constantium litteris edocebat inplorans subsidia, quorum metu tumor notissimus Caesaris exhalaret.</p>',
'picture' => 'galerie/landscape/iceberg.jpg',
@ -689,7 +699,13 @@ class init extends common {
'publishedOn' => 1550864502,
'state' => true,
'title' => 'Mon troisième article',
'userId' => '' // Géré au moment de l'installation
'userId' => '', // Géré au moment de l'installation
'editConsent' => 'all',
'commentMaxlength' => '500',
'commentApproved' => false,
'commentClose' => true,
'commentNotification' => false,
'commentGroupNotification' => 3
]
],
'galeries' => [

View File

@ -24,7 +24,6 @@ class theme extends common {
'index' => self::GROUP_ADMIN,
'menu' => self::GROUP_ADMIN,
'reset' => self::GROUP_ADMIN,
'resetAdmin' => self::GROUP_ADMIN,
'site' => self::GROUP_ADMIN,
'admin' => self::GROUP_ADMIN,
'manage' => self::GROUP_ADMIN,
@ -535,29 +534,32 @@ class theme extends common {
*/
public function reset() {
// Supprime le fichier de personnalisation avancée
unlink(self::DATA_DIR.'custom.css');
$redirect ='';
switch ($this->getUrl(2)) {
case 'admin':
$this->initData('admin');
$redirect = helper::baseUrl() . 'theme/admin';
break;
case 'manage':
$this->initData('theme');
$redirect = helper::baseUrl() . 'theme/manage';
break;
case 'custom':
unlink(self::DATA_DIR.'custom.css');
$redirect = helper::baseUrl() . 'theme/advanced';
break;
default :
$redirect = helper::baseUrl() . 'theme';
}
// Valeurs en sortie
$this->addOutput([
'notification' => 'Personnalisation avancée réinitialisée',
'redirect' => helper::baseUrl() . 'theme/advanced',
'notification' => 'Réinitialisation effectuée',
'redirect' => $redirect,
'state' => true
]);
}
/**
* Réinitialisation de la personnalisation avancée
*/
public function resetAdmin() {
// Supprime le fichier de personnalisation avancée
//unlink(self::DATA_DIR.'admin.json');
$this->initData('admin');
// Valeurs en sortie
$this->addOutput([
'notification' => 'Thème réinitialisé',
'redirect' => helper::baseUrl() . 'theme/admin',
'state' => true
]);
}
/**
* Options du site
@ -635,7 +637,7 @@ class theme extends common {
) {
$modele = 'admin';
}
if (!empty($modele)
if (!empty($modele)
) {
// traiter l'archive
$success = $zip->extractTo('.');

View File

@ -32,7 +32,7 @@ $("input, select").on("change", function() {
var colors = core.colorVariants($("#adminColorRed").val());
css += ".button.buttonRed {background-color: " + colors.normal + ";color:" + colors.text + ";}.button.buttonRed:hover {background-color:" + colors.darken + ";color:" + colors.text + "}.button.buttonRed:active {background-color:" + colors.veryDarken + ";color:" + colors.text + "}";
var colors = core.colorVariants($("#adminColorGreen").val());
css += "button[type=submit] {background-color: " + colors.normal + ";color: " + ";color:" + colors.text + "}button[type=submit]:hover {background-color: " + colors.darken + ";color:" + colors.text + ";}button[type=submit]:active {background-color:" + colors.veryDarken + ";color:" + colors.text + "}";
css += ".button.buttonGreen, button[type=submit] {background-color: " + colors.normal + ";color: " + ";color:" + colors.text + "}.button.buttonGreen:hover, button[type=submit]:hover {background-color: " + colors.darken + ";color:" + colors.text + ";}.button.buttonGreen:active, button[type=submit]:active {background-color:" + colors.veryDarken + ";color:" + colors.text + "}";
var colors = core.colorVariants($("#adminBackGroundBlockColor").val());
css += ".block {border: 1px solid " + $("#adminBorderBlockColor").val() + ";}.block h4 {background-color: " + colors.normal + ";color:" + colors.text + ";}";
css += "input[type=email],input[type=text],input[type=password],select:not(#barSelectPage),textarea:not(.editorWysiwyg),.inputFile{background-color: " + colors.normal + ";color:" + colors.text + ";border: 1px solid " + $("#adminBorderBlockColor").val() + ";}";
@ -46,3 +46,13 @@ $("input, select").on("change", function() {
.appendTo("head");
});
/**
* Confirmation de réinitialisation
*/
$("#configAdminReset").on("click", function() {
var _this = $(this);
return core.confirm("Êtes-vous sûr de vouloir réinitialiser à son état d'origine le thème de l\'administration ?", function() {
$(location).attr("href", _this.attr("href"));
});
});

View File

@ -16,7 +16,7 @@
<div class="col2 offset">
<?php echo template::button('configAdminReset', [
'class' => 'buttonRed',
'href' => helper::baseUrl() . 'theme/resetAdmin',
'href' => helper::baseUrl() . 'theme/reset/admin',
'value' => 'Réinitialiser',
'ico' => 'cancel'
]); ?>

View File

@ -10,7 +10,7 @@
</div>
<div class="col2 offset6">
<?php echo template::button('themeAdvancedReset', [
'href' => helper::baseUrl() . 'theme/reset',
'href' => helper::baseUrl() . 'theme/reset/custom',
'class' => 'buttonRed',
'ico' => 'cancel',
'value' => 'Réinitialiser'

View File

@ -0,0 +1,21 @@
/**
* 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
* @license GNU General Public License, version 3
* @link http://zwiicms.fr/
*/
/**
* Confirmation de réinitialisation
*/
$("#configManageReset").on("click", function() {
var _this = $(this);
return core.confirm("Êtes-vous sûr de vouloir réinitialiser à son état d'origine le thème du site ?", function() {
$(location).attr("href", _this.attr("href"));
});
});

View File

@ -8,53 +8,59 @@
'value' => 'Retour'
]); ?>
</div>
<div class="col2 offset6">
<?php echo template::button('configManageReset', [
'class' => 'buttonRed',
'href' => helper::baseUrl() . 'theme/reset/manage',
'value' => 'Réinitialiser',
'ico' => 'cancel'
]); ?>
</div>
<div class="col2">
<?php echo template::submit('themeImportSubmit', [
'value' => 'Appliquer'
]); ?>
</div>
</div>
<div class="row">
<div class="col6">
<div class="col12">
<div class="block">
<h4>Installer un thème archivé</h4>
<h4>Installer un thème archivé (site ou administration)</h4>
<div class="row">
<div class="col12">
<div class="col6 offset3">
<?php echo template::file('themeManageImport', [
'label' => 'Archive ZIP :',
'type' => 2
]); ?>
</div>
</div>
<div class="row">
<div class="col5 offset3">
<?php echo template::submit('themeImportSubmit', [
'value' => 'Appliquer'
]); ?>
</div>
</div>
</div>
</div>
</div>
<div class="row">
<div class="col6">
<div class="block">
<h4>Sauvegarder le thème</h4>
<h4>Sauvegarde du thème dans les <a href="<?php echo helper::baseUrl(false); ?>core/vendor/filemanager/dialog.php?fldr=theme&type=0&akey=<?php echo md5_file(self::DATA_DIR.'core.json'); ?>" data-lity>fichiers</a> du site</h4>
<div class="row">
<div class="col6">
<?php echo template::button('themeSave', [
'href' => helper::baseUrl() . 'theme/save/theme',
'ico' => 'download-cloud',
'value' => 'Thème site'
'value' => 'Thème du site'
]); ?>
</div>
<div class="col6">
<?php echo template::button('themeSaveAdmin', [
'href' => helper::baseUrl() . 'theme/save/admin',
'ico' => 'download-cloud',
'value' => 'Thème administration'
'value' => 'Thème de l\'administration'
]); ?>
</div>
</div>
<div class="row">
<div class="col12">
<em>Le fichier de sauvegarde est généré dans <a href="<?php echo helper::baseUrl(false); ?>core/vendor/filemanager/dialog.php?fldr=theme&type=0&akey=<?php echo md5_file(self::DATA_DIR.'core.json'); ?>" data-lity>le dossier Thème</a> du gestionnaire de fichiers.</em>
</div>
</div>
</div>
</div>
<div class="col6">
<div class="block">
<h4>Télécharger le thème</h4>
<div class="row">
@ -62,14 +68,14 @@
<?php echo template::button('themeExport', [
'href' => helper::baseUrl() . 'theme/export/theme',
'ico' => 'download',
'value' => 'Thème site'
'value' => 'Thème du site'
]); ?>
</div>
<div class="col6">
<?php echo template::button('themeExport', [
'href' => helper::baseUrl() . 'theme/export/admin',
'ico' => 'download',
'value' => 'Thème administration'
'value' => 'Thème de l\'administration'
]); ?>
</div>
</div>

View File

@ -178,8 +178,7 @@
<div class="row">
<div class="col4">
<?php echo template::checkbox('themeMenuLoginLink', true, 'Lien de connexion', [
'checked' => $this->getData(['theme', 'menu', 'loginLink']),
'help' => 'L\'activation de cette option n\'est pas recommandée'
'checked' => $this->getData(['theme', 'menu', 'loginLink'])
]); ?>
</div>
<div class="col4">

View File

@ -0,0 +1,8 @@
# Bloque l'accès aux données
Order deny,allow
Deny from all
# Sauf l'accès au modèle csv
<Files template.csv>
Order Allow,Deny
Allow from all
</Files>

View File

@ -0,0 +1,2 @@
id;nom;prenom;email;groupe
jbon;Bon;Jean;jean.bon@email.fr;1
1 id nom prenom email groupe
2 jbon Bon Jean jean.bon@email.fr 1

View File

@ -17,20 +17,35 @@ class user extends common {
public static $actions = [
'add' => self::GROUP_ADMIN,
'delete' => self::GROUP_ADMIN,
'edit' => self::GROUP_MEMBER,
'forgot' => self::GROUP_VISITOR,
'import' => self::GROUP_ADMIN,
'index' => self::GROUP_ADMIN,
'login' => self::GROUP_VISITOR,
'edit' => self::GROUP_MEMBER,
'logout' => self::GROUP_MEMBER,
'forgot' => self::GROUP_VISITOR,
'login' => self::GROUP_VISITOR,
'reset' => self::GROUP_VISITOR
];
public static $users = [];
//Paramètres pour choix de la signature
public static $signature = [
self::SIGNATURE_ID => 'Identifiant',
self::SIGNATURE_PSEUDO => 'Pseudo',
self::SIGNATURE_FIRSTLASTNAME => 'Prénom Nom',
self::SIGNATURE_LASTFIRSTNAME => 'Nom Prénom'
];
public static $userId = '';
public static $userLongtime = false;
public static $separators = [
';' => ';',
',' => ',',
':' => ':'
];
/**
* Ajout
*/
@ -63,8 +78,15 @@ class user extends common {
'forgot' => 0,
'group' => $this->getInput('userAddGroup', helper::FILTER_INT, true),
'lastname' => $userLastname,
'pseudo' => $this->getInput('userAddPseudo', helper::FILTER_STRING_SHORT, true),
'signature' => $this->getInput('userAddSignature', helper::FILTER_INT, true),
'mail' => $userMail,
'password' => $this->getInput('userAddPassword', helper::FILTER_PASSWORD, true),
"connectFail" => null,
"connectTimeout" => null,
"accessUrl" => null,
"accessTimer" => null,
"accessCsrf" => null
]
]);
@ -77,7 +99,6 @@ class user extends common {
'Bonjour <strong>' . $userFirstname . ' ' . $userLastname . '</strong>,<br><br>' .
'Un administrateur vous a créé un compte sur le site ' . $this->getData(['config', 'title']) . '. Vous trouverez ci-dessous les détails de votre compte.<br><br>' .
'<strong>Identifiant du compte :</strong> ' . $this->getInput('userAddId') . '<br>' .
'<strong>Mot de passe du compte :</strong> ' . $this->getInput('userAddPassword') . '<br><br>' .
'<small>Nous ne conservons pas les mots de passe, en conséquence nous vous conseillons de conserver ce message tant que vous ne vous êtes pas connecté. Vous pourrez modifier votre mot de passe après votre première connexion.</small>',
null
);
@ -208,15 +229,26 @@ class user extends common {
else {
$newGroup = $this->getData(['user', $this->getUrl(2), 'group']);
}
// Modification de nom Prénom
if($this->getUser('group') === self::GROUP_ADMIN){
$newfirstname = $this->getInput('userEditFirstname', helper::FILTER_STRING_SHORT, true);
$newlastname = $this->getInput('userEditLastname', helper::FILTER_STRING_SHORT, true);
}
else{
$newfirstname = $this->getData(['user', $this->getUrl(2), 'firstname']);
$newlastname = $this->getData(['user', $this->getUrl(2), 'lastname']);
}
// Modifie l'utilisateur
$this->setData([
'user',
$this->getUrl(2),
[
'firstname' => $this->getInput('userEditFirstname', helper::FILTER_STRING_SHORT, true),
'firstname' => $newfirstname,
'forgot' => 0,
'group' => $newGroup,
'lastname' => $this->getInput('userEditLastname', helper::FILTER_STRING_SHORT, true),
'lastname' => $newlastname,
'pseudo' => $this->getInput('userEditPseudo', helper::FILTER_STRING_SHORT, true),
'signature' => $this->getInput('userEditSignature', helper::FILTER_INT, true),
'mail' => $this->getInput('userEditMail', helper::FILTER_MAIL, true),
'password' => $newPassword,
'connectFail' => $this->getData(['user',$this->getUrl(2),'connectFail']),
@ -413,7 +445,8 @@ class user extends common {
// Valeurs en sortie
$this->addOutput([
'notification' => 'Connexion réussie',
'redirect' => helper::baseUrl() . str_replace('_', '/', str_replace('__', '#', $this->getUrl(2))),
'redirect' => helper::baseUrl(),
//'redirect' => helper::baseUrl() . str_replace('_', '/', str_replace('__', '#', $this->getUrl(2))),
'state' => true
]);
}
@ -532,9 +565,137 @@ class user extends common {
}
// Valeurs en sortie
$this->addOutput([
'title' => 'Réinitialisation du mot de passe',
'display' => self::DISPLAY_LAYOUT_LIGHT,
'title' => 'Réinitialisation de votre mot de passe',
'view' => 'reset'
]);
}
}
/**
* Importation CSV d'utilisateurs
*/
public function import() {
// Soumission du formulaire
$notification = '';
$success = true;
if($this->isPost()) {
// Lecture du CSV et construction du tableau
$file = $this->getInput('userImportCSVFile',helper::FILTER_STRING_SHORT, true);
$filePath = self::FILE_DIR . 'source/' . $file;
if ($file AND file_exists($filePath)) {
// Analyse et extraction du CSV
$rows = array_map(function($row) { return str_getcsv($row, $this->getInput('userImportSeparator') ); }, file($filePath));
$header = array_shift($rows);
$csv = array();
foreach($rows as $row) {
$csv[] = array_combine($header, $row);
}
// Traitement des données
foreach($csv as $item ) {
// Données valides
if( array_key_exists('id', $item)
AND array_key_exists('prenom',$item)
AND array_key_exists('nom',$item)
AND array_key_exists('groupe',$item)
AND array_key_exists('email',$item)
AND $item['nom']
AND $item['prenom']
AND $item['id']
AND $item['email']
AND $item['groupe']
) {
// Validation du groupe
$item['groupe'] = (int) $item['groupe'];
$item['groupe'] = ( $item['groupe'] >= self::GROUP_BANNED AND $item['groupe'] <= self::GROUP_ADMIN )
? $item['groupe'] : 1;
// L'utilisateur existe
if ( $this->getData(['user',helper::filter($item['id'] , helper::FILTER_ID)]))
{
// Notification du doublon
$item['notification'] = template::ico('cancel');
// Création du tableau de confirmation
self::$users[] = [
helper::filter($item['id'] , helper::FILTER_ID),
$item['nom'],
$item['prenom'],
self::$groups[$item['groupe']],
$item['prenom'],
$item['email'],
$item['notification']
];
// L'utilisateur n'existe pas
} else {
// Nettoyage de l'identifiant
$userId = helper::filter($item['id'] , helper::FILTER_ID);
// Enregistre le user
$create = $this->setData([
'user',
$userId, [
'firstname' => $item['prenom'],
'forgot' => 0,
'group' => $item['groupe'] ,
'lastname' => $item['nom'],
'mail' => $item['email'],
'pseudo' => $item['prenom'],
'signature' => 1, // Pseudo
'password' => uniqid(), // A modifier à la première connexion
"connectFail" => null,
"connectTimeout" => null,
"accessUrl" => null,
"accessTimer" => null,
"accessCsrf" => null
]]);
// Icône de notification
$item['notification'] = $create ? template::ico('check') : template::ico('cancel');
// Envoi du mail
if ($create
AND $this->getInput('userImportNotification',helper::FILTER_BOOLEAN) === true) {
$sent = $this->sendMail(
$item['email'],
'Compte créé sur ' . $this->getData(['config', 'title']),
'Bonjour <strong>' . $item['prenom'] . ' ' . $item['nom'] . '</strong>,<br><br>' .
'Un administrateur vous a créé un compte sur le site ' . $this->getData(['config', 'title']) . '. Vous trouverez ci-dessous les détails de votre compte.<br><br>' .
'<strong>Identifiant du compte :</strong> ' . $userId . '<br>' .
'<small>Un mot de passe provisoire vous été attribué, à la première connexion cliquez sur Mot de passe Oublié.</small>'
);
if ($sent === true) {
// Mail envoyé changement de l'icône
$item['notification'] = template::ico('mail') ;
}
}
// Création du tableau de confirmation
self::$users[] = [
$userId,
$item['nom'],
$item['prenom'],
self::$groups[$item['groupe']],
$item['prenom'],
$item['email'],
$item['notification']
];
}
}
}
if (empty(self::$users)) {
$notification = 'Rien à importer, erreur de format ou fichier incorrect' ;
$success = false;
} else {
$notification = 'Importation effectuée' ;
$success = true;
}
} else {
$notification = 'Erreur de lecture, vérifiez les permissions';
$success = false;
}
}
// Valeurs en sortie
$this->addOutput([
'title' => 'Importation',
'view' => 'import',
'notification' => $notification,
'state' => $success
]);
}
}

View File

@ -30,6 +30,14 @@
]); ?>
</div>
</div>
<?php echo template::text('userAddPseudo', [
'autocomplete' => 'off',
'label' => 'Pseudo'
]); ?>
<?php echo template::select('userAddSignature', $module::$signature, [
'label' => 'Signature',
'selected' => 1
]); ?>
<?php echo template::mail('userAddMail', [
'autocomplete' => 'off',
'label' => 'Adresse mail'
@ -73,9 +81,9 @@
'label' => 'Confirmation'
]); ?>
<?php echo template::checkbox('userAddSendMail', true,
'Prévenir l\'utilisateur par mail');
?>
'Prévenir l\'utilisateur par mail');
?>
</div>
</div>
</div>
<?php echo template::formClose(); ?>
<?php echo template::formClose(); ?>

View File

@ -1,7 +1,7 @@
<?php echo template::formOpen('userEditForm'); ?>
<div class="row">
<div class="col2">
<?php if($this->getUser('group') === self::GROUP_ADMIN): ?>
<?php if($this->getUser('group') === self::GROUP_ADMIN): ?>
<?php echo template::button('userEditBack', [
'class' => 'buttonGrey',
'href' => helper::baseUrl() . 'user',
@ -29,6 +29,7 @@
<div class="col6">
<?php echo template::text('userEditFirstname', [
'autocomplete' => 'off',
'disabled' => $this->getUser('group') > 2 ? false : true,
'label' => 'Prénom',
'value' => $this->getData(['user', $this->getUrl(2), 'firstname'])
]); ?>
@ -36,11 +37,21 @@
<div class="col6">
<?php echo template::text('userEditLastname', [
'autocomplete' => 'off',
'disabled' => $this->getUser('group') > 2 ? false : true,
'label' => 'Nom',
'value' => $this->getData(['user', $this->getUrl(2), 'lastname'])
]); ?>
</div>
</div>
<?php echo template::text('userEditPseudo', [
'autocomplete' => 'off',
'label' => 'Pseudo',
'value' => $this->getData(['user', $this->getUrl(2), 'pseudo'])
]); ?>
<?php echo template::select('userEditSignature', $module::$signature, [
'label' => 'Signature',
'selected' => $this->getData(['user', $this->getUrl(2), 'signature'])
]); ?>
<?php echo template::mail('userEditMail', [
'autocomplete' => 'off',
'label' => 'Adresse mail',
@ -98,4 +109,4 @@
</div>
</div>
</div>
<?php echo template::formClose(); ?>
<?php echo template::formClose(); ?>

View File

@ -5,7 +5,6 @@
<div class="row">
<div class="col3 offset6">
<?php echo template::button('userForgotBack', [
'class' => 'buttonGrey',
'href' => helper::baseUrl() . 'user/login/' . $this->getUrl(2),
'ico' => 'left',
'value' => 'Retour'

16
core/module/user/view/import/import.css vendored Normal file
View File

@ -0,0 +1,16 @@
/**
* This file is part of Zwii.
*
* For full copyright and license information, please see the LICENSE
* file that was distributed with this source code.
*
* @author Rémi Jean <remi.jean@outlook.com>
* @copyright Copyright (C) 2008-2018, Rémi Jean
* @author Frédéric Tempez <frederic.tempez@outlook.com>
* @copyright Copyright (C) 2018-2020, Frédéric Tempez
* @license GNU General Public License, version 3
* @link http://zwiicms.fr/
*/
@import url("site/data/admin.css");

View File

@ -0,0 +1,62 @@
<?php echo template::formOpen('userImportForm'); ?>
<div class="row">
<div class="col2">
<?php echo template::button('userImportBack', [
'class' => 'buttonGrey',
'href' => helper::baseUrl() . 'user',
'ico' => 'left',
'value' => 'Retour'
]); ?>
</div>
<div class="col2 offset8">
<?php echo template::submit('userImportSubmit', [
'value' => 'Importer'
]); ?>
</div>
</div>
<div class="row">
<div class="col12">
<div class="block">
<h4>Importation de fichier plat CSV</h4>
<div class="row">
<div class="col6">
<?php echo template::file('userImportCSVFile', [
'label' => 'Liste d\'utilisateurs :'
]); ?>
</div>
<div class="col2">
<?php echo template::select('userImportSeparator', $module::$separators, [
'label' => 'Séparateur'
]); ?>
</div>
</div>
<div class="row">
<div class="col12">
<?php echo template::checkbox('userImportNotification', true, 'Envoyer un message de confirmation', [
'checked' => false
]); ?>
</div>
</div>
<div class="row">
<div class="col1">
<p>Aide :</p>
</div>
<div class="col11">
<p>Les en-têtes obligatoires sont : id, nom, prenom, email et groupe
( 1 : membre - 2 : éditeur - 3 : administrateur )
<p>Voir ce <a href="core/module/user/ressource/template.csv">modèle</a> à compléter avec un tableur.
Enregistrement au format CSV, séparateur ; ou , ou :</p>
</div>
</div>
</div>
</div>
</div>
<?php echo template::formClose(); ?>
<?php if ($module::$users): ?>
<?php echo template::table([1, 3, 3, 1, 1, 2, 1, 1 ], $module::$users, ['Identifiant', 'Nom', 'Prénom','Groupe', 'Pseudo', 'eMail', 'Succès']); ?>
<div class="row">
<div class="col12 textAlignCenter">
<?php echo template::ico('check');?> Compte créé | <?php echo template::ico('comment');?> Compte créé et notifié | <?php echo template::ico('cancel');?> ou manquant : erreur, compte non importé
</div>
</div>
<?php endif;?>

View File

@ -7,7 +7,14 @@
'value' => 'Accueil'
]); ?>
</div>
<div class="col2 offset8">
<div class="col2 offset6">
<?php echo template::button('userImport', [
'href' => helper::baseUrl() . 'user/import',
'ico' => 'plus',
'value' => 'Importation'
]); ?>
</div>
<div class="col2">
<?php echo template::button('userAdd', [
'href' => helper::baseUrl() . 'user/add',
'ico' => 'plus',

View File

@ -119,7 +119,7 @@ $config = array(
| If you want to be forced to assign the extension starting from the mime type
|
*/
'mime_extension_rename' => true,
'mime_extension_rename' => false,
/*

View File

@ -4,6 +4,13 @@
*/
/**
* Quand tinyMCE est invoqué hors connexion, initialiser privateKey
*/
if ( typeof(privateKey) == 'undefined') {
var privateKey = null;
};
tinymce.init({
// Classe où appliquer l'éditeur
selector: ".editorWysiwyg",
@ -20,7 +27,7 @@ tinymce.init({
// Plugins
plugins: "advlist anchor autolink autoresize autosave codemirror colorpicker contextmenu fullscreen hr image imagetools link lists media paste searchreplace stickytoolbar tabfocus table template textcolor emoticons nonbreaking",
// Contenu de la barre d'outils
toolbar: "restoredraft | undo redo | bold italic underline forecolor backcolor | alignleft aligncenter alignright alignjustify | bullist numlist emoticons | table template | image media link | code fullscreen",
toolbar: "restoredraft | undo redo | formatselect bold italic underline forecolor backcolor | alignleft aligncenter alignright alignjustify | bullist numlist emoticons | table template | image media link | code fullscreen",
// Emoticons
emoticons_append: {
custom_mind_explode: {
@ -118,12 +125,6 @@ tinymce.init({
external_plugins: {
"filemanager": baseUrl + "core/vendor/filemanager/plugin.min.js"
},
// Thème mobile
// mobile: {
// theme: "mobile",
// plugins: [ 'autosave', 'lists', 'autolink' ],
// toolbar: [ 'undo', 'bold', 'italic', 'styleselect' ]
//},
// Contenu du bouton insérer
insert_button_items: "anchor hr table",
// Contenu du bouton formats
@ -206,6 +207,144 @@ tinymce.init({
]
});
tinymce.init({
// Classe où appliquer l'éditeur
selector: ".editorWysiwygComment",
setup:function(ed) {
// Aperçu dans le pied de page
ed.on('change', function(e) {
if (ed.id === 'themeFooterText') {
$("#footerText").html(tinyMCE.get('themeFooterText').getContent());
}
});
// Limitation du nombre de caractères des commentaires à maxlength
var alarmCaraMin = 200; // alarme sur le nombre de caractères restants à partir de...
var maxlength = parseInt($("#" + (ed.id)).attr("maxlength"));
var id_alarm = "#blogArticleContentAlarm"
var contentLength = 0;
ed.on("keydown", function(e) {
contentLength = ed.getContent({format : 'text'}).length;
if (contentLength > maxlength) {
$(id_alarm).html("Vous avez atteint le maximum de " + maxlength + " caractères ! ");
if(e.keyCode != 8 && e.keyCode != 46){
e.preventDefault();
e.stopPropagation();
return false;
}
}
else{
if(maxlength - contentLength < alarmCaraMin){
$(id_alarm).html((maxlength - contentLength) + " caractères restants");
}
else{
$(id_alarm).html(" ");
}
}
});
// Limitation y compris lors d'un copier/coller
ed.on("paste", function(e){
contentLeng = ed.getContent({format : 'text'}).length - 16;
var data = e.clipboardData.getData('Text');
if (data.length > (maxlength - contentLeng)) {
$(id_alarm).html("Vous alliez dépasser le maximum de " + maxlength + " caractères ! ");
return false;
} else {
if(maxlength - contentLeng < alarmCaraMin){
$(id_alarm).html((maxlength - contentLeng - data.length) + " caractères restants");
}
else{
$(id_alarm).html(" ");
}
return true;
}
});
},
// Langue
language: "fr_FR",
// Plugins
plugins: "advlist anchor autolink autoresize autosave colorpicker contextmenu fullscreen hr lists paste searchreplace stickytoolbar tabfocus template textcolor visualblocks emoticons",
// Contenu de la barre d'outils
toolbar: "restoredraft | undo redo | formatselect bold italic forecolor backcolor | alignleft aligncenter alignright alignjustify | bullist numlist emoticons | visualblocks fullscreen",
// Emoticons
emoticons_append: {
custom_mind_explode: {
keywords: ["brain", "mind", "explode", "blown"],
char: "🤯"
}
},
// Titre des images
image_title: true,
// Pages internes
link_list: baseUrl + "core/vendor/tinymce/links.php",
// Contenu du menu contextuel
contextmenu: "cut copy paste pastetext | selectall searchreplace ",
// Fichiers CSS à intégrer à l'éditeur
content_css: [
baseUrl + "core/layout/common.css",
baseUrl + "core/vendor/tinymce/content.css",
baseUrl + "site/data/theme.css",
baseUrl + "site/data/custom.css"
],
// Classe à ajouter à la balise body dans l'iframe
body_class: "editorWysiwyg",
// Cache les menus
menubar: false,
// URL menu contextuel
link_context_toolbar: true,
// Cache la barre de statut
statusbar: false,
// Autorise le copié collé à partir du web
paste_data_images: true,
// Autorise tous les éléments
//valid_elements :"*[*]",
//valid_children : "*[*]",
// Autorise l'ajout de script
// extended_valid_elements: "script[language|type|src]",
// Bloque le dimensionnement des médias (car automatiquement en fullsize avec fitvids pour le responsive)
media_dimensions: true,
// Désactiver la dimension des images
image_dimensions: true,
// Active l'onglet avancé lors de l'ajout d'une image
image_advtab: true,
// Urls absolues
relative_urls: false,
// Url de base
document_base_url: baseUrl,
// Contenu du bouton formats
style_formats: [
{title: "Headers", items: [
{title: "Header 1", format: "h1"},
{title: "Header 2", format: "h2"},
{title: "Header 3", format: "h3"},
{title: "Header 4", format: "h4"}
]},
{title: "Inline", items: [
{title: "Bold", icon: "bold", format: "bold"},
{title: "Italic", icon: "italic", format: "italic"},
{title: "Underline", icon: "underline", format: "underline"},
{title: "Strikethrough", icon: "strikethrough", format: "strikethrough"},
{title: "Superscript", icon: "superscript", format: "superscript"},
{title: "Subscript", icon: "subscript", format: "subscript"},
{title: "Code", icon: "code", format: "code"}
]},
{title: "Blocks", items: [
{title: "Paragraph", format: "p"},
{title: "Blockquote", format: "blockquote"},
{title: "Div", format: "div"},
{title: "Pre", format: "pre"}
]},
{title: "Alignment", items: [
{title: "Left", icon: "alignleft", format: "alignleft"},
{title: "Center", icon: "aligncenter", format: "aligncenter"},
{title: "Right", icon: "alignright", format: "alignright"},
{title: "Justify", icon: "alignjustify", format: "alignjustify"}
]}
]
});
tinymce.PluginManager.add('stickytoolbar', function(editor, url) {
editor.on('init', function() {
setSticky();

View File

@ -14,10 +14,16 @@
class blog extends common {
const EDIT_OWNER = 'owner';
const EDIT_GROUP = 'group';
const EDIT_ALL = 'all';
public static $actions = [
'add' => self::GROUP_MODERATOR,
'comment' => self::GROUP_MODERATOR,
'commentApprove' => self::GROUP_MODERATOR,
'commentDelete' => self::GROUP_MODERATOR,
'commentDeleteAll' => self::GROUP_MODERATOR,
'config' => self::GROUP_MODERATOR,
'delete' => self::GROUP_MODERATOR,
'edit' => self::GROUP_MODERATOR,
@ -26,8 +32,21 @@ class blog extends common {
public static $articles = [];
// Signature de l'article
public static $articleSignature = '';
// Signature du commentaire
public static $editCommentSignature = '';
public static $comments = [];
public static $nbCommentsApproved = 0;
public static $commentsDelete;
// Signatures des commentaires déjà saisis
public static $commentsSignature = [];
public static $pages;
public static $states = [
@ -48,10 +67,26 @@ class blog extends common {
'right' => 'À droite ',
];
//Paramètre longueur maximale des commentaires en nb de caractères
public static $commentLength = [
'500' => '500',
'1000' => '1000',
'2000' => '2000',
'5000' => '5000',
'10000' => '10000'
];
// Permissions d'un article
public static $articleConsent = [
self::EDIT_ALL => 'Tous les groupes',
self::EDIT_GROUP => 'Groupe du propriétaire',
self::EDIT_OWNER => 'Propiétaire'
];
public static $users = [];
const BLOG_VERSION = '2.02';
const BLOG_VERSION = '3.1';
/**
* Édition
@ -59,26 +94,39 @@ class blog extends common {
public function add() {
// Soumission du formulaire
if($this->isPost()) {
// Modification de l'userId
if($this->getUser('group') === self::GROUP_ADMIN){
$newuserid = $this->getInput('blogAddUserId', helper::FILTER_STRING_SHORT, true);
}
else{
$newuserid = $this->getUser('id');
}
// Incrémente l'id de l'article
$articleId = helper::increment($this->getInput('blogAddTitle', helper::FILTER_ID), $this->getData(['page']));
$articleId = helper::increment($articleId, (array) $this->getData(['module', $this->getUrl(0)]));
$articleId = helper::increment($articleId, array_keys(self::$actions));
// Crée l'article
$this->setData(['module', $this->getUrl(0), $articleId, [
'closeComment' => $this->getInput('blogAddCloseComment', helper::FILTER_BOOLEAN),
'mailNotification' => $this->getInput('blogAddMailNotification', helper::FILTER_BOOLEAN),
'groupNotification' => $this->getInput('blogAddGroupNotification', helper::FILTER_INT),
'comment' => [],
'content' => $this->getInput('blogAddContent', null),
'picture' => $this->getInput('blogAddPicture', helper::FILTER_STRING_SHORT, true),
'hidePicture' => $this->getInput('blogAddHidePicture', helper::FILTER_BOOLEAN),
'pictureSize' => $this->getInput('blogAddPictureSize', helper::FILTER_STRING_SHORT),
'picturePosition' => $this->getInput('blogAddPicturePosition', helper::FILTER_STRING_SHORT),
'publishedOn' => $this->getInput('blogAddPublishedOn', helper::FILTER_DATETIME, true),
'state' => $this->getInput('blogAddState', helper::FILTER_BOOLEAN),
'title' => $this->getInput('blogAddTitle', helper::FILTER_STRING_SHORT, true),
'userId' => $this->getInput('blogAddUserId', helper::FILTER_ID, true)
]]);
$this->setData(['module',
$this->getUrl(0),
$articleId, [
'comment' => $this->getData(['module', $this->getUrl(0), $this->getUrl(2), 'comment']),
'content' => $this->getInput('blogAddContent', null),
'picture' => $this->getInput('blogAddPicture', helper::FILTER_STRING_SHORT, true),
'hidePicture' => $this->getInput('blogAddHidePicture', helper::FILTER_BOOLEAN),
'pictureSize' => $this->getInput('blogAddPictureSize', helper::FILTER_STRING_SHORT),
'picturePosition' => $this->getInput('blogAddPicturePosition', helper::FILTER_STRING_SHORT),
'publishedOn' => $this->getInput('blogAddPublishedOn', helper::FILTER_DATETIME, true),
'state' => $this->getInput('blogAddState', helper::FILTER_BOOLEAN),
'title' => $this->getInput('blogAddTitle', helper::FILTER_STRING_SHORT, true),
'userId' => $newuserid,
'editConsent' => $this->getInput('blogAddConsent') === self::EDIT_GROUP ? $this->getUser('group') : $this->getInput('blogAddConsent'),
'commentMaxlength' => $this->getInput('blogAddCommentMaxlength'),
'commentApproved' => $this->getInput('blogAddCommentApproved', helper::FILTER_BOOLEAN),
'commentClose' => $this->getInput('blogAddCommentClose', helper::FILTER_BOOLEAN),
'commentNotification' => $this->getInput('blogAddCommentNotification', helper::FILTER_BOOLEAN),
'commentGroupNotification' => $this->getInput('blogAddCommentGroupNotification', helper::FILTER_INT)
]
]);
// Valeurs en sortie
$this->addOutput([
'redirect' => helper::baseUrl() . $this->getUrl(0) . '/config',
@ -108,14 +156,13 @@ class blog extends common {
* Liste des commentaires
*/
public function comment() {
// Liste les commentaires
$comments = [];
foreach((array) $this->getData(['module', $this->getUrl(0)]) as $articleId => $article) {
foreach($article['comment'] as &$comment) {
$comment['articleId'] = $articleId;
}
$comments += $article['comment'];
}
$comments = $this->getData(['module', $this->getUrl(0), $this->getUrl(2),'comment']);
self::$commentsDelete = template::button('blogCommentDeleteAll', [
'class' => 'blogCommentDeleteAll buttonRed',
'href' => helper::baseUrl() . $this->getUrl(0) . '/commentDeleteAll/' . $this->getUrl(2).'/' . $_SESSION['csrf'] ,
'ico' => 'cancel',
'value' => 'Tout effacer'
]);
// Ids des commentaires par ordre de création
$commentIds = array_keys(helper::arrayCollumn($comments, 'createdOn', 'SORT_DESC'));
// Pagination
@ -126,22 +173,34 @@ class blog extends common {
for($i = $pagination['first']; $i < $pagination['last']; $i++) {
// Met en forme le tableau
$comment = $comments[$commentIds[$i]];
// Bouton d'approbation
$buttonApproval = '';
// Compatibilité avec les commentaires des versions précédentes, les valider
$comment['approval'] = array_key_exists('approval', $comment) === false ? true : $comment['approval'] ;
if ( $this->getData(['module', $this->getUrl(0), $this->getUrl(2),'commentApproved']) === true) {
$buttonApproval = template::button('blogCommentApproved' . $commentIds[$i], [
'class' => $comment['approval'] === true ? 'blogCommentRejected buttonGreen' : 'blogCommentApproved buttonRed' ,
'href' => helper::baseUrl() . $this->getUrl(0) . '/commentApprove/' . $this->getUrl(2) . '/' . $commentIds[$i] . '/' . $_SESSION['csrf'] ,
'value' => $comment['approval'] === true ? 'A' : 'R'
]);
}
self::$comments[] = [
mb_detect_encoding(strftime('%d %B %Y - %H:%M', $comment['createdOn']), 'UTF-8', true)
? strftime('%d %B %Y - %H:%M', $comment['createdOn'])
: utf8_encode(strftime('%d %B %Y - %H:%M', $comment['createdOn'])),
$comment['content'],
$comment['userId'] ? $this->getData(['user', $comment['userId'], 'firstname']) . ' ' . $this->getData(['user', $comment['userId'], 'lastname']) : $comment['author'],
$buttonApproval,
template::button('blogCommentDelete' . $commentIds[$i], [
'class' => 'blogCommentDelete buttonRed',
'href' => helper::baseUrl() . $this->getUrl(0) . '/comment-delete/' . $comment['articleId'] . '/' . $commentIds[$i] . '/' . $_SESSION['csrf'] ,
'href' => helper::baseUrl() . $this->getUrl(0) . '/commentDelete/' . $this->getUrl(2) . '/' . $commentIds[$i] . '/' . $_SESSION['csrf'] ,
'value' => template::ico('cancel')
])
];
}
// Valeurs en sortie
$this->addOutput([
'title' => 'Gestion des commentaires',
'title' => 'Gestion des commentaires : '. $this->getData(['module', $this->getUrl(0), $this->getUrl(2), 'title']),
'view' => 'comment'
]);
}
@ -170,25 +229,122 @@ class blog extends common {
$this->deleteData(['module', $this->getUrl(0), $this->getUrl(2), 'comment', $this->getUrl(3)]);
// Valeurs en sortie
$this->addOutput([
'redirect' => helper::baseUrl() . $this->getUrl(0) . '/comment',
'redirect' => helper::baseUrl() . $this->getUrl(0) . '/comment/'.$this->getUrl(2),
'notification' => 'Commentaire supprimé',
'state' => true
]);
}
}
/**
* Suppression de tous les commentaires de l'article $this->getUrl(2)
*/
public function commentDeleteAll() {
// Jeton incorrect
if ($this->getUrl(3) !== $_SESSION['csrf']) {
// Valeurs en sortie
$this->addOutput([
'redirect' => helper::baseUrl() . $this->getUrl(0) . '/config',
'notification' => 'Action non autorisée'
]);
}
// Suppression
else {
$this->setData(['module', $this->getUrl(0), $this->getUrl(2), 'comment',[] ]);
// Valeurs en sortie
$this->addOutput([
'redirect' => helper::baseUrl() . $this->getUrl(0) . '/comment',
'notification' => 'Commentaires supprimés',
'state' => true
]);
}
}
/**
* Approbation oou désapprobation de commentaire
*/
public function commentApprove() {
// Le commentaire n'existe pas
if($this->getData(['module', $this->getUrl(0), $this->getUrl(2), 'comment', $this->getUrl(3)]) === null) {
// Valeurs en sortie
$this->addOutput([
'access' => false
]);
}
// Jeton incorrect
elseif ($this->getUrl(4) !== $_SESSION['csrf']) {
// Valeurs en sortie
$this->addOutput([
'redirect' => helper::baseUrl() . $this->getUrl(0) . '/config',
'notification' => 'Action non autorisée'
]);
}
// Inversion du statut
else {
$approved = !$this->getData(['module', $this->getUrl(0), $this->getUrl(2), 'comment', $this->getUrl(3), 'approval']) ;
$this->setData(['module', $this->getUrl(0), $this->getUrl(2), 'comment', $this->getUrl(3), [
'author' => $this->getData(['module', $this->getUrl(0), $this->getUrl(2), 'comment', $this->getUrl(3), 'author']),
'content' => $this->getData(['module', $this->getUrl(0), $this->getUrl(2), 'comment', $this->getUrl(3), 'content']),
'createdOn' => $this->getData(['module', $this->getUrl(0), $this->getUrl(2), 'comment', $this->getUrl(3), 'createdOn']),
'userId' => $this->getData(['module', $this->getUrl(0), $this->getUrl(2), 'comment', $this->getUrl(3), 'userId']),
'approval' => $approved
]]);
// Valeurs en sortie
$this->addOutput([
'redirect' => helper::baseUrl() . $this->getUrl(0) . '/comment/'.$this->getUrl(2),
'notification' => $approved ? 'Commentaire approuvé' : 'Commentaire rejeté',
'state' => $approved
]);
}
}
/**
* Configuration
*/
public function config() {
// Ids des articles par ordre de publication
$articleIds = array_keys(helper::arrayCollumn($this->getData(['module', $this->getUrl(0)]), 'publishedOn', 'SORT_DESC'));
// Gestion des droits d'accès
$filterData=[];
foreach ($articleIds as $key => $value) {
if (
( // Propriétaire
$this->getData(['module', $this->getUrl(0), $value,'editConsent']) === self::EDIT_OWNER
AND ( $this->getData(['module', $this->getUrl(0), $value,'userId']) === $this->getUser('id')
OR $this->getUser('group') === self::GROUP_ADMIN )
)
OR (
// Groupe
$this->getData(['module', $this->getUrl(0), $value,'editConsent']) !== self::EDIT_OWNER
AND $this->getUser('group') >= $this->getData(['module',$this->getUrl(0), $value,'editConsent'])
)
OR (
// Tout le monde
$this->getData(['module', $this->getUrl(0), $value,'editConsent']) === self::EDIT_ALL
)
) {
$filterData[] = $value;
}
}
$articleIds = $filterData;
// Pagination
$pagination = helper::pagination($articleIds, $this->getUrl(),$this->getData(['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), $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), $articleIds[$i],'comment']));
}
// Met en forme le tableau
$date = mb_detect_encoding(strftime('%d %B %Y', $this->getData(['module', $this->getUrl(0), $articleIds[$i], 'publishedOn'])), 'UTF-8', true)
? strftime('%d %B %Y', $this->getData(['module', $this->getUrl(0), $articleIds[$i], 'publishedOn']))
@ -197,9 +353,17 @@ class blog extends common {
? strftime('%H:%M', $this->getData(['module', $this->getUrl(0), $articleIds[$i], 'publishedOn']))
: utf8_encode(strftime('%H:%M', $this->getData(['module', $this->getUrl(0), $articleIds[$i], 'publishedOn'])));
self::$articles[] = [
$this->getData(['module', $this->getUrl(0), $articleIds[$i], 'title']),
'<a href="' . helper::baseurl() . $this->getUrl(0) . '/' . $articleIds[$i] . '" target="_blank" >' .
$this->getData(['module', $this->getUrl(0), $articleIds[$i], 'title']) .
'</a>',
$date .' à '. $heure,
self::$states[$this->getData(['module', $this->getUrl(0), $articleIds[$i], 'state'])],
// Bouton pour afficher les commentaires de l'article
template::button('blogConfigComment' . $articleIds[$i], [
'class' => ($toApprove || $approved ) > 0 ? 'buttonBlue' : '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')
@ -271,6 +435,12 @@ class blog extends common {
else {
// Soumission du formulaire
if($this->isPost()) {
if($this->getUser('group') === self::GROUP_ADMIN){
$newuserid = $this->getInput('blogEditUserId', helper::FILTER_STRING_SHORT, true);
}
else{
$newuserid = $this->getUser('id');
}
$articleId = $this->getInput('blogEditTitle', helper::FILTER_ID, true);
// Incrémente le nouvel id de l'article
if($articleId !== $this->getUrl(2)) {
@ -278,21 +448,27 @@ class blog extends common {
$articleId = helper::increment($articleId, $this->getData(['module', $this->getUrl(0)]));
$articleId = helper::increment($articleId, array_keys(self::$actions));
}
$this->setData(['module', $this->getUrl(0), $articleId, [
'closeComment' => $this->getInput('blogEditCloseComment'),
'mailNotification' => $this->getInput('blogEditMailNotification', helper::FILTER_BOOLEAN),
'groupNotification' => $this->getInput('blogEditGroupNotification', helper::FILTER_INT),
'comment' => $this->getData(['module', $this->getUrl(0), $this->getUrl(2), 'comment']),
'content' => $this->getInput('blogEditContent', null),
'picture' => $this->getInput('blogEditPicture', helper::FILTER_STRING_SHORT, true),
'hidePicture' => $this->getInput('blogEditHidePicture', helper::FILTER_BOOLEAN),
'pictureSize' => $this->getInput('blogEditPictureSize', helper::FILTER_STRING_SHORT),
'picturePosition' => $this->getInput('blogEditPicturePosition', helper::FILTER_STRING_SHORT),
'publishedOn' => $this->getInput('blogEditPublishedOn', helper::FILTER_DATETIME, true),
'state' => $this->getInput('blogEditState', helper::FILTER_BOOLEAN),
'title' => $this->getInput('blogEditTitle', helper::FILTER_STRING_SHORT, true),
'userId' => $this->getInput('blogEditUserId', helper::FILTER_ID, true)
]]);
$this->setData(['module',
$this->getUrl(0),
$articleId, [
'comment' => $this->getData(['module', $this->getUrl(0), $this->getUrl(2), 'comment']),
'content' => $this->getInput('blogEditContent', null),
'picture' => $this->getInput('blogEditPicture', helper::FILTER_STRING_SHORT, true),
'hidePicture' => $this->getInput('blogEditHidePicture', helper::FILTER_BOOLEAN),
'pictureSize' => $this->getInput('blogEditPictureSize', helper::FILTER_STRING_SHORT),
'picturePosition' => $this->getInput('blogEditPicturePosition', helper::FILTER_STRING_SHORT),
'publishedOn' => $this->getInput('blogEditPublishedOn', helper::FILTER_DATETIME, true),
'state' => $this->getInput('blogEditState', helper::FILTER_BOOLEAN),
'title' => $this->getInput('blogEditTitle', helper::FILTER_STRING_SHORT, true),
'userId' => $newuserid,
'editConsent' => $this->getInput('blogEditConsent') === self::EDIT_GROUP ? $this->getUser('group') : $this->getInput('blogEditConsent'),
'commentMaxlength' => $this->getInput('blogEditCommentMaxlength'),
'commentApproved' => $this->getInput('blogEditCommentApproved', helper::FILTER_BOOLEAN),
'commentClose' => $this->getInput('blogEditCommentClose', helper::FILTER_BOOLEAN),
'commentNotification' => $this->getInput('blogEditCommentNotification', helper::FILTER_BOOLEAN),
'commentGroupNotification' => $this->getInput('blogEditCommentGroupNotification', helper::FILTER_INT)
]
]);
// Supprime l'ancien article
if($articleId !== $this->getUrl(2)) {
$this->deleteData(['module', $this->getUrl(0), $this->getUrl(2)]);
@ -308,7 +484,11 @@ class blog extends common {
self::$users = helper::arrayCollumn($this->getData(['user']), 'firstname');
ksort(self::$users);
foreach(self::$users as $userId => &$userFirstname) {
$userFirstname = $userFirstname . ' ' . $this->getData(['user', $userId, 'lastname']);
// Les membres ne sont pas éditeurs, les exclure de la liste
if ( $this->getData(['user', $userId, 'group']) < self::GROUP_MODERATOR) {
unset(self::$users[$userId]);
}
$userFirstname = $userFirstname . ' ' . $this->getData(['user', $userId, 'lastname']) . ' (' . self::$groupEdits[$this->getData(['user', $userId, 'group'])] . ')';
}
unset($userFirstname);
// Valeurs en sortie
@ -354,37 +534,38 @@ class blog extends common {
}
// Crée le commentaire
$commentId = helper::increment(uniqid(), $this->getData(['module', $this->getUrl(0), $this->getUrl(1), 'comment']));
$content = $this->getInput('blogArticleContent', false);
$this->setData(['module', $this->getUrl(0), $this->getUrl(1), 'comment', $commentId, [
'author' => $this->getInput('blogArticleAuthor', helper::FILTER_STRING_SHORT, empty($this->getInput('blogArticleUserId')) ? TRUE : FALSE),
'content' => $this->getInput('blogArticleContent', helper::FILTER_STRING_SHORT, true),
'content' => $content,
'createdOn' => time(),
'userId' => $this->getInput('blogArticleUserId'),
'approval' => !$this->getData(['module', $this->getUrl(0), $this->getUrl(1), 'commentApproved']) // true commentaire publié false en attente de publication
]]);
// Envoi d'une notification aux administrateurs
// Init tableau
$to = [];
// Liste des destinataires
foreach($this->getData(['user']) as $userId => $user) {
if ($user['group'] >= $this->getData(['module', $this->getUrl(0), $this->getUrl(1), 'groupNotification']) ) {
if ($user['group'] >= $this->getData(['module', $this->getUrl(0), $this->getUrl(1), 'commentGroupNotification']) ) {
$to[] = $user['mail'];
}
}
// Envoi du mail $sent code d'erreur ou de réussite
if ($this->getData(['module', $this->getUrl(0), $this->getUrl(1), 'mailNotification']) === true) {
$notification = $this->getData(['module', $this->getUrl(0), $this->getUrl(1), 'commentApproved']) === true ? 'Commentaire déposé en attente d\'approbation': 'Commentaire déposé';
if ($this->getData(['module', $this->getUrl(0), $this->getUrl(1), 'commentNotification']) === true) {
$sent = $this->sendMail(
$to,
'Nouveau commentaire',
'Bonjour' . ' <strong>' . $user['firstname'] . ' ' . $user['lastname'] . '</strong>,<br><br>' .
'Nouveau commentaire déposé sur la page "' . $this->getData(['page', $this->getUrl(0), 'title']) . '" :<br><br>',
'Bonjour,'.'<br/>'. $notification.
' sur la page "'. $this->getData(['page', $this->getUrl(0), 'title']). '" dans l\'article "'.$this->getUrl(1) .'" :<br/>'.
$content,
''
);
// Valeurs en sortie
$this->addOutput([
'redirect' => helper::baseUrl() . $this->getUrl() . '#comment',
//'notification' => 'Commentaire ajouté',
//'state' => true
'notification' => ($sent === true ? 'Commentaire ajouté et une notification envoyée' : 'Commentaire ajouté, erreur de notification : <br/>' . $sent),
'notification' => ($sent === true ? $notification . '<br/>Une notification a été envoyée.' : $notification . '<br/> Erreur de notification : ' . $sent),
'state' => ($sent === true ? true : null)
]);
@ -392,26 +573,98 @@ class blog extends common {
// Valeurs en sortie
$this->addOutput([
'redirect' => helper::baseUrl() . $this->getUrl() . '#comment',
'notification' => 'Commentaire ajouté',
'notification' => $notification,
'state' => true
]);
}
}
// Ids des commentaires par ordre de publication
$commentIds = array_keys(helper::arrayCollumn($this->getData(['module', $this->getUrl(0), $this->getUrl(1), 'comment']), 'createdOn', 'SORT_DESC'));
// Ids des commentaires approuvés par ordre de publication
$commentsApproved = $this->getData(['module', $this->getUrl(0), $this->getUrl(1), 'comment']);
if ($commentsApproved) {
foreach( $commentsApproved as $key => $value){
if($value['approval']===false) unset($commentsApproved[$key]);
}
// Ligne suivante si affichage du nombre total de commentaires approuvés sous l'article
self::$nbCommentsApproved = count($commentsApproved);
}
$commentIds = array_keys(helper::arrayCollumn($commentsApproved, 'createdOn', 'SORT_DESC'));
// Pagination
$pagination = helper::pagination($commentIds, $this->getUrl(),$this->getData(['config','itemsperPage']),'#comment');
// Liste des pages
self::$pages = $pagination['pages'];
// Signature de l'article
$userIdArticle = $this->getData(['module', $this->getUrl(0), $this->getUrl(1), 'userId']);
switch ($this->getData(['user', $userIdArticle, 'signature'])){
case 1:
self::$articleSignature = $userIdArticle;
break;
case 2:
self::$articleSignature = $this->getData(['user', $userIdArticle, 'pseudo']);
break;
case 3:
self::$articleSignature = $this->getData(['user', $userIdArticle, 'firstname']) . ' ' . $this->getData(['user', $userIdArticle, 'lastname']);
break;
case 4:
self::$articleSignature = $this->getData(['user', $userIdArticle, 'lastname']) . ' ' . $this->getData(['user', $userIdArticle, 'firstname']);
break;
default:
self::$articleSignature = $this->getData(['user', $userIdArticle, 'firstname']);
}
// Signature du commentaire édité
if($this->getUser('password') === $this->getInput('ZWII_USER_PASSWORD')) {
$useridcomment = $this->getUser('id');
switch ($this->getData(['user', $useridcomment, 'signature'])){
case 1:
self::$editCommentSignature = $useridcomment;
break;
case 2:
self::$editCommentSignature = $this->getData(['user', $useridcomment, 'pseudo']);
break;
case 3:
self::$editCommentSignature = $this->getData(['user', $useridcomment, 'firstname']) . ' ' . $this->getData(['user', $useridcomment, 'lastname']);
break;
case 4:
self::$editCommentSignature = $this->getData(['user', $useridcomment, 'lastname']) . ' ' . $this->getData(['user', $useridcomment, 'firstname']);
break;
default:
self::$editCommentSignature = $this->getData(['user', $useridcomment, 'firstname']);
}
}
// Commentaires en fonction de la pagination
for($i = $pagination['first']; $i < $pagination['last']; $i++) {
self::$comments[$commentIds[$i]] = $this->getData(['module', $this->getUrl(0), $this->getUrl(1), 'comment', $commentIds[$i]]);
// Signatures des commentaires
$e = $this->getData(['module', $this->getUrl(0), $this->getUrl(1), 'comment', $commentIds[$i],'userId']);
if ($e) {
switch ($this->getData(['user', $e, 'signature'])){
case 1:
self::$commentsSignature[$commentIds[$i]] = $e;
break;
case 2:
self::$commentsSignature[$commentIds[$i]] = $this->getData(['user', $e, 'pseudo']);
break;
case 3:
self::$commentsSignature[$commentIds[$i]] = $this->getData(['user', $e, 'firstname']) . ' ' . $this->getData(['user', $e, 'lastname']);
break;
case 4:
self::$commentsSignature[$commentIds[$i]] = $this->getData(['user', $e, 'lastname']) . ' ' . $this->getData(['user', $e, 'firstname']);
break;
}
} else {
self::$commentsSignature[$commentIds[$i]] = $this->getData(['module', $this->getUrl(0), $this->getUrl(1), 'comment', $commentIds[$i],'author']);
}
// Données du commentaire si approuvé
if ($this->getData(['module', $this->getUrl(0), $this->getUrl(1), 'comment', $commentIds[$i],'approval']) === true ) {
self::$comments[$commentIds[$i]] = $this->getData(['module', $this->getUrl(0), $this->getUrl(1), 'comment', $commentIds[$i]]);
}
}
// Valeurs en sortie
$this->addOutput([
'showBarEditButton' => true,
'title' => $this->getData(['module', $this->getUrl(0), $this->getUrl(1), 'title']),
'vendor' => [
'tinymce'
],
'view' => 'article'
]);
}
@ -444,4 +697,5 @@ class blog extends common {
]);
}
}
}
}

View File

@ -16,4 +16,39 @@
$("#blogAddDraft").on("click", function() {
$("#blogAddState").val(0);
$("#blogAddForm").trigger("submit");
});
/**
* Options de commentaires
*/
$("#blogAddCommentClose").on("change", function() {
if ($(this).is(':checked') ) {
$(".commentOptionsWrapper").slideUp();
} else {
$(".commentOptionsWrapper").slideDown();
}
});
$("#blogAddCommentNotification").on("change", function() {
if ($(this).is(':checked') ) {
$("#blogAddCommentGroupNotification").slideDown();
} else {
$("#blogAddCommentGroupNotification").slideUp();
}
});
$( document).ready(function() {
if ($("#blogAddCloseComment").is(':checked') ) {
$(".commentOptionsWrapper").slideUp();
} else {
$(".commentOptionsWrapper").slideDown();
}
if ($("#blogAddCommentNotification").is(':checked') ) {
$("#blogAddCommentGroupNotification").slideDown();
} else {
$("#blogAddCommentGroupNotification").slideUp();
}
});

View File

@ -56,9 +56,7 @@
</div>
<div class="row">
<div class="col12">
<?php echo template::checkbox('blogAddHidePicture', true, 'Masquer l\'image dans l\'article', [
'checked' => $this->getData(['module', $this->getUrl(0), $this->getUrl(2), 'hidePicture'])
]); ?>
<?php echo template::checkbox('blogAddHidePicture', true, 'Masquer l\'image dans l\'article'); ?>
</div>
</div>
</div>
@ -68,31 +66,62 @@
'class' => 'editorWysiwyg'
]); ?>
<div class="row">
<div class="col6">
<div class="col12">
<div class="block">
<h4>Options de publication</h4>
<?php echo template::select('blogAddUserId', $module::$users, [
'label' => 'Auteur',
'selected' => $this->getUser('id')
]); ?>
<?php echo template::date('blogAddPublishedOn', [
'help' => 'L\'article n\'est visible qu\'après la date de publication prévue.',
'label' => 'Date de publication',
'value' => time()
]); ?>
</div>
</div>
<div class="col6">
<div class="block">
<h4>Options avancées</h4>
<?php echo template::checkbox('blogAddCloseComment', true, 'Fermer les commentaires' ); ?>
<?php echo template::checkbox('blogAddMailNotification', true, 'Notifier le commentaire aux groupes à partir de :', [
'help' => 'Editeurs = éditeurs + administrateurs<br/> Membres = membres + éditeurs + administrateurs'
]); ?>
<?php echo template::select('blogAddGroupNotification', $module::$groupNews, [
'label' => ''
]); ?>
<div class="row">
<div class="col4">
<?php echo template::select('blogAddUserId', $module::$users, [
'label' => 'Auteur',
'selected' => $this->getUser('id'),
'disabled' => $this->getUser('group') !== self::GROUP_ADMIN ? true : false
]); ?>
</div>
<div class="col4">
<?php echo template::date('blogAddPublishedOn', [
'help' => 'L\'article n\'est visible qu\'après la date de publication prévue.',
'label' => 'Date de publication',
'value' => time()
]); ?>
</div>
<div class="col4">
<?php echo template::select('blogAddConsent', $module::$articleConsent , [
'label' => 'Edition / Suppression',
'selected' => $module::EDIT_ALL,
'help' => 'Les utilisateurs des groupes supérieurs accèdent à l\'article sans restriction'
]); ?>
</div>
</div>
</div>
</div>
</div>
<?php echo template::formClose(); ?>
<div class="row">
<div class="col12">
<div class="block">
<h4>Commentaires</h4>
<div class="row">
<div class="col4 ">
<?php echo template::checkbox('blogAddCommentClose', true, 'Fermer les commentaires'); ?>
</div>
<div class="col4 commentOptionsWrapper ">
<?php echo template::checkbox('blogAddCommentApproved', true, 'Approbation par un modérateur'); ?>
</div>
<div class="col4 commentOptionsWrapper">
<?php echo template::select('blogAddCommentMaxlength', $module::$commentLength,[
'help' => 'Choix du nombre maximum de caractères pour chaque commentaire de l\'article, mise en forme html comprise.',
'label' => 'Caractères par commentaire'
]); ?>
</div>
</div>
<div class="row">
<div class="col3 commentOptionsWrapper offset2">
<?php echo template::checkbox('blogAddCommentNotification', true, 'Notification par email'); ?>
</div>
<div class="col4 commentOptionsWrapper">
<?php echo template::select('blogAddCommentGroupNotification', $module::$groupNews); ?>
</div>
</div>
</div>
</div>
</div>
<?php echo template::formClose(); ?>

View File

@ -50,6 +50,4 @@
.blogArticlePicture {
height:auto;
max-width: 100%;}
}
}

View File

@ -13,17 +13,35 @@
?>
</div>
</div>
<?php if(
$this->getUser('group') >= self::GROUP_ADMIN
AND $this->getUser('password') === $this->getInput('ZWII_USER_PASSWORD')
): ?>
<div class="col2">
<?php echo template::button('blogEdit', [
'href' => helper::baseUrl() . $this->getUrl(0) . '/edit/' . $this->getUrl(1) . '/' . $_SESSION['csrf'],
'value' => 'Editer'
]); ?>
</div>
<?php endif; ?>
<?php if (
$this->getUser('password') === $this->getInput('ZWII_USER_PASSWORD')
AND
( // Propriétaire
(
$this->getData(['module', $this->getUrl(0), $this->getUrl(1),'editConsent']) === $module::EDIT_OWNER
AND ( $this->getData(['module', $this->getUrl(0), $this->getUrl(1),'userId']) === $this->getUser('id')
OR $this->getUser('group') === self::GROUP_ADMIN )
)
OR (
// Groupe
( $this->getData(['module', $this->getUrl(0), $this->getUrl(1),'editConsent']) === self::GROUP_ADMIN
OR $this->getData(['module', $this->getUrl(0), $this->getUrl(1),'editConsent']) === self::GROUP_MODERATOR)
AND $this->getUser('group') >= $this->getData(['module',$this->getUrl(0), $this->getUrl(1),'editConsent'])
)
OR (
// Tout le monde
$this->getData(['module', $this->getUrl(0), $this->getUrl(1),'editConsent']) === $module::EDIT_ALL
AND $this->getUser('group') >= $module::$actions['config']
)
)
): ?>
<?php echo template::button('blogEdit', [
'href' => helper::baseUrl() . $this->getUrl(0) . '/edit/' . $this->getUrl(1) . '/' . $_SESSION['csrf'],
'value' => 'Editer'
]); ?>
<?php endif; ?>
</div>
</div>
<?php $pictureSize = $this->getData(['module', $this->getUrl(0), $this->getUrl(1), 'pictureSize']) === null ? '100' : $this->getData(['module', $this->getUrl(0), $this->getUrl(1), 'pictureSize']); ?>
<?php if ($this->getData(['module', $this->getUrl(0), $this->getUrl(1), 'hidePicture']) == false) {
@ -31,17 +49,14 @@
' pict' . $pictureSize . '" src="' . helper::baseUrl(false) . self::FILE_DIR.'source/' . $this->getData(['module', $this->getUrl(0), $this->getUrl(1), 'picture']) .
'" alt="' . $this->getData(['module', $this->getUrl(0), $this->getUrl(1), 'picture']) . '">';
} ?>
<?php echo $this->getData(['module', $this->getUrl(0), $this->getUrl(1), 'content']); ?>
<p class="clearBoth signature">
<?php echo $this->getData(['user', $this->getData(['module', $this->getUrl(0), $this->getUrl(1), 'userId']), 'firstname']); ?>
<?php echo $this->getData(['user', $this->getData(['module', $this->getUrl(0), $this->getUrl(1), 'userId']), 'lastname']); ?>
</p>
<?php if($this->getData(['module', $this->getUrl(0), $this->getUrl(1), 'closeComment'])): ?>
<p class="clearBoth signature"><?php echo $module::$articleSignature;?></p>
<?php if($this->getData(['module', $this->getUrl(0), $this->getUrl(1), 'commentClose'])): ?>
<p>Cet article ne reçoit pas de commentaire.</p>
<?php else: ?>
<h3 id="comment">
<?php $commentsNb = count($this->getData(['module', $this->getUrl(0), $this->getUrl(1), 'comment'])); ?>
<?php //$commentsNb = count($module::$comments); ?>
<?php $commentsNb = $module::$nbCommentsApproved; ?>
<?php $s = $commentsNb === 1 ? '': 's' ?>
<?php echo $commentsNb > 0 ? $commentsNb . ' ' . 'commentaire' . $s : 'Pas encore de commentaire'; ?>
</h3>
@ -51,11 +66,11 @@
'readonly' => true
]); ?>
<div id="blogArticleCommentWrapper" class="displayNone">
<?php if($this->getUser('password') === $this->getInput('ZWII_USER_PASSWORD')): ?>
<?php if($this->getUser('password') === $this->getInput('ZWII_USER_PASSWORD')): ?>
<?php echo template::text('blogArticleUserName', [
'label' => 'Nom',
'readonly' => true,
'value' => $this->getUser('firstname') . ' ' . $this->getUser('lastname')
'value' => $module::$editCommentSignature
]); ?>
<?php echo template::hidden('blogArticleUserId', [
'value' => $this->getUser('id')
@ -79,9 +94,12 @@
</div>
<?php endif; ?>
<?php echo template::textarea('blogArticleContent', [
'label' => 'Commentaire',
'maxlength' => '500'
'label' => 'Commentaire avec maximum '.$this->getData(['module', $this->getUrl(0), $this->getUrl(1), 'commentMaxlength']).' caractères',
'class' => 'editorWysiwygComment',
'noDirty' => true,
'maxlength' => $this->getData(['module', $this->getUrl(0), $this->getUrl(1), 'commentMaxlength'])
]); ?>
<div id="blogArticleContentAlarm"> </div>
<?php if($this->getUser('password') !== $this->getInput('ZWII_USER_PASSWORD')): ?>
<div class="row">
<div class="col12">
@ -113,17 +131,11 @@
<div class="col12">
<?php foreach($module::$comments as $commentId => $comment): ?>
<div class="block">
<h4>
<?php if($comment['userId']): ?>
<?php echo $this->getData(['user', $comment['userId'], 'firstname']) . ' ' . $this->getData(['user', $comment['userId'], 'lastname']); ?>
<?php else: ?>
<?php echo $comment['author']; ?>
<?php endif; ?>
le <?php echo mb_detect_encoding(strftime('%d %B %Y - %H:%M', $comment['createdOn']), 'UTF-8', true)
<h4><?php echo $module::$commentsSignature[$commentId]; ?>
le <?php echo mb_detect_encoding(strftime('%d %B %Y - %H:%M', $comment['createdOn']), 'UTF-8', true)
? strftime('%d %B %Y - %H:%M', $comment['createdOn'])
: utf8_encode(strftime('%d %B %Y - %H:%M', $comment['createdOn']));
?>
</h4>
?>
<?php echo $comment['content']; ?>
</div>
<?php endforeach; ?>

View File

@ -10,12 +10,53 @@
* @link http://zwiicms.fr/
*/
/**
* Confirmation de suppression
*/
$(".blogCommentDelete").on("click", function() {
var _this = $(this);
return core.confirm("Êtes-vous sûr de vouloir supprimer ce commentaire ?", function() {
var nom = "<?php echo $this->getData(['module', $this->getUrl(0), $this->getUrl(2), 'title' ]); ?>";
return core.confirm("Supprimer le commentaire de l'article " + nom + " ?", function() {
$(location).attr("href", _this.attr("href"));
});
});
});
/**
* Confirmation d'approbation
*/
$(".blogCommentApproved").on("click", function() {
var _this = $(this);
var nom = "<?php echo $this->getData(['module', $this->getUrl(0), $this->getUrl(2), 'title' ]); ?>";
return core.confirm("Approuver le commentaire de l'article " + nom + " ?", function() {
$(location).attr("href", _this.attr("href"));
});
});
/**
* Confirmation de rejet
*/
$(".blogCommentRejected").on("click", function() {
var _this = $(this);
var nom = "<?php echo $this->getData(['module', $this->getUrl(0), $this->getUrl(2), 'title' ]); ?>";
return core.confirm("Rejeter le commentaire de l'article " + nom + " ?", function() {
$(location).attr("href", _this.attr("href"));
});
});
/**
* Confirmation de suppression en masse
*/
$(".blogCommentDeleteAll").on("click", function() {
var _this = $(this);
var nombre = "<?php echo count($this->getData(['module', $this->getUrl(0), $this->getUrl(2), 'comment' ])); ?>";
var nom = "<?php echo $this->getData(['module', $this->getUrl(0), $this->getUrl(2), 'title' ]); ?>";
if( nombre === "1"){
var message = "Supprimer le commentaire de l'article " + nom + " ?";
} else{
var message = "Supprimer les " + nombre + " commentaires de l'article " + nom + " ?";
}
return core.confirm(message, function() {
$(location).attr("href", _this.attr("href"));
});
});

View File

@ -7,10 +7,16 @@
'value' => 'Retour'
]); ?>
</div>
</div>
<?php if($module::$comments): ?>
<?php echo template::table([3, 6, 2, 1], $module::$comments, ['Date', 'Contenu', 'Auteur', '']); ?>
<?php echo $module::$pages; ?>
<div class="col2 offset8">
<?php echo $module::$commentsDelete; ?>
</div>
</div>
<?php echo template::table([3, 5, 2, 1, 1], $module::$comments, ['Date', 'Contenu', 'Auteur', '', '']); ?>
<?php echo $module::$pages.'<br/>'; ?>
<?php else: ?>
</div>
<?php echo template::speech('Aucun commentaire.'); ?>
<?php endif; ?>
<?php endif; ?>

View File

@ -7,13 +7,7 @@
'value' => 'Retour'
]); ?>
</div>
<div class="col3 offset5">
<?php echo template::button('blogConfigComment', [
'href' => helper::baseUrl() . $this->getUrl(0) . '/comment',
'value' => 'Gérer les commentaires'
]); ?>
</div>
<div class="col2">
<div class="col2 offset8">
<?php echo template::button('blogConfigAdd', [
'href' => helper::baseUrl() . $this->getUrl(0) . '/add',
'ico' => 'plus',
@ -22,11 +16,11 @@
</div>
</div>
<?php if($module::$articles): ?>
<?php echo template::table([4, 4, 2, 1, 1], $module::$articles, ['Titre', 'Date de publication', 'État', '', '']); ?>
<?php echo template::table([4, 4, 1, 1, 1, 1], $module::$articles, ['Titre', 'Date de publication', 'État', 'Commentaires', '','']); ?>
<?php echo $module::$pages; ?>
<?php else: ?>
<?php echo template::speech('Aucun article.'); ?>
<?php endif; ?>
<div class="moduleVersion">Version
<?php echo $module::BLOG_VERSION; ?>
</div>
</div>

View File

@ -28,4 +28,39 @@ $("#blogEditMailNotification").on("change", function() {
$("#blogEditDraft").on("click", function() {
$("#blogEditState").val(0);
$("#blogEditForm").trigger("submit");
});
/**
* Options de commentaires
*/
$("#blogEditCommentClose").on("change", function() {
if ($(this).is(':checked') ) {
$(".commentOptionsWrapper").slideUp();
} else {
$(".commentOptionsWrapper").slideDown();
}
});
$("#blogEditCommentNotification").on("change", function() {
if ($(this).is(':checked') ) {
$("#blogEditCommentGroupNotification").slideDown();
} else {
$("#blogEditCommentGroupNotification").slideUp();
}
});
$( document).ready(function() {
if ($("#blogEditCloseComment").is(':checked') ) {
$(".commentOptionsWrapper").slideUp();
} else {
$(".commentOptionsWrapper").slideDown();
}
if ($("#blogEditCommentNotification").is(':checked') ) {
$("#blogEditCommentGroupNotification").slideDown();
} else {
$("#blogEditCommentGroupNotification").slideUp();
}
});

View File

@ -21,6 +21,7 @@
<?php echo template::submit('blogEditSubmit', [
'value' => 'Publier'
]); ?>
</div>
</div>
<div class="row">
@ -73,36 +74,74 @@
'value' => $this->getData(['module', $this->getUrl(0), $this->getUrl(2), 'content'])
]); ?>
<div class="row">
<div class="col6">
<div class="col12">
<div class="block">
<h4>Options de publication</h4>
<?php echo template::select('blogEditUserId', $module::$users, [
'label' => 'Auteur',
'selected' => $this->getUser('id')
]); ?>
<?php echo template::date('blogEditPublishedOn', [
'help' => 'L\'article n\'est visible qu\'après la date de publication prévue.',
'label' => 'Date de publication',
'value' => $this->getData(['module', $this->getUrl(0), $this->getUrl(2), 'publishedOn'])
]); ?>
</div>
</div>
<div class="col6">
<div class="block">
<h4>Options avancées</h4>
<?php echo template::checkbox('blogEditCloseComment', true, 'Fermer les commentaires', [
'checked' => $this->getData(['module', $this->getUrl(0), $this->getUrl(2), 'closeComment'])
]); ?>
<?php echo template::checkbox('blogEditMailNotification', true, 'Notifier le commentaire aux groupes à partir de :', [
'checked' => $this->getData(['module', $this->getUrl(0), $this->getUrl(2), 'mailNotification']),
'help' => 'Editeurs = éditeurs + administrateurs<br/> Membres = membres + éditeurs + administrateurs'
]); ?>
<?php echo template::select('blogEditGroupNotification', $module::$groupNews, [
'label' => '',
'selected' => $this->getData(['module', $this->getUrl(0), $this->getUrl(2), 'groupNotification'])
]); ?>
<div class="row">
<div class="col4">
<?php echo template::select('blogEditUserId', $module::$users, [
'label' => 'Auteur',
'selected' => $this->getUser('id'),
'disabled' => $this->getUser('group') !== self::GROUP_ADMIN ? true : false
]); ?>
</div>
<div class="col4">
<?php echo template::date('blogEditPublishedOn', [
'help' => 'L\'article n\'est visible qu\'après la date de publication prévue.',
'label' => 'Date de publication',
'value' => time()
]); ?>
</div>
<div class="col4">
<?php echo template::select('blogEditConsent', $module::$articleConsent , [
'label' => 'Edition / Suppression',
'selected' => is_numeric($this->getData(['module', $this->getUrl(0), $this->getUrl(2), 'editConsent'])) ? $module::EDIT_GROUP : $this->getData(['module', $this->getUrl(0), $this->getUrl(2), 'editConsent']),
'help' => 'Les utilisateurs des groupes supérieurs accèdent à l\'article sans restriction'
]); ?>
</div>
</div>
</div>
</div>
</div>
<?php echo template::formClose(); ?>
<div class="row">
<div class="col12">
<div class="block">
<h4>Commentaires</h4>
<div class="row">
<div class="col4 ">
<?php echo template::checkbox('blogEditCommentClose', true, 'Fermer les commentaires', [
'checked' => $this->getData(['module', $this->getUrl(0), $this->getUrl(2), 'commentClose'])
]); ?>
</div>
<div class="col4 commentOptionsWrapper ">
<?php echo template::checkbox('blogEditCommentApproved', true, 'Approbation par un modérateur', [
'checked' => $this->getData(['module', $this->getUrl(0), $this->getUrl(2), 'commentApproved']),
''
]); ?>
</div>
<div class="col4 commentOptionsWrapper">
<?php echo template::select('blogEditCommentMaxlength', $module::$commentLength,[
'help' => 'Choix du nombre maximum de caractères pour chaque commentaire de l\'article, mise en forme html comprise.',
'label' => 'Caractères par commentaire',
'selected' => $this->getData(['module', $this->getUrl(0), $this->getUrl(2), 'commentMaxlength'])
]); ?>
</div>
</div>
<div class="row">
<div class="col3 commentOptionsWrapper offset2">
<?php echo template::checkbox('blogEditCommentNotification', true, 'Notification par email', [
'checked' => $this->getData(['module', $this->getUrl(0), $this->getUrl(2), 'commentNotification']),
]); ?>
</div>
<div class="col4 commentOptionsWrapper">
<?php echo template::select('blogEditCommentGroupNotification', $module::$groupNews, [
'selected' => $this->getData(['module', $this->getUrl(0), $this->getUrl(2), 'commentGroupNotification']),
'help' => 'Editeurs = éditeurs + administrateurs<br/> Membres = membres + éditeurs + administrateurs'
]); ?>
</div>
</div>
</div>
</div>
</div>
<?php echo template::formClose(); ?>

View File

@ -21,6 +21,7 @@
</a>
</div>
<div class="col9">
<article>
<h1 class="blogTitle">
<a href="<?php echo helper::baseUrl() . $this->getUrl(0) . '/' . $articleId; ?>">
<?php echo $article['title']; ?>
@ -28,7 +29,9 @@
</h1>
<div class="blogComment">
<a href="<?php echo helper::baseUrl() . $this->getUrl(0) . '/' . $articleId; ?>#comment">
<?php echo count($article['comment']); ?>
<?php if ($article['comment']): ?>
<?php echo count($article['comment']); ?>
<?php endif; ?>
</a>
<?php echo template::ico('comment', 'left'); ?>
</div>
@ -42,6 +45,7 @@
<?php echo helper::subword(strip_tags($article['content']), 0, 400); ?>...
<a href="<?php echo helper::baseUrl() . $this->getUrl(0) . '/' . $articleId; ?>">Lire la suite</a>
</p>
</article>
</div>
</div>
<?php endforeach; ?>

View File

@ -45,7 +45,7 @@
<?php endforeach; ?>
<?php if($this->getData(['module', $this->getUrl(0), 'config', 'captcha'])): ?>
<div class="row">
<div class="col5">
<div class="col12 textAlignCenter">
<?php echo template::captcha('formCaptcha', [
'limit' => $this->getData(['config','captchaStrong'])
]); ?>