Completed
Branch master (c92e39)
by Michael
02:32
created

functions.php ➔ sf_createCategorySelect()   B

Complexity

Conditions 4
Paths 4

Size

Total Lines 23
Code Lines 12

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 4
eloc 12
nc 4
nop 3
dl 0
loc 23
rs 8.7972
c 0
b 0
f 0
1
<?php
0 ignored issues
show
Coding Style Compatibility introduced by
For compatibility and reusability of your code, PSR1 recommends that a file should introduce either new symbols (like classes, functions, etc.) or have side-effects (like outputting something, or including other files), but not both at the same time. The first symbol is defined on line 17 and the first side effect is on line 10.

The PSR-1: Basic Coding Standard recommends that a file should either introduce new symbols, that is classes, functions, constants or similar, or have side effects. Side effects are anything that executes logic, like for example printing output, changing ini settings or writing to a file.

The idea behind this recommendation is that merely auto-loading a class should not change the state of an application. It also promotes a cleaner style of programming and makes your code less prone to errors, because the logic is not spread out all over the place.

To learn more about the PSR-1, please see the PHP-FIG site on the PSR-1.

Loading history...
2
3
/**
4
 * Module: SmartFAQ
5
 * Author: The SmartFactory <www.smartfactory.ca>
6
 * Licence: GNU
7
 */
8
// defined('XOOPS_ROOT_PATH') || exit('XOOPS root path not defined');
0 ignored issues
show
Unused Code Comprehensibility introduced by
70% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
9
10
include_once XOOPS_ROOT_PATH . '/modules/smartfaq/class/category.php';
11
include_once XOOPS_ROOT_PATH . '/modules/smartfaq/class/faq.php';
12
include_once XOOPS_ROOT_PATH . '/modules/smartfaq/class/answer.php';
13
14
/**
15
 * @return mixed|null
16
 */
17
function sf_getModuleInfo()
18
{
19
    static $smartModule;
20 View Code Duplication
    if (!isset($smartModule)) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

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.

Loading history...
21
        global $xoopsModule;
0 ignored issues
show
Compatibility Best Practice introduced by
Use of global functionality is not recommended; it makes your code harder to test, and less reusable.

Instead of relying on global state, we recommend one of these alternatives:

1. Pass all data via parameters

function myFunction($a, $b) {
    // Do something
}

2. Create a class that maintains your state

class MyClass {
    private $a;
    private $b;

    public function __construct($a, $b) {
        $this->a = $a;
        $this->b = $b;
    }

    public function myFunction() {
        // Do something
    }
}
Loading history...
22
        if (isset($xoopsModule) && is_object($xoopsModule) && $xoopsModule->getVar('dirname') === 'smartfaq') {
23
            $smartModule = $xoopsModule;
24
        } else {
25
            $hModule     = xoops_getHandler('module');
26
            $smartModule = $hModule->getByDirname('smartfaq');
27
        }
28
    }
29
30
    return $smartModule;
31
}
32
33
/**
34
 * @return mixed
35
 */
36
function sf_getModuleConfig()
37
{
38
    static $smartConfig;
39
    if (!$smartConfig) {
40
        global $xoopsModule;
0 ignored issues
show
Compatibility Best Practice introduced by
Use of global functionality is not recommended; it makes your code harder to test, and less reusable.

Instead of relying on global state, we recommend one of these alternatives:

1. Pass all data via parameters

function myFunction($a, $b) {
    // Do something
}

2. Create a class that maintains your state

class MyClass {
    private $a;
    private $b;

    public function __construct($a, $b) {
        $this->a = $a;
        $this->b = $b;
    }

    public function myFunction() {
        // Do something
    }
}
Loading history...
41 View Code Duplication
        if (isset($xoopsModule) && is_object($xoopsModule) && $xoopsModule->getVar('dirname') === 'smartfaq') {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

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.

Loading history...
42
            global $xoopsModuleConfig;
0 ignored issues
show
Compatibility Best Practice introduced by
Use of global functionality is not recommended; it makes your code harder to test, and less reusable.

Instead of relying on global state, we recommend one of these alternatives:

1. Pass all data via parameters

function myFunction($a, $b) {
    // Do something
}

2. Create a class that maintains your state

class MyClass {
    private $a;
    private $b;

    public function __construct($a, $b) {
        $this->a = $a;
        $this->b = $b;
    }

    public function myFunction() {
        // Do something
    }
}
Loading history...
43
            $smartConfig = $xoopsModuleConfig;
44
        } else {
45
            $smartModule = sf_getModuleInfo();
46
            $hModConfig  = xoops_getHandler('config');
47
            $smartConfig = $hModConfig->getConfigsByCat(0, $smartModule->getVar('mid'));
48
        }
49
    }
50
51
    return $smartConfig;
52
}
53
54
/**
55
 * @return string
56
 */
57
function sf_getHelpPath()
58
{
59
    $smartConfig = sf_getModuleConfig();
60
    switch ($smartConfig['helppath_select']) {
61
        case 'docs.xoops.org':
62
            return 'http://docs.xoops.org/help/sfaqh/index.htm';
63
            break;
0 ignored issues
show
Unused Code introduced by
break is not strictly necessary here and could be removed.

The break statement is not necessary if it is preceded for example by a return statement:

switch ($x) {
    case 1:
        return 'foo';
        break; // This break is not necessary and can be left off.
}

If you would like to keep this construct to be consistent with other case statements, you can safely mark this issue as a false-positive.

Loading history...
64
65
        case 'inside':
66
            return XOOPS_URL . '/modules/smartfaq/doc/';
67
            break;
0 ignored issues
show
Unused Code introduced by
break is not strictly necessary here and could be removed.

The break statement is not necessary if it is preceded for example by a return statement:

switch ($x) {
    case 1:
        return 'foo';
        break; // This break is not necessary and can be left off.
}

If you would like to keep this construct to be consistent with other case statements, you can safely mark this issue as a false-positive.

Loading history...
68
69
        case 'custom':
70
            return $smartConfig['helppath_custom'];
71
            break;
0 ignored issues
show
Unused Code introduced by
break is not strictly necessary here and could be removed.

The break statement is not necessary if it is preceded for example by a return statement:

switch ($x) {
    case 1:
        return 'foo';
        break; // This break is not necessary and can be left off.
}

If you would like to keep this construct to be consistent with other case statements, you can safely mark this issue as a false-positive.

Loading history...
72
    }
73
}
74
75
/**
76
 * @param  array $errors
77
 * @return string
78
 */
79
function sf_formatErrors($errors = array())
80
{
81
    $ret = '';
82
    foreach ($errors as $key => $value) {
83
        $ret .= '<br> - ' . $value;
84
    }
85
86
    return $ret;
87
}
88
89
/**
90
 * @param         $categoryObj
91
 * @param  int    $selectedid
92
 * @param  int    $level
93
 * @param  string $ret
94
 * @return string
95
 */
96
function sf_addCategoryOption($categoryObj, $selectedid = 0, $level = 0, $ret = '')
97
{
98
    // Creating the category handler object
99
    $categoryHandler = sf_gethandler('category');
100
101
    $spaces = '';
102
    for ($j = 0; $j < $level; ++$j) {
103
        $spaces .= '--';
104
    }
105
106
    $ret .= "<option value='" . $categoryObj->categoryid() . "'";
107
    if ($selectedid == $categoryObj->categoryid()) {
108
        $ret .= ' selected';
109
    }
110
    $ret .= '>' . $spaces . $categoryObj->name() . "</option>\n";
111
112
    $subCategoriesObj = $categoryHandler->getCategories(0, 0, $categoryObj->categoryid());
113
    if (count($subCategoriesObj) > 0) {
114
        ++$level;
115
        foreach ($subCategoriesObj as $catID => $subCategoryObj) {
116
            $ret .= sf_addCategoryOption($subCategoryObj, $selectedid, $level);
117
        }
118
    }
119
120
    return $ret;
121
}
122
123
/**
124
 * @param  int  $selectedid
125
 * @param  int  $parentcategory
126
 * @param  bool $allCatOption
127
 * @return string
128
 */
129
function sf_createCategorySelect($selectedid = 0, $parentcategory = 0, $allCatOption = true)
130
{
131
    $ret = '' . _MB_SF_SELECTCAT . "&nbsp;<select name='options[]'>";
132
    if ($allCatOption) {
133
        $ret .= "<option value='0'";
134
        $ret .= '>' . _MB_SF_ALLCAT . "</option>\n";
135
    }
136
137
    // Creating the category handler object
138
    $categoryHandler = sf_gethandler('category');
139
140
    // Creating category objects
141
    $categoriesObj = $categoryHandler->getCategories(0, 0, $parentcategory);
142
143
    if (count($categoriesObj) > 0) {
144
        foreach ($categoriesObj as $catID => $categoryObj) {
145
            $ret .= sf_addCategoryOption($categoryObj, $selectedid);
146
        }
147
    }
148
    $ret .= "</select>\n";
149
150
    return $ret;
151
}
152
153
/**
154
 * @return array
155
 */
156
function sf_getStatusArray()
157
{
158
    $result = array(
159
        '1' => _AM_SF_STATUS1,
160
        '2' => _AM_SF_STATUS2,
161
        '3' => _AM_SF_STATUS3,
162
        '4' => _AM_SF_STATUS4,
163
        '5' => _AM_SF_STATUS5,
164
        '6' => _AM_SF_STATUS6,
165
        '7' => _AM_SF_STATUS7,
166
        '8' => _AM_SF_STATUS8
167
    );
168
169
    return $result;
170
}
171
172
/**
173
 * @return bool
174
 */
175
function sf_moderator()
176
{
177
    global $xoopsUser;
0 ignored issues
show
Compatibility Best Practice introduced by
Use of global functionality is not recommended; it makes your code harder to test, and less reusable.

Instead of relying on global state, we recommend one of these alternatives:

1. Pass all data via parameters

function myFunction($a, $b) {
    // Do something
}

2. Create a class that maintains your state

class MyClass {
    private $a;
    private $b;

    public function __construct($a, $b) {
        $this->a = $a;
        $this->b = $b;
    }

    public function myFunction() {
        // Do something
    }
}
Loading history...
178
179
    if (!$xoopsUser) {
180
        $result = false;
181
    } else {
182
        $smartPermHandler = xoops_getModuleHandler('permission', 'smartfaq');
183
184
        $categories = $smartPermHandler->getPermissions('moderation');
185
        if (count($categories) == 0) {
186
            $result = false;
187
        } else {
188
            $result = true;
189
        }
190
    }
191
192
    return $result;
193
}
194
195
/**
196
 * @return string
197
 */
198
function sf_modFooter()
199
{
200
    $smartModule = sf_getModuleInfo();
201
202
    $modfootertxt = 'Module ' . $smartModule->getInfo('name') . ' - Version ' . $smartModule->getInfo('version') . '';
203
204
    $modfooter = "<a href='"
205
                 . $smartModule->getInfo('support_site_url')
206
                 . "' target='_blank'><img src='"
207
                 . XOOPS_URL
208
                 . "/modules/smartfaq/assets/images/sfcssbutton.gif' title='"
209
                 . $modfootertxt
210
                 . "' alt='"
211
                 . $modfootertxt
212
                 . "'/></a>";
213
214
    return $modfooter;
215
}
216
217
/**
218
 * Checks if a user is admin of Smartfaq
219
 *
220
 * sf_userIsAdmin()
221
 *
222
 * @return boolean : array with userids and uname
223
 */
224
function sf_userIsAdmin()
225
{
226
    global $xoopsUser;
0 ignored issues
show
Compatibility Best Practice introduced by
Use of global functionality is not recommended; it makes your code harder to test, and less reusable.

Instead of relying on global state, we recommend one of these alternatives:

1. Pass all data via parameters

function myFunction($a, $b) {
    // Do something
}

2. Create a class that maintains your state

class MyClass {
    private $a;
    private $b;

    public function __construct($a, $b) {
        $this->a = $a;
        $this->b = $b;
    }

    public function myFunction() {
        // Do something
    }
}
Loading history...
227
228
    $result = false;
229
230
    $smartModule = sf_getModuleInfo();
231
    $module_id   = $smartModule->getVar('mid');
232
233
    if (!empty($xoopsUser)) {
234
        $groups = $xoopsUser->getGroups();
235
        $result = in_array(XOOPS_GROUP_ADMIN, $groups) || $xoopsUser->isAdmin($module_id);
236
    }
237
238
    return $result;
239
}
240
241
/**
242
 * Checks if a user has access to a selected faq. If no item permissions are
243
 * set, access permission is denied. The user needs to have necessary category
244
 * permission as well.
245
 *
246
 * faqAccessGranted()
247
 *
248
 * @param $faqObj
249
 * @return int : -1 if no access, 0 if partialview and 1 if full access
250
 * @internal param int $faqid : faqid on which we are setting permissions
251
 * @internal param $integer $ categoryid : categoryid of the faq
252
 */
253
254
// TODO : Move this function to sfFaq class
255
function faqAccessGranted($faqObj)
256
{
257
    global $xoopsUser;
0 ignored issues
show
Compatibility Best Practice introduced by
Use of global functionality is not recommended; it makes your code harder to test, and less reusable.

Instead of relying on global state, we recommend one of these alternatives:

1. Pass all data via parameters

function myFunction($a, $b) {
    // Do something
}

2. Create a class that maintains your state

class MyClass {
    private $a;
    private $b;

    public function __construct($a, $b) {
        $this->a = $a;
        $this->b = $b;
    }

    public function myFunction() {
        // Do something
    }
}
Loading history...
258
259
    if (sf_userIsAdmin()) {
260
        $result = 1;
261
    } else {
262
        $result = -1;
263
264
        $groups = $xoopsUser ? $xoopsUser->getGroups() : XOOPS_GROUP_ANONYMOUS;
265
266
        $gpermHandler = xoops_getHandler('groupperm');
267
        $smartModule  = sf_getModuleInfo();
268
        $module_id    = $smartModule->getVar('mid');
269
270
        // Do we have access to the parent category
271
        if ($gpermHandler->checkRight('category_read', $faqObj->categoryid(), $groups, $module_id)) {
272
            // Do we have access to the faq?
273
            if ($gpermHandler->checkRight('item_read', $faqObj->faqid(), $groups, $module_id)) {
274
                $result = 1;
275
            } else { // No we don't !
276
                // Check to see if we have partial view access
277
                if (!is_object($xoopsUser) && $faqObj->partialView()) {
278
                    return 0;
279
                }
280
            }
281
        } else { // No we don't !
282
            $result = false;
283
        }
284
    }
285
286
    return $result;
287
}
288
289
/**
290
 * Override FAQs permissions of a category by the category read permissions
291
 *
292
 *   sf_overrideFaqsPermissions()
293
 *
294
 * @param  array   $groups     : group with granted permission
295
 * @param  integer $categoryid :
296
 * @return boolean : TRUE if the no errors occured
297
 */
298
function sf_overrideFaqsPermissions($groups, $categoryid)
299
{
300
    global $xoopsDB;
0 ignored issues
show
Compatibility Best Practice introduced by
Use of global functionality is not recommended; it makes your code harder to test, and less reusable.

Instead of relying on global state, we recommend one of these alternatives:

1. Pass all data via parameters

function myFunction($a, $b) {
    // Do something
}

2. Create a class that maintains your state

class MyClass {
    private $a;
    private $b;

    public function __construct($a, $b) {
        $this->a = $a;
        $this->b = $b;
    }

    public function myFunction() {
        // Do something
    }
}
Loading history...
301
302
    $result      = true;
0 ignored issues
show
Unused Code introduced by
$result is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
303
    $smartModule = sf_getModuleInfo();
304
    $module_id   = $smartModule->getVar('mid');
305
306
    $gpermHandler = xoops_getHandler('groupperm');
307
308
    $sql    = 'SELECT faqid FROM ' . $xoopsDB->prefix('smartfaq_faq') . " WHERE categoryid = '$categoryid' ";
309
    $result = $xoopsDB->query($sql);
310
311
    if (count($result) > 0) {
312
        while (list($faqid) = $xoopsDB->fetchrow($result)) {
313
            // First, if the permissions are already there, delete them
314
            $gpermHandler->deleteByModule($module_id, 'item_read', $faqid);
315
            // Save the new permissions
316
            if (count($groups) > 0) {
317
                foreach ($groups as $group_id) {
318
                    $gpermHandler->addRight('item_read', $faqid, $group_id, $module_id);
319
                }
320
            }
321
        }
322
    }
323
324
    return $result;
325
}
326
327
/**
328
 * Saves permissions for the selected faq
329
 *
330
 *   sf_saveItemPermissions()
331
 *
332
 * @param  array   $groups : group with granted permission
333
 * @param  integer $itemID : faqid on which we are setting permissions
334
 * @return boolean : TRUE if the no errors occured
335
 */
336 View Code Duplication
function sf_saveItemPermissions($groups, $itemID)
0 ignored issues
show
Duplication introduced by
This function seems to be duplicated in your project.

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.

Loading history...
337
{
338
    $result      = true;
339
    $smartModule = sf_getModuleInfo();
340
    $module_id   = $smartModule->getVar('mid');
341
342
    $gpermHandler = xoops_getHandler('groupperm');
343
    // First, if the permissions are already there, delete them
344
    $gpermHandler->deleteByModule($module_id, 'item_read', $itemID);
345
    // Save the new permissions
346
    if (count($groups) > 0) {
347
        foreach ($groups as $group_id) {
348
            $gpermHandler->addRight('item_read', $itemID, $group_id, $module_id);
349
        }
350
    }
351
352
    return $result;
353
}
354
355
/**
356
 * Saves permissions for the selected category
357
 *
358
 *   sf_saveCategory_Permissions()
359
 *
360
 * @param  array   $groups     : group with granted permission
361
 * @param  integer $categoryid : categoryid on which we are setting permissions
362
 * @param  string  $perm_name  : name of the permission
363
 * @return boolean : TRUE if the no errors occured
364
 */
365
366 View Code Duplication
function sf_saveCategory_Permissions($groups, $categoryid, $perm_name)
0 ignored issues
show
Duplication introduced by
This function seems to be duplicated in your project.

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.

Loading history...
367
{
368
    $result      = true;
369
    $smartModule = sf_getModuleInfo();
370
    $module_id   = $smartModule->getVar('mid');
371
372
    $gpermHandler = xoops_getHandler('groupperm');
373
    // First, if the permissions are already there, delete them
374
    $gpermHandler->deleteByModule($module_id, $perm_name, $categoryid);
375
    // Save the new permissions
376
    if (count($groups) > 0) {
377
        foreach ($groups as $group_id) {
378
            $gpermHandler->addRight($perm_name, $categoryid, $group_id, $module_id);
379
        }
380
    }
381
382
    return $result;
383
}
384
385
/**
386
 * Saves permissions for the selected category
387
 *
388
 *   sf_saveModerators()
389
 *
390
 * @param  array   $moderators : moderators uids
391
 * @param  integer $categoryid : categoryid on which we are setting permissions
392
 * @return boolean : TRUE if the no errors occured
393
 */
394
395 View Code Duplication
function sf_saveModerators($moderators, $categoryid)
0 ignored issues
show
Duplication introduced by
This function seems to be duplicated in your project.

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.

Loading history...
396
{
397
    $result      = true;
398
    $smartModule = sf_getModuleInfo();
399
    $module_id   = $smartModule->getVar('mid');
400
401
    $gpermHandler = xoops_getHandler('groupperm');
402
    // First, if the permissions are already there, delete them
403
    $gpermHandler->deleteByModule($module_id, 'category_moderation', $categoryid);
404
    // Save the new permissions
405
    if (count($moderators) > 0) {
406
        foreach ($moderators as $uid) {
407
            $gpermHandler->addRight('category_moderation', $categoryid, $uid, $module_id);
408
        }
409
    }
410
411
    return $result;
412
}
413
414
/**
415
 * @param  int $faqid
416
 * @return array
417
 */
418
function sf_retrieveFaqByID($faqid = 0)
419
{
420
    $ret = array();
0 ignored issues
show
Unused Code introduced by
$ret is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
421
    global $xoopsDB;
0 ignored issues
show
Compatibility Best Practice introduced by
Use of global functionality is not recommended; it makes your code harder to test, and less reusable.

Instead of relying on global state, we recommend one of these alternatives:

1. Pass all data via parameters

function myFunction($a, $b) {
    // Do something
}

2. Create a class that maintains your state

class MyClass {
    private $a;
    private $b;

    public function __construct($a, $b) {
        $this->a = $a;
        $this->b = $b;
    }

    public function myFunction() {
        // Do something
    }
}
Loading history...
422
423
    $result = $xoopsDB->query('SELECT * FROM ' . $xoopsDB->prefix('smartfaq_faq') . " WHERE faqid = '$faqid'");
424
    $ret    = $xoopsDB->fetcharray($result);
425
426
    return $ret;
427
}
428
429
/**
430
 * sf_getAdminLinks()
431
 *
432
 * @param  integer $faqid
433
 * @param  bool    $open
434
 * @return string
435
 */
436
437
// TODO : Move this to the sfFaq class
438
function sf_getAdminLinks($faqid = 0, $open = false)
439
{
440
    global $xoopsUser, $xoopsModule, $xoopsModuleConfig, $xoopsConfig;
0 ignored issues
show
Compatibility Best Practice introduced by
Use of global functionality is not recommended; it makes your code harder to test, and less reusable.

Instead of relying on global state, we recommend one of these alternatives:

1. Pass all data via parameters

function myFunction($a, $b) {
    // Do something
}

2. Create a class that maintains your state

class MyClass {
    private $a;
    private $b;

    public function __construct($a, $b) {
        $this->a = $a;
        $this->b = $b;
    }

    public function myFunction() {
        // Do something
    }
}
Loading history...
441
    $adminLinks = '';
442
    $modulePath = XOOPS_URL . '/modules/' . $xoopsModule->dirname() . '/';
443
    $page       = $open ? 'question.php' : 'faq.php';
444
    if ($xoopsUser && $xoopsUser->isAdmin($xoopsModule->getVar('mid'))) {
445
        // Edit button
446
        $adminLinks .= "<a href='"
447
                       . $modulePath
448
                       . "admin/$page?op=mod&amp;faqid="
449
                       . $faqid
450
                       . "'><img src='"
451
                       . $modulePath
452
                       . "assets/images/links/edit.gif'"
453
                       . " title='"
454
                       . _MD_SF_EDIT
455
                       . "' alt='"
456
                       . _MD_SF_EDIT
457
                       . "'/></a>";
458
        $adminLinks .= ' ';
459
        // Delete button
460
        $adminLinks .= "<a href='"
461
                       . $modulePath
462
                       . "admin/$page?op=del&amp;faqid="
463
                       . $faqid
464
                       . "'><img src='"
465
                       . $modulePath
466
                       . "assets/images/links/delete.gif'"
467
                       . " title='"
468
                       . _MD_SF_DELETE
469
                       . "' alt='"
470
                       . _MD_SF_DELETE
471
                       . "'/></a>";
472
        $adminLinks .= ' ';
473
    }
474
    // Print button
475
    $adminLinks .= "<a href='"
476
                   . $modulePath
477
                   . 'print.php?faqid='
478
                   . $faqid
479
                   . "'><img src='"
480
                   . $modulePath
481
                   . "assets/images/links/print.gif' title='"
482
                   . _MD_SF_PRINT
483
                   . "' alt='"
484
                   . _MD_SF_PRINT
485
                   . "'/></a>";
486
    $adminLinks .= ' ';
487
    // Email button
488
    $maillink   = 'mailto:?subject='
489
                  . sprintf(_MD_SF_INTARTICLE, $xoopsConfig['sitename'])
490
                  . '&amp;body='
491
                  . sprintf(_MD_SF_INTARTFOUND, $xoopsConfig['sitename'])
492
                  . ':  '
493
                  . $modulePath
494
                  . 'faq.php?faqid='
495
                  . $faqid;
496
    $adminLinks .= '<a href="' . $maillink . "\"><img src='" . $modulePath . "assets/images/links/friend.gif' title='" . _MD_SF_MAIL . "' alt='" . _MD_SF_MAIL . "'/></a>";
497
    $adminLinks .= ' ';
498
    // Submit New Answer button
499
    if ($xoopsModuleConfig['allownewanswer'] && (is_object($xoopsUser) || $xoopsModuleConfig['anonpost'])) {
500
        $adminLinks .= "<a href='"
501
                       . $modulePath
502
                       . 'answer.php?faqid='
503
                       . $faqid
504
                       . "'><img src='"
505
                       . $modulePath
506
                       . "assets/images/links/newanswer.gif' title='"
507
                       . _MD_SF_SUBMITANSWER
508
                       . "' alt='"
509
                       . _MD_SF_SUBMITANSWER
510
                       . "'/></a>";
511
        $adminLinks .= ' ';
512
    }
513
514
    return $adminLinks;
515
}
516
517
/**
518
 * sf_getLinkedUnameFromId()
519
 *
520
 * @param  integer $userid Userid of poster etc
521
 * @param  integer $name   :  0 Use Usenamer 1 Use realname
522
 * @param  array   $users
523
 * @return string
524
 */
525
function sf_getLinkedUnameFromId($userid = 0, $name = 0, $users = array())
0 ignored issues
show
Coding Style introduced by
sf_getLinkedUnameFromId uses the super-global variable $GLOBALS which is generally not recommended.

Instead of super-globals, we recommend to explicitly inject the dependencies of your class. This makes your code less dependent on global state and it becomes generally more testable:

// Bad
class Router
{
    public function generate($path)
    {
        return $_SERVER['HOST'].$path;
    }
}

// Better
class Router
{
    private $host;

    public function __construct($host)
    {
        $this->host = $host;
    }

    public function generate($path)
    {
        return $this->host.$path;
    }
}

class Controller
{
    public function myAction(Request $request)
    {
        // Instead of
        $page = isset($_GET['page']) ? intval($_GET['page']) : 1;

        // Better (assuming you use the Symfony2 request)
        $page = $request->query->get('page', 1);
    }
}
Loading history...
526
{
527
    if (!is_numeric($userid)) {
528
        return $userid;
529
    }
530
531
    $userid = (int)$userid;
532
    if ($userid > 0) {
533
        if ($users == array()) {
534
            //fetching users
535
            $memberHandler = xoops_getHandler('member');
536
            $user          = $memberHandler->getUser($userid);
537
        } else {
538
            if (!isset($users[$userid])) {
539
                return $GLOBALS['xoopsConfig']['anonymous'];
540
            }
541
            $user =& $users[$userid];
542
        }
543
544
        if (is_object($user)) {
545
            $ts       = MyTextSanitizer::getInstance();
546
            $username = $user->getVar('uname');
547
            $fullname = '';
548
549
            $fullname2 = $user->getVar('name');
550
551
            if ($name && !empty($fullname2)) {
552
                $fullname = $user->getVar('name');
553
            }
554
            if (!empty($fullname)) {
555
                $linkeduser = "$fullname [<a href='" . XOOPS_URL . '/userinfo.php?uid=' . $userid . "'>" . $ts->htmlSpecialChars($username) . '</a>]';
556
            } else {
557
                $linkeduser = "<a href='" . XOOPS_URL . '/userinfo.php?uid=' . $userid . "'>" . ucwords($ts->htmlSpecialChars($username)) . '</a>';
558
            }
559
560
            return $linkeduser;
561
        }
562
    }
563
564
    return $GLOBALS['xoopsConfig']['anonymous'];
565
}
566
567
/**
568
 * @param  string $url
569
 * @return mixed|string
570
 */
571
function sf_getxoopslink($url = '')
572
{
573
    $xurl = $url;
574
    if (strlen($xurl) > 0) {
575
        if ($xurl[0] = '/') {
576
            $xurl = str_replace('/', '', $xurl);
577
        }
578
        $xurl = str_replace('{SITE_URL}', XOOPS_URL, $xurl);
0 ignored issues
show
Unused Code introduced by
$xurl is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
579
    }
580
    $xurl = $url;
581
582
    return $xurl;
583
}
584
585
/**
586
 * @param string $tablename
587
 * @param string $iconname
588
 */
589
function sf_collapsableBar($tablename = '', $iconname = '')
590
{
591
    ?>
592
    <script type="text/javascript"><!--
593
        function goto_URL(object) {
594
            window.location.href = object.options[object.selectedIndex].value;
595
        }
596
597
        function toggle(id) {
598
            if (document.getElementById) {
599
                obj = document.getElementById(id);
600
            }
601
            if (document.all) {
602
                obj = document.all[id];
603
            }
604
            if (document.layers) {
605
                obj = document.layers[id];
606
            }
607
            if (obj) {
608
                if (obj.style.display === "none") {
609
                    obj.style.display = "";
610
                } else {
611
                    obj.style.display = "none";
612
                }
613
            }
614
615
            return false;
616
        }
617
618
        var iconClose = new Image();
619
        iconClose.src = '../assets/images/icon/close12.gif';
620
        var iconOpen = new Image();
621
        iconOpen.src = '../assets/images/icon/open12.gif';
622
623
        function toggleIcon(iconName) {
624
            if (document.images[iconName].src == window.iconOpen.src) {
625
                document.images[iconName].src = window.iconClose.src;
626
            }
627
            elseif(document.images[iconName].src == window.iconClose.src)
628
            {
629
                document.images[iconName].src = window.iconOpen.src;
630
            }
631
632
            return;
633
        }
634
635
        //-->
636
    </script>
637
    <?php
638
    echo "<h3 style=\"color: #2F5376; margin: 6px 0 0 0; \"><a href='#' onClick=\"toggle('" . $tablename . "'); toggleIcon('" . $iconname . "');\">";
639
}
640
641
/**
642
 * @param       $name
643
 * @param  bool $optional
644
 * @return bool
0 ignored issues
show
Documentation introduced by
Should the return type not be object|false?

This check compares the return type specified in the @return annotation of a function or method doc comment with the types returned by the function and raises an issue if they mismatch.

Loading history...
645
 */
646
function sf_gethandler($name, $optional = false)
0 ignored issues
show
Coding Style introduced by
sf_gethandler uses the super-global variable $GLOBALS which is generally not recommended.

Instead of super-globals, we recommend to explicitly inject the dependencies of your class. This makes your code less dependent on global state and it becomes generally more testable:

// Bad
class Router
{
    public function generate($path)
    {
        return $_SERVER['HOST'].$path;
    }
}

// Better
class Router
{
    private $host;

    public function __construct($host)
    {
        $this->host = $host;
    }

    public function generate($path)
    {
        return $this->host.$path;
    }
}

class Controller
{
    public function myAction(Request $request)
    {
        // Instead of
        $page = isset($_GET['page']) ? intval($_GET['page']) : 1;

        // Better (assuming you use the Symfony2 request)
        $page = $request->query->get('page', 1);
    }
}
Loading history...
647
{
648
    static $handlers;
649
    $name = strtolower(trim($name));
650
    if (!isset($handlers[$name])) {
651
        if (file_exists($hnd_file = XOOPS_ROOT_PATH . '/modules/smartfaq/class/' . $name . '.php')) {
652
            require_once $hnd_file;
653
        }
654
        $class = 'sf' . ucfirst($name) . 'Handler';
655
        if (class_exists($class)) {
656
            $handlers[$name] = new $class($GLOBALS['xoopsDB']);
657
        }
658
    }
659
    if (!$optional && !isset($handlers[$name])) {
660
        trigger_error('Class <b>' . $class . '</b> does not exist<br>Handler Name: ' . $name, E_USER_ERROR);
0 ignored issues
show
Bug introduced by
The variable $class does not seem to be defined for all execution paths leading up to this point.

If you define a variable conditionally, it can happen that it is not defined for all execution paths.

Let’s take a look at an example:

function myFunction($a) {
    switch ($a) {
        case 'foo':
            $x = 1;
            break;

        case 'bar':
            $x = 2;
            break;
    }

    // $x is potentially undefined here.
    echo $x;
}

In the above example, the variable $x is defined if you pass “foo” or “bar” as argument for $a. However, since the switch statement has no default case statement, if you pass any other value, the variable $x would be undefined.

Available Fixes

  1. Check for existence of the variable explicitly:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        if (isset($x)) { // Make sure it's always set.
            echo $x;
        }
    }
    
  2. Define a default value for the variable:

    function myFunction($a) {
        $x = ''; // Set a default which gets overridden for certain paths.
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        echo $x;
    }
    
  3. Add a value for the missing path:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
    
            // We add support for the missing case.
            default:
                $x = '';
                break;
        }
    
        echo $x;
    }
    
Loading history...
661
    }
662
    $false = false;
663
664
    return isset($handlers[$name]) ? $handlers[$name] : $false;
665
}
666