Esempio n. 1
0
 public function testCanDetectHubs()
 {
     $feed = \Zend\Feed\Reader\Reader::importFile(__DIR__ . '/_files/rss20.xml');
     $this->assertEquals(array(
         'http://www.example.com/hub', 'http://www.example.com/hub2'
     ), PubSubHubbub\PubSubHubbub::detectHubs($feed));
 }
Esempio n. 2
0
 /**
  * Loads feed from an url or file path
  *
  * @param string $file
  *
  * @return Reader
  */
 public function load($file)
 {
     if (file_exists($file)) {
         $this->feed = ZendReader::importFile($file);
     } else {
         $this->feed = ZendReader::import($file);
     }
     return $this;
 }
Esempio n. 3
0
<?php

use Zend\Feed\Reader\Reader;
require_once __DIR__ . '/../vendor/autoload.php';
if ($argc != 5) {
    printf("[%s] Invalid arguments (requires 4, received %d)\n", $argv[0], $argc);
    printf("Usage:\n    %s [blog-rss] [security-config] [template] [homepage-path]\n", $argv[0]);
    exit(1);
}
$blogRssPath = $argv[1];
$securityConfigPath = $argv[2];
$template = $argv[3];
$homepagePath = $argv[4];
$items = array();
$max = 4;
$feed = Reader::importFile($blogRssPath);
$count = 0;
foreach ($feed as $item) {
    $items[] = array('title' => $item->getTitle(), 'href' => $item->getLink(), 'date' => $item->getDateCreated());
    $count += 1;
    if ($count == $max) {
        break;
    }
}
$securityConfig = (include $securityConfigPath);
$count = 0;
foreach ($securityConfig['security']['advisories'] as $issue => $item) {
    $items[] = array('title' => $item['title'], 'href' => sprintf('/security/advisory/%s', $issue), 'date' => DateTime::createFromFormat('D, d F Y H:i:s O', $item['date']));
    $count += 1;
    if ($count == $max) {
        break;
Esempio n. 4
0
 public function testImportsFile()
 {
     try {
         $feed = Reader\Reader::importFile(__DIR__ . '/Reader/Entry/_files/Atom/title/plain/atom10.xml');
     } catch (\Exception $e) {
         $this->fail($e->getMessage());
     }
 }
Esempio n. 5
0
 public function testImportsFile()
 {
     $feed = Reader\Reader::importFile(dirname(__FILE__) . '/Entry/_files/Atom/title/plain/atom10.xml');
     $this->assertInstanceOf('Zend\\Feed\\Reader\\Feed\\FeedInterface', $feed);
 }
Esempio n. 6
0
 /**
  * Return feed content and settings in JSON format.
  *
  * @return mixed
  */
 public function getFeedAjax()
 {
     if (!($id = $this->params()->fromQuery('id'))) {
         return $this->output('Missing feed id', self::STATUS_ERROR);
     }
     $touchDevice = $this->params()->fromQuery('touch-device') !== null ? $this->params()->fromQuery('touch-device') === '1' : false;
     $config = $this->getServiceLocator()->get('VuFind\\Config')->get('rss');
     if (!isset($config[$id])) {
         return $this->output('Missing feed configuration', self::STATUS_ERROR);
     }
     $config = $config[$id];
     if (!$config->active) {
         return $this->output('Feed inactive', self::STATUS_ERROR);
     }
     if (!($url = $config->url)) {
         return $this->output('Missing feed URL', self::STATUS_ERROR);
     }
     $translator = $this->getServiceLocator()->get('VuFind\\Translator');
     $language = $translator->getLocale();
     if (isset($url[$language])) {
         $url = trim($url[$language]);
     } else {
         if (isset($url['*'])) {
             $url = trim($url['*']);
         } else {
             return $this->output('Missing feed URL', self::STATUS_ERROR);
         }
     }
     $type = $config->type;
     $channel = null;
     // Check for cached version
     $cacheEnabled = false;
     $cacheDir = $this->getServiceLocator()->get('VuFind\\CacheManager')->getCache('feed')->getOptions()->getCacheDir();
     $cacheKey = $config->toArray();
     $cacheKey['language'] = $language;
     $localFile = "{$cacheDir}/" . md5(var_export($cacheKey, true)) . '.xml';
     $cacheConfig = $this->getServiceLocator()->get('VuFind\\Config')->get('config');
     $maxAge = isset($cacheConfig->Content->feedcachetime) ? $cacheConfig->Content->feedcachetime : false;
     $httpService = $this->getServiceLocator()->get('VuFind\\Http');
     Reader::setHttpClient($httpService->createClient());
     if ($maxAge) {
         $cacheEnabled = true;
         if (is_readable($localFile) && time() - filemtime($localFile) < $maxAge * 60) {
             $channel = Reader::importFile($localFile);
         }
     }
     if (!$channel) {
         // No cache available, read from source.
         if (preg_match('/^http(s)?:\\/\\//', $url)) {
             // Absolute URL
             $channel = Reader::import($url);
         } else {
             if (substr($url, 0, 1) === '/') {
                 // Relative URL
                 $url = substr($this->getServerUrl('home'), 0, -1) . $url;
                 $channel = Reader::import($url);
             } else {
                 // Local file
                 if (!is_file($url)) {
                     return $this->output("File {$url} could not be found", self::STATUS_ERROR);
                 }
                 $channel = Reader::importFile($url);
             }
         }
     }
     if (!$channel) {
         return $this->output('Parsing failed', self::STATUS_ERROR);
     }
     if ($cacheEnabled) {
         file_put_contents($localFile, $channel->saveXml());
     }
     $content = ['title' => 'getTitle', 'text' => 'getContent', 'image' => 'getEnclosure', 'link' => 'getLink', 'date' => 'getDateCreated'];
     $dateFormat = isset($config->dateFormat) ? $config->dateFormat : 'j.n.';
     $itemsCnt = isset($config->items) ? $config->items : null;
     $items = [];
     foreach ($channel as $item) {
         $data = [];
         foreach ($content as $setting => $method) {
             if (!isset($config->content[$setting]) || $config->content[$setting] != 0) {
                 $tmp = $item->{$method}();
                 if (is_object($tmp)) {
                     $tmp = get_object_vars($tmp);
                 }
                 if ($setting == 'image') {
                     if (!$tmp || stripos($tmp['type'], 'image') === false) {
                         // Attempt to parse image URL from content
                         if ($tmp = $this->extractImage($item->getContent())) {
                             $tmp = ['url' => $tmp];
                         }
                     }
                 } else {
                     if ($setting == 'date') {
                         if (isset($tmp['date'])) {
                             $tmp = new \DateTime($tmp['date']);
                             $tmp = $tmp->format($dateFormat);
                         }
                     } else {
                         if (is_string($tmp)) {
                             $tmp = strip_tags($tmp);
                         }
                     }
                 }
                 if ($tmp) {
                     $data[$setting] = $tmp;
                 }
             }
         }
         // Make sure that we have something to display
         $accept = $data['title'] && trim($data['title']) != '' || $data['text'] && trim($data['text']) != '' || $data['image'];
         if (!$accept) {
             continue;
         }
         $items[] = $data;
         if ($itemsCnt !== null) {
             if (--$itemsCnt === 0) {
                 break;
             }
         }
     }
     $images = isset($config->content['image']) ? $config->content['image'] : true;
     $moreLink = !isset($config->moreLink) || $config->moreLink ? $channel->getLink() : null;
     $key = $touchDevice ? 'touch' : 'desktop';
     $linkText = null;
     if (isset($config->linkText[$key])) {
         $linkText = $config->linkText[$key];
     } else {
         if (isset($config->linkText) && is_string($config->linkText)) {
             $linkText = $config->linkText;
         }
     }
     $feed = ['linkText' => $linkText, 'moreLink' => $moreLink, 'type' => $type, 'items' => $items, 'touchDevice' => $touchDevice, 'images' => $images];
     if (isset($config->title)) {
         if ($config->title == 'rss') {
             $feed['title'] = $channel->getTitle();
         } else {
             $feed['translateTitle'] = $config->title;
         }
     }
     if (isset($config->linkTarget)) {
         $feed['linkTarget'] = $config->linkTarget;
     }
     $template = $type == 'list' ? 'list' : 'carousel';
     $html = $this->getViewRenderer()->partial("ajax/feed-{$template}.phtml", $feed);
     $settings = [];
     $settings['type'] = $type;
     if (isset($config->height)) {
         $settings['height'] = $config->height;
     }
     if ($type == 'carousel' || $type == 'carousel-vertical') {
         $settings['images'] = $images;
         $settings['autoplay'] = isset($config->autoplay) ? $config->autoplay : false;
         $settings['dots'] = isset($config->dots) ? $config->dots == true : true;
         $breakPoints = ['desktop' => 4, 'desktop-small' => 3, 'tablet' => 2, 'mobile' => 1];
         foreach ($breakPoints as $breakPoint => $default) {
             $settings['slidesToShow'][$breakPoint] = isset($config->itemsPerPage[$breakPoint]) ? (int) $config->itemsPerPage[$breakPoint] : $default;
             $settings['scrolledItems'][$breakPoint] = isset($config->scrolledItems[$breakPoint]) ? (int) $config->scrolledItems[$breakPoint] : $settings['slidesToShow'][$breakPoint];
         }
         if ($type == 'carousel') {
             $settings['titlePosition'] = isset($config->titlePosition) ? $config->titlePosition : null;
         }
     }
     $res = ['html' => $html, 'settings' => $settings];
     return $this->output($res, self::STATUS_OK);
 }
Esempio n. 7
0
 /**
  * Utility function for processing a feed (see readFeed, readFeedFromUrl).
  *
  * @param array                          $feedConfig Configuration
  * @param Zend\Mvc\Controller\Plugin\Url $urlHelper  Url helper
  * @param string                         $viewUrl    View URL
  * @param string                         $id         Feed id (needed when the
  * feed content is shown on a content page or in a modal)
  *
  * @return mixed null|array
  */
 protected function processReadFeed($feedConfig, $urlHelper, $viewUrl, $id = null)
 {
     $config = $feedConfig['result'];
     $url = $feedConfig['url'];
     $type = $config->type;
     $cacheKey = $config->toArray();
     $cacheKey['language'] = $this->translator->getLocale();
     $modal = false;
     $showFullContentOnSite = isset($config->linkTo) && in_array($config->linkTo, ['modal', 'content-page']);
     $modal = $config->linkTo == 'modal';
     $contentPage = $config->linkTo == 'content-page';
     $dateFormat = isset($config->dateFormat) ? $config->dateFormat : 'j.n.';
     $contentDateFormat = isset($config->contentDateFormat) ? $config->contentDateFormat : 'j.n.Y';
     $itemsCnt = isset($config->items) ? $config->items : null;
     $elements = isset($config->content) ? $config->content : [];
     $channel = null;
     // Check for cached version
     $cacheDir = $this->cacheManager->getCache('feed')->getOptions()->getCacheDir();
     $localFile = "{$cacheDir}/" . md5(var_export($cacheKey, true)) . '.xml';
     $maxAge = isset($this->mainConfig->Content->feedcachetime) ? $this->mainConfig->Content->feedcachetime : 10;
     Reader::setHttpClient($this->http->createClient());
     if ($maxAge) {
         if (is_readable($localFile) && time() - filemtime($localFile) < $maxAge * 60) {
             $channel = Reader::importFile($localFile);
         }
     }
     if (!$channel) {
         // No cache available, read from source.
         if (preg_match('/^http(s)?:\\/\\//', $url)) {
             // Absolute URL
             $channel = Reader::import($url);
         } else {
             if (substr($url, 0, 1) === '/') {
                 // Relative URL
                 $url = substr($viewUrl, 0, -1) . $url;
                 try {
                     $channel = Reader::import($url);
                 } catch (\Exception $e) {
                     $this->logError("Error importing feed from url {$url}");
                     $this->logError("   " . $e->getMessage());
                 }
             } else {
                 // Local file
                 if (!is_file($url)) {
                     $this->logError("File {$url} could not be found");
                     throw new \Exception('Error reading feed');
                 }
                 $channel = Reader::importFile($url);
             }
         }
         if ($channel) {
             file_put_contents($localFile, $channel->saveXml());
         }
     }
     if (!$channel) {
         return false;
     }
     $content = ['title' => 'getTitle', 'text' => 'getContent', 'image' => 'getEnclosure', 'link' => 'getLink', 'date' => 'getDateCreated', 'contentDate' => 'getDateCreated'];
     $xpathContent = ['html' => '//item/content:encoded'];
     $items = [];
     $cnt = 0;
     $xpath = null;
     $cnt = 0;
     foreach ($channel as $item) {
         if (!$xpath) {
             $xpath = $item->getXpath();
         }
         $data = [];
         $data['modal'] = $modal;
         foreach ($content as $setting => $method) {
             if (!isset($elements[$setting]) || $elements[$setting] != 0) {
                 $value = $item->{$method}();
                 if (is_object($value)) {
                     $value = get_object_vars($value);
                 }
                 if ($setting == 'image') {
                     if (!$value || stripos($value['type'], 'image') === false) {
                         // Attempt to parse image URL from content
                         if ($value = $this->extractImage($item->getContent())) {
                             $value = ['url' => $value];
                         }
                     }
                 } else {
                     if ($setting == 'date') {
                         if (isset($value['date'])) {
                             $value = new \DateTime($value['date']);
                             if ($dateFormat) {
                                 $value = $value->format($dateFormat);
                             }
                         }
                     } else {
                         if ($setting == 'contentDate') {
                             if (isset($value['date'])) {
                                 $value = new \DateTime($value['date']);
                                 if ($contentDateFormat) {
                                     $value = $value->format($contentDateFormat);
                                 }
                             }
                         } else {
                             if ($setting == 'link' && $showFullContentOnSite) {
                                 $link = $urlHelper->fromRoute('feed-content-page', ['page' => $id, 'element' => $cnt]);
                                 $value = $link;
                             } else {
                                 if (is_string($value)) {
                                     $value = strip_tags($value);
                                 }
                             }
                         }
                     }
                 }
                 if ($value) {
                     $data[$setting] = $value;
                 }
             }
         }
         // Make sure that we have something to display
         $accept = $data['title'] && trim($data['title']) != '' || $data['text'] && trim($data['text']) != '' || $data['image'];
         if (!$accept) {
             continue;
         }
         $items[] = $data;
         $cnt++;
         if ($itemsCnt !== null && $cnt == $itemsCnt) {
             break;
         }
     }
     if ($xpath && !empty($xpathContent)) {
         if ($xpathItem = $xpath->query('//item/content:encoded')->item(0)) {
             $contentSearch = isset($config->htmlContentSearch) ? $config->htmlContentSearch->toArray() : [];
             $contentReplace = isset($config->htmlContentReplace) ? $config->htmlContentReplace->toArray() : [];
             $searchReplace = array_combine($contentSearch, $contentReplace);
             $cnt = 0;
             foreach ($items as &$item) {
                 foreach ($xpathContent as $setting => $xpathElement) {
                     $content = $xpath->query($xpathElement, $xpathItem)->item($cnt++)->nodeValue;
                     // Remove width & height declarations from style
                     // attributes in div & p elements
                     $dom = new \DOMDocument();
                     libxml_use_internal_errors(true);
                     $dom->loadHTML(mb_convert_encoding($content, 'HTML-ENTITIES', 'UTF-8'));
                     $domx = new \DOMXPath($dom);
                     $elements = $domx->query('//div[@style]|//p[@style]');
                     foreach ($elements as $el) {
                         $styleProperties = [];
                         $styleAttr = $el->getAttribute('style');
                         $properties = explode(';', $styleAttr);
                         foreach ($properties as $prop) {
                             list($field, $val) = explode(':', $prop);
                             if (stristr($field, 'width') === false && stristr($field, 'height') === false && stristr($field, 'margin') === false) {
                                 $styleProperties[] = $prop;
                             }
                         }
                         $el->removeAttribute("style");
                         $el->setAttribute('style', implode(';', $styleProperties));
                     }
                     $content = $dom->saveHTML();
                     // Process feed specific search-replace regexes
                     foreach ($searchReplace as $search => $replace) {
                         $pattern = "/{$search}/";
                         $replaced = preg_replace($pattern, $replace, $content);
                         if ($replaced !== null) {
                             $content = $replaced;
                         }
                     }
                     $item[$setting] = $content;
                 }
             }
         }
     }
     return compact('channel', 'items', 'config', 'modal', 'contentPage');
 }