Chris@0: dom = new DOMDocument('1.0', $this->container->getEncoding()); Chris@0: $this->dom->formatOutput = true; Chris@0: $this->dom->substituteEntities = false; Chris@0: $rss = $this->dom->createElement('rss'); Chris@0: $this->setRootElement($rss); Chris@0: $rss->setAttribute('version', '2.0'); Chris@0: Chris@0: $channel = $this->dom->createElement('channel'); Chris@0: $rss->appendChild($channel); Chris@0: $this->dom->appendChild($rss); Chris@0: $this->_setLanguage($this->dom, $channel); Chris@0: $this->_setBaseUrl($this->dom, $channel); Chris@0: $this->_setTitle($this->dom, $channel); Chris@0: $this->_setDescription($this->dom, $channel); Chris@0: $this->_setImage($this->dom, $channel); Chris@0: $this->_setDateCreated($this->dom, $channel); Chris@0: $this->_setDateModified($this->dom, $channel); Chris@0: $this->_setLastBuildDate($this->dom, $channel); Chris@0: $this->_setGenerator($this->dom, $channel); Chris@0: $this->_setLink($this->dom, $channel); Chris@0: $this->_setAuthors($this->dom, $channel); Chris@0: $this->_setCopyright($this->dom, $channel); Chris@0: $this->_setCategories($this->dom, $channel); Chris@0: Chris@0: foreach ($this->extensions as $ext) { Chris@0: $ext->setType($this->getType()); Chris@0: $ext->setRootElement($this->getRootElement()); Chris@12: $ext->setDomDocument($this->getDomDocument(), $channel); Chris@0: $ext->render(); Chris@0: } Chris@0: Chris@0: foreach ($this->container as $entry) { Chris@0: if ($this->getDataContainer()->getEncoding()) { Chris@0: $entry->setEncoding($this->getDataContainer()->getEncoding()); Chris@0: } Chris@0: if ($entry instanceof Writer\Entry) { Chris@0: $renderer = new Renderer\Entry\Rss($entry); Chris@0: } else { Chris@0: continue; Chris@0: } Chris@0: if ($this->ignoreExceptions === true) { Chris@0: $renderer->ignoreExceptions(); Chris@0: } Chris@0: $renderer->setType($this->getType()); Chris@0: $renderer->setRootElement($this->dom->documentElement); Chris@0: $renderer->render(); Chris@0: $element = $renderer->getElement(); Chris@0: $deep = version_compare(PHP_VERSION, '7', 'ge') ? 1 : true; Chris@0: $imported = $this->dom->importNode($element, $deep); Chris@0: $channel->appendChild($imported); Chris@0: } Chris@0: return $this; Chris@0: } Chris@0: Chris@0: /** Chris@0: * Set feed language Chris@0: * Chris@0: * @param DOMDocument $dom Chris@0: * @param DOMElement $root Chris@0: * @return void Chris@0: */ Chris@12: // @codingStandardsIgnoreStart Chris@0: protected function _setLanguage(DOMDocument $dom, DOMElement $root) Chris@0: { Chris@12: // @codingStandardsIgnoreEnd Chris@0: $lang = $this->getDataContainer()->getLanguage(); Chris@12: if (! $lang) { Chris@0: return; Chris@0: } Chris@0: $language = $dom->createElement('language'); Chris@0: $root->appendChild($language); Chris@0: $language->nodeValue = $lang; Chris@0: } Chris@0: Chris@0: /** Chris@0: * Set feed title Chris@0: * Chris@0: * @param DOMDocument $dom Chris@0: * @param DOMElement $root Chris@0: * @return void Chris@0: * @throws Writer\Exception\InvalidArgumentException Chris@0: */ Chris@12: // @codingStandardsIgnoreStart Chris@0: protected function _setTitle(DOMDocument $dom, DOMElement $root) Chris@0: { Chris@12: // @codingStandardsIgnoreEnd Chris@12: if (! $this->getDataContainer()->getTitle()) { Chris@0: $message = 'RSS 2.0 feed elements MUST contain exactly one' Chris@0: . ' title element but a title has not been set'; Chris@0: $exception = new Writer\Exception\InvalidArgumentException($message); Chris@12: if (! $this->ignoreExceptions) { Chris@0: throw $exception; Chris@0: } else { Chris@0: $this->exceptions[] = $exception; Chris@0: return; Chris@0: } Chris@0: } Chris@0: Chris@0: $title = $dom->createElement('title'); Chris@0: $root->appendChild($title); Chris@0: $text = $dom->createTextNode($this->getDataContainer()->getTitle()); Chris@0: $title->appendChild($text); Chris@0: } Chris@0: Chris@0: /** Chris@0: * Set feed description Chris@0: * Chris@0: * @param DOMDocument $dom Chris@0: * @param DOMElement $root Chris@0: * @return void Chris@0: * @throws Writer\Exception\InvalidArgumentException Chris@0: */ Chris@12: // @codingStandardsIgnoreStart Chris@0: protected function _setDescription(DOMDocument $dom, DOMElement $root) Chris@0: { Chris@12: // @codingStandardsIgnoreEnd Chris@12: if (! $this->getDataContainer()->getDescription()) { Chris@0: $message = 'RSS 2.0 feed elements MUST contain exactly one' Chris@0: . ' description element but one has not been set'; Chris@0: $exception = new Writer\Exception\InvalidArgumentException($message); Chris@12: if (! $this->ignoreExceptions) { Chris@0: throw $exception; Chris@0: } else { Chris@0: $this->exceptions[] = $exception; Chris@0: return; Chris@0: } Chris@0: } Chris@0: $subtitle = $dom->createElement('description'); Chris@0: $root->appendChild($subtitle); Chris@0: $text = $dom->createTextNode($this->getDataContainer()->getDescription()); Chris@0: $subtitle->appendChild($text); Chris@0: } Chris@0: Chris@0: /** Chris@0: * Set date feed was last modified Chris@0: * Chris@0: * @param DOMDocument $dom Chris@0: * @param DOMElement $root Chris@0: * @return void Chris@0: */ Chris@12: // @codingStandardsIgnoreStart Chris@0: protected function _setDateModified(DOMDocument $dom, DOMElement $root) Chris@0: { Chris@12: // @codingStandardsIgnoreEnd Chris@12: if (! $this->getDataContainer()->getDateModified()) { Chris@0: return; Chris@0: } Chris@0: Chris@0: $updated = $dom->createElement('pubDate'); Chris@0: $root->appendChild($updated); Chris@0: $text = $dom->createTextNode( Chris@0: $this->getDataContainer()->getDateModified()->format(DateTime::RSS) Chris@0: ); Chris@0: $updated->appendChild($text); Chris@0: } Chris@0: Chris@0: /** Chris@0: * Set feed generator string Chris@0: * Chris@0: * @param DOMDocument $dom Chris@0: * @param DOMElement $root Chris@0: * @return void Chris@0: */ Chris@12: // @codingStandardsIgnoreStart Chris@0: protected function _setGenerator(DOMDocument $dom, DOMElement $root) Chris@0: { Chris@12: // @codingStandardsIgnoreEnd Chris@12: if (! $this->getDataContainer()->getGenerator()) { Chris@0: $this->getDataContainer()->setGenerator( Chris@0: 'Zend_Feed_Writer', Chris@0: Version::VERSION, Chris@0: 'http://framework.zend.com' Chris@0: ); Chris@0: } Chris@0: Chris@0: $gdata = $this->getDataContainer()->getGenerator(); Chris@0: $generator = $dom->createElement('generator'); Chris@0: $root->appendChild($generator); Chris@0: $name = $gdata['name']; Chris@0: if (array_key_exists('version', $gdata)) { Chris@0: $name .= ' ' . $gdata['version']; Chris@0: } Chris@0: if (array_key_exists('uri', $gdata)) { Chris@0: $name .= ' (' . $gdata['uri'] . ')'; Chris@0: } Chris@0: $text = $dom->createTextNode($name); Chris@0: $generator->appendChild($text); Chris@0: } Chris@0: Chris@0: /** Chris@0: * Set link to feed Chris@0: * Chris@0: * @param DOMDocument $dom Chris@0: * @param DOMElement $root Chris@0: * @return void Chris@0: * @throws Writer\Exception\InvalidArgumentException Chris@0: */ Chris@12: // @codingStandardsIgnoreStart Chris@0: protected function _setLink(DOMDocument $dom, DOMElement $root) Chris@0: { Chris@12: // @codingStandardsIgnoreEnd Chris@0: $value = $this->getDataContainer()->getLink(); Chris@12: if (! $value) { Chris@0: $message = 'RSS 2.0 feed elements MUST contain exactly one' Chris@0: . ' link element but one has not been set'; Chris@0: $exception = new Writer\Exception\InvalidArgumentException($message); Chris@12: if (! $this->ignoreExceptions) { Chris@0: throw $exception; Chris@0: } else { Chris@0: $this->exceptions[] = $exception; Chris@0: return; Chris@0: } Chris@0: } Chris@0: $link = $dom->createElement('link'); Chris@0: $root->appendChild($link); Chris@0: $text = $dom->createTextNode($value); Chris@0: $link->appendChild($text); Chris@12: if (! Uri::factory($value)->isValid()) { Chris@0: $link->setAttribute('isPermaLink', 'false'); Chris@0: } Chris@0: } Chris@0: Chris@0: /** Chris@0: * Set feed authors Chris@0: * Chris@0: * @param DOMDocument $dom Chris@0: * @param DOMElement $root Chris@0: * @return void Chris@0: */ Chris@12: // @codingStandardsIgnoreStart Chris@0: protected function _setAuthors(DOMDocument $dom, DOMElement $root) Chris@0: { Chris@12: // @codingStandardsIgnoreEnd Chris@0: $authors = $this->getDataContainer()->getAuthors(); Chris@12: if (! $authors || empty($authors)) { Chris@0: return; Chris@0: } Chris@0: foreach ($authors as $data) { Chris@0: $author = $this->dom->createElement('author'); Chris@0: $name = $data['name']; Chris@0: if (array_key_exists('email', $data)) { Chris@0: $name = $data['email'] . ' (' . $data['name'] . ')'; Chris@0: } Chris@0: $text = $dom->createTextNode($name); Chris@0: $author->appendChild($text); Chris@0: $root->appendChild($author); Chris@0: } Chris@0: } Chris@0: Chris@0: /** Chris@0: * Set feed copyright Chris@0: * Chris@0: * @param DOMDocument $dom Chris@0: * @param DOMElement $root Chris@0: * @return void Chris@0: */ Chris@12: // @codingStandardsIgnoreStart Chris@0: protected function _setCopyright(DOMDocument $dom, DOMElement $root) Chris@0: { Chris@12: // @codingStandardsIgnoreEnd Chris@0: $copyright = $this->getDataContainer()->getCopyright(); Chris@12: if (! $copyright) { Chris@0: return; Chris@0: } Chris@0: $copy = $dom->createElement('copyright'); Chris@0: $root->appendChild($copy); Chris@0: $text = $dom->createTextNode($copyright); Chris@0: $copy->appendChild($text); Chris@0: } Chris@0: Chris@0: /** Chris@0: * Set feed channel image Chris@0: * Chris@0: * @param DOMDocument $dom Chris@0: * @param DOMElement $root Chris@0: * @return void Chris@0: * @throws Writer\Exception\InvalidArgumentException Chris@0: */ Chris@12: // @codingStandardsIgnoreStart Chris@0: protected function _setImage(DOMDocument $dom, DOMElement $root) Chris@0: { Chris@12: // @codingStandardsIgnoreEnd Chris@0: $image = $this->getDataContainer()->getImage(); Chris@12: if (! $image) { Chris@0: return; Chris@0: } Chris@0: Chris@12: if (! isset($image['title']) || empty($image['title']) Chris@12: || ! is_string($image['title']) Chris@0: ) { Chris@0: $message = 'RSS 2.0 feed images must include a title'; Chris@0: $exception = new Writer\Exception\InvalidArgumentException($message); Chris@12: if (! $this->ignoreExceptions) { Chris@0: throw $exception; Chris@0: } else { Chris@0: $this->exceptions[] = $exception; Chris@0: return; Chris@0: } Chris@0: } Chris@0: Chris@12: if (empty($image['link']) || ! is_string($image['link']) Chris@12: || ! Uri::factory($image['link'])->isValid() Chris@0: ) { Chris@0: $message = 'Invalid parameter: parameter \'link\'' Chris@0: . ' must be a non-empty string and valid URI/IRI'; Chris@0: $exception = new Writer\Exception\InvalidArgumentException($message); Chris@12: if (! $this->ignoreExceptions) { Chris@0: throw $exception; Chris@0: } else { Chris@0: $this->exceptions[] = $exception; Chris@0: return; Chris@0: } Chris@0: } Chris@0: Chris@0: $img = $dom->createElement('image'); Chris@0: $root->appendChild($img); Chris@0: Chris@0: $url = $dom->createElement('url'); Chris@0: $text = $dom->createTextNode($image['uri']); Chris@0: $url->appendChild($text); Chris@0: Chris@0: $title = $dom->createElement('title'); Chris@0: $text = $dom->createTextNode($image['title']); Chris@0: $title->appendChild($text); Chris@0: Chris@0: $link = $dom->createElement('link'); Chris@0: $text = $dom->createTextNode($image['link']); Chris@0: $link->appendChild($text); Chris@0: Chris@0: $img->appendChild($url); Chris@0: $img->appendChild($title); Chris@0: $img->appendChild($link); Chris@0: Chris@0: if (isset($image['height'])) { Chris@12: if (! ctype_digit((string) $image['height']) || $image['height'] > 400) { Chris@0: $message = 'Invalid parameter: parameter \'height\'' Chris@0: . ' must be an integer not exceeding 400'; Chris@0: $exception = new Writer\Exception\InvalidArgumentException($message); Chris@12: if (! $this->ignoreExceptions) { Chris@0: throw $exception; Chris@0: } else { Chris@0: $this->exceptions[] = $exception; Chris@0: return; Chris@0: } Chris@0: } Chris@0: $height = $dom->createElement('height'); Chris@0: $text = $dom->createTextNode($image['height']); Chris@0: $height->appendChild($text); Chris@0: $img->appendChild($height); Chris@0: } Chris@0: if (isset($image['width'])) { Chris@12: if (! ctype_digit((string) $image['width']) || $image['width'] > 144) { Chris@0: $message = 'Invalid parameter: parameter \'width\'' Chris@0: . ' must be an integer not exceeding 144'; Chris@0: $exception = new Writer\Exception\InvalidArgumentException($message); Chris@12: if (! $this->ignoreExceptions) { Chris@0: throw $exception; Chris@0: } else { Chris@0: $this->exceptions[] = $exception; Chris@0: return; Chris@0: } Chris@0: } Chris@0: $width = $dom->createElement('width'); Chris@0: $text = $dom->createTextNode($image['width']); Chris@0: $width->appendChild($text); Chris@0: $img->appendChild($width); Chris@0: } Chris@0: if (isset($image['description'])) { Chris@12: if (empty($image['description']) || ! is_string($image['description'])) { Chris@0: $message = 'Invalid parameter: parameter \'description\'' Chris@0: . ' must be a non-empty string'; Chris@0: $exception = new Writer\Exception\InvalidArgumentException($message); Chris@12: if (! $this->ignoreExceptions) { Chris@0: throw $exception; Chris@0: } else { Chris@0: $this->exceptions[] = $exception; Chris@0: return; Chris@0: } Chris@0: } Chris@0: $desc = $dom->createElement('description'); Chris@0: $text = $dom->createTextNode($image['description']); Chris@0: $desc->appendChild($text); Chris@0: $img->appendChild($desc); Chris@0: } Chris@0: } Chris@0: Chris@0: /** Chris@0: * Set date feed was created Chris@0: * Chris@0: * @param DOMDocument $dom Chris@0: * @param DOMElement $root Chris@0: * @return void Chris@0: */ Chris@12: // @codingStandardsIgnoreStart Chris@0: protected function _setDateCreated(DOMDocument $dom, DOMElement $root) Chris@0: { Chris@12: // @codingStandardsIgnoreEnd Chris@12: if (! $this->getDataContainer()->getDateCreated()) { Chris@0: return; Chris@0: } Chris@12: if (! $this->getDataContainer()->getDateModified()) { Chris@0: $this->getDataContainer()->setDateModified( Chris@0: $this->getDataContainer()->getDateCreated() Chris@0: ); Chris@0: } Chris@0: } Chris@0: Chris@0: /** Chris@0: * Set date feed last build date Chris@0: * Chris@0: * @param DOMDocument $dom Chris@0: * @param DOMElement $root Chris@0: * @return void Chris@0: */ Chris@12: // @codingStandardsIgnoreStart Chris@0: protected function _setLastBuildDate(DOMDocument $dom, DOMElement $root) Chris@0: { Chris@12: // @codingStandardsIgnoreEnd Chris@12: if (! $this->getDataContainer()->getLastBuildDate()) { Chris@0: return; Chris@0: } Chris@0: Chris@0: $lastBuildDate = $dom->createElement('lastBuildDate'); Chris@0: $root->appendChild($lastBuildDate); Chris@0: $text = $dom->createTextNode( Chris@0: $this->getDataContainer()->getLastBuildDate()->format(DateTime::RSS) Chris@0: ); Chris@0: $lastBuildDate->appendChild($text); Chris@0: } Chris@0: Chris@0: /** Chris@0: * Set base URL to feed links Chris@0: * Chris@0: * @param DOMDocument $dom Chris@0: * @param DOMElement $root Chris@0: * @return void Chris@0: */ Chris@12: // @codingStandardsIgnoreStart Chris@0: protected function _setBaseUrl(DOMDocument $dom, DOMElement $root) Chris@0: { Chris@12: // @codingStandardsIgnoreEnd Chris@0: $baseUrl = $this->getDataContainer()->getBaseUrl(); Chris@12: if (! $baseUrl) { Chris@0: return; Chris@0: } Chris@0: $root->setAttribute('xml:base', $baseUrl); Chris@0: } Chris@0: Chris@0: /** Chris@0: * Set feed categories Chris@0: * Chris@0: * @param DOMDocument $dom Chris@0: * @param DOMElement $root Chris@0: * @return void Chris@0: */ Chris@12: // @codingStandardsIgnoreStart Chris@0: protected function _setCategories(DOMDocument $dom, DOMElement $root) Chris@0: { Chris@12: // @codingStandardsIgnoreEnd Chris@0: $categories = $this->getDataContainer()->getCategories(); Chris@12: if (! $categories) { Chris@0: return; Chris@0: } Chris@0: foreach ($categories as $cat) { Chris@0: $category = $dom->createElement('category'); Chris@0: if (isset($cat['scheme'])) { Chris@0: $category->setAttribute('domain', $cat['scheme']); Chris@0: } Chris@0: $text = $dom->createTextNode($cat['term']); Chris@0: $category->appendChild($text); Chris@0: $root->appendChild($category); Chris@0: } Chris@0: } Chris@0: }