forum WIP

This commit is contained in:
Fred Tempez 2022-05-26 18:49:11 +02:00
parent 4af1e61f61
commit 2981220cc3
33 changed files with 3843 additions and 0 deletions

908
module/forum/forum.php Normal file
View File

@ -0,0 +1,908 @@
<?php
/**
* This file is part of Zwii.
* For full copyright and license information, please see the LICENSE
* file that was distributed with this source code.
*
* @author Rémi Jean <remi.jean@outlook.com>
* @copyright Copyright (C) 2008-2018, Rémi Jean
* @author Frédéric Tempez <frederic.tempez@outlook.com>
* @copyright Copyright (C) 2018-2022, Frédéric Tempez
* @license GNU General Public License, version 3
* @link http://zwiicms.fr/
*/
class forum extends common {
const VERSION = '0.1';
const REALNAME = 'Forum';
const DATADIRECTORY = ''; // Contenu localisé inclus par défaut (page.json et module.json)
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,
'option' => self::GROUP_MODERATOR,
'delete' => self::GROUP_MODERATOR,
'edit' => self::GROUP_MODERATOR,
'index' => self::GROUP_VISITOR,
'rss' => self::GROUP_VISITOR
];
public static $sujets = [];
// Signature de l'sujet
public static $sujetSignature = '';
// Signature du Réponse
public static $editCommentSignature = '';
public static $comments = [];
public static $nbCommentsApproved = 0;
public static $commentsDelete;
// Signatures des réponses déjà saisis
public static $commentsSignature = [];
public static $pages;
public static $states = [
false => 'Brouillon',
true => 'Publié'
];
public static $pictureSizes = [
'20' => 'Très petite',
'30' => 'Petite',
'40' => 'Grande',
'50' => 'Très Grande',
'100' => 'Pleine largeur',
];
public static $picturePositions = [
'left' => 'À gauche',
'right' => 'À droite ',
];
// Nombre d'objets par page
public static $SujetsListed = [
1 => '1 sujet',
2 => '2 sujets',
4 => '4 sujets',
6 => '6 sujets',
8 => '8 sujets',
10 => '10 sujets',
12 => '12 sujets'
];
//Paramètre longueur maximale des réponses en nb de caractères
public static $commentLength = [
100 => '100 signes',
250 => '250 signes',
500 => '500 signes',
750 => '750 signes'
];
public static $sujetsLenght = [
0 => 'Intégralité des sujets, disposition moderne',
200 => '200 signes',
400 => '400 signes',
600 => '600 signes',
800 => '800 signes'
];
// Permissions d'un sujet
public static $sujetConsent = [
self::EDIT_ALL => 'Tous les groupes',
self::EDIT_GROUP => 'Groupe du propriétaire',
self::EDIT_OWNER => 'Propriétaire'
];
// Nombre d'sujets dans la page de config:
public static $itemsperPage = 8;
public static $users = [];
/**
* Mise à jour du module
* Appelée par les fonctions index et config
*/
private function update() {
// Initialisation
if (version_compare($this->getData(['module', $this->getUrl(0), 'config', 'versionData']), '0.0', '<') ) {
$this->setData(['module', $this->getUrl(0), 'config', 'feeds', true]);
$this->setData(['module', $this->getUrl(0), 'config', 'feedsLabel', 'Flux RSS']);
$this->setData(['module', $this->getUrl(0), 'config', 'versionData','4.0']);
}
// Version 5.0
if (version_compare($this->getData(['module', $this->getUrl(0), 'config', 'versionData']), '5.0', '<') ) {
$this->setData(['module', $this->getUrl(0), 'config', 'itemsperPage', 6]);
$this->setData(['module', $this->getUrl(0), 'config', 'versionData','5.0']);
}
// Version 6.0
if (version_compare($this->getData(['module', $this->getUrl(0), 'config', 'versionData']), '6.0', '<') ) {
$this->setData(['module', $this->getUrl(0), 'config', 'sujetsLenght', 0]);
$this->setData(['module', $this->getUrl(0), 'config', 'commentMaxlength', 250]);
$this->setData(['module', $this->getUrl(0), 'config', 'versionData','6.0']);
}
}
/**
* Flux RSS
*/
public function rss() {
// Inclure les classes
include_once 'module/blog/vendor/FeedWriter/Item.php';
include_once 'module/blog/vendor/FeedWriter/Feed.php';
include_once 'module/blog/vendor/FeedWriter/RSS2.php';
include_once 'module/blog/vendor/FeedWriter/InvalidOperationException.php';
date_default_timezone_set('UTC');
$feeds = new \FeedWriter\RSS2();
// En-tête
$feeds->setTitle($this->getData (['page', $this->getUrl(0), 'title']));
$feeds->setLink(helper::baseUrl() . $this->getUrl(0));
$feeds->setDescription($this->getData (['page', $this->getUrl(0), 'metaDescription']));
$feeds->setChannelElement('language', 'fr-FR');
$feeds->setDate(date('r',time()));
$feeds->addGenerator();
// Corps des sujets
$sujetIdsPublishedOns = helper::arrayColumn($this->getData(['module', $this->getUrl(0), 'posts']), 'publishedOn', 'SORT_DESC');
$sujetIdsStates = helper::arrayColumn($this->getData(['module', $this->getUrl(0),'posts']), 'state', 'SORT_DESC');
foreach( $sujetIdsPublishedOns as $sujetId => $sujetPublishedOn ) {
if( $sujetPublishedOn <= time() AND $sujetIdsStates[$sujetId] ) {
// Miniature
$parts = explode('/',$this->getData(['module', $this->getUrl(0), 'posts', $sujetId, 'picture']));
$thumb = str_replace ($parts[(count($parts)-1)],'mini_' . $parts[(count($parts)-1)], $this->getData(['module', $this->getUrl(0), 'posts', $sujetId, 'picture']));
// Créer les sujets du flux
$newsSujet = $feeds->createNewItem();
// Signature de l'sujet
$author = $this->signature($this->getData(['module', $this->getUrl(0), 'posts', $sujetId, 'userId']));
$newsSujet->addElementArray([
'title' => $this->getData(['module', $this->getUrl(0), 'posts', $sujetId, 'title']),
'link' => helper::baseUrl() .$this->getUrl(0) . '/' . $sujetId,
'description' => '<img src="' . helper::baseUrl() . self::FILE_DIR . $thumb
. '" alt="' . $this->getData(['module', $this->getUrl(0), 'posts', $sujetId, 'title'])
. '" title="' . $this->getData(['module', $this->getUrl(0), 'posts', $sujetId, 'title'])
. '" />' .
$this->getData(['module', $this->getUrl(0), 'posts', $sujetId, 'content']),
]);
$newsSujet->setAuthor($author,'no@mail.com');
$newsSujet->setId(helper::baseUrl() .$this->getUrl(0) . '/' . $sujetId);
$newsSujet->setDate(date('r', $this->getData(['module', $this->getUrl(0), 'posts', $sujetId, 'publishedOn'])));
if ( file_exists($this->getData(['module', $this->getUrl(0), 'posts', $sujetId, 'picture'])) ) {
$imageData = getimagesize(helper::baseUrl(false) . self::FILE_DIR . 'thumb/' . $thumb);
$newsSujet->addEnclosure( helper::baseUrl(false) . self::FILE_DIR . 'thumb/' . $thumb,
$imageData[0] * $imageData[1],
$imageData['mime']
);
}
$feeds->addItem($newsSujet);
}
}
// Valeurs en sortie
$this->addOutput([
'display' => self::DISPLAY_RSS,
'content' => $feeds->generateFeed(),
'view' => 'rss'
]);
}
/**
* Édition
*/
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'sujet
$sujetId = helper::increment($this->getInput('blogAddPermalink'), $this->getData(['page']));
$sujetId = helper::increment($sujetId, (array) $this->getData(['module', $this->getUrl(0)]));
$sujetId = helper::increment($sujetId, array_keys(self::$actions));
// Crée l'sujet
$this->setData(['module',
$this->getUrl(0),
'posts',
$sujetId, [
'content' => $this->getInput('blogAddContent', null),
'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),
'comment' => []
]
]);
// Valeurs en sortie
$this->addOutput([
'redirect' => helper::baseUrl() . $this->getUrl(0) . '/config',
'notification' => 'Nouvel sujet créé',
'state' => true
]);
}
// Liste des utilisateurs
self::$users = helper::arrayColumn($this->getData(['user']), 'firstname');
ksort(self::$users);
foreach(self::$users as $userId => &$userFirstname) {
$userFirstname = $userFirstname . ' ' . $this->getData(['user', $userId, 'lastname']);
}
unset($userFirstname);
// Valeurs en sortie
$this->addOutput([
'title' => 'Nouveau sujet',
'vendor' => [
'flatpickr',
'tinymce',
'furl'
],
'view' => 'add'
]);
}
/**
* Liste des réponses
*/
public function comment() {
$comments = $this->getData(['module', $this->getUrl(0), 'posts', $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' => 'trash',
'value' => 'Tout effacer'
]);
// Ids des réponses par ordre de création
$commentIds = array_keys(helper::arrayColumn($comments, 'createdOn', 'SORT_DESC'));
// Pagination
$pagination = helper::pagination($commentIds, $this->getUrl(),$this->getData(['module', $this->getUrl(0), 'config', 'itemsperPage']) );
// Liste des pages
self::$pages = $pagination['pages'];
// Réponses en fonction de la pagination
for($i = $pagination['first']; $i < $pagination['last']; $i++) {
// Met en forme le tableau
$comment = $comments[$commentIds[$i]];
// Bouton d'approbation
$buttonApproval = '';
// Compatibilité avec les réponses 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), 'posts', $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) . '/commentDelete/' . $this->getUrl(2) . '/' . $commentIds[$i] . '/' . $_SESSION['csrf'] ,
'value' => template::ico('trash')
])
];
}
// Valeurs en sortie
$this->addOutput([
'title' => 'Gestion des réponses : '. $this->getData(['module', $this->getUrl(0), 'posts', $this->getUrl(2), 'title']),
'view' => 'comment'
]);
}
/**
* Suppression de Réponse
*/
public function commentDelete() {
// Le Réponse n'existe pas
if($this->getData(['module', $this->getUrl(0), 'posts', $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'
]);
}
// Suppression
else {
$this->deleteData(['module', $this->getUrl(0), 'posts', $this->getUrl(2), 'comment', $this->getUrl(3)]);
// Valeurs en sortie
$this->addOutput([
'redirect' => helper::baseUrl() . $this->getUrl(0) . '/comment/'.$this->getUrl(2),
'notification' => 'Réponse supprimé',
'state' => true
]);
}
}
/**
* Suppression de tous les réponses de l'sujet $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), 'posts', $this->getUrl(2), 'comment',[] ]);
// Valeurs en sortie
$this->addOutput([
'redirect' => helper::baseUrl() . $this->getUrl(0) . '/comment',
'notification' => 'Réponses supprimés',
'state' => true
]);
}
}
/**
* Approbation oou désapprobation de Réponse
*/
public function commentApprove() {
// Le Réponse n'existe pas
if($this->getData(['module', $this->getUrl(0), 'posts', $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), 'posts', $this->getUrl(2), 'comment', $this->getUrl(3), 'approval']) ;
$this->setData(['module', $this->getUrl(0), 'posts', $this->getUrl(2), 'comment', $this->getUrl(3), [
'author' => $this->getData(['module', $this->getUrl(0), 'posts', $this->getUrl(2), 'comment', $this->getUrl(3), 'author']),
'content' => $this->getData(['module', $this->getUrl(0), 'posts', $this->getUrl(2), 'comment', $this->getUrl(3), 'content']),
'createdOn' => $this->getData(['module', $this->getUrl(0), 'posts', $this->getUrl(2), 'comment', $this->getUrl(3), 'createdOn']),
'userId' => $this->getData(['module', $this->getUrl(0), 'posts', $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 ? 'Réponse approuvé' : 'Réponse rejeté',
'state' => $approved
]);
}
}
/**
* Configuration
*/
public function config() {
// Ids des sujets par ordre de publication
$sujetIds = array_keys(helper::arrayColumn($this->getData(['module', $this->getUrl(0), 'posts']), 'publishedOn', 'SORT_DESC'));
// Gestion des droits d'accès
$filterData=[];
foreach ($sujetIds as $key => $value) {
if (
( // Propriétaire
$this->getData(['module', $this->getUrl(0), 'posts', $value,'editConsent']) === self::EDIT_OWNER
AND ( $this->getData(['module', $this->getUrl(0), 'posts', $value,'userId']) === $this->getUser('id')
OR $this->getUser('group') === self::GROUP_ADMIN )
)
OR (
// Groupe
$this->getData(['module', $this->getUrl(0), 'posts', $value,'editConsent']) !== self::EDIT_OWNER
AND $this->getUser('group') >= $this->getData(['module',$this->getUrl(0), 'posts', $value,'editConsent'])
)
OR (
// Tout le monde
$this->getData(['module', $this->getUrl(0), 'posts', $value,'editConsent']) === self::EDIT_ALL
)
) {
$filterData[] = $value;
}
}
$sujetIds = $filterData;
// Pagination
$pagination = helper::pagination($sujetIds, $this->getUrl(),self::$itemsperPage);
// Liste des pages
self::$pages = $pagination['pages'];
// Sujets en fonction de la pagination
for($i = $pagination['first']; $i < $pagination['last']; $i++) {
// Nombre de réponses à approuver et approuvés
$approvals = helper::arrayColumn($this->getData(['module', $this->getUrl(0), 'posts', $sujetIds[$i], 'comment' ]),'approval', 'SORT_DESC');
if ( is_array($approvals) ) {
$a = array_values($approvals);
$toApprove = count(array_keys($a,false));
$approved = count(array_keys($a,true));
} else {
$toApprove = 0;
$approved = count($this->getData(['module', $this->getUrl(0), 'posts', $sujetIds[$i],'comment']));
}
// Met en forme le tableau
$date = mb_detect_encoding(strftime('%d %B %Y', $this->getData(['module', $this->getUrl(0), 'posts', $sujetIds[$i], 'publishedOn'])), 'UTF-8', true)
? strftime('%d %B %Y', $this->getData(['module', $this->getUrl(0), 'posts', $sujetIds[$i], 'publishedOn']))
: utf8_encode(strftime('%d %B %Y', $this->getData(['module', $this->getUrl(0), 'posts', $sujetIds[$i], 'publishedOn'])));
$heure = mb_detect_encoding(strftime('%H:%M', $this->getData(['module', $this->getUrl(0), 'posts', $sujetIds[$i], 'publishedOn'])), 'UTF-8', true)
? strftime('%H:%M', $this->getData(['module', $this->getUrl(0), 'posts', $sujetIds[$i], 'publishedOn']))
: utf8_encode(strftime('%H:%M', $this->getData(['module', $this->getUrl(0), 'posts', $sujetIds[$i], 'publishedOn'])));
self::$sujets[] = [
'<a href="' . helper::baseurl() . $this->getUrl(0) . '/' . $sujetIds[$i] . '" target="_blank" >' .
$this->getData(['module', $this->getUrl(0), 'posts', $sujetIds[$i], 'title']) .
'</a>',
$date .' à '. $heure,
self::$states[$this->getData(['module', $this->getUrl(0), 'posts', $sujetIds[$i], 'state'])],
// Bouton pour afficher les réponses de l'sujet
template::button('blogConfigComment' . $sujetIds[$i], [
'class' => ($toApprove || $approved ) > 0 ? '' : 'buttonGrey' ,
'href' => ($toApprove || $approved ) > 0 ? helper::baseUrl() . $this->getUrl(0) . '/comment/' . $sujetIds[$i] : '',
'value' => $toApprove > 0 ? $toApprove . '/' . $approved : $approved,
'help' => ($toApprove || $approved ) > 0 ? 'Editer / Approuver les réponses' : ''
]),
template::button('blogConfigEdit' . $sujetIds[$i], [
'href' => helper::baseUrl() . $this->getUrl(0) . '/edit/' . $sujetIds[$i] . '/' . $_SESSION['csrf'],
'value' => template::ico('pencil'),
'help' => 'Editer l\'sujet'
]),
template::button('blogConfigDelete' . $sujetIds[$i], [
'class' => 'blogConfigDelete buttonRed',
'href' => helper::baseUrl() . $this->getUrl(0) . '/delete/' . $sujetIds[$i] . '/' . $_SESSION['csrf'],
'value' => template::ico('trash'),
'help' => 'Effacer l\'sujet'
])
];
}
// Valeurs en sortie
$this->addOutput([
'title' => 'Configuration du module',
'view' => 'config'
]);
}
public function option() {
// Mise à jour des données de module
$this->update();
// Soumission du formulaire
if($this->isPost()) {
$this->setData(['module', $this->getUrl(0), 'config',[
'feeds' => $this->getInput('blogOptionShowFeeds',helper::FILTER_BOOLEAN),
'feedsLabel' => $this->getInput('blogOptionFeedslabel',helper::FILTER_STRING_SHORT),
'itemsperPage' => $this->getInput('blogOptionItemsperPage', helper::FILTER_INT,true),
'sujetsLenght'=> $this->getInput('blogOptionSujetsLenght', helper::FILTER_INT),
'versionData' => $this->getData(['module', $this->getUrl(0), 'config', 'versionData']),
]]);
// Valeurs en sortie
$this->addOutput([
'redirect' => helper::baseUrl() . $this->getUrl(0) . '/option',
'notification' => 'Modifications enregistrées',
'state' => true
]);
} else {
// Ids des sujets par ordre de publication
$sujetIds = array_keys(helper::arrayColumn($this->getData(['module', $this->getUrl(0), 'posts']), 'publishedOn', 'SORT_DESC'));
// Gestion des droits d'accès
$filterData=[];
foreach ($sujetIds as $key => $value) {
if (
( // Propriétaire
$this->getData(['module', $this->getUrl(0), 'posts', $value,'editConsent']) === self::EDIT_OWNER
AND ( $this->getData(['module', $this->getUrl(0), 'posts', $value,'userId']) === $this->getUser('id')
OR $this->getUser('group') === self::GROUP_ADMIN )
)
OR (
// Groupe
$this->getData(['module', $this->getUrl(0), 'posts', $value,'editConsent']) !== self::EDIT_OWNER
AND $this->getUser('group') >= $this->getData(['module',$this->getUrl(0), 'posts', $value,'editConsent'])
)
OR (
// Tout le monde
$this->getData(['module', $this->getUrl(0), 'posts', $value,'editConsent']) === self::EDIT_ALL
)
) {
$filterData[] = $value;
}
}
$sujetIds = $filterData;
// Pagination
$pagination = helper::pagination($sujetIds, $this->getUrl(),$this->getData(['module', $this->getUrl(0),'config', 'itemsperPage']));
// Liste des pages
self::$pages = $pagination['pages'];
// Sujets en fonction de la pagination
for($i = $pagination['first']; $i < $pagination['last']; $i++) {
// Nombre de réponses à approuver et approuvés
$approvals = helper::arrayColumn($this->getData(['module', $this->getUrl(0), 'posts', $sujetIds[$i], 'comment' ]),'approval', 'SORT_DESC');
if ( is_array($approvals) ) {
$a = array_values($approvals);
$toApprove = count(array_keys($a,false));
$approved = count(array_keys($a,true));
} else {
$toApprove = 0;
$approved = count($this->getData(['module', $this->getUrl(0), 'posts', $sujetIds[$i],'comment']));
}
// Met en forme le tableau
$date = mb_detect_encoding(strftime('%d %B %Y', $this->getData(['module', $this->getUrl(0), 'posts', $sujetIds[$i], 'publishedOn'])), 'UTF-8', true)
? strftime('%d %B %Y', $this->getData(['module', $this->getUrl(0), 'posts', $sujetIds[$i], 'publishedOn']))
: utf8_encode(strftime('%d %B %Y', $this->getData(['module', $this->getUrl(0), 'posts', $sujetIds[$i], 'publishedOn'])));
$heure = mb_detect_encoding(strftime('%H:%M', $this->getData(['module', $this->getUrl(0), 'posts', $sujetIds[$i], 'publishedOn'])), 'UTF-8', true)
? strftime('%H:%M', $this->getData(['module', $this->getUrl(0), 'posts', $sujetIds[$i], 'publishedOn']))
: utf8_encode(strftime('%H:%M', $this->getData(['module', $this->getUrl(0), 'posts', $sujetIds[$i], 'publishedOn'])));
self::$sujets[] = [
'<a href="' . helper::baseurl() . $this->getUrl(0) . '/' . $sujetIds[$i] . '" target="_blank" >' .
$this->getData(['module', $this->getUrl(0), 'posts', $sujetIds[$i], 'title']) .
'</a>',
$date .' à '. $heure,
self::$states[$this->getData(['module', $this->getUrl(0), 'posts', $sujetIds[$i], 'state'])],
// Bouton pour afficher les réponses de l'sujet
template::button('blogConfigComment' . $sujetIds[$i], [
'class' => ($toApprove || $approved ) > 0 ? '' : 'buttonGrey' ,
'href' => ($toApprove || $approved ) > 0 ? helper::baseUrl() . $this->getUrl(0) . '/comment/' . $sujetIds[$i] : '',
'value' => $toApprove > 0 ? $toApprove . '/' . $approved : $approved
]),
template::button('blogConfigEdit' . $sujetIds[$i], [
'href' => helper::baseUrl() . $this->getUrl(0) . '/edit/' . $sujetIds[$i] . '/' . $_SESSION['csrf'],
'value' => template::ico('pencil')
]),
template::button('blogConfigDelete' . $sujetIds[$i], [
'class' => 'blogConfigDelete buttonRed',
'href' => helper::baseUrl() . $this->getUrl(0) . '/delete/' . $sujetIds[$i] . '/' . $_SESSION['csrf'],
'value' => template::ico('cancel')
])
];
}
// Valeurs en sortie
$this->addOutput([
'title' => 'Options de configuration',
'view' => 'option'
]);
}
}
/**
* Suppression
*/
public function delete() {
if($this->getData(['module', $this->getUrl(0), 'posts', $this->getUrl(2)]) === null) {
// Valeurs en sortie
$this->addOutput([
'access' => false
]);
}
// Jeton incorrect
elseif ($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->deleteData(['module', $this->getUrl(0), 'posts', $this->getUrl(2)]);
// Valeurs en sortie
$this->addOutput([
'redirect' => helper::baseUrl() . $this->getUrl(0) . '/config',
'notification' => 'Sujet supprimé',
'state' => true
]);
}
}
/**
* Édition
*/
public function edit() {
// 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'
]);
}
// L'sujet n'existe pas
if($this->getData(['module', $this->getUrl(0), 'posts', $this->getUrl(2)]) === null) {
// Valeurs en sortie
$this->addOutput([
'access' => false
]);
}
// L'sujet existe
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');
}
$sujetId = $this->getInput('blogEditPermalink', null, true);
// Incrémente le nouvel id de l'sujet
if($sujetId !== $this->getUrl(2)) {
$sujetId = helper::increment($sujetId, $this->getData(['page']));
$sujetId = helper::increment($sujetId, $this->getData(['module', $this->getUrl(0),'posts']));
$sujetId = helper::increment($sujetId, array_keys(self::$actions));
}
$this->setData(['module',
$this->getUrl(0),
'posts',
$sujetId, [
'title' => $this->getInput('blogEditTitle', helper::FILTER_STRING_SHORT, true),
'comment' => $this->getData(['module', $this->getUrl(0), 'posts', $this->getUrl(2), 'comment']),
'content' => $this->getInput('blogEditContent', null),
'picture' => $this->getInput('blogEditPicture', helper::FILTER_STRING_SHORT),
'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),
'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 sujet
if($sujetId !== $this->getUrl(2)) {
$this->deleteData(['module', $this->getUrl(0), 'posts', $this->getUrl(2)]);
}
// Valeurs en sortie
$this->addOutput([
'redirect' => helper::baseUrl() . $this->getUrl(0) . '/config',
'notification' => 'Modifications enregistrées',
'state' => true
]);
}
// Liste des utilisateurs
self::$users = helper::arrayColumn($this->getData(['user']), 'firstname');
ksort(self::$users);
foreach(self::$users as $userId => &$userFirstname) {
// 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
$this->addOutput([
'title' => $this->getData(['module', $this->getUrl(0), 'posts', $this->getUrl(2), 'title']),
'vendor' => [
'flatpickr',
'tinymce',
'furl'
],
'view' => 'edit'
]);
}
}
/**
* Accueil (deux affichages en un pour éviter une url à rallonge)
*/
public function index() {
// Mise à jour des données de module
$this->update();
// Affichage d'un sujet
if(
$this->getUrl(1)
// Protection pour la pagination, un ID ne peut pas être un entier, une page oui
AND intval($this->getUrl(1)) === 0
) {
// L'sujet n'existe pas
if($this->getData(['module', $this->getUrl(0), 'posts', $this->getUrl(1)]) === null) {
// Valeurs en sortie
$this->addOutput([
'access' => false
]);
}
// L'sujet existe
else {
// Soumission du formulaire
if($this->isPost()) {
// Check la captcha
if(
$this->getUser('password') !== $this->getInput('ZWII_USER_PASSWORD')
//AND $this->getInput('blogSujetcaptcha', helper::FILTER_INT) !== $this->getInput('blogSujetcaptchaFirstNumber', helper::FILTER_INT) + $this->getInput('blogSujetcaptchaSecondNumber', helper::FILTER_INT))
AND password_verify($this->getInput('blogSujetCaptcha', helper::FILTER_INT), $this->getInput('blogSujetCaptchaResult') ) === false )
{
self::$inputNotices['blogSujetCaptcha'] = 'Incorrect';
}
// Crée le Réponse
$commentId = helper::increment(uniqid(), $this->getData(['module', $this->getUrl(0), 'posts', $this->getUrl(1), 'comment']));
$content = $this->getInput('blogSujetContent', false);
$this->setData(['module', $this->getUrl(0), 'posts', $this->getUrl(1), 'comment', $commentId, [
'author' => $this->getInput('blogSujetAuthor', helper::FILTER_STRING_SHORT, empty($this->getInput('blogSujetUserId')) ? TRUE : FALSE),
'content' => $content,
'createdOn' => time(),
'userId' => $this->getInput('blogSujetUserId'),
'approval' => !$this->getData(['module', $this->getUrl(0), 'posts', $this->getUrl(1), 'commentApproved']) // true Réponse 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), 'posts', $this->getUrl(1), 'commentGroupNotification']) ) {
$to[] = $user['mail'];
$firstname[] = $user['firstname'];
$lastname[] = $user['lastname'];
}
}
// Envoi du mail $sent code d'erreur ou de réussite
$notification = $this->getData(['module', $this->getUrl(0), 'posts', $this->getUrl(1), 'commentApproved']) === true ? 'Réponse déposé en attente d\'approbation': 'Réponse déposé';
if ($this->getData(['module', $this->getUrl(0), 'posts', $this->getUrl(1), 'commentNotification']) === true) {
$error = 0;
foreach($to as $key => $adress){
$sent = $this->sendMail(
$adress,
'Nouveau Réponse déposé',
'Bonjour' . ' <strong>' . $firstname[$key] . ' ' . $lastname[$key] . '</strong>,<br><br>' .
'L\'sujet <a href="' . helper::baseUrl() . $this->getUrl(0) . '/ ' . $this->getUrl(1) . '">' . $this->getData(['module', $this->getUrl(0), 'posts', $this->getUrl(1), 'title']) . '</a> a reçu un nouveau Réponse.<br><br>',
''
);
if( $sent === false) $error++;
}
// Valeurs en sortie
$this->addOutput([
'redirect' => helper::baseUrl() . $this->getUrl() . '#comment',
'notification' => ($error === 0 ? $notification . '<br/>Une notification a été envoyée.' : $notification . '<br/> Erreur de notification : ' . $sent),
'state' => ($sent === true ? true : null)
]);
} else {
// Valeurs en sortie
$this->addOutput([
'redirect' => helper::baseUrl() . $this->getUrl() . '#comment',
'notification' => $notification,
'state' => true
]);
}
}
// Ids des réponses approuvés par ordre de publication
$commentsApproved = $this->getData(['module', $this->getUrl(0), 'posts', $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 réponses approuvés sous l'sujet
self::$nbCommentsApproved = count($commentsApproved);
}
$commentIds = array_keys(helper::arrayColumn($commentsApproved, 'createdOn', 'SORT_DESC'));
// Pagination
$pagination = helper::pagination($commentIds, $this->getUrl(), $this->getData(['module', $this->getUrl(0),'config', 'itemsperPage']),'#comment');
// Liste des pages
self::$pages = $pagination['pages'];
// Signature de l'sujet
self::$sujetSignature = $this->signature($this->getData(['module', $this->getUrl(0), 'posts', $this->getUrl(1), 'userId']));
// Signature du Réponse édité
if($this->getUser('password') === $this->getInput('ZWII_USER_PASSWORD')) {
self::$editCommentSignature = $this->signature($this->getUser('id'));
}
// Réponses en fonction de la pagination
for($i = $pagination['first']; $i < $pagination['last']; $i++) {
// Signatures des réponses
$e = $this->getData(['module', $this->getUrl(0), 'posts', $this->getUrl(1), 'comment', $commentIds[$i],'userId']);
if ($e) {
self::$commentsSignature[$commentIds[$i]] = $this->signature($e);
} else {
self::$commentsSignature[$commentIds[$i]] = $this->getData(['module', $this->getUrl(0), 'posts', $this->getUrl(1), 'comment', $commentIds[$i],'author']);
}
// Données du Réponse si approuvé
if ($this->getData(['module', $this->getUrl(0), 'posts', $this->getUrl(1), 'comment', $commentIds[$i],'approval']) === true ) {
self::$comments[$commentIds[$i]] = $this->getData(['module', $this->getUrl(0), 'posts', $this->getUrl(1), 'comment', $commentIds[$i]]);
}
}
// Valeurs en sortie
$this->addOutput([
'showBarEditButton' => true,
'title' => $this->getData(['module', $this->getUrl(0), 'posts', $this->getUrl(1), 'title']),
'vendor' => [
'tinymce'
],
'view' => 'sujet'
]);
}
}
// Liste des sujets
else {
// Ids des sujets par ordre de publication
$sujetIdsPublishedOns = helper::arrayColumn($this->getData(['module', $this->getUrl(0),'posts']), 'publishedOn', 'SORT_DESC');
$sujetIdsStates = helper::arrayColumn($this->getData(['module', $this->getUrl(0), 'posts']), 'state', 'SORT_DESC');
$sujetIds = [];
foreach($sujetIdsPublishedOns as $sujetId => $sujetPublishedOn) {
if($sujetPublishedOn <= time() AND $sujetIdsStates[$sujetId]) {
$sujetIds[] = $sujetId;
// Nombre de réponses approuvés par sujet
self::$comments [$sujetId] = count ( $this->getData(['module', $this->getUrl(0), 'posts', $sujetId, 'comment']));
}
}
// Pagination
$pagination = helper::pagination($sujetIds, $this->getUrl(), $this->getData(['module', $this->getUrl(0),'config', 'itemsperPage']));
// Liste des pages
self::$pages = $pagination['pages'];
// Sujets en fonction de la pagination
for($i = $pagination['first']; $i < $pagination['last']; $i++) {
self::$sujets[$sujetIds[$i]] = $this->getData(['module', $this->getUrl(0), 'posts', $sujetIds[$i]]);
}
// Valeurs en sortie
$this->addOutput([
'showBarEditButton' => true,
'showPageContent' => true,
'view' => 'index'
]);
}
}
/**
* Retourne la signature d'un utilisateur
*/
public function signature($userId) {
switch ($this->getData(['user', $userId, 'signature'])){
case 1:
return $userId;
break;
case 2:
return $this->getData(['user', $userId, 'pseudo']);
break;
case 3:
return $this->getData(['user', $userId, 'firstname']) . ' ' . $this->getData(['user', $userId, 'lastname']);
break;
case 4:
return $this->getData(['user', $userId, 'lastname']) . ' ' . $this->getData(['user', $userId, 'firstname']);
break;
default:
return $this->getData(['user', $userId, 'firstname']);
}
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 652 B

38
module/forum/vendor/FeedWriter/ATOM.php vendored Normal file
View File

@ -0,0 +1,38 @@
<?php
namespace FeedWriter;
/*
* Copyright (C) 2012 Michael Bemmerl <mail@mx-server.de>
*
* This file is part of the "Universal Feed Writer" project.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/**
* Wrapper for creating ATOM feeds
*
* @package UniversalFeedWriter
*/
class ATOM extends Feed
{
/**
* {@inheritdoc}
*/
public function __construct()
{
parent::__construct(Feed::ATOM);
}
}

1017
module/forum/vendor/FeedWriter/Feed.php vendored Normal file

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,33 @@
<?php
namespace FeedWriter;
use \LogicException;
/*
* Copyright (C) 2016 Michael Bemmerl <mail@mx-server.de>
*
* This file is part of the "Universal Feed Writer" project.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/**
* The exception that is thrown when an invalid operation is performed on
* the object.
*
* @package UniversalFeedWriter
*/
class InvalidOperationException extends LogicException
{
}

413
module/forum/vendor/FeedWriter/Item.php vendored Normal file
View File

@ -0,0 +1,413 @@
<?php
namespace FeedWriter;
use \DateTime;
/*
* Copyright (C) 2008 Anis uddin Ahmad <anisniit@gmail.com>
* Copyright (C) 2010-2013, 2015-2016 Michael Bemmerl <mail@mx-server.de>
*
* This file is part of the "Universal Feed Writer" project.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/**
* Universal Feed Writer
*
* Item class - Used as feed element in Feed class
*
* @package UniversalFeedWriter
* @author Anis uddin Ahmad <anisniit@gmail.com>
* @link http://www.ajaxray.com/projects/rss
*/
class Item
{
/**
* Collection of feed item elements
*/
private $elements = array();
/**
* Contains the format of this feed.
*/
private $version;
/**
* Is used as a suffix when multiple elements have the same name.
**/
private $_cpt = 0;
/**
* Constructor
*
* @param string $version constant (RSS1/RSS2/ATOM) RSS2 is default.
*/
public function __construct($version = Feed::RSS2)
{
$this->version = $version;
}
/**
* Return an unique number
*
* @access private
* @return int
**/
private function cpt()
{
return $this->_cpt++;
}
/**
* Add an element to elements array
*
* @access public
* @param string $elementName The tag name of an element
* @param string $content The content of tag
* @param array $attributes Attributes (if any) in 'attrName' => 'attrValue' format
* @param boolean $overwrite Specifies if an already existing element is overwritten.
* @param boolean $allowMultiple Specifies if multiple elements of the same name are allowed.
* @return self
* @throws \InvalidArgumentException if the element name is not a string, empty or NULL.
*/
public function addElement($elementName, $content, array $attributes = null, $overwrite = FALSE, $allowMultiple = FALSE)
{
if (empty($elementName))
throw new \InvalidArgumentException('The element name may not be empty or NULL.');
if (!is_string($elementName))
throw new \InvalidArgumentException('The element name must be a string.');
$key = $elementName;
// return if element already exists & if overwriting is disabled
// & if multiple elements are not allowed.
if (isset($this->elements[$elementName]) && !$overwrite) {
if (!$allowMultiple)
return $this;
$key .= '-' . $this->cpt();
}
$this->elements[$key]['name'] = $elementName;
$this->elements[$key]['content'] = $content;
$this->elements[$key]['attributes'] = $attributes;
return $this;
}
/**
* Set multiple feed elements from an array.
* Elements which have attributes cannot be added by this method
*
* @access public
* @param array array of elements in 'tagName' => 'tagContent' format.
* @return self
*/
public function addElementArray(array $elementArray)
{
foreach ($elementArray as $elementName => $content) {
$this->addElement($elementName, $content);
}
return $this;
}
/**
* Return the collection of elements in this feed item
*
* @access public
* @return array All elements of this item.
* @throws InvalidOperationException on ATOM feeds if either a content or link element is missing.
* @throws InvalidOperationException on RSS1 feeds if a title or link element is missing.
*/
public function getElements()
{
// ATOM feeds have some specific requirements...
if ($this->version == Feed::ATOM)
{
// Add an 'id' element, if it was not added by calling the setLink method.
// Use the value of the title element as key, since no link element was specified.
if (!array_key_exists('id', $this->elements))
$this->setId(Feed::uuid($this->elements['title']['content'], 'urn:uuid:'));
// Either a 'link' or 'content' element is needed.
if (!array_key_exists('content', $this->elements) && !array_key_exists('link', $this->elements))
throw new InvalidOperationException('ATOM feed entries need a link or a content element. Call the setLink or setContent method.');
}
// ...same with RSS1 feeds.
else if ($this->version == Feed::RSS1)
{
if (!array_key_exists('title', $this->elements))
throw new InvalidOperationException('RSS1 feed entries need a title element. Call the setTitle method.');
if (!array_key_exists('link', $this->elements))
throw new InvalidOperationException('RSS1 feed entries need a link element. Call the setLink method.');
}
return $this->elements;
}
/**
* Return the type of this feed item
*
* @access public
* @return string The feed type, as defined in Feed.php
*/
public function getVersion()
{
return $this->version;
}
// Wrapper functions ------------------------------------------------------
/**
* Set the 'description' element of feed item
*
* @access public
* @param string $description The content of the 'description' or 'summary' element
* @return self
*/
public function setDescription($description)
{
$tag = ($this->version == Feed::ATOM) ? 'summary' : 'description';
return $this->addElement($tag, $description);
}
/**
* Set the 'content' element of the feed item
* For ATOM feeds only
*
* @access public
* @param string $content Content for the item (i.e., the body of a blog post).
* @return self
* @throws InvalidOperationException if this method is called on non-ATOM feeds.
*/
public function setContent($content)
{
if ($this->version != Feed::ATOM)
throw new InvalidOperationException('The content element is supported in ATOM feeds only.');
return $this->addElement('content', $content, array('type' => 'html'));
}
/**
* Set the 'title' element of feed item
*
* @access public
* @param string $title The content of 'title' element
* @return self
*/
public function setTitle($title)
{
return $this->addElement('title', $title);
}
/**
* Set the 'date' element of the feed item.
*
* The value of the date parameter can be either an instance of the
* DateTime class, an integer containing a UNIX timestamp or a string
* which is parseable by PHP's 'strtotime' function.
*
* @access public
* @param DateTime|int|string $date Date which should be used.
* @return self
* @throws \InvalidArgumentException if the given date was not parseable.
*/
public function setDate($date)
{
if (!is_numeric($date)) {
if ($date instanceof DateTime)
$date = $date->getTimestamp();
else {
$date = strtotime($date);
if ($date === FALSE)
throw new \InvalidArgumentException('The given date string was not parseable.');
}
} elseif ($date < 0)
throw new \InvalidArgumentException('The given date is not an UNIX timestamp.');
if ($this->version == Feed::ATOM) {
$tag = 'updated';
$value = date(\DATE_ATOM, $date);
} elseif ($this->version == Feed::RSS2) {
$tag = 'pubDate';
$value = date(\DATE_RSS, $date);
} else {
$tag = 'dc:date';
$value = date("Y-m-d", $date);
}
return $this->addElement($tag, $value);
}
/**
* Set the 'link' element of feed item
*
* @access public
* @param string $link The content of 'link' element
* @return self
*/
public function setLink($link)
{
if ($this->version == Feed::RSS2 || $this->version == Feed::RSS1) {
$this->addElement('link', $link);
} else {
$this->addElement('link','',array('href'=>$link));
$this->setId(Feed::uuid($link,'urn:uuid:'));
}
return $this;
}
/**
* Attach a external media to the feed item.
* Not supported in RSS 1.0 feeds.
*
* See RFC 4288 for syntactical correct MIME types.
*
* Note that you should avoid the use of more than one enclosure in one item,
* since some RSS aggregators don't support it.
*
* @access public
* @param string $url The URL of the media.
* @param integer $length The length of the media.
* @param string $type The MIME type attribute of the media.
* @param boolean $multiple Specifies if multiple enclosures are allowed
* @return self
* @link https://tools.ietf.org/html/rfc4288
* @throws \InvalidArgumentException if the length or type parameter is invalid.
* @throws InvalidOperationException if this method is called on RSS1 feeds.
*/
public function addEnclosure($url, $length, $type, $multiple = TRUE)
{
if ($this->version == Feed::RSS1)
throw new InvalidOperationException('Media attachment is not supported in RSS1 feeds.');
// the length parameter should be set to 0 if it can't be determined
// see http://www.rssboard.org/rss-profile#element-channel-item-enclosure
if (!is_numeric($length) || $length < 0)
throw new \InvalidArgumentException('The length parameter must be an integer and greater or equals to zero.');
// Regex used from RFC 4287, page 41
if (!is_string($type) || preg_match('/.+\/.+/', $type) != 1)
throw new \InvalidArgumentException('type parameter must be a string and a MIME type.');
$attributes = array('length' => $length, 'type' => $type);
if ($this->version == Feed::RSS2) {
$attributes['url'] = $url;
$this->addElement('enclosure', '', $attributes, FALSE, $multiple);
} else {
$attributes['href'] = $url;
$attributes['rel'] = 'enclosure';
$this->addElement('atom:link', '', $attributes, FALSE, $multiple);
}
return $this;
}
/**
* Set the 'author' element of feed item.
* Not supported in RSS 1.0 feeds.
*
* @access public
* @param string $author The author of this item
* @param string|null $email Optional email address of the author
* @param string|null $uri Optional URI related to the author
* @return self
* @throws \InvalidArgumentException if the provided email address is syntactically incorrect.
* @throws InvalidOperationException if this method is called on RSS1 feeds.
*/
public function setAuthor($author, $email = null, $uri = null)
{
if ($this->version == Feed::RSS1)
throw new InvalidOperationException('The author element is not supported in RSS1 feeds.');
// Regex from RFC 4287 page 41
if ($email != null && preg_match('/.+@.+/', $email) != 1)
throw new \InvalidArgumentException('The email address is syntactically incorrect.');
if ($this->version == Feed::RSS2)
{
if ($email != null)
$author = $email . ' (' . $author . ')';
$this->addElement('author', $author);
}
else
{
$elements = array('name' => $author);
if ($email != null)
$elements['email'] = $email;
if ($uri != null)
$elements['uri'] = $uri;
$this->addElement('author', $elements);
}
return $this;
}
/**
* Set the unique identifier of the feed item
*
* On ATOM feeds, the identifier must begin with an valid URI scheme.
*
* @access public
* @param string $id The unique identifier of this item
* @param boolean $permaLink The value of the 'isPermaLink' attribute in RSS 2 feeds.
* @return self
* @throws \InvalidArgumentException if the permaLink parameter is not boolean.
* @throws InvalidOperationException if this method is called on RSS1 feeds.
*/
public function setId($id, $permaLink = false)
{
if ($this->version == Feed::RSS2) {
if (!is_bool($permaLink))
throw new \InvalidArgumentException('The permaLink parameter must be boolean.');
$permaLink = $permaLink ? 'true' : 'false';
$this->addElement('guid', $id, array('isPermaLink' => $permaLink));
} elseif ($this->version == Feed::ATOM) {
// Check if the given ID is an valid URI scheme (see RFC 4287 4.2.6)
// The list of valid schemes was generated from http://www.iana.org/assignments/uri-schemes
// by using only permanent or historical schemes.
$validSchemes = array('aaa', 'aaas', 'about', 'acap', 'acct', 'cap', 'cid', 'coap', 'coaps', 'crid', 'data', 'dav', 'dict', 'dns', 'example', 'fax', 'file', 'filesystem', 'ftp', 'geo', 'go', 'gopher', 'h323', 'http', 'https', 'iax', 'icap', 'im', 'imap', 'info', 'ipp', 'ipps', 'iris', 'iris.beep', 'iris.lwz', 'iris.xpc', 'iris.xpcs', 'jabber', 'ldap', 'mailserver', 'mailto', 'mid', 'modem', 'msrp', 'msrps', 'mtqp', 'mupdate', 'news', 'nfs', 'ni', 'nih', 'nntp', 'opaquelocktoken', 'pack', 'pkcs11', 'pop', 'pres', 'prospero', 'reload', 'rtsp', 'rtsps', 'rtspu', 'service', 'session', 'shttp', 'sieve', 'sip', 'sips', 'sms', 'snews', 'snmp', 'soap.beep', 'soap.beeps', 'stun', 'stuns', 'tag', 'tel', 'telnet', 'tftp', 'thismessage', 'tip', 'tn3270', 'turn', 'turns', 'tv', 'urn', 'vemmi', 'videotex', 'vnc', 'wais', 'ws', 'wss', 'xcon', 'xcon-userid', 'xmlrpc.beep', 'xmlrpc.beeps', 'xmpp', 'z39.50', 'z39.50r', 'z39.50s');
$found = FALSE;
$checkId = strtolower($id);
foreach($validSchemes as $scheme)
if (strrpos($checkId, $scheme . ':', -strlen($checkId)) !== FALSE)
{
$found = TRUE;
break;
}
if (!$found)
throw new \InvalidArgumentException("The ID must begin with an IANA-registered URI scheme.");
$this->addElement('id', $id, NULL, TRUE);
} else
throw new InvalidOperationException('A unique ID is not supported in RSS1 feeds.');
return $this;
}
} // end of class Item

View File

@ -0,0 +1,42 @@
# Generate **RSS 1.0**, **RSS 2.0** or **ATOM** Formatted Feeds
This package can be used to generate feeds in either **RSS 1.0**, **RSS 2.0** or **ATOM** format.
Applications can create a feed object, several feed item objects, set several types of properties of either feed and feed items, and add items to the feed.
Once a feed is fully composed with its items, the feed class can generate the necessary XML structure to describe the feed in **RSS** or **ATOM** format. This structure can be directly sent to the browser, or just returned as string.
## Requirements
- PHP 5.3 or higher
If you don't have **PHP 5.3** available on your system there is a version supporting **PHP 5.0** and above. See the `legacy-php-5.0` branch.
## Documentation
The documentation can be found in the `gh-pages` branch, or on [GitHub Pages](https://mibe.github.io/FeedWriter/).
See the `/examples` directory for usage examples.
See the `CHANGELOG.md` file for changes between the different versions.
## Authors
In chronological order:
- [Anis uddin Ahmad](https://github.com/ajaxray)
- [Michael Bemmerl](https://github.com/mibe)
- Phil Freo
- Paul Ferrett
- Brennen Bearnes
- Michael Robinson
- Baptiste Fontaine
- Kristián Valentín
- Brandtley McMinn
- Julian Bogdani
- Cedric Gampert
- Yamek
- Thielj
- Pavel Khakhlou
- Daniel
- Tino Goratsch

37
module/forum/vendor/FeedWriter/RSS1.php vendored Normal file
View File

@ -0,0 +1,37 @@
<?php
namespace FeedWriter;
/*
* Copyright (C) 2012 Michael Bemmerl <mail@mx-server.de>
*
* This file is part of the "Universal Feed Writer" project.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/**
* Wrapper for creating RSS1 feeds
*
* @package UniversalFeedWriter
*/
class RSS1 extends Feed
{
/**
* {@inheritdoc}
*/
public function __construct()
{
parent::__construct(Feed::RSS1);
}
}

37
module/forum/vendor/FeedWriter/RSS2.php vendored Normal file
View File

@ -0,0 +1,37 @@
<?php
namespace FeedWriter;
/*
* Copyright (C) 2012 Michael Bemmerl <mail@mx-server.de>
*
* This file is part of the "Universal Feed Writer" project.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/**
* Wrapper for creating RSS2 feeds
*
* @package UniversalFeedWriter
*/
class RSS2 extends Feed
{
/**
* {@inheritdoc}
*/
public function __construct()
{
parent::__construct(Feed::RSS2);
}
}

21
module/forum/vendor/furl/LICENSE vendored Normal file
View File

@ -0,0 +1,21 @@
MIT License
Copyright (c) 2019 Vedat Taylan
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

4
module/forum/vendor/furl/README.md vendored Normal file
View File

@ -0,0 +1,4 @@
# furl
jQuery Furl (Friendly URL) Plugin 1.0.0
Usage : $('#InputID').furl({id:'ReplaceInputID', seperate (optional) : '_' });

3
module/forum/vendor/furl/inc.json vendored Normal file
View File

@ -0,0 +1,3 @@
[
"jquery.furl.js"
]

76
module/forum/vendor/furl/jquery.furl.js vendored Normal file
View File

@ -0,0 +1,76 @@
/*
* jQuery Furl (Friendly URL) Plugin 1.0.0
*
* Author : Vedat Taylan
*
* Year : 2018
* Usage : $('#InputID').furl({id:'ReplaceInputID', seperate (optional) : '_' });
*/
(function ($, undefined) {
function Furl() {
this.defaults = {
seperate: '-'
};
}
Furl.prototype = {
init: function (target, options) {
var $this = this;
options = $.extend({}, $this.defaults, options);
$(target).keyup(function () {
var url = urlReplace($(this).val(), options);
var $element = $('#' + options.id);
if ($element.length > 0) {
var tagName = $element.get(0).tagName;
switch (tagName) {
case 'INPUT':
$element.val(url);
break;
default:
$element.text(url);
}
}
});
}
};
function urlReplace(url, options) {
return url.toLowerCase()
.replace(/ä/g, 'ae')
.replace(/Ä/g, 'ae')
.replace(/ğ/g, 'g')
.replace(/ü/g, 'u')
.replace(/ş/g, 's')
.replace(/ı/g, 'i')
.replace(/ö/g, 'o')
.replace(/ç/g, 'c')
.replace(/Ğ/g, 'g')
.replace(/Ü/g, 'u')
.replace(/Ş/g, 's')
.replace(/I/g, 'i')
.replace(/İ/g, 'i')
.replace(/Ö/g, 'o')
.replace(/Ç/g, 'c')
.replace(/[^a-z0-9\s-]/g, "")
.replace(/[\s-]+/g, " ")
.replace(/^\s+|\s+$/g, "")
.replace(/\s/g, "-")
.replace(/^\s+|\s+$/g, "")
.replace(/[_|\s]+/g, "-")
.replace(/[^a-z\u0400-\u04FF0-9-]+/g, "")
.replace(/[-]+/g, "-")
.replace(/^-+|-+$/g, "")
.replace(/[-]+/g, options.seperate);
}
$.furl = new Furl();
$.furl.version = "1.0.0";
$.fn.furl = function (options) {
return this.each(function () {
$.furl.init(this, options);
});
};
})(jQuery);

View File

@ -0,0 +1,18 @@
/**
* This file is part of Zwii.
*
* For full copyright and license information, please see the LICENSE
* file that was distributed with this source code.
*
* @author Rémi Jean <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-2022, Frédéric Tempez
* @license GNU General Public License, version 3
* @link http://zwiicms.fr/
*/
/** NE PAS EFFACER
* admin.css
*/

View File

@ -0,0 +1,58 @@
/**
* 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-2022, Frédéric Tempez
* @license GNU General Public License, version 3
* @link http://zwiicms.fr/
*/
/**
* Soumission du formulaire pour enregistrer en brouillon
*/
$("#blogAddDraft").on("click", function() {
$("#blogAddState").val(0);
$("#blogAddForm").trigger("submit");
});
/**
* Options de réponses
*/
$("#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();
}
// Permalink
$('#blogAddTitle').furl({id:'blogAddPermalink', seperate: '_' });
});

View File

@ -0,0 +1,109 @@
<?php echo template::formOpen('blogAddForm'); ?>
<div class="row">
<div class="col1">
<?php echo template::button('blogAddBack', [
'class' => 'buttonGrey',
'href' => helper::baseUrl() . $this->getUrl(0) . '/config',
'value' => template::ico('left')
]); ?>
</div>
<div class="col2 offset7">
<?php echo template::button('blogAddDraft', [
'uniqueSubmission' => true,
'value' => 'Brouillon'
]); ?>
<?php echo template::hidden('blogAddState', [
'value' => true
]); ?>
</div>
<div class="col2">
<?php echo template::submit('blogAddPublish', [
'value' => 'Publier',
'uniqueSubmission' => true
]); ?>
</div>
</div>
<div class="row">
<div class="col12">
<div class="block">
<h4>Informations générales</h4>
<div class="row">
<div class="col12">
<?php echo template::text('blogAddTitle', [
'label' => 'Titre'
]); ?>
</div>
</div>
<div class="row">
<div class="col12">
<?php echo template::text('blogAddPermalink', [
'label' => 'Permalink'
]); ?>
</div>
</div>
</div>
</div>
</div>
<?php echo template::textarea('blogAddContent', [
'class' => 'editorWysiwyg'
]); ?>
<div class="row">
<div class="col12">
<div class="block">
<h4>Options de publication</h4>
<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\'sujet 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::$sujetConsent , [
'label' => 'Edition / Suppression',
'selected' => $module::EDIT_ALL,
'help' => 'Les utilisateurs des groupes supérieurs accèdent à l\'sujet sans restriction'
]); ?>
</div>
</div>
</div>
</div>
</div>
<div class="row">
<div class="col12">
<div class="block">
<h4>Réponses</h4>
<div class="row">
<div class="col4 ">
<?php echo template::checkbox('blogAddCommentClose', true, 'Fermer les réponses'); ?>
</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 Réponse de l\'sujet, mise en forme html comprise.',
'label' => 'Caractères par Réponse'
]); ?>
</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

@ -0,0 +1,63 @@
#sectionTitle {
margin-top: 0;
margin-bottom: 5px;
}
.blogSujetPicture {
height: auto;
border:1px solid lightgray;
box-shadow: 1px 1px 5px;
}
.blogSujetPictureleft {
float: left;
margin: 15px 10px 5px 0 ;
}
.blogSujetPictureright {
float: right;
margin: 15px 0 5px 10px ;
}
.pict20{
width: 20%;
}
.pict30{
width: 30%;
}
.pict40{
width: 40%;
}
.pict50{
width: 50%;
}
.pict100{
width: 100%;
margin: 15px 0 20px 0 ;
}
#blogSujetCommentShow {
cursor: text;
}
#blogSujetOr {
padding: 10px;
}
.blogDate {
font-style: italic;
color: grey;
height: 100%;
}
@media (max-width: 767px) {
.blogSujetPicture {
height:auto;
max-width: 100%;}
}
#rssFeed {
text-align: right;
float: right;
}
#rssFeed p {
display: inline;
vertical-align: top;
}

View File

@ -0,0 +1,44 @@
/**
* 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-2022, Frédéric Tempez
* @license GNU General Public License, version 3
* @link http://zwiicms.fr/
*/
/**
* Affiche le bloc pour rédiger un Réponse
*/
var commentShowDOM = $("#blogSujetCommentShow");
commentShowDOM.on("click focus", function() {
$("#blogSujetCommentShowWrapper").fadeOut(function() {
$("#blogSujetCommentWrapper").fadeIn();
$("#blogSujetCommentContent").trigger("focus");
});
});
if($("#blogSujetCommentWrapper").find("textarea.notice,input.notice").length) {
commentShowDOM.trigger("click");
}
/**
* Cache le bloc pour rédiger un Réponse
*/
$("#blogSujetCommentHide").on("click focus", function() {
$("#blogSujetCommentWrapper").fadeOut(function() {
$("#blogSujetCommentShowWrapper").fadeIn();
$("#blogSujetCommentContent").val("");
$("#blogSujetCommentAuthor").val("");
});
});
/**
* Force le scroll vers les réponses en cas d'erreur
*/
$("#blogSujetCommentForm").on("submit", function() {
$(location).attr("href", "#comment");
});

View File

@ -0,0 +1,164 @@
<div class="row">
<div class="col12">
<?php $pictureSize = $this->getData(['module', $this->getUrl(0), 'posts', $this->getUrl(1), 'pictureSize']) === null ? '100' : $this->getData(['module', $this->getUrl(0), 'posts', $this->getUrl(1), 'pictureSize']); ?>
<?php if ($this->getData(['module', $this->getUrl(0), 'posts', $this->getUrl(1), 'hidePicture']) == false) {
echo '<img class="blogSujetPicture blogSujetPicture' . $this->getData(['module', $this->getUrl(0), 'posts', $this->getUrl(1), 'picturePosition']) .
' pict' . $pictureSize . '" src="' . helper::baseUrl(false) . self::FILE_DIR.'source/' . $this->getData(['module', $this->getUrl(0), 'posts', $this->getUrl(1), 'picture']) .
'" alt="' . $this->getData(['module', $this->getUrl(0), 'posts', $this->getUrl(1), 'picture']) . '">';
} ?>
<?php echo $this->getData(['module', $this->getUrl(0),'posts', $this->getUrl(1), 'content']); ?>
</div>
</div>
<div class="row verticalAlignMiddle">
<div class="col12 blogDate">
<!-- bloc signature et date -->
<?php echo $module::$sujetSignature . ' - ';?>
<?php echo template::ico('calendar-empty'); ?>
<?php $date = mb_detect_encoding(strftime('%d %B %Y', $this->getData(['module', $this->getUrl(0), 'posts', $this->getUrl(1), 'publishedOn'])), 'UTF-8', true)
? strftime('%d %B %Y', $this->getData(['module', $this->getUrl(0), 'posts', $this->getUrl(1), 'publishedOn']))
: utf8_encode(strftime('%d %B %Y', $this->getData(['module', $this->getUrl(0), 'posts', $this->getUrl(1), 'publishedOn'])));
$heure = mb_detect_encoding(strftime('%H:%M', $this->getData(['module', $this->getUrl(0), 'posts', $this->getUrl(1), 'publishedOn'])), 'UTF-8', true)
? strftime('%H:%M', $this->getData(['module', $this->getUrl(0), 'posts', $this->getUrl(1), 'publishedOn']))
: utf8_encode(strftime('%H:%M', $this->getData(['module', $this->getUrl(0), 'posts', $this->getUrl(1), 'publishedOn'])));
echo $date . ' à ' . $heure;
?>
<!-- Bloc edition -->
<?php if (
$this->getUser('password') === $this->getInput('ZWII_USER_PASSWORD')
AND
( // Propriétaire
(
$this->getData(['module', $this->getUrl(0), 'posts', $this->getUrl(1),'editConsent']) === $module::EDIT_OWNER
AND ( $this->getData(['module', $this->getUrl(0), 'posts', $this->getUrl(1),'userId']) === $this->getUser('id')
OR $this->getUser('group') === self::GROUP_ADMIN )
)
OR (
// Groupe
( $this->getData(['module', $this->getUrl(0), 'posts', $this->getUrl(1),'editConsent']) === self::GROUP_ADMIN
OR $this->getData(['module', $this->getUrl(0), 'posts', $this->getUrl(1),'editConsent']) === self::GROUP_MODERATOR)
AND $this->getUser('group') >= $this->getData(['module',$this->getUrl(0), 'posts', $this->getUrl(1),'editConsent'])
)
OR (
// Tout le monde
$this->getData(['module', $this->getUrl(0), 'posts', $this->getUrl(1),'editConsent']) === $module::EDIT_ALL
AND $this->getUser('group') >= $module::$actions['config']
)
)
): ?>
<a href ="<?php echo helper::baseUrl() . $this->getUrl(0) . '/edit/' . $this->getUrl(1) . '/' . $_SESSION['csrf'];?>">
<?php echo template::ico('pencil');?> Editer
</a>
<?php endif; ?>
<!-- Bloc RSS-->
<?php if ($this->getData(['module',$this->getUrl(0), 'config', 'feeds'])): ?>
<div id="rssFeed">
<a type="application/rss+xml" href="<?php echo helper::baseUrl() . $this->getUrl(0) . '/rss'; ?>" target="_blank">
<img src='module/news/ressource/feed-icon-16.gif' />
<?php
echo '<p>' . $this->getData(['module',$this->getUrl(0), 'config', 'feedsLabel']) . '</p>' ;
?>
</a>
</div>
<?php endif; ?>
</div>
</div>
<?php if($this->getData(['module', $this->getUrl(0), 'posts', $this->getUrl(1), 'commentClose'])): ?>
<p>Cet sujet ne reçoit pas de Réponse.</p>
<?php else: ?>
<div class="row">
<div class="col12" id="comment">
<h3>
<?php
echo template::ico('comment', 'right');
if ($module::$nbCommentsApproved > 0) {
echo $module::$nbCommentsApproved . ' Réponse' . ($module::$nbCommentsApproved > 1 ? 's' : '');
} else {
echo 'Pas encore de Réponse';
}
?>
</h3>
</div>
</div>
<?php echo template::formOpen('blogSujetForm'); ?>
<?php echo template::text('blogSujetCommentShow', [
'placeholder' => 'Rédiger un Réponse...',
'readonly' => true
]); ?>
<div id="blogSujetCommentWrapper" class="displayNone">
<?php if($this->getUser('password') === $this->getInput('ZWII_USER_PASSWORD')): ?>
<?php echo template::text('blogSujetUserName', [
'label' => 'Nom',
'readonly' => true,
'value' => $module::$editCommentSignature
]); ?>
<?php echo template::hidden('blogSujetUserId', [
'value' => $this->getUser('id')
]); ?>
<?php else: ?>
<div class="row">
<div class="col9">
<?php echo template::text('blogSujetAuthor', [
'label' => 'Nom'
]); ?>
</div>
<div class="col1 textAlignCenter verticalAlignBottom">
<div id="blogSujetOr">Ou</div>
</div>
<div class="col2 verticalAlignBottom">
<?php echo template::button('blogSujetLogin', [
'href' => helper::baseUrl() . 'user/login/' . str_replace('/', '_', $this->getUrl()) . '__comment',
'value' => 'Connexion'
]); ?>
</div>
</div>
<?php endif; ?>
<?php echo template::textarea('blogSujetContent', [
'label' => 'Réponse avec maximum '.$this->getData(['module', $this->getUrl(0), 'posts', $this->getUrl(1), 'commentMaxlength']).' caractères',
'class' => 'editorWysiwygComment',
'noDirty' => true,
'maxlength' => $this->getData(['module', $this->getUrl(0), 'posts', $this->getUrl(1), 'commentMaxlength'])
]); ?>
<div id="blogSujetContentAlarm"> </div>
<?php if($this->getUser('password') !== $this->getInput('ZWII_USER_PASSWORD')): ?>
<div class="row">
<div class="col12">
<?php echo template::captcha('blogSujetCaptcha', [
'limit' => $this->getData(['config','connect', 'captchaStrong']),
'type' => $this->getData(['config','connect', 'captchaType'])
]); ?>
</div>
</div>
<?php endif; ?>
<div class="row">
<div class="col2 offset8">
<?php echo template::button('blogSujetCommentHide', [
'class' => 'buttonGrey',
'value' => 'Annuler'
]); ?>
</div>
<div class="col2">
<?php echo template::submit('blogSujetSubmit', [
'value' => 'Envoyer',
'ico' => ''
]); ?>
</div>
</div>
</div>
<?php endif;?>
<div class="row">
<div class="col12">
<?php foreach($module::$comments as $commentId => $comment): ?>
<div class="block">
<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; ?>
</div>
</div>
<?php echo $module::$pages; ?>

View File

@ -0,0 +1,18 @@
/**
* This file is part of Zwii.
*
* For full copyright and license information, please see the LICENSE
* file that was distributed with this source code.
*
* @author Rémi Jean <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-2022, Frédéric Tempez
* @license GNU General Public License, version 3
* @link http://zwiicms.fr/
*/
/** NE PAS EFFACER
* admin.css
*/

View File

@ -0,0 +1,63 @@
/**
* 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-2022, Frédéric Tempez
* @license GNU General Public License, version 3
* @link http://zwiicms.fr/
*/
/**
* Confirmation de suppression
*/
$(".blogCommentDelete").on("click", function() {
var _this = $(this);
var nom = "<?php echo $this->getData(['module', $this->getUrl(0), 'posts', $this->getUrl(2), 'title' ]); ?>";
return core.confirm("Supprimer le Réponse de l'sujet " + 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), 'posts', $this->getUrl(2), 'title' ]); ?>";
return core.confirm("Approuver le Réponse de l'sujet " + 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), 'posts', $this->getUrl(2), 'title' ]); ?>";
return core.confirm("Rejeter le Réponse de l'sujet " + 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), 'posts', $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 Réponse de l'sujet " + nom + " ?";
} else {
var message = "Supprimer les " + nombre + " réponses de l'sujet " + nom + " ?";
}
return core.confirm(message, function() {
$(location).attr("href", _this.attr("href"));
});
});

View File

@ -0,0 +1,22 @@
<div class="row">
<div class="col2">
<?php echo template::button('blogCommentBack', [
'class' => 'buttonGrey',
'href' => helper::baseUrl() . $this->getUrl(0) . '/config',
'ico' => 'left',
'value' => 'Retour'
]); ?>
</div>
<?php if($module::$comments): ?>
<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 Réponse.'); ?>
<?php endif; ?>

View File

@ -0,0 +1,18 @@
/**
* This file is part of Zwii.
*
* For full copyright and license information, please see the LICENSE
* file that was distributed with this source code.
*
* @author Rémi Jean <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-2022, Frédéric Tempez
* @license GNU General Public License, version 3
* @link http://zwiicms.fr/
*/
/** NE PAS EFFACER
* admin.css
*/

View File

@ -0,0 +1,22 @@
/**
* 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-2022, Frédéric Tempez
* @license GNU General Public License, version 3
* @link http://zwiicms.fr/
*/
/**
* Confirmation de suppression
*/
$(".blogConfigDelete").on("click", function() {
var _this = $(this);
return core.confirm("Êtes-vous sûr de vouloir supprimer cet sujet ?", function() {
$(location).attr("href", _this.attr("href"));
});
});

View File

@ -0,0 +1,36 @@
<?php echo template::formOpen('blogConfig'); ?>
<div class="row">
<div class="col1">
<?php echo template::button('blogConfigBack', [
'class' => 'buttonGrey',
'href' => helper::baseUrl() . 'page/edit/' . $this->getUrl(0), 'posts',
'value' => template::ico('left')
]); ?>
</div>
<div class="col1 offset9">
<?php echo template::button('blogConfigOption', [
'href' => helper::baseUrl() . $this->getUrl(0) . '/option',
'value' => template::ico('sliders'),
'help' => 'Options de configuration'
]); ?>
</div>
<div class="col1">
<?php echo template::button('blogConfigAdd', [
'href' => helper::baseUrl() . $this->getUrl(0) . '/add',
'value' => template::ico('plus'),
'help' => 'Rédiger un sujet'
]); ?>
</div>
</div>
<?php echo template::formClose(); ?>
<?php if($module::$sujets): ?>
<?php echo template::table([4, 4, 1, 1, 1, 1], $module::$sujets, ['Titre', 'Date de publication', 'État', 'Réponses', '','']); ?>
<?php echo $module::$pages; ?>
<?php else: ?>
<?php echo template::speech('Aucun sujet.'); ?>
<?php endif; ?>
<div class="moduleVersion">Version
<?php echo $module::VERSION; ?>
</div>

View File

@ -0,0 +1,18 @@
/**
* This file is part of Zwii.
*
* For full copyright and license information, please see the LICENSE
* file that was distributed with this source code.
*
* @author Rémi Jean <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-2022, Frédéric Tempez
* @license GNU General Public License, version 3
* @link http://zwiicms.fr/
*/
/** NE PAS EFFACER
* admin.css
*/

View File

@ -0,0 +1,71 @@
/**
* 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-2022, Frédéric Tempez
* @license GNU General Public License, version 3
* @link http://zwiicms.fr/
*/
// Lien de connexion
$("#blogEditMailNotification").on("change", function() {
if($(this).is(":checked")) {
$("#formConfigGroup").show();
}
else {
$("#formConfigGroup").hide();
}
}).trigger("change");
/**
* Soumission du formulaire pour enregistrer en brouillon
*/
$("#blogEditDraft").on("click", function() {
$("#blogEditState").val(0);
$("#blogEditForm").trigger("submit");
});
/**
* Options de réponses
*/
$("#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();
}
// Permalink
$('#blogEditTitle').furl({id:'blogEditPermalink', seperate: '_' });
});

View File

@ -0,0 +1,152 @@
<?php echo template::formOpen('blogEditForm'); ?>
<div class="row">
<div class="col1">
<?php echo template::button('blogEditBack', [
'class' => 'buttonGrey',
'href' => helper::baseUrl() . $this->getUrl(0) . '/config',
'value' => template::ico('left')
]); ?>
</div>
<div class="col3 offset6">
<?php echo template::button('blogEditDraft', [
'uniqueSubmission' => true,
'value' => 'Brouillon'
]); ?>
<?php echo template::hidden('blogEditState', [
'value' => true
]); ?>
</div>
<div class="col2">
<?php echo template::submit('blogEditSubmit', [
'value' => 'Publier',
'uniqueSubmission' => true
]); ?>
</div>
</div>
<div class="row">
<div class="col12">
<div class="block">
<h4>Informations générales</h4>
<div class="row">
<div class="col6">
<?php echo template::text('blogEditTitle', [
'label' => 'Titre',
'value' => $this->getData(['module', $this->getUrl(0), 'posts', $this->getUrl(2), 'title'])
]); ?>
</div>
<div class="col6">
<?php echo template::text('blogEditPermalink', [
'label' => 'Permalink',
'value' => $this->getUrl(2)
]); ?>
</div>
</div>
<div class="row">
<div class="col6">
<?php echo template::file('blogEditPicture', [
'help' => $this->getData(['theme', 'site', 'width']) !== '100%' ? 'Taille optimale de l\'image de couverture : ' . ((int) substr($this->getData(['theme', 'site', 'width']), 0, -2) - (20 * 2)) . ' x 350 pixels.' : '',
'label' => 'Image de couverture',
'type' => 1,
'value' => $this->getData(['module', $this->getUrl(0), 'posts', $this->getUrl(2), 'picture'])
]); ?>
</div>
<div class="col3">
<?php echo template::select('blogEditPictureSize', $module::$pictureSizes, [
'label' => 'Largeur de l\'image',
'selected' => $this->getData(['module', $this->getUrl(0), 'posts', $this->getUrl(2), 'pictureSize'])
]); ?>
</div>
<div class="col3">
<?php echo template::select('blogEditPicturePosition', $module::$picturePositions, [
'label' => 'Position',
'selected' => $this->getData(['module', $this->getUrl(0), 'posts', $this->getUrl(2), 'picturePosition']),
'help' => 'Le texte de l\'sujet est adapté autour de l\'image'
]); ?>
</div>
</div>
<div class="row">
<div class="col6">
<?php echo template::checkbox('blogEditHidePicture', true, 'Masquer l\'image de couverture dans l\'sujet', [
'checked' => $this->getData(['module', $this->getUrl(0), 'posts', $this->getUrl(2), 'hidePicture'])
]); ?>
</div>
</div>
</div>
</div>
</div>
<?php echo template::textarea('blogEditContent', [
'class' => 'editorWysiwyg',
'value' => $this->getData(['module', $this->getUrl(0), 'posts', $this->getUrl(2), 'content'])
]); ?>
<div class="row">
<div class="col12">
<div class="block">
<h4>Options de publication</h4>
<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\'sujet n\'est visible qu\'après la date de publication prévue.',
'label' => 'Date de publication',
'value' => $this->getData(['module', $this->getUrl(0), 'posts', $this->getUrl(2), 'publishedOn'])
]); ?>
</div>
<div class="col4">
<?php echo template::select('blogEditConsent', $module::$sujetConsent , [
'label' => 'Edition / Suppression',
'selected' => is_numeric($this->getData(['module', $this->getUrl(0), 'posts', $this->getUrl(2), 'editConsent'])) ? $module::EDIT_GROUP : $this->getData(['module', $this->getUrl(0), 'posts', $this->getUrl(2), 'editConsent']),
'help' => 'Les utilisateurs des groupes supérieurs accèdent à l\'sujet sans restriction'
]); ?>
</div>
</div>
</div>
</div>
</div>
<div class="row">
<div class="col12">
<div class="block">
<h4>Réponses</h4>
<div class="row">
<div class="col4 ">
<?php echo template::checkbox('blogEditCommentClose', true, 'Fermer les réponses', [
'checked' => $this->getData(['module', $this->getUrl(0), 'posts', $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), 'posts', $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 Réponse de l\'sujet, mise en forme html comprise.',
'label' => 'Caractères par Réponse',
'selected' => $this->getData(['module', $this->getUrl(0), 'posts', $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), 'posts', $this->getUrl(2), 'commentNotification']),
]); ?>
</div>
<div class="col4 commentOptionsWrapper">
<?php echo template::select('blogEditCommentGroupNotification', $module::$groupNews, [
'selected' => $this->getData(['module', $this->getUrl(0), 'posts', $this->getUrl(2), 'commentGroupNotification']),
'help' => 'Editeurs = éditeurs + administrateurs<br/> Membres = membres + éditeurs + administrateurs'
]); ?>
</div>
</div>
</div>
</div>
</div>
<?php echo template::formClose(); ?>

View File

@ -0,0 +1,104 @@
.rowSujet {
margin-bottom: 10px !important;
}
.blogPicture {
float: none;
border: 1px;
}
.blogPicture img {
width: 100%;
height: auto;
/*
border:1px solid lightgray;
box-shadow: 1px 1px 5px darkgray;
*/
}
#sectionTitle {
margin-top: 0;
margin-bottom: 5px;
}
.blogSujetPicture {
height: auto;
border:1px solid lightgray;
box-shadow: 1px 1px 5px;
}
.blogSujetPictureleft {
float: left;
margin: 15px 10px 5px 0 ;
}
.blogSujetPictureright {
float: right;
margin: 15px 0 5px 10px ;
}
.blogPicture:hover {
opacity: .7;
}
.row:after {
content: " ";
display: table;
clear: both;
}
.blogComment {
padding-right: 10px;
float: right;
}
.blogTitle {
/*background-color: #ECEFF1;*/
padding: 0px;
margin-bottom: 5px;
}
.blogContent {
float: left;
margin-top: 5px;
}
.blogDate {
font-size:0.8em;
font-style: italic;
/*
color: grey;
*/
}
@media (max-width: 768px) {
.blogContent {
display: none;
}
.blogPicture img {
width: 50% ;
display: block;
margin-left: auto;
margin-right: auto;
}
}
.pict20{
width: 20%;
}
.pict30{
width: 30%;
}
.pict40{
width: 40%;
}
.pict50{
width: 50%;
}
.pict100{
width: 100%;
margin: 15px 0 20px 0 ;
}
/*
* Flux RSS
*/
#rssFeed {
text-align: right;
float: right;
}
#rssFeed p {
display: inline;
vertical-align: top;
}

View File

@ -0,0 +1,155 @@
<?php if($module::$sujets): ?>
<sujet>
<?php foreach($module::$sujets as $sujetId => $sujet): ?>
<?php if ($this->getData(['module', $this->getUrl(0), 'config', 'sujetsLenght']) === 0): ?>
<div class="row">
<div class="col12">
<h2 class="blogTitle">
<a href="<?php echo helper::baseUrl() . $this->getUrl(0) . '/' . $sujetId; ?>">
<?php echo $sujet['title']; ?>
</a>
</h2>
</div>
</div>
<div class="row">
<div class="col12">
<?php if ( $this->getData(['module', $this->getUrl(0), 'posts', $sujetId, 'picture']) &&
file_exists( self::FILE_DIR.'source/' . $this->getData(['module', $this->getUrl(0), 'posts', $sujetId, 'picture'])) ): ?>
<?php $pictureSize = $this->getData(['module', $this->getUrl(0), 'posts', $sujetId, 'pictureSize']) === null ? '100' : $this->getData(['module', $this->getUrl(0), 'posts', $sujetId, 'pictureSize']); ?>
<?php if ($this->getData(['module', $this->getUrl(0), 'posts', $sujetId, 'hidePicture']) == false) {
echo '<img class="blogSujetPicture blogSujetPicture' . $this->getData(['module', $this->getUrl(0), 'posts', $sujetId, 'picturePosition']) .
' pict' . $pictureSize . '" src="' . helper::baseUrl(false) . self::FILE_DIR.'source/' . $this->getData(['module', $this->getUrl(0), 'posts', $sujetId, 'picture']) .
'" alt="' . $this->getData(['module', $this->getUrl(0), 'posts', $sujetId, 'picture']) . '">';
} ?>
<?php endif; ?>
<?php echo $this->getData(['module', $this->getUrl(0),'posts', $sujetId, 'content']); ?>
</div>
</div>
<div class="row verticalAlignMiddle">
<div class="col6 blogDate">
<!-- bloc signature et date -->
<?php echo $module->signature($this->getData(['module', $this->getUrl(0), 'posts', $sujetId, 'userId']));?>
<?php echo ' - ';?>
<?php echo template::ico('calendar-empty'); ?>
<?php $date = mb_detect_encoding(strftime('%d %B %Y', $this->getData(['module', $this->getUrl(0), 'posts', $sujetId, 'publishedOn'])), 'UTF-8', true)
? strftime('%d %B %Y', $this->getData(['module', $this->getUrl(0), 'posts', $sujetId, 'publishedOn']))
: utf8_encode(strftime('%d %B %Y', $this->getData(['module', $this->getUrl(0), 'posts', $sujetId, 'publishedOn'])));
$heure = mb_detect_encoding(strftime('%H:%M', $this->getData(['module', $this->getUrl(0), 'posts', $sujetId, 'publishedOn'])), 'UTF-8', true)
? strftime('%H:%M', $this->getData(['module', $this->getUrl(0), 'posts', $sujetId, 'publishedOn']))
: utf8_encode(strftime('%H:%M', $this->getData(['module', $this->getUrl(0), 'posts', $sujetId, 'publishedOn'])));
echo $date . ' à ' . $heure;
?>
<!-- Bloc edition -->
<?php if (
$this->getUser('password') === $this->getInput('ZWII_USER_PASSWORD')
AND
( // Propriétaire
(
$this->getData(['module', $this->getUrl(0), 'posts', $sujetId,'editConsent']) === $module::EDIT_OWNER
AND ( $this->getData(['module', $this->getUrl(0), 'posts', $sujetId,'userId']) === $this->getUser('id')
OR $this->getUser('group') === self::GROUP_ADMIN )
)
OR (
// Groupe
( $this->getData(['module', $this->getUrl(0), 'posts', $sujetId,'editConsent']) === self::GROUP_ADMIN
OR $this->getData(['module', $this->getUrl(0), 'posts', $sujetId,'editConsent']) === self::GROUP_MODERATOR)
AND $this->getUser('group') >= $this->getData(['module',$this->getUrl(0), 'posts', $sujetId,'editConsent'])
)
OR (
// Tout le monde
$this->getData(['module', $this->getUrl(0), 'posts', $sujetId,'editConsent']) === $module::EDIT_ALL
AND $this->getUser('group') >= $module::$actions['config']
)
)
): ?>
<a href ="<?php echo helper::baseUrl() . $this->getUrl(0) . '/edit/' .$sujetId . '/' . $_SESSION['csrf'];?>">
<?php echo template::ico('pencil');?> Editer
</a>
<?php endif; ?>
</div>
<div class="col6 textAlignRight" id="comment">
<?php if($this->getData(['module', $this->getUrl(0), 'posts', $sujetId, 'commentClose'])): ?>
<p>Cet sujet ne reçoit pas de Réponse.</p>
<?php else: ?>
<p>
<?php echo template::ico('comment', 'right'); ?>
<?php
if ($module::$comments[$sujetId] > 0) {
echo '<a href="'. helper::baseUrl() . $this->getUrl(0) . '/' . $sujetId .'">';
echo $module::$comments[$sujetId] . ' Réponse' . ($module::$comments[$sujetId] > 1 ? 's' : '');
echo '</a>';
} else {
echo 'Pas encore de Réponse';
}
?>
</p>
<?php endif; ?>
</div>
</div>
<?php else: ?>
<div class="row rowSujet">
<?php if ( $sujet['picture'] &&
file_exists( self::FILE_DIR . 'source/' . $sujet['picture']) ):?>
<div class="col3">
<?php // Déterminer le nom de la miniature
$parts = explode('/',$sujet['picture']);
$thumb = str_replace ($parts[(count($parts)-1)],'mini_' . $parts[(count($parts)-1)], $sujet['picture']);
// Créer la miniature si manquante
if (!file_exists( self::FILE_DIR . 'thumb/' . $thumb) ) {
$this->makeThumb( self::FILE_DIR . 'source/' . $sujet['picture'],
self::FILE_DIR . 'thumb/' . $thumb,
self::THUMBS_WIDTH);
}
?>
<a href="<?php echo helper::baseUrl() . $this->getUrl(0) . '/' . $sujetId; ?>" class="blogPicture">
<img src="<?php echo helper::baseUrl(false) . self::FILE_DIR . 'thumb/' . $thumb; ?>" alt="<?php echo $sujet['picture']; ?>">
</a>
</div>
<div class="col9">
<?php else:?>
<div class="col12">
<?php endif;?>
<h2 class="blogTitle">
<a href="<?php echo helper::baseUrl() . $this->getUrl(0) . '/' . $sujetId; ?>">
<?php echo $sujet['title']; ?>
</a>
</h2>
<div class="blogComment">
<a href="<?php echo helper::baseUrl() . $this->getUrl(0) . '/' . $sujetId; ?>#comment">
<?php if ($sujet['comment']): ?>
<?php echo count($sujet['comment']); ?>
<?php endif; ?>
</a>
<?php echo template::ico('comment', 'left'); ?>
</div>
<div class="blogDate">
<?php echo template::ico('calendar-empty'); ?>
<?php echo mb_detect_encoding(strftime('%d %B %Y - %H:%M', $sujet['publishedOn']), 'UTF-8', true)
? strftime('%d %B %Y', $sujet['publishedOn'])
: utf8_encode(strftime('%d %B %Y', $sujet['publishedOn'])); ?>
</div>
<p class="blogContent">
<?php $lenght = $this->getData(['module',$this->getUrl(0), 'config', 'sujetsLenght']) !== 0 ? $this->getData(['module',$this->getUrl(0), 'config', 'sujetsLenght']) : 500 ?>
<?php echo helper::subword(strip_tags($sujet['content'],'<br><p>'), 0, $lenght); ?>...
<a href="<?php echo helper::baseUrl() . $this->getUrl(0) . '/' . $sujetId; ?>">Lire la suite</a>
</p>
</div>
</div>
<?php endif; ?>
<?php endforeach; ?>
</sujet>
<?php echo $module::$pages; ?>
<?php if ($this->getData(['module',$this->getUrl(0), 'config', 'feeds'])): ?>
<div id="rssFeed">
<a type="application/rss+xml" href="<?php echo helper::baseUrl() . $this->getUrl(0) . '/rss'; ?>" target="_blank">
<img src='module/blog/ressource/feed-icon-16.gif' />
<?php
echo '<p>' . $this->getData(['module',$this->getUrl(0), 'config', 'feedsLabel']) . '</p>' ;
?>
</a>
</div>
<?php endif; ?>
<?php else: ?>
<?php echo template::speech('Aucun sujet.'); ?>
<?php endif; ?>

View File

@ -0,0 +1,18 @@
/**
* This file is part of Zwii.
*
* For full copyright and license information, please see the LICENSE
* file that was distributed with this source code.
*
* @author Rémi Jean <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-2022, Frédéric Tempez
* @license GNU General Public License, version 3
* @link http://zwiicms.fr/
*/
/** NE PAS EFFACER
* admin.css
*/

View File

@ -0,0 +1,60 @@
<?php echo template::formOpen('blogOption'); ?>
<div class="row">
<div class="col1">
<?php echo template::button('blogOptionBack', [
'class' => 'buttonGrey',
'href' => helper::baseUrl() . $this->getUrl(0) . '/config',
'value' => template::ico('left')
]); ?>
</div>
<div class="col2 offset9">
<?php echo template::submit('blogOptionSubmit'); ?>
</div>
</div>
<div class="row">
<div class="col12">
<div class="block">
<h4>Disposition de la liste des sujets</h4>
<div class="row">
<div class="col6">
<?php echo template::select('blogOptionSujetsLenght', $module::$sujetsLenght, [
'label' => 'Longueur des sujets',
'selected' => $this->getData(['module', $this->getUrl(0), 'config', 'sujetsLenght'])
]); ?>
</div>
<div class="col6">
<?php echo template::select('blogOptionItemsperPage', $module::$SujetsListed, [
'label' => 'Sujets par page',
'selected' => $this->getData(['module', $this->getUrl(0), 'config', 'itemsperPage'])
]); ?>
</div>
</div>
</div>
</div>
</div>
<div class="row">
<div class="col12">
<div class="block">
<h4>Flux RSS</h4>
<div class="row">
<div class="col6">
<?php echo template::checkbox('blogOptionShowFeeds', true, 'Lien du flux RSS', [
'checked' => $this->getData(['module', $this->getUrl(0), 'config', 'feeds']),
]); ?>
</div>
<div class="col6">
<?php echo template::text('blogOptionFeedslabel', [
'label' => 'Texte de l\'étiquette',
'value' => $this->getData(['module', $this->getUrl(0), 'config', 'feedsLabel'])
]); ?>
</div>
</div>
</div>
</div>
</div>
<?php echo template::formClose(); ?>
<div class="moduleVersion">Version
<?php echo $module::VERSION; ?>
</div>

View File

@ -0,0 +1 @@
Le flux RSS est vide ou indisponible !