Passed
Push — renovate/configure ( 5b5630...69e50f )
by
unknown
16:36
created

routes::get_parent_forum_route()   A

Complexity

Conditions 5
Paths 2

Size

Total Lines 18
Code Lines 10

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 5
eloc 10
nc 2
nop 2
dl 0
loc 18
rs 9.6111
c 0
b 0
f 0
1
<?php
2
3
/**
4
 *
5
 * @package sitemaker
6
 * @copyright (c) 2013 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\services\blocks;
12
13
class routes
14
{
15
	/** @var \phpbb\cache\driver\driver_interface */
16
	protected $cache;
17
18
	/** @var \phpbb\config\config */
19
	protected $config;
20
21
	/** @var \blitze\sitemaker\services\blocks\factory */
22
	protected $block_factory;
23
24
	/** @var \blitze\sitemaker\model\mapper_factory */
25
	protected $mapper_factory;
26
27
	/** @var string */
28
	protected $php_ext;
29
30
	/** @var bool */
31
	protected $is_sub_route = false;
32
33
	/**
34
	 * Constructor
35
	 *
36
	 * @param \phpbb\cache\driver\driver_interface			$cache					Cache driver interface
37
	 * @param \phpbb\config\config							$config					Config object
38
	 * @param \blitze\sitemaker\services\blocks\factory		$block_factory			Blocks factory object
39
	 * @param \blitze\sitemaker\model\mapper_factory		$mapper_factory			Mapper factory object
40
	 * @param string										$php_ext				phpEx
41
	 */
42
	public function __construct(\phpbb\cache\driver\driver_interface $cache, \phpbb\config\config $config, \blitze\sitemaker\services\blocks\factory $block_factory, \blitze\sitemaker\model\mapper_factory $mapper_factory, $php_ext)
43
	{
44
		$this->cache = $cache;
45
		$this->config = $config;
46
		$this->block_factory = $block_factory;
47
		$this->mapper_factory = $mapper_factory;
48
		$this->php_ext = $php_ext;
49
	}
50
51
	/**
52
	 * @param string $current_route
53
	 * @param string $page_dir
54
	 * @param int $style_id
55
	 * @param bool $edit_mode
56
	 * @return array
57
	 */
58
	public function get_route_info($current_route, $page_dir, $style_id, $edit_mode = false)
59
	{
60
		$routes = $this->get_routes_for_style($style_id);
61
		$current_route = str_replace('viewtopic.' . $this->php_ext, 'viewforum.' . $this->php_ext, $current_route);
62
		$route_info = array();
63
64
		// does route have own settings?
65
		if (isset($routes[$current_route]))
66
		{
67
			$route_info = $routes[$current_route];
68
		}
69
70
		if ($edit_mode)
71
		{
72
			$route_info += $this->get_default_route_info($current_route, $style_id);
73
			return $route_info;
74
		}
75
76
		return $this->inherit_route_info($routes, $route_info, $current_route, $page_dir, $style_id);
77
	}
78
79
	/**
80
	 * @param array $route_info
81
	 * @param int $style_id
82
	 * @param bool $edit_mode
83
	 * @return array
84
	 */
85
	public function get_blocks_for_route(array $route_info, $style_id, $edit_mode)
86
	{
87
		$blocks = $this->get_cached_blocks($edit_mode);
88
		$route_id = $route_info['route_id'];
89
90
		return (isset($blocks[$style_id][$route_id])) ? $blocks[$style_id][$route_id] : array();
91
	}
92
93
	/**
94
	 * @param array $df_settings
95
	 * @param array $db_settings
96
	 * @return array
97
	 */
98
	public function sync_settings(array $df_settings, array $db_settings = array())
99
	{
100
		$settings = array();
101
		foreach ($df_settings as $field => $vars)
102
		{
103
			if (!is_array($vars))
104
			{
105
				continue;
106
			}
107
			$settings[$field] = $vars['default'];
108
		}
109
110
		return array_merge($settings, array_intersect_key($db_settings, $settings));
111
	}
112
113
	/**
114
	 * Clear blocks cache
115
	 */
116
	public function clear_cache()
117
	{
118
		$this->cache->destroy('sitemaker_blocks');
119
		$this->cache->destroy('sitemaker_block_routes');
120
	}
121
122
	/**
123
	 * @param array $routes
124
	 * @param array $route_info
125
	 * @param string $current_route
126
	 * @param string $page_dir
127
	 * @param int $style_id
128
	 * @return array
129
	 */
130
	protected function inherit_route_info(array $routes, array $route_info, $current_route, $page_dir, $style_id)
131
	{
132
		// if block does not have own settings, inherit settings from parent route if it exists
133
		// if block has own settings but no blocks, inherit route_id and has_blocks from parent route if it exists
134
		if (empty($route_info['has_blocks']))
135
		{
136
			$parent_route_info = $this->get_parent_route($routes, $current_route, $page_dir);
137
138
			if (sizeof($parent_route_info))
139
			{
140
				$route_info['route_id'] = $parent_route_info['route_id'];
141
				$route_info['has_blocks'] = $parent_route_info['has_blocks'];
142
			}
143
		}
144
145
		// fill in missing fields, while forcing route and style props to current route and style
146
		unset($route_info['style'], $route_info['route']);
147
		$route_info += $this->get_default_route_info($current_route, $style_id);
148
149
		return $this->set_display_route_id($routes, $route_info);
150
	}
151
152
	/**
153
	 * @param string $route
154
	 * @return bool
155
	 */
156
	public function is_forum_route($route)
157
	{
158
		return (strpos($route, 'viewforum.' . $this->php_ext) !== false || strpos($route, 'viewtopic.' . $this->php_ext) !== false);
159
	}
160
161
	/**
162
	 * @param string $current_route
163
	 * @param int $style_id
164
	 * @return array
165
	 */
166
	protected function get_default_route_info($current_route, $style_id)
167
	{
168
		return array(
169
			'route_id'		=> 0,
170
			'ext_name'		=> '',
171
			'route'			=> $current_route,
172
			'style'			=> $style_id,
173
			'hide_blocks'	=> false,
174
			'ex_positions'	=> array(),
175
			'has_blocks'	=> false,
176
			'is_sub_route'	=> $this->is_sub_route,
177
		);
178
	}
179
180
	/**
181
	 * @param array $routes
182
	 * @param string $current_route
183
	 * @param string $page_dir
184
	 * @return array
185
	 */
186
	protected function get_parent_route(array $routes, $current_route, $page_dir)
187
	{
188
		if ($page_dir)
189
		{
190
			$route = ltrim(dirname($page_dir) . '/index.php', './');
191
			return $this->get_parent_route_info($routes, $route);
192
		}
193
		else if ($this->is_forum_route($current_route))
194
		{
195
			$forum_id = explode('?f=', $current_route)[1];
196
			return $this->get_parent_forum_route($forum_id, $routes);
0 ignored issues
show
Bug introduced by
$forum_id of type string is incompatible with the type integer expected by parameter $forum_id of blitze\sitemaker\service...et_parent_forum_route(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

196
			return $this->get_parent_forum_route(/** @scrutinizer ignore-type */ $forum_id, $routes);
Loading history...
197
		}
198
199
		return $this->get_virtual_parent($routes, $current_route);
200
	}
201
202
	/**
203
	 * @param int $forum_id
204
	 * @param array $routes
205
	 * @return array
206
	 */
207
	protected function get_parent_forum_route($forum_id, array $routes)
208
	{
209
		$parent_route = [];
210
		$forumslist = (array) make_forum_select(false, false, true, false, false, false, true);
211
212
		do
213
		{
214
			$forum_id = &$forumslist[$forum_id]['parent_id'];
215
			$route = "viewforum.{$this->php_ext}?f={$forum_id}";
216
217
			if (isset($routes[$route]) && $routes[$route]['has_blocks'])
218
			{
219
				$this->is_sub_route = true;
220
				$parent_route = $routes[$route];
221
			}
222
		} while ($forum_id && !$this->is_sub_route);
223
224
		return $parent_route;
225
	}
226
227
	/**
228
	 * @param array $routes_data
229
	 * @param string $current_route
230
	 * @return array
231
	 */
232
	protected function get_virtual_parent(array $routes_data, $current_route)
233
	{
234
		$routes = array_keys($routes_data);
235
236
		// We add the current route to the list and sort it in ascending order
237
		// Its parent will likely come before it in the list
238
		// Eg if current route is 'app.php/content/news' the route list might be:
239
		// ['app.php/content', 'app.php/content/category/cars', 'app.php/content/news', 'index.php']
240
		$routes[] = $current_route;
241
		sort($routes);
242
243
		// We find the position of the current route in the list
244
		$index = (int) array_search($current_route, $routes);
245
246
		// we use it as our starting point and walk backwords to find the immediate parent
247
		// in this case 'app.php/content'
248
		$parent_route = array();
249
		for ($i = $index - 1; $i >= 0; $i--)
250
		{
251
			if (strpos($current_route, $routes[$i]) !== false)
252
			{
253
				$parent_route = $routes_data[$routes[$i]];
254
				$this->is_sub_route = $parent_route['has_blocks'];
255
				break;
256
			}
257
		}
258
259
		return $parent_route;
260
	}
261
262
	/**
263
	 * @param array $routes
264
	 * @param string $route
265
	 * @return array
266
	 */
267
	protected function get_parent_route_info(array $routes, $route)
268
	{
269
		$route_info = array();
270
		if (isset($routes[$route]))
271
		{
272
			$this->is_sub_route = $routes[$route]['has_blocks'];
273
			$route_info = $routes[$route];
274
		}
275
276
		return $route_info;
277
	}
278
279
	/**
280
	 * We get blocks to display by route id, so we update the route id here,
281
	 * to show blocks from default route if current route or it's parent has no blocks
282
	 *
283
	 * @param array $routes
284
	 * @param array $route_info
285
	 * @return array
286
	 */
287
	protected function set_display_route_id(array $routes, array $route_info)
288
	{
289
		$default_route = $this->config['sitemaker_default_layout'];
290
		if (!$route_info['has_blocks'] && isset($routes[$default_route]))
291
		{
292
			$route_info['route_id'] = $routes[$default_route]['route_id'];
293
		}
294
295
		return $route_info;
296
	}
297
298
	/**
299
	 * @param array $condition
300
	 * @return array
301
	 */
302
	protected function get_all_blocks(array $condition)
303
	{
304
		$collection = $this->mapper_factory->create('blocks')->find($condition);
305
306
		$blocks = array();
307
		foreach ($collection as $entity)
308
		{
309
			if (($block_instance = $this->block_factory->get_block($entity->get_name())) !== null)
310
			{
311
				$default_settings = $block_instance->get_config(array());
312
				$settings = $this->sync_settings($default_settings, $entity->get_settings());
313
				$entity->set_settings($settings);
314
315
				$blocks[$entity->get_style()][$entity->get_route_id()][$entity->get_position()][] = $entity;
316
			}
317
		}
318
319
		return $blocks;
320
	}
321
322
	/**
323
	 * @return array|mixed
324
	 */
325
	protected function get_all_routes()
326
	{
327
		if (($all_routes = $this->cache->get('sitemaker_block_routes')) === false)
328
		{
329
			$route_mapper = $this->mapper_factory->create('routes');
330
			$collection = $route_mapper->find();
331
332
			$all_routes = array();
333
			foreach ($collection as $entity)
334
			{
335
				$route = $entity->get_route();
336
				$style = $entity->get_style();
337
				$all_routes[$style][$route] = $entity->to_array();
338
			}
339
340
			$this->cache->put('sitemaker_block_routes', $all_routes);
341
		}
342
343
		return $all_routes;
344
	}
345
346
	/**
347
	 * @param int $style_id
348
	 * @return array
349
	 */
350
	protected function get_routes_for_style($style_id)
351
	{
352
		$all_routes = $this->get_all_routes();
353
		return (isset($all_routes[$style_id])) ? $all_routes[$style_id] : array();
354
	}
355
356
	/**
357
	 * @param bool $edit_mode
358
	 * @return array
359
	 */
360
	protected function get_cached_blocks($edit_mode)
361
	{
362
		if (($blocks = $this->cache->get('sitemaker_blocks')) === false || $edit_mode)
363
		{
364
			$condition = (!$edit_mode) ? array('status', '=', 1) : array();
365
			$blocks = $this->get_all_blocks($condition);
366
			$this->cache_block($blocks, $edit_mode);
367
		}
368
369
		return $blocks;
370
	}
371
372
	/**
373
	 * @param array $blocks
374
	 * @param bool $edit_mode
375
	 */
376
	protected function cache_block(array $blocks, $edit_mode)
377
	{
378
		if ($edit_mode === false)
379
		{
380
			$this->cache->put('sitemaker_blocks', $blocks);
381
		}
382
	}
383
}
384