Completed
Push — master ( 454ebd...de22fe )
by Michael
03:58
created

Answer::displayAttachment()   C

Complexity

Conditions 11
Paths 2

Size

Total Lines 85
Code Lines 76

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 11
eloc 76
nc 2
nop 1
dl 0
loc 85
rs 5.2653
c 0
b 0
f 0

How to fix   Long Method    Complexity   

Long Method

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

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

Commonly applied refactorings include:

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

Our type inference engine has found an assignment to a property that is incompatible with the declared type of that property.

Either this assignment is in error or the assigned type should be added to the documentation/type hint for that property..

Loading history...
72
        } else {
73
            $this->attachment_array = @unserialize(base64_decode($attachment));
74
        }
75
76
        return $this->attachment_array;
77
    }
78
79
    /**
80
     * @param $attach_key
81
     * @return bool
82
     */
83
    public function incrementDownload($attach_key)
84
    {
85
        if (!$attach_key) {
86
            return false;
87
        }
88
        $this->attachment_array[(string)$attach_key]['num_download']++;
89
90
        return $this->attachment_array[(string)$attach_key]['num_download'];
91
    }
92
93
    /**
94
     * @return bool
95
     */
96
    public function saveAttachment()
0 ignored issues
show
Coding Style introduced by
saveAttachment uses the super-global variable $GLOBALS which is generally not recommended.

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

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

// Better
class Router
{
    private $host;

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

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

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

        // Better (assuming you use the Symfony2 request)
        $page = $request->query->get('page', 1);
    }
}
Loading history...
97
    {
98
        $attachment_save = '';
99 View Code Duplication
        if (is_array($this->attachment_array) && count($this->attachment_array) > 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...
100
            $attachment_save = base64_encode(serialize($this->attachment_array));
101
        }
102
        $this->setVar('attachment', $attachment_save);
103
        $sql = 'UPDATE ' . $GLOBALS['xoopsDB']->prefix('smartfaq_answers') . ' SET attachment=' . $GLOBALS['xoopsDB']->quoteString($attachment_save) . ' WHERE post_id = ' . $this->getVar('answerid');
104
        if (!$result = $GLOBALS['xoopsDB']->queryF($sql)) {
105
            //xoops_error($GLOBALS["xoopsDB"]->error());
0 ignored issues
show
Unused Code Comprehensibility introduced by
84% 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...
106
            return false;
107
        }
108
109
        return true;
110
    }
111
112
    /**
113
     * @param  null $attach_array
114
     * @return bool
115
     */
116
    public function deleteAttachment($attach_array = null)
117
    {
118
        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...
119
120
        $attach_old = $this->getAttachment();
121
        if (!is_array($attach_old) || count($attach_old) < 1) {
122
            return true;
123
        }
124
        $this->attachment_array = [];
125
126
        if (null === $attach_array) {
127
            $attach_array = array_keys($attach_old);
128
        } // to delete all!
129
        if (!is_array($attach_array)) {
130
            $attach_array = [$attach_array];
131
        }
132
133
        foreach ($attach_old as $key => $attach) {
134
            if (in_array($key, $attach_array)) {
135
                @unlink(XOOPS_ROOT_PATH . '/' . $xoopsModuleConfig['dir_attachments'] . '/' . $attach['name_saved']);
0 ignored issues
show
Security Best Practice introduced by
It seems like you do not handle an error condition here. This can introduce security issues, and is generally not recommended.

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...
136
                @unlink(XOOPS_ROOT_PATH . '/' . $xoopsModuleConfig['dir_attachments'] . '/thumbs/' . $attach['name_saved']); // delete thumbnails
0 ignored issues
show
Security Best Practice introduced by
It seems like you do not handle an error condition here. This can introduce security issues, and is generally not recommended.

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...
137
                continue;
138
            }
139
            $this->attachment_array[$key] = $attach;
140
        }
141
        $attachment_save = '';
142 View Code Duplication
        if (is_array($this->attachment_array) && count($this->attachment_array) > 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...
143
            $attachment_save = base64_encode(serialize($this->attachment_array));
144
        }
145
        $this->setVar('attachment', $attachment_save);
146
147
        return true;
148
    }
149
150
    /**
151
     * @param  string $name_saved
152
     * @param  string $name_display
153
     * @param  string $mimetype
154
     * @param  int    $num_download
155
     * @return bool
156
     */
157
    public function setAttachment($name_saved = '', $name_display = '', $mimetype = '', $num_download = 0)
158
    {
159
        static $counter = 0;
160
        $this->attachment_array = $this->getAttachment();
0 ignored issues
show
Documentation Bug introduced by
It seems like $this->getAttachment() of type * is incompatible with the declared type array of property $attachment_array.

Our type inference engine has found an assignment to a property that is incompatible with the declared type of that property.

Either this assignment is in error or the assigned type should be added to the documentation/type hint for that property..

Loading history...
161
        if ($name_saved) {
162
            $key                          = (string)(time() + ($counter++));
163
            $this->attachment_array[$key] = [
164
                'name_saved'   => $name_saved,
165
                'name_display' => isset($name_display) ? $name_display : $name_saved,
166
                'mimetype'     => $mimetype,
167
                'num_download' => isset($num_download) ? (int)$num_download : 0
168
            ];
169
        }
170
        $attachment_save = null;
171
        if (is_array($this->attachment_array)) {
172
            $attachment_save = base64_encode(serialize($this->attachment_array));
173
        }
174
        $this->setVar('attachment', $attachment_save);
175
176
        return true;
177
    }
178
179
    /**
180
     * TODO: refactor
181
     * @param  bool $asSource
182
     * @return string
183
     */
184
    public function displayAttachment($asSource = false)
185
    {
186
        global $xoopsModule, $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...
187
188
        $post_attachment = '';
189
        $attachments     = $this->getAttachment();
190
        if (is_array($attachments) && count($attachments) > 0) {
191
            $iconHandler = sf_getIconHandler();
192
            $mime_path   = $iconHandler->getPath('mime');
193
            require_once XOOPS_ROOT_PATH . '/modules/' . $xoopsModule->getVar('dirname', 'n') . '/include/functions.image.php';
194
            $image_extensions = ['jpg', 'jpeg', 'gif', 'png', 'bmp']; // need improve !!!
0 ignored issues
show
Unused Code Comprehensibility introduced by
38% 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...
195
            $post_attachment  .= '<br><strong>' . _MD_ATTACHMENT . '</strong>:';
196
            $post_attachment  .= '<br><hr size="1" noshade="noshade"><br>';
197
            foreach ($attachments as $key => $att) {
198
                $file_extension = ltrim(strrchr($att['name_saved'], '.'), '.');
199
                $filetype       = $file_extension;
200
                if (file_exists(XOOPS_ROOT_PATH . '/' . $mime_path . '/' . $filetype . '.gif')) {
201
                    $icon_filetype = XOOPS_URL . '/' . $mime_path . '/' . $filetype . '.gif';
202
                } else {
203
                    $icon_filetype = XOOPS_URL . '/' . $mime_path . '/unknown.gif';
204
                }
205
                $file_size = @filesize(XOOPS_ROOT_PATH . '/' . $xoopsModuleConfig['dir_attachments'] . '/' . $att['name_saved']);
206
                $file_size = number_format($file_size / 1024, 2) . ' KB';
207
                if ($xoopsModuleConfig['media_allowed'] && in_array(strtolower($file_extension), $image_extensions)) {
208
                    $post_attachment .= '<br><img src="' . $icon_filetype . '" alt="' . $filetype . '"><strong>&nbsp; ' . $att['name_display'] . '</strong> <small>(' . $file_size . ')</small>';
209
                    $post_attachment .= '<br>' . sf_attachmentImage($att['name_saved']);
210
                    $isDisplayed     = true;
0 ignored issues
show
Unused Code introduced by
$isDisplayed 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...
211
                } else {
212
                    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...
213
                    if (empty($xoopsModuleConfig['show_userattach'])) {
214
                        $post_attachment .= '<a href="'
215
                                            . XOOPS_URL
216
                                            . '/modules/'
217
                                            . $xoopsModule->getVar('dirname', 'n')
218
                                            . '/dl_attachment.php?attachid='
219
                                            . $key
220
                                            . '&amp;post_id='
221
                                            . $this->getVar('post_id')
222
                                            . '"> <img src="'
223
                                            . $icon_filetype
224
                                            . '" alt="'
225
                                            . $filetype
226
                                            . '"> '
227
                                            . $att['name_display']
228
                                            . '</a> '
229
                                            . _MD_FILESIZE
230
                                            . ': '
231
                                            . $file_size
232
                                            . '; '
233
                                            . _MD_HITS
234
                                            . ': '
235
                                            . $att['num_download'];
236
                    } elseif ($xoopsUser && $xoopsUser->uid() > 0 && $xoopsUser->isActive()) {
237
                        $post_attachment .= '<a href="'
238
                                            . XOOPS_URL
239
                                            . '/modules/'
240
                                            . $xoopsModule->getVar('dirname', 'n')
241
                                            . '/dl_attachment.php?attachid='
242
                                            . $key
243
                                            . '&amp;post_id='
244
                                            . $this->getVar('post_id')
245
                                            . '"> <img src="'
246
                                            . $icon_filetype
247
                                            . '" alt="'
248
                                            . $filetype
249
                                            . '"> '
250
                                            . $att['name_display']
251
                                            . '</a> '
252
                                            . _MD_FILESIZE
253
                                            . ': '
254
                                            . $file_size
255
                                            . '; '
256
                                            . _MD_HITS
257
                                            . ': '
258
                                            . $att['num_download'];
259
                    } else {
260
                        $post_attachment .= _MD_NEWBB_SEENOTGUEST;
261
                    }
262
                }
263
                $post_attachment .= '<br>';
264
            }
265
        }
266
267
        return $post_attachment;
268
    }
269
    // attachment functions
270
    // ////////////////////////////////////////////////////////////////////////////////////
271
272
    /**
273
     * @param  bool $force
274
     * @return bool
275
     */
276
    public function store($force = true)
277
    {
278
        $answerHandler = new AnswerHandler($this->db);
279
280
        if (Constants::SF_AN_STATUS_APPROVED == $this->status()) {
281
            $criteria = new \CriteriaCompo(new \Criteria('faqid', $this->faqid()));
282
            $answerHandler->updateAll('status', Constants::SF_AN_STATUS_REJECTED, $criteria);
283
        }
284
285
        return $answerHandler->insert($this, $force);
286
    }
287
288
    /**
289
     * @return mixed
290
     */
291
    public function answerid()
292
    {
293
        return $this->getVar('answerid');
294
    }
295
296
    /**
297
     * @return mixed
298
     */
299
    public function faqid()
300
    {
301
        return $this->getVar('faqid');
302
    }
303
304
    /**
305
     * @param  string $format
306
     * @return mixed
307
     */
308
    public function answer($format = 'S')
309
    {
310
        return $this->getVar('answer', $format);
311
    }
312
313
    /**
314
     * @return mixed
315
     */
316
    public function uid()
317
    {
318
        return $this->getVar('uid');
319
    }
320
321
    /**
322
     * @param  string $dateFormat
323
     * @param  string $format
324
     * @return string
325
     */
326 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...
327
    {
328
        if ('none' === $dateFormat) {
329
            $smartModuleConfig = Smartfaq\Utility::getModuleConfig();
330
            $dateFormat        = $smartModuleConfig['dateformat'];
331
        }
332
333
        return formatTimestamp($this->getVar('datesub', $format), $dateFormat);
334
    }
335
336
    /**
337
     * @return mixed
338
     */
339
    public function status()
340
    {
341
        return $this->getVar('status');
342
    }
343
344
    /**
345
     * @return bool
346
     */
347
    public function notLoaded()
348
    {
349
        return (-1 == $this->getVar('answerid'));
350
    }
351
352
    /**
353
     * @param array $notifications
354
     */
355
    public function sendNotifications($notifications = [])
356
    {
357
        $smartModule = Smartfaq\Utility::getModuleInfo();
358
359
        $myts                = \MyTextSanitizer::getInstance();
360
        $notificationHandler = xoops_getHandler('notification');
361
362
        $faqObj = new Smartfaq\Faq($this->faqid());
363
364
        $tags                  = [];
365
        $tags['MODULE_NAME']   = $myts->displayTarea($smartModule->getVar('name'));
366
        $tags['FAQ_NAME']      = $faqObj->question();
367
        $tags['FAQ_URL']       = XOOPS_URL . '/modules/' . $smartModule->getVar('dirname') . '/faq.php?faqid=' . $faqObj->faqid();
368
        $tags['CATEGORY_NAME'] = $faqObj->getCategoryName();
369
        $tags['CATEGORY_URL']  = XOOPS_URL . '/modules/' . $smartModule->getVar('dirname') . '/category.php?categoryid=' . $faqObj->categoryid();
370
        $tags['FAQ_QUESTION']  = $faqObj->question();
371
372
        // TODO : Not sure about the 'formpreview' ...
373
        $tags['FAQ_ANSWER'] = $this->answer('formpreview');
374
        $tags['DATESUB']    = $this->datesub();
375
376
        foreach ($notifications as $notification) {
377
            switch ($notification) {
378
                case Constants::SF_NOT_ANSWER_APPROVED:
379
                    // This notification is not working for PM, but is for email... and I don't understand why???
380
                    $notificationHandler->triggerEvent('faq', $this->answerid(), 'answer_approved', $tags);
381
                    break;
382
                case -1:
383
                default:
384
                    break;
385
            }
386
        }
387
    }
388
}
389