Merge commit 'fd511229181cca42029257d29b0407e5ca598dc9' into HEAD

This commit is contained in:
Fred Tempez 2024-03-23 15:36:02 +01:00
commit df06b1f7ba
18 changed files with 358 additions and 44 deletions

3
.gitignore vendored
View File

@ -9,4 +9,5 @@ site/i18n/*.json
core/vendor/tinymce/link_list.json core/vendor/tinymce/link_list.json
robots.txt robots.txt
sitemap.xml sitemap.xml
.gitignore .gitignore
core/module/config/tool/data.key

View File

@ -3,9 +3,11 @@
## Version 13.1.08 ## Version 13.1.08
### Amélioration ### Améliorations
- Sauvegarde de l'état des sélecteurs dans les tables des fontes et des utilisateurs. - 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.
## Version 13.1.07 ## Version 13.1.07

View File

@ -129,9 +129,9 @@ class JsonDb extends \Prowebcraft\Dot
} }
} }
$this->data = json_decode(file_get_contents($this->db), true); $this->data = json_decode(file_get_contents($this->db), true);
if (!$this->data === null) { if (!$this->data === null && json_last_error() !== JSON_ERROR_NONE) {
throw new \InvalidArgumentException('Database file ' . $this->db throw new \InvalidArgumentException('Le fichier ' . $this->db
. ' contains invalid json object. Please validate or remove file'); . ' contient des données invalides.');
} }
} }
return $this->data; return $this->data;
@ -142,9 +142,14 @@ class JsonDb extends \Prowebcraft\Dot
*/ */
public function save() public function save()
{ {
$v = json_encode($this->data, JSON_UNESCAPED_UNICODE | JSON_FORCE_OBJECT); $v = json_encode($this->data, JSON_UNESCAPED_UNICODE | JSON_FORCE_OBJECT | JSON_PRETTY_PRINT);
// $v = json_encode($this->data, JSON_UNESCAPED_UNICODE | JSON_FORCE_OBJECT);
$l = strlen($v); $l = strlen($v);
$t = 0; $t = 0;
if ($v === false) {
error_log('Erreur d\'encodage JSON : ' . json_last_error_msg());
exit ('Erreur d\'encodage JSON : ' . json_last_error_msg());
}
while ($t < 5) { while ($t < 5) {
$w = file_put_contents($this->db, $v); // Multi user get a locker $w = file_put_contents($this->db, $v); // Multi user get a locker
if ($w == $l) { if ($w == $l) {

View File

@ -0,0 +1,4 @@
<Files "data.key">
Order Allow,Deny
Deny from all
</Files>

View File

@ -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);
}

View File

@ -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);
}

View File

@ -16,7 +16,7 @@
class blog extends common class blog extends common
{ {
const VERSION = '7.5'; const VERSION = '7.6';
const REALNAME = 'Blog'; const REALNAME = 'Blog';
const DELETE = true; const DELETE = true;
const UPDATE = '0.0'; const UPDATE = '0.0';

View File

@ -1,3 +1,5 @@
# Version 7.6
- Mise à jour RSS Feed
# Version 7.5 # Version 7.5
- Bug paramètre de localisation erroné - Bug paramètre de localisation erroné
# Version 7.4 # Version 7.4

View File

@ -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

View File

@ -2,10 +2,11 @@
namespace FeedWriter; namespace FeedWriter;
use \DateTime; use \DateTime;
use \DateTimeInterface;
/* /*
* Copyright (C) 2008 Anis uddin Ahmad <anisniit@gmail.com> * 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. * This file is part of the "Universal Feed Writer" project.
* *
@ -76,6 +77,13 @@ abstract class Feed
*/ */
private $version = null; private $version = null;
/**
* Contains the encoding of this feed.
*
* @var string
*/
private $encoding = 'utf-8';
/** /**
* Constructor * Constructor
* *
@ -87,9 +95,6 @@ abstract class Feed
{ {
$this->version = $version; $this->version = $version;
// Setting default encoding
$this->encoding = 'utf-8';
// Setting default value for essential channel element // Setting default value for essential channel element
$this->setTitle($version . ' Feed'); $this->setTitle($version . ' Feed');
@ -396,9 +401,13 @@ abstract class Feed
* @access public * @access public
* @param string $title value of 'title' channel tag * @param string $title value of 'title' channel tag
* @return self * @return self
* @throws \InvalidArgumentException if the title is empty or NULL.
*/ */
public function setTitle($title) public function setTitle($title)
{ {
if (empty($title))
throw new \InvalidArgumentException('The title may not be empty or NULL.');
return $this->setChannelElement('title', $title); return $this->setChannelElement('title', $title);
} }
@ -406,15 +415,15 @@ abstract class Feed
* Set the date when the feed was lastly updated. * Set the date when the feed was lastly updated.
* *
* This adds the 'updated' element to the feed. The value of the date parameter * 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. * timestamp or a string which is parseable by PHP's 'strtotime' function.
* *
* Not supported in RSS1 feeds. * Not supported in RSS1 feeds.
* *
* @access public * @access public
* @param DateTime|int|string Date which should be used. * @param DateTimeInterface|int|string Date which should be used.
* @return self * @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. * @throws InvalidOperationException if this method is called on an RSS1 feed.
*/ */
public function setDate($date) public function setDate($date)
@ -425,7 +434,7 @@ abstract class Feed
// The feeds have different date formats. // The feeds have different date formats.
$format = $this->version == Feed::ATOM ? \DATE_ATOM : \DATE_RSS; $format = $this->version == Feed::ATOM ? \DATE_ATOM : \DATE_RSS;
if ($date instanceof DateTime) if ($date instanceof DateTimeInterface || $date instanceof DateTime)
$date = $date->format($format); $date = $date->format($format);
else if(is_numeric($date) && $date >= 0) else if(is_numeric($date) && $date >= 0)
$date = date($format, $date); $date = date($format, $date);
@ -438,7 +447,7 @@ abstract class Feed
$date = date($format, $timestamp); $date = date($format, $timestamp);
} }
else 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) if ($this->version == Feed::ATOM)
$this->setChannelElement('updated', $date); $this->setChannelElement('updated', $date);
@ -454,9 +463,13 @@ abstract class Feed
* @access public * @access public
* @param string $description Description of the feed. * @param string $description Description of the feed.
* @return self * @return self
* @throws \InvalidArgumentException if the description is empty or NULL.
*/ */
public function setDescription($description) public function setDescription($description)
{ {
if (empty($description))
throw new \InvalidArgumentException('The description may not be empty or NULL.');
if ($this->version != Feed::ATOM) if ($this->version != Feed::ATOM)
$this->setChannelElement('description', $description); $this->setChannelElement('description', $description);
else else
@ -471,9 +484,13 @@ abstract class Feed
* @access public * @access public
* @param string $link value of 'link' channel tag * @param string $link value of 'link' channel tag
* @return self * @return self
* @throws \InvalidArgumentException if the link is empty or NULL.
*/ */
public function setLink($link) public function setLink($link)
{ {
if (empty($link))
throw new \InvalidArgumentException('The link may not be empty or NULL.');
if ($this->version == Feed::ATOM) if ($this->version == Feed::ATOM)
$this->setAtomLink($link); $this->setAtomLink($link);
else else
@ -667,7 +684,7 @@ abstract class Feed
/** /**
* Replace invalid XML characters. * 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 http://www.w3.org/TR/REC-xml/#charsets
* @link https://github.com/mibe/FeedWriter/issues/30 * @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; $out .= "</rdf:Seq>" . PHP_EOL . "</items>" . PHP_EOL . "</channel>" . PHP_EOL;
// An image has its own element after the channel elements. // 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'])); $out .= $this->makeNode('image', $this->data['Image'], array('rdf:about' => $this->data['Image']['url']));
} else if ($this->version == Feed::ATOM) { } else if ($this->version == Feed::ATOM) {
// ATOM feeds have a unique feed ID. Use the title channel element as key. // ATOM feeds have a unique feed ID. Use the title channel element as key.

View File

@ -2,6 +2,7 @@
namespace FeedWriter; namespace FeedWriter;
use \DateTime; use \DateTime;
use \DateTimeInterface;
/* /*
* Copyright (C) 2008 Anis uddin Ahmad <anisniit@gmail.com> * Copyright (C) 2008 Anis uddin Ahmad <anisniit@gmail.com>
@ -217,19 +218,19 @@ class Item
/** /**
* Set the 'date' element of the feed item. * Set the 'date' element of the feed item.
* *
* The value of the date parameter can be either an instance of the * The value of the date parameter can be either a class implementing
* DateTime class, an integer containing a UNIX timestamp or a string * DateTimeInterface, an integer containing a UNIX timestamp or a string
* which is parseable by PHP's 'strtotime' function. * which is parseable by PHP's 'strtotime' function.
* *
* @access public * @access public
* @param DateTime|int|string $date Date which should be used. * @param DateTimeInterface|int|string $date Date which should be used.
* @return self * @return self
* @throws \InvalidArgumentException if the given date was not parseable. * @throws \InvalidArgumentException if the given date was not parseable.
*/ */
public function setDate($date) public function setDate($date)
{ {
if (!is_numeric($date)) { if (!is_numeric($date)) {
if ($date instanceof DateTime) if ($date instanceof DateTimeInterface || $date instanceof DateTime)
$date = $date->getTimestamp(); $date = $date->getTimestamp();
else { else {
$date = strtotime($date); $date = strtotime($date);
@ -277,7 +278,7 @@ class Item
* Attach a external media to the feed item. * Attach a external media to the feed item.
* Not supported in RSS 1.0 feeds. * 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, * Note that you should avoid the use of more than one enclosure in one item,
* since some RSS aggregators don't support it. * 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 string $type The MIME type attribute of the media.
* @param boolean $multiple Specifies if multiple enclosures are allowed * @param boolean $multiple Specifies if multiple enclosures are allowed
* @return self * @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 \InvalidArgumentException if the length or type parameter is invalid.
* @throws InvalidOperationException if this method is called on RSS1 feeds. * @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) // 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 // The list of valid schemes was generated from http://www.iana.org/assignments/uri-schemes
// by using only permanent or historical 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; $found = FALSE;
$checkId = strtolower($id); $checkId = strtolower($id);

View File

@ -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. 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 ## Documentation
The documentation can be found in the `gh-pages` branch, or on [GitHub Pages](https://mibe.github.io/FeedWriter/). 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 - Pavel Khakhlou
- Daniel - Daniel
- Tino Goratsch - Tino Goratsch
- John
- Özgür Görgülü
- Jan Tojnar

View File

@ -1,3 +1,5 @@
# Version 5.5
- Mise à jour RSS Feed
# Version 5.4 # Version 5.4
- Bug paramètre de localisation erroné - Bug paramètre de localisation erroné
# Version 5.3 # Version 5.3

View File

@ -16,7 +16,7 @@
class news extends common class news extends common
{ {
const VERSION = '5.4'; const VERSION = '5.5';
const REALNAME = 'News'; const REALNAME = 'News';
const DATADIRECTORY = self::DATA_DIR . 'news/'; const DATADIRECTORY = self::DATA_DIR . 'news/';

View File

@ -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

View File

@ -2,10 +2,11 @@
namespace FeedWriter; namespace FeedWriter;
use \DateTime; use \DateTime;
use \DateTimeInterface;
/* /*
* Copyright (C) 2008 Anis uddin Ahmad <anisniit@gmail.com> * 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. * This file is part of the "Universal Feed Writer" project.
* *
@ -76,6 +77,13 @@ abstract class Feed
*/ */
private $version = null; private $version = null;
/**
* Contains the encoding of this feed.
*
* @var string
*/
private $encoding = 'utf-8';
/** /**
* Constructor * Constructor
* *
@ -87,9 +95,6 @@ abstract class Feed
{ {
$this->version = $version; $this->version = $version;
// Setting default encoding
$this->encoding = 'utf-8';
// Setting default value for essential channel element // Setting default value for essential channel element
$this->setTitle($version . ' Feed'); $this->setTitle($version . ' Feed');
@ -396,9 +401,13 @@ abstract class Feed
* @access public * @access public
* @param string $title value of 'title' channel tag * @param string $title value of 'title' channel tag
* @return self * @return self
* @throws \InvalidArgumentException if the title is empty or NULL.
*/ */
public function setTitle($title) public function setTitle($title)
{ {
if (empty($title))
throw new \InvalidArgumentException('The title may not be empty or NULL.');
return $this->setChannelElement('title', $title); return $this->setChannelElement('title', $title);
} }
@ -406,15 +415,15 @@ abstract class Feed
* Set the date when the feed was lastly updated. * Set the date when the feed was lastly updated.
* *
* This adds the 'updated' element to the feed. The value of the date parameter * 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. * timestamp or a string which is parseable by PHP's 'strtotime' function.
* *
* Not supported in RSS1 feeds. * Not supported in RSS1 feeds.
* *
* @access public * @access public
* @param DateTime|int|string Date which should be used. * @param DateTimeInterface|int|string Date which should be used.
* @return self * @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. * @throws InvalidOperationException if this method is called on an RSS1 feed.
*/ */
public function setDate($date) public function setDate($date)
@ -425,7 +434,7 @@ abstract class Feed
// The feeds have different date formats. // The feeds have different date formats.
$format = $this->version == Feed::ATOM ? \DATE_ATOM : \DATE_RSS; $format = $this->version == Feed::ATOM ? \DATE_ATOM : \DATE_RSS;
if ($date instanceof DateTime) if ($date instanceof DateTimeInterface || $date instanceof DateTime)
$date = $date->format($format); $date = $date->format($format);
else if(is_numeric($date) && $date >= 0) else if(is_numeric($date) && $date >= 0)
$date = date($format, $date); $date = date($format, $date);
@ -438,7 +447,7 @@ abstract class Feed
$date = date($format, $timestamp); $date = date($format, $timestamp);
} }
else 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) if ($this->version == Feed::ATOM)
$this->setChannelElement('updated', $date); $this->setChannelElement('updated', $date);
@ -454,9 +463,13 @@ abstract class Feed
* @access public * @access public
* @param string $description Description of the feed. * @param string $description Description of the feed.
* @return self * @return self
* @throws \InvalidArgumentException if the description is empty or NULL.
*/ */
public function setDescription($description) public function setDescription($description)
{ {
if (empty($description))
throw new \InvalidArgumentException('The description may not be empty or NULL.');
if ($this->version != Feed::ATOM) if ($this->version != Feed::ATOM)
$this->setChannelElement('description', $description); $this->setChannelElement('description', $description);
else else
@ -471,9 +484,13 @@ abstract class Feed
* @access public * @access public
* @param string $link value of 'link' channel tag * @param string $link value of 'link' channel tag
* @return self * @return self
* @throws \InvalidArgumentException if the link is empty or NULL.
*/ */
public function setLink($link) public function setLink($link)
{ {
if (empty($link))
throw new \InvalidArgumentException('The link may not be empty or NULL.');
if ($this->version == Feed::ATOM) if ($this->version == Feed::ATOM)
$this->setAtomLink($link); $this->setAtomLink($link);
else else
@ -667,7 +684,7 @@ abstract class Feed
/** /**
* Replace invalid XML characters. * 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 http://www.w3.org/TR/REC-xml/#charsets
* @link https://github.com/mibe/FeedWriter/issues/30 * @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; $out .= "</rdf:Seq>" . PHP_EOL . "</items>" . PHP_EOL . "</channel>" . PHP_EOL;
// An image has its own element after the channel elements. // 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'])); $out .= $this->makeNode('image', $this->data['Image'], array('rdf:about' => $this->data['Image']['url']));
} else if ($this->version == Feed::ATOM) { } else if ($this->version == Feed::ATOM) {
// ATOM feeds have a unique feed ID. Use the title channel element as key. // ATOM feeds have a unique feed ID. Use the title channel element as key.

View File

@ -2,6 +2,7 @@
namespace FeedWriter; namespace FeedWriter;
use \DateTime; use \DateTime;
use \DateTimeInterface;
/* /*
* Copyright (C) 2008 Anis uddin Ahmad <anisniit@gmail.com> * Copyright (C) 2008 Anis uddin Ahmad <anisniit@gmail.com>
@ -217,19 +218,19 @@ class Item
/** /**
* Set the 'date' element of the feed item. * Set the 'date' element of the feed item.
* *
* The value of the date parameter can be either an instance of the * The value of the date parameter can be either a class implementing
* DateTime class, an integer containing a UNIX timestamp or a string * DateTimeInterface, an integer containing a UNIX timestamp or a string
* which is parseable by PHP's 'strtotime' function. * which is parseable by PHP's 'strtotime' function.
* *
* @access public * @access public
* @param DateTime|int|string $date Date which should be used. * @param DateTimeInterface|int|string $date Date which should be used.
* @return self * @return self
* @throws \InvalidArgumentException if the given date was not parseable. * @throws \InvalidArgumentException if the given date was not parseable.
*/ */
public function setDate($date) public function setDate($date)
{ {
if (!is_numeric($date)) { if (!is_numeric($date)) {
if ($date instanceof DateTime) if ($date instanceof DateTimeInterface || $date instanceof DateTime)
$date = $date->getTimestamp(); $date = $date->getTimestamp();
else { else {
$date = strtotime($date); $date = strtotime($date);
@ -277,7 +278,7 @@ class Item
* Attach a external media to the feed item. * Attach a external media to the feed item.
* Not supported in RSS 1.0 feeds. * 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, * Note that you should avoid the use of more than one enclosure in one item,
* since some RSS aggregators don't support it. * 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 string $type The MIME type attribute of the media.
* @param boolean $multiple Specifies if multiple enclosures are allowed * @param boolean $multiple Specifies if multiple enclosures are allowed
* @return self * @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 \InvalidArgumentException if the length or type parameter is invalid.
* @throws InvalidOperationException if this method is called on RSS1 feeds. * @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) // 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 // The list of valid schemes was generated from http://www.iana.org/assignments/uri-schemes
// by using only permanent or historical 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; $found = FALSE;
$checkId = strtolower($id); $checkId = strtolower($id);

View File

@ -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. 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 ## Documentation
The documentation can be found in the `gh-pages` branch, or on [GitHub Pages](https://mibe.github.io/FeedWriter/). 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 - Pavel Khakhlou
- Daniel - Daniel
- Tino Goratsch - Tino Goratsch
- John
- Özgür Görgülü
- Jan Tojnar