diff --git a/src/Entity/Item.php b/src/Entity/Item.php
index 8e43f6a..a50fe93 100644
--- a/src/Entity/Item.php
+++ b/src/Entity/Item.php
@@ -12,6 +12,17 @@ use Shikiryu\SRSS\Validator\Validator;
/**
* https://cyber.harvard.edu/rss/rss.html#hrelementsOfLtitemgt
+ * @property null|string title
+ * @property null|string link
+ * @property null|string description
+ * @property null|string author
+ * @property null|array category
+ * @property null|string comments
+ * @property null|Enclosure enclosure
+ * @property null|string guid
+ * @property null|string pubDate
+ * @property null|Source source
+ * @property array medias
*/
class Item extends HasValidator implements SRSSElement
{
diff --git a/src/Exception/InvalidPropertyException.php b/src/Exception/InvalidPropertyException.php
new file mode 100644
index 0000000..818f855
--- /dev/null
+++ b/src/Exception/InvalidPropertyException.php
@@ -0,0 +1,12 @@
+isValidValueForObjectProperty($this->channel, $name, $val)) {
- if (SRSSTools::getPropertyType(Channel::class, $name) === 'array') {
- $this->channel->{$name} = $val;
- } else {
- $val = is_string($val) ? (new Formator())->formatValue($this->channel, $name, $val) : $val;
- $this->channel->{$name} = $val;
- }
+ if (!(new Validator())->isValidValueForObjectProperty($this->channel, $name, $val)) {
+ throw new InvalidPropertyException(get_class($this), $name, $val);
+ }
+ if (SRSSTools::getPropertyType(Channel::class, $name) === 'array') {
+ $this->channel->{$name} = $val;
+ } else {
+ $val = is_string($val) ? (new Formator())->formatValue($this->channel, $name, $val) : $val;
+ $this->channel->{$name} = $val;
}
}
diff --git a/src/Validator/HasValidator.php b/src/Validator/HasValidator.php
index 5017501..8896080 100644
--- a/src/Validator/HasValidator.php
+++ b/src/Validator/HasValidator.php
@@ -2,6 +2,7 @@
namespace Shikiryu\SRSS\Validator;
+use Shikiryu\SRSS\Exception\InvalidPropertyException;
use Shikiryu\SRSS\Exception\PropertyNotFoundException;
use Shikiryu\SRSS\Exception\SRSSException;
use Shikiryu\SRSS\SRSSTools;
@@ -27,17 +28,19 @@ abstract class HasValidator
if (!property_exists(static::class, $name)) {
throw new PropertyNotFoundException(static::class, $name);
}
- if ((new Validator())->isValidValueForObjectProperty($this, $name, $val)) {
-
- if (SRSSTools::getPropertyType(static::class, $name) === 'array') {
- /** @var array $this->{$name} */
- $this->{$name}[] = $val;
- } else {
- $val = is_string($val) ? (new Formator())->formatValue($this, $name, $val) : $val;
- $this->{$name} = $val;
- }
+ if (!(new Validator())->isValidValueForObjectProperty($this, $name, $val)) {
+ throw new InvalidPropertyException(get_class($this), $name, $val);
}
+
+ if (SRSSTools::getPropertyType(static::class, $name) === 'array') {
+ /** @var array $this->{$name} */
+ $this->{$name}[] = $val;
+ } else {
+ $val = is_string($val) ? (new Formator())->formatValue($this, $name, $val) : $val;
+ $this->{$name} = $val;
+ }
+
}
/**
diff --git a/src/Validator/Validator.php b/src/Validator/Validator.php
index 0d6bdbb..6ff38f1 100644
--- a/src/Validator/Validator.php
+++ b/src/Validator/Validator.php
@@ -24,6 +24,7 @@ class Validator
*/
public function isValidValueForObjectProperty($object, $property, $value): bool
{
+ $this->object = $object;
try {
$property = $this->getReflectedProperty($object, $property);
} catch (ReflectionException) {
@@ -31,17 +32,19 @@ class Validator
}
$propertyAnnotations = $this->_getPropertyAnnotations($property);
- if (empty($value) && count(array_filter($property['rules'], static fn($rule) => str_starts_with($rule, 'required'))) === 0) {
+ if (empty($value) && count(array_filter($propertyAnnotations, static fn($rule) => str_starts_with($rule, 'required'))) === 0) {
return true;
}
foreach ($propertyAnnotations as $propertyAnnotation) {
$annotation = explode(' ', $propertyAnnotation);
- $object->validated[$property->name] = $this->_validateProperty($annotation, $value);
+ if ($this->_validateProperty($annotation, $value) === false) {
+ return false;
+ }
}
- return count(array_filter($object->validated, static fn($v) => ($v !== null && $v === false))) === 0;
+ return true;
}
/**
@@ -69,6 +72,7 @@ class Validator
*/
public function isObjectValid($object): bool
{
+ $object->validated = [];
// if (!$object->validated) {
$object = $this->validateObject($object);
// }
@@ -250,4 +254,13 @@ class Validator
{
return filter_var($value, FILTER_VALIDATE_EMAIL);
}
+
+ private function _validateMax($value, array $max): bool
+ {
+ return $value <= current($max);
+ }
+ private function _validateMin($value, array $max): bool
+ {
+ return $value >= current($max);
+ }
}
\ No newline at end of file
diff --git a/tests/FailingTest.php b/tests/FailingTest.php
index 17291e1..7dacf65 100644
--- a/tests/FailingTest.php
+++ b/tests/FailingTest.php
@@ -1,114 +1,230 @@
srss = SRSS::create();
- self::assertFalse($this->srss->isValid(), var_export($this->srss->validated, true));
- $this->srss->title = 'title'; // mandatory
- self::assertFalse($this->srss->isValid(), var_export($this->srss->validated, true));
- $this->srss->description = 'desc'; // mandatory
- self::assertFalse($this->srss->isValid(), var_export($this->srss->validated, true));
-
- $this->srss->link = 'desc'; // mandatory but should be a url
- self::assertFalse($this->srss->isValid(), var_export($this->srss->validated, true));
- $this->srss->link = 'https://example.org';
- self::assertTrue($this->srss->isValid(), var_export($this->srss->validated, true));
-
- $this->srss->language = 'en-en'; // should be a valid language
- self::assertFalse($this->srss->isValid(), var_export($this->srss->validated, true));
- $this->srss->language = 'en-us'; // should be a valid
- self::assertTrue($this->srss->isValid(), var_export($this->srss->validated, true));
-
- $this->srss->copyright = 'test'; // should not have html element
- self::assertFalse($this->srss->isValid(), var_export($this->srss->validated, true));
- $this->srss->copyright = 'shikiryu';
- self::assertTrue($this->srss->isValid(), var_export($this->srss->validated, true));
-
- $this->srss->managingEditor = 'test'; // should not have html element
- self::assertFalse($this->srss->isValid(), var_export($this->srss->validated, true));
- $this->srss->managingEditor = 'shikiryu';
- self::assertTrue($this->srss->isValid(), var_export($this->srss->validated, true));
-
- $this->srss->webMaster = 'test'; // should not have html element
- self::assertFalse($this->srss->isValid(), var_export($this->srss->validated, true));
- $this->srss->webMaster = 'shikiryu';
- self::assertTrue($this->srss->isValid(), var_export($this->srss->validated, true));
-
- $this->srss->pubDate = 'test'; // should be a valid date
- self::assertFalse($this->srss->isValid(), var_export($this->srss->validated, true));
- $this->srss->pubDate = (new DateTime())->format(DATE_RSS);
- self::assertTrue($this->srss->isValid(), var_export($this->srss->validated, true));
-
- $this->srss->lastBuildDate = 'test'; // should be a valid date
- self::assertFalse($this->srss->isValid(), var_export($this->srss->validated, true));
- $this->srss->lastBuildDate = (new DateTime())->format(DATE_RSS);
- self::assertTrue($this->srss->isValid(), var_export($this->srss->validated, true));
-
- $this->srss->generator = 'test'; // should not have html element
- self::assertFalse($this->srss->isValid(), var_export($this->srss->validated, true));
- $this->srss->generator = 'shikiryuRSS';
- self::assertTrue($this->srss->isValid(), var_export($this->srss->validated, true));
-
- $this->srss->docs = 'desc'; //should be a url
- self::assertFalse($this->srss->isValid(), var_export($this->srss->validated, true));
- $this->srss->docs = 'https://example.org';
- self::assertTrue($this->srss->isValid(), var_export($this->srss->validated, true));
-
- $this->srss->ttl = 'desc'; // should be an int
- self::assertFalse($this->srss->isValid(), var_export($this->srss->validated, true));
- $this->srss->ttl = '85';
- self::assertTrue($this->srss->isValid(), var_export($this->srss->validated, true));
-
- // rating and textInput not tested because there's no validation
-
- $this->srss->skipHours = 'desc'; // should be an hour
- self::assertFalse($this->srss->isValid(), var_export($this->srss->validated, true));
- $this->srss->skipHours = '12';
- self::assertTrue($this->srss->isValid(), var_export($this->srss->validated, true));
-
- $this->srss->skipDays = 'desc'; // should be a day
- self::assertFalse($this->srss->isValid(), var_export($this->srss->validated, true));
- $this->srss->skipDays = 'monday';
- self::assertTrue($this->srss->isValid(), var_export($this->srss->validated, true));
+ $rss = SRSS::create();
+ self::assertFalse($rss->isValid(), var_export($rss->validated, true));
+ $rss->title = 'title'; // mandatory
+ self::assertFalse($rss->isValid(), var_export($rss->validated, true));
+ $rss->description = 'desc'; // mandatory
+ self::assertFalse($rss->isValid(), var_export($rss->validated, true));
+ $rss->link = 'https://example.org';
+ self::assertTrue($rss->isValid(), var_export($rss->validated, true));
}
- public function testItem()
+ public function testInvalidChannelLink(): void
+ {
+ $this->expectException(InvalidPropertyException::class);
+ $rss = SRSS::create();
+ $rss->title = 'title'; // mandatory
+ $rss->description = 'desc'; // mandatory
+ $rss->link = 'desc'; // mandatory but should be an url
+ }
+
+ public function testInvalidChannelLanguage(): void
+ {
+ $rss = SRSS::create();
+ $this->expectException(InvalidPropertyException::class);
+ $rss->language = 'en-en'; // should be a valid language
+ }
+
+ public function testInvalidChannelCopyright(): void
+ {
+ $rss = SRSS::create();
+ $this->expectException(InvalidPropertyException::class);
+ $rss->copyright = 'test'; // should not have html element
+ }
+
+ public function testInvalidChannelManagingEditor(): void
+ {
+ $rss = SRSS::create();
+ $this->expectException(InvalidPropertyException::class);
+ $rss->managingEditor = 'test'; // should not have html element
+ }
+
+ public function testInvalidChannelWebmaster(): void
+ {
+ $rss = SRSS::create();
+ $this->expectException(InvalidPropertyException::class);
+ $rss->webMaster = 'test'; // should not have html element
+ }
+
+ public function testInvalidChannelPubDate(): void
+ {
+ $rss = SRSS::create();
+ $this->expectException(InvalidPropertyException::class);
+ $rss->pubDate = 'test'; // should be a valid date
+ }
+
+ public function testInvalidChannelLastBuildDate(): void
+ {
+ $rss = SRSS::create();
+ $this->expectException(InvalidPropertyException::class);
+ $rss->lastBuildDate = 'test'; // should be a valid date
+ }
+
+ public function testInvalidChannelGenerator(): void
+ {
+ $rss = SRSS::create();
+ $this->expectException(InvalidPropertyException::class);
+ $rss->generator = 'test'; // should not have html element
+ }
+
+ public function testInvalidChannelDocs(): void
+ {
+ $rss = SRSS::create();
+ $this->expectException(InvalidPropertyException::class);
+ $rss->docs = 'desc'; //should be a url
+ }
+
+ public function testInvalidChannelTTL(): void
+ {
+ $rss = SRSS::create();
+ $this->expectException(InvalidPropertyException::class);
+ $rss->ttl = 'desc'; // should be an int
+ }
+
+ public function testInvalidChannelSkipHours(): void
+ {
+ $rss = SRSS::create();
+ $this->expectException(InvalidPropertyException::class);
+ $rss->skipHours = 'desc'; // should be an hour
+ }
+
+ public function testInvalidChannelSkipDays(): void
+ {
+ $rss = SRSS::create();
+ $this->expectException(InvalidPropertyException::class);
+ $rss->skipDays = 'desc'; // should be a day
+ }
+
+ public function testInvalidItemAuthor(): void
{
$item = new Shikiryu\SRSS\Entity\Item();
-
- self::assertFalse($item->isValid(), var_export($item->validated, true));
- $item->title = 'title';
- self::assertTrue($item->isValid(), var_export($item->validated, true));
-
- $item->link = 'test';
- self::assertFalse($item->isValid(), var_export($item->validated, true));
- $item->link = 'https://example.org/link1';
- self::assertTrue($item->isValid(), var_export($item->validated, true));
-
- $item->title = null;
- self::assertFalse($item->isValid(), var_export($item->validated, true));
- $item->description = 'desc';
- self::assertTrue($item->isValid(), var_export($item->validated, true));
- $item->title = 'title';
- self::assertTrue($item->isValid(), var_export($item->validated, true));
-
- $item->author = 'test';
- self::assertFalse($item->isValid(), var_export($item->validated, true));
- $item->author = 'email@example.org';
- self::assertTrue($item->isValid(), var_export($item->validated, true));
-
- $item->comments = 'test';
- self::assertFalse($item->isValid(), var_export($item->validated, true));
- $item->comments = 'https://example.org/link1';
- self::assertTrue($item->isValid(), var_export($item->validated, true));
-
- // guid is not validated and, so, not tested
+ $this->expectException(InvalidPropertyException::class);
+ $item->author = 'test'; // should be an email
}
-}
\ No newline at end of file
+
+ public function testInvalidItemComments(): void
+ {
+ $item = new Shikiryu\SRSS\Entity\Item();
+ $this->expectException(InvalidPropertyException::class);
+ $item->comments = 'test'; // should be an url
+ }
+
+ public function testInvalidItemMandatory(): void
+ {
+ $item = new Shikiryu\SRSS\Entity\Item();
+ $item->title = 'title';
+ self::assertTrue($item->isValid(), var_export($item->validated, true));
+ $item->description = 'desc';
+ $item->title = null;
+ self::assertTrue($item->isValid(), var_export($item->validated, true));
+
+ $this->expectException(InvalidPropertyException::class);
+ $item->title = null;
+ $item->description = null;
+ }
+
+ public function testChannelCategoryDomain(): void
+ {
+ $category = new Category();
+ $this->expectException(InvalidPropertyException::class);
+ $category->domain = 'test';
+ }
+
+ public function testChannelCloudPort(): void
+ {
+ $cloud = new Cloud();
+ $this->expectException(InvalidPropertyException::class);
+ $cloud->port = 'test';
+ }
+
+ public function testChannelImageUrl(): void
+ {
+ $image = new Image();
+ $this->expectException(InvalidPropertyException::class);
+ $image->url = 'test';
+ }
+
+ public function testChannelImageTitle(): void
+ {
+ $image = new Image();
+ $this->expectException(InvalidPropertyException::class);
+ $image->title = 'test';
+ }
+
+ public function testChannelImageLink(): void
+ {
+ $image = new Image();
+ $this->expectException(InvalidPropertyException::class);
+ $image->link = 'test';
+ }
+
+ public function testChannelImageWidthType(): void
+ {
+ $image = new Image();
+ $this->expectException(InvalidPropertyException::class);
+ $image->width = 'test';
+ }
+
+ public function testChannelImageWidthMax(): void
+ {
+ $image = new Image();
+ $this->expectException(InvalidPropertyException::class);
+ $image->width = '150';
+ }
+
+ public function testChannelImageHeightType(): void
+ {
+ $image = new Image();
+ $this->expectException(InvalidPropertyException::class);
+ $image->height = 'test';
+ }
+
+ public function testChannelImageHeightMax(): void
+ {
+ $image = new Image();
+ $this->expectException(InvalidPropertyException::class);
+ $image->height = '500';
+ }
+
+ public function testItemEnclosureUrl(): void
+ {
+ $enclosure = new Enclosure();
+ $this->expectException(InvalidPropertyException::class);
+ $enclosure->url = 'test';
+ }
+
+ public function testItemEnclosureLength(): void
+ {
+ $enclosure = new Enclosure();
+ $this->expectException(InvalidPropertyException::class);
+ $enclosure->length = 'test';
+ }
+
+ public function testItemSourceUrl()
+ {
+ $source = new Source();
+ $this->expectException(InvalidPropertyException::class);
+ $source->url = 'test';
+ }
+
+ public function testItemSourceValue()
+ {
+ $source = new Source();
+ $this->expectException(InvalidPropertyException::class);
+ $source->value = 'test';
+ }
+}