diff --git a/lib/Parser/XML/Feed.php b/lib/Parser/XML/Feed.php index efd2cdd..6e1058e 100644 --- a/lib/Parser/XML/Feed.php +++ b/lib/Parser/XML/Feed.php @@ -144,7 +144,7 @@ class Feed implements \MensBeam\Lax\Parser\Feed { public function getSchedule(): Schedule { $out = new Schedule; - $out->interval = $this->getSchedIntervalRss2(); + $out->interval = $this->getSchedIntervalRss1() ?? $this->getSchedIntervalRss2(); $out->skip = $this->getSchedSkipRss2(); $out->expired = $this->getExpiredPod(); if (is_null($out->expired) && (($out->skip & Schedule::DAY_ALL) == Schedule::DAY_ALL || ($out->skip & Schedule::HOUR_ALL) == Schedule::HOUR_ALL)) { diff --git a/lib/Parser/XML/Primitives/Feed.php b/lib/Parser/XML/Primitives/Feed.php index f21886e..d4eb0d6 100644 --- a/lib/Parser/XML/Primitives/Feed.php +++ b/lib/Parser/XML/Primitives/Feed.php @@ -95,23 +95,20 @@ trait Feed { "monthly" => ["D", 30], // 30 days "yearly" => ["M", 12], // 12 months ][strtolower($period)]; - $f = min(1, (int) $this->fetchString("sched:updateFrequency", "0*[1-9]\d*")); // a frequency of zero makes no sense + $f = max(1, (int) $this->fetchString("sched:updateFrequency", "0*[1-9]\d*")); // a frequency of zero makes no sense // divide the period by the frequency // FIXME: we must have an integer result because PHP (incorrectly) rejects fractional intervals // see https://bugs.php.net/bug.php?id=53831 - $n = min(1, intdiv($n, $f)); // a frequency of zero still makes no sense, so we assume at least one subdivision + $n = max(1, intdiv($n, $f)); // a frequency of zero still makes no sense, so we assume at least one subdivision return new \DateInterval("P".(strlen($p) === 1 ? "" : $p[0]).$n.$p[-1]); } return null; } - - /** Computes the "skip-schedule" of an RSS feed, the set of days and hours during which a feed should not be fetched */ protected function getSchedSkipRss2(): ?int { $out = 0; - $hours = $this->fetchString("skipHours/hour", "\d+", true) ?? []; - foreach($hours as $h) { + foreach($this->fetchString("skipHours/hour", "\d+", true) ?? [] as $h) { $out |= [ Schedule::HOUR_0, Schedule::HOUR_1, @@ -140,8 +137,7 @@ trait Feed { Schedule::HOUR_0, ][(int) $h] ?? 0; } - $days = $this->fetchString("skipDays/day", null, true) ?? []; - foreach($days as $d) { + foreach($this->fetchString("skipDays/day", null, true) ?? [] as $d) { $out |= [ "monday" => Schedule::DAY_MON, "tuesday" => Schedule::DAY_TUE, diff --git a/tests/cases/AbstractParserTestCase.php b/tests/cases/AbstractParserTestCase.php index bfd6fe3..21c92de 100644 --- a/tests/cases/AbstractParserTestCase.php +++ b/tests/cases/AbstractParserTestCase.php @@ -90,6 +90,8 @@ class AbstractParserTestCase extends \PHPUnit\Framework\TestCase { foreach ($v as $kk => $vv) { if ($kk === "url") { $f->$k->$kk = $this->makeUrl($vv); + } elseif ($kk === "interval") { + $f->$k->$kk = new \DateInterval($vv); } else { $f->$k->$kk = $vv; } diff --git a/tests/cases/XML/feed-rss1.yaml b/tests/cases/XML/feed-rss1.yaml index 00094bf..28c9bdc 100644 --- a/tests/cases/XML/feed-rss1.yaml +++ b/tests/cases/XML/feed-rss1.yaml @@ -52,3 +52,72 @@ DC ID with whitespace: format: rdf version: '1.0' id: 'http://example.com/' + +Syndication schedule 1: + input: > + + + hourly + + + output: + format: rdf + version: '1.0' + sched: + interval: PT60M + +Syndication schedule 2: + input: > + + + DAILY + 012 + + + output: + format: rdf + version: '1.0' + sched: + interval: PT2H + +Syndication schedule 3: + input: > + + + WeeKLy + 2 + + + output: + format: rdf + version: '1.0' + sched: + interval: P3D + +Syndication schedule 4: + input: > + + + monthly + 3 + + + output: + format: rdf + version: '1.0' + sched: + interval: P10D + +Syndication schedule 5: + input: > + + + yearly + 24 + + + output: + format: rdf + version: '1.0' + sched: + interval: P1M diff --git a/tests/cases/XML/feed-rss2.yaml b/tests/cases/XML/feed-rss2.yaml index 4b9860e..01d6c93 100644 --- a/tests/cases/XML/feed-rss2.yaml +++ b/tests/cases/XML/feed-rss2.yaml @@ -38,6 +38,47 @@ Root GUID: # Any elements on the RSS2 root element should be ignored output: format: rss +Schedule interval 1: + input: > + + 60 + + output: + format: rss + sched: + interval: PT60M + +Schedule interval 2: + input: > + + bogus + 60 + + output: + format: rss + sched: + interval: PT60M + +Schedule interval 3: + input: > + + + 0120 + + + output: + format: rss + sched: + interval: PT120M + +Schedule interval 4: + input: > + + 0 + + output: + format: rss + Skip days: input: >