Passed
Push — release-3.2.0 ( 8165d1...607af8 )
by Daniel
03:27
created

feeds::get_feeds_array()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Importance

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