Passed
Push — master ( 81ba93...c6c854 )
by Michael
03:30
created

Answer   B

Complexity

Total Complexity 52

Size/Duplication

Total Lines 376
Duplicated Lines 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
wmc 52
eloc 192
c 1
b 0
f 0
dl 0
loc 376
rs 7.44

16 Methods

Rating   Name   Duplication   Size   Complexity  
A status() 0 3 1
A saveAttachment() 0 14 4
A __construct() 0 28 4
A setAttachment() 0 20 5
A datesub() 0 10 2
A faqid() 0 3 1
A answer() 0 3 1
C displayAttachment() 0 86 11
A notLoaded() 0 3 1
B deleteAttachment() 0 33 9
A sendNotifications() 0 31 4
A uid() 0 3 1
A incrementDownload() 0 8 2
A answerid() 0 3 1
A store() 0 10 2
A getAttachment() 0 13 3

How to fix   Complexity   

Complex Class

Complex classes like Answer often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

While breaking up the class, it is a good idea to analyze how other classes use Answer, and based on these observations, apply Extract Interface, too.

1
<?php
2
3
namespace XoopsModules\Smartfaq;
4
5
/**
6
 * Module: SmartFAQ
7
 * Author: The SmartFactory <www.smartfactory.ca>
8
 * Licence: GNU
9
 */
10
11
use XoopsModules\Smartfaq;
12
13
// defined('XOOPS_ROOT_PATH') || die('Restricted access');
14
15
/**
16
 * Class Answer
17
 */
18
class Answer extends \XoopsObject
19
{
20
    public $attachment_array = [];
21
    public $db;
22
23
    /**
24
     * constructor
25
     * @param null $id
0 ignored issues
show
Documentation Bug introduced by
Are you sure the doc-type for parameter $id is correct as it would always require null to be passed?
Loading history...
26
     */
27
    public function __construct($id = null)
28
    {
29
        $this->db = \XoopsDatabaseFactory::getDatabaseConnection();
30
        $this->initVar('answerid', XOBJ_DTYPE_INT, null, false);
31
        $this->initVar('status', XOBJ_DTYPE_INT, -1, false);
32
        $this->initVar('faqid', XOBJ_DTYPE_INT, null, false);
33
        $this->initVar('answer', XOBJ_DTYPE_TXTAREA, null, true);
34
        $this->initVar('uid', XOBJ_DTYPE_INT, 0, false);
35
        $this->initVar('datesub', XOBJ_DTYPE_INT, null, false);
36
        $this->initVar('notifypub', XOBJ_DTYPE_INT, 0, false);
37
38
        $this->initVar('attachment', XOBJ_DTYPE_TXTAREA, '');
39
40
        $this->initVar('dohtml', XOBJ_DTYPE_INT, 1, false);
41
        $this->initVar('doxcode', XOBJ_DTYPE_INT, 1, false);
42
        $this->initVar('dosmiley', XOBJ_DTYPE_INT, 1, false);
43
        $this->initVar('doimage', XOBJ_DTYPE_INT, 0, false);
44
        $this->initVar('dobr', XOBJ_DTYPE_INT, 1, false);
45
46
        // for backward compatibility
47
        if (isset($id)) {
48
            if (is_array($id)) {
49
                $this->assignVars($id);
50
            } else {
51
                $answerHandler = new AnswerHandler($this->db);
52
                $answer        = $answerHandler->get($id);
53
                foreach ($answer->vars as $k => $v) {
54
                    $this->assignVar($k, $v['value']);
55
                }
56
            }
57
        }
58
    }
59
60
    // ////////////////////////////////////////////////////////////////////////////////////
61
    // attachment functions    TODO: there should be a file/attachment management class
62
63
    /**
64
     * @return array|mixed|null
65
     */
66
    public function getAttachment()
67
    {
68
        if (count($this->attachment_array)) {
69
            return $this->attachment_array;
70
        }
71
        $attachment = $this->getVar('attachment');
72
        if (empty($attachment)) {
73
            $this->attachment_array = null;
74
        } else {
75
            $this->attachment_array = @unserialize(base64_decode($attachment, true));
0 ignored issues
show
Bug introduced by
It seems like $attachment can also be of type array and array; however, parameter $data of base64_decode() does only seem to accept string, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

75
            $this->attachment_array = @unserialize(base64_decode(/** @scrutinizer ignore-type */ $attachment, true));
Loading history...
76
        }
77
78
        return $this->attachment_array;
79
    }
80
81
    /**
82
     * @param $attach_key
83
     * @return bool
84
     */
85
    public function incrementDownload($attach_key)
86
    {
87
        if (!$attach_key) {
88
            return false;
89
        }
90
        $this->attachment_array[(string)$attach_key]['num_download']++;
91
92
        return $this->attachment_array[(string)$attach_key]['num_download'];
93
    }
94
95
    /**
96
     * @return bool
97
     */
98
    public function saveAttachment()
99
    {
100
        $attachment_save = '';
101
        if ($this->attachment_array && is_array($this->attachment_array)) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $this->attachment_array 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...
102
            $attachment_save = base64_encode(serialize($this->attachment_array));
103
        }
104
        $this->setVar('attachment', $attachment_save);
105
        $sql = 'UPDATE ' . $GLOBALS['xoopsDB']->prefix('smartfaq_answers') . ' SET attachment=' . $GLOBALS['xoopsDB']->quoteString($attachment_save) . ' WHERE post_id = ' . $this->getVar('answerid');
106
        if (!$result = $GLOBALS['xoopsDB']->queryF($sql)) {
0 ignored issues
show
Unused Code introduced by
The assignment to $result is dead and can be removed.
Loading history...
107
            //xoops_error($GLOBALS["xoopsDB"]->error());
108
            return false;
109
        }
110
111
        return true;
112
    }
113
114
    /**
115
     * @param  null $attach_array
0 ignored issues
show
Documentation Bug introduced by
Are you sure the doc-type for parameter $attach_array is correct as it would always require null to be passed?
Loading history...
116
     * @return bool
117
     */
118
    public function deleteAttachment($attach_array = null)
119
    {
120
        /** @var Smartfaq\Helper $helper */
121
        $helper = Smartfaq\Helper::getInstance();
122
123
        $attach_old = $this->getAttachment();
124
        if (!is_array($attach_old) || count($attach_old) < 1) {
125
            return true;
126
        }
127
        $this->attachment_array = [];
128
129
        if (null === $attach_array) {
0 ignored issues
show
introduced by
The condition null === $attach_array is always true.
Loading history...
130
            $attach_array = array_keys($attach_old);
131
        } // to delete all!
132
        if (!is_array($attach_array)) {
0 ignored issues
show
introduced by
The condition is_array($attach_array) is always true.
Loading history...
133
            $attach_array = [$attach_array];
134
        }
135
136
        foreach ($attach_old as $key => $attach) {
137
            if (in_array($key, $attach_array)) {
138
                @unlink(XOOPS_ROOT_PATH . '/' . $helper->getConfig('dir_attachments') . '/' . $attach['name_saved']);
0 ignored issues
show
Security Best Practice introduced by
It seems like you do not handle an error condition for unlink(). This can introduce security issues, and is generally not recommended. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-unhandled  annotation

138
                /** @scrutinizer ignore-unhandled */ @unlink(XOOPS_ROOT_PATH . '/' . $helper->getConfig('dir_attachments') . '/' . $attach['name_saved']);

If you suppress an error, we recommend checking for the error condition explicitly:

// For example instead of
@mkdir($dir);

// Better use
if (@mkdir($dir) === false) {
    throw new \RuntimeException('The directory '.$dir.' could not be created.');
}
Loading history...
139
                @unlink(XOOPS_ROOT_PATH . '/' . $helper->getConfig('dir_attachments') . '/thumbs/' . $attach['name_saved']); // delete thumbnails
140
                continue;
141
            }
142
            $this->attachment_array[$key] = $attach;
143
        }
144
        $attachment_save = '';
145
        if ($this->attachment_array && is_array($this->attachment_array)) {
146
            $attachment_save = base64_encode(serialize($this->attachment_array));
147
        }
148
        $this->setVar('attachment', $attachment_save);
149
150
        return true;
151
    }
152
153
    /**
154
     * @param  string $name_saved
155
     * @param  string $name_display
156
     * @param  string $mimetype
157
     * @param  int    $num_download
158
     * @return bool
159
     */
160
    public function setAttachment($name_saved = '', $name_display = '', $mimetype = '', $num_download = 0)
161
    {
162
        static $counter = 0;
163
        $this->attachment_array = $this->getAttachment();
164
        if ($name_saved) {
165
            $key                          = (string)(time() + ($counter++));
166
            $this->attachment_array[$key] = [
167
                'name_saved'   => $name_saved,
168
                'name_display' => isset($name_display) ? $name_display : $name_saved,
169
                'mimetype'     => $mimetype,
170
                'num_download' => isset($num_download) ? (int)$num_download : 0,
171
            ];
172
        }
173
        $attachment_save = null;
174
        if (is_array($this->attachment_array)) {
175
            $attachment_save = base64_encode(serialize($this->attachment_array));
176
        }
177
        $this->setVar('attachment', $attachment_save);
178
179
        return true;
180
    }
181
182
    /**
183
     * TODO: refactor
184
     * @param  bool $asSource
185
     * @return string
186
     */
187
    public function displayAttachment($asSource = false)
0 ignored issues
show
Unused Code introduced by
The parameter $asSource is not used and could be removed. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-unused  annotation

187
    public function displayAttachment(/** @scrutinizer ignore-unused */ $asSource = false)

This check looks for parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
188
    {
189
        global $xoopsModule;
190
        /** @var Smartfaq\Helper $helper */
191
        $helper = Smartfaq\Helper::getInstance();
192
193
        $post_attachment = '';
194
        $attachments     = $this->getAttachment();
195
        if ($attachments && is_array($attachments)) {
196
            $iconHandler = sf_getIconHandler();
197
            $mime_path   = $iconHandler->getPath('mime');
198
            require_once XOOPS_ROOT_PATH . '/modules/' . $xoopsModule->getVar('dirname', 'n') . '/include/functions.image.php';
199
            $image_extensions = ['jpg', 'jpeg', 'gif', 'png', 'bmp']; // need improve !!!
200
            $post_attachment  .= '<br><strong>' . _MD_ATTACHMENT . '</strong>:';
201
            $post_attachment  .= '<br><hr size="1" noshade="noshade"><br>';
202
            foreach ($attachments as $key => $att) {
203
                $file_extension = ltrim(mb_strrchr($att['name_saved'], '.'), '.');
204
                $filetype       = $file_extension;
205
                if (file_exists(XOOPS_ROOT_PATH . '/' . $mime_path . '/' . $filetype . '.gif')) {
206
                    $icon_filetype = XOOPS_URL . '/' . $mime_path . '/' . $filetype . '.gif';
207
                } else {
208
                    $icon_filetype = XOOPS_URL . '/' . $mime_path . '/unknown.gif';
209
                }
210
                $file_size = @filesize(XOOPS_ROOT_PATH . '/' . $helper->getConfig('dir_attachments') . '/' . $att['name_saved']);
211
                $file_size = number_format($file_size / 1024, 2) . ' KB';
212
                if ($helper->getConfig('media_allowed') && in_array(mb_strtolower($file_extension), $image_extensions)) {
213
                    $post_attachment .= '<br><img src="' . $icon_filetype . '" alt="' . $filetype . '"><strong>&nbsp; ' . $att['name_display'] . '</strong> <small>(' . $file_size . ')</small>';
214
                    $post_attachment .= '<br>' . sf_attachmentImage($att['name_saved']);
215
                    $isDisplayed     = true;
0 ignored issues
show
Unused Code introduced by
The assignment to $isDisplayed is dead and can be removed.
Loading history...
216
                } else {
217
                    global $xoopsUser;
218
                    if (empty($helper->getConfig('show_userattach'))) {
219
                        $post_attachment .= '<a href="'
220
                                            . XOOPS_URL
221
                                            . '/modules/'
222
                                            . $xoopsModule->getVar('dirname', 'n')
223
                                            . '/dl_attachment.php?attachid='
224
                                            . $key
225
                                            . '&amp;post_id='
226
                                            . $this->getVar('post_id')
227
                                            . '"> <img src="'
228
                                            . $icon_filetype
229
                                            . '" alt="'
230
                                            . $filetype
231
                                            . '"> '
232
                                            . $att['name_display']
233
                                            . '</a> '
234
                                            . _MD_FILESIZE
235
                                            . ': '
236
                                            . $file_size
237
                                            . '; '
238
                                            . _MD_HITS
239
                                            . ': '
240
                                            . $att['num_download'];
241
                    } elseif ($xoopsUser && $xoopsUser->uid() > 0 && $xoopsUser->isActive()) {
242
                        $post_attachment .= '<a href="'
243
                                            . XOOPS_URL
244
                                            . '/modules/'
245
                                            . $xoopsModule->getVar('dirname', 'n')
246
                                            . '/dl_attachment.php?attachid='
247
                                            . $key
248
                                            . '&amp;post_id='
249
                                            . $this->getVar('post_id')
250
                                            . '"> <img src="'
251
                                            . $icon_filetype
252
                                            . '" alt="'
253
                                            . $filetype
254
                                            . '"> '
255
                                            . $att['name_display']
256
                                            . '</a> '
257
                                            . _MD_FILESIZE
258
                                            . ': '
259
                                            . $file_size
260
                                            . '; '
261
                                            . _MD_HITS
262
                                            . ': '
263
                                            . $att['num_download'];
264
                    } else {
265
                        $post_attachment .= _MD_NEWBB_SEENOTGUEST;
0 ignored issues
show
Bug introduced by
The constant XoopsModules\Smartfaq\_MD_NEWBB_SEENOTGUEST was not found. Maybe you did not declare it correctly or list all dependencies?
Loading history...
266
                    }
267
                }
268
                $post_attachment .= '<br>';
269
            }
270
        }
271
272
        return $post_attachment;
273
    }
274
275
    // attachment functions
276
    // ////////////////////////////////////////////////////////////////////////////////////
277
278
    /**
279
     * @param  bool $force
280
     * @return bool
281
     */
282
    public function store($force = true)
283
    {
284
        $answerHandler = new AnswerHandler($this->db);
285
286
        if (Constants::SF_AN_STATUS_APPROVED == $this->status()) {
287
            $criteria = new \CriteriaCompo(new \Criteria('faqid', $this->faqid()));
0 ignored issues
show
Bug introduced by
It seems like $this->faqid() can also be of type array and array; however, parameter $value of Criteria::__construct() does only seem to accept string, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

287
            $criteria = new \CriteriaCompo(new \Criteria('faqid', /** @scrutinizer ignore-type */ $this->faqid()));
Loading history...
288
            $answerHandler->updateAll('status', Constants::SF_AN_STATUS_REJECTED, $criteria);
289
        }
290
291
        return $answerHandler->insert($this, $force);
292
    }
293
294
    /**
295
     * @return mixed
296
     */
297
    public function answerid()
298
    {
299
        return $this->getVar('answerid');
300
    }
301
302
    /**
303
     * @return mixed
304
     */
305
    public function faqid()
306
    {
307
        return $this->getVar('faqid');
308
    }
309
310
    /**
311
     * @param  string $format
312
     * @return mixed
313
     */
314
    public function answer($format = 'S')
315
    {
316
        return $this->getVar('answer', $format);
317
    }
318
319
    /**
320
     * @return mixed
321
     */
322
    public function uid()
323
    {
324
        return $this->getVar('uid');
325
    }
326
327
    /**
328
     * @param  string $dateFormat
329
     * @param  string $format
330
     * @return string
331
     */
332
    public function datesub($dateFormat = 'none', $format = 'S')
333
    {
334
        if ('none' === $dateFormat) {
335
            /** @var Smartfaq\Helper $helper */
336
            $helper = Smartfaq\Helper::getInstance();
337
            $smartModuleConfig = $helper->getConfig();
338
            $dateFormat        = $smartModuleConfig['dateformat'];
339
        }
340
341
        return formatTimestamp($this->getVar('datesub', $format), $dateFormat);
342
    }
343
344
    /**
345
     * @return mixed
346
     */
347
    public function status()
348
    {
349
        return $this->getVar('status');
350
    }
351
352
    /**
353
     * @return bool
354
     */
355
    public function notLoaded()
356
    {
357
        return (-1 == $this->getVar('answerid'));
358
    }
359
360
    /**
361
     * @param array $notifications
362
     */
363
    public function sendNotifications($notifications = [])
364
    {
365
        $smartModule = Smartfaq\Utility::getModuleInfo();
366
367
        $myts = \MyTextSanitizer::getInstance();
368
        /** @var \XoopsNotificationHandler $notificationHandler */
369
        $notificationHandler = xoops_getHandler('notification');
370
371
        $faqObj = new Smartfaq\Faq($this->faqid());
372
373
        $tags                  = [];
374
        $tags['MODULE_NAME']   = $myts->displayTarea($smartModule->getVar('name'));
375
        $tags['FAQ_NAME']      = $faqObj->question();
376
        $tags['FAQ_URL']       = XOOPS_URL . '/modules/' . $smartModule->getVar('dirname') . '/faq.php?faqid=' . $faqObj->faqid();
377
        $tags['CATEGORY_NAME'] = $faqObj->getCategoryName();
378
        $tags['CATEGORY_URL']  = XOOPS_URL . '/modules/' . $smartModule->getVar('dirname') . '/category.php?categoryid=' . $faqObj->categoryid();
379
        $tags['FAQ_QUESTION']  = $faqObj->question();
380
381
        // TODO : Not sure about the 'formpreview' ...
382
        $tags['FAQ_ANSWER'] = $this->answer('formpreview');
383
        $tags['DATESUB']    = $this->datesub();
384
385
        foreach ($notifications as $notification) {
386
            switch ($notification) {
387
                case Constants::SF_NOT_ANSWER_APPROVED:
388
                    // This notification is not working for PM, but is for email... and I don't understand why???
389
                    $notificationHandler->triggerEvent('faq', $this->answerid(), 'answer_approved', $tags);
390
                    break;
391
                case -1:
392
                default:
393
                    break;
394
            }
395
        }
396
    }
397
}
398