public function items() { $feedURL = (string) $this->getRequiredTemplateVariable('FeedURL'); $nativeOrder = StringUtils::strToBool((string) $this->getTemplateVariable('NativeOrder')); $includeImage = StringUtils::strToBool((string) $this->getTemplateVariable('IncludeImage')); $maxRows = intval((string) $this->getRequiredTemplateVariable('MaxRows')); $items = array(); if (!URLUtils::isUrl($feedURL)) { return $items; } try { $feed = $this->FeedParser->parseFeed($feedURL, $nativeOrder); $i = 0; foreach ($feed->get_items() as $item) { if ($i >= $maxRows) { break; } if (trim($item->get_title()) == '') { continue; } $itemDate = null; if ($item->get_date() != '') { $itemDate = $this->DateFactory->newStorageDate($item->get_date()); } $img = null; if ($includeImage) { // first try to get it from the enclosure node itself $tags = $item->get_item_tags('', 'enclosure'); if (is_array($tags)) { foreach ($tags as $tag) { if (!isset($tag['attribs']['']['type'])) { continue; } if (strpos($tag['attribs']['']['type'], 'image') !== false) { $img = isset($tag['attribs']['']['url']) ? $tag['attribs']['']['url'] : null; break; } } } if (empty($img)) { $enclosure = $item->get_enclosure(); if ($enclosure) { $img = $enclosure->get_thumbnail(); if (empty($img)) { $img = $enclosure->get_link(); } } } } $items[] = array('Permalink' => $item->get_permalink(), 'Title' => $item->get_title(), 'Description' => $item->get_description(), 'PublishDate' => $itemDate, 'Image' => $img); $i++; } } catch (FeedParserException $fpe) { $this->Logger->debug($fpe->getMessage()); } return $items; }
/** * Calls an rss feed and returns up to $count rows from that feed. * Feeds are stored in cache but passing a different count will not store * a new cache entry, it will simply return that number of items from the * cached feed. * * Count is not guaranteed to be returned if the feed doesn't supply that * many items. * * Returns a simple array of the feed and its items * * <code> * array( * 'status' => 200, * 'permalink' => '', * 'title' => '', * 'description' => '', * 'timestamp' => '', * 'item_count' => '', * 'items' => array( * 'permalink' => '' * 'title' => '' * 'description' => '' * 'image' => '' * ) * ); * </code> * * @param string $feedURL the full url to an rss feed. * @param int $count number of items to return from the feed * @param bool $nativeOrder sets the order the feed items are returned in @see SimplePie * @param int $itemLimit total number of items from the feed to store * * @return array * * @throws \InvalidArgumentException */ public function getFeed($feedURL, $count = 25, $nativeOrder = false, $itemLimit = 100) { if (!\URLUtils::isUrl($feedURL)) { return array('status' => 404, 'item_count' => 0, 'items' => array()); } if ($count > $itemLimit) { throw new \InvalidArgumentException('Count cannot be greater than the item limit.'); } $cacheKey = $this->cacheKey($feedURL . ($nativeOrder ? ':nativeorder' : '') . ':' . $itemLimit); $this->logger->info("Lookup for key [{$cacheKey}]"); $feed = $this->cacheStore->get($cacheKey); if (is_array($feed)) { $this->logger->info("Found feed in cache for key [{$cacheKey}]"); $feed['items'] = array_slice($feed['items'], 0, $count); return $feed; } try { $this->logger->info("Calling feed [{$feedURL}]"); /* @var \SimplePie $rawFeed */ $rawFeed = $this->feedParser->parseFeed($feedURL, $nativeOrder); if ($publishDate = $rawFeed->get_channel_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'pubDate')) { $publishDate = $this->dateFactory->newStorageDate($publishDate[0]['data'])->toUnix(); } else { $publishDate = null; } $feed = array('status' => 200, 'permalink' => $rawFeed->get_permalink(), 'title' => trim($rawFeed->get_title()), 'description' => trim($rawFeed->get_description()), 'timestamp' => $publishDate, 'item_count' => $rawFeed->get_item_quantity(), 'items' => array()); $this->logger->debug($feed); $i = 0; /* @var \SimplePie_Item $item */ foreach ($rawFeed->get_items() as $item) { if ($i >= $itemLimit) { break; } if (trim($item->get_title()) == '') { continue; } $itemDate = null; if ($item->get_date() != '') { $itemDate = $this->dateFactory->newStorageDate($item->get_date())->toUnix(); } $img = null; // first try to get it from the enclosure node itself $tags = $item->get_item_tags('', 'enclosure'); if (is_array($tags)) { foreach ($tags as $tag) { if (!isset($tag['attribs']['']['type'])) { continue; } if (strpos($tag['attribs']['']['type'], 'image') !== false) { $img = isset($tag['attribs']['']['url']) ? $tag['attribs']['']['url'] : null; break; } } } if (empty($img)) { /* @var \SimplePie_Enclosure $enclosure */ $enclosure = $item->get_enclosure(); if ($enclosure) { $img = $enclosure->get_thumbnail(); if (empty($img)) { $img = $enclosure->get_link(); } } } $feed['items'][] = array('permalink' => $item->get_permalink(), 'title' => $item->get_title(), 'description' => $item->get_description(), 'timestamp' => $itemDate, 'image' => $img); $i++; } } catch (\FeedParserException $fpe) { $this->logger->error($fpe->getMessage()); $feed = array('status' => $fpe->getCode(), 'item_count' => 0, 'items' => array()); } catch (\Exception $e) { $this->logger->error($e->getMessage()); $feed = array('status' => $e->getCode(), 'item_count' => 0, 'items' => array()); } $this->logger->info("Putting feed into cache with key [{$cacheKey}] and ttl of [{$this->cacheTtl}]"); $this->cacheStore->put($cacheKey, $feed, $this->cacheTtl); $feed['items'] = array_slice($feed['items'], 0, $count); return $feed; }
/** * Returns TRUE if the given value passes validation. * * @param string $value A value to test * * @return boolean */ public function isValid($value) { if ($this->skipValidation) { return true; } $datatype = $this->validation['datatype']; //NULL check, empty strings are considered null if (in_array($datatype, array('string', 'url', 'email', 'slug', 'slugwithslash', 'html', 'binary', 'json')) && strlen(trim($value)) == 0) { $value = null; } if ($this->validation['nullable'] === false && $value === null && $datatype != 'boolean') { $this->failureCode = 'nullable'; $this->failureMessage = 'cannot be empty'; return false; } //Nothing more to validate if the value is null... if ($value === null) { return true; } //Check date makes sense if ($datatype === 'date') { //todo: not sure how to check validity of date... it's already a DateTime instance. if (false) { $this->failureCode = 'invalid'; $this->failureMessage = 'is an invalid date'; return false; } } //Validate MIN $min = $this->validation['min']; if ($min != null) { if ($datatype === 'float') { if ($value < floatval($min)) { $this->failureCode = 'min'; $this->failureMessage = 'is less than the minimum value'; return false; } } else { if ($datatype === 'int') { if ($value < intval($min)) { $this->failureCode = 'min'; $this->failureMessage = 'is less than the minimum value'; return false; } } else { if (is_string($value) && strlen($value) < intval($min)) { $this->failureCode = 'minlength'; $this->failureMessage = 'must be at least ' . $min . ' characters'; return false; } } } } //Validate MAX $max = $this->validation['max']; if ($max != null) { if ($datatype === 'float') { if ($value > floatval($max)) { $this->failureCode = 'max'; $this->failureMessage = 'is more than the maximum value'; return false; } } else { if ($datatype === 'int') { if ($value > intval($max)) { $this->failureCode = 'max'; $this->failureMessage = 'is more than the maximum value'; return false; } } else { $maxbytes = intval($max); if (intval($max) < 255) { // count characters if (is_string($value) && StringUtils::charCount($value) > intval($max)) { $this->failureCode = 'maxlength'; $this->failureMessage = 'must be a maximum of ' . $max . ' characters'; return false; } $maxbytes = 255; } // count bytes if (is_string($value) && StringUtils::byteCount($value) > intval($maxbytes)) { $this->failureCode = 'maxlength'; $this->failureMessage = 'must be a maximum of ' . $maxbytes . ' bytes'; return false; } } } } if ($datatype === 'slug') { if (!SlugUtils::isSlug($value, false)) { $this->failureCode = 'invalid'; $this->failureMessage = 'is not a valid slug, cannot contain slashes'; return false; } } if ($datatype === 'slugwithslash') { if (!SlugUtils::isSlug($value, true)) { $this->failureCode = 'invalid'; $this->failureMessage = 'is not a valid slug'; return false; } } if ($datatype === 'url') { if (!URLUtils::isUrl($value)) { $this->failureCode = 'invalid'; $this->failureMessage = 'is not a valid URL'; return false; } } if ($datatype === 'email') { if (!EmailUtils::isEmailAddress($value)) { $this->failureCode = 'invalid'; $this->failureMessage = 'is not a valid email address'; return false; } } if ($datatype === 'json') { if (!JSONUtils::isValid($value)) { $this->failureCode = 'invalid'; $this->failureMessage = 'is not a valid json string'; return false; } } //Validate MATCH expression $match = $this->validation['match']; if ($match != null) { // Automatically escape unescaped slashes in the match before running it $match = preg_replace('/([^\\\\])\\//', '$1\\/', $match); if (preg_match('/' . $match . '/s', $value) === 0) { $this->failureCode = 'invalid'; //$this->failureMessage = 'is invalid (' . substr($value, 0, 255) . ')'; $this->failureMessage = 'is invalid'; return false; } } // Validate all custom functions foreach ($this->validation['callback'] as $callback) { if (!empty($callback) && call_user_func($callback, $value) === false) { $this->failureCode = $callback; $this->failureMessage = 'is invalid'; return false; } } return true; }