feeds::get_fields()   A
last analyzed

Complexity

Conditions 3
Paths 3

Size

Total Lines 33
Code Lines 20

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 3
eloc 20
nc 3
nop 0
dl 0
loc 33
rs 9.6
c 1
b 0
f 0
1
<?php
2
3
/**
4
 *
5
 * @package sitemaker
6
 * @copyright (c) 2019 Daniel A. (blitze)
7
 * @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2
8
 *
9
 */
10
11
namespace blitze\sitemaker\blocks;
12
13
use blitze\sitemaker\services\blocks\driver\block;
14
15
/**
16
 * Feeds Block
17
 */
18
class feeds extends block
19
{
20
	/** @var \phpbb\language\language */
21
	protected $translator;
22
23
	/** @var \phpbb\request\request_interface */
24
	protected $request;
25
26
	/** @var \phpbb\template\twig\environment */
27
	protected $twig;
28
29
	/** @var \blitze\sitemaker\services\simplepie\feed */
30
	protected $simplepie;
31
32
	/** @var string */
33
	protected $cache_dir;
34
35
	/** @var array */
36
	protected $feed_fields = ['title', 'description', 'category', 'categories', 'author', 'authors', 'contributor', 'contributors', 'copyright', 'image_url', 'image_title', 'image_link', 'image_width', 'image_height', 'permalink', 'link', 'links'];
37
38
	/** @var array */
39
	protected $item_fields = ['id', 'title', 'description', 'content', 'category', 'categories', 'author', 'authors', 'contributor', 'contributors', 'copyright', 'date', 'updated_date', 'gmdate', 'updated_gmdate', 'permalink', 'link', 'links', 'enclosure', 'enclosures', 'latitude', 'longitude', 'source'];
40
41
	/**
42
	 * Constructor
43
	 *
44
	 * @param \phpbb\language\language						$translator			Language object
45
	 * @param \phpbb\request\request_interface				$request			Request object
46
	 * @param \phpbb\template\twig\environment				$twig				Twig environment
47
	 * @param \blitze\sitemaker\services\simplepie\feed		$simplepie			An extension of simple pie
48
	 * @param string 										$cache_dir			Path to cache directory
49
	 */
50
	public function __construct(\phpbb\language\language $translator, \phpbb\request\request_interface $request, \phpbb\template\twig\environment $twig, \blitze\sitemaker\services\simplepie\feed $simplepie, $cache_dir)
51
	{
52
		$this->translator = $translator;
53
		$this->request = $request;
54
		$this->twig = $twig;
55
		$this->simplepie = $simplepie;
56
		$this->cache_dir = $cache_dir;
57
	}
58
59
	/**
60
	 * {@inheritdoc}
61
	 */
62
	public function get_config(array $settings)
63
	{
64
		$template_default = '<a target="_blank" href="{{ item.link }}">{{ item.title }}</a>';
65
		return array(
66
			'legend1'		=> 'SETTINGS',
67
			'feeds'			=> array('lang' => 'FEED_URLS', 'type' => 'multi_input:0', 'default' => []),
68
			'template'		=> array('type' => 'custom', 'default' => $template_default, 'object' => $this, 'method' => 'get_cfg_feeds_template'),
69
			'max'			=> array('lang' => 'MAX_ITEMS', 'validate' => 'int:1', 'type' => 'number:1', 'default' => 5),
70
			'cache'			=> array('lang' => 'CACHE_DURATION', 'validate' => 'int:1', 'type' => 'number:1', 'default' => 6, 'append' => 'HOURS_SHORT'),
71
		);
72
	}
73
74
	/**
75
	 * {@inheritdoc}
76
	 */
77
	public function display(array $bdata, $edit_mode = false)
78
	{
79
		$settings = $bdata['settings'];
80
		$feed_urls = $this->get_feeds_array($settings['feeds']);
81
		$status = 0;
82
83
		try
84
		{
85
			$content = $this->render_feeds($feed_urls, $settings, $status);
86
		}
87
		catch (\Exception $e)
88
		{
89
			$content = $e->getMessage();
90
		}
91
92
		return array(
93
			'title'		=> 'FEEDS',
94
			'content'	=> $status || $edit_mode ? $content : '',
95
			'status'	=> $status,
96
		);
97
	}
98
99
	/**
100
	 * @param array $feeds_url
101
	 * @param array $settings
102
	 * @param int $status
103
	 * @return string
104
	 */
105
	protected function render_feeds(array $feed_urls, array $settings, &$status)
106
	{
107
		$content = '';
108
		if ($items = $this->get_feed_items($feed_urls, $content, $settings['max'], $settings['cache']))
109
		{
110
			// We try to render block with user-provided trig template
111
			$template = $this->twig->createTemplate($this->get_feed_template($settings['template']));
112
113
			$status = 1;
114
			$content = $template->render([
115
				'items'	=> $items,
116
			]);
117
		}
118
119
		return $content;
120
	}
121
122
	/**
123
	 * @param string $source
124
	 * @return string
125
	 */
126
	public function get_cfg_feeds_template($source)
127
	{
128
		$template = $this->twig->load('@blitze_sitemaker/cfg_fields/feeds.html');
129
		return $template->render([
130
			'template'	=> $source,
131
		]);
132
	}
133
134
	/**
135
	 * Called when editing feed block to get available rss/atom fields
136
	 * @return array
137
	 */
138
	public function get_fields()
139
	{
140
		$this->translator->add_lang('feed_fields', 'blitze/sitemaker');
141
142
		$feeds = $this->request->variable('feeds', array(0 => ''));
143
		$feeds = $this->get_feeds_array($feeds);
144
145
		$message = '';
146
		$data = array('items' => []);
147
		$fields = array('items' => $this->get_field_defaults('items'));
148
149
		$feed_items = $this->get_feed_items($feeds, $message, 0, 0, 1, true);
150
151
		foreach ($feed_items as $feed)
152
		{
153
			$feed_data = $feed_fields = [];
154
			$fields['items']['children'] += $this->get_feed_fields($feed, $feed_data);
155
156
			foreach ($this->item_fields as $field)
157
			{
158
				$value = $feed->{$field};
159
				$feed_data[$field] = $value;
160
				$feed_fields[$field] = $this->build_tags($field, $value);
161
			}
162
163
			$data['items'][] = array_filter($feed_data);
164
			$fields['items']['children'] = array_replace_recursive($fields['items']['children'], array_filter($feed_fields));
165
		}
166
167
		return [
168
			'fields'	=> array_filter($fields),
169
			'data'		=> array_filter($data),
170
			'message'	=> $message,
171
		];
172
	}
173
174
	/**
175
	 * @param array $feed_urls
176
	 * @param string $message
177
	 * @param int $max
178
	 * @param int $cache
179
	 * @param bool $quiet
180
	 * @return array
181
	 */
182
	protected function get_feed_items(array $feed_urls, &$message, $max, $cache = 0, $items_per_feed = 0, $quiet = false)
183
	{
184
		if (!sizeof($feed_urls))
185
		{
186
			if (!$quiet)
187
			{
188
				throw new \Exception($this->translator->lang('FEED_URL_MISSING'));
189
			}
190
			return [];
191
		}
192
193
		$items = [];
194
195
		try
196
		{
197
			$this->simplepie->set_feed_url($feed_urls);
198
			$this->simplepie->enable_cache((bool) $cache);
199
			$this->simplepie->set_cache_location($this->cache_dir);
200
			$this->simplepie->set_cache_duration($cache * 3600);
201
202
			if ($items_per_feed)
203
			{
204
				$this->simplepie->set_item_limit($items_per_feed);
205
			}
206
207
			$this->simplepie->init();
208
			$this->simplepie->handle_content_type();
209
210
			if (!($items = $this->simplepie->get_items(0, $max)))
211
			{
212
				$message = $this->translator->lang('FEED_PROBLEMS');
213
			}
214
		}
215
		catch (\Exception $e)
216
		{
217
			$message = $e->getMessage();
218
		}
219
220
		return array_filter((array) $items);
221
	}
222
223
	/**
224
	 * @param \blitze\sitemaker\services\simplepie\item $feed
225
	 * @return array
226
	 */
227
	protected function get_feed_fields(\blitze\sitemaker\services\simplepie\item $item, array &$data)
228
	{
229
		$feed_props = [];
230
		foreach ($this->feed_fields as $field)
231
		{
232
			$feed_props[$field] = $this->build_tags($field, $item->feed->{$field});
233
			$data['feed'][$field] = $item->feed->{$field};
234
		}
235
236
		$feed_props = array_filter($feed_props);
237
		$data['feed'] = array_filter($data['feed']);
238
239
		$fields = [];
240
		if (sizeof($feed_props))
241
		{
242
			$fields['feed'] = $this->get_field_defaults('feed');
243
			$fields['feed']['children'] = $feed_props;
244
		}
245
246
		return $fields;
247
	}
248
249
	/**
250
	 * @param string $field
251
	 * @param mixed $value
252
	 * @return array|string
253
	 */
254
	protected function build_tags($field, $value)
255
	{
256
		if (empty($value))
257
		{
258
			return '';
259
		}
260
261
		$data = $this->get_field_defaults($field);
262
263
		if ($this->is_array_of_objects($value))
264
		{
265
			$value = array_slice($value, 0, 1);
266
			$this->iterate_props($value, $data);
267
		}
268
		else if (gettype($value) === 'object')
269
		{
270
			$props = array_filter(get_object_vars($value));
271
			$this->iterate_props($props, $data);
272
		}
273
274
		return $data;
275
	}
276
277
	/**
278
	 * @param array $props
279
	 * @param array $data
280
	 * @return void
281
	 */
282
	protected function iterate_props(array $props, array &$data)
283
	{
284
		ksort($props);
285
		foreach ($props as $prop => $value)
286
		{
287
			$data['children'][$prop] = $this->build_tags($prop, $value);
288
		}
289
	}
290
291
	/**
292
	 * @param mixed $value
293
	 * @return bool
294
	 */
295
	protected function is_array_of_objects($value)
296
	{
297
		return (is_array($value) && gettype($value[0]) === 'object');
298
	}
299
300
	/**
301
	 * @param string $field
302
	 * @return array
303
	 */
304
	protected function get_field_defaults($field)
305
	{
306
		$field = (string) $field;
307
		return [
308
			'text'			=> $field,
309
			'displayText'	=> $this->translator->lang(strtoupper($field)),
310
			'children'		=> [],
311
		];
312
	}
313
314
	/**
315
	 * @param string $tpl
316
	 * @return string
317
	 */
318
	protected function get_feed_template($item_tpl)
319
	{
320
		$item_tpl = html_entity_decode(trim($item_tpl));
321
		return "<ul class=\"sm-list\">
322
			{% for item in items %}
323
			<li>
324
				$item_tpl
325
			</li>
326
			{% endfor %}
327
		</ul>";
328
	}
329
330
	/**
331
	 * @param mixed $feeds
332
	 * @return array
333
	 */
334
	protected function get_feeds_array($feeds)
335
	{
336
		return array_map('trim', array_filter((array) $feeds));
337
	}
338
}
339