/** * Detect the feed type of the provided feed * * @param Feed\AbstractFeed|DOMDocument|string $feed * @param bool $specOnly * @return string * @throws Exception\InvalidArgumentException * @throws Exception\RuntimeException */ public static function detectType($feed, $specOnly = false) { if ($feed instanceof Feed\AbstractFeed) { $dom = $feed->getDomDocument(); } elseif ($feed instanceof DOMDocument) { $dom = $feed; } elseif (is_string($feed) && !empty($feed)) { ErrorHandler::start(E_NOTICE | E_WARNING); ini_set('track_errors', 1); $oldValue = libxml_disable_entity_loader(true); $dom = new DOMDocument(); $status = $dom->loadXML($feed); foreach ($dom->childNodes as $child) { if ($child->nodeType === XML_DOCUMENT_TYPE_NODE) { throw new Exception\InvalidArgumentException('Invalid XML: Detected use of illegal DOCTYPE'); } } libxml_disable_entity_loader($oldValue); ini_restore('track_errors'); ErrorHandler::stop(); if (!$status) { if (!isset($phpErrormsg)) { if (function_exists('xdebug_is_enabled')) { $phpErrormsg = '(error message not available, when XDebug is running)'; } else { $phpErrormsg = '(error message not available)'; } } throw new Exception\RuntimeException("DOMDocument cannot parse XML: {$phpErrormsg}"); } } else { throw new Exception\InvalidArgumentException('Invalid object/scalar provided: must' . ' be of type Zend\\Feed\\Reader\\Feed, DomDocument or string'); } $xpath = new DOMXPath($dom); if ($xpath->query('/rss')->length) { $type = self::TYPE_RSS_ANY; $version = $xpath->evaluate('string(/rss/@version)'); if (strlen($version) > 0) { switch ($version) { case '2.0': $type = self::TYPE_RSS_20; break; case '0.94': $type = self::TYPE_RSS_094; break; case '0.93': $type = self::TYPE_RSS_093; break; case '0.92': $type = self::TYPE_RSS_092; break; case '0.91': $type = self::TYPE_RSS_091; break; } } return $type; } $xpath->registerNamespace('rdf', self::NAMESPACE_RDF); if ($xpath->query('/rdf:RDF')->length) { $xpath->registerNamespace('rss', self::NAMESPACE_RSS_10); if ($xpath->query('/rdf:RDF/rss:channel')->length || $xpath->query('/rdf:RDF/rss:image')->length || $xpath->query('/rdf:RDF/rss:item')->length || $xpath->query('/rdf:RDF/rss:textinput')->length) { return self::TYPE_RSS_10; } $xpath->registerNamespace('rss', self::NAMESPACE_RSS_090); if ($xpath->query('/rdf:RDF/rss:channel')->length || $xpath->query('/rdf:RDF/rss:image')->length || $xpath->query('/rdf:RDF/rss:item')->length || $xpath->query('/rdf:RDF/rss:textinput')->length) { return self::TYPE_RSS_090; } } $xpath->registerNamespace('atom', self::NAMESPACE_ATOM_10); if ($xpath->query('//atom:feed')->length) { return self::TYPE_ATOM_10; } if ($xpath->query('//atom:entry')->length) { if ($specOnly == true) { return self::TYPE_ATOM_10; } else { return self::TYPE_ATOM_10_ENTRY; } } $xpath->registerNamespace('atom', self::NAMESPACE_ATOM_03); if ($xpath->query('//atom:feed')->length) { return self::TYPE_ATOM_03; } return self::TYPE_ANY; }
/** * Detect the feed type of the provided feed * * @param Feed\AbstractFeed|DOMDocument|string $feed * @return string * @throws Exception\ExceptionInterface */ public static function detectType($feed, $specOnly = false) { if ($feed instanceof Feed\AbstractFeed) { $dom = $feed->getDomDocument(); } elseif($feed instanceof DOMDocument) { $dom = $feed; } elseif(is_string($feed) && !empty($feed)) { @ini_set('track_errors', 1); $dom = new DOMDocument; $status = @$dom->loadXML($feed); @ini_restore('track_errors'); if (!$status) { if (!isset($php_errormsg)) { if (function_exists('xdebug_is_enabled')) { $php_errormsg = '(error message not available, when XDebug is running)'; } else { $php_errormsg = '(error message not available)'; } } throw new Exception\RuntimeException("DOMDocument cannot parse XML: $php_errormsg"); } } else { throw new Exception\InvalidArgumentException('Invalid object/scalar provided: must' . ' be of type Zend\Feed\Reader\Feed, DomDocument or string'); } $xpath = new DOMXPath($dom); if ($xpath->query('/rss')->length) { $type = self::TYPE_RSS_ANY; $version = $xpath->evaluate('string(/rss/@version)'); if (strlen($version) > 0) { switch($version) { case '2.0': $type = self::TYPE_RSS_20; break; case '0.94': $type = self::TYPE_RSS_094; break; case '0.93': $type = self::TYPE_RSS_093; break; case '0.92': $type = self::TYPE_RSS_092; break; case '0.91': $type = self::TYPE_RSS_091; break; } } return $type; } $xpath->registerNamespace('rdf', self::NAMESPACE_RDF); if ($xpath->query('/rdf:RDF')->length) { $xpath->registerNamespace('rss', self::NAMESPACE_RSS_10); if ($xpath->query('/rdf:RDF/rss:channel')->length || $xpath->query('/rdf:RDF/rss:image')->length || $xpath->query('/rdf:RDF/rss:item')->length || $xpath->query('/rdf:RDF/rss:textinput')->length ) { return self::TYPE_RSS_10; } $xpath->registerNamespace('rss', self::NAMESPACE_RSS_090); if ($xpath->query('/rdf:RDF/rss:channel')->length || $xpath->query('/rdf:RDF/rss:image')->length || $xpath->query('/rdf:RDF/rss:item')->length || $xpath->query('/rdf:RDF/rss:textinput')->length ) { return self::TYPE_RSS_090; } } $type = self::TYPE_ATOM_ANY; $xpath->registerNamespace('atom', self::NAMESPACE_ATOM_10); if ($xpath->query('//atom:feed')->length) { return self::TYPE_ATOM_10; } if ($xpath->query('//atom:entry')->length) { if ($specOnly == true) { return self::TYPE_ATOM_10; } else { return self::TYPE_ATOM_10_ENTRY; } } $xpath->registerNamespace('atom', self::NAMESPACE_ATOM_03); if ($xpath->query('//atom:feed')->length) { return self::TYPE_ATOM_03; } return self::TYPE_ANY; }