Passed
Push — develop ( 4eb606...0e8a98 )
by Daniel
03:34 queued 11s
created

routes::get_inherited_route_info()   A

Complexity

Conditions 3
Paths 4

Size

Total Lines 6
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 6
CRAP Score 3

Importance

Changes 0
Metric Value
cc 3
eloc 3
nc 4
nop 1
dl 0
loc 6
ccs 6
cts 6
cp 1
crap 3
rs 10
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
	 */
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 42
	{
44 42
		$this->cache = $cache;
45 42
		$this->config = $config;
46 42
		$this->block_factory = $block_factory;
47 42
		$this->mapper_factory = $mapper_factory;
48 42
		$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 25
	 */
58
	public function get_route_info($current_route, $page_dir, $style_id, $edit_mode = false)
59 25
	{
60 25
		$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 25
64 25
		// does route have own settings?
65 17
		if (isset($routes[$current_route]))
66 17
		{
67
			$route_info = $routes[$current_route];
68
		}
69 25
70 9
		if ($edit_mode)
71 9
		{
72
			$route_info += $this->get_default_route_info($current_route, $style_id);
73
			return $route_info;
74 16
		}
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 bool $edit_mode
82
	 * @return array
83 23
	 */
84
	public function get_blocks_for_route(array $route_info, $edit_mode)
85 23
	{
86 23
		$blocks = $this->get_cached_blocks($edit_mode);
87
		$route_id = $route_info['route_id'];
88 23
		$style_id = $route_info['style'];
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 38
	 * @return array
97
	 */
98 38
	public function sync_settings(array $df_settings, array $db_settings = array())
99 38
	{
100
		$settings = array();
101 34
		foreach ($df_settings as $field => $vars)
102 34
		{
103 34
			if (!is_array($vars))
104
			{
105 34
				continue;
106 38
			}
107
			$settings[$field] = $vars['default'];
108 38
		}
109
110
		return array_merge($settings, array_intersect_key($db_settings, $settings));
111
	}
112
113
	/**
114 1
	 * Clear blocks cache
115
	 */
116 1
	public function clear_cache()
117 1
	{
118 1
		$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 16
	 * @return array
129
	 */
130
	protected function inherit_route_info(array $routes, array $route_info, $current_route, $page_dir, $style_id)
131
	{
132 16
		// if block does not have own settings, inherit settings from parent route if it exists
133 16
		// if block has own settings but no blocks, inherit route_id and has_blocks from parent route if it exists
134 10
		if (empty($route_info['has_blocks']))
135 10
		{
136 10
			$parent_route_info = $this->get_parent_route($routes, $current_route, $page_dir);
137
138
			if (sizeof($parent_route_info))
139 16
			{
140 16
				$route_info['route_id'] = $parent_route_info['route_id'];
141
				$route_info['has_blocks'] = $parent_route_info['has_blocks'];
142 16
			}
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($style_id, $route_info);
150 25
	}
151
152
	/**
153 25
	 * @param string $route
154 25
	 * @return bool
155 25
	 */
156 25
	public function is_forum_route($route)
157 25
	{
158 25
		return (strpos($route, 'viewforum.' . $this->php_ext) !== false || strpos($route, 'viewtopic.' . $this->php_ext) !== false);
159 25
	}
160 25
161
	/**
162
	 * @param string $route
163
	 * @return bool
164
	 */
165
	public function is_forum_route($route)
166
	{
167
		return (strpos($route, 'viewforum.' . $this->php_ext) !== false || strpos($route, 'viewtopic.' . $this->php_ext) !== false);
168
	}
169 10
170
	/**
171
	 * @param string $current_route
172 10
	 * @param int $style_id
173 4
	 * @return array
174 4
	 */
175 4
	protected function get_default_route_info($current_route, $style_id)
176 6
	{
177 6
		return array(
178 1
			'route_id'		=> 0,
179 1
			'ext_name'		=> '',
180 1
			'route'			=> $current_route,
181
			'style'			=> $style_id,
182
			'hide_blocks'	=> false,
183 5
			'ex_positions'	=> array(),
184
			'has_blocks'	=> false,
185
			'is_sub_route'	=> $this->is_sub_route,
186 10
		);
187
	}
188
189
	/**
190
	 * @param array $routes
191
	 * @param string $current_route
192
	 * @param string $page_dir
193
	 * @return array
194 5
	 */
195
	protected function get_parent_route(array $routes, $current_route, $page_dir)
196 5
	{
197 5
		if ($page_dir)
198 5
		{
199 5
			$route = ltrim(dirname($page_dir) . '/index.php', './');
200
			return $this->get_parent_route_info($routes, $route);
201 5
		}
202 5
		else if ($this->is_forum_route($current_route))
203 5
		{
204 1
			$forum_id = explode('?f=', $current_route)[1];
205 1
			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

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