3 * Zend Framework (http://framework.zend.com/)
5 * @link http://github.com/zendframework/zf2 for the canonical source repository
6 * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com)
7 * @license http://framework.zend.com/license/new-bsd New BSD License
10 namespace Zend\Feed\Reader;
16 class FeedSet extends ArrayObject
25 * Import a DOMNodeList from any document containing a set of links
26 * for alternate versions of a document, which will normally refer to
27 * RSS/RDF/Atom feeds for the current document.
29 * All such links are stored internally, however the first instance of
30 * each RSS, RDF or Atom type has its URI stored as a public property
31 * as a shortcut where the use case is simply to get a quick feed ref.
33 * Note that feeds are not loaded at this point, but will be lazy
34 * loaded automatically when each links 'feed' array key is accessed.
36 * @param DOMNodeList $links
40 public function addLinks(DOMNodeList $links, $uri)
42 foreach ($links as $link) {
43 if (strtolower($link->getAttribute('rel')) !== 'alternate'
44 || ! $link->getAttribute('type') || ! $link->getAttribute('href')) {
47 if (! isset($this->rss) && $link->getAttribute('type') == 'application/rss+xml') {
48 $this->rss = $this->absolutiseUri(trim($link->getAttribute('href')), $uri);
49 } elseif (! isset($this->atom) && $link->getAttribute('type') == 'application/atom+xml') {
50 $this->atom = $this->absolutiseUri(trim($link->getAttribute('href')), $uri);
51 } elseif (! isset($this->rdf) && $link->getAttribute('type') == 'application/rdf+xml') {
52 $this->rdf = $this->absolutiseUri(trim($link->getAttribute('href')), $uri);
54 $this[] = new static([
56 'type' => $link->getAttribute('type'),
57 'href' => $this->absolutiseUri(trim($link->getAttribute('href')), $uri),
58 'title' => $link->getAttribute('title'),
64 * Attempt to turn a relative URI into an absolute URI
67 * @param string $uri OPTIONAL
68 * @return string|null absolutised link or null if invalid
70 protected function absolutiseUri($link, $uri = null)
72 $linkUri = Uri::factory($link);
73 if ($linkUri->isAbsolute()) {
74 // invalid absolute link can not be recovered
75 return $linkUri->isValid() ? $link : null;
80 $uri = Uri::factory($uri);
81 $scheme = $uri->getScheme() ?: $scheme;
84 if ($linkUri->getHost()) {
85 $link = $this->resolveSchemeRelativeUri($link, $scheme);
86 } elseif ($uri !== null) {
87 $link = $this->resolveRelativeUri($link, $scheme, $uri->getHost(), $uri->getPath());
90 if (! Uri::factory($link)->isValid()) {
98 * Resolves scheme relative link to absolute
100 * @param string $link
101 * @param string $scheme
104 private function resolveSchemeRelativeUri($link, $scheme)
106 $link = ltrim($link, '/');
107 return sprintf('%s://%s', $scheme, $link);
111 * Resolves relative link to absolute
113 * @param string $link
114 * @param string $scheme
115 * @param string $host
116 * @param string $uriPath
119 private function resolveRelativeUri($link, $scheme, $host, $uriPath)
121 if ($link[0] !== '/') {
122 $link = $uriPath . '/' . $link;
128 $this->canonicalizePath($link)
133 * Canonicalize relative path
135 protected function canonicalizePath($path)
137 $parts = array_filter(explode('/', $path));
139 foreach ($parts as $part) {
144 array_pop($absolutes);
146 $absolutes[] = $part;
149 return implode('/', $absolutes);
153 * Supports lazy loading of feeds using Reader::import() but
154 * delegates any other operations to the parent class.
156 * @param string $offset
159 public function offsetGet($offset)
161 if ($offset == 'feed' && ! $this->offsetExists('feed')) {
162 if (! $this->offsetExists('href')) {
165 $feed = Reader::import($this->offsetGet('href'));
166 $this->offsetSet('feed', $feed);
169 return parent::offsetGet($offset);