/**
  * Handles (RSS & Atom) Type.FEED parsing using Zend's feed parser
  *
  * @param RemoteContentRequest $result
  * @param string $url
  * @param int $numEntries
  * @param boolean $getSummaries
  * @return response string, either a json encoded feed structure or an error message
  */
 private function parseFeed($result, $url, $numEntries = 3, $getSummaries = false)
 {
     require 'external/Zend/Feed.php';
     $channel = array();
     if ((int) $result->getHttpCode() == 200) {
         $content = $result->getResponseContent();
         try {
             $feed = Zend_Feed::importString($content);
             if ($feed instanceof Zend_Feed_Rss) {
                 // Try get author
                 if ($feed->author()) {
                     $author = $feed->author();
                 } else {
                     if ($feed->creator()) {
                         $author = $feed->creator();
                     } else {
                         $author = null;
                     }
                 }
                 // Loop over each channel item and store relevant data
                 $counter = 0;
                 $channel['Entry'] = array();
                 foreach ($feed as $item) {
                     if ($counter >= $numEntries) {
                         break;
                     }
                     $_entry = array();
                     $_entry['Title'] = $item->title();
                     $_entry['Link'] = $item->link();
                     if (!is_string($_entry['Link']) && isset($_entry['Link'][1]) && $_entry['Link'][1] instanceof DOMElement) {
                         $_entry['Link'] = $_entry['Link'][1]->getAttribute('href');
                     }
                     if ($getSummaries && $item->description()) {
                         $_entry['Summary'] = $item->description();
                     }
                     $date = 0;
                     if ($item->date()) {
                         $date = strtotime($item->date());
                     } else {
                         if ($item->pubDate()) {
                             $date = strtotime($item->pubDate());
                         }
                     }
                     $_entry['Date'] = $date;
                     $channel['Entry'][] = $_entry;
                     // Remember author if first found
                     if (empty($author) && $item->author()) {
                         $author = $item->author();
                     } else {
                         if ($item->creator()) {
                             $author = $item->creator();
                         }
                     }
                     $counter++;
                 }
                 $channel['Title'] = $feed->title();
                 $channel['URL'] = $url;
                 $channel['Description'] = $feed->description();
                 if ($feed->link()) {
                     if (is_array($feed->link())) {
                         foreach ($feed->link() as $_link) {
                             if ($_link->nodeValue) {
                                 $channel['Link'] = $_link->nodeValue;
                             }
                         }
                     } else {
                         $channel['Link'] = $feed->link();
                     }
                 }
                 if ($author != null) {
                     $channel['Author'] = $author;
                 }
             } elseif ($feed instanceof Zend_Feed_Atom) {
                 // Try get author
                 if ($feed->author()) {
                     if ($feed->author->name()) {
                         $author = $feed->author->name();
                     } else {
                         if ($feed->author->email()) {
                             $author = $feed->author->email();
                         } else {
                             $author = $feed->author();
                         }
                     }
                 } else {
                     $author = null;
                 }
                 // Loop over each entries and store relevant data
                 $counter = 0;
                 $channel['Entry'] = array();
                 foreach ($feed as $entry) {
                     if ($counter >= $numEntries) {
                         break;
                     }
                     $_entry = array();
                     $_entry['Title'] = $entry->title();
                     // get Link if rel="alternate"
                     if ($entry->link('alternate')) {
                         $_entry['Link'] = $entry->link('alternate');
                     } else {
                         // if there's no alternate, pick the one without "rel" attribtue
                         $_links = $entry->link;
                         if (is_array($_links)) {
                             foreach ($_links as $_link) {
                                 if (empty($_link['rel'])) {
                                     $_entry['Link'] = $_link['href'];
                                     break;
                                 }
                             }
                         } else {
                             $_entry['Link'] = $_links['href'];
                         }
                     }
                     if ($getSummaries && $entry->summary()) {
                         $_entry['Summary'] = $entry->summary();
                     }
                     $date = 0;
                     if ($entry->updated()) {
                         $date = strtotime($entry->updated());
                     } else {
                         if ($entry->published()) {
                             $date = strtotime($entry->published());
                         }
                     }
                     $_entry['Date'] = $date;
                     $channel['Entry'][] = $_entry;
                     // Remember author if first found
                     if (empty($author) && $entry->author()) {
                         if ($entry->author->name()) {
                             $author = $entry->author->name();
                         } else {
                             if ($entry->author->email()) {
                                 $author = $entry->author->email();
                             } else {
                                 $author = $entry->author();
                             }
                         }
                     } elseif (empty($author)) {
                         $author = null;
                     }
                     $counter++;
                 }
                 $channel['Title'] = $feed->title();
                 $channel['URL'] = $url;
                 $channel['Description'] = $feed->subtitle();
                 // get Link if rel="alternate"
                 if ($feed->link('alternate')) {
                     $channel['Link'] = $feed->link('alternate');
                 } else {
                     // if there's no alternate, pick the one without "rel" attribtue
                     $_links = $feed->link;
                     if (is_array($_links)) {
                         foreach ($_links as $_link) {
                             if (empty($_link['rel'])) {
                                 $channel['Link'] = $_link['href'];
                                 break;
                             }
                         }
                     } else {
                         $channel['Link'] = $_links['href'];
                     }
                 }
                 if (!empty($author)) {
                     $channel['Author'] = $author;
                 }
             } else {
                 throw new Exception('Invalid feed type');
             }
             $resp = json_encode($channel);
         } catch (Zend_Feed_Exception $e) {
             $resp = 'Error parsing feed: ' . $e->getMessage();
         }
     } else {
         // feed import failed
         $resp = "Error fetching feed, response code: " . $result->getHttpCode();
     }
     return $resp;
 }
 private function setRequestCache(RemoteContentRequest $originalRequest, RemoteContentRequest $request, Cache $cache)
 {
     if ($request->isStrictNoCache()) {
         return;
     }
     $ignoreCache = $originalRequest->getOptions()->ignoreCache;
     if (($this->cachePostRequest || !$request->isPost()) && !$ignoreCache) {
         $ttl = Shindig_Config::get('cache_time');
         if ((int) $request->getHttpCode() == 200) {
             // Got a 200 OK response, calculate the TTL to use for caching it
             if (($expires = $request->getResponseHeader('Expires')) != null) {
                 // prefer to use the servers notion of the time since there could be a clock-skew, but otherwise use our own
                 $date = $request->getResponseHeader('Date') != null ? $request->getResponseHeader('Date') : gmdate('D, d M Y H:i:s', $_SERVER['REQUEST_TIME']) . ' GMT';
                 // convert both dates to unix epoch seconds, and calculate the TTL
                 date_default_timezone_set('GMT');
                 $date = strtotime($date);
                 $expires = strtotime($expires);
                 $ttl = $expires - $date;
                 // Don't fall for the old expiration-date-in-the-past trick, we *really* want to cache stuff since a large SNS's traffic would devastate a gadget developer's server
                 if ($expires - $date > 1) {
                     $ttl = $expires - $date;
                 }
             }
             // See http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html : The Cache-Control: max-age=<seconds> overrides the expires header, so if both are present this one will overwrite the $ttl
             if (($cacheControl = $request->getResponseHeader('Cache-Control')) != null) {
                 $bits = explode('=', $cacheControl);
                 foreach ($bits as $key => $val) {
                     if ($val == 'max-age' && isset($bits[$key + 1])) {
                         $ttl = $bits[$key + 1];
                         break;
                     }
                 }
             }
         } else {
             $ttl = 5 * 60;
             // cache errors for 5 minutes, takes the denial of service attack type behaviour out of having an error :)
         }
         $this->invalidateService->markResponse($request);
         $this->cache->set($originalRequest->toHash(), $request, $ttl);
     }
 }