Completed
Push — master ( bb1ebf...0d7d1b )
by Michael
02:07
created

sfFaqHandler::insert()   D

Complexity

Conditions 9
Paths 27

Size

Total Lines 45
Code Lines 27

Duplication

Lines 5
Ratio 11.11 %

Importance

Changes 0
Metric Value
cc 9
eloc 27
nc 27
nop 2
dl 5
loc 45
rs 4.909
c 0
b 0
f 0
1
<?php
0 ignored issues
show
Coding Style Compatibility introduced by
For compatibility and reusability of your code, PSR1 recommends that a file should introduce either new symbols (like classes, functions, etc.) or have side-effects (like outputting something, or including other files), but not both at the same time. The first symbol is defined on line 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 (null !== $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
        require_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 . $xoopsConfig['sitename'] . ' : <a href=' . XOOPS_URL . '/modules/smartfaq/faq.php?faqid=' . $this->faqid() . '>' . XOOPS_URL . '/modules/smartfaq/faq.php?faqid=' . $this->faqid() . '</a>';
650
    }
651
652
    /**
653
     * @param  array $faq
654
     * @param  null  $category
655
     * @param  bool  $linkInQuestion
656
     * @return array
657
     */
658
    public function toArray($faq = array(), $category = null, $linkInQuestion = true)
659
    {
660
        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...
661
        $lastfaqsize = (int)$xoopsModuleConfig['lastfaqsize'];
662
663
        $faq['id']         = $this->faqid();
664
        $faq['categoryid'] = $this->categoryid();
665
        $faq['question']   = $this->question();
666
        $page              = ($this->status() == _SF_STATUS_OPENED) ? 'answer.php' : 'faq.php';
667
668
        $faq['questionlink'] = "<a href='$page?faqid=" . $this->faqid() . "'>" . $this->question($lastfaqsize) . '</a>';
669
        if ($linkInQuestion) {
670
            $faq['fullquestionlink'] = "<a href='$page?faqid=" . $this->faqid() . "'>" . $this->question() . '</a>';
671
        } else {
672
            $faq['fullquestionlink'] = $this->question();
673
        }
674
        $faq['faqid']      = $this->faqid();
675
        $faq['counter']    = $this->counter();
676
        $faq['cancomment'] = $this->cancomment();
677
        $faq['comments']   = $this->comments();
678
        $faq['datesub']    = $this->datesub();
679
        if (null !== $category) {
680
            if (is_object($category) && strtolower(get_class($category)) === 'sfcategory') {
681
                $categoryObj = $category;
682
            } elseif (is_array($category)) {
683
                $categoryObj = $category[$this->categoryid()];
684
            }
685
            $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...
686
            $faq['categorylink'] = "<a href='" . XOOPS_URL . '/modules/smartfaq/category.php?categoryid=' . $this->categoryid() . "'>" . $categoryObj->getVar('name') . '</a>';
687
        }
688
689
        return $faq;
690
    }
691
}
692
693
/**
694
 * Q&A handler class.
695
 * This class is responsible for providing data access mechanisms to the data source
696
 * of Q&A class objects.
697
 *
698
 * @author  marcan <[email protected]>
699
 * @package SmartFAQ
700
 */
701
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...
702
{
703
    /**
704
     * @param  bool $isNew
705
     * @return sfFaq
706
     */
707
    public function create($isNew = true)
708
    {
709
        $faq = new sfFaq();
710
        if ($isNew) {
711
            $faq->setDefaultPermissions();
712
            $faq->setNew();
713
        }
714
715
        return $faq;
716
    }
717
718
    /**
719
     * retrieve an FAQ
720
     *
721
     * @param  int $id faqid of the user
722
     * @return mixed reference to the {@link sfFaq} object, FALSE if failed
723
     */
724 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...
725
    {
726
        if ((int)$id > 0) {
727
            $sql = 'SELECT * FROM ' . $this->db->prefix('smartfaq_faq') . ' WHERE faqid=' . $id;
728
            if (!$result = $this->db->query($sql)) {
729
                return false;
730
            }
731
732
            $numrows = $this->db->getRowsNum($result);
733
            if ($numrows == 1) {
734
                $faq = new sfFaq();
735
                $faq->assignVars($this->db->fetchArray($result));
736
737
                return $faq;
738
            }
739
        }
740
741
        return false;
742
    }
743
744
    /**
745
     * insert a new faq in the database
746
     *
747
     * @param  XoopsObject $faq reference to the {@link sfFaq} object
748
     * @param  bool        $force
749
     * @return bool        FALSE if failed, TRUE if already present and unchanged or successful
750
     */
751
    public function insert(XoopsObject $faq, $force = false)
752
    {
753
        if (strtolower(get_class($faq)) !== 'sffaq') {
754
            return false;
755
        }
756
757
        if (!$faq->isDirty()) {
758
            return true;
759
        }
760
761
        if (!$faq->cleanVars()) {
762
            return false;
763
        }
764
765
        foreach ($faq->cleanVars as $k => $v) {
766
            ${$k} = $v;
767
        }
768
769
        if ($faq->isNew()) {
770
            $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)',
771
                           $this->db->prefix('smartfaq_faq'), $categoryid, $this->db->quoteString($question), $this->db->quoteString($howdoi), $this->db->quoteString($diduno), $uid, time(), $status, $counter, $weight, $html, $smiley, $xcodes, $cancomment, $comments, $notifypub,
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...
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...
772
                           $this->db->quoteString($modulelink), $this->db->quoteString($contextpage), $exacturl, $partialview);
0 ignored issues
show
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...
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...
773
        } else {
774
            $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"',
775
                           $this->db->prefix('smartfaq_faq'), $categoryid, $this->db->quoteString($question), $this->db->quoteString($howdoi), $this->db->quoteString($diduno), $uid, $datesub, $status, $counter, $weight, $html, $smiley, $xcodes, $cancomment, $comments, $notifypub,
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...
776
                           $this->db->quoteString($modulelink), $this->db->quoteString($contextpage), $exacturl, $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...
777
        }
778 View Code Duplication
        if (false !== $force) {
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...
779
            $result = $this->db->queryF($sql);
780
        } else {
781
            $result = $this->db->query($sql);
782
        }
783
784
        if (!$result) {
785
            return false;
786
        }
787
        if ($faq->isNew()) {
788
            $faq->assignVar('faqid', $this->db->getInsertId());
789
        }
790
791
        // Saving permissions
792
        sf_saveItemPermissions($faq->getGroups_read(), $faq->faqid());
793
794
        return true;
795
    }
796
797
    /**
798
     * delete an FAQ from the database
799
     *
800
     * @param  XoopsObject $faq reference to the FAQ to delete
801
     * @param  bool        $force
802
     * @return bool        FALSE if failed.
803
     */
804
    public function delete(XoopsObject $faq, $force = false)
805
    {
806
        $smartModule = sf_getModuleInfo();
807
        $module_id   = $smartModule->getVar('mid');
808
809
        if (strtolower(get_class($faq)) !== 'sffaq') {
810
            return false;
811
        }
812
813
        // Deleting the answers
814
        $answerHandler = new sfAnswerHandler($this->db);
815
        if (!$answerHandler->deleteFaqAnswers($faq)) {
816
            // error msg...
817
            echo 'error while deleteing an answer';
818
        }
819
820
        $sql = sprintf('DELETE FROM %s WHERE faqid = %u', $this->db->prefix('smartfaq_faq'), $faq->getVar('faqid'));
821
822 View Code Duplication
        if (false !== $force) {
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...
823
            $result = $this->db->queryF($sql);
824
        } else {
825
            $result = $this->db->query($sql);
826
        }
827
        if (!$result) {
828
            return false;
829
        }
830
831
        xoops_groupperm_deletebymoditem($module_id, 'item_read', $faq->faqid());
832
833
        return true;
834
    }
835
836
    /**
837
     * retrieve FAQs from the database
838
     *
839
     * @param  CriteriaElement $criteria  {@link CriteriaElement} conditions to be met
0 ignored issues
show
Documentation introduced by
Should the type for parameter $criteria not be null|CriteriaElement?

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...
840
     * @param  bool            $id_as_key use the faqid as key for the array?
841
     * @param  string          $notNullFields
842
     * @return false|array  array of <a href='psi_element://sfFaq'>sfFaq</a> objects
843
     */
844
    public function &getObjects(CriteriaElement $criteria = null, $id_as_key = false, $notNullFields = '')
845
    {
846
        $ret   = array();
847
        $limit = $start = 0;
848
        $sql   = 'SELECT * FROM ' . $this->db->prefix('smartfaq_faq');
849
850 View Code Duplication
        if (null !== $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...
851
            $whereClause = $criteria->renderWhere();
852
853
            if ($whereClause !== 'WHERE ()') {
854
                $sql .= ' ' . $criteria->renderWhere();
855
                if (!empty($notNullFields)) {
856
                    $sql .= $this->NotNullFieldClause($notNullFields, true);
857
                }
858
            } elseif (!empty($notNullFields)) {
859
                $sql .= ' WHERE ' . $this->NotNullFieldClause($notNullFields);
860
            }
861
            if ($criteria->getSort() != '') {
862
                $sql .= ' ORDER BY ' . $criteria->getSort() . ' ' . $criteria->getOrder();
863
            }
864
            $limit = $criteria->getLimit();
865
            $start = $criteria->getStart();
866
        } elseif (!empty($notNullFields)) {
867
            $sql .= $sql .= ' WHERE ' . $this->NotNullFieldClause($notNullFields);
868
        }
869
870
        //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...
871
        $result = $this->db->query($sql, $limit, $start);
872
        if (!$result) {
873
            return false;
874
        }
875
876
        if (count($result) == 0) {
877
            return false;
878
        }
879
880 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...
881
            $faq = new sfFaq();
882
            $faq->assignVars($myrow);
883
884
            if (!$id_as_key) {
885
                $ret[] =& $faq;
886
            } else {
887
                $ret[$myrow['faqid']] =& $faq;
888
            }
889
            unset($faq);
890
        }
891
892
        return $ret;
893
    }
894
895
    /**
896
     * @param  null|CriteriaElement $criteria
897
     * @param  bool                 $id_as_key
898
     * @param  string               $notNullFields
899
     * @return array|bool
900
     */
901
    public function &getObjectsAdminSide(CriteriaElement $criteria = null, $id_as_key = false, $notNullFields = '')
902
    {
903
        $ret   = array();
904
        $limit = $start = 0;
905
        $sql   = 'SELECT
906
                            faq.faqid AS faqid,
907
                            faq.categoryid AS categoryid,
908
                            faq.question AS question,
909
                            faq.howdoi AS howdoi,
910
                            faq.diduno AS diduno,
911
                            faq.uid AS uid,
912
                            faq.datesub AS datesub,
913
                            faq.status AS status,
914
                            faq.counter AS counter,
915
                            faq.weight AS weight,
916
                            faq.html AS html,
917
                            faq.smiley AS smiley,
918
                            faq.image AS image,
919
                            faq.linebreak AS linebreak,
920
                            faq.xcodes AS xcodes,
921
                            faq.cancomment AS cancomment,
922
                            faq.comments AS comments,
923
                            faq.notifypub AS notifypub,
924
                            faq.modulelink AS modulelink,
925
                            faq.contextpage AS contextpage,
926
                            faq.exacturl AS exacturl
927
                FROM ' . $this->db->prefix('smartfaq_faq') . ' AS faq INNER JOIN ' . $this->db->prefix('smartfaq_categories') . ' AS category ON faq.categoryid = category.categoryid ';
928
929 View Code Duplication
        if (null !== $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...
930
            $whereClause = $criteria->renderWhere();
931
932
            if ($whereClause !== 'WHERE ()') {
933
                $sql .= ' ' . $criteria->renderWhere();
934
                if (!empty($notNullFields)) {
935
                    $sql .= $this->NotNullFieldClause($notNullFields, true);
936
                }
937
            } elseif (!empty($notNullFields)) {
938
                $sql .= ' WHERE ' . $this->NotNullFieldClause($notNullFields);
939
            }
940
            if ($criteria->getSort() != '') {
941
                $sql .= ' ORDER BY ' . $criteria->getSort() . ' ' . $criteria->getOrder();
942
            }
943
            $limit = $criteria->getLimit();
944
            $start = $criteria->getStart();
945
        } elseif (!empty($notNullFields)) {
946
            $sql .= $sql .= ' WHERE ' . $this->NotNullFieldClause($notNullFields);
947
        }
948
949
        //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...
950
        $result = $this->db->query($sql, $limit, $start);
951
        if (!$result) {
952
            return false;
953
        }
954
955
        if (count($result) == 0) {
956
            return false;
957
        }
958
959 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...
960
            $faq = new sfFaq();
961
            $faq->assignVars($myrow);
962
963
            if (!$id_as_key) {
964
                $ret[] =& $faq;
965
            } else {
966
                $ret[$myrow['faqid']] =& $faq;
967
            }
968
            unset($faq);
969
        }
970
971
        return $ret;
972
973
        /*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...
974
            $faq = new sfFaq($myrow['faqid']);
975
976
            if (!$id_as_key) {
977
                $ret[] =& $faq;
978
            } else {
979
                $ret[$myrow['faqid']] =& $faq;
980
            }
981
            unset($faq);
982
        }
983
984
        return $ret;*/
985
    }
986
987
    /**
988
     * count FAQs matching a condition
989
     *
990
     * @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...
991
     * @param  string $notNullFields
992
     * @return int    count of FAQs
993
     */
994
    public function getCount($criteria = null, $notNullFields = '')
995
    {
996
        $sql = 'SELECT COUNT(*) FROM ' . $this->db->prefix('smartfaq_faq');
997
        if (null !== $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...
998
            $whereClause = $criteria->renderWhere();
999
            if ($whereClause !== 'WHERE ()') {
1000
                $sql .= ' ' . $criteria->renderWhere();
1001
                if (!empty($notNullFields)) {
1002
                    $sql .= $this->NotNullFieldClause($notNullFields, true);
1003
                }
1004
            } elseif (!empty($notNullFields)) {
1005
                $sql .= ' WHERE ' . $this->NotNullFieldClause($notNullFields);
1006
            }
1007
        } elseif (!empty($notNullFields)) {
1008
            $sql .= ' WHERE ' . $this->NotNullFieldClause($notNullFields);
1009
        }
1010
1011
        //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...
1012
        $result = $this->db->query($sql);
1013
        if (!$result) {
1014
            return 0;
1015
        }
1016
        list($count) = $this->db->fetchRow($result);
1017
1018
        return $count;
1019
    }
1020
1021
    /**
1022
     * @param  int    $categoryid
1023
     * @param  string $status
1024
     * @param  string $notNullFields
1025
     * @return int
1026
     */
1027
    public function getFaqsCount($categoryid = -1, $status = '', $notNullFields = '')
1028
    {
1029
        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...
1030
1031
        //  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...
1032
        //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...
1033
        //}
1034
1035
        $userIsAdmin = sf_userIsAdmin();
1036
        // Categories for which user has access
1037 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...
1038
            $smartPermHandler = xoops_getModuleHandler('permission', 'smartfaq');
1039
1040
            $categoriesGranted = $smartPermHandler->getPermissions('category');
1041
            $grantedCategories = new Criteria('categoryid', '(' . implode(',', $categoriesGranted) . ')', 'IN');
1042
1043
            $faqsGranted = $smartPermHandler->getPermissions('item');
1044
            $grantedFaq  = new CriteriaCompo();
1045
            $grantedFaq->add(new Criteria('faqid', '(' . implode(',', $faqsGranted) . ')', 'IN'), 'OR');
1046
            // If user is anonymous, check if the FAQ allow partialview
1047
            if (!is_object($xoopsUser)) {
1048
                $grantedFaq->add(new Criteria('partialview', '1'), 'OR');
1049
            }
1050
        }
1051
1052
        if (isset($categoryid) && ($categoryid != -1)) {
1053
            $criteriaCategory = new criteria('categoryid', $categoryid);
1054
        }
1055
1056
        $criteriaStatus = new CriteriaCompo();
1057
        if (!empty($status) && is_array($status)) {
1058
            foreach ($status as $v) {
1059
                $criteriaStatus->add(new Criteria('status', $v), 'OR');
1060
            }
1061
        } elseif (!empty($status) && ($status != -1)) {
1062
            $criteriaStatus->add(new Criteria('status', $status), 'OR');
1063
        }
1064
1065
        $criteriaPermissions = new CriteriaCompo();
1066
        if (!$userIsAdmin) {
1067
            $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...
1068
            $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...
1069
        }
1070
1071
        $criteria = new CriteriaCompo();
1072
        if (!empty($criteriaCategory)) {
1073
            $criteria->add($criteriaCategory);
1074
        }
1075
1076
        if (!empty($criteriaPermissions) && (!$userIsAdmin)) {
1077
            $criteria->add($criteriaPermissions);
1078
        }
1079
1080
        if (!empty($criteriaStatus)) {
1081
            $criteria->add($criteriaStatus);
1082
        }
1083
1084
        return $this->getCount($criteria, $notNullFields);
1085
    }
1086
1087
    /**
1088
     * @return array
1089
     */
1090
    public function getFaqsCountByStatus()
1091
    {
1092
        $sql    = 'SELECT status, COUNT(*) FROM ' . $this->db->prefix('smartfaq_faq') . ' GROUP BY status';
1093
        $result = $this->db->query($sql);
1094
        if (!$result) {
1095
            return array();
1096
        }
1097
        $ret = array();
1098
        while (list($status, $count) = $this->db->fetchRow($result)) {
1099
            $ret[$status] = $count;
1100
        }
1101
1102
        return $ret;
1103
    }
1104
1105
    /**
1106
     * @param  int    $limit
1107
     * @param  int    $start
1108
     * @param  int    $categoryid
1109
     * @param  string $sort
1110
     * @param  string $order
1111
     * @param  bool   $asobject
1112
     * @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...
1113
     */
1114
    public function getAllPublished(
1115
        $limit = 0,
1116
        $start = 0,
1117
        $categoryid = -1,
1118
        $sort = 'datesub',
1119
        $order = 'DESC',
1120
        $asobject = true
1121
    ) {
1122
        return $this->getFaqs($limit, $start, array(_SF_STATUS_PUBLISHED, _SF_STATUS_NEW_ANSWER), $categoryid, $sort, $order, null, $asobject, null);
1123
    }
1124
1125
    /**
1126
     * @param  int    $limit
1127
     * @param  int    $start
1128
     * @param  string $status
1129
     * @param  int    $categoryid
1130
     * @param  string $sort
1131
     * @param  string $order
1132
     * @param  string $notNullFields
1133
     * @param  bool   $asobject
1134
     * @param  null   $otherCriteria
1135
     * @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...
1136
     */
1137
    public function getFaqs(
1138
        $limit = 0,
1139
        $start = 0,
1140
        $status = '',
1141
        $categoryid = -1,
1142
        $sort = 'datesub',
1143
        $order = 'DESC',
1144
        $notNullFields = '',
1145
        $asobject = true,
1146
        $otherCriteria = null
1147
    ) {
1148
        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...
1149
        require_once XOOPS_ROOT_PATH . '/modules/smartfaq/include/functions.php';
1150
1151
        //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...
1152
        //  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...
1153
        //}
1154
        $ret         = array();
0 ignored issues
show
Unused Code introduced by
$ret is not used, you could remove the assignment.

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

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

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

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

Loading history...
1155
        $userIsAdmin = sf_userIsAdmin();
1156
        // Categories for which user has access
1157 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...
1158
            $smartPermHandler = xoops_getModuleHandler('permission', 'smartfaq');
1159
1160
            $categoriesGranted = $smartPermHandler->getPermissions('category');
1161
            $grantedCategories = new Criteria('categoryid', '(' . implode(',', $categoriesGranted) . ')', 'IN');
1162
1163
            $faqsGranted = $smartPermHandler->getPermissions('item');
1164
            $grantedFaq  = new CriteriaCompo();
1165
            $grantedFaq->add(new Criteria('faqid', '(' . implode(',', $faqsGranted) . ')', 'IN'), 'OR');
1166
            // If user is anonymous, check if the FAQ allow partialview
1167
            if (!is_object($xoopsUser)) {
1168
                $grantedFaq->add(new Criteria('partialview', '1'), 'OR');
1169
            }
1170
        }
1171
1172
        if (isset($categoryid) && ($categoryid != -1)) {
1173
            if (is_array($categoryid)) {
1174
                $criteriaCategory = new Criteria('categoryid', '(' . implode(',', $categoryid) . ')', 'IN');
1175
            } else {
1176
                $criteriaCategory = new Criteria('categoryid', (int)$categoryid);
1177
            }
1178
        }
1179
1180 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...
1181
            $criteriaStatus = new CriteriaCompo();
1182
            foreach ($status as $v) {
1183
                $criteriaStatus->add(new Criteria('status', $v), 'OR');
1184
            }
1185
        } elseif (!empty($status) && ($status != -1)) {
1186
            $criteriaStatus = new CriteriaCompo();
1187
            $criteriaStatus->add(new Criteria('status', $status), 'OR');
1188
        }
1189
1190
        $criteriaPermissions = new CriteriaCompo();
1191
        if (!$userIsAdmin) {
1192
            $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...
1193
            $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...
1194
        }
1195
1196
        $criteria = new CriteriaCompo();
1197
        if (!empty($criteriaCategory)) {
1198
            $criteria->add($criteriaCategory);
1199
        }
1200
1201
        if (!empty($criteriaPermissions) && (!$userIsAdmin)) {
1202
            $criteria->add($criteriaPermissions);
1203
        }
1204
1205
        if (!empty($criteriaStatus)) {
1206
            $criteria->add($criteriaStatus);
1207
        }
1208
1209
        if (!empty($otherCriteria)) {
1210
            $criteria->add($otherCriteria);
1211
        }
1212
1213
        $criteria->setLimit($limit);
1214
        $criteria->setStart($start);
1215
        $criteria->setSort($sort);
1216
        $criteria->setOrder($order);
1217
        $ret = $this->getObjects($criteria, false, $notNullFields);
1218
1219
        return $ret;
1220
    }
1221
1222
    /**
1223
     * @param  int    $limit
1224
     * @param  int    $start
1225
     * @param  string $status
1226
     * @param  int    $categoryid
1227
     * @param  string $sort
1228
     * @param  string $order
1229
     * @param  bool   $asobject
1230
     * @param  null   $otherCriteria
1231
     * @return array|bool
1232
     */
1233
    public function getFaqsAdminSide(
1234
        $limit = 0,
1235
        $start = 0,
1236
        $status = '',
1237
        $categoryid = -1,
1238
        $sort = 'datesub',
1239
        $order = 'DESC',
1240
        $asobject = true,
1241
        $otherCriteria = null
1242
    ) {
1243
        require_once XOOPS_ROOT_PATH . '/modules/smartfaq/include/functions.php';
1244
1245
        $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...
1246
1247
        $ret = array();
0 ignored issues
show
Unused Code introduced by
$ret is not used, you could remove the assignment.

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

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

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

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

Loading history...
1248
1249
        if (isset($categoryid) && ($categoryid != -1)) {
1250
            $criteriaCategory = new criteria('faq.categoryid', $categoryid);
1251
        }
1252
1253 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...
1254
            $criteriaStatus = new CriteriaCompo();
1255
            foreach ($status as $v) {
1256
                $criteriaStatus->add(new Criteria('faq.status', $v), 'OR');
1257
            }
1258
        } elseif (!empty($status) && ($status != -1)) {
1259
            $criteriaStatus = new CriteriaCompo();
1260
            $criteriaStatus->add(new Criteria('faq.status', $status), 'OR');
1261
        }
1262
1263
        $criteria = new CriteriaCompo();
1264
        if (!empty($criteriaCategory)) {
1265
            $criteria->add($criteriaCategory);
1266
        }
1267
1268
        if (!empty($criteriaStatus)) {
1269
            $criteria->add($criteriaStatus);
1270
        }
1271
1272
        if (!empty($otherCriteria)) {
1273
            $criteria->add($otherCriteria);
1274
        }
1275
1276
        $criteria->setLimit($limit);
1277
        $criteria->setStart($start);
1278
        $criteria->setSort($sort);
1279
        $criteria->setOrder($order);
1280
        $ret = $this->getObjectsAdminSide($criteria, false);
1281
1282
        return $ret;
1283
    }
1284
1285
    /**
1286
     * @param  string $field
1287
     * @param  string $status
1288
     * @param  int    $category
1289
     * @return bool|mixed
1290
     */
1291
    public function getRandomFaq($field = '', $status = '', $category = -1)
1292
    {
1293
        $ret = false;
1294
1295
        $notNullFields = $field;
1296
1297
        // Getting the number of published FAQ
1298
        $totalFaqs = $this->getFaqsCount(-1, $status, $notNullFields);
1299
1300
        if ($totalFaqs > 0) {
1301
            --$totalFaqs;
1302
            mt_srand((double)microtime() * 1000000);
1303
            $entrynumber = mt_rand(0, $totalFaqs);
1304
            $faq         = $this->getFaqs(1, $entrynumber, $status, -1, 'datesub', 'DESC', $notNullFields);
1305
            if ($faq) {
1306
                $ret =& $faq[0];
1307
            }
1308
        }
1309
1310
        return $ret;
1311
    }
1312
1313
    /**
1314
     * @param  int $limit
1315
     * @return array|bool
1316
     */
1317
    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...
1318
    {
1319
        $ret = false;
1320
1321
        $otherCriteria = new CriteriaCompo();
1322
        $otherCriteria->add(new Criteria('modulelink', 'None', '<>'));
1323
1324
        $faqsObj = $this->getFaqs(0, 0, array(_SF_STATUS_PUBLISHED, _SF_STATUS_NEW_ANSWER), -1, 'datesub', 'DESC', '', true, $otherCriteria);
1325
1326
        $totalfaqs  = count($faqsObj);
1327
        $randomFaqs = array();
1328
        if ($faqsObj) {
1329
            for ($i = 0; $i < $totalfaqs; ++$i) {
1330
                $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...
1331
1332
                $http        = (strpos(XOOPS_URL, 'https://') === false) ? 'http://' : 'https://';
1333
                $phpself     = $_SERVER['PHP_SELF'];
1334
                $httphost    = $_SERVER['HTTP_HOST'];
1335
                $querystring = $_SERVER['QUERY_STRING'];
1336
                if ($querystring != '') {
1337
                    $querystring = '?' . $querystring;
1338
                }
1339
                $currenturl     = $http . $httphost . $phpself . $querystring;
1340
                $fullcontexturl = XOOPS_URL . '/' . $faqsObj[$i]->contextpage();
1341
                switch ($faqsObj[$i]->modulelink()) {
1342
                    case '':
1343
                        $display = false;
1344
                        break;
1345
                    case 'None':
1346
                        $display = false;
1347
                        break;
1348
                    case 'All':
1349
                        $display = true;
1350
                        break;
1351
                    case 'url':
1352
                        if ($faqsObj[$i]->exacturl()) {
1353
                            $display = ($currenturl == $fullcontexturl);
1354
                        } else {
1355
                            $display = (strpos($currenturl, $fullcontexturl) === false);
1356
                        }
1357
                        break;
1358
                    default:
1359
                        if (strpos($currenturl, XOOPS_URL . '/modules/') === false) {
1360
                            $display = false;
1361
                        } else {
1362
                            if (strpos($currenturl, $faqsObj[$i]->modulelink()) === false) {
1363
                                $display = false;
1364
                            } else {
1365
                                $display = true;
1366
                            }
1367
                        }
1368
                        break;
1369
                }
1370
                if ($display) {
1371
                    $randomFaqs[] =& $faqsObj[$i];
1372
                }
1373
            }
1374
        }
1375
1376
        if (count($randomFaqs) > $limit) {
1377
            mt_srand((float)microtime() * 10000000);
1378
            $rand_keys = array_rand($randomFaqs, $limit);
1379
            for ($j = 0, $jMax = count($rand_keys); $j < $jMax; ++$j) {
1380
                $ret[] =& $randomFaqs[$rand_keys[$j]];
1381
            }
1382
        } else {
1383
            $ret =& $randomFaqs;
1384
        }
1385
1386
        return $ret;
1387
    }
1388
1389
    /**
1390
     * @param  array $status
1391
     * @return array
1392
     */
1393
    public function getLastPublishedByCat($status = array(_SF_STATUS_PUBLISHED, _SF_STATUS_NEW_ANSWER))
1394
    {
1395
        $ret       = array();
1396
        $faqclause = '';
1397
        if (!sf_userIsAdmin()) {
1398
            $smartPermHandler = xoops_getModuleHandler('permission', 'smartfaq');
1399
            $items            = $smartPermHandler->getPermissions('item');
1400
            $faqclause        = ' AND faqid IN (' . implode(',', $items) . ')';
1401
        }
1402
1403
        $sql  = "CREATE TEMPORARY TABLE tmp (categoryid INT(8) UNSIGNED NOT NULL,datesub INT(11) DEFAULT '0' NOT NULL);";
1404
        $sql2 = ' LOCK TABLES ' . $this->db->prefix('smartfaq_faq') . ' READ;';
1405
        $sql3 = ' INSERT INTO tmp SELECT categoryid, MAX(datesub) FROM ' . $this->db->prefix('smartfaq_faq') . ' WHERE status IN (' . implode(',', $status) . ") $faqclause GROUP BY categoryid;";
1406
        $sql4 = ' SELECT ' . $this->db->prefix('smartfaq_faq') . '.categoryid, faqid, question, uid, ' . $this->db->prefix('smartfaq_faq') . '.datesub FROM ' . $this->db->prefix('smartfaq_faq') . ', tmp
1407
                              WHERE ' . $this->db->prefix('smartfaq_faq') . '.categoryid=tmp.categoryid AND ' . $this->db->prefix('smartfaq_faq') . '.datesub=tmp.datesub;';
1408
        /*
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...
1409
        //Old implementation
1410
        $sql = "SELECT categoryid, faqid, question, uid, MAX(datesub) AS datesub FROM ".$this->db->prefix("smartfaq_faq")."
1411
               WHERE status IN (". implode(',', $status).")";
1412
        $sql .= " GROUP BY categoryid";
1413
        */
1414
        $this->db->queryF($sql);
1415
        $this->db->queryF($sql2);
1416
        $this->db->queryF($sql3);
1417
        $result = $this->db->query($sql4);
1418
        $error  = $this->db->error();
1419
        $this->db->queryF('UNLOCK TABLES;');
1420
        $this->db->queryF('DROP TABLE tmp;');
1421
        if (!$result) {
1422
            trigger_error('Error in getLastPublishedByCat SQL: ' . $error);
1423
1424
            return $ret;
1425
        }
1426 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...
1427
            $faq = new sfFaq();
1428
            $faq->assignVars($row);
1429
            $ret[$row['categoryid']] =& $faq;
1430
            unset($faq);
1431
        }
1432
1433
        return $ret;
1434
    }
1435
1436
    /**
1437
     * delete FAQs matching a set of conditions
1438
     *
1439
     * @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...
1440
     * @return bool   FALSE if deletion failed
1441
     */
1442 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...
1443
    {
1444
        $sql = 'DELETE FROM ' . $this->db->prefix('smartfaq_faq');
1445
        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...
1446
            $sql .= ' ' . $criteria->renderWhere();
1447
        }
1448
        if (!$this->db->query($sql)) {
1449
            return false;
1450
            // TODO : Also delete the permissions related to each FAQ
1451
        }
1452
1453
        return true;
1454
    }
1455
1456
    /**
1457
     * Change a value for FAQ with a certain criteria
1458
     *
1459
     * @param string $fieldname  Name of the field
1460
     * @param string $fieldvalue Value to write
1461
     * @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...
1462
     *
1463
     * @return bool
1464
     **/
1465 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...
1466
    {
1467
        $set_clause = is_numeric($fieldvalue) ? $fieldname . ' = ' . $fieldvalue : $fieldname . ' = ' . $this->db->quoteString($fieldvalue);
1468
        $sql        = 'UPDATE ' . $this->db->prefix('smartfaq_faq') . ' SET ' . $set_clause;
1469
        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...
1470
            $sql .= ' ' . $criteria->renderWhere();
1471
        }
1472
        if (!$this->db->queryF($sql)) {
1473
            return false;
1474
        }
1475
1476
        return true;
1477
    }
1478
1479
    /**
1480
     * @param $faqid
1481
     * @return bool
1482
     */
1483
    public function updateCounter($faqid)
1484
    {
1485
        $sql = 'UPDATE ' . $this->db->prefix('smartfaq_faq') . ' SET counter=counter+1 WHERE faqid = ' . $faqid;
1486
        if ($this->db->queryF($sql)) {
1487
            return true;
1488
        } else {
1489
            return false;
1490
        }
1491
    }
1492
1493
    /**
1494
     * @param  string $notNullFields
1495
     * @param  bool   $withAnd
1496
     * @return string
1497
     */
1498
    public function NotNullFieldClause($notNullFields = '', $withAnd = false)
1499
    {
1500
        $ret = '';
1501
        if ($withAnd) {
1502
            $ret .= ' AND ';
1503
        }
1504
        if (!empty($notNullFields) && is_array($notNullFields)) {
1505
            foreach ($notNullFields as $v) {
1506
                $ret .= " ($v IS NOT NULL AND $v <> ' ' )";
1507
            }
1508
        } elseif (!empty($notNullFields)) {
1509
            $ret .= " ($notNullFields IS NOT NULL AND $notNullFields <> ' ' )";
1510
        }
1511
1512
        return $ret;
1513
    }
1514
1515
    /**
1516
     * @param  array  $queryarray
1517
     * @param  string $andor
1518
     * @param  int    $limit
1519
     * @param  int    $offset
1520
     * @param  int    $userid
1521
     * @return array
1522
     */
1523
    public function getFaqsFromSearch($queryarray = array(), $andor = 'AND', $limit = 0, $offset = 0, $userid = 0)
1524
    {
1525
        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...
1526
1527
        $ret = array();
1528
1529
        $userIsAdmin = sf_userIsAdmin();
1530
1531
        if ($userid != 0) {
1532
            $criteriaUser = new CriteriaCompo();
1533
            $criteriaUser->add(new Criteria('faq.uid', $userid), 'OR');
1534
            $criteriaUser->add(new Criteria('answer.uid', $userid), 'OR');
1535
        }
1536
1537
        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...
1538
            $criteriaKeywords = new CriteriaCompo();
1539
            for ($i = 0, $iMax = count($queryarray); $i < $iMax; ++$i) {
1540
                $criteriaKeyword = new CriteriaCompo();
1541
                $criteriaKeyword->add(new Criteria('faq.question', '%' . $queryarray[$i] . '%', 'LIKE'), 'OR');
1542
                $criteriaKeyword->add(new Criteria('answer.answer', '%' . $queryarray[$i] . '%', 'LIKE'), 'OR');
1543
                $criteriaKeywords->add($criteriaKeyword, $andor);
1544
                unset($criteriaKeyword);
1545
            }
1546
        }
1547
1548
        // Categories for which user has access
1549
        if (!$userIsAdmin) {
1550
            $smartPermHandler = xoops_getModuleHandler('permission', 'smartfaq');
1551
1552
            $categoriesGranted = $smartPermHandler->getPermissions('category');
1553
            $faqsGranted       = $smartPermHandler->getPermissions('item');
1554
            if (!$categoriesGranted) {
1555
                return $ret;
1556
            }
1557
            if (!$faqsGranted) {
1558
                return $ret;
1559
            }
1560
            $grantedCategories = new Criteria('faq.categoryid', '(' . implode(',', $categoriesGranted) . ')', 'IN');
1561
            $grantedFaq        = new CriteriaCompo();
1562
            $grantedFaq->add(new Criteria('faq.faqid', '(' . implode(',', $faqsGranted) . ')', 'IN'), 'OR');
1563
            // If user is anonymous, check if the FAQ allow partialview
1564
            if (!is_object($xoopsUser)) {
1565
                $grantedFaq->add(new Criteria('partialview', '1'), 'OR');
1566
            }
1567
        }
1568
1569
        $criteriaPermissions = new CriteriaCompo();
1570
        if (!$userIsAdmin) {
1571
            $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...
1572
            $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...
1573
        }
1574
1575
        $criteriaAnswersStatus = new CriteriaCompo();
1576
        $criteriaAnswersStatus->add(new Criteria('answer.status', _SF_AN_STATUS_APPROVED));
1577
1578
        $criteriaFasStatus = new CriteriaCompo();
1579
        $criteriaFasStatus->add(new Criteria('faq.status', _SF_STATUS_OPENED), 'OR');
1580
        $criteriaFasStatus->add(new Criteria('faq.status', _SF_STATUS_PUBLISHED), 'OR');
1581
1582
        $criteria = new CriteriaCompo();
1583
        if (!empty($criteriaUser)) {
1584
            $criteria->add($criteriaUser, 'AND');
1585
        }
1586
1587
        if (!empty($criteriaKeywords)) {
1588
            $criteria->add($criteriaKeywords, 'AND');
1589
        }
1590
1591
        if (!empty($criteriaPermissions) && (!$userIsAdmin)) {
1592
            $criteria->add($criteriaPermissions);
1593
        }
1594
1595
        if (!empty($criteriaAnswersStatus)) {
1596
            $criteria->add($criteriaAnswersStatus, 'AND');
1597
        }
1598
1599
        if (!empty($criteriaFasStatus)) {
1600
            $criteria->add($criteriaFasStatus, 'AND');
1601
        }
1602
1603
        $criteria->setLimit($limit);
1604
        $criteria->setStart($offset);
1605
        $criteria->setSort('faq.datesub');
1606
        $criteria->setOrder('DESC');
1607
1608
        $sql = 'SELECT faq.faqid, faq.question, faq.datesub, faq.uid FROM ' . $this->db->prefix('smartfaq_faq') . ' AS faq INNER JOIN ' . $this->db->prefix('smartfaq_answers') . ' AS answer ON faq.faqid = answer.faqid';
1609
1610
        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...
1611
            $whereClause = $criteria->renderWhere();
1612
1613 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...
1614
                $sql .= ' ' . $criteria->renderWhere();
1615
                if ($criteria->getSort() != '') {
1616
                    $sql .= ' ORDER BY ' . $criteria->getSort() . ' ' . $criteria->getOrder();
1617
                }
1618
                $limit = $criteria->getLimit();
1619
                $start = $criteria->getStart();
1620
            }
1621
        }
1622
1623
        //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...
1624
1625
        $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...
1626
        if (!$result) {
1627
            trigger_error('Query did not work in smartfaq', E_USER_WARNING);
1628
1629
            return $ret;
1630
        }
1631
1632
        if (count($result) == 0) {
1633
            return $ret;
1634
        }
1635
1636
        while ($myrow = $this->db->fetchArray($result)) {
1637
            $faq = new sfFaq();
1638
            $faq->assignVars($myrow);
1639
            $ret[] =& $faq;
1640
            unset($faq);
1641
        }
1642
1643
        return $ret;
1644
    }
1645
1646
    /**
1647
     * @param  int   $cat_id
1648
     * @param        $status
1649
     * @return array
1650
     */
1651
    public function getCountsByCat($cat_id = 0, $status)
1652
    {
1653
        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...
1654
        $ret = array();
1655
        $sql = 'SELECT categoryid, COUNT(*) AS count FROM ' . $this->db->prefix('smartfaq_faq');
1656
        if ((int)$cat_id > 0) {
1657
            $sql .= ' WHERE categoryid = ' . (int)$cat_id;
1658
            $sql .= ' AND status IN (' . implode(',', $status) . ')';
1659
        } else {
1660
            $sql .= ' WHERE status IN (' . implode(',', $status) . ')';
1661
            if (!sf_userIsAdmin()) {
1662
                $smartPermHandler = xoops_getModuleHandler('permission', 'smartfaq');
1663
                $items            = $smartPermHandler->getPermissions('item');
1664
                if (is_object($xoopsUser)) {
1665
                    $sql .= ' AND faqid IN (' . implode(',', $items) . ')';
1666
                } else {
1667
                    $sql .= ' AND (faqid IN (' . implode(',', $items) . ') OR partialview = 1)';
1668
                }
1669
            }
1670
        }
1671
        $sql .= ' GROUP BY categoryid';
1672
1673
        //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...
1674
1675
        $result = $this->db->query($sql);
1676
        if (!$result) {
1677
            return $ret;
1678
        }
1679
        while ($row = $this->db->fetchArray($result)) {
1680
            $ret[$row['categoryid']] = (int)$row['count'];
1681
        }
1682
1683
        return $ret;
1684
    }
1685
}
1686