cat::_sync_dir_cat()   A
last analyzed

Complexity

Conditions 1
Paths 1

Size

Total Lines 15

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 15
rs 9.7666
c 0
b 0
f 0
cc 1
nc 1
nop 1
1
<?php
2
/**
3
*
4
* phpBB Directory extension for the phpBB Forum Software package.
5
*
6
* @copyright (c) 2014 ErnadoO <http://www.phpbb-services.com>
7
* @license GNU General Public License, version 2 (GPL-2.0)
8
*
9
*/
10
11
namespace ernadoo\phpbbdirectory\controller\acp;
12
13
use \ernadoo\phpbbdirectory\core\helper;
14
15
class cat extends helper
16
{
17
	/** @var \phpbb\cache\service */
18
	protected $cache;
19
20
	/** @var \phpbb\db\driver\driver_interface */
21
	protected $db;
22
23
	/** @var \phpbb\controller\helper */
24
	protected $helper;
25
26
	/** @var \phpbb\language\language */
27
	protected $language;
28
29
	/** @var \phpbb\log\log */
30
	protected $phpbb_log;
31
32
	/** @var \phpbb\request\request */
33
	protected $request;
34
35
	/** @var \phpbb\template\template */
36
	protected $template;
37
38
	/** @var \phpbb\user */
39
	protected $user;
40
41
	/** @var \ernadoo\phpbbdirectory\core\categorie */
42
	protected $categorie;
43
44
	/** @var \ernadoo\phpbbdirectory\core\nestedset_category */
45
	protected $nestedset_category;
46
47
	/** @var string Custom form action */
48
	protected $u_action;
49
50
	/** @var string */
51
	private $action;
52
53
	/** @var array */
54
	private $cat_data = array();
55
56
	/** @var int */
57
	private $cat_id;
58
59
	/** @var array */
60
	private $errors = array();
61
62
	/** @var string */
63
	private $form_key;
64
65
	/** @var int */
66
	private $parent_id;
67
68
	/** @var bool */
69
	private $update;
70
71
	/**
72
	* Constructor
73
	*
74
	* @param \phpbb\cache\service								$cache				Cache object
75
	* @param \phpbb\db\driver\driver_interface 					$db					Database object
76
	* @param \phpbb\controller\helper							$helper				Helper object
77
	* @param \phpbb\language\language							$language			Language object
78
	* @param \phpbb\log\log										$log				Log object
79
	* @param \phpbb\request\request								$request			Request object
80
	* @param \phpbb\template\template							$template			Template object
81
	* @param \phpbb\user										$user				User object
82
	* @param \ernadoo\phpbbdirectory\core\categorie				$categorie			PhpBB Directory extension categorie object
83
	* @param \ernadoo\phpbbdirectory\core\nestedset_category	$nestedset_category	PhpBB Directory extension nestedset object
84
	*/
85
	public function __construct(\phpbb\cache\service $cache, \phpbb\db\driver\driver_interface $db, \phpbb\controller\helper $helper, \phpbb\language\language $language, \phpbb\log\log $log, \phpbb\request\request $request, \phpbb\template\template $template, \phpbb\user $user, \ernadoo\phpbbdirectory\core\categorie $categorie, \ernadoo\phpbbdirectory\core\nestedset_category $nestedset_category)
86
	{
87
		$this->cache				= $cache;
88
		$this->db					= $db;
89
		$this->helper				= $helper;
90
		$this->language				= $language;
91
		$this->phpbb_log			= $log;
92
		$this->request				= $request;
93
		$this->template				= $template;
94
		$this->user					= $user;
95
		$this->categorie			= $categorie;
96
		$this->nestedset_category	= $nestedset_category;
97
98
		$this->form_key = 'acp_dir_cat';
99
		add_form_key($this->form_key);
100
101
		$this->action		= $this->request->variable('action', '');
102
		$this->cat_id		= $request->variable('c', 0);
103
		$this->parent_id	= $request->variable('parent_id', 0);
104
		$this->update		= ($this->request->is_set_post('update')) ? true : false;
105
	}
106
107
	/**
108
	* Initialize defaults data for add page
109
	*
110
	* @return null
111
	*/
112
	public function action_add()
113
	{
114
		$this->cat_id = $this->parent_id;
115
		$parents_list = $this->categorie->make_cat_select($this->parent_id);
116
117
		// Fill categorie data with default values
118
		if (!$this->update)
119
		{
120
			$this->cat_data = array(
121
				'parent_id'				=> $this->parent_id,
122
				'cat_name'				=> $this->request->variable('cat_name', '', true),
123
				'cat_route'				=> '',
124
				'cat_desc'				=> '',
125
				'cat_icon'				=> '',
126
				'cat_allow_comments'	=> true,
127
				'cat_allow_votes'		=> true,
128
				'cat_must_describe'		=> true,
129
				'cat_count_all'			=> false,
130
				'cat_validate'			=> false,
131
				'enable_icons'			=> false,
132
133
				'display_subcat_list'	=> true,
134
135
				'cat_link_back'			=> false,
136
				'cat_cron_enable'		=> false,
137
				'cat_cron_freq'			=> 7,
138
				'cat_cron_nb_check'		=> 1,
139
			);
140
		}
141
142
		$this->_display_cat_form($parents_list);
143
	}
144
145
	/**
146
	* Display deleting page
147
	*
148
	* @return null
149
	*/
150
	public function action_delete()
151
	{
152 View Code Duplication
		if (!$this->cat_id)
153
		{
154
			trigger_error($this->language->lang('DIR_NO_CAT') . adm_back_link($this->u_action . '&amp;parent_id=' . $this->parent_id), E_USER_WARNING);
155
		}
156
157
		$this->cat_data = $this->_get_cat_info($this->cat_id);
158
159
		$subcats_id = array();
160
		$subcats = $this->nestedset_category->get_subtree_data($this->cat_id);
161
162
		foreach ($subcats as $row)
163
		{
164
			$subcats_id[] = $row['cat_id'];
165
		}
166
167
		$cat_list = $this->categorie->make_cat_select((int) $this->cat_data['parent_id'], $subcats_id);
168
169
		$sql = 'SELECT cat_id
170
			FROM ' . $this->categories_table . '
171
			WHERE cat_id <> ' . (int) $this->cat_id;
172
		$result = $this->db->sql_query_limit($sql, 1);
173
174
		if ($this->db->sql_fetchrow($result))
175
		{
176
			$this->template->assign_vars(array(
177
				'S_MOVE_DIR_CAT_OPTIONS'	=> $this->categorie->make_cat_select((int) $this->cat_data['parent_id'], $subcats_id))
178
			);
179
		}
180
		$this->db->sql_freeresult($result);
181
182
		$parent_id = ($this->parent_id == $this->cat_id) ? 0 : $this->parent_id;
183
184
		$this->template->assign_vars(array(
185
			'S_DELETE_DIR_CAT'		=> true,
186
			'U_ACTION'				=> $this->u_action . "&amp;parent_id={$parent_id}&amp;action=delete&amp;c=$this->cat_id",
187
			'U_BACK'				=> $this->u_action . '&amp;parent_id=' . $this->parent_id,
188
189
			'DIR_CAT_NAME'			=> $this->cat_data['cat_name'],
190
			'S_HAS_SUBCATS'			=> ($this->cat_data['right_id'] - $this->cat_data['left_id'] > 1) ? true : false,
191
			'S_CATS_LIST'			=> $cat_list,
192
			'S_ERROR'				=> (count($this->errors)) ? true : false,
193
			'ERROR_MSG'				=> (count($this->errors)) ? implode('<br />', $this->errors) : '')
194
		);
195
196
		return;
197
	}
198
199
	/**
200
	* Initialize data for edit page
201
	*
202
	* @return null
203
	*/
204
	public function action_edit()
205
	{
206
		$row = $this->_get_cat_info($this->cat_id);
207
208
		if (!$this->update)
209
		{
210
			$this->cat_data = $row;
211
		}
212
		else
213
		{
214
			$this->cat_data['left_id'] = $row['left_id'];
215
			$this->cat_data['right_id'] = $row['right_id'];
216
		}
217
218
		// Make sure no direct child categories are able to be selected as parents.
219
		$exclude_cats = array();
220
		foreach ($this->nestedset_category->get_subtree_data($this->cat_id) as $row2)
221
		{
222
			$exclude_cats[] = $row2['cat_id'];
223
		}
224
		$parents_list = $this->categorie->make_cat_select((int) $this->cat_data['parent_id'], $exclude_cats);
225
226
		$this->_display_cat_form($parents_list);
227
	}
228
229
	/**
230
	* Move order categories
231
	*
232
	* @return null
233
	*/
234
	public function action_move()
235
	{
236 View Code Duplication
		if (!$this->cat_id)
237
		{
238
			trigger_error($this->language->lang('DIR_NO_CAT') . adm_back_link($this->u_action . '&amp;parent_id=' . $this->parent_id), E_USER_WARNING);
239
		}
240
241
		$sql = 'SELECT cat_id, cat_name, parent_id, left_id, right_id
242
			FROM ' . $this->categories_table . '
243
			WHERE cat_id = ' . (int) $this->cat_id;
244
		$result = $this->db->sql_query($sql);
245
		$row = $this->db->sql_fetchrow($result);
246
		$this->db->sql_freeresult($result);
247
248 View Code Duplication
		if (!$row)
249
		{
250
			trigger_error($this->language->lang('DIR_NO_CAT') . adm_back_link($this->u_action . '&amp;parent_id=' . $this->parent_id), E_USER_WARNING);
251
		}
252
253
		try
254
		{
255
			$move_cat_name = $this->nestedset_category->{$this->action}($this->cat_id);
256
		}
257
		catch (\Exception $e)
258
		{
259
			trigger_error($e->getMessage(), E_USER_WARNING);
260
		}
261
262
		if ($move_cat_name !== false)
263
		{
264
			$this->phpbb_log->add('admin', $this->user->data['user_id'], $this->user->ip, 'LOG_DIR_CAT_' . strtoupper($this->action), time(), array($row['cat_name'], $move_cat_name));
265
			$this->cache->destroy('sql', $this->categories_table);
266
		}
267
268
		if ($this->request->is_ajax())
269
		{
270
			$json_response = new \phpbb\json_response;
271
			$json_response->send(array('success' => ($move_cat_name !== false)));
272
		}
273
	}
274
275
	/**
276
	* Display progress bar for syncinc categories
277
	*
278
	* @return null
279
	*/
280
	public function action_progress_bar()
281
	{
282
		$start = $this->request->variable('start', 0);
283
		$total = $this->request->variable('total', 0);
284
285
		adm_page_header($this->language->lang('SYNC_IN_PROGRESS'));
286
287
		$this->template->set_filenames(array(
288
			'body'	=> 'progress_bar.html')
289
		);
290
291
		$this->template->assign_vars(array(
292
			'L_PROGRESS'			=> $this->language->lang('SYNC_IN_PROGRESS'),
293
			'L_PROGRESS_EXPLAIN'	=> ($start && $total) ? $this->language->lang('SYNC_IN_PROGRESS_EXPLAIN', $start, $total) : $this->language->lang('SYNC_IN_PROGRESS'))
294
		);
295
296
		adm_page_footer();
297
	}
298
299
	/**
300
	* Get link's ID interval for _sync_dir_links()
301
	*
302
	* @return null
303
	*/
304
	public function action_sync()
305
	{
306 View Code Duplication
		if (!$this->cat_id)
307
		{
308
			trigger_error($this->language->lang('DIR_NO_CAT') . adm_back_link($this->u_action . '&amp;parent_id=' . $this->parent_id), E_USER_WARNING);
309
		}
310
311
		@set_time_limit(0);
312
313
		$sql = 'SELECT cat_name, cat_links
314
			FROM ' . $this->categories_table . '
315
			WHERE cat_id = ' . (int) $this->cat_id;
316
		$result = $this->db->sql_query($sql);
317
		$row = $this->db->sql_fetchrow($result);
318
		$this->db->sql_freeresult($result);
319
320 View Code Duplication
		if (!$row)
321
		{
322
			trigger_error($this->language->lang('DIR_NO_CAT') . adm_back_link($this->u_action . '&amp;parent_id=' . $this->parent_id), E_USER_WARNING);
323
		}
324
325
		$sql = 'SELECT MIN(link_id) as min_link_id, MAX(link_id) as max_link_id
326
			FROM ' . $this->links_table . '
327
			WHERE link_cat = ' . (int) $this->cat_id . '
328
				AND link_active = 1';
329
		$result = $this->db->sql_query($sql);
330
		$row2 = $this->db->sql_fetchrow($result);
331
		$this->db->sql_freeresult($result);
332
333
		// Typecast to int if there is no data available
334
		$row2['min_link_id'] = (int) $row2['min_link_id'];
335
		$row2['max_link_id'] = (int) $row2['max_link_id'];
336
337
		$start = $this->request->variable('start', $row2['min_link_id']);
338
339
		$batch_size = 200;
340
		$end = $start + $batch_size;
341
342
		// Sync all links in batch mode...
343
		$this->_sync_dir_links($start, $end);
344
345
		if ($end < $row2['max_link_id'])
346
		{
347
			// We really need to find a way of showing statistics... no progress here
348
			$sql = 'SELECT COUNT(link_id) as num_links
349
				FROM ' . $this->links_table . '
350
				WHERE link_cat = ' . (int) $this->cat_id . '
351
						AND link_active = 1
352
						AND link_id BETWEEN ' . (int) $start . ' AND ' . (int) $end;
353
			$result = $this->db->sql_query($sql);
354
			$links_done = $this->request->variable('links_done', 0) + (int) $this->db->sql_fetchfield('num_links');
355
			$this->db->sql_freeresult($result);
356
357
			$start += $batch_size;
358
359
			$url = $this->u_action . "&amp;parent_id={$this->parent_id}&amp;c=$this->cat_id&amp;action=sync&amp;start=$start&amp;links_done=$links_done&amp;total={$row['cat_links']}";
360
361
			meta_refresh(0, $url);
362
363
			$this->template->assign_vars(array(
364
				'UA_PROGRESS_BAR'		=> $this->u_action . "&amp;action=progress_bar&amp;start=$links_done&amp;total={$row['cat_links']}",
365
				'S_CONTINUE_SYNC'		=> true,
366
				'L_PROGRESS_EXPLAIN'	=> $this->language->lang('SYNC_IN_PROGRESS_EXPLAIN', $links_done, $row['cat_links']))
367
			);
368
369
			return;
370
		}
371
372
		$url = $this->u_action . "&amp;parent_id={$this->parent_id}&amp;c=$this->cat_id&amp;action=sync_cat";
373
		meta_refresh(0, $url);
374
375
		$this->template->assign_vars(array(
376
			'UA_PROGRESS_BAR'		=> $this->u_action . '&amp;action=progress_bar',
377
			'S_CONTINUE_SYNC'		=> true,
378
			'L_PROGRESS_EXPLAIN'	=> $this->language->lang('SYNC_IN_PROGRESS_EXPLAIN', 0, $row['cat_links']))
379
		);
380
381
		return;
382
	}
383
384
	/**
385
	* Sync category data
386
	*
387
	* @return null
388
	*/
389
	public function action_sync_cat()
390
	{
391
		$sql = 'SELECT cat_name
392
			FROM ' . $this->categories_table . '
393
			WHERE cat_id = ' . (int) $this->cat_id;
394
		$result = $this->db->sql_query($sql);
395
		$row = $this->db->sql_fetchrow($result);
396
		$this->db->sql_freeresult($result);
397
398 View Code Duplication
		if (!$row)
399
		{
400
			trigger_error($this->language->lang('DIR_NO_CAT') . adm_back_link($this->u_action . '&amp;parent_id=' . $this->parent_id), E_USER_WARNING);
401
		}
402
403
		$this->_sync_dir_cat($this->cat_id);
404
405
		$this->phpbb_log->add('admin', $this->user->data['user_id'], $this->user->ip, 'LOG_DIR_CAT_SYNC', time(), array($row['cat_name']));
406
		$this->cache->destroy('sql', $this->categories_table);
407
408
		$this->template->assign_var('L_DIR_CAT_RESYNCED', $this->language->lang('DIR_CAT_RESYNCED', $row['cat_name']));
409
	}
410
411
	/**
412
	* Display categories page
413
	*
414
	* @return null
415
	*/
416
	public function display_cats()
417
	{
418
		// Default management page
419
		if (!$this->parent_id)
420
		{
421
			$navigation = $this->language->lang('DIR_INDEX');
422
		}
423
		else
424
		{
425
			$navigation = '<a href="' . $this->u_action . '">' . $this->language->lang('DIR_INDEX') . '</a>';
426
427
			$cats_nav = $this->nestedset_category->get_path_data($this->parent_id);
428
429
			foreach ($cats_nav as $row)
430
			{
431
				if ($row['cat_id'] == $this->parent_id)
432
				{
433
					$navigation .= ' -&gt; ' . $row['cat_name'];
434
				}
435
				else
436
				{
437
					$navigation .= ' -&gt; <a href="' . $this->u_action . '&amp;parent_id=' . $row['cat_id'] . '">' . $row['cat_name'] . '</a>';
438
				}
439
			}
440
		}
441
442
		// Jumpbox
443
		$cat_box = $this->categorie->make_cat_select($this->parent_id);
444
445
		if ($this->action == 'sync' || $this->action == 'sync_cat')
446
		{
447
			$this->template->assign_var('S_RESYNCED', true);
448
		}
449
450
		$sql = 'SELECT cat_id, parent_id, right_id, left_id, cat_name, cat_icon, cat_desc_uid, cat_desc_bitfield, cat_desc, cat_desc_options, cat_links
451
			FROM ' . $this->categories_table . '
452
			WHERE parent_id = ' . (int) $this->parent_id . '
453
			ORDER BY left_id';
454
		$result = $this->db->sql_query($sql);
455
456
		if ($row = $this->db->sql_fetchrow($result))
457
		{
458
			do
459
			{
460
				$folder_image = ($row['left_id'] + 1 != $row['right_id']) ? '<img src="images/icon_subfolder.gif" alt="' . $this->language->lang('DIR_SUBCAT') . '" />' : '<img src="images/icon_folder.gif" alt="' . $this->language->lang('FOLDER') . '" />';
461
462
				$url = $this->u_action . "&amp;parent_id=$this->parent_id&amp;c={$row['cat_id']}";
463
464
				$this->template->assign_block_vars('cats', array(
465
					'FOLDER_IMAGE'		=> $folder_image,
466
					'CAT_IMAGE'			=> ($row['cat_icon']) ? '<img src="' . $this->get_img_path('icons', $row['cat_icon']) . '" alt="" />' : '',
467
					'CAT_NAME'			=> $row['cat_name'],
468
					'CAT_DESCRIPTION'	=> generate_text_for_display($row['cat_desc'], $row['cat_desc_uid'], $row['cat_desc_bitfield'], $row['cat_desc_options']),
469
					'CAT_LINKS'			=> $row['cat_links'],
470
471
					'U_CAT'				=> $this->u_action . '&amp;parent_id=' . $row['cat_id'],
472
					'U_MOVE_UP'			=> $url . '&amp;action=move_up',
473
					'U_MOVE_DOWN'		=> $url . '&amp;action=move_down',
474
					'U_EDIT'			=> $url . '&amp;action=edit',
475
					'U_DELETE'			=> $url . '&amp;action=delete',
476
					'U_SYNC'			=> $url . '&amp;action=sync')
477
				);
478
			}
479
			while ($row = $this->db->sql_fetchrow($result));
480
		}
481
		else if ($this->parent_id)
482
		{
483
			$row = $this->_get_cat_info($this->parent_id);
484
485
			$url = $this->u_action . '&amp;parent_id=' . $this->parent_id . '&amp;c=' . $row['cat_id'];
486
487
			$this->template->assign_vars(array(
488
				'S_NO_CATS'			=> true,
489
490
				'U_EDIT'			=> $url . '&amp;action=edit',
491
				'U_DELETE'			=> $url . '&amp;action=delete',
492
				'U_SYNC'			=> $url . '&amp;action=sync')
493
			);
494
		}
495
		$this->db->sql_freeresult($result);
496
497
		$this->template->assign_vars(array(
498
			'ERROR_MSG'		=> (count($this->errors)) ? implode('<br />', $this->errors) : '',
499
			'NAVIGATION'	=> $navigation,
500
			'CAT_BOX'		=> $cat_box,
501
			'U_SEL_ACTION'	=> $this->u_action,
502
			'U_ACTION'		=> $this->u_action . '&amp;parent_id=' . $this->parent_id,
503
504
			'UA_PROGRESS_BAR'	=> $this->u_action . '&amp;action=progress_bar',
505
		));
506
	}
507
508
	/**
509
	* Set page url
510
	*
511
	* @param	string $u_action Custom form action
512
	* @return	null
513
	* @access	public
514
	*/
515
	public function set_page_url($u_action)
516
	{
517
		$this->u_action = $u_action;
518
	}
519
520
	/**
521
	* Update cat table
522
	*
523
	* @return null
524
	*/
525
	public function update()
526
	{
527
		if (!check_form_key($this->form_key))
528
		{
529
			$this->update = false;
530
			$this->errors[] = $this->language->lang('FORM_INVALID');
531
			return;
532
		}
533
534
		switch ($this->action)
535
		{
536
			case 'delete':
537
				$action_subcats	= $this->request->variable('action_subcats', '');
538
				$subcats_to_id	= $this->request->variable('subcats_to_id', 0);
539
				$action_links	= $this->request->variable('action_links', '');
540
				$links_to_id	= $this->request->variable('links_to_id', 0);
541
542
				try
543
				{
544
					$this->errors = $this->_delete_cat($action_links, $action_subcats, $links_to_id, $subcats_to_id);
545
				}
546
				catch (\Exception $e)
547
				{
548
					trigger_error($e->getMessage(), E_USER_WARNING);
549
				}
550
551
				$message = 'DIR_CAT_DELETED';
552
553
				break;
554
555
			case 'edit':
556
				$this->cat_data = array(
557
					'cat_id'		=>	$this->cat_id
558
				);
559
				// No break here
560
			case 'add':
561
562
				$this->cat_data += array(
563
					'parent_id'				=> $this->request->variable('cat_parent_id', (int) $this->parent_id),
564
					'cat_parents'			=> '',
565
					'cat_name'				=> $this->request->variable('cat_name', '', true),
566
					'cat_route'				=> $this->request->variable('cat_route', ''),
567
					'cat_desc'				=> $this->request->variable('cat_desc', '', true),
568
					'cat_desc_uid'			=> '',
569
					'cat_desc_options'		=> 7,
570
					'cat_desc_bitfield'		=> '',
571
					'cat_icon'				=> $this->request->variable('cat_icon', ''),
572
					'display_subcat_list'	=> $this->request->variable('display_on_index', false),
573
					'cat_allow_comments'	=> $this->request->variable('allow_comments', 1),
574
					'cat_allow_votes'		=> $this->request->variable('allow_votes', 1),
575
					'cat_must_describe'		=> $this->request->variable('must_describe', 1),
576
					'cat_count_all'			=> $this->request->variable('count_all', 0),
577
					'cat_validate'			=> $this->request->variable('validate', 0),
578
					'cat_link_back'			=> $this->request->variable('link_back', 0),
579
					'cat_cron_enable'		=> $this->request->variable('cron_enable', 0),
580
					'cat_cron_freq'			=> $this->request->variable('cron_every', 7),
581
					'cat_cron_nb_check'		=> $this->request->variable('nb_check', 1),
582
				);
583
584
				// Get data for cat description if specified
585
				if ($this->cat_data['cat_desc'])
586
				{
587
					generate_text_for_storage($this->cat_data['cat_desc'], $this->cat_data['cat_desc_uid'], $this->cat_data['cat_desc_bitfield'], $this->cat_data['cat_desc_options'], $this->request->variable('desc_parse_bbcode', false), $this->request->variable('desc_parse_urls', false), $this->request->variable('desc_parse_smilies', false));
588
				}
589
590
				try
591
				{
592
					$this->errors = $this->_update_cat_data();
593
				}
594
				catch (\Exception $e)
595
				{
596
					trigger_error($e->getMessage(), E_USER_WARNING);
597
				}
598
599
				$message = ($this->action == 'add') ? 'DIR_CAT_CREATED' : 'DIR_CAT_UPDATED';
600
601
			break;
602
		}
603
604 View Code Duplication
		if (!count($this->errors))
605
		{
606
			// Purge the cache to refresh route collections
607
			$this->cache->purge();
608
609
			trigger_error($this->language->lang($message) . adm_back_link($this->u_action . '&amp;parent_id=' . $this->parent_id));
610
		}
611
	}
612
613
	/**
614
	* Check route
615
	*
616
	* @param string $route Route text
617
	* @return null
618
	* @access public
619
	* @throws \phpbb\pages\exception\unexpected_value
620
	*/
621
	private function _check_route($route)
622
	{
623
		// Route is a required field
624
		if (empty($route))
625
		{
626
			$this->errors[] = $this->language->lang('DIR_CAT_ROUTE_EMPTY');
627
			return;
628
		}
629
630
		// Route should not contain any unexpected special characters
631
		if (!preg_match('/^[^!"#$%&*\'()+,.\/\\\\:;<=>?@\\[\\]^`{|}~ ]*$/', $route))
632
		{
633
			$this->errors[] = $this->language->lang('DIR_CAT_ROUTE_ILLEGAL_CHARACTERS');
634
		}
635
636
		$sql = 'SELECT cat_route
637
			FROM ' . $this->categories_table  . "
638
			WHERE cat_route = '" . $this->db->sql_escape($route) . "'
639
				AND cat_id <> " . $this->cat_id;
640
		$result = $this->db->sql_query_limit($sql, 1);
641
		$row = $this->db->sql_fetchrow($result);
642
		$this->db->sql_freeresult($result);
643
644
		if ($row)
645
		{
646
			$this->errors[] = $this->language->lang('DIR_CAT_ROUTE_NOT_UNIQUE');
647
		}
648
	}
649
650
	/**
651
	* Display form
652
	*
653
	* @param	string $parents_list	Drop-down list
654
	* @return	null
655
	*/
656
	private function _display_cat_form($parents_list)
657
	{
658
		$dir_cat_desc_data = array(
659
			'text'			=> $this->cat_data['cat_desc'],
660
			'allow_bbcode'	=> true,
661
			'allow_smilies'	=> true,
662
			'allow_urls'	=> true
663
		);
664
665
		// Parse desciption if specified
666
		if ($this->cat_data['cat_desc'])
667
		{
668
			if (!isset($this->cat_data['cat_desc_uid']))
669
			{
670
				// Before we are able to display the preview and plane text, we need to parse our $request->variable()'d value...
671
				$this->cat_data['cat_desc_uid'] = '';
672
				$this->cat_data['cat_desc_bitfield'] = '';
673
				$this->cat_data['cat_desc_options'] = 0;
674
675
				generate_text_for_storage($this->cat_data['cat_desc'], $this->cat_data['cat_desc_uid'], $this->cat_data['cat_desc_bitfield'], $this->cat_data['cat_desc_options'], $this->request->variable('desc_allow_bbcode', false), $this->request->variable('desc_allow_urls', false), $this->request->variable('desc_allow_smilies', false));
676
			}
677
678
			// decode...
679
			$dir_cat_desc_data = generate_text_for_edit($this->cat_data['cat_desc'], $this->cat_data['cat_desc_uid'], $this->cat_data['cat_desc_options']);
680
		}
681
682
		$this->template->assign_vars(array(
683
			'S_EDIT_CAT'		=> true,
684
			'S_ERROR'			=> (count($this->errors)) ? true : false,
685
			'S_CAT_PARENT_ID'	=> $this->cat_data['parent_id'],
686
			'S_ADD_ACTION'		=> ($this->action == 'add') ? true : false,
687
688
			'U_BACK'			=> $this->u_action . '&amp;parent_id=' . $this->parent_id,
689
			'U_EDIT_ACTION'		=> $this->u_action . "&amp;parent_id={$this->parent_id}&amp;action=$this->action&amp;c=$this->cat_id",
690
691
			'L_TITLE'					=> $this->language->lang('DIR_' . strtoupper($this->action) . '_CAT'),
692
			'ERROR_MSG'					=> (count($this->errors)) ? implode('<br />', $this->errors) : '',
693
			'ICON_IMAGE'				=> ($this->cat_data['cat_icon']) ? $this->get_img_path('icons', $this->cat_data['cat_icon']) : 'images/spacer.gif',
694
695
			'DIR_ICON_PATH'				=> $this->get_img_path('icons'),
696
			'DIR_CAT_NAME'				=> $this->cat_data['cat_name'],
697
			'DIR_CAT_ROUTE'				=> $this->cat_data['cat_route'],
698
			'DIR_CAT_DESC'				=> $dir_cat_desc_data['text'],
699
700
			'S_DESC_BBCODE_CHECKED'		=> ($dir_cat_desc_data['allow_bbcode']) ? true : false,
701
			'S_DESC_SMILIES_CHECKED'	=> ($dir_cat_desc_data['allow_smilies']) ? true : false,
702
			'S_DESC_URLS_CHECKED'		=> ($dir_cat_desc_data['allow_urls']) ? true : false,
703
			'S_DISPLAY_SUBCAT_LIST'		=> ($this->cat_data['display_subcat_list']) ? true : false,
704
			'S_PARENT_OPTIONS'			=> $parents_list,
705
			'S_ICON_OPTIONS'			=> $this->_get_dir_icon_list($this->get_img_path('icons'), $this->cat_data['cat_icon']),
706
			'S_ALLOW_COMMENTS'			=> ($this->cat_data['cat_allow_comments']) ? true : false,
707
			'S_ALLOW_VOTES'				=> ($this->cat_data['cat_allow_votes']) ? true : false,
708
			'S_MUST_DESCRIBE'			=> ($this->cat_data['cat_must_describe']) ? true : false,
709
			'S_COUNT_ALL'				=> ($this->cat_data['cat_count_all']) ? true : false,
710
			'S_VALIDATE'				=> ($this->cat_data['cat_validate']) ? true : false,
711
712
			'DIR_CRON_EVERY'			=> $this->cat_data['cat_cron_freq'],
713
			'DIR_NEXT_CRON_ACTION'		=> !empty($this->cat_data['cat_cron_next']) ? $this->user->format_date($this->cat_data['cat_cron_next']) : '-',
714
			'DIR_CRON_NB_CHECK'			=> $this->cat_data['cat_cron_nb_check'],
715
716
			'S_LINK_BACK'				=> ($this->cat_data['cat_link_back']) ? true : false,
717
			'S_CRON_ENABLE'				=> ($this->cat_data['cat_cron_enable']) ? true : false,
718
719
			'U_DATE'					=> $this->helper->route('ernadoo_phpbbdirectory_ajax_date_controller'),
720
			'U_SLUG'					=> $this->helper->route('ernadoo_phpbbdirectory_ajax_slug_controller'),
721
		));
722
723
		return;
724
	}
725
726
	/**
727
	* Get category details
728
	*
729
	* @param	int		$cat_id	The category ID
730
	* @return 	array
731
	*/
732 View Code Duplication
	private function _get_cat_info($cat_id)
733
	{
734
		$sql = 'SELECT cat_id, parent_id, right_id, left_id, cat_desc, cat_desc_uid, cat_desc_options, cat_icon, cat_name, cat_route, display_subcat_list, cat_allow_comments, cat_allow_votes, cat_must_describe, cat_count_all, cat_validate, cat_cron_freq, cat_cron_nb_check, cat_link_back, cat_cron_enable, cat_cron_next
735
			FROM ' . $this->categories_table . '
736
			WHERE cat_id = ' . (int) $cat_id;
737
		$result = $this->db->sql_query($sql);
738
		$row = $this->db->sql_fetchrow($result);
739
		$this->db->sql_freeresult($result);
740
741
		if (!$row)
742
		{
743
			trigger_error('DIR_ERROR_NO_CATS', E_USER_ERROR);
744
		}
745
746
		return $row;
747
	}
748
749
	/**
750
	* Update category data
751
	*
752
	* @return array
753
	*/
754
	private function _update_cat_data()
755
	{
756
		if (!$this->cat_data['cat_name'])
757
		{
758
			$this->errors[] = $this->language->lang('DIR_CAT_NAME_EMPTY');
759
		}
760
761
		$this->_check_route($this->cat_data['cat_route']);
762
763
		if (utf8_strlen($this->cat_data['cat_desc']) > 4000)
764
		{
765
			$this->errors[] = $this->language->lang('DIR_CAT_DESC_TOO_LONG');
766
		}
767
768
		if (($this->cat_data['cat_cron_enable'] && $this->cat_data['cat_cron_freq'] <= 0) || $this->cat_data['cat_cron_nb_check'] < 0)
769
		{
770
			$this->errors[] = $this->language->lang('DIR_CAT_DATA_NEGATIVE');
771
		}
772
773
		// Unset data that are not database fields
774
		$cat_data_sql = $this->cat_data;
775
776
		// What are we going to do tonight Brain? The same thing we do everynight,
777
		// try to take over the world ... or decide whether to continue update
778
		// and if so, whether it's a new cat/link or an existing one
779
		if (count($this->errors))
780
		{
781
			return $this->errors;
782
		}
783
784
		if (!$cat_data_sql['cat_link_back'])
785
		{
786
			$cat_data_sql['cat_cron_enable'] = 0;
787
			$cat_data_sql['cat_cron_next'] = 0;
788
		}
789
790
		if (!$cat_data_sql['parent_id'])
791
		{
792
			$cat_data_sql['display_subcat_list'] = 0;
793
		}
794
795
		// no cat_id means we're creating a new categorie
796
		if (!isset($cat_data_sql['cat_id']))
797
		{
798
			if ($cat_data_sql['cat_cron_enable'])
799
			{
800
				$cat_data_sql['cat_cron_next'] = time() + $cat_data_sql['cat_cron_freq']*86400;
801
			}
802
803
			$this->cat_data = $this->nestedset_category->insert($cat_data_sql);
804
805
			if ($cat_data_sql['parent_id'])
806
			{
807
				$this->nestedset_category->change_parent($this->cat_data['cat_id'], $cat_data_sql['parent_id']);
808
			}
809
810
			$this->phpbb_log->add('admin', $this->user->data['user_id'], $this->user->ip, 'LOG_DIR_CAT_ADD', time(), array($this->cat_data['cat_name']));
811
		}
812
		else
813
		{
814
			$row = $this->_get_cat_info($cat_data_sql['cat_id']);
815
816
			if ($row['parent_id'] != $cat_data_sql['parent_id'])
817
			{
818
				$this->nestedset_category->change_parent($cat_data_sql['cat_id'], $cat_data_sql['parent_id']);
819
			}
820
821
			if ($cat_data_sql['cat_cron_enable'] && ($row['cat_cron_freq'] != $cat_data_sql['cat_cron_freq'] || !$row['cat_cron_enable']))
822
			{
823
				$cat_data_sql['cat_cron_next'] = time() + $cat_data_sql['cat_cron_freq']*86400;
824
			}
825
826
			if ($row['cat_name'] != $cat_data_sql['cat_name'])
827
			{
828
				// the cat name has changed, clear the parents list of all categories (for safety)
829
				$sql = 'UPDATE ' . $this->categories_table . "
830
					SET cat_parents = ''";
831
				$this->db->sql_query($sql);
832
			}
833
834
			// Setting the cat id to the categorie id is not really received well by some dbs. ;)
835
			unset($cat_data_sql['cat_id']);
836
837
			$sql = 'UPDATE ' . $this->categories_table . '
838
				SET ' . $this->db->sql_build_array('UPDATE', $cat_data_sql) . '
839
				WHERE cat_id = ' . (int) $this->cat_id;
840
			$this->db->sql_query($sql);
841
842
			$this->phpbb_log->add('admin', $this->user->data['user_id'], $this->user->ip, 'LOG_DIR_CAT_EDIT', time(), array($this->cat_data['cat_name']));
843
		}
844
845
		return $this->errors;
846
	}
847
848
	/**
849
	* Remove complete category
850
	*
851
	* @param	string		$action_links	Action for categories links
852
	* @param	string		$action_subcats	Action for sub-categories
853
	* @param	int			$links_to_id	New category ID for links
854
	* @param	int			$subcats_to_id	New category ID for sub-categories
855
	* @return 	array|null
856
	*/
857
	private function _delete_cat($action_links = 'delete', $action_subcats = 'delete', $links_to_id = 0, $subcats_to_id = 0)
858
	{
859
		$this->cat_data = $this->_get_cat_info($this->cat_id);
860
861
		$log_action_links = $log_action_cats = $links_to_name = $subcats_to_name = '';
862
863
		if ($action_links == 'delete')
864
		{
865
			$log_action_links = 'LINKS';
866
			$this->_delete_cat_content();
867
		}
868
		else if ($action_links == 'move')
869
		{
870
			if (!$links_to_id)
871
			{
872
				$this->errors[] = $this->language->lang('DIR_NO_DESTINATION_CAT');
873
			}
874
			else
875
			{
876
				$log_action_links = 'MOVE_LINKS';
877
878
				$sql = 'SELECT cat_name
879
					FROM ' . $this->categories_table . '
880
					WHERE cat_id = ' . (int) $links_to_id;
881
				$result = $this->db->sql_query($sql);
882
				$row = $this->db->sql_fetchrow($result);
883
				$this->db->sql_freeresult($result);
884
885
				if (!$row)
886
				{
887
					throw new \OutOfBoundsException('DIR_NO_CAT');
888
				}
889
				else
890
				{
891
					$links_to_name = $row['cat_name'];
892
					$this->_move_cat_content($this->cat_id, $links_to_id);
893
				}
894
			}
895
		}
896
897
		if (count($this->errors))
898
		{
899
			return $this->errors;
900
		}
901
902
		if ($action_subcats == 'delete')
903
		{
904
			$log_action_cats = 'CATS';
905
		}
906
		else if ($action_subcats == 'move')
907
		{
908
			if (!$subcats_to_id)
909
			{
910
				$this->errors[] = $this->language->lang('DIR_NO_DESTINATION_CAT');
911
			}
912
			else
913
			{
914
				$log_action_cats = 'MOVE_CATS';
915
916
				$subcats_to_name = $row['cat_name'];
917
				$this->nestedset_category->move_children($this->cat_id, $subcats_to_id);
918
			}
919
		}
920
921
		if (count($this->errors))
922
		{
923
			return $this->errors;
924
		}
925
926
		$this->nestedset_category->delete($this->cat_id);
927
928
		$log_action = implode('_', array($log_action_links, $log_action_cats));
929
930
		switch ($log_action)
931
		{
932 View Code Duplication
			case 'MOVE_LINKS_MOVE_CATS':
933
				$this->phpbb_log->add('admin', $this->user->data['user_id'], $this->user->ip, 'LOG_DIR_CAT_DEL_MOVE_LINKS_MOVE_CATS', time(), array($links_to_name, $subcats_to_name, $this->cat_data['cat_name']));
934
			break;
935
936 View Code Duplication
			case 'MOVE_LINKS_CATS':
937
				$this->phpbb_log->add('admin', $this->user->data['user_id'], $this->user->ip, 'LOG_DIR_CAT_DEL_MOVE_LINKS_CATS', time(), array($links_to_name, $this->cat_data['cat_name']));
938
			break;
939
940 View Code Duplication
			case 'LINKS_MOVE_CATS':
941
				$this->phpbb_log->add('admin', $this->user->data['user_id'], $this->user->ip, 'LOG_DIR_CAT_DEL_LINKS_MOVE_CATS', time(), array($subcats_to_name, $this->cat_data['cat_name']));
942
			break;
943
944 View Code Duplication
			case '_MOVE_CATS':
945
				$this->phpbb_log->add('admin', $this->user->data['user_id'], $this->user->ip, 'LOG_DIR_CAT_DEL_MOVE_CATS', time(), array($subcats_to_name, $this->cat_data['cat_name']));
946
			break;
947
948 View Code Duplication
			case 'MOVE_LINKS_':
949
				$this->phpbb_log->add('admin', $this->user->data['user_id'], $this->user->ip, 'LOG_DIR_CAT_DEL_MOVE_LINKS', time(), array($links_to_name, $this->cat_data['cat_name']));
950
			break;
951
952 View Code Duplication
			case 'LINKS_CATS':
953
				$this->phpbb_log->add('admin', $this->user->data['user_id'], $this->user->ip, 'LOG_DIR_CAT_DEL_LINKS_CATS', time(), array($this->cat_data['cat_name']));
954
			break;
955
956 View Code Duplication
			case '_CATS':
957
				$this->phpbb_log->add('admin', $this->user->data['user_id'], $this->user->ip, 'LOG_DIR_CAT_DEL_CATS', time(), array($this->cat_data['cat_name']));
958
			break;
959
960 View Code Duplication
			case 'LINKS_':
961
				$this->phpbb_log->add('admin', $this->user->data['user_id'], $this->user->ip, 'LOG_DIR_CAT_DEL_LINKS', time(), array($this->cat_data['cat_name']));
962
			break;
963
964 View Code Duplication
			default:
965
				$this->phpbb_log->add('admin', $this->user->data['user_id'], $this->user->ip, 'LOG_DIR_CAT_DEL_CAT', time(), array($this->cat_data['cat_name']));
966
			break;
967
		}
968
	}
969
970
	/**
971
	* Move category content from one to another forum
972
	*
973
	* @param	int	$from_id
974
	* @param	int	$to_id
975
	* @return	null
976
	*/
977
	private function _move_cat_content($from_id, $to_id)
978
	{
979
		$sql = 'UPDATE ' . $this->links_table . '
980
			SET link_cat = ' . (int) $to_id . '
981
			WHERE link_cat = ' . (int) $from_id;
982
		$this->db->sql_query($sql);
983
984
		$sql = 'DELETE FROM ' . $this->watch_table . '
985
			WHERE cat_id = ' . (int) $from_id;
986
		$this->db->sql_query($sql);
987
988
		$this->_sync_dir_cat($to_id);
989
	}
990
991
	/**
992
	* Delete category content
993
	*
994
	* @return null
995
	*/
996
	private function _delete_cat_content()
997
	{
998
		$this->db->sql_transaction('begin');
999
1000
		// Before we remove anything we make sure we are able to adjust the post counts later. ;)
1001
		$sql = 'SELECT link_id, link_banner
1002
			FROM ' . $this->links_table . '
1003
			WHERE link_cat = ' . (int) $this->cat_id;
1004
		$result = $this->db->sql_query($sql);
1005
1006
		$link_ids = array();
1007
		while ($row = $this->db->sql_fetchrow($result))
1008
		{
1009
			$link_ids[] = $row['link_id'];
1010
1011 View Code Duplication
			if ($row['link_banner'] && !preg_match('/^(http:\/\/|https:\/\/|ftp:\/\/|ftps:\/\/|www\.).+/si', $row['link_banner']))
1012
			{
1013
				$banner_img = $this->get_banner_path(basename($row['link_banner']));
1014
1015
				if (file_exists($banner_img))
1016
				{
1017
					@unlink($banner_img);
1018
				}
1019
			}
1020
		}
1021
		$this->db->sql_freeresult($result);
1022
1023
		if (count($link_ids))
1024
		{
1025
			// Delete links datas
1026
			$link_datas_ary = array(
1027
				$this->comments_table	=> 'comment_link_id',
1028
				$this->votes_table		=> 'vote_link_id',
1029
			);
1030
1031
			foreach ($link_datas_ary as $table => $field)
1032
			{
1033
				$this->db->sql_query("DELETE FROM $table WHERE " . $this->db->sql_in_set($field, $link_ids));
1034
			}
1035
		}
1036
1037
		// Delete cats datas
1038
		$cat_datas_ary = array(
1039
			$this->links_table	=> 'link_cat',
1040
			$this->watch_table	=> 'cat_id',
1041
		);
1042
1043
		foreach ($cat_datas_ary as $table => $field)
1044
		{
1045
			$this->db->sql_query("DELETE FROM $table WHERE $field = " . (int) $this->cat_id);
1046
		}
1047
1048
		$this->db->sql_transaction('commit');
1049
	}
1050
1051
	/**
1052
	* Update links counter
1053
	*
1054
	* @param	int $cat_id	The category ID
1055
	* @return	null
1056
	*/
1057
	private function _sync_dir_cat($cat_id)
1058
	{
1059
		$sql = 'SELECT COUNT(link_id) AS num_links
1060
			FROM ' . $this->links_table . '
1061
			WHERE link_cat = ' . (int) $cat_id . '
1062
				AND link_active = 1';
1063
		$result = $this->db->sql_query($sql);
1064
		$total_links = (int) $this->db->sql_fetchfield('num_links');
1065
		$this->db->sql_freeresult($result);
1066
1067
		$sql = 'UPDATE ' . $this->categories_table . '
1068
			SET cat_links = ' . $total_links . '
1069
			WHERE cat_id = ' . (int) $cat_id;
1070
		$this->db->sql_query($sql);
1071
	}
1072
1073
	/**
1074
	* Update link data (note, vote, comment)
1075
	*
1076
	* @param	int	$start
1077
	* @param	int	$stop
1078
	* @return	null
1079
	*/
1080
	private function _sync_dir_links($start, $stop)
1081
	{
1082
		$sql_ary = array(
1083
			'link_comment'	=> 0,
1084
			'link_note'		=> 0,
1085
			'link_vote'		=> 0,
1086
		);
1087
1088
		$sql = 'UPDATE ' . $this->links_table . '
1089
			SET ' . $this->db->sql_build_array('UPDATE', $sql_ary) . '
1090
			WHERE link_id BETWEEN ' . (int) $start . ' AND ' . (int) $stop;
1091
		$this->db->sql_query($sql);
1092
1093
		$sql = 'SELECT vote_link_id, COUNT(vote_note) AS nb_vote, SUM(vote_note) AS total FROM ' . $this->votes_table . '
1094
			WHERE vote_link_id BETWEEN ' . (int) $start . ' AND ' . (int) $stop . '
1095
			GROUP BY vote_link_id';
1096
		$result = $this->db->sql_query($sql);
1097
		while ($tmp = $this->db->sql_fetchrow($result))
1098
		{
1099
			$sql = 'UPDATE ' . $this->links_table . '
1100
				SET link_note = ' . (int) $tmp['total'] . ', link_vote = ' . (int) $tmp['nb_vote'] . '
1101
				WHERE link_id = ' . (int) $tmp['vote_link_id'];
1102
			$this->db->sql_query($sql);
1103
		}
1104
		$this->db->sql_freeresult($result);
1105
1106
		$sql = 'SELECT 	comment_link_id, COUNT(comment_id) AS nb_comment
1107
			FROM ' . $this->comments_table . '
1108
			WHERE comment_link_id BETWEEN ' . (int) $start . ' AND ' . (int) $stop . '
1109
			GROUP BY comment_link_id';
1110
		$result = $this->db->sql_query($sql);
1111
		while ($tmp = $this->db->sql_fetchrow($result))
1112
		{
1113
			$sql = 'UPDATE ' . $this->links_table . '
1114
				SET link_comment = ' . (int) $tmp['nb_comment'] . '
1115
				WHERE link_id = ' . (int) $tmp['comment_link_id'];
1116
			$this->db->sql_query($sql);
1117
		}
1118
		$this->db->sql_freeresult($result);
1119
	}
1120
1121
	/**
1122
	* Display icons drop-down list
1123
	*
1124
	* @param	string	$icons_path
1125
	* @param	string	$img_selected
1126
	* @return	string
1127
	*/
1128
	private function _get_dir_icon_list($icons_path, $img_selected)
1129
	{
1130
		$imglist = filelist($icons_path, '');
1131
		$filename_list = '<option value="">----------</option>';
1132
1133
		foreach ($imglist as $path => $img_ary)
1134
		{
1135
			sort($img_ary);
1136
1137
			foreach ($img_ary as $img)
1138
			{
1139
				$img = $path . $img;
1140
				$selected = '';
1141
1142
				if (strlen($img) > 255)
1143
				{
1144
					continue;
1145
				}
1146
1147
				if ($img == $img_selected)
1148
				{
1149
					$selected = ' selected="selected"';
1150
				}
1151
1152
				$filename_list .= '<option value="' . htmlspecialchars($img) . '"' . $selected . '>' . $img . '</option>';
1153
			}
1154
		}
1155
1156
		return ($filename_list);
1157
	}
1158
}
1159