diff --git a/example-json.php b/example-json.php new file mode 100644 index 0000000..143b234 --- /dev/null +++ b/example-json.php @@ -0,0 +1,27 @@ + + +

title) ?>

+ +

description)){ echo htmlspecialchars($json->description); } ?>

+ +items as $item): ?> +

title) ?> + timestamp) ?>

+ + content_html)): ?> +
content_html ?>
+ +

summary) ?>

+ + diff --git a/readme.md b/readme.md index 05f9afb..ad678eb 100644 --- a/readme.md +++ b/readme.md @@ -57,6 +57,12 @@ Download Atom feed from URL: $atom = Feed::loadAtom($url); ``` +Download JSON feed from URL: + +```php +$json = Feed::loadJsonfeed($url); +``` + You can also enable caching: ```php diff --git a/src/Feed.php b/src/Feed.php index 6c5fe55..ecfcf11 100644 --- a/src/Feed.php +++ b/src/Feed.php @@ -18,6 +18,12 @@ class Feed /** @var string */ public static $userAgent = 'FeedFetcher-Google'; + /** @var array */ + public static $supportedJsonfeedVersions = [ + 'https://jsonfeed.org/version/1', + 'https://jsonfeed.org/version/1.1' + ]; + /** @var SimpleXMLElement */ protected $xml; @@ -69,6 +75,20 @@ public static function loadAtom($url, $user = null, $pass = null) } + /** + * Loads JSON feed. + * @param string JSON feed URL + * @param string optional user name + * @param string optional password + * @return Feed + * @throws FeedException + */ + public static function loadJsonfeed($url, $user = null, $pass = null) + { + return self::fromJson(self::loadJson($url, $user, $pass)); + } + + private static function fromRss(SimpleXMLElement $xml) { if (!$xml->channel) { @@ -114,6 +134,32 @@ private static function fromAtom(SimpleXMLElement $xml) } + private static function fromJson(object $json) + { + if (!in_array($json->version, self::$supportedJsonfeedVersions, true)) { + throw new FeedException('Invalid feed.'); + } + + // generate 'url' & 'timestamp' tags + foreach ($json->items as $item) { + $item->timestamp = strtotime($item->date_published); + + if (empty($item->content_text)) { + $item->summary = (string) strip_tags($item->content_html); + } + if (empty($item->content_html)) { + $item->summary = (string) strip_tags($item->content_text); + } + if (empty($item->summary)) { + $item->summary = (string) $item->content_text; + } + } + $feed = new self; + $feed->xml = $json; + return $feed; + } + + /** * Returns property value. Do not call directly. * @param string tag name @@ -197,6 +243,43 @@ private static function loadXml($url, $user, $pass) } + /** + * Load JSON from cache or HTTP. + * @param string + * @param string + * @param string + * @return object + * @throws FeedException + */ + private static function loadJson($url, $user, $pass) + { + $e = self::$cacheExpire; + $cacheFile = self::$cacheDir . '/feed.' . md5(serialize(func_get_args())) . '.xml'; + + if (self::$cacheDir + && (time() - @filemtime($cacheFile) <= (is_string($e) ? strtotime($e) - time() : $e)) + && $data = @file_get_contents($cacheFile) + ) { + // ok + } elseif ($data = trim(self::httpRequest($url, $user, $pass))) { + if (self::$cacheDir) { + file_put_contents($cacheFile, $data); + } + } elseif (self::$cacheDir && $data = @file_get_contents($cacheFile)) { + // ok + } else { + throw new FeedException('Cannot load feed.'); + } + + $json = json_decode($data); + if(!$json){ + throw new FeedException('Cannot parse feed.'); + } + + return $json; + } + + /** * Process HTTP request. * @param string