ReferencesReferences_categoriesHandler   A
last analyzed

Complexity

Total Complexity 16

Size/Duplication

Total Lines 135
Duplicated Lines 33.33 %

Coupling/Cohesion

Components 1
Dependencies 4

Importance

Changes 0
Metric Value
dl 45
loc 135
rs 10
c 0
b 0
f 0
wmc 16
lcom 1
cbo 4

7 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 4 1
B getPermissionsCategoriesCriteria() 5 23 7
A getCategories() 11 12 1
A getListArray() 11 12 1
A getCategoriesSelect() 0 13 2
A notifyNewCategory() 7 7 1
A userCanSeeCategory() 11 12 3

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
2
/**
3
 * ****************************************************************************
4
 * references - MODULE FOR XOOPS
5
 * Copyright (c) Hervé Thouzard of Instant Zero (http://www.instant-zero.com)
6
 *
7
 * You may not change or alter any portion of this comment or credits
8
 * of supporting developers from this source code or any supporting source code
9
 * which is considered copyrighted (c) material of the original comment or credit authors.
10
 * This program is distributed in the hope that it will be useful,
11
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
13
 *
14
 * @copyright       Hervé Thouzard of Instant Zero (http://www.instant-zero.com)
15
 * @license         http://www.fsf.org/copyleft/gpl.html GNU public license
16
 * @package         references
17
 * @author          Hervé Thouzard of Instant Zero (http://www.instant-zero.com)
18
 *
19
 * ****************************************************************************
20
 */
21
defined('XOOPS_ROOT_PATH') || exit('XOOPS root path not defined');
22
23
require_once XOOPS_ROOT_PATH . '/kernel/object.php';
24
if (!class_exists('references_XoopsPersistableObjectHandler')) {
25
    require_once XOOPS_ROOT_PATH . '/modules/references/class/PersistableObjectHandler.php';
26
}
27
28
class references_categories extends references_Object
29
{
30
    public function __construct()
31
    {
32
        $this->initVar('category_id', XOBJ_DTYPE_INT, null, false);
33
        $this->initVar('category_title', XOBJ_DTYPE_TXTBOX, null, false);
34
        $this->initVar('category_weight', XOBJ_DTYPE_INT, null, false);
35
        $this->initVar('category_description', XOBJ_DTYPE_TXTAREA, null, false);
36
        // Pour autoriser le html
37
        $this->initVar('dohtml', XOBJ_DTYPE_INT, 1, false);
38
    }
39
40
    /**
41
     * Retourne la chaine de caractères qui peut être utilisée dans l'attribut href d'une balise html A.
42
     *
43
     * @return string
44
     */
45
    public function getHrefTitle()
46
    {
47
        return references_utils::makeHrefTitle($this->getVar('category_title'));
48
    }
49
50
    /**
51
     * Retourne l'url à utiliser pour atteindre la catégorie
52
     *
53
     * @param bool $shortVersion
54
     * @return string
55
     */
56 View Code Duplication
    public function getUrl($shortVersion = false)
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...
57
    {
58
        if (!$shortVersion) {
59
            return REFERENCES_URL . 'category.php?category_id=' . $this->getVar('category_id');
60
        } else {
61
            return 'category.php?category_id=' . $this->getVar('category_id');
62
        }
63
    }
64
65
    /**
66
     * Retourne les éléments de l'annnonce formatés pour affichage
67
     *
68
     * @param string $format Format à utiliser
69
     * @return array
70
     */
71
    public function toArray($format = 's')
72
    {
73
        $ret                          = array();
0 ignored issues
show
Unused Code introduced by
$ret is not used, you could remove the assignment.

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

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

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

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

Loading history...
74
        $ret                          = parent::toArray($format);
75
        $ret['category_href_title']   = $this->getHrefTitle();
76
        $ret['category_url_rewrited'] = $this->getUrl();
77
78
        return $ret;
79
    }
80
}
81
82
class ReferencesReferences_categoriesHandler extends references_XoopsPersistableObjectHandler
83
{
84
    public function __construct($db)
85
    {    //                         Table                   Classe                    Id                Descr.
86
        parent::__construct($db, 'references_categories', 'references_categories', 'category_id', 'category_title');
87
    }
88
89
    /**
90
     * Retourne le crit�re � utiliser pour voir les cat�gories en respectant les permissions
91
     *
92
     * @param  string $permissionsType Type de permission (pour l'instant permission de voir)
93
     * @return obejct de type Criteria
94
     */
95
    public function getPermissionsCategoriesCriteria($permissionsType = REFERENCES_PERM_READ)
96
    {
97
        global $xoopsUser;
98
        static $permissions = array();
99
        if (references_utils::isAdmin()) {
100
            return new Criteria('category_id', '0', '>');
0 ignored issues
show
Bug Best Practice introduced by
The return type of return new \Criteria('category_id', '0', '>'); (Criteria) is incompatible with the return type documented by ReferencesReferences_cat...sionsCategoriesCriteria of type obejct.

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...
101
        }
102
        if (is_array($permissions) && array_key_exists($permissionsType, $permissions)) {
103
            return $permissions[$permissionsType];
104
        }
105
        $categories    = array();
0 ignored issues
show
Unused Code introduced by
$categories 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...
106
        $currentModule = references_utils::getModule();
107
        $groups        = is_object($xoopsUser) ? $xoopsUser->getGroups() : XOOPS_GROUP_ANONYMOUS;
108
        $gperm_handler = xoops_getHandler('groupperm');
109
        $categories    = $gperm_handler->getItemIds($permissionsType, $groups, $currentModule->getVar('mid'));
110 View Code Duplication
        if (is_array($categories) && count($categories) > 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...
111
            $permissions[$permissionsType] = new Criteria('category_id', '(' . implode(',', $categories) . ')', 'IN');
112
        } else {    // Ne peut rien voir
113
            $permissions[$permissionsType] = new Criteria('category_id', '0', '=');
114
        }
115
116
        return $permissions[$permissionsType];
0 ignored issues
show
Bug Best Practice introduced by
The return type of return $permissions[$permissionsType]; (Criteria) is incompatible with the return type documented by ReferencesReferences_cat...sionsCategoriesCriteria of type obejct.

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...
117
    }
118
119
    /**
120
     * Retourne les catégories
121
     *
122
     * @param integer $start Indice de début
123
     * @param integer $limit Nombre d'objets à renvoyer
124
     * @param  string $sort  Zone de tri
125
     * @param  string $order Sens du tri
126
     * @return array   Objets de type references_categories
0 ignored issues
show
Documentation introduced by
Should the return type not be array|string?

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...
127
     */
128 View Code Duplication
    public function getCategories($start = 0, $limit = 0, $sort = 'category_weight', $order = 'ASC')
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...
129
    {
130
        $criteria = new CriteriaCompo();
131
        $criteria->add(new Criteria('category_id', 0, '<>'));
132
        $criteria->add($this->getPermissionsCategoriesCriteria());
133
        $criteria->setStart($start);
134
        $criteria->setSort($sort);
135
        $criteria->setOrder($order);
136
        $criteria->setLimit($limit);
137
138
        return $this->getObjects($criteria, true);
139
    }
140
141
    /**
142
     * Retourne la liste des catégories en tant que tableau
143
     * @param integer $start Position de départ
144
     * @param integer $limit Nombre maximum d'objets à retourner
145
     * @param  string $sort  ordre de tri
146
     * @param  string $order Sens du tri
147
     * @return array
0 ignored issues
show
Documentation introduced by
Should the return type not be array|string?

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...
148
     */
149 View Code Duplication
    public function getListArray($start = 0, $limit = 0, $sort = 'category_weight', $order = 'ASC')
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...
150
    {
151
        $criteria = new CriteriaCompo();
152
        $criteria->add(new Criteria('category_id', 0, '<>'));
153
        $criteria->add($this->getPermissionsCategoriesCriteria());
154
        $criteria->setStart($start);
155
        $criteria->setSort($sort);
156
        $criteria->setOrder($order);
157
        $criteria->setLimit($limit);
158
159
        return $this->getList($criteria);
160
    }
161
162
    /**
163
     * Retourne le sélecteur à utiliser pour voir la liste des catégies
164
     *
165
     * @param string  $selectName Le nom du sélecteur
166
     * @param integer $selected   L'élément sélectionné
167
     * @return string
168
     */
169
    public function getCategoriesSelect($selectName = 'categoriesSelect', $selected = 0)
170
    {
171
        $categories = array();
0 ignored issues
show
Unused Code introduced by
$categories 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...
172
        $ret        = '';
173
        $categories = $this->getListArray(0, 0, 'category_weight ASC, category_title', 'ASC');
174
        if (count($categories) == 0) {
175
            return $ret;
176
        }
177
        $jump  = REFERENCES_URL . 'category.php?category_id=';
178
        $extra = " onchange='location=\"" . $jump . "\"+this.options[this.selectedIndex].value'";
179
180
        return references_utils::htmlSelect($selectName, $categories, $selected, true, '', false, 1, $extra);
0 ignored issues
show
Bug introduced by
It seems like $categories defined by $this->getListArray(0, 0...category_title', 'ASC') on line 173 can also be of type string; however, references_utils::htmlSelect() does only seem to accept array, maybe add an additional type check?

If a method or function can return multiple different values and unless you are sure that you only can receive a single value in this context, we recommend to add an additional type check:

/**
 * @return array|string
 */
function returnsDifferentValues($x) {
    if ($x) {
        return 'foo';
    }

    return array();
}

$x = returnsDifferentValues($y);
if (is_array($x)) {
    // $x is an array.
}

If this a common case that PHP Analyzer should handle natively, please let us know by opening an issue.

Loading history...
181
    }
182
183
    /**
184
     * Notification de la création d'une nouvelle catégorie
185
     *
186
     * @param object|references_categories $category
187
     * @return bool
188
     */
189 View Code Duplication
    public function notifyNewCategory(references_categories $category)
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...
190
    {
191
        $plugins = references_plugins::getInstance();
192
        $plugins->fireAction(references_plugins::EVENT_ON_CATEGORY_CREATE, new references_parameters(array('category' => $category)));
193
194
        return true;
195
    }
196
197
    /**
198
     * Indique si une catégorie est visible d'un utilisateur
199
     *
200
     * @param object|references_categories $category La catégorie à controler
201
     * @param integer                      $uid      L'id de l'utilisateur à controler
202
     * @return bool
203
     */
204 View Code Duplication
    public function userCanSeeCategory(references_categories $category, $uid = 0)
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...
205
    {
206
        global $xoopsUser;
207
        if ($uid == 0) {
208
            $uid = references_utils::getCurrentUserID();
209
        }
210
        $currentModule = references_utils::getModule();
211
        $groups        = is_object($xoopsUser) ? $xoopsUser->getGroups() : XOOPS_GROUP_ANONYMOUS;
0 ignored issues
show
Unused Code introduced by
$groups 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...
212
        $gperm_handler = xoops_getHandler('groupperm');
213
214
        return $gperm_handler->checkRight(REFERENCES_PERM_READ, $category->category_id, references_utils::getMemberGroups($uid), $currentModule->getVar('mid'));
215
    }
216
}
217