Chris@0: getAttribute('rel')) !== 'alternate' Chris@2: || ! $link->getAttribute('type') || ! $link->getAttribute('href')) { Chris@0: continue; Chris@0: } Chris@2: if (! isset($this->rss) && $link->getAttribute('type') == 'application/rss+xml') { Chris@0: $this->rss = $this->absolutiseUri(trim($link->getAttribute('href')), $uri); Chris@2: } elseif (! isset($this->atom) && $link->getAttribute('type') == 'application/atom+xml') { Chris@0: $this->atom = $this->absolutiseUri(trim($link->getAttribute('href')), $uri); Chris@2: } elseif (! isset($this->rdf) && $link->getAttribute('type') == 'application/rdf+xml') { Chris@0: $this->rdf = $this->absolutiseUri(trim($link->getAttribute('href')), $uri); Chris@0: } Chris@0: $this[] = new static([ Chris@0: 'rel' => 'alternate', Chris@0: 'type' => $link->getAttribute('type'), Chris@0: 'href' => $this->absolutiseUri(trim($link->getAttribute('href')), $uri), Chris@2: 'title' => $link->getAttribute('title'), Chris@0: ]); Chris@0: } Chris@0: } Chris@0: Chris@0: /** Chris@0: * Attempt to turn a relative URI into an absolute URI Chris@2: * Chris@2: * @param string $link Chris@2: * @param string $uri OPTIONAL Chris@2: * @return string|null absolutised link or null if invalid Chris@0: */ Chris@0: protected function absolutiseUri($link, $uri = null) Chris@0: { Chris@0: $linkUri = Uri::factory($link); Chris@2: if ($linkUri->isAbsolute()) { Chris@2: // invalid absolute link can not be recovered Chris@2: return $linkUri->isValid() ? $link : null; Chris@2: } Chris@0: Chris@2: $scheme = 'http'; Chris@2: if ($uri !== null) { Chris@2: $uri = Uri::factory($uri); Chris@2: $scheme = $uri->getScheme() ?: $scheme; Chris@2: } Chris@0: Chris@2: if ($linkUri->getHost()) { Chris@2: $link = $this->resolveSchemeRelativeUri($link, $scheme); Chris@2: } elseif ($uri !== null) { Chris@2: $link = $this->resolveRelativeUri($link, $scheme, $uri->getHost(), $uri->getPath()); Chris@2: } Chris@0: Chris@2: if (! Uri::factory($link)->isValid()) { Chris@2: return null; Chris@0: } Chris@2: Chris@0: return $link; Chris@0: } Chris@0: Chris@0: /** Chris@2: * Resolves scheme relative link to absolute Chris@2: * Chris@2: * @param string $link Chris@2: * @param string $scheme Chris@2: * @return string Chris@2: */ Chris@2: private function resolveSchemeRelativeUri($link, $scheme) Chris@2: { Chris@2: $link = ltrim($link, '/'); Chris@2: return sprintf('%s://%s', $scheme, $link); Chris@2: } Chris@2: Chris@2: /** Chris@2: * Resolves relative link to absolute Chris@2: * Chris@2: * @param string $link Chris@2: * @param string $scheme Chris@2: * @param string $host Chris@2: * @param string $uriPath Chris@2: * @return string Chris@2: */ Chris@2: private function resolveRelativeUri($link, $scheme, $host, $uriPath) Chris@2: { Chris@2: if ($link[0] !== '/') { Chris@2: $link = $uriPath . '/' . $link; Chris@2: } Chris@2: return sprintf( Chris@2: '%s://%s/%s', Chris@2: $scheme, Chris@2: $host, Chris@2: $this->canonicalizePath($link) Chris@2: ); Chris@2: } Chris@2: Chris@2: /** Chris@0: * Canonicalize relative path Chris@0: */ Chris@0: protected function canonicalizePath($path) Chris@0: { Chris@0: $parts = array_filter(explode('/', $path)); Chris@0: $absolutes = []; Chris@0: foreach ($parts as $part) { Chris@0: if ('.' == $part) { Chris@0: continue; Chris@0: } Chris@0: if ('..' == $part) { Chris@0: array_pop($absolutes); Chris@0: } else { Chris@0: $absolutes[] = $part; Chris@0: } Chris@0: } Chris@0: return implode('/', $absolutes); Chris@0: } Chris@0: Chris@0: /** Chris@0: * Supports lazy loading of feeds using Reader::import() but Chris@0: * delegates any other operations to the parent class. Chris@0: * Chris@0: * @param string $offset Chris@0: * @return mixed Chris@0: */ Chris@0: public function offsetGet($offset) Chris@0: { Chris@2: if ($offset == 'feed' && ! $this->offsetExists('feed')) { Chris@2: if (! $this->offsetExists('href')) { Chris@0: return; Chris@0: } Chris@0: $feed = Reader::import($this->offsetGet('href')); Chris@0: $this->offsetSet('feed', $feed); Chris@0: return $feed; Chris@0: } Chris@0: return parent::offsetGet($offset); Chris@0: } Chris@0: }