2023-04-05 14:44:57 +02:00
|
|
|
<?php
|
|
|
|
|
|
|
|
namespace Shikiryu\SRSS;
|
|
|
|
|
|
|
|
use Iterator;
|
2023-04-06 00:38:26 +02:00
|
|
|
use Shikiryu\SRSS\Entity\Channel;
|
|
|
|
use Shikiryu\SRSS\Entity\Item;
|
2023-04-05 14:44:57 +02:00
|
|
|
|
2023-04-06 11:07:06 +02:00
|
|
|
class SRSS implements Iterator
|
2023-04-05 14:44:57 +02:00
|
|
|
{
|
2023-04-07 00:35:20 +02:00
|
|
|
public Channel $channel;
|
2023-04-06 11:07:06 +02:00
|
|
|
public array $items; // array of SRSSItems
|
2023-04-05 14:44:57 +02:00
|
|
|
|
2023-04-07 00:35:20 +02:00
|
|
|
private int $position; // Iterator position
|
2023-04-06 00:38:26 +02:00
|
|
|
|
2023-04-05 14:44:57 +02:00
|
|
|
// lists of possible attributes for RSS
|
|
|
|
protected $possibleAttr = [
|
2023-04-06 11:07:06 +02:00
|
|
|
'title' => 'nohtml',
|
|
|
|
'link' => 'link',
|
|
|
|
'description' => 'html',
|
|
|
|
'language' => '',
|
2023-04-05 14:44:57 +02:00
|
|
|
//'language' => 'lang',
|
2023-04-06 11:07:06 +02:00
|
|
|
'copyright' => 'nohtml',
|
|
|
|
'pubDate' => 'date',
|
|
|
|
'lastBuildDate' => 'date',
|
|
|
|
'category' => 'nohtml',
|
|
|
|
'docs' => 'link',
|
|
|
|
'cloud' => '',
|
|
|
|
'generator' => 'nohtml',
|
|
|
|
'managingEditor' => 'email',
|
|
|
|
'webMaster' => 'email',
|
|
|
|
'ttl' => 'int',
|
|
|
|
'image' => '',
|
|
|
|
'rating' => 'nohtml',
|
2023-04-05 14:44:57 +02:00
|
|
|
//'textInput' => '',
|
2023-04-06 11:07:06 +02:00
|
|
|
'skipHours' => 'hour',
|
|
|
|
'skipDays' => 'day',
|
2023-04-05 14:44:57 +02:00
|
|
|
];
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Constructor
|
|
|
|
*/
|
|
|
|
public function __construct()
|
|
|
|
{
|
2023-04-06 00:38:26 +02:00
|
|
|
$this->items = [];
|
2023-04-05 14:44:57 +02:00
|
|
|
$this->position = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
2023-04-06 00:38:26 +02:00
|
|
|
* @param string $link url of the rss
|
2023-04-06 11:07:06 +02:00
|
|
|
*
|
2023-04-05 14:44:57 +02:00
|
|
|
* @return SRSS
|
2023-04-06 11:07:06 +02:00
|
|
|
* @throws SRSSException
|
2023-04-05 14:44:57 +02:00
|
|
|
*/
|
2023-04-06 00:38:26 +02:00
|
|
|
public static function read(string $link): SRSS
|
2023-04-05 14:44:57 +02:00
|
|
|
{
|
2023-04-06 11:07:06 +02:00
|
|
|
return (new SRSSParser())->parse($link);
|
2023-04-05 14:44:57 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @return SRSS
|
2023-04-06 00:38:26 +02:00
|
|
|
* @throws \DOMException
|
2023-04-05 14:44:57 +02:00
|
|
|
*/
|
|
|
|
public static function create()
|
|
|
|
{
|
|
|
|
$doc = new SRSS;
|
2023-04-06 11:07:06 +02:00
|
|
|
|
2023-04-06 00:38:26 +02:00
|
|
|
$doc->channel = new Channel();
|
|
|
|
$doc->items = [];
|
|
|
|
|
2023-04-05 14:44:57 +02:00
|
|
|
return $doc;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* check if current RSS is a valid one (based on specifications)
|
|
|
|
* @return bool
|
|
|
|
*/
|
2023-04-07 00:35:20 +02:00
|
|
|
public function isValid(): bool
|
2023-04-05 14:44:57 +02:00
|
|
|
{
|
|
|
|
$valid = true;
|
|
|
|
$items = $this->getItems();
|
2023-04-06 00:38:26 +02:00
|
|
|
$invalidItems = [];
|
2023-04-05 14:44:57 +02:00
|
|
|
$i = 1;
|
2023-04-06 11:07:06 +02:00
|
|
|
foreach ($items as $item) {
|
|
|
|
if ($item->isValid() === false) {
|
2023-04-05 14:44:57 +02:00
|
|
|
$invalidItems[] = $i;
|
|
|
|
$valid = false;
|
|
|
|
}
|
|
|
|
$i++;
|
|
|
|
}
|
2023-04-06 00:38:26 +02:00
|
|
|
|
2023-04-06 11:07:06 +02:00
|
|
|
return ($valid && $this->channel->isValid());
|
2023-04-05 14:44:57 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @param $name
|
|
|
|
*
|
|
|
|
* @return bool
|
|
|
|
*/
|
|
|
|
public function __isset($name)
|
|
|
|
{
|
2023-04-06 11:07:06 +02:00
|
|
|
return isset($this->channel->{$name});
|
2023-04-05 14:44:57 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* setter of others attributes
|
2023-04-06 11:07:06 +02:00
|
|
|
*
|
2023-04-05 14:44:57 +02:00
|
|
|
* @param $name
|
|
|
|
* @param $val
|
2023-04-06 11:07:06 +02:00
|
|
|
*
|
2023-04-05 14:44:57 +02:00
|
|
|
* @throws SRSSException
|
|
|
|
*/
|
|
|
|
public function __set($name, $val)
|
|
|
|
{
|
2023-04-07 00:35:20 +02:00
|
|
|
if (!property_exists(Channel::class, $name)) {
|
2023-04-06 11:07:06 +02:00
|
|
|
throw new SRSSException($name . ' is not a possible item');
|
|
|
|
}
|
|
|
|
$flag = $this->possibleAttr[$name];
|
|
|
|
$val = SRSSTools::check($val, $flag);
|
|
|
|
if (!empty($val)) {
|
|
|
|
$this->channel->{$name} = $val;
|
2023-04-05 14:44:57 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* getter of others attributes
|
2023-04-06 11:07:06 +02:00
|
|
|
*
|
2023-04-05 14:44:57 +02:00
|
|
|
* @param $name
|
2023-04-06 11:07:06 +02:00
|
|
|
*
|
2023-04-05 14:44:57 +02:00
|
|
|
* @return null|string
|
|
|
|
*/
|
|
|
|
public function __get($name)
|
|
|
|
{
|
2023-04-06 11:07:06 +02:00
|
|
|
return $this->channel->{$name} ?? null;
|
2023-04-05 14:44:57 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* rewind from Iterator
|
|
|
|
*/
|
2023-04-06 11:07:06 +02:00
|
|
|
public function rewind(): void
|
|
|
|
{
|
2023-04-05 14:44:57 +02:00
|
|
|
$this->position = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* current from Iterator
|
|
|
|
*/
|
2023-04-07 00:35:20 +02:00
|
|
|
public function current(): mixed
|
2023-04-06 11:07:06 +02:00
|
|
|
{
|
2023-04-05 14:44:57 +02:00
|
|
|
return $this->items[$this->position];
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* key from Iterator
|
|
|
|
*/
|
2023-04-06 11:07:06 +02:00
|
|
|
public function key(): int
|
2023-04-06 00:38:26 +02:00
|
|
|
{
|
2023-04-05 14:44:57 +02:00
|
|
|
return $this->position;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* next from Iterator
|
|
|
|
*/
|
2023-04-06 11:07:06 +02:00
|
|
|
public function next(): void
|
2023-04-06 00:38:26 +02:00
|
|
|
{
|
2023-04-05 14:44:57 +02:00
|
|
|
++$this->position;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* valid from Iterator
|
|
|
|
*/
|
2023-04-06 11:07:06 +02:00
|
|
|
public function valid(): bool
|
2023-04-06 00:38:26 +02:00
|
|
|
{
|
2023-04-05 14:44:57 +02:00
|
|
|
return isset($this->items[$this->position]);
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* getter of 1st item
|
2023-04-07 00:35:20 +02:00
|
|
|
* @return Item|null
|
2023-04-05 14:44:57 +02:00
|
|
|
*/
|
2023-04-06 00:38:26 +02:00
|
|
|
public function getFirst(): ?Item
|
2023-04-05 14:44:57 +02:00
|
|
|
{
|
|
|
|
return $this->getItem(1);
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* getter of last item
|
2023-04-06 00:38:26 +02:00
|
|
|
* @return Item
|
2023-04-05 14:44:57 +02:00
|
|
|
*/
|
2023-04-06 00:38:26 +02:00
|
|
|
public function getLast(): Item
|
2023-04-05 14:44:57 +02:00
|
|
|
{
|
|
|
|
$items = $this->getItems();
|
2023-04-06 11:07:06 +02:00
|
|
|
|
2023-04-06 00:38:26 +02:00
|
|
|
return $items[array_key_last($items)];
|
2023-04-05 14:44:57 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* getter of an item
|
2023-04-06 11:07:06 +02:00
|
|
|
*
|
2023-04-05 14:44:57 +02:00
|
|
|
* @param $i int
|
2023-04-06 00:38:26 +02:00
|
|
|
*
|
|
|
|
* @return Item|null
|
2023-04-05 14:44:57 +02:00
|
|
|
*/
|
2023-04-06 00:38:26 +02:00
|
|
|
public function getItem(int $i): ?Item
|
2023-04-05 14:44:57 +02:00
|
|
|
{
|
|
|
|
$i--;
|
2023-04-06 11:07:06 +02:00
|
|
|
|
2023-04-06 00:38:26 +02:00
|
|
|
return $this->items[$i] ?? null;
|
2023-04-05 14:44:57 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* getter of all items
|
2023-04-06 00:38:26 +02:00
|
|
|
* @return Item[]
|
2023-04-05 14:44:57 +02:00
|
|
|
*/
|
2023-04-06 00:38:26 +02:00
|
|
|
public function getItems(): array
|
2023-04-05 14:44:57 +02:00
|
|
|
{
|
|
|
|
return $this->items;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* transform current object into an array
|
|
|
|
* @return array
|
|
|
|
*/
|
2023-04-06 00:38:26 +02:00
|
|
|
public function toArray(): array
|
2023-04-05 14:44:57 +02:00
|
|
|
{
|
2023-04-06 00:38:26 +02:00
|
|
|
$doc = $this->channel->toArray();
|
|
|
|
|
2023-04-06 11:07:06 +02:00
|
|
|
foreach ($this->getItems() as $item) {
|
2023-04-05 14:44:57 +02:00
|
|
|
$doc['items'][] = $item->toArray();
|
|
|
|
}
|
2023-04-06 00:38:26 +02:00
|
|
|
|
2023-04-05 14:44:57 +02:00
|
|
|
return $doc;
|
|
|
|
}
|
2023-04-06 11:07:06 +02:00
|
|
|
}
|