Completed
Pull Request — master (#337)
by Michael
10:31
created

SystemBlock   B

Complexity

Total Complexity 31

Size/Duplication

Total Lines 266
Duplicated Lines 25.94 %

Coupling/Cohesion

Components 1
Dependencies 18

Importance

Changes 0
Metric Value
dl 69
loc 266
rs 7.1866
c 0
b 0
f 0
wmc 31
lcom 1
cbo 18

5 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 4 1
F getForm() 0 158 16
C getOptions() 29 29 7
A isCustom() 0 4 1
B getContent() 40 40 6

How to fix   Duplicated Code   

Duplicated Code

Duplicate code is one of the most pungent code smells. A rule that is often used is to re-structure code once it is duplicated in three or more places.

Common duplication problems, and corresponding solutions are:

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

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
 * Block Class Manager
4
 *
5
 * You may not change or alter any portion of this comment or credits
6
 * of supporting developers from this source code or any supporting source code
7
 * which is considered copyrighted (c) material of the original comment or credit authors.
8
 * This program is distributed in the hope that it will be useful,
9
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
11
 *
12
 * @copyright       (c) 2000-2016 XOOPS Project (www.xoops.org)
13
 * @license             GNU GPL 2 (http://www.gnu.org/licenses/gpl-2.0.html)
14
 * @package             system
15
 */
16
// defined('XOOPS_ROOT_PATH') || exit('XOOPS root path not defined');
17
18
require_once XOOPS_ROOT_PATH . '/kernel/block.php';
19
20
/**
21
 * System Block
22
 *
23
 * @copyright       (c) 2000-2016 XOOPS Project (www.xoops.org)
24
 * @package             system
25
 */
26
class SystemBlock extends XoopsBlock
27
{
28
    /**
29
     *
30
     */
31
    public function __construct()
32
    {
33
        parent::__construct();
34
    }
35
36
    /**
37
     * @param string $mode
38
     *
39
     * @return XoopsThemeForm
40
     */
41
    public function getForm($mode = 'edit')
42
    {
43
        if ($this->isNew()) {
44
            $title   = _AM_SYSTEM_BLOCKS_ADDBLOCK;
45
            $modules = array(-1);
46
            $groups  = array(XOOPS_GROUP_USERS, XOOPS_GROUP_ANONYMOUS, XOOPS_GROUP_ADMIN);
47
            $this->setVar('block_type', 'C');
48
            $this->setVar('visible', 1);
49
            $op = 'save';
50
        } else {
51
            // Search modules
52
            /* @var  $blocklinkmodule_handler SystemBlockLinkModuleHandler */
53
            $blocklinkmodule_handler = xoops_getModuleHandler('blocklinkmodule');
54
            $criteria                = new CriteriaCompo(new Criteria('block_id', $this->getVar('bid')));
55
            $blocklinkmodule         = $blocklinkmodule_handler->getObjects($criteria);
56
            foreach ($blocklinkmodule as $link) {
57
                /* @var  $link SystemBlockLinkModule */
58
                $modules[] = $link->getVar('module_id');
0 ignored issues
show
Coding Style Comprehensibility introduced by
$modules was never initialized. Although not strictly required by PHP, it is generally a good practice to add $modules = array(); before regardless.

Adding an explicit array definition is generally preferable to implicit array definition as it guarantees a stable state of the code.

Let’s take a look at an example:

foreach ($collection as $item) {
    $myArray['foo'] = $item->getFoo();

    if ($item->hasBar()) {
        $myArray['bar'] = $item->getBar();
    }

    // do something with $myArray
}

As you can see in this example, the array $myArray is initialized the first time when the foreach loop is entered. You can also see that the value of the bar key is only written conditionally; thus, its value might result from a previous iteration.

This might or might not be intended. To make your intention clear, your code more readible and to avoid accidental bugs, we recommend to add an explicit initialization $myArray = array() either outside or inside the foreach loop.

Loading history...
59
            }
60
            // Search perms
61
            /* @var $groupperm_handler XoopsGroupPermHandler  */
62
            $groupperm_handler = xoops_getHandler('groupperm');
63
            $groups            = $groupperm_handler->getGroupIds('block_read', $this->getVar('bid'));
64
            switch ($mode) {
65
                case 'edit':
66
                    $title = _AM_SYSTEM_BLOCKS_EDITBLOCK;
67
                    break;
68
                case 'clone':
69
                    $title = _AM_SYSTEM_BLOCKS_CLONEBLOCK;
70
                    $this->setVar('bid', 0);
71
                    if ($this->isCustom()) {
72
                        $this->setVar('block_type', 'C');
73
                    } else {
74
                        $this->setVar('block_type', 'D');
75
                    }
76
                    break;
77
            }
78
            $op = 'save';
79
        }
80
        $form = new XoopsThemeForm($title, 'blockform', 'admin.php', 'post', true);
0 ignored issues
show
Bug introduced by
The variable $title 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...
81
        if (!$this->isNew()) {
82
            $form->addElement(new XoopsFormLabel(_AM_SYSTEM_BLOCKS_NAME, $this->getVar('name')));
83
        }
84
        // Side position
85
        $side_select = new XoopsFormSelect(_AM_SYSTEM_BLOCKS_TYPE, 'side', $this->getVar('side'));
86
        $side_select->addOptionArray(array(
87
                                         0  => _AM_SYSTEM_BLOCKS_SBLEFT,
88
                                         1  => _AM_SYSTEM_BLOCKS_SBRIGHT,
89
                                         3  => _AM_SYSTEM_BLOCKS_CBLEFT,
90
                                         4  => _AM_SYSTEM_BLOCKS_CBRIGHT,
91
                                         5  => _AM_SYSTEM_BLOCKS_CBCENTER,
92
                                         7  => _AM_SYSTEM_BLOCKS_CBBOTTOMLEFT,
93
                                         8  => _AM_SYSTEM_BLOCKS_CBBOTTOMRIGHT,
94
                                         9  => _AM_SYSTEM_BLOCKS_CBBOTTOM,
95
                                         10 => _AM_SYSTEM_BLOCKS_CBFOOTERLEFT,
96
                                         11 => _AM_SYSTEM_BLOCKS_CBFOOTERRIGHT,
97
                                         12 => _AM_SYSTEM_BLOCKS_CBFOOTERCENTER));
98
99
        $form->addElement($side_select);
100
        // Order
101
        $form->addElement(new XoopsFormText(_AM_SYSTEM_BLOCKS_WEIGHT, 'weight', 2, 5, $this->getVar('weight')));
102
        // Display
103
        $form->addElement(new XoopsFormRadioYN(_AM_SYSTEM_BLOCKS_VISIBLE, 'visible', $this->getVar('visible')));
104
        // Visible In
105
        $mod_select     = new XoopsFormSelect(_AM_SYSTEM_BLOCKS_VISIBLEIN, 'modules', $modules, 5, true);
0 ignored issues
show
Bug introduced by
The variable $modules 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...
106
        /* @var $module_handler XoopsModuleHandler */
107
        $module_handler = xoops_getHandler('module');
108
        $criteria       = new CriteriaCompo(new Criteria('hasmain', 1));
109
        $criteria->add(new Criteria('isactive', 1));
110
        $module_list     = $module_handler->getList($criteria);
111
        $module_list[-1] = _AM_SYSTEM_BLOCKS_TOPPAGE;
112
        $module_list[0]  = _AM_SYSTEM_BLOCKS_ALLPAGES;
113
        ksort($module_list);
114
        $mod_select->addOptionArray($module_list);
115
        $form->addElement($mod_select);
116
        // Title
117
        $form->addElement(new XoopsFormText(_AM_SYSTEM_BLOCKS_TITLE, 'title', 50, 255, $this->getVar('title')), false);
118
        if ($this->isNew() || $this->isCustom()) {
119
            $editor_configs           = array();
120
            $editor_configs['name']   = 'content_block';
121
            $editor_configs['value']  = $this->getVar('content', 'e');
122
            $editor_configs['rows']   = 20;
123
            $editor_configs['cols']   = 100;
124
            $editor_configs['width']  = '100%';
125
            $editor_configs['height'] = '400px';
126
            $editor_configs['editor'] = xoops_getModuleOption('blocks_editor', 'system');
0 ignored issues
show
Deprecated Code introduced by
The function xoops_getModuleOption() has been deprecated.

This function has been deprecated.

Loading history...
127
            $form->addElement(new XoopsFormEditor(_AM_SYSTEM_BLOCKS_CONTENT, 'content_block', $editor_configs), true);
128
            if (in_array($editor_configs['editor'], array('dhtmltextarea', 'textarea'))) {
129
                $ctype_select = new XoopsFormSelect(_AM_SYSTEM_BLOCKS_CTYPE, 'c_type', $this->getVar('c_type'));
130
                $ctype_select->addOptionArray(array(
131
                                                  'H' => _AM_SYSTEM_BLOCKS_HTML,
132
                                                  'P' => _AM_SYSTEM_BLOCKS_PHP,
133
                                                  'S' => _AM_SYSTEM_BLOCKS_AFWSMILE,
134
                                                  'T' => _AM_SYSTEM_BLOCKS_AFNOSMILE));
135
                $form->addElement($ctype_select);
136
            } else {
137
                $form->addElement(new XoopsFormHidden('c_type', 'H'));
138
            }
139
        } else {
140
            if ($this->getVar('template') !== '') {
141
                $tplfile_handler = xoops_getHandler('tplfile');
142
                $btemplate       = $tplfile_handler->find($GLOBALS['xoopsConfig']['template_set'], 'block', $this->getVar('bid'));
143
                if (count($btemplate) > 0) {
144
                    $form->addElement(new XoopsFormLabel(_AM_SYSTEM_BLOCKS_CONTENT, '<a href="' . XOOPS_URL . '/modules/system/admin.php?fct=tplsets&amp;op=edittpl&amp;id=' . $btemplate[0]->getVar('tpl_id') . '">' . _AM_SYSTEM_BLOCKS_EDITTPL . '</a>'));
145
                } else {
146
                    $btemplate2 = $tplfile_handler->find('default', 'block', $this->getVar('bid'));
147
                    if (count($btemplate2) > 0) {
148
                        $form->addElement(new XoopsFormLabel(_AM_SYSTEM_BLOCKS_CONTENT, '<a href="' . XOOPS_URL . '/modules/system/admin.php?fct=tplsets&amp;op=edittpl&amp;id=' . $btemplate2[0]->getVar('tpl_id') . '" rel="external">' . _AM_SYSTEM_BLOCKS_EDITTPL . '</a>'));
149
                    }
150
                }
151
            }
152
            if ($this->getOptions() !== false) {
153
                $form->addElement(new XoopsFormLabel(_AM_SYSTEM_BLOCKS_OPTIONS, $this->getOptions()));
0 ignored issues
show
Bug introduced by
It seems like $this->getOptions() targeting SystemBlock::getOptions() can also be of type boolean; however, XoopsFormLabel::__construct() does only seem to accept string, maybe add an additional type check?

This check looks at variables that are passed out again to other methods.

If the outgoing method call has stricter type requirements than the method itself, an issue is raised.

An additional type check may prevent trouble.

Loading history...
154
            } else {
155
                $form->addElement(new XoopsFormHidden('options', $this->getVar('options')));
156
            }
157
            $form->addElement(new XoopsFormHidden('c_type', 'H'));
158
        }
159
        $cache_select = new XoopsFormSelect(_AM_SYSTEM_BLOCKS_BCACHETIME, 'bcachetime', $this->getVar('bcachetime'));
160
        $cache_select->addOptionArray(array(
161
                                          '0'       => _NOCACHE,
162
                                          '30'      => sprintf(_SECONDS, 30),
163
                                          '60'      => _MINUTE,
164
                                          '300'     => sprintf(_MINUTES, 5),
165
                                          '1800'    => sprintf(_MINUTES, 30),
166
                                          '3600'    => _HOUR,
167
                                          '18000'   => sprintf(_HOURS, 5),
168
                                          '86400'   => _DAY,
169
                                          '259200'  => sprintf(_DAYS, 3),
170
                                          '604800'  => _WEEK,
171
                                          '2592000' => _MONTH));
172
        $form->addElement($cache_select);
173
        // Groups
174
        $form->addElement(new XoopsFormSelectGroup(_AM_SYSTEM_BLOCKS_GROUP, 'groups', true, $groups, 5, true));
175
176
        $form->addElement(new XoopsFormHidden('block_type', $this->getVar('block_type')));
177
        $form->addElement(new XoopsFormHidden('mid', $this->getVar('mid')));
178
        $form->addElement(new XoopsFormHidden('func_num', $this->getVar('func_num')));
179
        $form->addElement(new XoopsFormHidden('func_file', $this->getVar('func_file')));
180
        $form->addElement(new XoopsFormHidden('show_func', $this->getVar('show_func')));
181
        $form->addElement(new XoopsFormHidden('edit_func', $this->getVar('edit_func')));
182
        $form->addElement(new XoopsFormHidden('template', $this->getVar('template')));
183
        $form->addElement(new XoopsFormHidden('dirname', $this->getVar('dirname')));
184
        $form->addElement(new XoopsFormHidden('name', $this->getVar('name')));
185
        $form->addElement(new XoopsFormHidden('bid', $this->getVar('bid')));
186
        $form->addElement(new XoopsFormHidden('op', $op));
187
        $form->addElement(new XoopsFormHidden('fct', 'blocksadmin'));
188
        $button_tray = new XoopsFormElementTray('', '&nbsp;');
189
        if ($this->isNew() || $this->isCustom()) {
190
            $preview = new XoopsFormButton('', 'previewblock', _PREVIEW, 'preview');
191
            $preview->setExtra("onclick=\"blocks_preview();\"");
192
            $button_tray->addElement($preview);
193
        }
194
        $button_tray->addElement(new XoopsFormButton('', 'submitblock', _SUBMIT, 'submit'));
195
        $form->addElement($button_tray);
196
197
        return $form;
198
    }
199
200
    /**
201
     * XoopsBlock::getOptions()
202
     *
203
     * @return bool|string
204
     */
205 View Code Duplication
    public function getOptions()
206
    {
207
        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...
208
        if (!$this->isCustom()) {
209
            $edit_func = $this->getVar('edit_func');
210
            if (!$edit_func) {
211
                return false;
0 ignored issues
show
Bug Best Practice introduced by
The return type of return false; (false) is incompatible with the return type of the parent method XoopsBlock::getOptions of type string.

If you return a value from a function or method, it should be a sub-type of the type that is given by the parent type f.e. an interface, or abstract method. This is more formally defined by the Lizkov substitution principle, and guarantees that classes that depend on the parent type can use any instance of a child type interchangably. This principle also belongs to the SOLID principles for object oriented design.

Let’s take a look at an example:

class Author {
    private $name;

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

    public function getName() {
        return $this->name;
    }
}

abstract class Post {
    public function getAuthor() {
        return 'Johannes';
    }
}

class BlogPost extends Post {
    public function getAuthor() {
        return new Author('Johannes');
    }
}

class ForumPost extends Post { /* ... */ }

function my_function(Post $post) {
    echo strtoupper($post->getAuthor());
}

Our function my_function expects a Post object, and outputs the author of the post. The base class Post returns a simple string and outputting a simple string will work just fine. However, the child class BlogPost which is a sub-type of Post instead decided to return an object, and is therefore violating the SOLID principles. If a BlogPost were passed to my_function, PHP would not complain, but ultimately fail when executing the strtoupper call in its body.

Loading history...
212
            }
213
            if (file_exists($GLOBALS['xoops']->path('modules/' . $this->getVar('dirname') . '/blocks/' . $this->getVar('func_file')))) {
214
                if (file_exists($file = $GLOBALS['xoops']->path('modules/' . $this->getVar('dirname') . '/language/' . $xoopsConfig['language'] . '/blocks.php'))) {
215
                    include_once $file;
216
                } elseif (file_exists($file = $GLOBALS['xoops']->path('modules/' . $this->getVar('dirname') . '/language/english/blocks.php'))) {
217
                    include_once $file;
218
                }
219
                include_once $GLOBALS['xoops']->path('modules/' . $this->getVar('dirname') . '/blocks/' . $this->getVar('func_file'));
220
                $options   = explode('|', $this->getVar('options'));
221
                $edit_form = $edit_func($options);
222
                if (!$edit_form) {
223
                    return false;
0 ignored issues
show
Bug Best Practice introduced by
The return type of return false; (false) is incompatible with the return type of the parent method XoopsBlock::getOptions of type string.

If you return a value from a function or method, it should be a sub-type of the type that is given by the parent type f.e. an interface, or abstract method. This is more formally defined by the Lizkov substitution principle, and guarantees that classes that depend on the parent type can use any instance of a child type interchangably. This principle also belongs to the SOLID principles for object oriented design.

Let’s take a look at an example:

class Author {
    private $name;

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

    public function getName() {
        return $this->name;
    }
}

abstract class Post {
    public function getAuthor() {
        return 'Johannes';
    }
}

class BlogPost extends Post {
    public function getAuthor() {
        return new Author('Johannes');
    }
}

class ForumPost extends Post { /* ... */ }

function my_function(Post $post) {
    echo strtoupper($post->getAuthor());
}

Our function my_function expects a Post object, and outputs the author of the post. The base class Post returns a simple string and outputting a simple string will work just fine. However, the child class BlogPost which is a sub-type of Post instead decided to return an object, and is therefore violating the SOLID principles. If a BlogPost were passed to my_function, PHP would not complain, but ultimately fail when executing the strtoupper call in its body.

Loading history...
224
                }
225
226
                return $edit_form;
227
            } else {
228
                return false;
0 ignored issues
show
Bug Best Practice introduced by
The return type of return false; (false) is incompatible with the return type of the parent method XoopsBlock::getOptions of type string.

If you return a value from a function or method, it should be a sub-type of the type that is given by the parent type f.e. an interface, or abstract method. This is more formally defined by the Lizkov substitution principle, and guarantees that classes that depend on the parent type can use any instance of a child type interchangably. This principle also belongs to the SOLID principles for object oriented design.

Let’s take a look at an example:

class Author {
    private $name;

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

    public function getName() {
        return $this->name;
    }
}

abstract class Post {
    public function getAuthor() {
        return 'Johannes';
    }
}

class BlogPost extends Post {
    public function getAuthor() {
        return new Author('Johannes');
    }
}

class ForumPost extends Post { /* ... */ }

function my_function(Post $post) {
    echo strtoupper($post->getAuthor());
}

Our function my_function expects a Post object, and outputs the author of the post. The base class Post returns a simple string and outputting a simple string will work just fine. However, the child class BlogPost which is a sub-type of Post instead decided to return an object, and is therefore violating the SOLID principles. If a BlogPost were passed to my_function, PHP would not complain, but ultimately fail when executing the strtoupper call in its body.

Loading history...
229
            }
230
        } else {
231
            return false;
0 ignored issues
show
Bug Best Practice introduced by
The return type of return false; (false) is incompatible with the return type of the parent method XoopsBlock::getOptions of type string.

If you return a value from a function or method, it should be a sub-type of the type that is given by the parent type f.e. an interface, or abstract method. This is more formally defined by the Lizkov substitution principle, and guarantees that classes that depend on the parent type can use any instance of a child type interchangably. This principle also belongs to the SOLID principles for object oriented design.

Let’s take a look at an example:

class Author {
    private $name;

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

    public function getName() {
        return $this->name;
    }
}

abstract class Post {
    public function getAuthor() {
        return 'Johannes';
    }
}

class BlogPost extends Post {
    public function getAuthor() {
        return new Author('Johannes');
    }
}

class ForumPost extends Post { /* ... */ }

function my_function(Post $post) {
    echo strtoupper($post->getAuthor());
}

Our function my_function expects a Post object, and outputs the author of the post. The base class Post returns a simple string and outputting a simple string will work just fine. However, the child class BlogPost which is a sub-type of Post instead decided to return an object, and is therefore violating the SOLID principles. If a BlogPost were passed to my_function, PHP would not complain, but ultimately fail when executing the strtoupper call in its body.

Loading history...
232
        }
233
    }
234
235
    /**
236
     * @return bool
237
     */
238
    public function isCustom()
239
    {
240
        return $this->getVar('block_type') === 'C';
241
    }
242
243
    /**
244
     * do stripslashes/htmlspecialchars according to the needed output
245
     *
246
     * @param string $format output use: S for Show and E for Edit
247
     * @param string $c_type type of block content
248
     *
249
     * @returns string
250
     */
251 View Code Duplication
    public function getContent($format = 's', $c_type = 'T')
252
    {
253
        $format = strtolower($format);
254
        $c_type = strtoupper($c_type);
255
        switch ($format) {
256
            case 's':
257
                // check the type of content
258
                // H : custom HTML block
259
                // P : custom PHP block
260
                // S : use text sanitizater (smilies enabled)
261
                // T : use text sanitizater (smilies disabled)
262
                if ($c_type === 'H') {
263
                    return str_replace('{X_SITEURL}', XOOPS_URL . '/', $this->getVar('content', 'n'));
264
                } elseif ($c_type === 'P') {
265
                    ob_start();
266
                    echo eval($this->getVar('content', 'n'));
0 ignored issues
show
Coding Style introduced by
It is generally not recommended to use eval unless absolutely required.

On one hand, eval might be exploited by malicious users if they somehow manage to inject dynamic content. On the other hand, with the emergence of faster PHP runtimes like the HHVM, eval prevents some optimization that they perform.

Loading history...
267
                    $content = ob_get_contents();
268
                    ob_end_clean();
269
270
                    return str_replace('{X_SITEURL}', XOOPS_URL . '/', $content);
271
                } elseif ($c_type === 'S') {
272
                    $myts    = MyTextSanitizer::getInstance();
273
                    $content = str_replace('{X_SITEURL}', XOOPS_URL . '/', $this->getVar('content', 'n'));
274
275
                    return $myts->displayTarea($content, 1, 1);
276
                } else {
277
                    $myts    = MyTextSanitizer::getInstance();
278
                    $content = str_replace('{X_SITEURL}', XOOPS_URL . '/', $this->getVar('content', 'n'));
279
280
                    return $myts->displayTarea($content, 1, 0);
281
                }
282
                break;
0 ignored issues
show
Unused Code introduced by
break; does not seem to be reachable.

This check looks for unreachable code. It uses sophisticated control flow analysis techniques to find statements which will never be executed.

Unreachable code is most often the result of return, die or exit statements that have been added for debug purposes.

function fx() {
    try {
        doSomething();
        return true;
    }
    catch (\Exception $e) {
        return false;
    }

    return false;
}

In the above example, the last return false will never be executed, because a return statement has already been met in every possible execution path.

Loading history...
283
            case 'e':
284
                return $this->getVar('content', 'e');
285
                break;
0 ignored issues
show
Unused Code introduced by
break is not strictly necessary here and could be removed.

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

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

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

Loading history...
286
            default:
287
                return $this->getVar('content', 'n');
288
                break;
0 ignored issues
show
Unused Code introduced by
break is not strictly necessary here and could be removed.

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

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

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

Loading history...
289
        }
290
    }
291
}
292
293
/**
294
 * System block handler class.
295
 *
296
 * This class is responsible for providing data access mechanisms to the data source
297
 * of XOOPS block class objects.
298
 *
299
 * @copyright       (c) 2000-2016 XOOPS Project (www.xoops.org)
300
 * @package             system
301
 * @subpackage          blocks
302
 */
303
class SystemBlockHandler extends XoopsPersistableObjectHandler
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...
304
{
305
    /**
306
     * @param null|XoopsDatabase $db
307
     */
308
    public function __construct(XoopsDatabase $db)
309
    {
310
        parent::__construct($db, 'newblocks', 'SystemBlock', 'bid', 'title');
311
    }
312
313
    /**
314
     * @param XoopsObject|SystemBlock $obj
315
     *
316
     * @return int|bool object id on success, otherwise false
317
     */
318 View Code Duplication
    public function insert(XoopsObject $obj, $force = true)
319
    {
320
        if (!($obj instanceof $this->className)) {
321
            return false;
322
        }
323
        $obj->setVar('last_modified', time());
324
325
        return parent::insert($obj, $force);
326
    }
327
328
    /**
329
     * retrieve array of {@link XoopsBlock}s meeting certain conditions
330
     *
331
     * @param CriteriaElement|CriteriaCompo $criteria {@link CriteriaElement} with conditions for the blocks
332
     * @param bool $id_as_key           should the blocks' bid be the key for the returned array?
333
     * @param bool $as_object           return an array of objects
334
     *
335
     * @return array {@link XoopsBlock}s matching the conditions
336
     **/
337
    public function &getObjects(CriteriaElement $criteria = null, $id_as_key = false, $as_object = true)
338
    {
339
        $ret   = array();
340
        $limit = $start = 0;
341
        $sql   = 'SELECT DISTINCT(b.bid), b.* FROM ' . $this->db->prefix('newblocks') . ' b LEFT JOIN ' . $this->db->prefix('block_module_link') . ' l ON b.bid=l.block_id';
342
        if (isset($criteria) && is_subclass_of($criteria, 'criteriaelement')) {
343
            $sql .= ' ' . $criteria->renderWhere();
0 ignored issues
show
Bug introduced by
The method renderWhere() does not exist on CriteriaElement. Did you maybe mean render()?

This check marks calls to methods that do not seem to exist on an object.

This is most likely the result of a method being renamed without all references to it being renamed likewise.

Loading history...
344
            $limit = $criteria->getLimit();
345
            $start = $criteria->getStart();
346
        }
347
        $result = $this->db->query($sql, $limit, $start);
348
        if (!$result) {
349
            return $ret;
350
        }
351
352
        if ($as_object) {
353 View Code Duplication
            while ($myrow = $this->db->fetchArray($result)) {
354
                $object = $this->create(false);
355
                $object->assignVars($myrow);
356
                if ($id_as_key) {
357
                    $ret[$myrow[$this->keyName]] = $object;
358
                } else {
359
                    $ret[] = $object;
360
                }
361
                unset($object);
362
            }
363 View Code Duplication
        } else {
364
            $object = $this->create(false);
365
            while ($myrow = $this->db->fetchArray($result)) {
366
                $object->assignVars($myrow);
367
                if ($id_as_key) {
368
                    $ret[$myrow[$this->keyName]] = $object->getValues(array_keys($myrow));
369
                } else {
370
                    $ret[] = $object->getValues(array_keys($myrow));
371
                }
372
            }
373
            unset($object);
374
        }
375
376
        return $ret;
377
    }
378
379
    /**
380
     * get all the blocks that match the supplied parameters
381
     *
382
     * @param int|int[] $groupid  groupid (can be an array)
383
     * @param bool $asobject
384
     * @param int|string $side
385
     *                            0: sideblock - left
386
     *                            1: sideblock - right
387
     *                            2: sideblock - left and right
388
     *                            3: centerblock - left
389
     *                            4: centerblock - right
390
     *                            5: centerblock - center
391
     *                            6: centerblock - left, right, center
392
     * @param           $visible  0: not visible 1: visible
393
     * @param string $orderby     order of the blocks
394
     * @param int $isactive
395
     *
396
     * @return array of block objects
397
     */
398
    public function getAllBlocksByGroup($groupid, $asobject = true, $side = null, $visible = null, $orderby = 'b.weight,b.bid', $isactive = 1)
399
    {
400
        /* @var $db XoopsMySQLDatabase  */
401
        $db  = XoopsDatabaseFactory::getDatabaseConnection();
402
        $ret = array();
403
        $sql = 'SELECT b.* ';
404
        if (!$asobject) {
405
            $sql = 'SELECT b.bid ';
406
        }
407
        $sql .= 'FROM ' . $db->prefix('newblocks') . ' b LEFT JOIN ' . $db->prefix('group_permission') . " l ON l.gperm_itemid=b.bid WHERE gperm_name = 'block_read' AND gperm_modid = 1";
408 View Code Duplication
        if (is_array($groupid)) {
409
            $sql .= ' AND (l.gperm_groupid=' . $groupid[0] . '';
410
            $size = count($groupid);
411
            if ($size > 1) {
412
                for ($i = 1; $i < $size; ++$i) {
413
                    $sql .= ' OR l.gperm_groupid=' . $groupid[$i] . '';
414
                }
415
            }
416
            $sql .= ')';
417
        } else {
418
            $sql .= ' AND l.gperm_groupid=' . $groupid . '';
419
        }
420
        $sql .= ' AND b.isactive=' . $isactive;
421
        if (isset($side)) {
422
            // get both sides in sidebox? (some themes need this)
423
            if ($side === XOOPS_SIDEBLOCK_BOTH) {
424
                $side = '(b.side=0 OR b.side=1)';
425
            } elseif ($side === XOOPS_CENTERBLOCK_ALL) {
426
                $side = '(b.side=3 OR b.side=4 OR b.side=5 OR b.side=7 OR b.side=8 OR b.side=9 )';
427
            } elseif ($side === XOOPS_FOOTERBLOCK_ALL) {
428
                $side = '(b.side=10 OR b.side=11 OR b.side=12 )';
429
            } else {
430
                $side = 'b.side=' . $side;
431
            }
432
            $sql .= ' AND ' . $side;
433
        }
434
        if (isset($visible)) {
435
            $sql .= " AND b.visible=$visible";
436
        }
437
        $sql .= " ORDER BY $orderby";
438
        $result = $db->query($sql);
0 ignored issues
show
Bug introduced by
Are you sure the assignment to $result is correct as $db->query($sql) (which targets XoopsMySQLDatabase::query()) seems to always return null.

This check looks for function or method calls that always return null and whose return value is assigned to a variable.

class A
{
    function getObject()
    {
        return null;
    }

}

$a = new A();
$object = $a->getObject();

The method getObject() can return nothing but null, so it makes no sense to assign that value to a variable.

The reason is most likely that a function or method is imcomplete or has been reduced for debug purposes.

Loading history...
439
        $added  = array();
440 View Code Duplication
        while ($myrow = $db->fetchArray($result)) {
441
            if (!in_array($myrow['bid'], $added)) {
442
                if (!$asobject) {
443
                    $ret[] = $myrow['bid'];
444
                } else {
445
                    $ret[] = new XoopsBlock($myrow);
446
                }
447
                $added[] = $myrow['bid'];
448
            }
449
        }
450
451
        return $ret;
452
    }
453
454
    /**
455
     * @param $groupid
456
     *
457
     * @return array
0 ignored issues
show
Documentation introduced by
Should the return type not be array|null?

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...
458
     */
459
    public function getBlockByPerm($groupid)
460
    {
461
        if (isset($groupid)) {
462
            $sql = 'SELECT DISTINCT gperm_itemid FROM ' . $this->db->prefix('group_permission') . " WHERE gperm_name = 'block_read' AND gperm_modid = 1";
463
            if (is_array($groupid)) {
464
                $sql .= ' AND gperm_groupid IN (' . implode(',', $groupid) . ')';
465
            } else {
466
                if ((int)$groupid > 0) {
467
                    $sql .= ' AND gperm_groupid=' . (int)$groupid;
468
                }
469
            }
470
            $result   = $this->db->query($sql);
471
            $blockids = array();
472
            while ($myrow = $this->db->fetchArray($result)) {
473
                $blockids[] = $myrow['gperm_itemid'];
474
            }
475
            if (empty($blockids)) {
476
                return $blockids;
477
            }
478
479
            return $blockids;
480
        }
481
482
        return null;
483
    }
484
485
    /**
486
     * @param        $groupid
487
     * @param int $module_id
488
     * @param bool $toponlyblock
489
     * @param null $visible
490
     * @param string $orderby
491
     * @param int $isactive
492
     *
493
     * @return array
494
     */
495 View Code Duplication
    public function getAllByGroupModule($groupid, $module_id = 0, $toponlyblock = false, $visible = null, $orderby = 'b.weight, m.block_id', $isactive = 1)
496
    {
497
        $isactive = (int)$isactive;
498
        $db       = $GLOBALS['xoopsDB'];
499
        $ret      = array();
500
        if (isset($groupid)) {
501
            $sql = 'SELECT DISTINCT gperm_itemid FROM ' . $db->prefix('group_permission') . " WHERE gperm_name = 'block_read' AND gperm_modid = 1";
502
            if (is_array($groupid)) {
503
                $sql .= ' AND gperm_groupid IN (' . implode(',', $groupid) . ')';
504
            } else {
505
                if ((int)$groupid > 0) {
506
                    $sql .= ' AND gperm_groupid=' . (int)$groupid;
507
                }
508
            }
509
            $result   = $db->query($sql);
510
            $blockids = array();
511
            while ($myrow = $db->fetchArray($result)) {
512
                $blockids[] = $myrow['gperm_itemid'];
513
            }
514
            if (empty($blockids)) {
515
                return $blockids;
516
            }
517
        }
518
        $sql = 'SELECT b.* FROM ' . $db->prefix('newblocks') . ' b, ' . $db->prefix('block_module_link') . ' m WHERE m.block_id=b.bid';
519
        $sql .= ' AND b.isactive=' . $isactive;
520
        if (isset($visible)) {
521
            $sql .= ' AND b.visible=' . (int)$visible;
522
        }
523
        if (!isset($module_id)) {
0 ignored issues
show
Unused Code introduced by
This if statement is empty and can be removed.

This check looks for the bodies of if statements that have no statements or where all statements have been commented out. This may be the result of changes for debugging or the code may simply be obsolete.

These if bodies can be removed. If you have an empty if but statements in the else branch, consider inverting the condition.

if (rand(1, 6) > 3) {
//print "Check failed";
} else {
    print "Check succeeded";
}

could be turned into

if (rand(1, 6) <= 3) {
    print "Check succeeded";
}

This is much more concise to read.

Loading history...
524
        } elseif (!empty($module_id)) {
525
            $sql .= ' AND m.module_id IN (0,' . (int)$module_id;
526
            if ($toponlyblock) {
527
                $sql .= ',-1';
528
            }
529
            $sql .= ')';
530
        } else {
531
            if ($toponlyblock) {
532
                $sql .= ' AND m.module_id IN (0,-1)';
533
            } else {
534
                $sql .= ' AND m.module_id=0';
535
            }
536
        }
537
        if (!empty($blockids)) {
538
            $sql .= ' AND b.bid IN (' . implode(',', $blockids) . ')';
539
        }
540
        $sql .= ' ORDER BY ' . $orderby;
541
        $result = $db->query($sql);
542
        while ($myrow = $db->fetchArray($result)) {
543
            $block              = new XoopsBlock($myrow);
544
            $ret[$myrow['bid']] =& $block;
545
            unset($block);
546
        }
547
548
        return $ret;
549
    }
550
551
    /**
552
     * @param int $module_id
553
     * @param bool $toponlyblock
554
     * @param null $visible
555
     * @param string $orderby
556
     * @param int $isactive
557
     *
558
     * @return array
559
     */
560 View Code Duplication
    public function getNonGroupedBlocks($module_id = 0, $toponlyblock = false, $visible = null, $orderby = 'b.weight, m.block_id', $isactive = 1)
561
    {
562
        $db   = $GLOBALS['xoopsDB'];
563
        $ret  = array();
564
        $bids = array();
565
        $sql  = 'SELECT DISTINCT(bid) from ' . $db->prefix('newblocks');
566
        if ($result = $db->query($sql)) {
567
            while ($myrow = $db->fetchArray($result)) {
568
                $bids[] = $myrow['bid'];
569
            }
570
        }
571
        $sql     = 'SELECT DISTINCT(p.gperm_itemid) from ' . $db->prefix('group_permission') . ' p, ' . $db->prefix('groups') . " g WHERE g.groupid=p.gperm_groupid AND p.gperm_name='block_read'";
572
        $grouped = array();
573
        if ($result = $db->query($sql)) {
574
            while ($myrow = $db->fetchArray($result)) {
575
                $grouped[] = $myrow['gperm_itemid'];
576
            }
577
        }
578
        $non_grouped = array_diff($bids, $grouped);
579
        if (!empty($non_grouped)) {
580
            $sql = 'SELECT b.* FROM ' . $db->prefix('newblocks') . ' b, ' . $db->prefix('block_module_link') . ' m WHERE m.block_id=b.bid';
581
            $sql .= ' AND b.isactive=' . (int)$isactive;
582
            if (isset($visible)) {
583
                $sql .= ' AND b.visible=' . (int)$visible;
584
            }
585
            if (!isset($module_id)) {
0 ignored issues
show
Unused Code introduced by
This if statement is empty and can be removed.

This check looks for the bodies of if statements that have no statements or where all statements have been commented out. This may be the result of changes for debugging or the code may simply be obsolete.

These if bodies can be removed. If you have an empty if but statements in the else branch, consider inverting the condition.

if (rand(1, 6) > 3) {
//print "Check failed";
} else {
    print "Check succeeded";
}

could be turned into

if (rand(1, 6) <= 3) {
    print "Check succeeded";
}

This is much more concise to read.

Loading history...
586
            } elseif (!empty($module_id)) {
587
                $sql .= ' AND m.module_id IN (0,' . (int)$module_id;
588
                if ($toponlyblock) {
589
                    $sql .= ',-1';
590
                }
591
                $sql .= ')';
592
            } else {
593
                if ($toponlyblock) {
594
                    $sql .= ' AND m.module_id IN (0,-1)';
595
                } else {
596
                    $sql .= ' AND m.module_id=0';
597
                }
598
            }
599
            $sql .= ' AND b.bid IN (' . implode(',', $non_grouped) . ')';
600
            $sql .= ' ORDER BY ' . $orderby;
601
            $result = $db->query($sql);
602
            while ($myrow = $db->fetchArray($result)) {
603
                $block              = new XoopsBlock($myrow);
604
                $ret[$myrow['bid']] =& $block;
605
                unset($block);
606
            }
607
        }
608
609
        return $ret;
610
    }
611
612
    /**
613
     * XoopsBlock::countSimilarBlocks()
614
     *
615
     * @param  mixed $moduleId
616
     * @param  mixed $funcNum
617
     * @param  mixed $showFunc
618
     * @return int
619
     */
620 View Code Duplication
    public function countSimilarBlocks($moduleId, $funcNum, $showFunc = null)
621
    {
622
        $funcNum  = (int)$funcNum;
623
        $moduleId = (int)$moduleId;
624
        if ($funcNum < 1 || $moduleId < 1) {
625
            // invalid query
626
            return 0;
627
        }
628
        /* @var $db XoopsMySQLDatabase  */
629
        $db = XoopsDatabaseFactory::getDatabaseConnection();
630
        if (isset($showFunc)) {
631
            // showFunc is set for more strict comparison
632
            $sql = sprintf('SELECT COUNT(*) FROM %s WHERE mid = %d AND func_num = %d AND show_func = %s', $db->prefix('newblocks'), $moduleId, $funcNum, $db->quoteString(trim($showFunc)));
633
        } else {
634
            $sql = sprintf('SELECT COUNT(*) FROM %s WHERE mid = %d AND func_num = %d', $db->prefix('newblocks'), $moduleId, $funcNum);
635
        }
636
        if (!$result = $db->query($sql)) {
0 ignored issues
show
Bug introduced by
Are you sure the assignment to $result is correct as $db->query($sql) (which targets XoopsMySQLDatabase::query()) seems to always return null.

This check looks for function or method calls that always return null and whose return value is assigned to a variable.

class A
{
    function getObject()
    {
        return null;
    }

}

$a = new A();
$object = $a->getObject();

The method getObject() can return nothing but null, so it makes no sense to assign that value to a variable.

The reason is most likely that a function or method is imcomplete or has been reduced for debug purposes.

Loading history...
637
            return 0;
638
        }
639
        list($count) = $db->fetchRow($result);
640
641
        return $count;
642
    }
643
}
644