Compare commits
65 Commits
Author | SHA1 | Date |
---|---|---|
Fred Tempez | 9bfa8280fd | |
Fred Tempez | 55b4e7335d | |
Fred Tempez | f7c2aab390 | |
Fred Tempez | cdab4659a6 | |
Fred Tempez | fc69015448 | |
Fred Tempez | 9e656294a6 | |
Fred Tempez | 8e91faf2d2 | |
Fred Tempez | 36c8619b63 | |
Fred Tempez | d77afce37b | |
Fred Tempez | bca34949a9 | |
Fred Tempez | 07baed8713 | |
Fred Tempez | 6687c324e5 | |
Fred Tempez | 03d1dacb88 | |
Fred Tempez | 77d8296642 | |
Fred Tempez | 999370646b | |
Fred Tempez | d8f4af660f | |
Fred Tempez | 5f146bfbdc | |
Fred Tempez | 950ba8cc9d | |
Fred Tempez | 2448e50793 | |
Fred Tempez | 5e29699563 | |
Fred Tempez | b78fc84a89 | |
Fred Tempez | 665c8dea6d | |
Fred Tempez | 159297e421 | |
Fred Tempez | fc502a1c64 | |
Fred Tempez | 457c8e0f66 | |
Fred Tempez | 660398bad7 | |
Fred Tempez | fad19249db | |
Fred Tempez | 060aa9e4d5 | |
Fred Tempez | 9052247e53 | |
Fred Tempez | df06b1f7ba | |
Fred Tempez | 8d324f9c79 | |
Fred Tempez | f18d4eee1d | |
Fred Tempez | fd51122918 | |
Fred Tempez | 15bd0400ea | |
Fred Tempez | 1147b5c5e1 | |
Fred Tempez | 2cbd3d5923 | |
Fred Tempez | 11753b4476 | |
Fred Tempez | f2a6d35351 | |
Fred Tempez | c4a23de744 | |
Fred Tempez | a47cbe49fe | |
Fred Tempez | 5f5815cbd9 | |
Fred Tempez | e811660d7c | |
Fred Tempez | 10083e7ee8 | |
Fred Tempez | d89455d86a | |
Fred Tempez | 5e7c9597cd | |
Fred Tempez | 49180ab4ed | |
Fred Tempez | c4fc466876 | |
Fred Tempez | 75203d6e8e | |
Fred Tempez | f61c2a977a | |
Fred Tempez | a02ce894c8 | |
Fred Tempez | 2d92bd3963 | |
Fred Tempez | b8c0b47faf | |
Fred Tempez | 2a8563ce9a | |
Fred Tempez | f924a2b2b3 | |
Fred Tempez | 5846c111fe | |
Fred Tempez | f86f38d8b0 | |
Fred Tempez | 68d0aaff84 | |
Fred Tempez | f5f04c90d9 | |
Fred Tempez | d8525bf123 | |
Fred Tempez | 25d6192e0e | |
Fred Tempez | 90a5a8a96a | |
Fred Tempez | 69852c82bc | |
Fred Tempez | f3ae03a133 | |
Fred Tempez | 9b5cc38c94 | |
Fred Tempez | 890cf97127 |
|
@ -9,4 +9,5 @@ site/i18n/*.json
|
|||
core/vendor/tinymce/link_list.json
|
||||
robots.txt
|
||||
sitemap.xml
|
||||
.gitignore
|
||||
.gitignore
|
||||
core/module/config/tool/data.key
|
23
CHANGES.md
23
CHANGES.md
|
@ -1,5 +1,28 @@
|
|||
# Changelog
|
||||
|
||||
## Version 13.2.02
|
||||
|
||||
Corrige un warning quand un module blog ou news ne contient pas d'article.
|
||||
|
||||
|
||||
## Version 13.2.01
|
||||
|
||||
### Correction
|
||||
|
||||
Modification de la fonction d'écriture des données de la classe jsonDB dans le but de s'assurer de l'intégrité des données écrites. Un trafic intense en pointe sur des fichiers volumineux et sur un serveur peu puissant pouvait occasionner des erreurs d'écriture ou un mauvais formatage des données json.
|
||||
|
||||
## Version 13.1.08
|
||||
|
||||
### Corrections
|
||||
|
||||
- Corrige des erreurs quand une page parente ou des pages enfants ont des permissions limitées.
|
||||
- Module Search 3.1 : initialisation du module après installation dans une page sans configration par l'utilisateur.
|
||||
|
||||
### Améliorations
|
||||
|
||||
- Sauvegarde de l'état des sélecteurs dans les tables des fontes et des utilisateurs.
|
||||
- Ajoute des contrôles d'intégrité des bases de données Json lors des opérations de chargement et de sauvegarde.
|
||||
- Fournit une interface pour le contrôle des sauvegardes automatisées et de leur nettoyage par script CRON.
|
||||
|
||||
## Version 13.1.07
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
# ZwiiCMS 13.1.07
|
||||
# ZwiiCMS 13.2.02
|
||||
|
||||
Zwii est un CMS sans base de données (flat-file) qui permet de créer et gérer facilement un site web sans aucune connaissance en programmation.
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
# ZwiiCMS 13.1.07
|
||||
# ZwiiCMS 13.2.02
|
||||
|
||||
Zwii is a database-less (flat-file) CMS that allows you to easily create and manage a web site without any programming knowledge.
|
||||
|
||||
|
|
|
@ -77,7 +77,7 @@ class helper
|
|||
// Créer la variable
|
||||
$data = array_merge($data, [$text => '']);
|
||||
}
|
||||
file_put_contents('site/i18n/' . $to . '.json', json_encode($data, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES | JSON_PRETTY_PRINT), LOCK_EX);
|
||||
file_put_contents('site/i18n/' . $to . '.json', json_encode($data, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES | JSON_PRETTY_PRINT));
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
@ -18,6 +18,12 @@ class JsonDb extends \Prowebcraft\Dot
|
|||
protected $db = '';
|
||||
protected $data = null;
|
||||
protected $config = [];
|
||||
// Tentative d'encodage après échec
|
||||
const MAX_JSON_ENCODE_ATTEMPTS = 5;
|
||||
// Tentative d'écriture après échec
|
||||
const MAX_FILE_WRITE_ATTEMPTS = 5;
|
||||
// Délais entre deux tentaives
|
||||
const RETRY_DELAY_SECONDS = 1;
|
||||
|
||||
public function __construct($config = [])
|
||||
{
|
||||
|
@ -121,10 +127,10 @@ class JsonDb extends \Prowebcraft\Dot
|
|||
} else {
|
||||
if ($this->config['backup']) {
|
||||
try {
|
||||
//todo make backup of database
|
||||
copy($this->config['dir'] . DIRECTORY_SEPARATOR . $this->config['name'], $this->config['dir'] . DIRECTORY_SEPARATOR . $this->config['name'] . '.backup');
|
||||
} catch (\Exception $e) {
|
||||
|
||||
error_log('Erreur de chargement : ' . $e);
|
||||
exit('Erreur de chargement : ' . $e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -142,20 +148,40 @@ class JsonDb extends \Prowebcraft\Dot
|
|||
*/
|
||||
public function save()
|
||||
{
|
||||
$v = json_encode($this->data, JSON_UNESCAPED_UNICODE | JSON_FORCE_OBJECT);
|
||||
$l = strlen($v);
|
||||
$t = 0;
|
||||
while ($t < 5) {
|
||||
$w = file_put_contents($this->db, $v); // Multi user get a locker
|
||||
if ($w == $l) {
|
||||
// Encode les données au format JSON avec les options spécifiées
|
||||
$encoded_data = json_encode($this->data, JSON_UNESCAPED_UNICODE | JSON_FORCE_OBJECT | JSON_PRETTY_PRINT);
|
||||
|
||||
// Vérifie la longueur de la chaîne JSON encodée
|
||||
$encoded_length = strlen($encoded_data);
|
||||
|
||||
// Initialise le compteur de tentatives
|
||||
$attempt = 0;
|
||||
|
||||
// Tente d'encoder les données en JSON et de les sauvegarder jusqu'à 5 fois en cas d'échec
|
||||
while ($attempt < 5) {
|
||||
// Essaye d'écrire les données encodées dans le fichier de base de données
|
||||
$write_result = file_put_contents($this->db, $encoded_data, LOCK_EX); // Les utilisateurs multiples obtiennent un verrou
|
||||
|
||||
// Vérifie si l'écriture a réussi
|
||||
if ($write_result === $encoded_length) {
|
||||
// Sort de la boucle si l'écriture a réussi
|
||||
break;
|
||||
}
|
||||
$t++;
|
||||
}
|
||||
if ($w !== $l) {
|
||||
error_log('Erreur d\'écriture, les données n\'ont pas été sauvegardées.');
|
||||
exit('Erreur d\'écriture, les données n\'ont pas été sauvegardées.');
|
||||
|
||||
// Incrémente le compteur de tentatives
|
||||
$attempt++;
|
||||
|
||||
// Attente
|
||||
sleep(1);
|
||||
}
|
||||
|
||||
// Vérifie si l'écriture a échoué même après plusieurs tentatives
|
||||
if ($write_result !== $encoded_length) {
|
||||
// Enregistre un message d'erreur dans le journal des erreurs
|
||||
error_log('Erreur d\'écriture, les données n\'ont pas été sauvegardées.');
|
||||
|
||||
// Affiche un message d'erreur et termine le script
|
||||
exit('Erreur d\'écriture, les données n\'ont pas été sauvegardées.');
|
||||
}
|
||||
}
|
||||
}
|
|
@ -151,7 +151,7 @@ class layout extends common
|
|||
}
|
||||
echo '</div>';
|
||||
}
|
||||
echo '</main></section>';
|
||||
echo '</section></main>';
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -61,17 +61,17 @@ class core extends common
|
|||
|
||||
// Crée le fichier de personnalisation avancée
|
||||
if (file_exists(self::DATA_DIR . 'custom.css') === false) {
|
||||
file_put_contents(self::DATA_DIR . 'custom.css', file_get_contents('core/module/theme/resource/custom.css'));
|
||||
$this->secure_file_put_contents(self::DATA_DIR . 'custom.css', file_get_contents('core/module/theme/resource/custom.css'));
|
||||
chmod(self::DATA_DIR . 'custom.css', 0755);
|
||||
}
|
||||
// Crée le fichier de personnalisation
|
||||
if (file_exists(self::DATA_DIR . 'theme.css') === false) {
|
||||
file_put_contents(self::DATA_DIR . 'theme.css', '');
|
||||
$this->secure_file_put_contents(self::DATA_DIR . 'theme.css', '');
|
||||
chmod(self::DATA_DIR . 'theme.css', 0755);
|
||||
}
|
||||
// Crée le fichier de personnalisation de l'administration
|
||||
if (file_exists(self::DATA_DIR . 'admin.css') === false) {
|
||||
file_put_contents(self::DATA_DIR . 'admin.css', '');
|
||||
$this->secure_file_put_contents(self::DATA_DIR . 'admin.css', '');
|
||||
chmod(self::DATA_DIR . 'admin.css', 0755);
|
||||
}
|
||||
|
||||
|
@ -273,7 +273,7 @@ class core extends common
|
|||
$css .= '#footerCopyright{text-align:' . $this->getData(['theme', 'footer', 'copyrightAlign']) . '}';
|
||||
|
||||
// Enregistre la personnalisation
|
||||
file_put_contents(self::DATA_DIR . 'theme.css', $css);
|
||||
$this->secure_file_put_contents(self::DATA_DIR . 'theme.css', $css);
|
||||
|
||||
// Effacer le cache pour tenir compte de la couleur de fond TinyMCE
|
||||
header("Expires: Tue, 01 Jan 2000 00:00:00 GMT");
|
||||
|
@ -367,7 +367,7 @@ class core extends common
|
|||
// Bordure du contour TinyMCE
|
||||
$css .= '.mce-tinymce{border: 1px solid ' . $this->getData(['admin', 'borderBlockColor']) . '!important;}';
|
||||
// Enregistre la personnalisation
|
||||
file_put_contents(self::DATA_DIR . 'admin.css', $css);
|
||||
$this->secure_file_put_contents(self::DATA_DIR . 'admin.css', $css);
|
||||
}
|
||||
}
|
||||
/**
|
||||
|
|
182
core/core.php
182
core/core.php
|
@ -51,7 +51,7 @@ class common
|
|||
const ACCESS_TIMER = 1800;
|
||||
|
||||
// Numéro de version
|
||||
const ZWII_VERSION = '13.1.07';
|
||||
const ZWII_VERSION = '13.2.02';
|
||||
|
||||
// URL autoupdate
|
||||
const ZWII_UPDATE_URL = 'https://forge.chapril.org/ZwiiCMS-Team/cms-update/raw/branch/master/';
|
||||
|
@ -60,6 +60,18 @@ class common
|
|||
// Valeurs possibles multiple de 10, 10 autorise 9 profils, 100 autorise 99 profils
|
||||
const MAX_PROFILS = 10;
|
||||
|
||||
const MAX_FILE_WRITE_ATTEMPTS = 5;
|
||||
|
||||
/**
|
||||
* Nombre maximal de tentatives d'encodage JSON
|
||||
*/
|
||||
const MAX_JSON_ENCODE_ATTEMPTS = 3;
|
||||
|
||||
/**
|
||||
* Temps d'attente entre les tentatives en secondes
|
||||
*/
|
||||
const RETRY_DELAY_SECONDS = 1;
|
||||
|
||||
|
||||
public static $actions = [];
|
||||
public static $coreModuleIds = [
|
||||
|
@ -347,6 +359,7 @@ class common
|
|||
// Instanciation de la classe des entrées / sorties
|
||||
$this->jsonDB(self::$siteContent);
|
||||
|
||||
|
||||
// Installation fraîche, initialisation des modules
|
||||
if ($this->user === []) {
|
||||
foreach ($this->dataFiles as $stageId => $item) {
|
||||
|
@ -589,10 +602,48 @@ class common
|
|||
public function setPage($page, $value, $lang)
|
||||
{
|
||||
|
||||
return file_put_contents(self::DATA_DIR . $lang . '/content/' . $page . '.html', $value);
|
||||
return $this->secure_file_put_contents(self::DATA_DIR . $lang . '/content/' . $page . '.html', $value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Écrit les données dans un fichier avec plusieurs tentatives d'écriture et verrouillage
|
||||
*
|
||||
* @param string $filename Le nom du fichier
|
||||
* @param string $data Les données à écrire dans le fichier
|
||||
* @param int $flags Les drapeaux optionnels à passer à la fonction $this->secure_file_put_contents
|
||||
* @return bool True si l'écriture a réussi, sinon false
|
||||
*/
|
||||
function secure_file_put_contents($filename, $data, $flags = 0)
|
||||
{
|
||||
|
||||
// Initialise le compteur de tentatives
|
||||
$attempts = 0;
|
||||
|
||||
// Convertit les données en chaîne de caractères
|
||||
$serialized_data = serialize($data);
|
||||
|
||||
// Vérifie la longueur des données
|
||||
$data_length = strlen($serialized_data);
|
||||
|
||||
// Effectue jusqu'à 5 tentatives d'écriture
|
||||
while ($attempts < 5) {
|
||||
// Essaye d'écrire les données dans le fichier avec verrouillage exclusif
|
||||
$write_result = file_put_contents($filename, $data, LOCK_EX | $flags);
|
||||
|
||||
// Vérifie si l'écriture a réussi
|
||||
if ($write_result !== false && $write_result === $data_length) {
|
||||
// Sort de la boucle si l'écriture a réussi
|
||||
return true;
|
||||
}
|
||||
|
||||
// Incrémente le compteur de tentatives
|
||||
$attempts++;
|
||||
}
|
||||
|
||||
// Échec de l'écriture après plusieurs tentatives
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Effacer les données de la page
|
||||
|
@ -706,65 +757,65 @@ class common
|
|||
* Appelée par le core uniquement
|
||||
*/
|
||||
|
||||
private function buildHierarchy()
|
||||
{
|
||||
|
||||
$pages = helper::arrayColumn($this->getData(['page']), 'position', 'SORT_ASC');
|
||||
// Parents
|
||||
foreach ($pages as $pageId => $pagePosition) {
|
||||
if (
|
||||
// Page parent
|
||||
$this->getData(['page', $pageId, 'parentPageId']) === ""
|
||||
// Ignore les pages dont l'utilisateur n'a pas accès
|
||||
and ($this->getData(['page', $pageId, 'group']) === self::GROUP_VISITOR
|
||||
or ($this->getUser('password') === $this->getInput('ZWII_USER_PASSWORD')
|
||||
//and $this->getUser('group') >= $this->getData(['page', $pageId, 'group'])
|
||||
// Modification qui tient compte du profil de la page
|
||||
and ($this->getUser('group') * self::MAX_PROFILS + $this->getUser('profil')) >= ($this->getData(['page', $pageId, 'group']) * self::MAX_PROFILS + $this->getData(['page', $pageId, 'profil']))
|
||||
|
||||
)
|
||||
)
|
||||
) {
|
||||
if ($pagePosition !== 0) {
|
||||
$this->hierarchy['visible'][$pageId] = [];
|
||||
}
|
||||
if ($this->getData(['page', $pageId, 'block']) === 'bar') {
|
||||
$this->hierarchy['bar'][$pageId] = [];
|
||||
}
|
||||
$this->hierarchy['all'][$pageId] = [];
|
||||
}
|
||||
}
|
||||
// Enfants
|
||||
foreach ($pages as $pageId => $pagePosition) {
|
||||
if (
|
||||
// Page parent
|
||||
$parentId = $this->getData(['page', $pageId, 'parentPageId'])
|
||||
// Ignore les pages dont l'utilisateur n'a pas accès
|
||||
and (
|
||||
($this->getData(['page', $pageId, 'group']) === self::GROUP_VISITOR
|
||||
and $this->getData(['page', $parentId, 'group']) === self::GROUP_VISITOR
|
||||
)
|
||||
or ($this->getUser('password') === $this->getInput('ZWII_USER_PASSWORD')
|
||||
//and $this->getUser('group') >= $this->getData(['page', $parentId, 'group'])
|
||||
//and $this->getUser('group') >= $this->getData(['page', $pageId, 'group'])
|
||||
|
||||
// Modification qui tient compte du profil de la page
|
||||
and ($this->getUser('group') * self::MAX_PROFILS + $this->getUser('profil')) >= ($this->getData(['page', $this->$parentId, 'group']) * self::MAX_PROFILS + $this->getData(['page', $this->$parentId, 'profil']))
|
||||
and ($this->getUser('group') * self::MAX_PROFILS + $this->getUser('profil')) >= ($this->getData(['page', $this->$pageId, 'group']) * self::MAX_PROFILS + $this->getData(['page', $pageId, 'profil']))
|
||||
|
||||
)
|
||||
)
|
||||
) {
|
||||
if ($pagePosition !== 0) {
|
||||
$this->hierarchy['visible'][$parentId][] = $pageId;
|
||||
}
|
||||
if ($this->getData(['page', $pageId, 'block']) === 'bar') {
|
||||
$this->hierarchy['bar'][$pageId] = [];
|
||||
}
|
||||
$this->hierarchy['all'][$parentId][] = $pageId;
|
||||
}
|
||||
}
|
||||
}
|
||||
private function buildHierarchy()
|
||||
{
|
||||
|
||||
$pages = helper::arrayColumn($this->getData(['page']), 'position', 'SORT_ASC');
|
||||
// Parents
|
||||
foreach ($pages as $pageId => $pagePosition) {
|
||||
if (
|
||||
// Page parent
|
||||
$this->getData(['page', $pageId, 'parentPageId']) === ""
|
||||
// Ignore les pages dont l'utilisateur n'a pas accès
|
||||
and ($this->getData(['page', $pageId, 'group']) === self::GROUP_VISITOR
|
||||
or ($this->getUser('password') === $this->getInput('ZWII_USER_PASSWORD')
|
||||
//and $this->getUser('group') >= $this->getData(['page', $pageId, 'group'])
|
||||
// Modification qui tient compte du profil de la page
|
||||
and ($this->getUser('group') * self::MAX_PROFILS + $this->getUser('profil')) >= ($this->getData(['page', $pageId, 'group']) * self::MAX_PROFILS + $this->getData(['page', $pageId, 'profil']))
|
||||
|
||||
)
|
||||
)
|
||||
) {
|
||||
if ($pagePosition !== 0) {
|
||||
$this->hierarchy['visible'][$pageId] = [];
|
||||
}
|
||||
if ($this->getData(['page', $pageId, 'block']) === 'bar') {
|
||||
$this->hierarchy['bar'][$pageId] = [];
|
||||
}
|
||||
$this->hierarchy['all'][$pageId] = [];
|
||||
}
|
||||
}
|
||||
// Enfants
|
||||
foreach ($pages as $pageId => $pagePosition) {
|
||||
|
||||
if (
|
||||
// Page parent
|
||||
$parentId = $this->getData(['page', $pageId, 'parentPageId'])
|
||||
// Ignore les pages dont l'utilisateur n'a pas accès
|
||||
and (
|
||||
(
|
||||
$this->getData(['page', $pageId, 'group']) === self::GROUP_VISITOR
|
||||
and
|
||||
$this->getData(['page', $parentId, 'group']) === self::GROUP_VISITOR
|
||||
)
|
||||
or (
|
||||
$this->getUser('password') === $this->getInput('ZWII_USER_PASSWORD')
|
||||
and
|
||||
$this->getUser('group') * self::MAX_PROFILS + $this->getUser('profil')) >= ($this->getData(['page', $pageId, 'group']) * self::MAX_PROFILS + $this->getData(['page', $pageId, 'profil'])
|
||||
|
||||
)
|
||||
)
|
||||
) {
|
||||
if ($pagePosition !== 0) {
|
||||
$this->hierarchy['visible'][$parentId][] = $pageId;
|
||||
}
|
||||
if ($this->getData(['page', $pageId, 'block']) === 'bar') {
|
||||
$this->hierarchy['bar'][$pageId] = [];
|
||||
}
|
||||
$this->hierarchy['all'][$parentId][] = $pageId;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Génère un fichier json avec la liste des pages
|
||||
|
@ -1068,8 +1119,9 @@ class common
|
|||
}
|
||||
// Articles du blog
|
||||
if (
|
||||
$this->getData(['page', $parentPageId, 'moduleId']) === 'blog' &&
|
||||
!empty($this->getData(['module', $parentPageId]))
|
||||
$this->getData(['page', $parentPageId, 'moduleId']) === 'blog'
|
||||
&& !empty($this->getData(['module', $parentPageId]))
|
||||
&& $this->getData(['module', $parentPageId, 'posts'])
|
||||
) {
|
||||
foreach ($this->getData(['module', $parentPageId, 'posts']) as $articleId => $article) {
|
||||
if ($this->getData(['module', $parentPageId, 'posts', $articleId, 'state']) === true) {
|
||||
|
@ -1121,7 +1173,7 @@ class common
|
|||
}
|
||||
$sitemap->updateRobots();
|
||||
} else {
|
||||
file_put_contents('robots.txt', 'User-agent: *' . PHP_EOL . 'Disallow: /');
|
||||
$this->secure_file_put_contents('robots.txt', 'User-agent: *' . PHP_EOL . 'Disallow: /');
|
||||
}
|
||||
|
||||
// Submit your sitemaps to Google, Yahoo, Bing and Ask.com
|
||||
|
@ -1398,7 +1450,7 @@ class common
|
|||
$dataLog .= $message ? $this->getUrl() . ';' . $message : $this->getUrl();
|
||||
$dataLog .= PHP_EOL;
|
||||
if ($this->getData(['config', 'connect', 'log'])) {
|
||||
file_put_contents(self::DATA_DIR . 'journal.log', $dataLog, FILE_APPEND);
|
||||
$this->secure_file_put_contents(self::DATA_DIR . 'journal.log', $dataLog, FILE_APPEND);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -135,7 +135,7 @@ if ($this->getData(['core', 'dataVersion']) < 10200) {
|
|||
}
|
||||
// Créer les en-têtes du journal
|
||||
$d = 'Date;Heure;IP;Id;Action' . PHP_EOL;
|
||||
file_put_contents(self::DATA_DIR . 'journal.log', $d);
|
||||
$this->secure_file_put_contents(self::DATA_DIR . 'journal.log', $d);
|
||||
// Init préservation htaccess
|
||||
$this->setData(['config', 'autoUpdateHtaccess', false]);
|
||||
// Options de barre de membre simple
|
||||
|
@ -459,7 +459,7 @@ if ($this->getData(['core', 'dataVersion']) < 11000) {
|
|||
}
|
||||
foreach ($hierarchy as $parentKey => $parent) {
|
||||
$content = $this->getData(['page', $parent, 'content']);
|
||||
//file_put_contents(self::DATA_DIR . self::$siteContent . '/content/' . $parent . '.html', $content);
|
||||
//$this->secure_file_put_contents(self::DATA_DIR . self::$siteContent . '/content/' . $parent . '.html', $content);
|
||||
$this->setPage($parent, $content, 'fr');
|
||||
$this->setData(['page', $parent, 'content', $parent . '.html']);
|
||||
}
|
||||
|
@ -982,7 +982,7 @@ if ($this->getData(['core', 'dataVersion']) < 12309) {
|
|||
$d = json_decode(file_get_contents(self::DATA_DIR . $key . '/locale.json'), true);
|
||||
$d = array_merge($d['locale'], ['poweredPageLabel' => 'Motorisé par']);
|
||||
$t['locale'] = $d;
|
||||
file_put_contents(self::DATA_DIR . $key . '/locale.json', json_encode($t));
|
||||
$this->secure_file_put_contents(self::DATA_DIR . $key . '/locale.json', $t);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -534,7 +534,7 @@ class config extends common
|
|||
'</IfModule>' . PHP_EOL .
|
||||
'# URL rewriting' . PHP_EOL;
|
||||
$fileContent = str_replace('# URL rewriting', $rewriteData, $fileContent);
|
||||
file_put_contents(
|
||||
$this->secure_file_put_contents(
|
||||
'.htaccess',
|
||||
$fileContent
|
||||
);
|
||||
|
@ -550,7 +550,7 @@ class config extends common
|
|||
$fileContent = file_get_contents('.htaccess');
|
||||
$fileContent = explode('# URL rewriting', $fileContent);
|
||||
$fileContent = $fileContent[0] . '# URL rewriting' . $fileContent[2];
|
||||
file_put_contents(
|
||||
$this->secure_file_put_contents(
|
||||
'.htaccess',
|
||||
$fileContent
|
||||
);
|
||||
|
@ -654,10 +654,10 @@ class config extends common
|
|||
) {
|
||||
// Ecrire les fichiers de script
|
||||
if ($this->geturl(2) === 'head') {
|
||||
file_put_contents(self::DATA_DIR . 'head.inc.html', $this->getInput('configScriptHead', null));
|
||||
$this->secure_file_put_contents(self::DATA_DIR . 'head.inc.html', $this->getInput('configScriptHead', null));
|
||||
}
|
||||
if ($this->geturl(2) === 'body') {
|
||||
file_put_contents(self::DATA_DIR . 'body.inc.html', $this->getInput('configScriptBody', null));
|
||||
$this->secure_file_put_contents(self::DATA_DIR . 'body.inc.html', $this->getInput('configScriptBody', null));
|
||||
}
|
||||
// Valeurs en sortie
|
||||
$this->addOutput([
|
||||
|
@ -699,7 +699,7 @@ class config extends common
|
|||
unlink(self::DATA_DIR . 'journal.log');
|
||||
// Créer les en-têtes des journaux
|
||||
$d = 'Date;Heure;IP;Id;Action' . PHP_EOL;
|
||||
file_put_contents(self::DATA_DIR . 'journal.log', $d);
|
||||
$this->secure_file_put_contents(self::DATA_DIR . 'journal.log', $d);
|
||||
// Valeurs en sortie
|
||||
$this->addOutput([
|
||||
'title' => helper::translate('Configuration'),
|
||||
|
@ -775,7 +775,7 @@ class config extends common
|
|||
ob_start();
|
||||
$fileName = self::TEMP_DIR . 'blacklist.log';
|
||||
$d = 'Date dernière tentative;Heure dernière tentative;Id;Adresse IP;Nombre d\'échecs' . PHP_EOL;
|
||||
file_put_contents($fileName, $d);
|
||||
$this->secure_file_put_contents($fileName, $d);
|
||||
if (file_exists($fileName)) {
|
||||
$d = $this->getData(['blacklist']);
|
||||
$data = '';
|
||||
|
@ -783,7 +783,7 @@ class config extends common
|
|||
$data .= helper::dateUTF8('%Y %m %d', $item['lastFail'], self::$i18nUI) . ' - ' . helper::dateUTF8('%H:%M', time(), self::$i18nUI);
|
||||
$data .= $key . ';' . $item['ip'] . ';' . $item['connectFail'] . PHP_EOL;
|
||||
}
|
||||
file_put_contents($fileName, $data, FILE_APPEND);
|
||||
$this->secure_file_put_contents($fileName, $data, FILE_APPEND);
|
||||
header('Content-Description: File Transfer');
|
||||
header('Content-Type: application/octet-stream');
|
||||
header('Content-Transfer-Encoding: binary');
|
||||
|
|
|
@ -0,0 +1,4 @@
|
|||
<Files "data.key">
|
||||
Order Allow,Deny
|
||||
Deny from all
|
||||
</Files>
|
|
@ -0,0 +1,47 @@
|
|||
<?php
|
||||
|
||||
/*
|
||||
Ce script PHP est conçu pour être appelé via une requête HTTP GET avec une clé spécifique pour déclencher la création d'une archive ZIP de sauvegarde.
|
||||
|
||||
Exemple d'appel dans une URL :
|
||||
http://example.com/chemin/vers/autobackup.php?key=your_secret_key
|
||||
|
||||
La clé doit être fournie en tant que paramètre "key" dans l'URL et correspondre à celle stockée dans le fichier "data.key" pour que la création de l'archive soit autorisée. Si la clé est valide, le script parcourt le répertoire spécifié et ajoute les fichiers à l'archive ZIP. Si la clé est invalide ou absente, le script affiche un message d'erreur et termine son exécution.
|
||||
|
||||
*/
|
||||
|
||||
// Vérification de la clé
|
||||
if (isset ($_GET['key'])) {
|
||||
$key = $_GET['key'];
|
||||
$storedKey = file_get_contents('data.key');
|
||||
if ($key !== $storedKey) {
|
||||
http_response_code(401);
|
||||
exit();
|
||||
}
|
||||
// Création du ZIP
|
||||
$filter = ['backup', 'tmp'];
|
||||
$fileName = date('Y-m-d-H-i-s', time()) . '-rolling-backup.zip';
|
||||
$zip = new ZipArchive();
|
||||
$zip->open('../../../../site/backup/' . $fileName, ZipArchive::CREATE | ZipArchive::OVERWRITE);
|
||||
$directory = '../../../../site';
|
||||
$files = new RecursiveIteratorIterator(
|
||||
new RecursiveCallbackFilterIterator(
|
||||
new RecursiveDirectoryIterator(
|
||||
$directory,
|
||||
RecursiveDirectoryIterator::SKIP_DOTS
|
||||
),
|
||||
function ($fileInfo, $key, $iterator) use ($filter) {
|
||||
return $fileInfo->isFile() || !in_array($fileInfo->getBaseName(), $filter);
|
||||
}
|
||||
)
|
||||
);
|
||||
foreach ($files as $name => $file) {
|
||||
if (!$file->isDir()) {
|
||||
$filePath = $file->getRealPath();
|
||||
$relativePath = substr($filePath, strlen(realpath($directory)) + 1);
|
||||
$zip->addFile($filePath, $relativePath);
|
||||
}
|
||||
}
|
||||
$zip->close();
|
||||
http_response_code(201);
|
||||
}
|
|
@ -0,0 +1,49 @@
|
|||
<?php
|
||||
|
||||
/*
|
||||
Ce script PHP est conçu pour supprimer les fichiers ayant l'extension 'tar.gz' dans un répertoire de sauvegarde si leur dernière modification remonte à un certain nombre de jours spécifié via une requête HTTP GET.
|
||||
|
||||
Exemple d'appel dans une URL avec le nombre de jours spécifié :
|
||||
http://example.com/chemin/vers/script.php?days=7&key=your_secret_key
|
||||
|
||||
Le script vérifie également la présence et la validité d'une clé spécifique pour déclencher son exécution. La clé doit être fournie en tant que paramètre "key" dans l'URL et correspondre à celle stockée dans le fichier "data.key" pour que la suppression des fichiers soit autorisée. Si la clé est invalide ou absente, le script affiche un message d'erreur et termine son exécution.
|
||||
|
||||
*/
|
||||
|
||||
// Vérification de la clé
|
||||
if (isset ($_GET['key'])) {
|
||||
// Récupération de la clé fournie en GET
|
||||
$key = $_GET['key'];
|
||||
|
||||
// Récupération de la clé stockée dans le fichier data.key
|
||||
$storedKey = file_get_contents('data.key');
|
||||
|
||||
// Vérification de correspondance entre les clés
|
||||
if ($key !== $storedKey) {
|
||||
http_response_code(401);
|
||||
exit();
|
||||
}
|
||||
|
||||
// Récupère le nombre de jours à partir de la variable GET 'days'
|
||||
$days = isset ($_GET['days']) ? (int) $_GET['days'] : 1; // Par défaut à 1 si non spécifié
|
||||
|
||||
// Chemin vers le répertoire contenant les fichiers
|
||||
$directory = '../../../../site/backup/'; // Remplacez par le chemin réel
|
||||
|
||||
// Convertit le nombre de jours en secondes
|
||||
$timeLimit = strtotime("-$days days");
|
||||
|
||||
// Crée un nouvel objet DirectoryIterator
|
||||
foreach (new DirectoryIterator($directory) as $file) {
|
||||
// Vérifie si l'élément courant est un fichier et a l'extension 'tar.gz'
|
||||
if ($file->isFile() && $file->getExtension() === 'tar.gz') {
|
||||
// Vérifie si le fichier a été modifié avant la limite de temps
|
||||
if ($file->getMTime() < $timeLimit) {
|
||||
// Supprime le fichier
|
||||
unlink($file->getRealPath());
|
||||
}
|
||||
}
|
||||
}
|
||||
// Si la clé est manquante, affiche un message d'erreur et arrête l'exécution du script
|
||||
http_response_code(201);
|
||||
}
|
|
@ -7,7 +7,7 @@
|
|||
'value' => template::ico('left')
|
||||
]); ?>
|
||||
</div>
|
||||
<div class="col2 offset8">
|
||||
<div class="col2 offset9">
|
||||
<?php echo template::submit('configManageSubmit', [
|
||||
'value' => 'Valider',
|
||||
'ico' => 'check'
|
||||
|
|
|
@ -292,7 +292,7 @@ class install extends common
|
|||
case 2:
|
||||
$success = true;
|
||||
$message = '';
|
||||
file_put_contents(self::TEMP_DIR . 'update.tar.gz', helper::getUrlContents(common::ZWII_UPDATE_URL . common::ZWII_UPDATE_CHANNEL . '/update.tar.gz'));
|
||||
$this->secure_file_put_contents(self::TEMP_DIR . 'update.tar.gz', helper::getUrlContents(common::ZWII_UPDATE_URL . common::ZWII_UPDATE_CHANNEL . '/update.tar.gz'));
|
||||
$md5origin = helper::getUrlContents(common::ZWII_UPDATE_URL . common::ZWII_UPDATE_CHANNEL . '/update.md5');
|
||||
$md5origin = explode(' ', $md5origin);
|
||||
$md5target = md5_file(self::TEMP_DIR . 'update.tar.gz');
|
||||
|
@ -401,7 +401,7 @@ class install extends common
|
|||
'</IfModule>' . PHP_EOL .
|
||||
'# URL rewriting' . PHP_EOL;
|
||||
$fileContent = str_replace('# URL rewriting', $rewriteData, $fileContent);
|
||||
$success = file_put_contents(
|
||||
$success = $this->secure_file_put_contents(
|
||||
'.htaccess',
|
||||
$fileContent
|
||||
);
|
||||
|
|
|
@ -99,7 +99,7 @@ class language extends common
|
|||
is_array($descripteur['language'][$lang])
|
||||
) {
|
||||
if ($this->setData(['language', $lang, $descripteur['language'][$lang]])) {
|
||||
$success = file_put_contents(self::I18N_DIR . $lang . '.json', json_encode($languageData, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES | JSON_PRETTY_PRINT));
|
||||
$success = $this->secure_file_put_contents(self::I18N_DIR . $lang . '.json', $languageData);
|
||||
$success = is_int($success) ? true : false;
|
||||
}
|
||||
}
|
||||
|
@ -430,7 +430,7 @@ class language extends common
|
|||
$this->setData(['locale', $data['locale']]);
|
||||
} else {
|
||||
// Sauver sur le disque
|
||||
file_put_contents(self::DATA_DIR . $lang . '/locale.json', json_encode($data, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES | JSON_PRETTY_PRINT), LOCK_EX);
|
||||
$this->secure_file_put_contents(self::DATA_DIR . $lang . '/locale.json', $data);
|
||||
}
|
||||
|
||||
// Valeurs en sortie
|
||||
|
@ -512,7 +512,7 @@ class language extends common
|
|||
$data[$key] = $target;
|
||||
}
|
||||
}
|
||||
file_put_contents(self::I18N_DIR . $lang . '.json', json_encode($data, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES | JSON_PRETTY_PRINT), LOCK_EX);
|
||||
$this->secure_file_put_contents(self::I18N_DIR . $lang . '.json', $data);
|
||||
|
||||
// Mettre à jour le descripteur
|
||||
$this->setData([
|
||||
|
@ -546,7 +546,7 @@ class language extends common
|
|||
$data[$key] = '';
|
||||
}
|
||||
}
|
||||
file_put_contents(self::I18N_DIR . $lang . '.json', json_encode($data, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES | JSON_PRETTY_PRINT), LOCK_EX);
|
||||
$this->secure_file_put_contents(self::I18N_DIR . $lang . '.json', $data);
|
||||
|
||||
// Tableau des chaines à traduire dans la langue sélectionnée
|
||||
foreach ($data as $key => $value) {
|
||||
|
|
|
@ -177,7 +177,7 @@ class page extends common
|
|||
if (!is_dir(self::DATA_DIR . self::$siteContent . '/content')) {
|
||||
mkdir(self::DATA_DIR . self::$siteContent . '/content', 0755);
|
||||
}
|
||||
//file_put_contents(self::DATA_DIR . self::$siteContent . '/content/' . $pageId . '.html', '<p>Contenu de votre nouvelle page.</p>');
|
||||
//$this->secure_file_put_contents(self::DATA_DIR . self::$siteContent . '/content/' . $pageId . '.html', '<p>Contenu de votre nouvelle page.</p>');
|
||||
$this->setPage($pageId, '<p>Contenu de votre nouvelle page.</p>', self::$siteContent);
|
||||
|
||||
// Met à jour le sitemap
|
||||
|
|
|
@ -314,7 +314,7 @@ class plugin extends common
|
|||
mkdir(self::FILE_DIR . 'source/modules', 0755);
|
||||
}
|
||||
// Sauver les données du fichiers
|
||||
file_put_contents(self::FILE_DIR . 'source/modules/' . $moduleFile, $moduleData);
|
||||
$this->secure_file_put_contents(self::FILE_DIR . 'source/modules/' . $moduleFile, $moduleData);
|
||||
|
||||
// Installation directe
|
||||
if (file_exists(self::FILE_DIR . 'source/modules/' . $moduleFile)) {
|
||||
|
@ -592,7 +592,7 @@ class plugin extends common
|
|||
$fileName = $moduleId . str_replace('.', '-', $infoModule[$moduleId]['version']) . '.zip';
|
||||
|
||||
// Régénération du descripteur du module
|
||||
file_put_contents(self::MODULE_DIR . $moduleId . '/enum.json', json_encode($infoModule[$moduleId], JSON_UNESCAPED_UNICODE));
|
||||
$this->secure_file_put_contents(self::MODULE_DIR . $moduleId . '/enum.json', $infoModule[$moduleId]);
|
||||
|
||||
// Construire l'archive
|
||||
$this->makeZip($tmpFolder . $fileName, self::MODULE_DIR . $moduleId);
|
||||
|
|
|
@ -304,7 +304,7 @@ class theme extends common
|
|||
$this->isPost()
|
||||
) {
|
||||
// Enregistre le CSS
|
||||
file_put_contents(self::DATA_DIR . 'custom.css', $this->getInput('themeAdvancedCss', null));
|
||||
$this->secure_file_put_contents(self::DATA_DIR . 'custom.css', $this->getInput('themeAdvancedCss', null));
|
||||
// Valeurs en sortie
|
||||
$this->addOutput([
|
||||
'notification' => helper::translate('Modifications enregistrées'),
|
||||
|
@ -1290,7 +1290,7 @@ class theme extends common
|
|||
}
|
||||
// Sauvegarder la chaîne modifiée
|
||||
if ($count > 0) {
|
||||
file_put_contents($file, $data);
|
||||
$this->secure_file_put_contents($file, $data);
|
||||
}
|
||||
// Retourner le nombre d'occurrences
|
||||
return ($count);
|
||||
|
@ -1396,8 +1396,8 @@ class theme extends common
|
|||
}
|
||||
|
||||
// Enregistre la personnalisation
|
||||
file_put_contents(self::DATA_DIR . 'font/font.html', $fileContent);
|
||||
$this->secure_file_put_contents(self::DATA_DIR . 'font/font.html', $fileContent);
|
||||
// Enregistre la personnalisation
|
||||
file_put_contents(self::DATA_DIR . 'font/font.css', $fileContentCss);
|
||||
$this->secure_file_put_contents(self::DATA_DIR . 'font/font.css', $fileContentCss);
|
||||
}
|
||||
}
|
|
@ -19,6 +19,7 @@ $('#dataTables').DataTable({
|
|||
url: "core/vendor/datatables/french.json",
|
||||
},
|
||||
locale: 'fr',
|
||||
stateSave: true,
|
||||
"columnDefs": [{
|
||||
target: 5,
|
||||
orderable: false,
|
||||
|
|
|
@ -739,9 +739,9 @@ class user extends common
|
|||
}
|
||||
|
||||
// Chemin vers les dossiers du gestionnaire de fichier
|
||||
self::$sharePath = $this->getSubdirectories('./site/file/source');
|
||||
self::$sharePath = $this->getSubdirectories('site/file/source');
|
||||
self::$sharePath = array_flip(self::$sharePath);
|
||||
self::$sharePath = array_merge(['./site/file/source/' => 'Tous les dossiers'], self::$sharePath);
|
||||
self::$sharePath = array_merge(['site/file/source/' => 'Tous les dossiers'], self::$sharePath);
|
||||
self::$sharePath = array_merge([null => 'Aucun dossier'], self::$sharePath);
|
||||
|
||||
// Liste des modules installés
|
||||
|
@ -896,9 +896,9 @@ class user extends common
|
|||
}
|
||||
|
||||
// Chemin vers les dossiers du gestionnaire de fichier
|
||||
self::$sharePath = $this->getSubdirectories('./site/file/source');
|
||||
self::$sharePath = $this->getSubdirectories('site/file/source');
|
||||
self::$sharePath = array_flip(self::$sharePath);
|
||||
self::$sharePath = array_merge(['./site/file/source/' => 'Tous les dossiers'], self::$sharePath);
|
||||
self::$sharePath = array_merge(['site/file/source/' => 'Tous les dossiers'], self::$sharePath);
|
||||
self::$sharePath = array_merge([null => 'Aucun dossier'], self::$sharePath);
|
||||
|
||||
// Liste des modules installés
|
||||
|
|
|
@ -28,6 +28,7 @@ $(document).ready((function () {
|
|||
url: "core/vendor/datatables/french.json",
|
||||
},
|
||||
locale: 'fr',
|
||||
stateSave: true,
|
||||
"columnDefs": [
|
||||
{
|
||||
target: 5,
|
||||
|
|
|
@ -16,7 +16,7 @@
|
|||
class blog extends common
|
||||
{
|
||||
|
||||
const VERSION = '7.5';
|
||||
const VERSION = '7.6';
|
||||
const REALNAME = 'Blog';
|
||||
const DELETE = true;
|
||||
const UPDATE = '0.0';
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
# Version 7.6
|
||||
- Mise à jour RSS Feed
|
||||
# Version 7.5
|
||||
- Bug paramètre de localisation erroné
|
||||
# Version 7.4
|
||||
|
|
|
@ -0,0 +1,74 @@
|
|||
# Change Log
|
||||
All notable changes to this project will be documented in this file.
|
||||
|
||||
The format is based on [Keep a Changelog](http://keepachangelog.com/) .
|
||||
|
||||
## [v1.1.2] - 2023-05-25
|
||||
### Changed
|
||||
- Throw an exception if required feed elements are set with ```NULL``` value. See issue #46.
|
||||
|
||||
## [v1.1.1] - 2016-11-19
|
||||
### Changed
|
||||
- Improved the documentation.
|
||||
- Changed to PSR-4 autoloader in composer.json.
|
||||
|
||||
### Fixed
|
||||
- Item::addElement did not method chain in error conditions.
|
||||
|
||||
## [v1.1.0] - 2016-11-08
|
||||
### Added
|
||||
- Support for multiple element values.
|
||||
- Support for a feed description in ATOM feeds.
|
||||
- Support for ATOM feeds without ```link``` elements.
|
||||
- Support for a feed image in RSS 1.0 and ATOM feeds.
|
||||
|
||||
### Changed
|
||||
- The script does now throw Exceptions instead of stopping the PHP interpreter on error conditions.
|
||||
- The unique identifier for ATOM feeds / entries use the feed / entry title for generating the ID (previously the feed / entry link).
|
||||
- Some URI schemes for ```Item::setId``` were wrongly allowed.
|
||||
- The parameter order of the ```Feed::setImage``` method was changed.
|
||||
|
||||
### Fixed
|
||||
- Fixed slow generation of the feed with huge amounts of feed entries (like 40k entries).
|
||||
- Fixed PHP warning when ```Feed::setChannelAbout``` for RSS 1.0 feeds was not called.
|
||||
- A feed element was generated twice if the element content & attribute value was ```NULL```.
|
||||
- The detection of twice the same link with ```rel=alternate```, ```hreflang``` & ```type``` did not work.
|
||||
|
||||
### Removed
|
||||
- The deprecated method ```Item::setEnclosure``` was removed. Use ```Item::addEnclosure``` instead.
|
||||
|
||||
## [v1.0.4] - 2016-04-17
|
||||
### Changed
|
||||
- The unique identifier for ATOM feed entries is now compliant to the ATOM standard.
|
||||
|
||||
### Fixed
|
||||
- Filter more invalid XML chars.
|
||||
- Fixed a PHP warning displayed if ```Feed::setTitle``` or ```Feed::setLink``` was not called.
|
||||
|
||||
## [v1.0.3] - 2015-11-11
|
||||
### Added
|
||||
- Method for removing tags which were CDATA encoded.
|
||||
|
||||
### Fixed
|
||||
- Fixed error when the filtering of invalid XML chars failed.
|
||||
- Fixed missing docblock documentation.
|
||||
|
||||
## [v1.0.2] - 2015-01-23
|
||||
### Fixed
|
||||
- Fixed a wrong docblock return data type.
|
||||
|
||||
## [v1.0.1] - 2014-09-21
|
||||
### Fixed
|
||||
- Filter invalid XML chars.
|
||||
|
||||
## v1.0 - 2014-09-14
|
||||
|
||||
|
||||
[Unreleased]: https://github.com/mibe/FeedWriter/compare/v1.1.2...HEAD
|
||||
[v1.1.2]: https://github.com/mibe/FeedWriter/compare/v1.1.1...v1.1.2
|
||||
[v1.1.1]: https://github.com/mibe/FeedWriter/compare/v1.1.0...v1.1.1
|
||||
[v1.1.0]: https://github.com/mibe/FeedWriter/compare/v1.0.4...v1.1.0
|
||||
[v1.0.4]: https://github.com/mibe/FeedWriter/compare/v1.0.3...v1.0.4
|
||||
[v1.0.3]: https://github.com/mibe/FeedWriter/compare/v1.0.2...v1.0.3
|
||||
[v1.0.2]: https://github.com/mibe/FeedWriter/compare/v1.0.1...v1.0.2
|
||||
[v1.0.1]: https://github.com/mibe/FeedWriter/compare/v1.0...v1.0.1
|
|
@ -2,10 +2,11 @@
|
|||
namespace FeedWriter;
|
||||
|
||||
use \DateTime;
|
||||
use \DateTimeInterface;
|
||||
|
||||
/*
|
||||
* Copyright (C) 2008 Anis uddin Ahmad <anisniit@gmail.com>
|
||||
* Copyright (C) 2010-2016 Michael Bemmerl <mail@mx-server.de>
|
||||
* Copyright (C) 2010-2016, 2022 Michael Bemmerl <mail@mx-server.de>
|
||||
*
|
||||
* This file is part of the "Universal Feed Writer" project.
|
||||
*
|
||||
|
@ -76,6 +77,13 @@ abstract class Feed
|
|||
*/
|
||||
private $version = null;
|
||||
|
||||
/**
|
||||
* Contains the encoding of this feed.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
private $encoding = 'utf-8';
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
|
@ -87,9 +95,6 @@ abstract class Feed
|
|||
{
|
||||
$this->version = $version;
|
||||
|
||||
// Setting default encoding
|
||||
$this->encoding = 'utf-8';
|
||||
|
||||
// Setting default value for essential channel element
|
||||
$this->setTitle($version . ' Feed');
|
||||
|
||||
|
@ -396,9 +401,13 @@ abstract class Feed
|
|||
* @access public
|
||||
* @param string $title value of 'title' channel tag
|
||||
* @return self
|
||||
* @throws \InvalidArgumentException if the title is empty or NULL.
|
||||
*/
|
||||
public function setTitle($title)
|
||||
{
|
||||
if (empty($title))
|
||||
throw new \InvalidArgumentException('The title may not be empty or NULL.');
|
||||
|
||||
return $this->setChannelElement('title', $title);
|
||||
}
|
||||
|
||||
|
@ -406,15 +415,15 @@ abstract class Feed
|
|||
* Set the date when the feed was lastly updated.
|
||||
*
|
||||
* This adds the 'updated' element to the feed. The value of the date parameter
|
||||
* can be either an instance of the DateTime class, an integer containing a UNIX
|
||||
* can be either a class implementing DateTimeInterface, an integer containing a UNIX
|
||||
* timestamp or a string which is parseable by PHP's 'strtotime' function.
|
||||
*
|
||||
* Not supported in RSS1 feeds.
|
||||
*
|
||||
* @access public
|
||||
* @param DateTime|int|string Date which should be used.
|
||||
* @param DateTimeInterface|int|string Date which should be used.
|
||||
* @return self
|
||||
* @throws \InvalidArgumentException if the given date is not an instance of DateTime, a UNIX timestamp or a date string.
|
||||
* @throws \InvalidArgumentException if the given date is not an implementation of DateTimeInterface, a UNIX timestamp or a date string.
|
||||
* @throws InvalidOperationException if this method is called on an RSS1 feed.
|
||||
*/
|
||||
public function setDate($date)
|
||||
|
@ -425,7 +434,7 @@ abstract class Feed
|
|||
// The feeds have different date formats.
|
||||
$format = $this->version == Feed::ATOM ? \DATE_ATOM : \DATE_RSS;
|
||||
|
||||
if ($date instanceof DateTime)
|
||||
if ($date instanceof DateTimeInterface || $date instanceof DateTime)
|
||||
$date = $date->format($format);
|
||||
else if(is_numeric($date) && $date >= 0)
|
||||
$date = date($format, $date);
|
||||
|
@ -438,7 +447,7 @@ abstract class Feed
|
|||
$date = date($format, $timestamp);
|
||||
}
|
||||
else
|
||||
throw new \InvalidArgumentException('The given date is not an instance of DateTime, a UNIX timestamp or a date string.');
|
||||
throw new \InvalidArgumentException('The given date is not an implementation of DateTimeInterface, a UNIX timestamp or a date string.');
|
||||
|
||||
if ($this->version == Feed::ATOM)
|
||||
$this->setChannelElement('updated', $date);
|
||||
|
@ -454,9 +463,13 @@ abstract class Feed
|
|||
* @access public
|
||||
* @param string $description Description of the feed.
|
||||
* @return self
|
||||
* @throws \InvalidArgumentException if the description is empty or NULL.
|
||||
*/
|
||||
public function setDescription($description)
|
||||
{
|
||||
if (empty($description))
|
||||
throw new \InvalidArgumentException('The description may not be empty or NULL.');
|
||||
|
||||
if ($this->version != Feed::ATOM)
|
||||
$this->setChannelElement('description', $description);
|
||||
else
|
||||
|
@ -471,9 +484,13 @@ abstract class Feed
|
|||
* @access public
|
||||
* @param string $link value of 'link' channel tag
|
||||
* @return self
|
||||
* @throws \InvalidArgumentException if the link is empty or NULL.
|
||||
*/
|
||||
public function setLink($link)
|
||||
{
|
||||
if (empty($link))
|
||||
throw new \InvalidArgumentException('The link may not be empty or NULL.');
|
||||
|
||||
if ($this->version == Feed::ATOM)
|
||||
$this->setAtomLink($link);
|
||||
else
|
||||
|
@ -667,7 +684,7 @@ abstract class Feed
|
|||
/**
|
||||
* Replace invalid XML characters.
|
||||
*
|
||||
* @link http://www.phpwact.org/php/i18n/charsets#xml See utf8_for_xml() function
|
||||
* @link https://web.archive.org/web/20160608013721/http://www.phpwact.org:80/php/i18n/charsets#xml See utf8_for_xml() function
|
||||
* @link http://www.w3.org/TR/REC-xml/#charsets
|
||||
* @link https://github.com/mibe/FeedWriter/issues/30
|
||||
*
|
||||
|
@ -906,7 +923,7 @@ abstract class Feed
|
|||
$out .= "</rdf:Seq>" . PHP_EOL . "</items>" . PHP_EOL . "</channel>" . PHP_EOL;
|
||||
|
||||
// An image has its own element after the channel elements.
|
||||
if (array_key_exists('image', $this->data))
|
||||
if (array_key_exists('Image', $this->data))
|
||||
$out .= $this->makeNode('image', $this->data['Image'], array('rdf:about' => $this->data['Image']['url']));
|
||||
} else if ($this->version == Feed::ATOM) {
|
||||
// ATOM feeds have a unique feed ID. Use the title channel element as key.
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
namespace FeedWriter;
|
||||
|
||||
use \DateTime;
|
||||
use \DateTimeInterface;
|
||||
|
||||
/*
|
||||
* Copyright (C) 2008 Anis uddin Ahmad <anisniit@gmail.com>
|
||||
|
@ -217,19 +218,19 @@ class Item
|
|||
/**
|
||||
* 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
|
||||
* The value of the date parameter can be either a class implementing
|
||||
* DateTimeInterface, 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.
|
||||
* @param DateTimeInterface|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)
|
||||
if ($date instanceof DateTimeInterface || $date instanceof DateTime)
|
||||
$date = $date->getTimestamp();
|
||||
else {
|
||||
$date = strtotime($date);
|
||||
|
@ -277,7 +278,7 @@ class Item
|
|||
* Attach a external media to the feed item.
|
||||
* Not supported in RSS 1.0 feeds.
|
||||
*
|
||||
* See RFC 4288 for syntactical correct MIME types.
|
||||
* See RFC 6838 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.
|
||||
|
@ -288,7 +289,8 @@ class Item
|
|||
* @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
|
||||
* @link https://tools.ietf.org/html/rfc6838
|
||||
* @link http://www.iana.org/assignments/media-types/media-types.xhtml
|
||||
* @throws \InvalidArgumentException if the length or type parameter is invalid.
|
||||
* @throws InvalidOperationException if this method is called on RSS1 feeds.
|
||||
*/
|
||||
|
@ -389,7 +391,7 @@ class Item
|
|||
// 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');
|
||||
$validSchemes = array('aaa', 'aaas', 'about', 'acap', 'acct', 'bb', 'cap', 'cid', 'coap', 'coap+tcp', 'coap+ws', 'coaps', 'coaps+tcp', 'coaps+ws', 'crid', 'data', 'dav', 'dict', 'dns', 'drop', 'dtn', 'example', 'fax', 'file', 'filesystem', 'ftp', 'geo', 'go', 'gopher', 'grd', 'h323', 'http', 'https', 'iax', 'icap', 'im', 'imap', 'info', 'ipn', 'ipp', 'ipps', 'iris', 'iris.beep', 'iris.lwz', 'iris.xpc', 'iris.xpcs', 'jabber', 'ldap', 'leaptofrogans', 'mailserver', 'mailto', 'mid', 'modem', 'msrp', 'msrps', 'mt', 'mtqp', 'mupdate', 'news', 'nfs', 'ni', 'nih', 'nntp', 'opaquelocktoken', 'p1', 'pack', 'pkcs11', 'pop', 'pres', 'prospero', 'reload', 'rtsp', 'rtsps', 'rtspu', 'service', 'session', 'shttp (OBSOLETE)', 'sieve', 'sip', 'sips', 'sms', 'snews', 'snmp', 'soap.beep', 'soap.beeps', 'stun', 'stuns', 'tag', 'tel', 'telnet', 'tftp', 'thismessage', 'tip', 'tn3270', 'turn', 'turns', 'tv', 'upt', 'urn', 'vemmi', 'videotex', 'vnc', 'wais', 'wpid', 'ws', 'wss', 'xcon', 'xcon-userid', 'xmlrpc.beep', 'xmlrpc.beeps', 'xmpp', 'z39.50', 'z39.50r', 'z39.50s');
|
||||
$found = FALSE;
|
||||
$checkId = strtolower($id);
|
||||
|
||||
|
|
|
@ -12,6 +12,11 @@ Once a feed is fully composed with its items, the feed class can generate the ne
|
|||
|
||||
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.
|
||||
|
||||
## Installation
|
||||
You can install via [Composer](https://getcomposer.org/).
|
||||
|
||||
composer require mibe/feedwriter
|
||||
|
||||
## Documentation
|
||||
|
||||
The documentation can be found in the `gh-pages` branch, or on [GitHub Pages](https://mibe.github.io/FeedWriter/).
|
||||
|
@ -40,3 +45,6 @@ In chronological order:
|
|||
- Pavel Khakhlou
|
||||
- Daniel
|
||||
- Tino Goratsch
|
||||
- John
|
||||
- Özgür Görgülü
|
||||
- Jan Tojnar
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
# Version 5.5
|
||||
- Mise à jour RSS Feed
|
||||
# Version 5.4
|
||||
- Bug paramètre de localisation erroné
|
||||
# Version 5.3
|
||||
|
|
|
@ -16,7 +16,7 @@
|
|||
class news extends common
|
||||
{
|
||||
|
||||
const VERSION = '5.4';
|
||||
const VERSION = '5.5';
|
||||
const REALNAME = 'News';
|
||||
const DATADIRECTORY = self::DATA_DIR . 'news/';
|
||||
|
||||
|
|
|
@ -0,0 +1,74 @@
|
|||
# Change Log
|
||||
All notable changes to this project will be documented in this file.
|
||||
|
||||
The format is based on [Keep a Changelog](http://keepachangelog.com/) .
|
||||
|
||||
## [v1.1.2] - 2023-05-25
|
||||
### Changed
|
||||
- Throw an exception if required feed elements are set with ```NULL``` value. See issue #46.
|
||||
|
||||
## [v1.1.1] - 2016-11-19
|
||||
### Changed
|
||||
- Improved the documentation.
|
||||
- Changed to PSR-4 autoloader in composer.json.
|
||||
|
||||
### Fixed
|
||||
- Item::addElement did not method chain in error conditions.
|
||||
|
||||
## [v1.1.0] - 2016-11-08
|
||||
### Added
|
||||
- Support for multiple element values.
|
||||
- Support for a feed description in ATOM feeds.
|
||||
- Support for ATOM feeds without ```link``` elements.
|
||||
- Support for a feed image in RSS 1.0 and ATOM feeds.
|
||||
|
||||
### Changed
|
||||
- The script does now throw Exceptions instead of stopping the PHP interpreter on error conditions.
|
||||
- The unique identifier for ATOM feeds / entries use the feed / entry title for generating the ID (previously the feed / entry link).
|
||||
- Some URI schemes for ```Item::setId``` were wrongly allowed.
|
||||
- The parameter order of the ```Feed::setImage``` method was changed.
|
||||
|
||||
### Fixed
|
||||
- Fixed slow generation of the feed with huge amounts of feed entries (like 40k entries).
|
||||
- Fixed PHP warning when ```Feed::setChannelAbout``` for RSS 1.0 feeds was not called.
|
||||
- A feed element was generated twice if the element content & attribute value was ```NULL```.
|
||||
- The detection of twice the same link with ```rel=alternate```, ```hreflang``` & ```type``` did not work.
|
||||
|
||||
### Removed
|
||||
- The deprecated method ```Item::setEnclosure``` was removed. Use ```Item::addEnclosure``` instead.
|
||||
|
||||
## [v1.0.4] - 2016-04-17
|
||||
### Changed
|
||||
- The unique identifier for ATOM feed entries is now compliant to the ATOM standard.
|
||||
|
||||
### Fixed
|
||||
- Filter more invalid XML chars.
|
||||
- Fixed a PHP warning displayed if ```Feed::setTitle``` or ```Feed::setLink``` was not called.
|
||||
|
||||
## [v1.0.3] - 2015-11-11
|
||||
### Added
|
||||
- Method for removing tags which were CDATA encoded.
|
||||
|
||||
### Fixed
|
||||
- Fixed error when the filtering of invalid XML chars failed.
|
||||
- Fixed missing docblock documentation.
|
||||
|
||||
## [v1.0.2] - 2015-01-23
|
||||
### Fixed
|
||||
- Fixed a wrong docblock return data type.
|
||||
|
||||
## [v1.0.1] - 2014-09-21
|
||||
### Fixed
|
||||
- Filter invalid XML chars.
|
||||
|
||||
## v1.0 - 2014-09-14
|
||||
|
||||
|
||||
[Unreleased]: https://github.com/mibe/FeedWriter/compare/v1.1.2...HEAD
|
||||
[v1.1.2]: https://github.com/mibe/FeedWriter/compare/v1.1.1...v1.1.2
|
||||
[v1.1.1]: https://github.com/mibe/FeedWriter/compare/v1.1.0...v1.1.1
|
||||
[v1.1.0]: https://github.com/mibe/FeedWriter/compare/v1.0.4...v1.1.0
|
||||
[v1.0.4]: https://github.com/mibe/FeedWriter/compare/v1.0.3...v1.0.4
|
||||
[v1.0.3]: https://github.com/mibe/FeedWriter/compare/v1.0.2...v1.0.3
|
||||
[v1.0.2]: https://github.com/mibe/FeedWriter/compare/v1.0.1...v1.0.2
|
||||
[v1.0.1]: https://github.com/mibe/FeedWriter/compare/v1.0...v1.0.1
|
|
@ -2,10 +2,11 @@
|
|||
namespace FeedWriter;
|
||||
|
||||
use \DateTime;
|
||||
use \DateTimeInterface;
|
||||
|
||||
/*
|
||||
* Copyright (C) 2008 Anis uddin Ahmad <anisniit@gmail.com>
|
||||
* Copyright (C) 2010-2016 Michael Bemmerl <mail@mx-server.de>
|
||||
* Copyright (C) 2010-2016, 2022 Michael Bemmerl <mail@mx-server.de>
|
||||
*
|
||||
* This file is part of the "Universal Feed Writer" project.
|
||||
*
|
||||
|
@ -76,6 +77,13 @@ abstract class Feed
|
|||
*/
|
||||
private $version = null;
|
||||
|
||||
/**
|
||||
* Contains the encoding of this feed.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
private $encoding = 'utf-8';
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
|
@ -87,9 +95,6 @@ abstract class Feed
|
|||
{
|
||||
$this->version = $version;
|
||||
|
||||
// Setting default encoding
|
||||
$this->encoding = 'utf-8';
|
||||
|
||||
// Setting default value for essential channel element
|
||||
$this->setTitle($version . ' Feed');
|
||||
|
||||
|
@ -396,9 +401,13 @@ abstract class Feed
|
|||
* @access public
|
||||
* @param string $title value of 'title' channel tag
|
||||
* @return self
|
||||
* @throws \InvalidArgumentException if the title is empty or NULL.
|
||||
*/
|
||||
public function setTitle($title)
|
||||
{
|
||||
if (empty($title))
|
||||
throw new \InvalidArgumentException('The title may not be empty or NULL.');
|
||||
|
||||
return $this->setChannelElement('title', $title);
|
||||
}
|
||||
|
||||
|
@ -406,15 +415,15 @@ abstract class Feed
|
|||
* Set the date when the feed was lastly updated.
|
||||
*
|
||||
* This adds the 'updated' element to the feed. The value of the date parameter
|
||||
* can be either an instance of the DateTime class, an integer containing a UNIX
|
||||
* can be either a class implementing DateTimeInterface, an integer containing a UNIX
|
||||
* timestamp or a string which is parseable by PHP's 'strtotime' function.
|
||||
*
|
||||
* Not supported in RSS1 feeds.
|
||||
*
|
||||
* @access public
|
||||
* @param DateTime|int|string Date which should be used.
|
||||
* @param DateTimeInterface|int|string Date which should be used.
|
||||
* @return self
|
||||
* @throws \InvalidArgumentException if the given date is not an instance of DateTime, a UNIX timestamp or a date string.
|
||||
* @throws \InvalidArgumentException if the given date is not an implementation of DateTimeInterface, a UNIX timestamp or a date string.
|
||||
* @throws InvalidOperationException if this method is called on an RSS1 feed.
|
||||
*/
|
||||
public function setDate($date)
|
||||
|
@ -425,7 +434,7 @@ abstract class Feed
|
|||
// The feeds have different date formats.
|
||||
$format = $this->version == Feed::ATOM ? \DATE_ATOM : \DATE_RSS;
|
||||
|
||||
if ($date instanceof DateTime)
|
||||
if ($date instanceof DateTimeInterface || $date instanceof DateTime)
|
||||
$date = $date->format($format);
|
||||
else if(is_numeric($date) && $date >= 0)
|
||||
$date = date($format, $date);
|
||||
|
@ -438,7 +447,7 @@ abstract class Feed
|
|||
$date = date($format, $timestamp);
|
||||
}
|
||||
else
|
||||
throw new \InvalidArgumentException('The given date is not an instance of DateTime, a UNIX timestamp or a date string.');
|
||||
throw new \InvalidArgumentException('The given date is not an implementation of DateTimeInterface, a UNIX timestamp or a date string.');
|
||||
|
||||
if ($this->version == Feed::ATOM)
|
||||
$this->setChannelElement('updated', $date);
|
||||
|
@ -454,9 +463,13 @@ abstract class Feed
|
|||
* @access public
|
||||
* @param string $description Description of the feed.
|
||||
* @return self
|
||||
* @throws \InvalidArgumentException if the description is empty or NULL.
|
||||
*/
|
||||
public function setDescription($description)
|
||||
{
|
||||
if (empty($description))
|
||||
throw new \InvalidArgumentException('The description may not be empty or NULL.');
|
||||
|
||||
if ($this->version != Feed::ATOM)
|
||||
$this->setChannelElement('description', $description);
|
||||
else
|
||||
|
@ -471,9 +484,13 @@ abstract class Feed
|
|||
* @access public
|
||||
* @param string $link value of 'link' channel tag
|
||||
* @return self
|
||||
* @throws \InvalidArgumentException if the link is empty or NULL.
|
||||
*/
|
||||
public function setLink($link)
|
||||
{
|
||||
if (empty($link))
|
||||
throw new \InvalidArgumentException('The link may not be empty or NULL.');
|
||||
|
||||
if ($this->version == Feed::ATOM)
|
||||
$this->setAtomLink($link);
|
||||
else
|
||||
|
@ -667,7 +684,7 @@ abstract class Feed
|
|||
/**
|
||||
* Replace invalid XML characters.
|
||||
*
|
||||
* @link http://www.phpwact.org/php/i18n/charsets#xml See utf8_for_xml() function
|
||||
* @link https://web.archive.org/web/20160608013721/http://www.phpwact.org:80/php/i18n/charsets#xml See utf8_for_xml() function
|
||||
* @link http://www.w3.org/TR/REC-xml/#charsets
|
||||
* @link https://github.com/mibe/FeedWriter/issues/30
|
||||
*
|
||||
|
@ -906,7 +923,7 @@ abstract class Feed
|
|||
$out .= "</rdf:Seq>" . PHP_EOL . "</items>" . PHP_EOL . "</channel>" . PHP_EOL;
|
||||
|
||||
// An image has its own element after the channel elements.
|
||||
if (array_key_exists('image', $this->data))
|
||||
if (array_key_exists('Image', $this->data))
|
||||
$out .= $this->makeNode('image', $this->data['Image'], array('rdf:about' => $this->data['Image']['url']));
|
||||
} else if ($this->version == Feed::ATOM) {
|
||||
// ATOM feeds have a unique feed ID. Use the title channel element as key.
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
namespace FeedWriter;
|
||||
|
||||
use \DateTime;
|
||||
use \DateTimeInterface;
|
||||
|
||||
/*
|
||||
* Copyright (C) 2008 Anis uddin Ahmad <anisniit@gmail.com>
|
||||
|
@ -217,19 +218,19 @@ class Item
|
|||
/**
|
||||
* 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
|
||||
* The value of the date parameter can be either a class implementing
|
||||
* DateTimeInterface, 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.
|
||||
* @param DateTimeInterface|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)
|
||||
if ($date instanceof DateTimeInterface || $date instanceof DateTime)
|
||||
$date = $date->getTimestamp();
|
||||
else {
|
||||
$date = strtotime($date);
|
||||
|
@ -277,7 +278,7 @@ class Item
|
|||
* Attach a external media to the feed item.
|
||||
* Not supported in RSS 1.0 feeds.
|
||||
*
|
||||
* See RFC 4288 for syntactical correct MIME types.
|
||||
* See RFC 6838 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.
|
||||
|
@ -288,7 +289,8 @@ class Item
|
|||
* @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
|
||||
* @link https://tools.ietf.org/html/rfc6838
|
||||
* @link http://www.iana.org/assignments/media-types/media-types.xhtml
|
||||
* @throws \InvalidArgumentException if the length or type parameter is invalid.
|
||||
* @throws InvalidOperationException if this method is called on RSS1 feeds.
|
||||
*/
|
||||
|
@ -389,7 +391,7 @@ class Item
|
|||
// 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');
|
||||
$validSchemes = array('aaa', 'aaas', 'about', 'acap', 'acct', 'bb', 'cap', 'cid', 'coap', 'coap+tcp', 'coap+ws', 'coaps', 'coaps+tcp', 'coaps+ws', 'crid', 'data', 'dav', 'dict', 'dns', 'drop', 'dtn', 'example', 'fax', 'file', 'filesystem', 'ftp', 'geo', 'go', 'gopher', 'grd', 'h323', 'http', 'https', 'iax', 'icap', 'im', 'imap', 'info', 'ipn', 'ipp', 'ipps', 'iris', 'iris.beep', 'iris.lwz', 'iris.xpc', 'iris.xpcs', 'jabber', 'ldap', 'leaptofrogans', 'mailserver', 'mailto', 'mid', 'modem', 'msrp', 'msrps', 'mt', 'mtqp', 'mupdate', 'news', 'nfs', 'ni', 'nih', 'nntp', 'opaquelocktoken', 'p1', 'pack', 'pkcs11', 'pop', 'pres', 'prospero', 'reload', 'rtsp', 'rtsps', 'rtspu', 'service', 'session', 'shttp (OBSOLETE)', 'sieve', 'sip', 'sips', 'sms', 'snews', 'snmp', 'soap.beep', 'soap.beeps', 'stun', 'stuns', 'tag', 'tel', 'telnet', 'tftp', 'thismessage', 'tip', 'tn3270', 'turn', 'turns', 'tv', 'upt', 'urn', 'vemmi', 'videotex', 'vnc', 'wais', 'wpid', 'ws', 'wss', 'xcon', 'xcon-userid', 'xmlrpc.beep', 'xmlrpc.beeps', 'xmpp', 'z39.50', 'z39.50r', 'z39.50s');
|
||||
$found = FALSE;
|
||||
$checkId = strtolower($id);
|
||||
|
||||
|
|
|
@ -12,6 +12,11 @@ Once a feed is fully composed with its items, the feed class can generate the ne
|
|||
|
||||
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.
|
||||
|
||||
## Installation
|
||||
You can install via [Composer](https://getcomposer.org/).
|
||||
|
||||
composer require mibe/feedwriter
|
||||
|
||||
## Documentation
|
||||
|
||||
The documentation can be found in the `gh-pages` branch, or on [GitHub Pages](https://mibe.github.io/FeedWriter/).
|
||||
|
@ -40,3 +45,6 @@ In chronological order:
|
|||
- Pavel Khakhlou
|
||||
- Daniel
|
||||
- Tino Goratsch
|
||||
- John
|
||||
- Özgür Görgülü
|
||||
- Jan Tojnar
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
# Version 3.1
|
||||
- Initialise un module installé dans une page sans avoir ouvert la page de configuration sans lancer de mise à jour.
|
||||
# Version 3.0
|
||||
- Gestion des permissions intégrée dans le module
|
||||
# Version 2.8
|
||||
|
|
|
@ -20,7 +20,7 @@
|
|||
class search extends common
|
||||
{
|
||||
|
||||
const VERSION = '3.0';
|
||||
const VERSION = '3.1';
|
||||
const REALNAME = 'Recherche';
|
||||
const DATADIRECTORY = self::DATA_DIR . 'search/';
|
||||
|
||||
|
@ -173,8 +173,8 @@ class search extends common
|
|||
public function index()
|
||||
{
|
||||
|
||||
// Mise à jour des données de module
|
||||
$this->update();
|
||||
// Initialise un module non configuré
|
||||
$this->init();
|
||||
|
||||
if (
|
||||
$this->isPost()
|
||||
|
|
Loading…
Reference in New Issue