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

sfFaq::sendNotifications()   C

Complexity

Conditions 11
Paths 20

Size

Total Lines 87
Code Lines 53

Duplication

Lines 28
Ratio 32.18 %

Importance

Changes 0
Metric Value
cc 11
eloc 53
nc 20
nop 1
dl 28
loc 87
rs 5.2653
c 0
b 0
f 0

How to fix   Long Method    Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

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 14 and the first side effect is on line 11.

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
9
// 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...
10
11
require_once XOOPS_ROOT_PATH . '/modules/smartfaq/class/category.php';
12
13
// FAQ status
14
define('_SF_STATUS_NOTSET', -1);
15
define('_SF_STATUS_ALL', 0);
16
define('_SF_STATUS_ASKED', 1);
17
define('_SF_STATUS_OPENED', 2);
18
define('_SF_STATUS_ANSWERED', 3);
19
define('_SF_STATUS_SUBMITTED', 4);
20
define('_SF_STATUS_PUBLISHED', 5);
21
define('_SF_STATUS_NEW_ANSWER', 6);
22
define('_SF_STATUS_OFFLINE', 7);
23
define('_SF_STATUS_REJECTED_QUESTION', 8);
24
define('_SF_STATUS_REJECTED_SMARTFAQ', 9);
25
26
// Notification Events
27
define('_SF_NOT_CATEGORY_CREATED', 1);
28
define('_SF_NOT_FAQ_SUBMITTED', 2);
29
define('_SF_NOT_FAQ_PUBLISHED', 3);
30
define('_SF_NOT_FAQ_REJECTED', 4);
31
define('_SF_NOT_QUESTION_SUBMITTED', 5);
32
define('_SF_NOT_QUESTION_PUBLISHED', 6);
33
define('_SF_NOT_NEW_ANSWER_PROPOSED', 7);
34
define('_SF_NOT_NEW_ANSWER_PUBLISHED', 8);
35
36
/**
37
 * Class sfFaq
38
 */
39
class sfFaq extends XoopsObject
0 ignored issues
show
Coding Style Compatibility introduced by
PSR1 recommends that each class must be in a namespace of at least one level to avoid collisions.

You can fix this by adding a namespace to your class:

namespace YourVendor;

class YourClass { }

When choosing a vendor namespace, try to pick something that is not too generic to avoid conflicts with other libraries.

Loading history...
40
{
41
42
    /**
43
     * @var sfCategory
44
     * @access private
45
     */
46
    private $category = null;
47
48
    /**
49
     * @var sfAnswer
50
     * @access private
51
     */
52
    private $answer = null;
53
54
    /**
55
     * @var array
56
     * @access private
57
     */
58
    private $_notifications = null;
0 ignored issues
show
Unused Code introduced by
The property $_notifications is not used and could be removed.

This check marks private properties in classes that are never used. Those properties can be removed.

Loading history...
59
    // TODO : Create a seperated class for notifications
60
61
    /**
62
     * @var array
63
     * @access private
64
     */
65
    private $groups_read = null;
66
67
    /**
68
     * @var object
69
     * @access private
70
     */
71
    // Is this still usefull??
72
    private $_smartModule = null;
0 ignored issues
show
Unused Code introduced by
The property $_smartModule is not used and could be removed.

This check marks private properties in classes that are never used. Those properties can be removed.

Loading history...
73
    private $_smartModuleConfig;
0 ignored issues
show
Unused Code introduced by
The property $_smartModuleConfig is not used and could be removed.

This check marks private properties in classes that are never used. Those properties can be removed.

Loading history...
74
75
    /**
76
     * constructor
77
     * @param null $id
78
     */
79
    public function __construct($id = null)
80
    {
81
        $this->db = XoopsDatabaseFactory::getDatabaseConnection();
82
        $this->initVar('faqid', XOBJ_DTYPE_INT, -1, false);
83
        $this->initVar('categoryid', XOBJ_DTYPE_INT, 0, false);
84
        $this->initVar('question', XOBJ_DTYPE_TXTBOX, null, true, 100000);
85
        $this->initVar('howdoi', XOBJ_DTYPE_TXTBOX, null, false, 255);
86
        $this->initVar('diduno', XOBJ_DTYPE_TXTBOX, null, false, 255);
87
        $this->initVar('uid', XOBJ_DTYPE_INT, 0, false);
88
        $this->initVar('datesub', XOBJ_DTYPE_INT, null, false);
89
        $this->initVar('status', XOBJ_DTYPE_INT, -1, false);
90
        $this->initVar('counter', XOBJ_DTYPE_INT, 0, false);
91
        $this->initVar('weight', XOBJ_DTYPE_INT, 0, false);
92
        $this->initVar('html', XOBJ_DTYPE_INT, 1, false);
93
        $this->initVar('smiley', XOBJ_DTYPE_INT, 1, false);
94
        $this->initVar('image', XOBJ_DTYPE_INT, 1, false);
95
        $this->initVar('linebreak', XOBJ_DTYPE_INT, 1, false);
96
        $this->initVar('xcodes', XOBJ_DTYPE_INT, 1, false);
97
        $this->initVar('cancomment', XOBJ_DTYPE_INT, 1, false);
98
        $this->initVar('comments', XOBJ_DTYPE_INT, 0, false);
99
        $this->initVar('notifypub', XOBJ_DTYPE_INT, 1, false);
100
        $this->initVar('modulelink', XOBJ_DTYPE_TXTBOX, 'None', false, 50);
101
        $this->initVar('contextpage', XOBJ_DTYPE_TXTBOX, null, false, 255);
102
        $this->initVar('exacturl', XOBJ_DTYPE_INT, 0, false);
103
        $this->initVar('partialview', XOBJ_DTYPE_INT, 0, false);
104
105
        if (isset($id)) {
106
            $faqHandler = new sfFaqHandler($this->db);
107
            $faq        = &$faqHandler->get($id);
108
            foreach ($faq->vars as $k => $v) {
109
                $this->assignVar($k, $v['value']);
110
            }
111
            $this->assignOtherProperties();
112
        }
113
    }
114
115
    public function assignOtherProperties()
116
    {
117
        $smartModule = sf_getModuleInfo();
118
        $module_id   = $smartModule->getVar('mid');
119
120
        $gpermHandler = xoops_getHandler('groupperm');
121
122
        $this->category    = new sfCategory($this->getVar('categoryid'));
123
        $this->groups_read = $gpermHandler->getGroupIds('item_read', $this->faqid(), $module_id);
124
    }
125
126
    /**
127
     * @return bool
128
     */
129 View Code Duplication
    public function checkPermission()
0 ignored issues
show
Duplication introduced by
This method 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...
130
    {
131
        include_once XOOPS_ROOT_PATH . '/modules/smartfaq/include/functions.php';
132
133
        $userIsAdmin = sf_userIsAdmin();
134
        if ($userIsAdmin) {
135
            return true;
136
        }
137
138
        $smartPermHandler = xoops_getModuleHandler('permission', 'smartfaq');
139
140
        $faqsGranted = $smartPermHandler->getPermissions('item');
141
        if (in_array($this->categoryid(), $faqsGranted)) {
142
            $ret = true;
143
        }
144
145
        return $ret;
0 ignored issues
show
Bug introduced by
The variable $ret 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...
146
    }
147
148
    /**
149
     * @return array
150
     */
151
    public function getGroups_read()
152
    {
153
        if (count($this->groups_read) < 1) {
154
            $this->assignOtherProperties();
155
        }
156
157
        return $this->groups_read;
158
    }
159
160
    /**
161
     * @param array $groups_read
162
     */
163
    public function setGroups_read($groups_read = array('0'))
164
    {
165
        $this->groups_read = $groups_read;
166
    }
167
168
    /**
169
     * @return mixed
170
     */
171
    public function faqid()
172
    {
173
        return $this->getVar('faqid');
174
    }
175
176
    /**
177
     * @return mixed
178
     */
179
    public function categoryid()
180
    {
181
        return $this->getVar('categoryid');
182
    }
183
184
    /**
185
     * @return sfCategory
186
     */
187
    public function category()
188
    {
189
        return $this->category;
190
    }
191
192
    /**
193
     * @param  int    $maxLength
194
     * @param  string $format
195
     * @return mixed|string
196
     */
197
    public function question($maxLength = 0, $format = 'S')
198
    {
199
        $ret = $this->getVar('question', $format);
200
        if (($format === 's') || ($format === 'S') || ($format === 'show')) {
201
            $myts = MyTextSanitizer:: getInstance();
0 ignored issues
show
Coding Style introduced by
Expected 0 spaces after double colon; 1 found

This check looks for references to static members where there are spaces between the name of the type and the actual member.

An example:

Certificate:: TRIPLEDES_CBC

will actually work, but is not very readable.

Loading history...
202
            $ret  = $myts->displayTarea($ret);
203
        }
204 View Code Duplication
        if ($maxLength != 0) {
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...
205
            if (!XOOPS_USE_MULTIBYTES) {
206
                if (strlen($ret) >= $maxLength) {
207
                    $ret = substr($ret, 0, $maxLength - 1) . '...';
208
                }
209
            }
210
        }
211
212
        return $ret;
213
    }
214
215
    /**
216
     * @param  string $format
217
     * @return mixed
218
     */
219 View Code Duplication
    public function howdoi($format = 'S')
0 ignored issues
show
Duplication introduced by
This method 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...
220
    {
221
        $ret = $this->getVar('howdoi', $format);
222
        if (($format === 's') || ($format === 'S') || ($format === 'show')) {
223
            $myts = MyTextSanitizer:: getInstance();
0 ignored issues
show
Coding Style introduced by
Expected 0 spaces after double colon; 1 found

This check looks for references to static members where there are spaces between the name of the type and the actual member.

An example:

Certificate:: TRIPLEDES_CBC

will actually work, but is not very readable.

Loading history...
224
            $ret  = $myts->displayTarea($ret);
225
        }
226
227
        return $ret;
228
    }
229
230
    /**
231
     * @param  string $format
232
     * @return mixed
233
     */
234 View Code Duplication
    public function diduno($format = 'S')
0 ignored issues
show
Duplication introduced by
This method 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...
235
    {
236
        $ret = $this->getVar('diduno', $format);
237
        if (($format === 's') || ($format === 'S') || ($format === 'show')) {
238
            $myts = MyTextSanitizer:: getInstance();
0 ignored issues
show
Coding Style introduced by
Expected 0 spaces after double colon; 1 found

This check looks for references to static members where there are spaces between the name of the type and the actual member.

An example:

Certificate:: TRIPLEDES_CBC

will actually work, but is not very readable.

Loading history...
239
            $ret  = $myts->displayTarea($ret);
240
        }
241
242
        return $ret;
243
    }
244
245
    /**
246
     * @return mixed
247
     */
248
    public function uid()
249
    {
250
        return $this->getVar('uid');
251
    }
252
253
    /**
254
     * @param  string $dateFormat
255
     * @param  string $format
256
     * @return string
257
     */
258 View Code Duplication
    public function datesub($dateFormat = 'none', $format = 'S')
0 ignored issues
show
Duplication introduced by
This method 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...
259
    {
260
        if ($dateFormat === 'none') {
261
            $smartConfig = sf_getModuleConfig();
262
            $dateFormat  = $smartConfig['dateformat'];
263
        }
264
265
        return formatTimestamp($this->getVar('datesub', $format), $dateFormat);
266
    }
267
268
    /**
269
     * @return mixed
270
     */
271
    public function status()
272
    {
273
        return $this->getVar('status');
274
    }
275
276
    /**
277
     * @return mixed
278
     */
279
    public function counter()
280
    {
281
        return $this->getVar('counter');
282
    }
283
284
    /**
285
     * @return mixed
286
     */
287
    public function weight()
288
    {
289
        return $this->getVar('weight');
290
    }
291
292
    /**
293
     * @return mixed
294
     */
295
    public function html()
296
    {
297
        return $this->getVar('html');
298
    }
299
300
    /**
301
     * @return mixed
302
     */
303
    public function smiley()
304
    {
305
        return $this->getVar('smiley');
306
    }
307
308
    /**
309
     * @return mixed
310
     */
311
    public function xcodes()
312
    {
313
        return $this->getVar('xcodes');
314
    }
315
316
    /**
317
     * @return mixed
318
     */
319
    public function cancomment()
320
    {
321
        return $this->getVar('cancomment');
322
    }
323
324
    /**
325
     * @return mixed
326
     */
327
    public function comments()
328
    {
329
        return $this->getVar('comments');
330
    }
331
332
    /**
333
     * @return mixed
334
     */
335
    public function notifypub()
336
    {
337
        return $this->getVar('notifypub');
338
    }
339
340
    /**
341
     * @param  string $format
342
     * @return mixed
343
     */
344
    public function modulelink($format = 'S')
345
    {
346
        return $this->getVar('modulelink', $format);
347
    }
348
349
    /**
350
     * @param  string $format
351
     * @return mixed
352
     */
353
    public function contextpage($format = 'S')
354
    {
355
        return $this->getVar('contextpage', $format);
356
    }
357
358
    /**
359
     * @return mixed
360
     */
361
    public function exacturl()
362
    {
363
        return $this->getVar('exacturl');
364
    }
365
366
    /**
367
     * @return mixed
368
     */
369
    public function partialview()
370
    {
371
        return $this->getVar('partialview');
372
    }
373
374
    /**
375
     * @param  int $realName
376
     * @return string
377
     */
378
    public function posterName($realName = -1)
379
    {
380
        if ($realName == -1) {
381
            $smartConfig = sf_getModuleConfig();
382
            $realName    = $smartConfig['userealname'];
383
        }
384
385
        return sf_getLinkedUnameFromId($this->uid(), $realName);
386
    }
387
388
    /**
389
     * @return mixed|object|sfAnswer
390
     */
391
    public function answer()
392
    {
393
        $answerHandler = new sfAnswerHandler($this->db);
394
        switch ($this->status()) {
395
            case _SF_STATUS_SUBMITTED:
396
                $theAnswers = $answerHandler->getAllAnswers($this->faqid(), _SF_AN_STATUS_APPROVED, 1, 0);
397
                //echo "test";
398
                //exit;
399
                $this->answer = &$theAnswers[0];
400
                break;
401
402
            case _SF_STATUS_ANSWERED:
403
                $theAnswers = $answerHandler->getAllAnswers($this->faqid(), _SF_AN_STATUS_PROPOSED, 1, 0);
404
                //echo "test";
405
                //exit;
406
                $this->answer = &$theAnswers[0];
407
                break;
408
409
            case _SF_STATUS_PUBLISHED:
410
            case _SF_STATUS_NEW_ANSWER:
411
            case _SF_STATUS_OFFLINE:
412
                $this->answer = $answerHandler->getOfficialAnswer($this->faqid());
413
                break;
414
415
            case _SF_STATUS_ASKED:
416
                $this->answer = $answerHandler->create();
417
                break;
418
            case _SF_STATUS_OPENED:
419
                $this->answer = $answerHandler->create();
420
                break;
421
        }
422
423
        if ($this->answer) {
424
            $this->answer->setVar('dohtml', $this->getVar('html'));
425
            $this->answer->setVar('doxcode', $this->getVar('xcodes'));
426
            $this->answer->setVar('dosmiley', $this->getVar('smiley'));
427
            $this->answer->setVar('doimage', $this->getVar('image'));
428
            $this->answer->setVar('dobr', $this->getVar('linebreak'));
429
        }
430
431
        return $this->answer;
432
    }
433
434
    /**
435
     * @return array
436
     */
437
    public function getAllAnswers()
438
    {
439
        $answerHandler = new sfAnswerHandler($this->db);
440
441
        return $answerHandler->getAllAnswers($this->faqid());
442
    }
443
444
    /**
445
     * @return bool
446
     */
447
    public function updateCounter()
448
    {
449
        $faqHandler = new sfFaqHandler($this->db);
450
451
        return $faqHandler->updateCounter($this->faqid());
452
    }
453
454
    /**
455
     * @param  bool $force
456
     * @return bool
457
     */
458
    public function store($force = true)
459
    {
460
        $faqHandler = new sfFaqHandler($this->db);
461
462
        return $faqHandler->insert($this, $force);
463
    }
464
465
    /**
466
     * @return mixed
467
     */
468
    public function getCategoryName()
469
    {
470
        if (!isset($this->category)) {
471
            $this->category = new sfCategory($this->getVar('categoryid'));
472
        }
473
474
        return $this->category->name();
475
    }
476
477
    /**
478
     * @param array $notifications
479
     */
480
    public function sendNotifications($notifications = array())
481
    {
482
        $smartModule = sf_getModuleInfo();
483
484
        $myts                = MyTextSanitizer:: getInstance();
0 ignored issues
show
Coding Style introduced by
Expected 0 spaces after double colon; 1 found

This check looks for references to static members where there are spaces between the name of the type and the actual member.

An example:

Certificate:: TRIPLEDES_CBC

will actually work, but is not very readable.

Loading history...
485
        $notificationHandler = xoops_getHandler('notification');
486
        //$categoryObj = $this->category();
0 ignored issues
show
Unused Code Comprehensibility introduced by
60% 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...
487
488
        $tags                  = array();
489
        $tags['MODULE_NAME']   = $myts->displayTarea($smartModule->getVar('name'));
490
        $tags['FAQ_NAME']      = $this->question();
491
        $tags['CATEGORY_NAME'] = $this->getCategoryName();
492
        $tags['CATEGORY_URL']  = XOOPS_URL . '/modules/' . $smartModule->getVar('dirname') . '/category.php?categoryid=' . $this->categoryid();
493
        $tags['FAQ_QUESTION']  = $this->question();
494
        $answerObj             = $this->answer();
495
        if (is_object($answerObj)) {
496
            // TODO : Not sure about the 'formpreview' ...
497
            $tags['FAQ_ANSWER'] = $answerObj->answer('formpreview');
498
        }
499
        $tags['DATESUB'] = $this->datesub();
500
501
        foreach ($notifications as $notification) {
502
            switch ($notification) {
503 View Code Duplication
                case _SF_NOT_FAQ_PUBLISHED:
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...
504
                    $tags['FAQ_URL'] = XOOPS_URL . '/modules/' . $smartModule->getVar('dirname') . '/faq.php?faqid=' . $this->faqid();
505
506
                    $notificationHandler->triggerEvent('global_faq', 0, 'published', $tags);
507
                    $notificationHandler->triggerEvent('category_faq', $this->categoryid(), 'published', $tags);
508
                    $notificationHandler->triggerEvent('faq', $this->faqid(), 'approved', $tags);
509
                    break;
510
511 View Code Duplication
                case _SF_NOT_FAQ_SUBMITTED:
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...
512
                    $tags['WAITINGFILES_URL'] = XOOPS_URL . '/modules/' . $smartModule->getVar('dirname') . '/admin/faq.php?faqid=' . $this->faqid();
513
                    $notificationHandler->triggerEvent('global_faq', 0, 'submitted', $tags);
514
                    $notificationHandler->triggerEvent('category_faq', $this->categoryid(), 'submitted', $tags);
515
                    break;
516
517 View Code Duplication
                case _SF_NOT_QUESTION_PUBLISHED:
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...
518
                    $tags['FAQ_URL'] = XOOPS_URL . '/modules/' . $smartModule->getVar('dirname') . '/answer.php?faqid=' . $this->faqid();
519
                    $notificationHandler->triggerEvent('global_question', 0, 'published', $tags);
520
                    $notificationHandler->triggerEvent('category_question', $this->categoryid(), 'published', $tags);
521
                    $notificationHandler->triggerEvent('question', $this->faqid(), 'approved', $tags);
522
                    break;
523
524 View Code Duplication
                case _SF_NOT_QUESTION_SUBMITTED:
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...
525
                    $tags['WAITINGFILES_URL'] = XOOPS_URL . '/modules/' . $smartModule->getVar('dirname') . '/admin/question.php?op=mod&faqid=' . $this->faqid();
526
                    $notificationHandler->triggerEvent('global_question', 0, 'submitted', $tags);
527
                    $notificationHandler->triggerEvent('category_question', $this->categoryid(), 'submitted', $tags);
528
                    break;
529
530
                case _SF_NOT_FAQ_REJECTED:
531
                    $notificationHandler->triggerEvent('faq', $this->faqid(), 'rejected', $tags);
532
                    break;
533
534 View Code Duplication
                case _SF_NOT_NEW_ANSWER_PROPOSED:
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...
535
                    $tags['WAITINGFILES_URL'] = XOOPS_URL . '/modules/' . $smartModule->getVar('dirname') . '/admin/answer.php?op=mod&faqid=' . $this->faqid();
536
                    $notificationHandler->triggerEvent('global_faq', 0, 'answer_proposed', $tags);
537
                    $notificationHandler->triggerEvent('category_faq', $this->categoryid(), 'answer_proposed', $tags);
538
                    break;
539
540
                case _SF_NOT_NEW_ANSWER_PUBLISHED:
541
                    $notificationHandler->triggerEvent('global_faq', 0, 'answer_published', $tags);
542
                    $notificationHandler->triggerEvent('category_faq', $this->categoryid(), 'answer_published', $tags);
543
                    break;
544
545
                // TODO : I commented out this one because I'm not sure. The $this->faqid() should probably be the
546
                // answerid not the faqid....
547
                /*
0 ignored issues
show
Unused Code Comprehensibility introduced by
66% 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...
548
                case _SF_NOT_ANSWER_APPROVED:
549
                $notificationHandler->triggerEvent('faq', $this->faqid(), 'answer_approved', $tags);
550
                break;
551
                */
552
553
                // TODO : I commented out this one because I'm not sure. The $this->faqid() should probably be the
554
                // answerid not the faqid....
555
                /*
0 ignored issues
show
Unused Code Comprehensibility introduced by
66% 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...
556
                case _SF_NOT_ANSWER_REJECTED:
557
                $notificationHandler->triggerEvent('faq', $this->faqid(), 'answer_approved', $tags);
558
                break;
559
                */
560
561
                case -1:
562
                default:
563
                    break;
564
            }
565
        }
566
    }
567
568 View Code Duplication
    public function setDefaultPermissions()
0 ignored issues
show
Duplication introduced by
This method 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...
569
    {
570
        $memberHandler = xoops_getHandler('member');
571
        $groups        = $memberHandler->getGroupList();
572
573
        $j         = 0;
574
        $group_ids = array();
575
        foreach (array_keys($groups) as $i) {
576
            $group_ids[$j] = $i;
577
            ++$j;
578
        }
579
        $this->groups_read = $group_ids;
580
    }
581
582
    /**
583
     * @param $group_ids
584
     */
585 View Code Duplication
    public function setPermissions($group_ids)
0 ignored issues
show
Duplication introduced by
This method 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...
586
    {
587
        if (!isset($group_ids)) {
588
            $memberHandler = xoops_getHandler('member');
589
            $groups        = $memberHandler->getGroupList();
590
591
            $j         = 0;
592
            $group_ids = array();
593
            foreach (array_keys($groups) as $i) {
594
                $group_ids[$j] = $i;
595
                ++$j;
596
            }
597
        }
598
    }
599
600
    /**
601
     * @return bool
602
     */
603
    public function notLoaded()
604
    {
605
        return ($this->getVar('faqid') == -1);
606
    }
607
608
    /**
609
     * @param  null  $answerObj
610
     * @param  array $users
611
     * @return string
612
     */
613
    public function getWhoAndWhen($answerObj = null, $users = array())
614
    {
615
        $smartModuleConfig = sf_getModuleConfig();
616
617
        $requester   = sf_getLinkedUnameFromId($this->uid(), $smartModuleConfig['userealname'], $users);
618
        $requestdate = $this->datesub();
619
620
        if (($this->status() == _SF_STATUS_PUBLISHED) || $this->status() == _SF_STATUS_NEW_ANSWER) {
621
            if ($answerObj == null) {
622
                $answerObj = $this->answer();
623
            }
624
            $submitdate = $answerObj->datesub();
625
            if ($this->uid() == $answerObj->uid()) {
626
                $result = sprintf(_MD_SF_REQUESTEDANDANSWERED, $requester, $submitdate);
627
            } else {
628
                $submitter = sf_getLinkedUnameFromId($answerObj->uid(), $smartModuleConfig['userealname'], $users);
629
                $result    = sprintf(_MD_SF_REQUESTEDBYANDANSWEREDBY, $requester, $submitter, $submitdate);
630
            }
631
        } else {
632
            $result = sprintf(_MD_SF_REQUESTEDBY, $requester, $requestdate);
633
        }
634
635
        return $result;
636
    }
637
638
    /**
639
     * @return string
640
     */
641
    public function getComeFrom()
642
    {
643
        global $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...
644
        $text = _MD_SF_QUESTIONCOMEFROM;
645
        if (($this->status() == _SF_STATUS_PUBLISHED) || $this->status() == _SF_STATUS_NEW_ANSWER) {
646
            $text = _MD_SF_FAQCOMEFROM;
647
        }
648
649
        return $text
650
               . $xoopsConfig['sitename']
651
               . ' : <a href='
652
               . XOOPS_URL
653
               . '/modules/smartfaq/faq.php?faqid='
654
               . $this->faqid()
655
               . '>'
656
               . XOOPS_URL
657
               . '/modules/smartfaq/faq.php?faqid='
658
               . $this->faqid()
659
               . '</a>';
660
    }
661
662
    /**
663
     * @param  array $faq
664
     * @param  null  $category
665
     * @param  bool  $linkInQuestion
666
     * @return array
667
     */
668
    public function toArray($faq = array(), $category = null, $linkInQuestion = true)
669
    {
670
        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...
671
        $lastfaqsize = (int)$xoopsModuleConfig['lastfaqsize'];
672
673
        $faq['id']         = $this->faqid();
674
        $faq['categoryid'] = $this->categoryid();
675
        $faq['question']   = $this->question();
676
        $page              = ($this->status() == _SF_STATUS_OPENED) ? 'answer.php' : 'faq.php';
677
678
        $faq['questionlink'] = "<a href='$page?faqid=" . $this->faqid() . "'>" . $this->question($lastfaqsize) . '</a>';
679
        if ($linkInQuestion) {
680
            $faq['fullquestionlink'] = "<a href='$page?faqid=" . $this->faqid() . "'>" . $this->question() . '</a>';
681
        } else {
682
            $faq['fullquestionlink'] = $this->question();
683
        }
684
        $faq['faqid']      = $this->faqid();
685
        $faq['counter']    = $this->counter();
686
        $faq['cancomment'] = $this->cancomment();
687
        $faq['comments']   = $this->comments();
688
        $faq['datesub']    = $this->datesub();
689
        if (isset($category)) {
690
            if (is_object($category) && strtolower(get_class($category)) === 'sfcategory') {
691
                $categoryObj = $category;
692
            } elseif (is_array($category)) {
693
                $categoryObj = $category[$this->categoryid()];
694
            }
695
            $faq['categoryname'] = $categoryObj->getVar('name');
0 ignored issues
show
Bug introduced by
The variable $categoryObj 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...
696
            $faq['categorylink'] = "<a href='" . XOOPS_URL . '/modules/smartfaq/category.php?categoryid=' . $this->categoryid() . "'>" . $categoryObj->getVar('name') . '</a>';
697
        }
698
699
        return $faq;
700
    }
701
}
702
703
/**
704
 * Q&A handler class.
705
 * This class is responsible for providing data access mechanisms to the data source
706
 * of Q&A class objects.
707
 *
708
 * @author  marcan <[email protected]>
709
 * @package SmartFAQ
710
 */
711
class sfFaqHandler extends XoopsObjectHandler
0 ignored issues
show
Coding Style Compatibility introduced by
PSR1 recommends that each class should be in its own file to aid autoloaders.

Having each class in a dedicated file usually plays nice with PSR autoloaders and is therefore a well established practice. If you use other autoloaders, you might not want to follow this rule.

Loading history...
Coding Style Compatibility introduced by
PSR1 recommends that each class must be in a namespace of at least one level to avoid collisions.

You can fix this by adding a namespace to your class:

namespace YourVendor;

class YourClass { }

When choosing a vendor namespace, try to pick something that is not too generic to avoid conflicts with other libraries.

Loading history...
712
{
713
    /**
714
     * @param  bool $isNew
715
     * @return sfFaq
716
     */
717
    public function & create($isNew = true)
718
    {
719
        $faq = new sfFaq();
720
        if ($isNew) {
721
            $faq->setDefaultPermissions();
722
            $faq->setNew();
723
        }
724
725
        return $faq;
726
    }
727
728
    /**
729
     * retrieve an FAQ
730
     *
731
     * @param  int $id faqid of the user
732
     * @return mixed reference to the {@link sfFaq} object, FALSE if failed
733
     */
734 View Code Duplication
    public function & get($id)
0 ignored issues
show
Duplication introduced by
This method 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...
735
    {
736
        if ((int)$id > 0) {
737
            $sql = 'SELECT * FROM ' . $this->db->prefix('smartfaq_faq') . ' WHERE faqid=' . $id;
738
            if (!$result = $this->db->query($sql)) {
739
                return false;
740
            }
741
742
            $numrows = $this->db->getRowsNum($result);
743
            if ($numrows == 1) {
744
                $faq = new sfFaq();
745
                $faq->assignVars($this->db->fetchArray($result));
746
747
                return $faq;
748
            }
749
        }
750
751
        return false;
752
    }
753
754
    /**
755
     * insert a new faq in the database
756
     *
757
     * @param  XoopsObject $faq reference to the {@link sfFaq} object
758
     * @param  bool        $force
759
     * @return bool        FALSE if failed, TRUE if already present and unchanged or successful
760
     */
761
    public function insert(XoopsObject $faq, $force = false)
762
    {
763
        if (strtolower(get_class($faq)) !== 'sffaq') {
764
            return false;
765
        }
766
767
        if (!$faq->isDirty()) {
768
            return true;
769
        }
770
771
        if (!$faq->cleanVars()) {
772
            return false;
773
        }
774
775
        foreach ($faq->cleanVars as $k => $v) {
776
            ${$k} = $v;
777
        }
778
779
        if ($faq->isNew()) {
780
            $sql = sprintf('INSERT INTO %s (faqid, categoryid, question, howdoi, diduno, uid, datesub, `status`, counter, weight, html, smiley, xcodes, cancomment, comments, notifypub, modulelink, contextpage, exacturl, partialview) VALUES (NULL, %u, %s, %s, %s, %u, %u, %u, %u, %u, %u, %u, %u, %u, %u, %u, %s, %s, %u, %u)',
781
                           $this->db->prefix('smartfaq_faq'), $categoryid, $this->db->quoteString($question), $this->db->quoteString($howdoi), $this->db->quoteString($diduno), $uid, time(), $status,
0 ignored issues
show
Bug introduced by
The variable $categoryid does not exist. Did you forget to declare it?

This check marks access to variables or properties that have not been declared yet. While PHP has no explicit notion of declaring a variable, accessing it before a value is assigned to it is most likely a bug.

Loading history...
Bug introduced by
The variable $question does not exist. Did you forget to declare it?

This check marks access to variables or properties that have not been declared yet. While PHP has no explicit notion of declaring a variable, accessing it before a value is assigned to it is most likely a bug.

Loading history...
Bug introduced by
The variable $howdoi does not exist. Did you forget to declare it?

This check marks access to variables or properties that have not been declared yet. While PHP has no explicit notion of declaring a variable, accessing it before a value is assigned to it is most likely a bug.

Loading history...
Bug introduced by
The variable $diduno does not exist. Did you forget to declare it?

This check marks access to variables or properties that have not been declared yet. While PHP has no explicit notion of declaring a variable, accessing it before a value is assigned to it is most likely a bug.

Loading history...
Bug introduced by
The variable $uid does not exist. Did you forget to declare it?

This check marks access to variables or properties that have not been declared yet. While PHP has no explicit notion of declaring a variable, accessing it before a value is assigned to it is most likely a bug.

Loading history...
Bug introduced by
The variable $status does not exist. Did you forget to declare it?

This check marks access to variables or properties that have not been declared yet. While PHP has no explicit notion of declaring a variable, accessing it before a value is assigned to it is most likely a bug.

Loading history...
782
                           $counter, $weight, $html, $smiley, $xcodes, $cancomment, $comments, $notifypub, $this->db->quoteString($modulelink), $this->db->quoteString($contextpage), $exacturl,
0 ignored issues
show
Bug introduced by
The variable $counter does not exist. Did you forget to declare it?

This check marks access to variables or properties that have not been declared yet. While PHP has no explicit notion of declaring a variable, accessing it before a value is assigned to it is most likely a bug.

Loading history...
Bug introduced by
The variable $weight does not exist. Did you forget to declare it?

This check marks access to variables or properties that have not been declared yet. While PHP has no explicit notion of declaring a variable, accessing it before a value is assigned to it is most likely a bug.

Loading history...
Bug introduced by
The variable $html does not exist. Did you forget to declare it?

This check marks access to variables or properties that have not been declared yet. While PHP has no explicit notion of declaring a variable, accessing it before a value is assigned to it is most likely a bug.

Loading history...
Bug introduced by
The variable $smiley does not exist. Did you forget to declare it?

This check marks access to variables or properties that have not been declared yet. While PHP has no explicit notion of declaring a variable, accessing it before a value is assigned to it is most likely a bug.

Loading history...
Bug introduced by
The variable $xcodes does not exist. Did you forget to declare it?

This check marks access to variables or properties that have not been declared yet. While PHP has no explicit notion of declaring a variable, accessing it before a value is assigned to it is most likely a bug.

Loading history...
Bug introduced by
The variable $cancomment does not exist. Did you forget to declare it?

This check marks access to variables or properties that have not been declared yet. While PHP has no explicit notion of declaring a variable, accessing it before a value is assigned to it is most likely a bug.

Loading history...
Bug introduced by
The variable $comments does not exist. Did you forget to declare it?

This check marks access to variables or properties that have not been declared yet. While PHP has no explicit notion of declaring a variable, accessing it before a value is assigned to it is most likely a bug.

Loading history...
Bug introduced by
The variable $notifypub does not exist. Did you forget to declare it?

This check marks access to variables or properties that have not been declared yet. While PHP has no explicit notion of declaring a variable, accessing it before a value is assigned to it is most likely a bug.

Loading history...
Bug introduced by
The variable $modulelink does not exist. Did you forget to declare it?

This check marks access to variables or properties that have not been declared yet. While PHP has no explicit notion of declaring a variable, accessing it before a value is assigned to it is most likely a bug.

Loading history...
Bug introduced by
The variable $contextpage does not exist. Did you forget to declare it?

This check marks access to variables or properties that have not been declared yet. While PHP has no explicit notion of declaring a variable, accessing it before a value is assigned to it is most likely a bug.

Loading history...
Bug introduced by
The variable $exacturl does not exist. Did you forget to declare it?

This check marks access to variables or properties that have not been declared yet. While PHP has no explicit notion of declaring a variable, accessing it before a value is assigned to it is most likely a bug.

Loading history...
783
                           $partialview);
0 ignored issues
show
Bug introduced by
The variable $partialview does not exist. Did you forget to declare it?

This check marks access to variables or properties that have not been declared yet. While PHP has no explicit notion of declaring a variable, accessing it before a value is assigned to it is most likely a bug.

Loading history...
784
        } else {
785
            $sql = sprintf('UPDATE %s SET categoryid = %u, question = %s, howdoi = %s, diduno = %s, uid = %u, datesub = %u, `status` = %u, counter = %u, weight = %u, html = %u, smiley = %u, xcodes = %u, cancomment = %u, comments = %u, notifypub = %u, modulelink = %s, contextpage = %s, exacturl = %u, partialview = %u  WHERE faqid = %u',
786
                           $this->db->prefix('smartfaq_faq'), $categoryid, $this->db->quoteString($question), $this->db->quoteString($howdoi), $this->db->quoteString($diduno), $uid, $datesub, $status,
0 ignored issues
show
Bug introduced by
The variable $datesub does not exist. Did you forget to declare it?

This check marks access to variables or properties that have not been declared yet. While PHP has no explicit notion of declaring a variable, accessing it before a value is assigned to it is most likely a bug.

Loading history...
787
                           $counter, $weight, $html, $smiley, $xcodes, $cancomment, $comments, $notifypub, $this->db->quoteString($modulelink), $this->db->quoteString($contextpage), $exacturl,
788
                           $partialview, $faqid);
0 ignored issues
show
Bug introduced by
The variable $faqid does not exist. Did you forget to declare it?

This check marks access to variables or properties that have not been declared yet. While PHP has no explicit notion of declaring a variable, accessing it before a value is assigned to it is most likely a bug.

Loading history...
789
        }
790 View Code Duplication
        if (false != $force) {
0 ignored issues
show
Coding Style Best Practice introduced by
It seems like you are loosely comparing two booleans. Considering using the strict comparison !== instead.

When comparing two booleans, it is generally considered safer to use the strict comparison operator.

Loading history...
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...
791
            $result = $this->db->queryF($sql);
792
        } else {
793
            $result = $this->db->query($sql);
794
        }
795
796
        if (!$result) {
797
            return false;
798
        }
799
        if ($faq->isNew()) {
800
            $faq->assignVar('faqid', $this->db->getInsertId());
801
        }
802
803
        // Saving permissions
804
        sf_saveItemPermissions($faq->getGroups_read(), $faq->faqid());
805
806
        return true;
807
    }
808
809
    /**
810
     * delete an FAQ from the database
811
     *
812
     * @param  XoopsObject $faq reference to the FAQ to delete
813
     * @param  bool        $force
814
     * @return bool        FALSE if failed.
815
     */
816
    public function delete(XoopsObject $faq, $force = false)
817
    {
818
        $smartModule = sf_getModuleInfo();
819
        $module_id   = $smartModule->getVar('mid');
820
821
        if (strtolower(get_class($faq)) !== 'sffaq') {
822
            return false;
823
        }
824
825
        // Deleting the answers
826
        $answerHandler = new sfAnswerHandler($this->db);
827
        if (!$answerHandler->deleteFaqAnswers($faq)) {
828
            // error msg...
829
            echo 'error while deleteing an answer';
830
        }
831
832
        $sql = sprintf('DELETE FROM %s WHERE faqid = %u', $this->db->prefix('smartfaq_faq'), $faq->getVar('faqid'));
833
834 View Code Duplication
        if (false != $force) {
0 ignored issues
show
Coding Style Best Practice introduced by
It seems like you are loosely comparing two booleans. Considering using the strict comparison !== instead.

When comparing two booleans, it is generally considered safer to use the strict comparison operator.

Loading history...
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...
835
            $result = $this->db->queryF($sql);
836
        } else {
837
            $result = $this->db->query($sql);
838
        }
839
        if (!$result) {
840
            return false;
841
        }
842
843
        xoops_groupperm_deletebymoditem($module_id, 'item_read', $faq->faqid());
844
845
        return true;
846
    }
847
848
    /**
849
     * retrieve FAQs from the database
850
     *
851
     * @param  object $criteria  {@link CriteriaElement} conditions to be met
0 ignored issues
show
Documentation introduced by
Should the type for parameter $criteria not be object|null?

This check looks for @param annotations where the type inferred by our type inference engine differs from the declared type.

It makes a suggestion as to what type it considers more descriptive.

Most often this is a case of a parameter that can be null in addition to its declared types.

Loading history...
852
     * @param  bool   $id_as_key use the faqid as key for the array?
853
     * @param  string $notNullFields
854
     * @return false|array  array of <a href='psi_element://sfFaq'>sfFaq</a> objects
855
     */
856
    public function &getObjects($criteria = null, $id_as_key = false, $notNullFields = '')
857
    {
858
        $ret   = array();
859
        $limit = $start = 0;
860
        $sql   = 'SELECT * FROM ' . $this->db->prefix('smartfaq_faq');
861
862 View Code Duplication
        if (isset($criteria) && is_subclass_of($criteria, 'criteriaelement')) {
0 ignored issues
show
Bug introduced by
Due to PHP Bug #53727, is_subclass_of returns inconsistent results on some PHP versions for interfaces; you could instead use ReflectionClass::implementsInterface.
Loading history...
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...
863
            $whereClause = $criteria->renderWhere();
864
865
            if ($whereClause !== 'WHERE ()') {
866
                $sql .= ' ' . $criteria->renderWhere();
867
                if (!empty($notNullFields)) {
868
                    $sql .= $this->NotNullFieldClause($notNullFields, true);
869
                }
870
            } elseif (!empty($notNullFields)) {
871
                $sql .= ' WHERE ' . $this->NotNullFieldClause($notNullFields);
872
            }
873
            if ($criteria->getSort() != '') {
874
                $sql .= ' ORDER BY ' . $criteria->getSort() . ' ' . $criteria->getOrder();
875
            }
876
            $limit = $criteria->getLimit();
877
            $start = $criteria->getStart();
878
        } elseif (!empty($notNullFields)) {
879
            $sql .= $sql .= ' WHERE ' . $this->NotNullFieldClause($notNullFields);
880
        }
881
882
        //echo "<br>" . $sql . "<br>";
0 ignored issues
show
Unused Code Comprehensibility introduced by
42% 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...
883
        $result = $this->db->query($sql, $limit, $start);
884
        if (!$result) {
885
            return false;
886
        }
887
888
        if (count($result) == 0) {
889
            return false;
890
        }
891
892 View Code Duplication
        while ($myrow = $this->db->fetchArray($result)) {
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...
893
            $faq = new sfFaq();
894
            $faq->assignVars($myrow);
895
896
            if (!$id_as_key) {
897
                $ret[] = &$faq;
898
            } else {
899
                $ret[$myrow['faqid']] = &$faq;
900
            }
901
            unset($faq);
902
        }
903
904
        return $ret;
905
    }
906
907
    /**
908
     * @param  null   $criteria
909
     * @param  bool   $id_as_key
910
     * @param  string $notNullFields
911
     * @return array|bool
912
     */
913
    public function &getObjectsAdminSide($criteria = null, $id_as_key = false, $notNullFields = '')
914
    {
915
        $ret   = array();
916
        $limit = $start = 0;
917
        $sql   = 'SELECT
918
                            faq.faqid AS faqid,
919
                            faq.categoryid AS categoryid,
920
                            faq.question AS question,
921
                            faq.howdoi AS howdoi,
922
                            faq.diduno AS diduno,
923
                            faq.uid AS uid,
924
                            faq.datesub AS datesub,
925
                            faq.status AS status,
926
                            faq.counter AS counter,
927
                            faq.weight AS weight,
928
                            faq.html AS html,
929
                            faq.smiley AS smiley,
930
                            faq.image AS image,
931
                            faq.linebreak AS linebreak,
932
                            faq.xcodes AS xcodes,
933
                            faq.cancomment AS cancomment,
934
                            faq.comments AS comments,
935
                            faq.notifypub AS notifypub,
936
                            faq.modulelink AS modulelink,
937
                            faq.contextpage AS contextpage,
938
                            faq.exacturl AS exacturl
939
                FROM ' . $this->db->prefix('smartfaq_faq') . ' AS faq INNER JOIN ' . $this->db->prefix('smartfaq_categories') . ' AS category ON faq.categoryid = category.categoryid ';
940
941 View Code Duplication
        if (isset($criteria) && is_subclass_of($criteria, 'criteriaelement')) {
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...
Bug introduced by
Due to PHP Bug #53727, is_subclass_of returns inconsistent results on some PHP versions for interfaces; you could instead use ReflectionClass::implementsInterface.
Loading history...
942
            $whereClause = $criteria->renderWhere();
943
944
            if ($whereClause !== 'WHERE ()') {
945
                $sql .= ' ' . $criteria->renderWhere();
946
                if (!empty($notNullFields)) {
947
                    $sql .= $this->NotNullFieldClause($notNullFields, true);
948
                }
949
            } elseif (!empty($notNullFields)) {
950
                $sql .= ' WHERE ' . $this->NotNullFieldClause($notNullFields);
951
            }
952
            if ($criteria->getSort() != '') {
953
                $sql .= ' ORDER BY ' . $criteria->getSort() . ' ' . $criteria->getOrder();
954
            }
955
            $limit = $criteria->getLimit();
956
            $start = $criteria->getStart();
957
        } elseif (!empty($notNullFields)) {
958
            $sql .= $sql .= ' WHERE ' . $this->NotNullFieldClause($notNullFields);
959
        }
960
961
        //echo "<br>" . $sql . "<br>";
0 ignored issues
show
Unused Code Comprehensibility introduced by
42% 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...
962
        $result = $this->db->query($sql, $limit, $start);
963
        if (!$result) {
964
            return false;
965
        }
966
967
        if (count($result) == 0) {
968
            return false;
969
        }
970
971 View Code Duplication
        while ($myrow = $this->db->fetchArray($result)) {
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...
972
            $faq = new sfFaq();
973
            $faq->assignVars($myrow);
974
975
            if (!$id_as_key) {
976
                $ret[] = &$faq;
977
            } else {
978
                $ret[$myrow['faqid']] = &$faq;
979
            }
980
            unset($faq);
981
        }
982
983
        return $ret;
984
985
        /*while ($myrow = $this->db->fetchArray($result)) {
0 ignored issues
show
Unused Code Comprehensibility introduced by
62% 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...
986
            $faq = new sfFaq($myrow['faqid']);
987
988
            if (!$id_as_key) {
989
                $ret[] =& $faq;
990
            } else {
991
                $ret[$myrow['faqid']] =& $faq;
992
            }
993
            unset($faq);
994
        }
995
996
        return $ret;*/
997
    }
998
999
    /**
1000
     * count FAQs matching a condition
1001
     *
1002
     * @param  object $criteria {@link CriteriaElement} to match
0 ignored issues
show
Documentation introduced by
Should the type for parameter $criteria not be object|null?

This check looks for @param annotations where the type inferred by our type inference engine differs from the declared type.

It makes a suggestion as to what type it considers more descriptive.

Most often this is a case of a parameter that can be null in addition to its declared types.

Loading history...
1003
     * @param  string $notNullFields
1004
     * @return int    count of FAQs
1005
     */
1006
    public function getCount($criteria = null, $notNullFields = '')
1007
    {
1008
        $sql = 'SELECT COUNT(*) FROM ' . $this->db->prefix('smartfaq_faq');
1009
        if (isset($criteria) && is_subclass_of($criteria, 'criteriaelement')) {
0 ignored issues
show
Bug introduced by
Due to PHP Bug #53727, is_subclass_of returns inconsistent results on some PHP versions for interfaces; you could instead use ReflectionClass::implementsInterface.
Loading history...
1010
            $whereClause = $criteria->renderWhere();
1011
            if ($whereClause !== 'WHERE ()') {
1012
                $sql .= ' ' . $criteria->renderWhere();
1013
                if (!empty($notNullFields)) {
1014
                    $sql .= $this->NotNullFieldClause($notNullFields, true);
1015
                }
1016
            } elseif (!empty($notNullFields)) {
1017
                $sql .= ' WHERE ' . $this->NotNullFieldClause($notNullFields);
1018
            }
1019
        } elseif (!empty($notNullFields)) {
1020
            $sql .= ' WHERE ' . $this->NotNullFieldClause($notNullFields);
1021
        }
1022
1023
        //echo "<br>" . $sql . "<br>";
0 ignored issues
show
Unused Code Comprehensibility introduced by
42% 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...
1024
        $result = $this->db->query($sql);
1025
        if (!$result) {
1026
            return 0;
1027
        }
1028
        list($count) = $this->db->fetchRow($result);
1029
1030
        return $count;
1031
    }
1032
1033
    /**
1034
     * @param  int    $categoryid
1035
     * @param  string $status
1036
     * @param  string $notNullFields
1037
     * @return int
1038
     */
1039
    public function getFaqsCount($categoryid = -1, $status = '', $notNullFields = '')
1040
    {
1041
        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...
1042
1043
        //  if ( ($categoryid = -1) && (empty($status) || ($status == -1)) ) {
0 ignored issues
show
Unused Code Comprehensibility introduced by
55% 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...
1044
        //return $this->getCount();
0 ignored issues
show
Unused Code Comprehensibility introduced by
75% 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...
1045
        //}
1046
1047
        $userIsAdmin = sf_userIsAdmin();
1048
        // Categories for which user has access
1049 View Code Duplication
        if (!$userIsAdmin) {
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...
1050
            $smartPermHandler = xoops_getModuleHandler('permission', 'smartfaq');
1051
1052
            $categoriesGranted = $smartPermHandler->getPermissions('category');
1053
            $grantedCategories = new Criteria('categoryid', '(' . implode(',', $categoriesGranted) . ')', 'IN');
1054
1055
            $faqsGranted = $smartPermHandler->getPermissions('item');
1056
            $grantedFaq  = new CriteriaCompo();
1057
            $grantedFaq->add(new Criteria('faqid', '(' . implode(',', $faqsGranted) . ')', 'IN'), 'OR');
1058
            // If user is anonymous, check if the FAQ allow partialview
1059
            if (!is_object($xoopsUser)) {
1060
                $grantedFaq->add(new Criteria('partialview', '1'), 'OR');
1061
            }
1062
        }
1063
1064
        if (isset($categoryid) && ($categoryid != -1)) {
1065
            $criteriaCategory = new criteria('categoryid', $categoryid);
1066
        }
1067
1068
        $criteriaStatus = new CriteriaCompo();
1069
        if (!empty($status) && is_array($status)) {
1070
            foreach ($status as $v) {
1071
                $criteriaStatus->add(new Criteria('status', $v), 'OR');
1072
            }
1073
        } elseif (!empty($status) && ($status != -1)) {
1074
            $criteriaStatus->add(new Criteria('status', $status), 'OR');
1075
        }
1076
1077
        $criteriaPermissions = new CriteriaCompo();
1078
        if (!$userIsAdmin) {
1079
            $criteriaPermissions->add($grantedCategories, 'AND');
0 ignored issues
show
Bug introduced by
The variable $grantedCategories 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...
1080
            $criteriaPermissions->add($grantedFaq, 'AND');
0 ignored issues
show
Bug introduced by
The variable $grantedFaq 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...
1081
        }
1082
1083
        $criteria = new CriteriaCompo();
1084
        if (!empty($criteriaCategory)) {
1085
            $criteria->add($criteriaCategory);
1086
        }
1087
1088
        if (!empty($criteriaPermissions) && (!$userIsAdmin)) {
1089
            $criteria->add($criteriaPermissions);
1090
        }
1091
1092
        if (!empty($criteriaStatus)) {
1093
            $criteria->add($criteriaStatus);
1094
        }
1095
1096
        return $this->getCount($criteria, $notNullFields);
1097
    }
1098
1099
    /**
1100
     * @return array
1101
     */
1102
    public function getFaqsCountByStatus()
1103
    {
1104
        $sql    = 'SELECT status, COUNT(*) FROM ' . $this->db->prefix('smartfaq_faq') . ' GROUP BY status';
1105
        $result = $this->db->query($sql);
1106
        if (!$result) {
1107
            return array();
1108
        }
1109
        $ret = array();
1110
        while (list($status, $count) = $this->db->fetchRow($result)) {
1111
            $ret[$status] = $count;
1112
        }
1113
1114
        return $ret;
1115
    }
1116
1117
    /**
1118
     * @param  int    $limit
1119
     * @param  int    $start
1120
     * @param  int    $categoryid
1121
     * @param  string $sort
1122
     * @param  string $order
1123
     * @param  bool   $asobject
1124
     * @return array
0 ignored issues
show
Documentation introduced by
Should the return type not be false|array?

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...
1125
     */
1126
    public function getAllPublished(
1127
        $limit = 0,
1128
        $start = 0,
1129
        $categoryid = -1,
1130
        $sort = 'datesub',
1131
        $order = 'DESC',
1132
        $asobject = true
1133
    ) {
1134
        return $this->getFaqs($limit, $start, array(_SF_STATUS_PUBLISHED, _SF_STATUS_NEW_ANSWER), $categoryid, $sort, $order, null, $asobject, null);
1135
    }
1136
1137
    /**
1138
     * @param  int    $limit
1139
     * @param  int    $start
1140
     * @param  string $status
1141
     * @param  int    $categoryid
1142
     * @param  string $sort
1143
     * @param  string $order
1144
     * @param  string $notNullFields
1145
     * @param  bool   $asobject
1146
     * @param  null   $otherCriteria
1147
     * @return array
0 ignored issues
show
Documentation introduced by
Should the return type not be false|array?

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...
1148
     */
1149
    public function getFaqs(
1150
        $limit = 0,
1151
        $start = 0,
1152
        $status = '',
1153
        $categoryid = -1,
1154
        $sort = 'datesub',
1155
        $order = 'DESC',
1156
        $notNullFields = '',
1157
        $asobject = true,
1158
        $otherCriteria = null
1159
    ) {
1160
        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...
1161
        include_once XOOPS_ROOT_PATH . '/modules/smartfaq/include/functions.php';
1162
1163
        //if ( ($categoryid == -1) && (empty($status) || ($status == -1)) && ($limit == 0) && ($start ==0) ) {
0 ignored issues
show
Unused Code Comprehensibility introduced by
55% 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...
1164
        //  return $this->getObjects();
0 ignored issues
show
Unused Code Comprehensibility introduced by
67% 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...
1165
        //}
1166
        $ret         = array();
1167
        $userIsAdmin = sf_userIsAdmin();
1168
        // Categories for which user has access
1169 View Code Duplication
        if (!$userIsAdmin) {
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...
1170
            $smartPermHandler = xoops_getModuleHandler('permission', 'smartfaq');
1171
1172
            $categoriesGranted = $smartPermHandler->getPermissions('category');
1173
            $grantedCategories = new Criteria('categoryid', '(' . implode(',', $categoriesGranted) . ')', 'IN');
1174
1175
            $faqsGranted = $smartPermHandler->getPermissions('item');
1176
            $grantedFaq  = new CriteriaCompo();
1177
            $grantedFaq->add(new Criteria('faqid', '(' . implode(',', $faqsGranted) . ')', 'IN'), 'OR');
1178
            // If user is anonymous, check if the FAQ allow partialview
1179
            if (!is_object($xoopsUser)) {
1180
                $grantedFaq->add(new Criteria('partialview', '1'), 'OR');
1181
            }
1182
        }
1183
1184
        if (isset($categoryid) && ($categoryid != -1)) {
1185
            if (is_array($categoryid)) {
1186
                $criteriaCategory = new Criteria('categoryid', '(' . implode(',', $categoryid) . ')', 'IN');
1187
            } else {
1188
                $criteriaCategory = new Criteria('categoryid', (int)$categoryid);
1189
            }
1190
        }
1191
1192 View Code Duplication
        if (!empty($status) && is_array($status)) {
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...
1193
            $criteriaStatus = new CriteriaCompo();
1194
            foreach ($status as $v) {
1195
                $criteriaStatus->add(new Criteria('status', $v), 'OR');
1196
            }
1197
        } elseif (!empty($status) && ($status != -1)) {
1198
            $criteriaStatus = new CriteriaCompo();
1199
            $criteriaStatus->add(new Criteria('status', $status), 'OR');
1200
        }
1201
1202
        $criteriaPermissions = new CriteriaCompo();
1203
        if (!$userIsAdmin) {
1204
            $criteriaPermissions->add($grantedCategories, 'AND');
0 ignored issues
show
Bug introduced by
The variable $grantedCategories 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...
1205
            $criteriaPermissions->add($grantedFaq, 'AND');
0 ignored issues
show
Bug introduced by
The variable $grantedFaq 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...
1206
        }
1207
1208
        $criteria = new CriteriaCompo();
1209
        if (!empty($criteriaCategory)) {
1210
            $criteria->add($criteriaCategory);
1211
        }
1212
1213
        if (!empty($criteriaPermissions) && (!$userIsAdmin)) {
1214
            $criteria->add($criteriaPermissions);
1215
        }
1216
1217
        if (!empty($criteriaStatus)) {
1218
            $criteria->add($criteriaStatus);
1219
        }
1220
1221
        if (!empty($otherCriteria)) {
1222
            $criteria->add($otherCriteria);
1223
        }
1224
1225
        $criteria->setLimit($limit);
1226
        $criteria->setStart($start);
1227
        $criteria->setSort($sort);
1228
        $criteria->setOrder($order);
1229
        $ret = &$this->getObjects($criteria, false, $notNullFields);
1230
1231
        return $ret;
1232
    }
1233
1234
    /**
1235
     * @param  int    $limit
1236
     * @param  int    $start
1237
     * @param  string $status
1238
     * @param  int    $categoryid
1239
     * @param  string $sort
1240
     * @param  string $order
1241
     * @param  bool   $asobject
1242
     * @param  null   $otherCriteria
1243
     * @return array|bool
1244
     */
1245
    public function getFaqsAdminSide(
1246
        $limit = 0,
1247
        $start = 0,
1248
        $status = '',
1249
        $categoryid = -1,
1250
        $sort = 'datesub',
1251
        $order = 'DESC',
1252
        $asobject = true,
1253
        $otherCriteria = null
1254
    ) {
1255
        include_once XOOPS_ROOT_PATH . '/modules/smartfaq/include/functions.php';
1256
1257
        $smartModule = sf_getModuleInfo();
0 ignored issues
show
Unused Code introduced by
$smartModule 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...
1258
1259
        $ret = array();
1260
1261
        if (isset($categoryid) && ($categoryid != -1)) {
1262
            $criteriaCategory = new criteria('faq.categoryid', $categoryid);
1263
        }
1264
1265 View Code Duplication
        if (!empty($status) && is_array($status)) {
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...
1266
            $criteriaStatus = new CriteriaCompo();
1267
            foreach ($status as $v) {
1268
                $criteriaStatus->add(new Criteria('faq.status', $v), 'OR');
1269
            }
1270
        } elseif (!empty($status) && ($status != -1)) {
1271
            $criteriaStatus = new CriteriaCompo();
1272
            $criteriaStatus->add(new Criteria('faq.status', $status), 'OR');
1273
        }
1274
1275
        $criteria = new CriteriaCompo();
1276
        if (!empty($criteriaCategory)) {
1277
            $criteria->add($criteriaCategory);
1278
        }
1279
1280
        if (!empty($criteriaStatus)) {
1281
            $criteria->add($criteriaStatus);
1282
        }
1283
1284
        if (!empty($otherCriteria)) {
1285
            $criteria->add($otherCriteria);
1286
        }
1287
1288
        $criteria->setLimit($limit);
1289
        $criteria->setStart($start);
1290
        $criteria->setSort($sort);
1291
        $criteria->setOrder($order);
1292
        $ret = &$this->getObjectsAdminSide($criteria, false);
1293
1294
        return $ret;
1295
    }
1296
1297
    /**
1298
     * @param  string $field
1299
     * @param  string $status
1300
     * @param  int    $category
1301
     * @return bool|mixed
1302
     */
1303
    public function getRandomFaq($field = '', $status = '', $category = -1)
1304
    {
1305
        $ret = false;
1306
1307
        $notNullFields = $field;
1308
1309
        // Getting the number of published FAQ
1310
        $totalFaqs = $this->getFaqsCount(-1, $status, $notNullFields);
1311
1312
        if ($totalFaqs > 0) {
1313
            --$totalFaqs;
1314
            mt_srand((double)microtime() * 1000000);
1315
            $entrynumber = mt_rand(0, $totalFaqs);
1316
            $faq         = $this->getFaqs(1, $entrynumber, $status, -1, 'datesub', 'DESC', $notNullFields);
1317
            if ($faq) {
1318
                $ret = &$faq[0];
1319
            }
1320
        }
1321
1322
        return $ret;
1323
    }
1324
1325
    /**
1326
     * @param  int $limit
1327
     * @return array|bool
1328
     */
1329
    public function getContextualFaqs($limit = 0)
0 ignored issues
show
Coding Style introduced by
getContextualFaqs uses the super-global variable $_SERVER 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...
1330
    {
1331
        $ret = false;
1332
1333
        $otherCriteria = new CriteriaCompo();
1334
        $otherCriteria->add(new Criteria('modulelink', 'None', '<>'));
1335
1336
        $faqsObj = $this->getFaqs(0, 0, array(_SF_STATUS_PUBLISHED, _SF_STATUS_NEW_ANSWER), -1, 'datesub', 'DESC', '', true, $otherCriteria);
1337
1338
        $totalfaqs  = count($faqsObj);
1339
        $randomFaqs = array();
1340
        if ($faqsObj) {
1341
            for ($i = 0; $i < $totalfaqs; ++$i) {
1342
                $display = false;
0 ignored issues
show
Unused Code introduced by
$display 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...
1343
1344
                $http        = (strpos(XOOPS_URL, 'https://') === false) ? 'http://' : 'https://';
1345
                $phpself     = $_SERVER['PHP_SELF'];
1346
                $httphost    = $_SERVER['HTTP_HOST'];
1347
                $querystring = $_SERVER['QUERY_STRING'];
1348
                if ($querystring != '') {
1349
                    $querystring = '?' . $querystring;
1350
                }
1351
                $currenturl     = $http . $httphost . $phpself . $querystring;
1352
                $fullcontexturl = XOOPS_URL . '/' . $faqsObj[$i]->contextpage();
1353
                switch ($faqsObj[$i]->modulelink()) {
1354
                    case '':
1355
                        $display = false;
1356
                        break;
1357
                    case 'None':
1358
                        $display = false;
1359
                        break;
1360
                    case 'All':
1361
                        $display = true;
1362
                        break;
1363
                    case 'url':
1364
                        if ($faqsObj[$i]->exacturl()) {
1365
                            $display = ($currenturl == $fullcontexturl);
1366
                        } else {
1367
                            $display = (strpos($currenturl, $fullcontexturl) === false);
1368
                        }
1369
                        break;
1370
                    default:
1371
                        if (strpos($currenturl, XOOPS_URL . '/modules/') === false) {
1372
                            $display = false;
1373
                        } else {
1374
                            if (strpos($currenturl, $faqsObj[$i]->modulelink()) === false) {
1375
                                $display = false;
1376
                            } else {
1377
                                $display = true;
1378
                            }
1379
                        }
1380
                        break;
1381
                }
1382
                if ($display) {
1383
                    $randomFaqs[] = &$faqsObj[$i];
1384
                }
1385
            }
1386
        }
1387
1388
        if (count($randomFaqs) > $limit) {
1389
            mt_srand((float)microtime() * 10000000);
1390
            $rand_keys = array_rand($randomFaqs, $limit);
1391
            for ($j = 0, $jMax = count($rand_keys); $j < $jMax; ++$j) {
1392
                $ret[] = &$randomFaqs[$rand_keys[$j]];
1393
            }
1394
        } else {
1395
            $ret = &$randomFaqs;
1396
        }
1397
1398
        return $ret;
1399
    }
1400
1401
    /**
1402
     * @param  array $status
1403
     * @return array
1404
     */
1405
    public function getLastPublishedByCat($status = array(_SF_STATUS_PUBLISHED, _SF_STATUS_NEW_ANSWER))
1406
    {
1407
        $ret       = array();
1408
        $faqclause = '';
1409
        if (!sf_userIsAdmin()) {
1410
            $smartPermHandler = xoops_getModuleHandler('permission', 'smartfaq');
1411
            $items            = $smartPermHandler->getPermissions('item');
1412
            $faqclause        = ' AND faqid IN (' . implode(',', $items) . ')';
1413
        }
1414
1415
        $sql  = "CREATE TEMPORARY TABLE tmp (categoryid INT(8) UNSIGNED NOT NULL,datesub INT(11) DEFAULT '0' NOT NULL);";
1416
        $sql2 = ' LOCK TABLES ' . $this->db->prefix('smartfaq_faq') . ' READ;';
1417
        $sql3 = ' INSERT INTO tmp SELECT categoryid, MAX(datesub) FROM ' . $this->db->prefix('smartfaq_faq') . ' WHERE status IN (' . implode(',', $status) . ") $faqclause GROUP BY categoryid;";
1418
        $sql4 = ' SELECT ' . $this->db->prefix('smartfaq_faq') . '.categoryid, faqid, question, uid, ' . $this->db->prefix('smartfaq_faq') . '.datesub FROM ' . $this->db->prefix('smartfaq_faq') . ', tmp
1419
                              WHERE ' . $this->db->prefix('smartfaq_faq') . '.categoryid=tmp.categoryid AND ' . $this->db->prefix('smartfaq_faq') . '.datesub=tmp.datesub;';
1420
        /*
0 ignored issues
show
Unused Code Comprehensibility introduced by
48% 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...
1421
        //Old implementation
1422
        $sql = "SELECT categoryid, faqid, question, uid, MAX(datesub) AS datesub FROM ".$this->db->prefix("smartfaq_faq")."
1423
               WHERE status IN (". implode(',', $status).")";
1424
        $sql .= " GROUP BY categoryid";
1425
        */
1426
        $this->db->queryF($sql);
1427
        $this->db->queryF($sql2);
1428
        $this->db->queryF($sql3);
1429
        $result = $this->db->query($sql4);
1430
        $error  = $this->db->error();
1431
        $this->db->queryF('UNLOCK TABLES;');
1432
        $this->db->queryF('DROP TABLE tmp;');
1433
        if (!$result) {
1434
            trigger_error('Error in getLastPublishedByCat SQL: ' . $error);
1435
1436
            return $ret;
1437
        }
1438 View Code Duplication
        while ($row = $this->db->fetchArray($result)) {
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...
1439
            $faq = new sfFaq();
1440
            $faq->assignVars($row);
1441
            $ret[$row['categoryid']] = &$faq;
1442
            unset($faq);
1443
        }
1444
1445
        return $ret;
1446
    }
1447
1448
    /**
1449
     * delete FAQs matching a set of conditions
1450
     *
1451
     * @param  object $criteria {@link CriteriaElement}
0 ignored issues
show
Documentation introduced by
Should the type for parameter $criteria not be object|null?

This check looks for @param annotations where the type inferred by our type inference engine differs from the declared type.

It makes a suggestion as to what type it considers more descriptive.

Most often this is a case of a parameter that can be null in addition to its declared types.

Loading history...
1452
     * @return bool   FALSE if deletion failed
1453
     */
1454 View Code Duplication
    public function deleteAll($criteria = null)
0 ignored issues
show
Duplication introduced by
This method 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...
1455
    {
1456
        $sql = 'DELETE FROM ' . $this->db->prefix('smartfaq_faq');
1457
        if (isset($criteria) && is_subclass_of($criteria, 'criteriaelement')) {
0 ignored issues
show
Bug introduced by
Due to PHP Bug #53727, is_subclass_of returns inconsistent results on some PHP versions for interfaces; you could instead use ReflectionClass::implementsInterface.
Loading history...
1458
            $sql .= ' ' . $criteria->renderWhere();
1459
        }
1460
        if (!$this->db->query($sql)) {
1461
            return false;
1462
            // TODO : Also delete the permissions related to each FAQ
1463
        }
1464
1465
        return true;
1466
    }
1467
1468
    /**
1469
     * Change a value for FAQ with a certain criteria
1470
     *
1471
     * @param string $fieldname  Name of the field
1472
     * @param string $fieldvalue Value to write
1473
     * @param object $criteria   {@link CriteriaElement}
0 ignored issues
show
Documentation introduced by
Should the type for parameter $criteria not be object|null?

This check looks for @param annotations where the type inferred by our type inference engine differs from the declared type.

It makes a suggestion as to what type it considers more descriptive.

Most often this is a case of a parameter that can be null in addition to its declared types.

Loading history...
1474
     *
1475
     * @return bool
1476
     **/
1477 View Code Duplication
    public function updateAll($fieldname, $fieldvalue, $criteria = null)
0 ignored issues
show
Duplication introduced by
This method 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...
1478
    {
1479
        $set_clause = is_numeric($fieldvalue) ? $fieldname . ' = ' . $fieldvalue : $fieldname . ' = ' . $this->db->quoteString($fieldvalue);
1480
        $sql        = 'UPDATE ' . $this->db->prefix('smartfaq_faq') . ' SET ' . $set_clause;
1481
        if (isset($criteria) && is_subclass_of($criteria, 'criteriaelement')) {
0 ignored issues
show
Bug introduced by
Due to PHP Bug #53727, is_subclass_of returns inconsistent results on some PHP versions for interfaces; you could instead use ReflectionClass::implementsInterface.
Loading history...
1482
            $sql .= ' ' . $criteria->renderWhere();
1483
        }
1484
        if (!$this->db->queryF($sql)) {
1485
            return false;
1486
        }
1487
1488
        return true;
1489
    }
1490
1491
    /**
1492
     * @param $faqid
1493
     * @return bool
1494
     */
1495
    public function updateCounter($faqid)
1496
    {
1497
        $sql = 'UPDATE ' . $this->db->prefix('smartfaq_faq') . ' SET counter=counter+1 WHERE faqid = ' . $faqid;
1498
        if ($this->db->queryF($sql)) {
1499
            return true;
1500
        } else {
1501
            return false;
1502
        }
1503
    }
1504
1505
    /**
1506
     * @param  string $notNullFields
1507
     * @param  bool   $withAnd
1508
     * @return string
1509
     */
1510
    public function NotNullFieldClause($notNullFields = '', $withAnd = false)
1511
    {
1512
        $ret = '';
1513
        if ($withAnd) {
1514
            $ret .= ' AND ';
1515
        }
1516
        if (!empty($notNullFields) && is_array($notNullFields)) {
1517
            foreach ($notNullFields as $v) {
1518
                $ret .= " ($v IS NOT NULL AND $v <> ' ' )";
1519
            }
1520
        } elseif (!empty($notNullFields)) {
1521
            $ret .= " ($notNullFields IS NOT NULL AND $notNullFields <> ' ' )";
1522
        }
1523
1524
        return $ret;
1525
    }
1526
1527
    /**
1528
     * @param  array  $queryarray
1529
     * @param  string $andor
1530
     * @param  int    $limit
1531
     * @param  int    $offset
1532
     * @param  int    $userid
1533
     * @return array
1534
     */
1535
    public function getFaqsFromSearch($queryarray = array(), $andor = 'AND', $limit = 0, $offset = 0, $userid = 0)
1536
    {
1537
        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...
1538
1539
        $ret = array();
1540
1541
        $userIsAdmin = sf_userIsAdmin();
1542
1543
        if ($userid != 0) {
1544
            $criteriaUser = new CriteriaCompo();
1545
            $criteriaUser->add(new Criteria('faq.uid', $userid), 'OR');
1546
            $criteriaUser->add(new Criteria('answer.uid', $userid), 'OR');
1547
        }
1548
1549
        if ($queryarray) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $queryarray of type array is implicitly converted to a boolean; are you sure this is intended? If so, consider using ! empty($expr) instead to make it clear that you intend to check for an array without elements.

This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent.

Consider making the comparison explicit by using empty(..) or ! empty(...) instead.

Loading history...
1550
            $criteriaKeywords = new CriteriaCompo();
1551
            for ($i = 0, $iMax = count($queryarray); $i < $iMax; ++$i) {
1552
                $criteriaKeyword = new CriteriaCompo();
1553
                $criteriaKeyword->add(new Criteria('faq.question', '%' . $queryarray[$i] . '%', 'LIKE'), 'OR');
1554
                $criteriaKeyword->add(new Criteria('answer.answer', '%' . $queryarray[$i] . '%', 'LIKE'), 'OR');
1555
                $criteriaKeywords->add($criteriaKeyword, $andor);
1556
                unset($criteriaKeyword);
1557
            }
1558
        }
1559
1560
        // Categories for which user has access
1561
        if (!$userIsAdmin) {
1562
            $smartPermHandler = xoops_getModuleHandler('permission', 'smartfaq');
1563
1564
            $categoriesGranted = $smartPermHandler->getPermissions('category');
1565
            $faqsGranted       = $smartPermHandler->getPermissions('item');
1566
            if (!$categoriesGranted) {
1567
                return $ret;
1568
            }
1569
            if (!$faqsGranted) {
1570
                return $ret;
1571
            }
1572
            $grantedCategories = new Criteria('faq.categoryid', '(' . implode(',', $categoriesGranted) . ')', 'IN');
1573
            $grantedFaq        = new CriteriaCompo();
1574
            $grantedFaq->add(new Criteria('faq.faqid', '(' . implode(',', $faqsGranted) . ')', 'IN'), 'OR');
1575
            // If user is anonymous, check if the FAQ allow partialview
1576
            if (!is_object($xoopsUser)) {
1577
                $grantedFaq->add(new Criteria('partialview', '1'), 'OR');
1578
            }
1579
        }
1580
1581
        $criteriaPermissions = new CriteriaCompo();
1582
        if (!$userIsAdmin) {
1583
            $criteriaPermissions->add($grantedCategories, 'AND');
0 ignored issues
show
Bug introduced by
The variable $grantedCategories 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...
1584
            $criteriaPermissions->add($grantedFaq, 'AND');
0 ignored issues
show
Bug introduced by
The variable $grantedFaq 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...
1585
        }
1586
1587
        $criteriaAnswersStatus = new CriteriaCompo();
1588
        $criteriaAnswersStatus->add(new Criteria('answer.status', _SF_AN_STATUS_APPROVED));
1589
1590
        $criteriaFasStatus = new CriteriaCompo();
1591
        $criteriaFasStatus->add(new Criteria('faq.status', _SF_STATUS_OPENED), 'OR');
1592
        $criteriaFasStatus->add(new Criteria('faq.status', _SF_STATUS_PUBLISHED), 'OR');
1593
1594
        $criteria = new CriteriaCompo();
1595
        if (!empty($criteriaUser)) {
1596
            $criteria->add($criteriaUser, 'AND');
1597
        }
1598
1599
        if (!empty($criteriaKeywords)) {
1600
            $criteria->add($criteriaKeywords, 'AND');
1601
        }
1602
1603
        if (!empty($criteriaPermissions) && (!$userIsAdmin)) {
1604
            $criteria->add($criteriaPermissions);
1605
        }
1606
1607
        if (!empty($criteriaAnswersStatus)) {
1608
            $criteria->add($criteriaAnswersStatus, 'AND');
1609
        }
1610
1611
        if (!empty($criteriaFasStatus)) {
1612
            $criteria->add($criteriaFasStatus, 'AND');
1613
        }
1614
1615
        $criteria->setLimit($limit);
1616
        $criteria->setStart($offset);
1617
        $criteria->setSort('faq.datesub');
1618
        $criteria->setOrder('DESC');
1619
1620
        $sql = 'SELECT faq.faqid, faq.question, faq.datesub, faq.uid FROM '
1621
               . $this->db->prefix('smartfaq_faq')
1622
               . ' AS faq INNER JOIN '
1623
               . $this->db->prefix('smartfaq_answers')
1624
               . ' AS answer ON faq.faqid = answer.faqid';
1625
1626
        if (isset($criteria) && is_subclass_of($criteria, 'criteriaelement')) {
0 ignored issues
show
Bug introduced by
Due to PHP Bug #53727, is_subclass_of returns inconsistent results on some PHP versions for interfaces; you could instead use ReflectionClass::implementsInterface.
Loading history...
1627
            $whereClause = $criteria->renderWhere();
1628
1629 View Code Duplication
            if ($whereClause !== 'WHERE ()') {
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...
1630
                $sql .= ' ' . $criteria->renderWhere();
1631
                if ($criteria->getSort() != '') {
1632
                    $sql .= ' ORDER BY ' . $criteria->getSort() . ' ' . $criteria->getOrder();
1633
                }
1634
                $limit = $criteria->getLimit();
1635
                $start = $criteria->getStart();
1636
            }
1637
        }
1638
1639
        //echo "<br>" . $sql . "<br>";
0 ignored issues
show
Unused Code Comprehensibility introduced by
42% 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...
1640
1641
        $result = $this->db->query($sql, $limit, $start);
0 ignored issues
show
Bug introduced by
The variable $start 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...
1642
        if (!$result) {
1643
            trigger_error('Query did not work in smartfaq', E_USER_WARNING);
1644
1645
            return $ret;
1646
        }
1647
1648
        if (count($result) == 0) {
1649
            return $ret;
1650
        }
1651
1652
        while ($myrow = $this->db->fetchArray($result)) {
1653
            $faq = new sfFaq();
1654
            $faq->assignVars($myrow);
1655
            $ret[] = &$faq;
1656
            unset($faq);
1657
        }
1658
1659
        return $ret;
1660
    }
1661
1662
    /**
1663
     * @param  int   $cat_id
1664
     * @param        $status
1665
     * @return array
1666
     */
1667
    public function getCountsByCat($cat_id = 0, $status)
1668
    {
1669
        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...
1670
        $ret = array();
1671
        $sql = 'SELECT categoryid, COUNT(*) AS count FROM ' . $this->db->prefix('smartfaq_faq');
1672
        if ((int)$cat_id > 0) {
1673
            $sql .= ' WHERE categoryid = ' . (int)$cat_id;
1674
            $sql .= ' AND status IN (' . implode(',', $status) . ')';
1675
        } else {
1676
            $sql .= ' WHERE status IN (' . implode(',', $status) . ')';
1677
            if (!sf_userIsAdmin()) {
1678
                $smartPermHandler = xoops_getModuleHandler('permission', 'smartfaq');
1679
                $items            = $smartPermHandler->getPermissions('item');
1680
                if (is_object($xoopsUser)) {
1681
                    $sql .= ' AND faqid IN (' . implode(',', $items) . ')';
1682
                } else {
1683
                    $sql .= ' AND (faqid IN (' . implode(',', $items) . ') OR partialview = 1)';
1684
                }
1685
            }
1686
        }
1687
        $sql .= ' GROUP BY categoryid';
1688
1689
        //echo "<br>" . $sql . "<br>";
0 ignored issues
show
Unused Code Comprehensibility introduced by
42% 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...
1690
1691
        $result = $this->db->query($sql);
1692
        if (!$result) {
1693
            return $ret;
1694
        }
1695
        while ($row = $this->db->fetchArray($result)) {
1696
            $ret[$row['categoryid']] = (int)$row['count'];
1697
        }
1698
1699
        return $ret;
1700
    }
1701
}
1702