Completed
Push — master ( 6452b0...d576ea )
by Michael
05:58 queued 03:02
created

MyXoopsTree::__construct()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 8
Code Lines 6

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
c 1
b 0
f 0
dl 0
loc 8
rs 9.4285
cc 1
eloc 6
nc 1
nop 3
1
<?php
2
/**
3
 * XOOPS tree handler
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       XOOPS Project (http://xoops.org)
13
 * @license         GNU GPL 2 (http://www.gnu.org/licenses/old-licenses/gpl-2.0.html)
14
 * @package         kernel
15
 * @since           2.0.0
16
 * @author          Kazumi Ono (AKA onokazu) http://www.myweb.ne.jp/, http://jp.xoops.org/
17
 */
18
19
// defined('XOOPS_ROOT_PATH') || exit('XOOPS root path not defined');
0 ignored issues
show
Unused Code Comprehensibility introduced by
70% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
20
21
/**
22
 * Abstract base class for forms
23
 *
24
 * @author     Kazumi Ono <[email protected]>
25
 * @author     John Neill <[email protected]>
26
 * @copyright  copyright (c) XOOPS.org
27
 * @package    kernel
28
 * @subpackage XoopsTree
29
 * @access     public
30
 */
31
class MyXoopsTree
0 ignored issues
show
Coding Style Compatibility introduced by
PSR1 recommends that each class must be in a namespace of at least one level to avoid collisions.

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

namespace YourVendor;

class YourClass { }

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

Loading history...
32
{
33
    public $table; //table with parent-child structure
34
    public $id; //name of unique id for records in table $table
35
    public $pid; // name of parent id used in table $table
36
    public $order; //specifies the order of query results
37
    public $title; // name of a field in table $table which will be used when  selection box and paths are generated
38
    public $db;
39
40
    //constructor of class XoopsTree
41
    //sets the names of table, unique id, and parend id
42
    /**
43
     * @param $table_name
44
     * @param $id_name
45
     * @param $pid_name
46
     */
47
    public function __construct($table_name, $id_name, $pid_name)
0 ignored issues
show
Coding Style introduced by
__construct 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...
48
    {
49
        $GLOBALS['xoopsLogger']->addDeprecated("Class '" . __CLASS__ . "' is deprecated, check 'XoopsObjectTree' in tree.php");
50
        $this->db = XoopsDatabaseFactory::getDatabaseConnection();
51
        $this->table = $table_name;
52
        $this->id    = $id_name;
53
        $this->pid   = $pid_name;
54
    }
55
56
    // returns an array of first child objects for a given id($sel_id)
57
    /**
58
     * @param        $sel_id
59
     * @param string $order
60
     *
61
     * @return array
62
     */
63
    public function getFirstChild($sel_id, $order = '')
64
    {
65
        $sel_id = (int)$sel_id;
66
        $arr    = array();
67
        $sql    = 'SELECT * FROM ' . $this->table . ' WHERE ' . $this->pid . '=' . $sel_id . '';
68
        if ($order != '') {
69
            $sql .= " ORDER BY $order";
70
        }
71
        $result = $this->db->query($sql);
72
        $count  = $this->db->getRowsNum($result);
73
        if ($count == 0) {
74
            return $arr;
75
        }
76
        while ($myrow = $this->db->fetchArray($result)) {
77
            array_push($arr, $myrow);
78
        }
79
80
        return $arr;
81
    }
82
83
    // returns an array of all FIRST child ids of a given id($sel_id)
84
    /**
85
     * @param $sel_id
86
     *
87
     * @return array
88
     */
89
    public function getFirstChildId($sel_id)
90
    {
91
        $sel_id  = (int)$sel_id;
92
        $idarray = array();
93
        $result  = $this->db->query('SELECT ' . $this->id . ' FROM ' . $this->table . ' WHERE ' . $this->pid . '=' . $sel_id . '');
94
        $count   = $this->db->getRowsNum($result);
95
        if ($count == 0) {
96
            return $idarray;
97
        }
98
        while (list($id) = $this->db->fetchRow($result)) {
99
            array_push($idarray, $id);
100
        }
101
102
        return $idarray;
103
    }
104
105
    //returns an array of ALL child ids for a given id($sel_id)
106
    /**
107
     * @param        $sel_id
108
     * @param string $order
109
     * @param array  $idarray
110
     *
111
     * @return array
112
     */
113 View Code Duplication
    public function getAllChildId($sel_id, $order = '', $idarray = array())
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...
114
    {
115
        $sel_id = (int)$sel_id;
116
        $sql    = 'SELECT ' . $this->id . ' FROM ' . $this->table . ' WHERE ' . $this->pid . '=' . $sel_id . '';
117
        if ($order != '') {
118
            $sql .= " ORDER BY $order";
119
        }
120
        $result = $this->db->query($sql);
121
        $count  = $this->db->getRowsNum($result);
122
        if ($count == 0) {
123
            return $idarray;
124
        }
125
        while (list($r_id) = $this->db->fetchRow($result)) {
126
            array_push($idarray, $r_id);
127
            $idarray = $this->getAllChildId($r_id, $order, $idarray);
128
        }
129
130
        return $idarray;
131
    }
132
133
    //returns an array of ALL parent ids for a given id($sel_id)
134
    /**
135
     * @param        $sel_id
136
     * @param string $order
137
     * @param array  $idarray
138
     *
139
     * @return array
140
     */
141 View Code Duplication
    public function getAllParentId($sel_id, $order = '', $idarray = array())
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...
142
    {
143
        $sel_id = (int)$sel_id;
144
        $sql    = 'SELECT ' . $this->pid . ' FROM ' . $this->table . ' WHERE ' . $this->id . '=' . $sel_id . '';
145
        if ($order != '') {
146
            $sql .= " ORDER BY $order";
147
        }
148
        $result = $this->db->query($sql);
149
        list($r_id) = $this->db->fetchRow($result);
150
        if ($r_id == 0) {
151
            return $idarray;
152
        }
153
        array_push($idarray, $r_id);
154
        $idarray = $this->getAllParentId($r_id, $order, $idarray);
155
156
        return $idarray;
157
    }
158
159
    //generates path from the root id to a given id($sel_id)
160
    // the path is delimetered with "/"
161
    /**
162
     * @param        $sel_id
163
     * @param        $title
164
     * @param string $path
165
     *
166
     * @return string
167
     */
168
    public function getPathFromId($sel_id, $title, $path = '')
169
    {
170
        $sel_id = (int)$sel_id;
171
        $result = $this->db->query('SELECT ' . $this->pid . ', ' . $title . ' FROM ' . $this->table . ' WHERE ' . $this->id . "=$sel_id");
172
        if ($this->db->getRowsNum($result) == 0) {
173
            return $path;
174
        }
175
        list($parentid, $name) = $this->db->fetchRow($result);
176
        $myts = &MyTextSanitizer::getInstance();
177
        $name = $myts->htmlspecialchars($name);
178
        $path = '/' . $name . $path . '';
179
        if ($parentid == 0) {
180
            return $path;
181
        }
182
        $path = $this->getPathFromId($parentid, $title, $path);
183
184
        return $path;
185
    }
186
187
    //makes a nicely ordered selection box
188
    //$preset_id is used to specify a preselected item
189
    //set $none to 1 to add a option with value 0
190
    /**
191
     * @param        $title
192
     * @param string $order
193
     * @param int    $preset_id
194
     * @param int    $none
195
     * @param string $sel_name
196
     * @param string $onchange
197
     */
198
    public function makeMySelBox($title, $order = '', $preset_id = 0, $none = 0, $sel_name = '', $onchange = '')
199
    {
200
        if ($sel_name == '') {
201
            $sel_name = $this->id;
202
        }
203
        $myts = &MyTextSanitizer::getInstance();
204
        echo "<select name='" . $sel_name . "'";
205
        if ($onchange != '') {
206
            echo " onchange='" . $onchange . "'";
207
        }
208
        echo ">\n";
209
        $sql = 'SELECT ' . $this->id . ', ' . $title . ' FROM ' . $this->table . ' WHERE ' . $this->pid . '=0';
210
        if ($order != '') {
211
            $sql .= " ORDER BY $order";
212
        }
213
        $result = $this->db->query($sql);
214
        if ($none) {
215
            echo "<option value='0'>----</option>\n";
216
        }
217
        while (list($catid, $name) = $this->db->fetchRow($result)) {
218
            $sel = '';
219
            if ($catid == $preset_id) {
220
                $sel = " selected='selected'";
221
            }
222
            echo "<option value='$catid'$sel>$name</option>\n";
223
            $sel = '';
224
            $arr = $this->getChildTreeArray($catid, $order);
225
            foreach ($arr as $option) {
226
                $option['prefix'] = str_replace('.', '--', $option['prefix']);
227
                $catpath          = $option['prefix'] . '&nbsp;' . $myts->htmlspecialchars($option[$title]);
228
                if ($option[$this->id] == $preset_id) {
229
                    $sel = " selected='selected'";
230
                }
231
                echo "<option value='" . $option[$this->id] . "'$sel>$catpath</option>\n";
232
                $sel = '';
233
            }
234
        }
235
        echo "</select>\n";
236
    }
237
238
    //generates nicely formatted linked path from the root id to a given id
239
    /**
240
     * @param        $sel_id
241
     * @param        $title
242
     * @param        $funcURL
243
     * @param string $path
244
     *
245
     * @return string
246
     */
247
    public function getNicePathFromId($sel_id, $title, $funcURL, $path = '')
248
    {
249
        $path   = !empty($path) ? '&nbsp;:&nbsp;' . $path : $path;
250
        $sel_id = (int)$sel_id;
251
        $sql    = 'SELECT ' . $this->pid . ', ' . $title . ' FROM ' . $this->table . ' WHERE ' . $this->id . "=$sel_id";
252
        $result = $this->db->query($sql);
253
        if ($this->db->getRowsNum($result) == 0) {
254
            return $path;
255
        }
256
        list($parentid, $name) = $this->db->fetchRow($result);
257
        $myts = &MyTextSanitizer::getInstance();
258
        $name = $myts->htmlspecialchars($name);
259
        $path = "<a href='" . $funcURL . '&amp;' . $this->id . '=' . $sel_id . "'>" . $name . '</a>' . $path . '';
260
        if ($parentid == 0) {
261
            return $path;
262
        }
263
        $path = $this->getNicePathFromId($parentid, $title, $funcURL, $path);
264
265
        return $path;
266
    }
267
268
    //generates id path from the root id to a given id
269
    // the path is delimetered with "/"
270
    /**
271
     * @param        $sel_id
272
     * @param string $path
273
     *
274
     * @return string
275
     */
276
    public function getIdPathFromId($sel_id, $path = '')
277
    {
278
        $sel_id = (int)$sel_id;
279
        $result = $this->db->query('SELECT ' . $this->pid . ' FROM ' . $this->table . ' WHERE ' . $this->id . "=$sel_id");
280
        if ($this->db->getRowsNum($result) == 0) {
281
            return $path;
282
        }
283
        list($parentid) = $this->db->fetchRow($result);
284
        $path = '/' . $sel_id . $path . '';
285
        if ($parentid == 0) {
286
            return $path;
287
        }
288
        $path = $this->getIdPathFromId($parentid, $path);
289
290
        return $path;
291
    }
292
293
    /**
294
     * Enter description here...
295
     *
296
     * @param int|\unknown_type    $sel_id
297
     * @param string|\unknown_type $order
298
     * @param array|\unknown_type  $parray
299
     *
300
     * @return unknown
301
     */
302 View Code Duplication
    public function getAllChild($sel_id = 0, $order = '', $parray = array())
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...
303
    {
304
        $sel_id = (int)$sel_id;
305
        $sql    = 'SELECT * FROM ' . $this->table . ' WHERE ' . $this->pid . '=' . $sel_id . '';
306
        if ($order != '') {
307
            $sql .= " ORDER BY $order";
308
        }
309
        $result = $this->db->query($sql);
310
        $count  = $this->db->getRowsNum($result);
311
        if ($count == 0) {
312
            return $parray;
0 ignored issues
show
Bug Best Practice introduced by
The return type of return $parray; (array|unknown_type) is incompatible with the return type documented by MyXoopsTree::getAllChild of type unknown.

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...
313
        }
314
        while ($row = $this->db->fetchArray($result)) {
315
            array_push($parray, $row);
316
            $parray = $this->getAllChild($row[$this->id], $order, $parray);
317
        }
318
319
        return $parray;
320
    }
321
322
    /**
323
     * Enter description here...
324
     *
325
     * @param int|\unknown_type    $sel_id
326
     * @param string|\unknown_type $order
327
     * @param array|\unknown_type  $parray
328
     * @param string|\unknown_type $r_prefix
329
     *
330
     * @return unknown
331
     */
332
    public function getChildTreeArray($sel_id = 0, $order = '', $parray = array(), $r_prefix = '')
333
    {
334
        $sel_id = (int)$sel_id;
335
        $sql    = 'SELECT * FROM ' . $this->table . ' WHERE ' . $this->pid . '=' . $sel_id . '';
336
        if ($order != '') {
337
            $sql .= " ORDER BY $order";
338
        }
339
        $result = $this->db->query($sql);
340
        $count  = $this->db->getRowsNum($result);
341
        if ($count == 0) {
342
            return $parray;
0 ignored issues
show
Bug Best Practice introduced by
The return type of return $parray; (array|unknown_type) is incompatible with the return type documented by MyXoopsTree::getChildTreeArray of type unknown.

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...
343
        }
344 View Code Duplication
        while ($row = $this->db->fetchArray($result)) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
345
            $row['prefix'] = $r_prefix . '.';
346
            array_push($parray, $row);
347
            $parray = $this->getChildTreeArray($row[$this->id], $order, $parray, $row['prefix']);
348
        }
349
350
        return $parray;
351
    }
352
}
353