/** * 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; }
/** * 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'); }