Overview

Namespaces

  • FastFeed
    • Aggregator
    • Cache
    • Exception
    • Logger
    • Parser
    • Processor
  • PHP

Classes

  • Factory
  • FastFeed
  • Item

Interfaces

  • FastFeedInterface
  • Overview
  • Namespace
  • Class
  • Tree
  1: <?php
  2: /**
  3:  * This file is part of the FastFeed package.
  4:  *
  5:  * (c) Daniel González <daniel@desarrolla2.com>
  6:  *
  7:  * For the full copyright and license information, please view the LICENSE
  8:  * file that was distributed with this source code.
  9:  */
 10: 
 11: namespace FastFeed;
 12: 
 13: use Guzzle\Http\ClientInterface;
 14: use Psr\Log\LoggerInterface;
 15: use Psr\Log\LogLevel;
 16: use FastFeed\Exception\LogicException;
 17: use FastFeed\Parser\ParserInterface;
 18: use FastFeed\Processor\ProcessorInterface;
 19: 
 20: /**
 21:  * FastFeed
 22:  */
 23: class FastFeed implements FastFeedInterface
 24: {
 25:     /**
 26:      * @const VERSION
 27:      */
 28:     const VERSION = '0.1';
 29: 
 30:     /**
 31:      * @const USER_AGENT
 32:      */
 33:     const USER_AGENT = 'FastFeed/FastFeed';
 34: 
 35:     /**
 36:      * @var ClientInterface;
 37:      */
 38:     protected $http;
 39: 
 40:     /**
 41:      * @var LoggerInterface
 42:      */
 43:     protected $logger;
 44: 
 45:     /**
 46:      * @var array
 47:      */
 48:     protected $parsers = array();
 49: 
 50:     /**
 51:      * @var array
 52:      */
 53:     protected $processors = array();
 54: 
 55:     /**
 56:      * @var array
 57:      */
 58:     protected $feeds = array();
 59: 
 60:     /**
 61:      * @param ClientInterface $guzzle
 62:      * @param LoggerInterface $logger
 63:      */
 64:     public function __construct(ClientInterface $guzzle, LoggerInterface $logger)
 65:     {
 66:         $this->http = $guzzle;
 67:         $this->logger = $logger;
 68:     }
 69: 
 70:     /**
 71:      * Add feed to channel
 72:      *
 73:      * @param string $channel
 74:      * @param string $feed
 75:      *
 76:      * @throws LogicException
 77:      */
 78:     public function addFeed($channel, $feed)
 79:     {
 80:         if (!filter_var($feed, FILTER_VALIDATE_URL)) {
 81:             throw new LogicException('You tried to add a invalid url.');
 82:         }
 83:         $this->feeds[$channel][] = $feed;
 84:     }
 85: 
 86:     /**
 87:      * @param string $channel
 88:      *
 89:      * @return array
 90:      * @throws Exception\LogicException
 91:      */
 92:     public function fetch($channel = 'default')
 93:     {
 94:         if (!is_string($channel)) {
 95:             throw new LogicException('You tried to add a invalid channel.');
 96:         }
 97: 
 98:         $items = $this->retrieve($channel);
 99: 
100:         foreach ($this->processors as $processor) {
101:             $items = $processor->process($items);
102:         }
103: 
104:         return $items;
105:     }
106: 
107:     /**
108:      * Retrieve a channel
109:      *
110:      * @param string $channel
111:      *
112:      * @return string
113:      * @throws LogicException
114:      */
115:     public function getFeed($channel)
116:     {
117:         if (!isset($this->feeds[$channel])) {
118:             throw new LogicException('You tried to get a not existent channel');
119:         }
120: 
121:         return $this->feeds[$channel];
122:     }
123: 
124:     /**
125:      * @return ParserInterface
126:      * @throws Exception\LogicException
127:      */
128:     public function popParser()
129:     {
130:         if (!$this->parsers) {
131:             throw new LogicException('You tried to pop from an empty parsers stack.');
132:         }
133: 
134:         return array_shift($this->parsers);
135:     }
136: 
137:     /**
138:      * @param ParserInterface $parser
139:      */
140:     public function pushParser(ParserInterface $parser)
141:     {
142:         $this->parsers[] = $parser;
143:     }
144: 
145:     /**
146:      * @return ProcessorInterface
147:      * @throws Exception\LogicException
148:      */
149:     public function popProcessor()
150:     {
151:         if (!$this->processors) {
152:             throw new LogicException('You tried to pop from an empty Processor stack.');
153:         }
154: 
155:         return array_shift($this->processors);
156:     }
157: 
158:     /**
159:      * @param ProcessorInterface $processor
160:      */
161:     public function pushProcessor(ProcessorInterface $processor)
162:     {
163:         $this->processors[] = $processor;
164:     }
165: 
166:     /**
167:      * Retrieve all channels
168:      *
169:      * @return array
170:      */
171:     public function getFeeds()
172:     {
173:         return $this->feeds;
174:     }
175: 
176:     /**
177:      * Set Guzzle
178:      *
179:      * @param ClientInterface $guzzle
180:      */
181:     public function setHttpClient(ClientInterface $guzzle)
182:     {
183:         $this->http = $guzzle;
184:     }
185: 
186:     /**
187:      * @param LoggerInterface $logger
188:      */
189:     public function setLogger(LoggerInterface $logger)
190:     {
191:         $this->logger = $logger;
192:     }
193: 
194:     /**
195:      * Set a channel
196:      *
197:      * @param string $channel
198:      * @param string $feed
199:      *
200:      * @throws LogicException
201:      */
202:     public function setFeed($channel, $feed)
203:     {
204:         if (!is_string($channel)) {
205:             throw new LogicException('You tried to add a invalid channel.');
206:         }
207:         $this->feeds[$channel] = array();
208:         $this->addFeed($channel, $feed);
209:     }
210: 
211:     /**
212:      * Retrieve content from a resource
213:      *
214:      * @param $url
215:      *
216:      * @return \Guzzle\Http\EntityBodyInterface|string
217:      */
218:     protected function get($url)
219:     {
220:         $request = $this->http->get(
221:             $url,
222:             array('User-Agent' => self::USER_AGENT . ' v.' . self::VERSION)
223:         );
224: 
225:         $response = $request->send();
226: 
227:         if (!$response->isSuccessful()) {
228:             $this->log('fail with ' . $response->getStatusCode() . ' http code in url "' . $url . '" ');
229: 
230:             return;
231:         }
232:         $this->logger->log(LogLevel::INFO, 'retrieved url "' . $url . '" ');
233: 
234:         return $response->getBody();
235:     }
236: 
237:     /**
238:      * @param $channel
239:      *
240:      * @return array
241:      */
242:     protected function retrieve($channel)
243:     {
244:         $result = array();
245: 
246:         foreach ($this->feeds[$channel] as $feed) {
247:             $content = $this->get($feed);
248:             if (!$content) {
249:                 continue;
250:             }
251:             $result = array_merge($result, $this->parse($content));
252:         }
253: 
254:         return $result;
255:     }
256: 
257:     /**
258:      * @param $content
259:      *
260:      * @return array
261:      */
262:     protected function parse($content)
263:     {
264:         $result = array();
265:         foreach ($this->parsers as $parser) {
266:             $nodes = $parser->getNodes($content);
267:             if (!$nodes) {
268:                 continue;
269:             }
270: 
271:             foreach ($nodes as $node) {
272:                 $result[] = $node;
273:             }
274:         }
275: 
276:         return $result;
277:     }
278: 
279:     /**
280:      * @param $message
281:      */
282:     protected function log($message)
283:     {
284:         $this->logger->log(
285:             LogLevel::INFO,
286:             '[' . self::USER_AGENT . ' v.' . self::VERSION . '] - ' . $message
287:         );
288:     }
289: }
290: 
API documentation generated by ApiGen 2.8.0