1
|
|
|
<?php |
2
|
|
|
/** |
3
|
|
|
* The main category class |
4
|
|
|
* |
5
|
|
|
* PHP Version 5.3 |
6
|
|
|
* |
7
|
|
|
* This Source Code Form is subject to the terms of the Mozilla Public License, |
8
|
|
|
* v. 2.0. If a copy of the MPL was not distributed with this file, You can |
9
|
|
|
* obtain one at http://mozilla.org/MPL/2.0/. |
10
|
|
|
* |
11
|
|
|
* @category phpMyFAQ |
12
|
|
|
* @package Category |
13
|
|
|
* @author Thorsten Rinne <[email protected]> |
14
|
|
|
* @author Lars Tiedemann <[email protected]> |
15
|
|
|
* @author Matteo Scaramuccia <[email protected]> |
16
|
|
|
* @author Rudi Ferrari <[email protected]> |
17
|
|
|
* @copyright 2004-2016 phpMyFAQ Team |
18
|
|
|
* @license http://www.mozilla.org/MPL/2.0/ Mozilla Public License Version 2.0 |
19
|
|
|
* @link http://www.phpmyfaq.de |
20
|
|
|
* @since 2004-02-16 |
21
|
|
|
*/ |
22
|
|
|
|
23
|
|
|
if (!defined('IS_VALID_PHPMYFAQ')) { |
24
|
|
|
exit(); |
25
|
|
|
} |
26
|
|
|
|
27
|
|
|
/** |
28
|
|
|
* Category |
29
|
|
|
* |
30
|
|
|
* @category phpMyFAQ |
31
|
|
|
* @package Category |
32
|
|
|
* @author Thorsten Rinne <[email protected]> |
33
|
|
|
* @author Lars Tiedemann <[email protected]> |
34
|
|
|
* @author Matteo Scaramuccia <[email protected]> |
35
|
|
|
* @author Rudi Ferrari <[email protected]> |
36
|
|
|
* @copyright 2004-2016 phpMyFAQ Team |
37
|
|
|
* @license http://www.mozilla.org/MPL/2.0/ Mozilla Public License Version 2.0 |
38
|
|
|
* @link http://www.phpmyfaq.de |
39
|
|
|
* @since 2004-02-16 |
40
|
|
|
*/ |
41
|
|
|
class PMF_Category |
42
|
|
|
{ |
43
|
|
|
/** |
44
|
|
|
* @var PMF_Configuration |
45
|
|
|
*/ |
46
|
|
|
private $_config = null; |
47
|
|
|
|
48
|
|
|
/** |
49
|
|
|
* User ID |
50
|
|
|
* |
51
|
|
|
* @var integer |
52
|
|
|
*/ |
53
|
|
|
private $user = -1; |
54
|
|
|
|
55
|
|
|
/** |
56
|
|
|
* Groupd |
57
|
|
|
* |
58
|
|
|
* @var array |
59
|
|
|
*/ |
60
|
|
|
private $groups = array(-1); |
61
|
|
|
|
62
|
|
|
/** |
63
|
|
|
* |
64
|
|
|
* The categories as an array. |
65
|
|
|
* |
66
|
|
|
* @var array |
67
|
|
|
*/ |
68
|
|
|
public $categories = array(); |
69
|
|
|
|
70
|
|
|
/** |
71
|
|
|
* The category names as an array. |
72
|
|
|
* |
73
|
|
|
* @var array |
74
|
|
|
*/ |
75
|
|
|
public $categoryName = array(); |
76
|
|
|
|
77
|
|
|
/** |
78
|
|
|
* The category tree |
79
|
|
|
* |
80
|
|
|
* @var array |
81
|
|
|
*/ |
82
|
|
|
public $catTree = array(); |
83
|
|
|
|
84
|
|
|
/** |
85
|
|
|
* The children nodes |
86
|
|
|
* |
87
|
|
|
* @var array |
88
|
|
|
*/ |
89
|
|
|
private $children = array(); |
90
|
|
|
|
91
|
|
|
/** |
92
|
|
|
* The current language |
93
|
|
|
* |
94
|
|
|
* @var string |
95
|
|
|
*/ |
96
|
|
|
private $language = null; |
97
|
|
|
|
98
|
|
|
/** |
99
|
|
|
* The lines of tabs |
100
|
|
|
* |
101
|
|
|
* @var array |
102
|
|
|
*/ |
103
|
|
|
private $lineTab = array(); |
104
|
|
|
|
105
|
|
|
/** |
106
|
|
|
* The tree with the tabs |
107
|
|
|
* |
108
|
|
|
* @var array |
109
|
|
|
*/ |
110
|
|
|
public $treeTab = array(); |
111
|
|
|
|
112
|
|
|
/** |
113
|
|
|
* Category owners |
114
|
|
|
* |
115
|
|
|
* @var array |
116
|
|
|
*/ |
117
|
|
|
private $owner = array(); |
118
|
|
|
|
119
|
|
|
/** |
120
|
|
|
* Symbol for each item |
121
|
|
|
* NOTE: We do not use this currently |
122
|
|
|
* |
123
|
|
|
* @var array |
124
|
|
|
*/ |
125
|
|
|
private $symbols = array( |
126
|
|
|
'vertical' => '|', |
127
|
|
|
'plus' => '+', |
128
|
|
|
'minus' => '-', |
129
|
|
|
'space' => ' ', |
130
|
|
|
'angle' => '-', |
131
|
|
|
'medium' => '|-'); |
132
|
|
|
|
133
|
|
|
/** |
134
|
|
|
* Constructor |
135
|
|
|
* |
136
|
|
|
* @param PMF_Configuration $config Configuration object |
137
|
|
|
* @param array $groups Array with group IDs |
138
|
|
|
* @param boolean $withperm With or without permission check |
139
|
|
|
* |
140
|
|
|
* @return PMF_Category |
141
|
|
|
*/ |
142
|
|
|
public function __construct(PMF_Configuration $config, $groups = array(), $withperm = true) |
143
|
|
|
{ |
144
|
|
|
$this->_config = $config; |
145
|
|
|
$this->setGroups($groups); |
146
|
|
|
$this->setLanguage($this->_config->getLanguage()->getLanguage()); |
147
|
|
|
|
148
|
|
|
$this->lineTab = $this->getOrderedCategories($withperm); |
149
|
|
|
for ($i = 0; $i < count($this->lineTab); $i++) { |
150
|
|
|
$this->lineTab[$i]['level'] = $this->levelOf($this->lineTab[$i]['id']); |
151
|
|
|
} |
152
|
|
|
} |
153
|
|
|
|
154
|
|
|
/** |
155
|
|
|
* @param integer $userId |
156
|
|
|
*/ |
157
|
|
|
public function setUser($userId = -1) |
158
|
|
|
{ |
159
|
|
|
$this->user = $userId; |
160
|
|
|
} |
161
|
|
|
|
162
|
|
|
/** |
163
|
|
|
* @param array $groups |
164
|
|
|
*/ |
165
|
|
|
public function setGroups(Array $groups) |
166
|
|
|
{ |
167
|
|
|
if (0 === count($groups)) { |
168
|
|
|
$groups = array(-1); |
169
|
|
|
} |
170
|
|
|
$this->groups = $groups; |
171
|
|
|
} |
172
|
|
|
|
173
|
|
|
/** |
174
|
|
|
* Returns all categories with ordered category IDs according to the user |
175
|
|
|
* and group permissions |
176
|
|
|
* |
177
|
|
|
* @param boolean $withperm With or without permission check |
178
|
|
|
* @return array |
179
|
|
|
*/ |
180
|
|
|
private function getOrderedCategories($withperm = true) |
181
|
|
|
{ |
182
|
|
|
$where = ''; |
183
|
|
|
|
184
|
|
View Code Duplication |
if ($withperm) { |
185
|
|
|
$where = sprintf(" |
186
|
|
|
WHERE |
187
|
|
|
( fg.group_id IN (%s) |
188
|
|
|
OR |
189
|
|
|
(fu.user_id = %d AND fg.group_id IN (%s)))", |
190
|
|
|
implode(', ', $this->groups), |
191
|
|
|
$this->user, |
192
|
|
|
implode(', ', $this->groups)); |
193
|
|
|
} |
194
|
|
|
|
195
|
|
|
if (isset($this->language) && preg_match("/^[a-z\-]{2,}$/", $this->language)) { |
196
|
|
|
$where .= empty($where) ? ' |
197
|
|
|
WHERE' : ' |
198
|
|
|
AND'; |
199
|
|
|
$where .= " |
200
|
|
|
fc.lang = '".$this->language."'"; |
201
|
|
|
} |
202
|
|
|
|
203
|
|
|
$query = sprintf(" |
204
|
|
|
SELECT |
205
|
|
|
fc.id AS id, |
206
|
|
|
fc.lang AS lang, |
207
|
|
|
fc.parent_id AS parent_id, |
208
|
|
|
fc.name AS name, |
209
|
|
|
fc.description AS description, |
210
|
|
|
fc.user_id AS user_id |
211
|
|
|
FROM |
212
|
|
|
%sfaqcategories fc |
213
|
|
|
LEFT JOIN |
214
|
|
|
%sfaqcategory_group fg |
215
|
|
|
ON |
216
|
|
|
fc.id = fg.category_id |
217
|
|
|
LEFT JOIN |
218
|
|
|
%sfaqcategory_user fu |
219
|
|
|
ON |
220
|
|
|
fc.id = fu.category_id%s |
221
|
|
|
GROUP BY |
222
|
|
|
fc.id, fc.lang, fc.parent_id, fc.name, fc.description, fc.user_id |
223
|
|
|
ORDER BY |
224
|
|
|
fc.id", |
225
|
|
|
PMF_Db::getTablePrefix(), |
226
|
|
|
PMF_Db::getTablePrefix(), |
227
|
|
|
PMF_Db::getTablePrefix(), |
228
|
|
|
$where |
229
|
|
|
); |
230
|
|
|
|
231
|
|
|
$result = $this->_config->getDb()->query($query); |
232
|
|
|
|
233
|
|
|
while ($row = $this->_config->getDb()->fetchArray($result)) { |
234
|
|
|
$this->categoryName[$row['id']] = $row; |
235
|
|
|
$this->categories[] =& $this->categoryName[$row['id']]; |
236
|
|
|
$this->children[$row['parent_id']][$row['id']] =& $this->categoryName[$row['id']]; |
237
|
|
|
$this->owner[$row['id']] =& $row['user_id']; |
238
|
|
|
} |
239
|
|
|
|
240
|
|
|
return $this->categories; |
241
|
|
|
} |
242
|
|
|
|
243
|
|
|
/** |
244
|
|
|
* Gets the main categories and write them in an array |
245
|
|
|
* |
246
|
|
|
* @param string $categories Array of parent category ids |
247
|
|
|
* @param boolean $parent_id Only top level categories? |
248
|
|
|
* |
249
|
|
|
* @return array |
250
|
|
|
*/ |
251
|
|
|
public function getCategories($categories, $parent_id = true) |
252
|
|
|
{ |
253
|
|
|
$_query = ''; |
254
|
|
|
$query = sprintf(' |
255
|
|
|
SELECT |
256
|
|
|
id, lang, parent_id, name, description, user_id |
257
|
|
|
FROM |
258
|
|
|
%sfaqcategories |
259
|
|
|
WHERE ', |
260
|
|
|
PMF_Db::getTablePrefix()); |
261
|
|
|
|
262
|
|
|
if (true == $parent_id) { |
263
|
|
|
$query .= 'parent_id = 0'; |
264
|
|
|
} |
265
|
|
|
foreach (explode(',', $categories) as $cats) { |
266
|
|
|
$_query .= ' OR parent_id = '.$cats; |
267
|
|
|
} |
268
|
|
|
if (false == $parent_id && 0 < PMF_String::strlen($_query)) { |
269
|
|
|
$query .= PMF_String::substr($_query, 4); |
270
|
|
|
} |
271
|
|
View Code Duplication |
if (isset($this->language) && preg_match("/^[a-z\-]{2,}$/", $this->language)) { |
272
|
|
|
$query .= " AND lang = '".$this->language."'"; |
273
|
|
|
} |
274
|
|
|
$query .= " ORDER BY id"; |
275
|
|
|
$result = $this->_config->getDb()->query($query); |
276
|
|
View Code Duplication |
while ($row = $this->_config->getDb()->fetchArray($result)) { |
277
|
|
|
$this->categories[$row['id']] = $row; |
278
|
|
|
} |
279
|
|
|
return $this->categories; |
280
|
|
|
} |
281
|
|
|
|
282
|
|
|
/** |
283
|
|
|
* Gets all categories and write them in an array |
284
|
|
|
* |
285
|
|
|
* @return array |
286
|
|
|
*/ |
287
|
|
|
public function getAllCategories() |
288
|
|
|
{ |
289
|
|
|
$query = sprintf(" |
290
|
|
|
SELECT |
291
|
|
|
id, lang, parent_id, name, description, user_id |
292
|
|
|
FROM |
293
|
|
|
%sfaqcategories", |
294
|
|
|
PMF_Db::getTablePrefix()); |
295
|
|
View Code Duplication |
if (isset($this->language) && preg_match("/^[a-z\-]{2,}$/", $this->language)) { |
|
|
|
|
296
|
|
|
$query .= " WHERE lang = '".$this->language."'"; |
297
|
|
|
} |
298
|
|
|
$result = $this->_config->getDb()->query($query); |
299
|
|
View Code Duplication |
while ($row = $this->_config->getDb()->fetchArray($result)) { |
|
|
|
|
300
|
|
|
$this->categories[$row["id"]] = $row; |
301
|
|
|
} |
302
|
|
|
return $this->categories; |
303
|
|
|
} |
304
|
|
|
|
305
|
|
|
/** |
306
|
|
|
* Builds the category tree |
307
|
|
|
* |
308
|
|
|
* @param integer $id_parent Parent id |
309
|
|
|
* @param integer $indent Indention |
310
|
|
|
* @return void |
311
|
|
|
*/ |
312
|
|
|
public function buildTree($id_parent = 0, $indent = 0) |
313
|
|
|
{ |
314
|
|
|
$tt = array(); |
315
|
|
|
$x = 0; |
316
|
|
|
|
317
|
|
|
foreach ($this->categories as $k => $n) { |
318
|
|
|
if (isset($n['parent_id']) && $n['parent_id'] == $id_parent) { |
319
|
|
|
$tt[$x++] = $k; |
320
|
|
|
} |
321
|
|
|
} |
322
|
|
|
|
323
|
|
|
if ($x != 0) { |
324
|
|
|
foreach ($tt as $d) { |
325
|
|
|
$tmp = array(); |
326
|
|
|
if (isset($this->categories[$d])) { |
327
|
|
|
foreach ($this->categories[$d] as $key => $value) { |
328
|
|
|
$tmp[$key] = $value; |
329
|
|
|
} |
330
|
|
|
$tmp['indent'] = $indent; |
331
|
|
|
$this->catTree[] = $tmp; |
332
|
|
|
$this->buildTree($tmp["id"], $indent + 1); |
333
|
|
|
} |
334
|
|
|
} |
335
|
|
|
} |
336
|
|
|
} |
337
|
|
|
|
338
|
|
|
/** |
339
|
|
|
* Get the level of the item id |
340
|
|
|
* |
341
|
|
|
* @param integer $id Category id |
342
|
|
|
* @return integer |
343
|
|
|
*/ |
344
|
|
|
private function levelOf($id) |
345
|
|
|
{ |
346
|
|
|
$alreadies = array($id); |
347
|
|
|
$ret = 0; |
348
|
|
|
while ((isset($this->categoryName[$id]['parent_id'])) && ($this->categoryName[$id]['parent_id'] != 0)) { |
349
|
|
|
$ret++; |
350
|
|
|
$id = $this->categoryName[$id]['parent_id']; |
351
|
|
|
|
352
|
|
|
if (in_array($id, $alreadies)) { |
353
|
|
|
break; |
354
|
|
|
} else { |
355
|
|
|
array_push($alreadies, $id); |
356
|
|
|
} |
357
|
|
|
} |
358
|
|
|
return $ret; |
359
|
|
|
} |
360
|
|
|
|
361
|
|
|
/** |
362
|
|
|
* Get the line number where to find the node $id |
363
|
|
|
* |
364
|
|
|
* @param integer $id Category id |
365
|
|
|
* @return integer |
366
|
|
|
*/ |
367
|
|
|
private function getLine($id) |
368
|
|
|
{ |
369
|
|
|
for ($i = 0; $i < count($this->lineTab); $i++) { |
370
|
|
|
if ($this->lineTab[$i]['id'] == $id) { |
371
|
|
|
return $i; |
372
|
|
|
} |
373
|
|
|
} |
374
|
|
|
} |
375
|
|
|
|
376
|
|
|
/** |
377
|
|
|
* Transforms the linear array in a 1D array in the order of the tree, with |
378
|
|
|
* the info |
379
|
|
|
* |
380
|
|
|
* @param integer $id Category id |
381
|
|
|
* @return void |
382
|
|
|
*/ |
383
|
|
|
public function transform($id) |
384
|
|
|
{ |
385
|
|
|
$thisParent_id = 0; |
386
|
|
|
$tree = array(); |
387
|
|
|
$tabs = isset($this->children[$id]) ? array_keys($this->children[$id]) : array(); |
388
|
|
|
$num = count($tabs); |
389
|
|
|
|
390
|
|
|
if ($id > 0) { |
391
|
|
|
$thisLevel = $this->categoryName[$id]['level']; |
392
|
|
|
$thisParent_id = $this->categoryName[$id]['parent_id']; |
393
|
|
|
$thisName = $this->categoryName[$id]['name']; |
394
|
|
|
$thisdescription = $this->categoryName[$id]['description']; |
395
|
|
|
} |
396
|
|
|
|
397
|
|
|
if ($num > 0) { |
398
|
|
|
$symbol = 'minus'; |
399
|
|
|
} else { |
400
|
|
|
$temp = isset($this->children[$thisParent_id]) ? array_keys($this->children[$thisParent_id]) : array(); |
401
|
|
|
if (isset($temp[count($temp)-1])) { |
402
|
|
|
$symbol = ($id == $temp[count($temp)-1]) ? 'angle' : 'medium'; |
403
|
|
|
} |
404
|
|
|
} |
405
|
|
|
|
406
|
|
|
$ascendants = $this->getNodes($id); |
407
|
|
|
$num_ascendants = count($ascendants); |
408
|
|
|
|
409
|
|
|
if ($id > 0) { |
410
|
|
|
for ($i = 0; $i < $num_ascendants; $i++) { |
411
|
|
|
$brothers = $this->getBrothers($ascendants[$i]); |
412
|
|
|
$tree[$i] = ($ascendants[$i] == $brothers[count($brothers) - 1]) ? 'space' : 'vertical'; |
413
|
|
|
} |
414
|
|
|
} |
415
|
|
|
|
416
|
|
|
if ($id > 0) { |
417
|
|
|
$this->treeTab[] = array( |
418
|
|
|
'id' => $id, |
419
|
|
|
'symbol' => $symbol, |
420
|
|
|
'name' => $thisName, |
421
|
|
|
'numChilds' => count($tabs), |
422
|
|
|
'level' => $thisLevel, |
423
|
|
|
'parent_id' => $thisParent_id, |
424
|
|
|
'childs' => $tabs, |
425
|
|
|
'tree' => $tree, |
426
|
|
|
'description' => $thisdescription |
427
|
|
|
); |
428
|
|
|
} |
429
|
|
|
|
430
|
|
|
foreach ($tabs as $i) { |
431
|
|
|
$this->transform($i); |
432
|
|
|
} |
433
|
|
|
} |
434
|
|
|
|
435
|
|
|
/** |
436
|
|
|
* Get the line number where to find the node $id in the category tree |
437
|
|
|
* |
438
|
|
|
* @param integer $id Category id |
439
|
|
|
* @return integer |
440
|
|
|
*/ |
441
|
|
|
private function getLineCategory($id) |
442
|
|
|
{ |
443
|
|
|
for ($i = 0; $i < count($this->treeTab); $i++) { |
444
|
|
|
if (isset($this->treeTab[$i]['id']) && $this->treeTab[$i]['id'] == $id) { |
445
|
|
|
return $i; |
446
|
|
|
} |
447
|
|
|
} |
448
|
|
|
} |
449
|
|
|
|
450
|
|
|
// |
451
|
|
|
/** |
452
|
|
|
* List in a array of the $id of the child |
453
|
|
|
* |
454
|
|
|
* @param integer $id Category id |
455
|
|
|
* @return array |
456
|
|
|
* @access public |
457
|
|
|
* @author Thorsten Rinne <[email protected]> |
458
|
|
|
*/ |
459
|
|
|
public function getChildren($id) |
460
|
|
|
{ |
461
|
|
|
return isset($this->children[$id]) ? array_keys($this->children[$id]) : array(); |
462
|
|
|
} |
463
|
|
|
|
464
|
|
|
/** |
465
|
|
|
* list in a array of the $id of the child |
466
|
|
|
* |
467
|
|
|
* @param integer $id Category id |
468
|
|
|
* @return array |
469
|
|
|
*/ |
470
|
|
|
public function getChildNodes($id) |
471
|
|
|
{ |
472
|
|
|
$childs = array(); |
473
|
|
|
|
474
|
|
|
if (isset($this->children[$id])) { |
475
|
|
|
foreach(array_keys($this->children[$id]) as $childId) { |
476
|
|
|
$childs = array_merge($childs, array($childId)); |
477
|
|
|
$childs = array_merge($childs, $this->getChildNodes($childId)); |
478
|
|
|
} |
479
|
|
|
} |
480
|
|
|
|
481
|
|
|
return $childs; |
482
|
|
|
} |
483
|
|
|
|
484
|
|
|
/** |
485
|
|
|
* number of childs of the $id |
486
|
|
|
* |
487
|
|
|
* @param integer $id Category id |
488
|
|
|
* @return integer |
489
|
|
|
*/ |
490
|
|
|
private function numChilds($id) |
491
|
|
|
{ |
492
|
|
|
return count($this->getNodes($id)); |
493
|
|
|
} |
494
|
|
|
|
495
|
|
|
/** |
496
|
|
|
* List in array the root, super-root, ... of the $id |
497
|
|
|
* |
498
|
|
|
* @param integer $id Category id |
499
|
|
|
* @return array |
500
|
|
|
*/ |
501
|
|
|
private function getNodes($id) |
502
|
|
|
{ |
503
|
|
|
if (($id > 0) && (isset($this->categoryName[$id]['level']))) { |
504
|
|
|
$thisLevel = $this->categoryName[$id]['level']; |
505
|
|
|
$temp = array(); |
506
|
|
|
for ($i = $thisLevel; $i > 0; $i--) { |
507
|
|
|
$id = $this->categoryName[$id]['parent_id']; |
508
|
|
|
array_unshift($temp, $id); |
509
|
|
|
} |
510
|
|
|
return $temp; |
511
|
|
|
} |
512
|
|
|
} |
513
|
|
|
|
514
|
|
|
/** |
515
|
|
|
* Collapse the complete category tree |
516
|
|
|
* |
517
|
|
|
* @return void |
518
|
|
|
*/ |
519
|
|
View Code Duplication |
public function collapseAll() |
520
|
|
|
{ |
521
|
|
|
for ($i = 0; $i < count($this->treeTab); $i++) { |
522
|
|
|
if ($this->treeTab[$i]["symbol"] == "minus") { |
523
|
|
|
$this->treeTab[$i]["symbol"] = "plus"; |
524
|
|
|
} |
525
|
|
|
} |
526
|
|
|
} |
527
|
|
|
|
528
|
|
|
/** |
529
|
|
|
* expand the node $id |
530
|
|
|
* |
531
|
|
|
* @param integer $id Category id |
532
|
|
|
* @return void |
533
|
|
|
*/ |
534
|
|
|
public function expand($id) |
535
|
|
|
{ |
536
|
|
|
$this->treeTab[$this->getLineCategory($id)]["symbol"] = "minus"; |
537
|
|
|
} |
538
|
|
|
|
539
|
|
|
// try to expand from the parent_id to the node $id |
540
|
|
|
public function expandTo($id) |
541
|
|
|
{ |
542
|
|
|
$this->collapseAll(); |
543
|
|
|
$ascendants = $this->getNodes($id); |
544
|
|
|
$ascendants[] = $id; |
545
|
|
|
for ($i = 0; $i < count($ascendants); $i++) { |
546
|
|
|
$numChilds = 0; |
547
|
|
|
if (isset($this->treeTab[$this->getLineCategory($ascendants[$i])]["numChilds"])) { |
548
|
|
|
$numChilds = $this->treeTab[$this->getLineCategory($ascendants[$i])]["numChilds"]; |
549
|
|
|
if ($numChilds > 0) { |
550
|
|
|
$this->expand($ascendants[$i]); |
551
|
|
|
} else { |
552
|
|
|
$i = count($ascendants); |
553
|
|
|
} |
554
|
|
|
} |
555
|
|
|
} |
556
|
|
|
} |
557
|
|
|
|
558
|
|
|
/** |
559
|
|
|
* expand the entire tree |
560
|
|
|
* |
561
|
|
|
* @return void |
562
|
|
|
*/ |
563
|
|
View Code Duplication |
public function expandAll() |
564
|
|
|
{ |
565
|
|
|
for ($i = 0; $i < count($this->treeTab); $i++) { |
566
|
|
|
if ($this->treeTab[$i]["symbol"] == "plus") { |
567
|
|
|
$this->treeTab[$i]["symbol"] = "minus"; |
568
|
|
|
} |
569
|
|
|
} |
570
|
|
|
} |
571
|
|
|
|
572
|
|
|
/** |
573
|
|
|
* Total height of the expanded tree |
574
|
|
|
* |
575
|
|
|
* @return integer |
576
|
|
|
*/ |
577
|
|
|
public function height() |
578
|
|
|
{ |
579
|
|
|
return count($this->treeTab); |
580
|
|
|
} |
581
|
|
|
|
582
|
|
|
/** |
583
|
|
|
* print the static tree with the number of records |
584
|
|
|
* |
585
|
|
|
* @return string |
586
|
|
|
*/ |
587
|
|
|
public function viewTree() |
588
|
|
|
{ |
589
|
|
|
global $sids, $PMF_LANG, $plr; |
590
|
|
|
$totFaqRecords = 0; |
591
|
|
|
|
592
|
|
|
$query = sprintf(" |
593
|
|
|
SELECT |
594
|
|
|
fcr.category_id AS category_id, |
595
|
|
|
count(fcr.category_id) AS number |
596
|
|
|
FROM |
597
|
|
|
%sfaqcategoryrelations fcr, |
598
|
|
|
%sfaqdata fd |
599
|
|
|
WHERE |
600
|
|
|
fcr.record_id = fd.id |
601
|
|
|
AND |
602
|
|
|
fcr.record_lang = fd.lang", |
603
|
|
|
PMF_Db::getTablePrefix(), |
604
|
|
|
PMF_Db::getTablePrefix()); |
605
|
|
|
|
606
|
|
|
if (strlen($this->language) > 0) { |
607
|
|
|
$query .= sprintf(" AND fd.lang = '%s'", |
608
|
|
|
$this->language); |
609
|
|
|
} |
610
|
|
|
|
611
|
|
|
$query .= sprintf(" |
612
|
|
|
AND |
613
|
|
|
fd.active = 'yes' |
614
|
|
|
GROUP BY |
615
|
|
|
fcr.category_id", |
616
|
|
|
PMF_Db::getTablePrefix(), |
617
|
|
|
PMF_Db::getTablePrefix()); |
618
|
|
|
$result = $this->_config->getDb()->query($query); |
619
|
|
|
if ($this->_config->getDb()->numRows($result) > 0) { |
620
|
|
|
while ($row = $this->_config->getDb()->fetchObject($result)) { |
621
|
|
|
$number[$row->category_id] = $row->number; |
622
|
|
|
} |
623
|
|
|
} |
624
|
|
|
$output = "<ul>\n"; |
625
|
|
|
$open = 0; |
626
|
|
|
$this->expandAll(); |
627
|
|
|
|
628
|
|
|
for ($y = 0 ;$y < $this->height(); $y = $this->getNextLineTree($y)) { |
629
|
|
|
|
630
|
|
|
list($categoryName, $parent, $description) = $this->getLineDisplay($y); |
631
|
|
|
$level = $this->treeTab[$y]['level']; |
632
|
|
|
$leveldiff = $open - $level; |
633
|
|
|
|
634
|
|
View Code Duplication |
if ($leveldiff > 1) { |
635
|
|
|
$output .= '</li>'; |
636
|
|
|
for ($i = $leveldiff; $i > 1; $i--) { |
637
|
|
|
$output .= sprintf("\n%s</ul>\n%s</li>\n", |
638
|
|
|
str_repeat("\t", $level + $i + 1), |
639
|
|
|
str_repeat("\t", $level + $i)); |
640
|
|
|
} |
641
|
|
|
} |
642
|
|
|
|
643
|
|
|
if (!isset($number[$parent])) { |
644
|
|
|
$number[$parent] = 0; |
645
|
|
|
} |
646
|
|
|
|
647
|
|
|
if ($level < $open) { |
648
|
|
|
if (($level - $open) == -1) { |
649
|
|
|
$output .= '</li>'; |
650
|
|
|
} |
651
|
|
|
$output .= sprintf("\n%s</ul>\n%s</li>\n", |
652
|
|
|
str_repeat("\t", $level + 2), |
653
|
|
|
str_repeat("\t", $level + 1)); |
654
|
|
|
} elseif ($level == $open && $y != 0) { |
655
|
|
|
$output .= "</li>\n"; |
656
|
|
|
} |
657
|
|
|
|
658
|
|
|
if ($level > $open) { |
659
|
|
|
$output .= sprintf("\n%s<ul>\n%s<li>", |
660
|
|
|
str_repeat("\t", $level + 1), |
661
|
|
|
str_repeat("\t", $level + 1)); |
662
|
|
|
} else { |
663
|
|
|
$output .= str_repeat("\t", $level + 1)."<li>"; |
664
|
|
|
} |
665
|
|
|
|
666
|
|
|
if (0 == $number[$parent] && 0 == $level) { |
667
|
|
|
$num_entries = ''; |
668
|
|
|
} else { |
669
|
|
|
$totFaqRecords += $number[$parent]; |
670
|
|
|
$num_entries = '<span class="rssCategoryLink"> ('.$plr->GetMsg('plmsgEntries',$number[$parent]); |
671
|
|
|
$num_entries .= sprintf( |
672
|
|
|
' <a href="feed/category/rss.php?category_id=%d&category_lang=%s" target="_blank"><img id="category_%d_RSS" src="assets/img/feed.png" width="16" height="16" alt="RSS"></a>', |
673
|
|
|
$parent, |
674
|
|
|
$this->language, |
675
|
|
|
$parent |
676
|
|
|
); |
677
|
|
|
$num_entries .= ')</span>'; |
678
|
|
|
} |
679
|
|
|
|
680
|
|
|
$url = sprintf( |
681
|
|
|
'%s?%saction=show&cat=%d', |
682
|
|
|
PMF_Link::getSystemRelativeUri(), |
683
|
|
|
$sids, |
684
|
|
|
$parent |
685
|
|
|
); |
686
|
|
|
$oLink = new PMF_Link($url, $this->_config); |
687
|
|
|
$oLink->itemTitle = $categoryName; |
688
|
|
|
$oLink->text = $categoryName; |
689
|
|
|
$oLink->tooltip = $description; |
690
|
|
|
|
691
|
|
|
$output .= $oLink->toHtmlAnchor() . $num_entries; |
692
|
|
|
$open = $level; |
693
|
|
|
} |
694
|
|
|
|
695
|
|
|
if (isset($level) && $level > 0) { |
696
|
|
|
$output .= str_repeat("</li>\n\t</ul>\n\t", $level); |
697
|
|
|
} |
698
|
|
|
|
699
|
|
|
$output .= "\t</li>\n"; |
700
|
|
|
$output .= "\t</ul>\n"; |
701
|
|
|
$output .= '<span id="totFaqRecords" style="display: none;">'.$totFaqRecords."</span>\n"; |
702
|
|
|
return $output; |
703
|
|
|
} |
704
|
|
|
|
705
|
|
|
/** |
706
|
|
|
* Returns the three parts of a line to display: category name, the ID of |
707
|
|
|
* the root node and the description |
708
|
|
|
* |
709
|
|
|
* @param integer $y ID |
710
|
|
|
* @return array |
711
|
|
|
*/ |
712
|
|
|
public function getLineDisplay($y) |
713
|
|
|
{ |
714
|
|
|
$ret[0] = $this->treeTab[$y]['name']; |
715
|
|
|
$ret[1] = $this->treeTab[$y]['id']; |
716
|
|
|
$ret[2] = $this->treeTab[$y]['description']; |
717
|
|
|
|
718
|
|
|
return $ret; |
719
|
|
|
} |
720
|
|
|
|
721
|
|
|
/** |
722
|
|
|
* Gets the next line in the array treeTab, depending of the |
723
|
|
|
* collapse/expand node |
724
|
|
|
* |
725
|
|
|
* @param integer $l Current line |
726
|
|
|
* @return integer |
727
|
|
|
*/ |
728
|
|
|
public function getNextLineTree($l) |
729
|
|
|
{ |
730
|
|
|
if ($this->treeTab[$l]["symbol"] != "plus") { |
731
|
|
|
return $l + 1; |
732
|
|
|
} else { |
733
|
|
|
for ($i = $l + 1; $i < $this->height(); $i++) { |
734
|
|
|
if ($this->treeTab[$i]["level"]<=$this->treeTab[$l]["level"]) { |
735
|
|
|
return $i; |
736
|
|
|
} |
737
|
|
|
} |
738
|
|
|
} |
739
|
|
|
return $this->height(); |
740
|
|
|
} |
741
|
|
|
|
742
|
|
|
/** |
743
|
|
|
* Gets the list of the brothers of $id (include $id) |
744
|
|
|
* |
745
|
|
|
* @param integer $id Brothers |
746
|
|
|
* @return array |
747
|
|
|
*/ |
748
|
|
|
private function getBrothers($id) |
749
|
|
|
{ |
750
|
|
|
return $this->getChildren($this->categoryName[$id]['parent_id']); |
751
|
|
|
} |
752
|
|
|
|
753
|
|
|
/** |
754
|
|
|
* Creates a category link |
755
|
|
|
* |
756
|
|
|
* @param string $sids Session id |
757
|
|
|
* @param integer $categoryId Parent category |
758
|
|
|
* @param string $categoryName Category name |
759
|
|
|
* @param string $description Description |
760
|
|
|
* @param boolean $hasChildren Child categories available |
761
|
|
|
* @param boolean $isActive Sets a link active via CSS |
762
|
|
|
* @return string |
763
|
|
|
*/ |
764
|
|
|
public function addCategoryLink($sids, $categoryId, $categoryName, $description, $hasChildren = false, $isActive = false) |
765
|
|
|
{ |
766
|
|
|
$url = sprintf( |
767
|
|
|
'%s?%saction=show&cat=%d', |
768
|
|
|
PMF_Link::getSystemRelativeUri(), |
769
|
|
|
$sids, |
770
|
|
|
$categoryId |
771
|
|
|
); |
772
|
|
|
|
773
|
|
|
$oLink = new PMF_Link($url, $this->_config); |
774
|
|
|
$oLink->id = 'category_' . $categoryId; |
775
|
|
|
$oLink->itemTitle = $categoryName; |
776
|
|
|
$oLink->text = $categoryName; |
777
|
|
|
|
778
|
|
|
if ($hasChildren) { |
779
|
|
|
$oLink->text .= sprintf( |
780
|
|
|
' <img src="assets/img/more.gif" width="11" height="11" alt="%s" style="border: none; vertical-align: middle;" />', |
781
|
|
|
$categoryName); |
782
|
|
|
} |
783
|
|
|
|
784
|
|
|
if ($isActive) { |
785
|
|
|
$oLink->class = 'active'; |
786
|
|
|
} |
787
|
|
|
|
788
|
|
|
$oLink->tooltip = $description; |
789
|
|
|
|
790
|
|
|
return $oLink->toHtmlAnchor(); |
791
|
|
|
} |
792
|
|
|
|
793
|
|
|
/** |
794
|
|
|
* Gets the path from root to child as breadcrumbs |
795
|
|
|
* |
796
|
|
|
* @param integer $id Category ID |
797
|
|
|
* @param string $separator Path separator |
798
|
|
|
* @param boolean $renderAsMicroData Renders breadcrumbs as HTML5 microdata |
799
|
|
|
* @param string $useCssClass Use CSS class "breadcrumb" |
800
|
|
|
* @return string |
801
|
|
|
*/ |
802
|
|
|
public function getPath($id, $separator = ' » ', $renderAsMicroData = false, $useCssClass = 'breadcrumb') |
803
|
|
|
{ |
804
|
|
|
global $sids; |
805
|
|
|
|
806
|
|
|
$ids = $this->getNodes($id); |
807
|
|
|
$num = count($ids); |
808
|
|
|
|
809
|
|
|
$temp = $catid = $desc = $breadcrumb = array(); |
810
|
|
|
|
811
|
|
|
for ($i = 0; $i < $num; $i++) { |
812
|
|
|
$t = $this->getLineCategory($ids[$i]); |
813
|
|
|
if (array_key_exists($t, $this->treeTab)) { |
814
|
|
|
$temp[] = $this->treeTab[$this->getLineCategory($ids[$i])]['name']; |
815
|
|
|
$catid[] = $this->treeTab[$this->getLineCategory($ids[$i])]['id']; |
816
|
|
|
$desc[] = $this->treeTab[$this->getLineCategory($ids[$i])]['description']; |
817
|
|
|
} |
818
|
|
|
} |
819
|
|
|
if (isset($this->treeTab[$this->getLineCategory($id)]['name'])) { |
820
|
|
|
$temp[] = $this->treeTab[$this->getLineCategory($id)]['name']; |
821
|
|
|
$catid[] = $this->treeTab[$this->getLineCategory($id)]['id']; |
822
|
|
|
$desc[] = $this->treeTab[$this->getLineCategory($id)]['description']; |
823
|
|
|
} |
824
|
|
|
|
825
|
|
|
// @todo Maybe this should be done somewhere else ... |
826
|
|
|
if ($renderAsMicroData) { |
827
|
|
|
|
828
|
|
|
foreach ($temp as $k => $category) { |
829
|
|
|
$url = sprintf( |
830
|
|
|
'%s?%saction=show&cat=%d', |
831
|
|
|
PMF_Link::getSystemRelativeUri(), |
832
|
|
|
$sids, |
833
|
|
|
$catid[$k] |
834
|
|
|
); |
835
|
|
|
$oLink = new PMF_Link($url, $this->_config); |
836
|
|
|
$oLink->text = sprintf('<span itemprop="title">%s</span>', $category); |
837
|
|
|
$oLink->itemTitle = $category; |
838
|
|
|
$oLink->tooltip = $desc[$k]; |
839
|
|
|
$oLink->setItemProperty('url'); |
840
|
|
|
if (0 == $k) { |
841
|
|
|
$oLink->setRelation('index'); |
842
|
|
|
} |
843
|
|
|
|
844
|
|
|
$breadcrumb[] = sprintf( |
845
|
|
|
'<li itemscope itemtype="http://data-vocabulary.org/Breadcrumb">%s</li>', |
846
|
|
|
$oLink->toHtmlAnchor() |
847
|
|
|
); |
848
|
|
|
} |
849
|
|
|
|
850
|
|
|
$temp = $breadcrumb; |
851
|
|
|
|
852
|
|
|
return sprintf( |
853
|
|
|
'<ul class="%s">%s</ul>', |
854
|
|
|
$useCssClass, |
855
|
|
|
implode('<li class="divider">' . $separator . '</li>', $temp) |
856
|
|
|
); |
857
|
|
|
} else { |
858
|
|
|
return implode($separator, $temp); |
859
|
|
|
} |
860
|
|
|
} |
861
|
|
|
|
862
|
|
|
/** |
863
|
|
|
* Returns the categories from a record id and language |
864
|
|
|
* |
865
|
|
|
* @param integer $record_id record id |
866
|
|
|
* @param integer $record_lang record language |
867
|
|
|
* @return array |
868
|
|
|
*/ |
869
|
|
View Code Duplication |
public function getCategoryRelationsFromArticle($record_id, $record_lang) |
870
|
|
|
{ |
871
|
|
|
$categories = array(); |
872
|
|
|
|
873
|
|
|
$query = sprintf(" |
874
|
|
|
SELECT |
875
|
|
|
category_id, category_lang |
876
|
|
|
FROM |
877
|
|
|
%sfaqcategoryrelations |
878
|
|
|
WHERE |
879
|
|
|
record_id = %d |
880
|
|
|
AND |
881
|
|
|
record_lang = '%s'", |
882
|
|
|
PMF_Db::getTablePrefix(), |
883
|
|
|
$record_id, |
884
|
|
|
$record_lang); |
885
|
|
|
|
886
|
|
|
$result = $this->_config->getDb()->query($query); |
887
|
|
|
while ($row = $this->_config->getDb()->fetchObject($result)) { |
888
|
|
|
$categories[] = array( |
889
|
|
|
'category_id' => $row->category_id, |
890
|
|
|
'category_lang' => $row->category_lang); |
891
|
|
|
} |
892
|
|
|
|
893
|
|
|
return $categories; |
894
|
|
|
} |
895
|
|
|
|
896
|
|
|
/** |
897
|
|
|
* Returns all categories that are related to the given article-id and |
898
|
|
|
* the current language $this->language in an unsorted array which consists |
899
|
|
|
* of associative arrays with the keys 'name', 'id', 'lang', |
900
|
|
|
* 'parent_id' and 'description'. |
901
|
|
|
* |
902
|
|
|
* @param integer $articleId Record id |
903
|
|
|
* |
904
|
|
|
* @return array |
905
|
|
|
*/ |
906
|
|
|
public function getCategoriesFromArticle($articleId) |
907
|
|
|
{ |
908
|
|
|
$query = sprintf(" |
909
|
|
|
SELECT |
910
|
|
|
fc.id AS id, |
911
|
|
|
fc.lang AS lang, |
912
|
|
|
fc.parent_id AS parent_id, |
913
|
|
|
fc.name AS name, |
914
|
|
|
fc.description AS description |
915
|
|
|
FROM |
916
|
|
|
%sfaqcategoryrelations fcr, |
917
|
|
|
%sfaqcategories fc |
918
|
|
|
WHERE |
919
|
|
|
fc.id = fcr.category_id |
920
|
|
|
AND |
921
|
|
|
fcr.record_id = %d |
922
|
|
|
AND |
923
|
|
|
fcr.category_lang = '%s' |
924
|
|
|
AND |
925
|
|
|
fc.lang = '%s'", |
926
|
|
|
PMF_Db::getTablePrefix(), |
927
|
|
|
PMF_Db::getTablePrefix(), |
928
|
|
|
$articleId, |
929
|
|
|
$this->language, |
930
|
|
|
$this->language); |
931
|
|
|
|
932
|
|
|
$result = $this->_config->getDb()->query($query); |
933
|
|
|
$num = $this->_config->getDb()->numRows($result); |
934
|
|
|
$this->categories = array(); |
935
|
|
|
if ($num > 0) { |
936
|
|
|
while ($row = $this->_config->getDb()->fetchArray($result)) { |
937
|
|
|
$this->categories[] = $row; |
938
|
|
|
} |
939
|
|
|
} |
940
|
|
|
return $this->categories; |
941
|
|
|
} |
942
|
|
|
|
943
|
|
|
/** |
944
|
|
|
* Returns the ID of a category that associated with the given article. |
945
|
|
|
* |
946
|
|
|
* @param integer $article_id Record id |
947
|
|
|
* @return integer |
948
|
|
|
*/ |
949
|
|
|
public function getCategoryIdFromArticle($article_id) |
950
|
|
|
{ |
951
|
|
|
$cats = $this->getCategoryIdsFromArticle($article_id); |
952
|
|
|
if (isset($cats[0])) { |
953
|
|
|
return $cats[0]; |
954
|
|
|
} else { |
955
|
|
|
return 0; |
956
|
|
|
} |
957
|
|
|
} |
958
|
|
|
|
959
|
|
|
/** |
960
|
|
|
* Returns an array with the IDs of all categories that are associated with |
961
|
|
|
* the given article. |
962
|
|
|
* |
963
|
|
|
* @param integer $article_id Record id |
964
|
|
|
* @return array |
965
|
|
|
*/ |
966
|
|
|
public function getCategoryIdsFromArticle($article_id) |
967
|
|
|
{ |
968
|
|
|
$cats = $this->getCategoriesFromArticle($article_id); |
969
|
|
|
$arr = array(); |
970
|
|
|
foreach ($cats as $cat) { |
971
|
|
|
$arr[] = $cat['id']; |
972
|
|
|
} |
973
|
|
|
return $arr; |
974
|
|
|
} |
975
|
|
|
|
976
|
|
|
/** |
977
|
|
|
* Adds a new category entry |
978
|
|
|
* |
979
|
|
|
* @param array $categoryData Array of category data |
980
|
|
|
* @param integer $parentId Parent id |
981
|
|
|
* @param integer $id Category id |
982
|
|
|
* |
983
|
|
|
* @return integer |
984
|
|
|
*/ |
985
|
|
|
public function addCategory(Array $categoryData, $parentId = 0, $id = null) |
986
|
|
|
{ |
987
|
|
|
// If we only need a new language, we don't need a new category id |
988
|
|
|
if (is_null($id)) { |
989
|
|
|
$id = $this->_config->getDb()->nextId(PMF_Db::getTablePrefix().'faqcategories', 'id'); |
990
|
|
|
} |
991
|
|
|
|
992
|
|
|
$query = sprintf(" |
993
|
|
|
INSERT INTO |
994
|
|
|
%sfaqcategories |
995
|
|
|
(id, lang, parent_id, name, description, user_id) |
996
|
|
|
VALUES |
997
|
|
|
(%d, '%s', %d, '%s', '%s', %d)", |
998
|
|
|
PMF_Db::getTablePrefix(), |
999
|
|
|
$id, |
1000
|
|
|
$categoryData['lang'], |
1001
|
|
|
$parentId, |
1002
|
|
|
$categoryData['name'], |
1003
|
|
|
$categoryData['description'], |
1004
|
|
|
$categoryData['user_id'] |
1005
|
|
|
); |
1006
|
|
|
$this->_config->getDb()->query($query); |
1007
|
|
|
|
1008
|
|
|
return $id; |
1009
|
|
|
} |
1010
|
|
|
|
1011
|
|
|
/** |
1012
|
|
|
* Updates an existent category entry |
1013
|
|
|
* |
1014
|
|
|
* @param array $category_data Array of category data |
1015
|
|
|
* @return boolean |
1016
|
|
|
*/ |
1017
|
|
View Code Duplication |
public function updateCategory(Array $category_data) |
1018
|
|
|
{ |
1019
|
|
|
if (!is_array($category_data)) { |
1020
|
|
|
return false; |
1021
|
|
|
} |
1022
|
|
|
|
1023
|
|
|
$query = sprintf(" |
1024
|
|
|
UPDATE |
1025
|
|
|
%sfaqcategories |
1026
|
|
|
SET |
1027
|
|
|
name = '%s', |
1028
|
|
|
description = '%s', |
1029
|
|
|
user_id = %d |
1030
|
|
|
WHERE |
1031
|
|
|
id = %d |
1032
|
|
|
AND |
1033
|
|
|
lang = '%s'", |
1034
|
|
|
PMF_Db::getTablePrefix(), |
1035
|
|
|
$category_data['name'], |
1036
|
|
|
$category_data['description'], |
1037
|
|
|
$category_data['user_id'], |
1038
|
|
|
$category_data['id'], |
1039
|
|
|
$category_data['lang']); |
1040
|
|
|
$this->_config->getDb()->query($query); |
1041
|
|
|
|
1042
|
|
|
return true; |
1043
|
|
|
} |
1044
|
|
|
|
1045
|
|
|
/** |
1046
|
|
|
* Move the categories ownership, if any. |
1047
|
|
|
* |
1048
|
|
|
* @param integer $from Old user id |
1049
|
|
|
* @param integer $to New user id |
1050
|
|
|
* @return boolean |
1051
|
|
|
*/ |
1052
|
|
|
public function moveOwnership($from, $to) |
1053
|
|
|
{ |
1054
|
|
|
if (!is_numeric($from) || !is_numeric($to)) { |
1055
|
|
|
return false; |
1056
|
|
|
} |
1057
|
|
|
|
1058
|
|
|
$query = sprintf(" |
1059
|
|
|
UPDATE |
1060
|
|
|
%sfaqcategories |
1061
|
|
|
SET |
1062
|
|
|
user_id = %d |
1063
|
|
|
WHERE |
1064
|
|
|
user_id = %d", |
1065
|
|
|
PMF_Db::getTablePrefix(), |
1066
|
|
|
$to, |
1067
|
|
|
$from |
1068
|
|
|
); |
1069
|
|
|
$this->_config->getDb()->query($query); |
1070
|
|
|
|
1071
|
|
|
return true; |
1072
|
|
|
} |
1073
|
|
|
|
1074
|
|
|
/** |
1075
|
|
|
* Checks wether a language is already defined for a category id |
1076
|
|
|
* |
1077
|
|
|
* @param integer $category_id Category id |
1078
|
|
|
* @param string $category_lang Category language |
1079
|
|
|
* @return boolean |
1080
|
|
|
*/ |
1081
|
|
|
public function checkLanguage($category_id, $category_lang) |
1082
|
|
|
{ |
1083
|
|
|
$query = sprintf(" |
1084
|
|
|
SELECT |
1085
|
|
|
lang |
1086
|
|
|
FROM |
1087
|
|
|
%sfaqcategories |
1088
|
|
|
WHERE |
1089
|
|
|
id = %d |
1090
|
|
|
AND |
1091
|
|
|
lang = '%s'", |
1092
|
|
|
PMF_Db::getTablePrefix(), |
1093
|
|
|
$category_id, |
1094
|
|
|
$category_lang); |
1095
|
|
|
|
1096
|
|
|
$result = $this->_config->getDb()->query($query); |
1097
|
|
|
return $this->_config->getDb()->numRows($result); |
1098
|
|
|
} |
1099
|
|
|
|
1100
|
|
|
/** |
1101
|
|
|
* Swaps two categories |
1102
|
|
|
* |
1103
|
|
|
* @param integer $category_id_1 First category |
1104
|
|
|
* @param integer $category_id_2 Second category |
1105
|
|
|
* @return boolean |
1106
|
|
|
*/ |
1107
|
|
|
public function swapCategories($category_id_1, $category_id_2) |
1108
|
|
|
{ |
1109
|
|
|
$temp_cat = rand(200000, 400000); |
1110
|
|
|
|
1111
|
|
|
$tables = array( |
1112
|
|
|
array('faqcategories' => 'id'), |
1113
|
|
|
array('faqcategories' => 'parent_id'), |
1114
|
|
|
array('faqcategoryrelations' => 'category_id'), |
1115
|
|
|
array('faqcategory_group' => 'category_id'), |
1116
|
|
|
array('faqcategory_user' => 'category_id')); |
1117
|
|
|
|
1118
|
|
|
$result = true; |
1119
|
|
View Code Duplication |
foreach ($tables as $pair) { |
1120
|
|
|
foreach ($pair as $_table => $_field) { |
1121
|
|
|
$result = $result && $this->_config->getDb()->query(sprintf("UPDATE %s SET %s = %d WHERE %s = %d", |
1122
|
|
|
PMF_Db::getTablePrefix().$_table, |
1123
|
|
|
$_field, |
1124
|
|
|
$temp_cat, |
1125
|
|
|
$_field, |
1126
|
|
|
$category_id_2)); |
1127
|
|
|
$result = $result && $this->_config->getDb()->query(sprintf("UPDATE %s SET %s = %d WHERE %s = %d", |
1128
|
|
|
PMF_Db::getTablePrefix().$_table, |
1129
|
|
|
$_field, |
1130
|
|
|
$category_id_2, |
1131
|
|
|
$_field, |
1132
|
|
|
$category_id_1)); |
1133
|
|
|
$result = $result && $this->_config->getDb()->query(sprintf("UPDATE %s SET %s = %d WHERE %s = %d", |
1134
|
|
|
PMF_Db::getTablePrefix().$_table, |
1135
|
|
|
$_field, |
1136
|
|
|
$category_id_1, |
1137
|
|
|
$_field, |
1138
|
|
|
$temp_cat)); |
1139
|
|
|
} |
1140
|
|
|
} |
1141
|
|
|
|
1142
|
|
|
$tables2 = array(array('faqquestions' => 'category_id')); |
1143
|
|
|
|
1144
|
|
View Code Duplication |
foreach ($tables2 as $pair) { |
1145
|
|
|
foreach ($pair as $_table => $_field) { |
1146
|
|
|
$result = $result && $this->_config->getDb()->query(sprintf("UPDATE %s SET %s = '%d' WHERE %s = '%d'", |
1147
|
|
|
PMF_Db::getTablePrefix().$_table, |
1148
|
|
|
$_field, |
1149
|
|
|
$temp_cat, |
1150
|
|
|
$_field, |
1151
|
|
|
$category_id_2)); |
1152
|
|
|
$result = $result && $this->_config->getDb()->query(sprintf("UPDATE %s SET %s = '%d' WHERE %s = '%d'", |
1153
|
|
|
PMF_Db::getTablePrefix().$_table, |
1154
|
|
|
$_field, |
1155
|
|
|
$category_id_2, |
1156
|
|
|
$_field, |
1157
|
|
|
$category_id_1)); |
1158
|
|
|
$result = $result && $this->_config->getDb()->query(sprintf("UPDATE %s SET %s = '%d' WHERE %s = '%d'", |
1159
|
|
|
PMF_Db::getTablePrefix().$_table, |
1160
|
|
|
$_field, |
1161
|
|
|
$category_id_1, |
1162
|
|
|
$_field, |
1163
|
|
|
$temp_cat)); |
1164
|
|
|
} |
1165
|
|
|
} |
1166
|
|
|
|
1167
|
|
|
return $result; |
1168
|
|
|
} |
1169
|
|
|
|
1170
|
|
|
/** |
1171
|
|
|
* Updates the parent category |
1172
|
|
|
* |
1173
|
|
|
* @param integer $category_id Category id |
1174
|
|
|
* @param integer $parent_id Parent category id |
1175
|
|
|
* @return boolean |
1176
|
|
|
*/ |
1177
|
|
|
public function updateParentCategory($category_id, $parent_id) |
1178
|
|
|
{ |
1179
|
|
|
if ((!is_numeric($category_id) || !is_numeric($parent_id)) && $category_id != $parent_id) { |
1180
|
|
|
return false; |
1181
|
|
|
} |
1182
|
|
|
|
1183
|
|
|
$query = sprintf(" |
1184
|
|
|
UPDATE |
1185
|
|
|
%sfaqcategories |
1186
|
|
|
SET |
1187
|
|
|
parent_id = %d |
1188
|
|
|
WHERE |
1189
|
|
|
id = %d", |
1190
|
|
|
PMF_Db::getTablePrefix(), |
1191
|
|
|
$parent_id, |
1192
|
|
|
$category_id); |
1193
|
|
|
$this->_config->getDb()->query($query); |
1194
|
|
|
|
1195
|
|
|
return true; |
1196
|
|
|
} |
1197
|
|
|
|
1198
|
|
|
/** |
1199
|
|
|
* Deletes a category |
1200
|
|
|
* |
1201
|
|
|
* @param integer $category_id Category id |
1202
|
|
|
* @param string $category_lang Categiry language |
1203
|
|
|
* @param boolean $delete_all Delete all languages? |
1204
|
|
|
* @return boolean |
1205
|
|
|
*/ |
1206
|
|
View Code Duplication |
public function deleteCategory($category_id, $category_lang, $delete_all = false) |
1207
|
|
|
{ |
1208
|
|
|
$query = sprintf(" |
1209
|
|
|
DELETE FROM |
1210
|
|
|
%sfaqcategories |
1211
|
|
|
WHERE |
1212
|
|
|
id = %d", |
1213
|
|
|
PMF_Db::getTablePrefix(), |
1214
|
|
|
$category_id); |
1215
|
|
|
if (!$delete_all) { |
1216
|
|
|
$query .= " AND lang = '".$category_lang."'"; |
1217
|
|
|
} |
1218
|
|
|
$this->_config->getDb()->query($query); |
1219
|
|
|
|
1220
|
|
|
return true; |
1221
|
|
|
} |
1222
|
|
|
/** |
1223
|
|
|
* Deletes a category relation |
1224
|
|
|
* |
1225
|
|
|
* @param integer $category_id Category id |
1226
|
|
|
* @param string $category_lang Categiry language |
1227
|
|
|
* @param boolean $delete_all Delete all languages? |
1228
|
|
|
* @return boolean |
1229
|
|
|
*/ |
1230
|
|
View Code Duplication |
public function deleteCategoryRelation($category_id, $category_lang, $delete_all = false) |
1231
|
|
|
{ |
1232
|
|
|
$query = sprintf(" |
1233
|
|
|
DELETE FROM |
1234
|
|
|
%sfaqcategoryrelations |
1235
|
|
|
WHERE |
1236
|
|
|
category_id = %d", |
1237
|
|
|
PMF_Db::getTablePrefix(), |
1238
|
|
|
$category_id); |
1239
|
|
|
if (!$delete_all) { |
1240
|
|
|
$query .= " AND category_lang = '".$category_lang."'"; |
1241
|
|
|
} |
1242
|
|
|
$this->_config->getDb()->query($query); |
1243
|
|
|
|
1244
|
|
|
return true; |
1245
|
|
|
} |
1246
|
|
|
|
1247
|
|
|
/** |
1248
|
|
|
* Create array with translated categories |
1249
|
|
|
* |
1250
|
|
|
* @param integer $category_id |
1251
|
|
|
* @return array |
1252
|
|
|
* @access public |
1253
|
|
|
* @since 2006-09-10 |
1254
|
|
|
* @author Rudi Ferrari <[email protected]> |
1255
|
|
|
*/ |
1256
|
|
|
public function getCategoryLanguagesTranslated($category_id) |
1257
|
|
|
{ |
1258
|
|
|
global $languageCodes; |
1259
|
|
|
|
1260
|
|
|
$existcatlang = $this->_config->getLanguage()->languageAvailable($category_id, 'faqcategories'); |
1261
|
|
|
$translated = array(); |
1262
|
|
|
|
1263
|
|
|
foreach ($existcatlang as $language) { |
1264
|
|
|
$query = sprintf(" |
1265
|
|
|
SELECT |
1266
|
|
|
name, description |
1267
|
|
|
FROM |
1268
|
|
|
%sfaqcategories |
1269
|
|
|
WHERE |
1270
|
|
|
id = %d |
1271
|
|
|
AND |
1272
|
|
|
lang = '%s'", |
1273
|
|
|
PMF_Db::getTablePrefix(), |
1274
|
|
|
$category_id, |
1275
|
|
|
$language); |
1276
|
|
|
$result = $this->_config->getDb()->query($query); |
1277
|
|
|
if ($row = $this->_config->getDb()->fetchArray($result)) { |
1278
|
|
|
$translated[$languageCodes[strtoupper($language)]] = $row['name'].('' == $row['description'] ? '' : ' ('.$row['description'].')'); |
1279
|
|
|
} |
1280
|
|
|
} |
1281
|
|
|
ksort($translated); |
1282
|
|
|
|
1283
|
|
|
return $translated; |
1284
|
|
|
} |
1285
|
|
|
|
1286
|
|
|
/** |
1287
|
|
|
* Create all languagess which can be used for translation as <option> |
1288
|
|
|
* |
1289
|
|
|
* @param integer $category_id Category id |
1290
|
|
|
* @param string $selected_lang Selected language |
1291
|
|
|
* |
1292
|
|
|
* @return string |
1293
|
|
|
*/ |
1294
|
|
|
public function getCategoryLanguagesToTranslate($category_id, $selected_lang) |
1295
|
|
|
{ |
1296
|
|
|
$output = ''; |
1297
|
|
|
$existcatlang = $this->_config->getLanguage()->languageAvailable($category_id, 'faqcategories'); |
1298
|
|
|
|
1299
|
|
|
foreach (PMF_Language::getAvailableLanguages() as $lang => $langname) { |
1300
|
|
|
if (!in_array(strtolower($lang), $existcatlang)) { |
1301
|
|
|
$output .= "\t<option value=\"".strtolower($lang)."\""; |
1302
|
|
|
if ($lang == $selected_lang) { |
1303
|
|
|
$output .= " selected=\"selected\""; |
1304
|
|
|
} |
1305
|
|
|
$output .= ">".$langname."</option>\n"; |
1306
|
|
|
} |
1307
|
|
|
} |
1308
|
|
|
|
1309
|
|
|
return $output; |
1310
|
|
|
} |
1311
|
|
|
|
1312
|
|
|
/** |
1313
|
|
|
* Gets all categories which are not translated in actual language |
1314
|
|
|
* to add in this->categories (used in admin section) |
1315
|
|
|
* |
1316
|
|
|
* @return void |
1317
|
|
|
*/ |
1318
|
|
|
public function getMissingCategories() |
1319
|
|
|
{ |
1320
|
|
|
$query = sprintf(" |
1321
|
|
|
SELECT |
1322
|
|
|
id, lang, parent_id, name, description, user_id |
1323
|
|
|
FROM |
1324
|
|
|
%sfaqcategories", |
1325
|
|
|
PMF_Db::getTablePrefix()); |
1326
|
|
View Code Duplication |
if (isset($this->language) && preg_match("/^[a-z\-]{2,}$/", $this->language)) { |
|
|
|
|
1327
|
|
|
$query .= " WHERE lang != '".$this->language."'"; |
1328
|
|
|
} |
1329
|
|
|
$query .= ' ORDER BY id'; |
1330
|
|
|
$result = $this->_config->getDb()->query($query); |
1331
|
|
|
while ($row = $this->_config->getDb()->fetchArray($result)) { |
1332
|
|
|
if (!array_key_exists($row['id'],$this->categoryName)) { |
1333
|
|
|
$this->categoryName[$row['id']] = $row; |
1334
|
|
|
$this->categories[] =& $this->categoryName[$row['id']]; |
1335
|
|
|
$this->children[$row['parent_id']][$row['id']] =& $this->categoryName[$row['id']]; |
1336
|
|
|
} |
1337
|
|
|
} |
1338
|
|
|
} |
1339
|
|
|
|
1340
|
|
|
/** |
1341
|
|
|
* Get number of nodes at the same parent_id level |
1342
|
|
|
* |
1343
|
|
|
* @param integer $parent_id Parent id |
1344
|
|
|
* @return integer |
1345
|
|
|
*/ |
1346
|
|
|
public function numParent($parent_id) |
1347
|
|
|
{ |
1348
|
|
|
$query = sprintf(" |
1349
|
|
|
SELECT distinct |
1350
|
|
|
id |
1351
|
|
|
FROM |
1352
|
|
|
%sfaqcategories |
1353
|
|
|
WHERE |
1354
|
|
|
parent_id = %d", |
1355
|
|
|
PMF_Db::getTablePrefix(), |
1356
|
|
|
$parent_id); |
1357
|
|
|
$result = $this->_config->getDb()->query($query); |
1358
|
|
|
|
1359
|
|
|
return $this->_config->getDb()->numRows($result); |
1360
|
|
|
} |
1361
|
|
|
|
1362
|
|
|
/** |
1363
|
|
|
* Adds the category permissions for users and groups |
1364
|
|
|
* |
1365
|
|
|
* @param string $mode 'group' or 'user' |
1366
|
|
|
* @param array $categories ID of the current category |
1367
|
|
|
* @param array $ids Array of group or user IDs |
1368
|
|
|
* |
1369
|
|
|
* @return boolean |
1370
|
|
|
*/ |
1371
|
|
|
public function addPermission($mode, Array $categories, Array $ids) |
1372
|
|
|
{ |
1373
|
|
|
if ('user' !== $mode && 'group' !== $mode) { |
1374
|
|
|
return false; |
1375
|
|
|
} |
1376
|
|
|
|
1377
|
|
|
foreach ($categories as $categoryId) { |
1378
|
|
|
foreach ($ids as $id) { |
1379
|
|
|
$query = sprintf( |
1380
|
|
|
"SELECT * FROM %sfaqcategory_%s WHERE category_id = %d AND %s_id = %d", |
1381
|
|
|
PMF_Db::getTablePrefix(), |
1382
|
|
|
$mode, |
1383
|
|
|
$categoryId, |
1384
|
|
|
$mode, |
1385
|
|
|
$id |
1386
|
|
|
); |
1387
|
|
|
|
1388
|
|
|
if ($this->_config->getDb()->numRows($this->_config->getDb()->query($query))) { |
1389
|
|
|
continue; |
1390
|
|
|
} |
1391
|
|
|
|
1392
|
|
|
$query = sprintf( |
1393
|
|
|
'INSERT INTO %sfaqcategory_%s (category_id, %s_id) VALUES (%d, %d)', |
1394
|
|
|
PMF_Db::getTablePrefix(), |
1395
|
|
|
$mode, |
1396
|
|
|
$mode, |
1397
|
|
|
$categoryId, |
1398
|
|
|
$id |
1399
|
|
|
); |
1400
|
|
|
|
1401
|
|
|
$this->_config->getDb()->query($query); |
1402
|
|
|
} |
1403
|
|
|
} |
1404
|
|
|
|
1405
|
|
|
return true; |
1406
|
|
|
} |
1407
|
|
|
|
1408
|
|
|
/** |
1409
|
|
|
* Deletes the category permissions for users and groups |
1410
|
|
|
* |
1411
|
|
|
* @param string $mode 'group' or 'user' |
1412
|
|
|
* @param array $categories ID of the current category |
1413
|
|
|
* @return boolean |
1414
|
|
|
*/ |
1415
|
|
View Code Duplication |
public function deletePermission($mode, $categories) |
1416
|
|
|
{ |
1417
|
|
|
if (!($mode == "user" || $mode == "group")) { |
1418
|
|
|
return false; |
1419
|
|
|
} |
1420
|
|
|
if (!is_array($categories)) { |
1421
|
|
|
return false; |
1422
|
|
|
} |
1423
|
|
|
|
1424
|
|
|
foreach ($categories as $category_id) { |
1425
|
|
|
$query = sprintf(" |
1426
|
|
|
DELETE FROM |
1427
|
|
|
%sfaqcategory_%s |
1428
|
|
|
WHERE |
1429
|
|
|
category_id = %d", |
1430
|
|
|
PMF_Db::getTablePrefix(), |
1431
|
|
|
$mode, |
1432
|
|
|
$category_id); |
1433
|
|
|
$this->_config->getDb()->query($query); |
1434
|
|
|
} |
1435
|
|
|
|
1436
|
|
|
return true; |
1437
|
|
|
} |
1438
|
|
|
|
1439
|
|
|
/** |
1440
|
|
|
* Returns the category permissions for users and groups |
1441
|
|
|
* |
1442
|
|
|
* @param string $mode 'group' or 'user' |
1443
|
|
|
* @param array $categories Array of category ids |
1444
|
|
|
* @return array |
1445
|
|
|
*/ |
1446
|
|
|
public function getPermissions($mode, Array $categories) |
1447
|
|
|
{ |
1448
|
|
|
$permissions = array(); |
1449
|
|
|
if (!($mode == "user" || $mode == "group")) { |
1450
|
|
|
return false; |
1451
|
|
|
} |
1452
|
|
|
if (!is_array($categories)) { |
1453
|
|
|
return false; |
1454
|
|
|
} |
1455
|
|
|
|
1456
|
|
|
$query = sprintf(" |
1457
|
|
|
SELECT |
1458
|
|
|
%s_id AS permission |
1459
|
|
|
FROM |
1460
|
|
|
%sfaqcategory_%s |
1461
|
|
|
WHERE |
1462
|
|
|
category_id IN (%s)", |
1463
|
|
|
$mode, |
1464
|
|
|
PMF_Db::getTablePrefix(), |
1465
|
|
|
$mode, |
1466
|
|
|
implode(', ', $categories)); |
1467
|
|
|
|
1468
|
|
|
$result = $this->_config->getDb()->query($query); |
1469
|
|
|
while ($row = $this->_config->getDb()->fetchObject($result)) { |
1470
|
|
|
$permissions[] = $row->permission; |
1471
|
|
|
} |
1472
|
|
|
return $permissions; |
1473
|
|
|
} |
1474
|
|
|
|
1475
|
|
|
/** |
1476
|
|
|
* Returns the number of records in each category |
1477
|
|
|
* |
1478
|
|
|
* @return array |
1479
|
|
|
*/ |
1480
|
|
|
public function getNumberOfRecordsOfCategory() |
1481
|
|
|
{ |
1482
|
|
|
$numRecordsByCat = array(); |
1483
|
|
|
|
1484
|
|
|
$query = sprintf(" |
1485
|
|
|
SELECT |
1486
|
|
|
fcr.category_id AS category_id, |
1487
|
|
|
COUNT(fcr.record_id) AS number |
1488
|
|
|
FROM |
1489
|
|
|
%sfaqcategoryrelations fcr, %sfaqdata fd |
1490
|
|
|
WHERE |
1491
|
|
|
fcr.record_id = fd.id |
1492
|
|
|
AND |
1493
|
|
|
fcr.record_lang = fd.lang |
1494
|
|
|
GROUP BY fcr.category_id", |
1495
|
|
|
PMF_Db::getTablePrefix(), |
1496
|
|
|
PMF_Db::getTablePrefix()); |
1497
|
|
|
|
1498
|
|
|
$result = $this->_config->getDb()->query($query); |
1499
|
|
|
if ($this->_config->getDb()->numRows($result) > 0) { |
1500
|
|
|
while ($row = $this->_config->getDb()->fetchObject($result)) { |
1501
|
|
|
$numRecordsByCat[$row->category_id] = $row->number; |
1502
|
|
|
} |
1503
|
|
|
} |
1504
|
|
|
|
1505
|
|
|
return $numRecordsByCat; |
1506
|
|
|
} |
1507
|
|
|
|
1508
|
|
|
/** |
1509
|
|
|
* Create a matrix for representing categories and faq records |
1510
|
|
|
* |
1511
|
|
|
* @return array |
1512
|
|
|
*/ |
1513
|
|
|
public function getCategoryRecordsMatrix() |
1514
|
|
|
{ |
1515
|
|
|
$matrix = array(); |
1516
|
|
|
|
1517
|
|
|
$query = sprintf(' |
1518
|
|
|
SELECT |
1519
|
|
|
fcr.category_id AS id_cat, |
1520
|
|
|
fd.id AS id |
1521
|
|
|
FROM |
1522
|
|
|
%sfaqdata fd |
1523
|
|
|
INNER JOIN |
1524
|
|
|
%sfaqcategoryrelations fcr |
1525
|
|
|
ON |
1526
|
|
|
fd.id = fcr.record_id |
1527
|
|
|
AND |
1528
|
|
|
fd.lang = fcr.category_lang |
1529
|
|
|
ORDER BY |
1530
|
|
|
fcr.category_id, fd.id', |
1531
|
|
|
PMF_Db::getTablePrefix(), |
1532
|
|
|
PMF_Db::getTablePrefix()); |
1533
|
|
|
$result = $this->_config->getDb()->query($query); |
1534
|
|
|
|
1535
|
|
|
if ($this->_config->getDb()->numRows($result) > 0) { |
1536
|
|
|
while ($row = $this->_config->getDb()->fetchObject($result)) { |
1537
|
|
|
$matrix[$row->id_cat][$row->id] = true; |
1538
|
|
|
} |
1539
|
|
|
} |
1540
|
|
|
|
1541
|
|
|
return $matrix; |
1542
|
|
|
} |
1543
|
|
|
|
1544
|
|
|
/** |
1545
|
|
|
* Sets language |
1546
|
|
|
* |
1547
|
|
|
* @param string $language |
1548
|
|
|
*/ |
1549
|
|
|
public function setLanguage($language) |
1550
|
|
|
{ |
1551
|
|
|
$this->language = $language; |
1552
|
|
|
} |
1553
|
|
|
|
1554
|
|
|
/** |
1555
|
|
|
* Returns the user id of the category owner |
1556
|
|
|
* |
1557
|
|
|
* @param integer $categoryId |
1558
|
|
|
* |
1559
|
|
|
* @return integer |
1560
|
|
|
*/ |
1561
|
|
|
public function getOwner($categoryId) |
1562
|
|
|
{ |
1563
|
|
|
return isset($this->owner[$categoryId]) ? $this->owner[$categoryId] : 1; |
1564
|
|
|
} |
1565
|
|
|
} |
1566
|
|
|
|
Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.
You can also find more detailed suggestions in the “Code” section of your repository.