/**
  * Fetch data from cache or external API.
  *
  * @param string $action Action
  * @param array  $params Query parameters
  *
  * @return mixed result or false on error.
  */
 protected function fetchData($action, $params)
 {
     $params['limit'] = 1000;
     $url = $this->config->General->url . '/' . $action . '?' . http_build_query($params);
     $cacheDir = $this->cacheManager->getCache('organisation-info')->getOptions()->getCacheDir();
     $localFile = "{$cacheDir}/" . md5($url) . '.json';
     $maxAge = isset($this->config->General->cachetime) ? $this->config->General->cachetime : 10;
     $response = false;
     if ($maxAge) {
         if (is_readable($localFile) && time() - filemtime($localFile) < $maxAge * 60) {
             $response = file_get_contents($localFile);
         }
     }
     if (!$response) {
         $client = $this->http->createClient($url);
         $result = $client->setMethod('GET')->send();
         if ($result->isSuccess()) {
             if ($result->getStatusCode() != 200) {
                 $this->logError('Error querying organisation info, response code ' . $result->getStatusCode() . ", url: {$url}");
                 return false;
             }
         } else {
             $this->logError('Error querying organisation info: ' . $result->getStatusCode() . ': ' . $result->getReasonPhrase() . ", url: {$url}");
             return false;
         }
         $response = $result->getBody();
         if ($maxAge) {
             file_put_contents($localFile, $response);
         }
     }
     if (!$response) {
         return false;
     }
     $response = json_decode($response, true);
     $jsonError = json_last_error();
     if ($jsonError !== JSON_ERROR_NONE) {
         $this->logError("Error decoding JSON: {$jsonError} (url: {$url})");
         return false;
     }
     return $response;
 }
Example #2
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');
 }