Completed
Pull Request — master (#25)
by Erwan
04:33
created

cat::_delete_cat_content()   C

Complexity

Conditions 8
Paths 16

Size

Total Lines 50
Code Lines 27

Duplication

Lines 9
Ratio 18 %

Importance

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