]> git.agnieray.net Git - galette.git/blob - galette/lib/Galette/IO/News.php
Scrutinizer Auto-Fixes (#59)
[galette.git] / galette / lib / Galette / IO / News.php
1 <?php
2
3 /* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
4
5 /**
6 * Galette's news from RSS feed
7 *
8 * PHP version 5
9 *
10 * Copyright © 2014 The Galette Team
11 *
12 * This file is part of Galette (http://galette.tuxfamily.org).
13 *
14 * Galette is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU General Public License as published by
16 * the Free Software Foundation, either version 3 of the License, or
17 * (at your option) any later version.
18 *
19 * Galette is distributed in the hope that it will be useful,
20 * but WITHOUT ANY WARRANTY; without even the implied warranty of
21 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22 * GNU General Public License for more details.
23 *
24 * You should have received a copy of the GNU General Public License
25 * along with Galette. If not, see <http://www.gnu.org/licenses/>.
26 *
27 * @category News
28 * @package Galette
29 *
30 * @author Johan Cwiklinski <johan@x-tnd.be>
31 * @copyright 2014 The Galette Team
32 * @license http://www.gnu.org/licenses/gpl-3.0.html GPL License 3.0 or (at your option) any later version
33 * @version SVN: $Id$
34 * @link http://galette.tuxfamily.org
35 * @since Available since 0.7dev - 2011-11-11
36 */
37
38 namespace Galette\IO;
39
40 use Analog\Analog;
41
42 /**
43 * News class from rss feed for galette
44 *
45 * @category News
46 * @name News
47 * @package Galette
48 * @author Johan Cwiklinski <johan@x-tnd.be>
49 * @copyright 2011-2013 The Galette Team
50 * @license http://www.gnu.org/licenses/gpl-3.0.html GPL License 3.0 or (at your option) any later version
51 * @link http://galette.tuxfamily.org
52 * @since Available since 0.7dev - 2011-11-11
53 */
54 class News
55 {
56 private $cache_filename = '%feed.cache';
57 private $show = 10;
58 //number of hours until cache will be invalid
59 private $cache_timeout = 24;
60 private $feed_url = null;
61 private $posts = [];
62 private $stream_opts = [
63 'http' => [
64 'timeout' => 5
65 ]
66 ];
67
68 /**
69 * Default constructor
70 *
71 * @param string $url Feed URL
72 * @param boolean $nocache Do not try to cache
73 */
74 public function __construct($url, $nocache = false)
75 {
76 $this->feed_url = $this->getFeedURL($url);
77
78 //only if cache should be used
79 if ($nocache === false && GALETTE_MODE !== 'DEV') {
80 if (!$this->checkCache()) {
81 $this->makeCache();
82 } else {
83 $this->loadCache();
84 }
85 } else {
86 $this->parseFeed();
87 }
88 }
89
90 /**
91 * Check if cache is valid
92 *
93 * @return boolean
94 */
95 private function checkCache()
96 {
97 $cfile = $this->getCacheFilename();
98 if (file_exists($cfile)) {
99 try {
100 $dformat = 'Y-m-d H:i:s';
101 $mdate = \DateTime::createFromFormat(
102 $dformat,
103 date(
104 $dformat,
105 filemtime($cfile)
106 )
107 );
108 $expire = $mdate->add(
109 new \DateInterval('PT' . $this->cache_timeout . 'H')
110 );
111 $now = new \DateTime();
112 $has_expired = $now > $expire;
113 return !$has_expired;
114 } catch (\Exception $e) {
115 Analog::log(
116 'Unable check cache expiracy. Are you sure you have ' .
117 'properly configured PHP timezone settings on your server?',
118 Analog::WARNING
119 );
120 return false;
121 }
122 } else {
123 return false;
124 }
125 }
126
127 /**
128 * Creates/update the cache
129 *
130 * @return boolean
131 */
132 private function makeCache()
133 {
134 $this->parseFeed();
135 $cfile = $this->getCacheFilename();
136 $stream = fopen($cfile, 'w+');
137 fwrite(
138 $stream,
139 serialize(
140 $this->posts
141 )
142 );
143 fclose($stream);
144 return false;
145 }
146
147 /**
148 * Loads entries from cache
149 *
150 * @return void
151 */
152 private function loadCache()
153 {
154 $cfile = $this->getCacheFilename();
155 $data = unserialize(file_get_contents($cfile));
156
157 $refresh_cache = false;
158 $this->posts = $data;
159 //check if posts were cached
160 if (!is_array($this->posts) || count($this->posts) == 0) {
161 $this->parseFeed();
162 $refresh_cache = true;
163 }
164
165 if ($refresh_cache === true) {
166 $this->makeCache(false);
167 }
168 }
169
170 /**
171 * Complete path to cache file
172 *
173 * @return string
174 */
175 private function getCacheFilename()
176 {
177 return GALETTE_CACHE_DIR . str_replace(
178 '%feed',
179 md5($this->feed_url),
180 $this->cache_filename
181 );
182 }
183
184 /**
185 * Parse feed
186 *
187 * @return void
188 */
189 private function parseFeed()
190 {
191 try {
192 if (!ini_get('allow_url_fopen')) {
193 throw new \RuntimeException(
194 'allow_url_fopen is set to false; cannot load news.'
195 );
196 }
197
198 $context = stream_context_create($this->stream_opts);
199 $data = file_get_contents($this->feed_url, false, $context);
200 if (!$data) {
201 throw new \Exception();
202 }
203
204 $xml = simplexml_load_string($data);
205 if (!$xml) {
206 throw new \Exception();
207 }
208
209 $posts = array();
210
211 if (isset($xml->entry)) {
212 //Reading an atom feed
213 foreach ($xml->entry as $post) {
214 $posts[] = array(
215 'title' => (string)$post->title,
216 'url' => (string)$post->link['href'],
217 'date' => (string)$post->published
218 );
219 if (count($posts) == $this->show) {
220 break;
221 }
222 }
223 } elseif (isset($xml->channel->item)) {
224 //Reading a RSS feed
225 foreach ($xml->channel->item as $post) {
226 $posts[] = array(
227 'title' => (string)$post->title,
228 'url' => (string)$post->link,
229 'date' => (string)$post->pubDate
230 );
231 if (count($posts) == $this->show) {
232 break;
233 }
234 }
235 } else {
236 throw new \RuntimeException(
237 'Unknown feed type!'
238 );
239 }
240 $this->posts = $posts;
241 } catch (\Exception $e) {
242 Analog::log(
243 'Unable to load feed from "' . $this->feed_url .
244 '" :( | ' . $e->getMessage(),
245 Analog::ERROR
246 );
247 }
248 }
249
250
251 /**
252 * Get posts
253 *
254 * @return array
255 */
256 public function getPosts()
257 {
258 return $this->posts;
259 }
260
261 /**
262 * Get feed url, handle Galette website to check available langs
263 *
264 * @param string $url Requested URL
265 *
266 * @return string
267 */
268 public function getFeedURL($url)
269 {
270 global $i18n;
271
272 if (strpos($url, 'galette.eu') !== false || trim($url) == '') {
273 $url = 'https://galette.eu/site';
274 } elseif (strpos($url, 'localhost:4000') !== false) {
275 $url = 'http://localhost:4000/site';
276 } else {
277 return $url;
278 }
279
280 $galette_website_langs = $url . '/langs.json';
281 $context = stream_context_create($this->stream_opts);
282 $langs = json_decode(file_get_contents($galette_website_langs, false, $context));
283
284 if ($i18n->getAbbrev() != 'en' && in_array($i18n->getAbbrev(), $langs)) {
285 $url .= '/' . $i18n->getAbbrev();
286 }
287 $url .= '/feed.xml';
288
289 return $url;
290 }
291 }