Completed
Push — master ( 47719d...a5b475 )
by
unknown
03:14
created

Language   A

Complexity

Total Complexity 12

Size/Duplication

Total Lines 122
Duplicated Lines 5.74 %

Coupling/Cohesion

Components 1
Dependencies 0

Test Coverage

Coverage 0%

Importance

Changes 0
Metric Value
wmc 12
lcom 1
cbo 0
dl 7
loc 122
ccs 0
cts 40
cp 0
rs 10
c 0
b 0
f 0

3 Methods

Rating   Name   Duplication   Size   Complexity  
B getLanguageDatabase() 0 31 4
A getLanguageRedis() 7 17 4
B setLanguageRedis() 0 26 4

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
 * This file is part of the PhpBotFramework.
5
 *
6
 * PhpBotFramework is free software: you can redistribute it and/or modify
7
 * it under the terms of the GNU Lesser General Public License as
8
 * published by the Free Software Foundation, version 3.
9
 *
10
 * PhpBotFramework is distributed in the hope that it will be useful, but
11
 * WITHOUT ANY WARRANTY; without even the implied warranty of
12
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13
 * Lesser General Public License for more details.
14
 *
15
 * You should have received a copy of the GNU Lesser General Public License
16
 * along with this program. If not, see <http://www.gnu.org/licenses/>.
17
 */
18
19
namespace PhpBotFramework\Localization;
20
21
trait Language
22
{
23
24
    /**
25
     * \addtogroup Localization Localization
26
     * @{
27
     */
28
29
    /** \brief Stores the language for a multi-language bot */
30
    public $language;
31
32
    /** PDO connection to the database. */
33
    public $pdo;
34
35
    /** \brief Table containing bot users data into database. */
36
    public $user_table = '"User"';
37
38
    /** \brief Name of the column that represents the user ID into database */
39
    public $id_column = 'chat_id';
40
41
    /**
42
     * \brief Get current user's language from the database, and set it in $language.
43
     * @param $default_language <i>Optional</i>. Default language to return in case of errors.
44
     * @return Language set for the current user, $default_language on errors.
0 ignored issues
show
Comprehensibility Bug introduced by
The return type Language is a trait, and thus cannot be used for type-hinting in PHP. Maybe consider adding an interface and use that for type-hinting?

In PHP traits cannot be used for type-hinting as they do not define a well-defined structure. This is because any class that uses a trait can rename that trait’s methods.

If you would like to return an object that has a guaranteed set of methods, you could create a companion interface that lists these methods explicitly.

Loading history...
45
     */
46
    public function getLanguageDatabase($default_language = 'en')
47
    {
48
        // If we have no database
49
        if (!isset($this->_database)) {
50
            $this->language = $default_language;
51
            return $default_language;
52
        }
53
54
        // Get the language from the bot
55
        $sth = $this->pdo->prepare('SELECT language FROM ' . $this->user_table . ' WHERE '
56
                                                           . $this->id_column . ' = :chat_id');
57
        $sth->bindParam(':chat_id', $this->_chat_id);
0 ignored issues
show
Bug introduced by
The property _chat_id does not exist. Did you maybe forget to declare it?

In PHP it is possible to write to properties without declaring them. For example, the following is perfectly valid PHP code:

class MyClass { }

$x = new MyClass();
$x->foo = true;

Generally, it is a good practice to explictly declare properties to avoid accidental typos and provide IDE auto-completion:

class MyClass {
    public $foo;
}

$x = new MyClass();
$x->foo = true;
Loading history...
58
59
        try {
60
            $sth->execute();
61
        } catch (PDOException $e) {
0 ignored issues
show
Bug introduced by
The class PhpBotFramework\Localization\PDOException does not exist. Did you forget a USE statement, or did you not list all dependencies?

Scrutinizer analyzes your composer.json/composer.lock file if available to determine the classes, and functions that are defined by your dependencies.

It seems like the listed class was neither found in your dependencies, nor was it found in the analyzed files in your repository. If you are using some other form of dependency management, you might want to disable this analysis.

Loading history...
62
            echo $e->getMessage();
63
        }
64
65
        $row = $sth->fetch();
66
        $sth = null;
0 ignored issues
show
Unused Code introduced by
$sth 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...
67
68
        if (isset($row['language'])) {
69
            $this->language = $row['language'];
70
            return $row['language'];
71
        }
72
73
        // If we couldn't get it, set the language to the default one
74
        $this->language = $default_language;
75
        return $this->language;
76
    }
77
78
    /**
79
     * \brief Get current user language from Redis (as a cache) and set it in language.
80
     * \details Using Redis as cache, check for the language. On failure, get the language
81
     * from the database and store it (with default expiring time of one day) in Redis.
82
     *
83
     * It also change $language parameter of the bot to the language returned.
84
     * @param $default_language <i>Optional</i>. Default language to return in case of errors.
85
     * @param $expiring_time <i>Optional</i>. Set the expiring time for the language on
86
     * redis each time it is took from the sql database.
87
     * @return Language for the current user, $default_language on errors.
0 ignored issues
show
Comprehensibility Bug introduced by
The return type Language is a trait, and thus cannot be used for type-hinting in PHP. Maybe consider adding an interface and use that for type-hinting?

In PHP traits cannot be used for type-hinting as they do not define a well-defined structure. This is because any class that uses a trait can rename that trait’s methods.

If you would like to return an object that has a guaranteed set of methods, you could create a companion interface that lists these methods explicitly.

Loading history...
88
     */
89
    public function getLanguageRedis($default_language = 'en', $expiring_time = '86400') : string
90
    {
91
        if (!isset($this->redis) || !isset($this->pdo)) {
92
            return $default_language;
93
        }
94
95
        // Check if the language exists on Redis
96 View Code Duplication
        if ($this->redis->exists($this->_chat_id . ':language')) {
1 ignored issue
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...
97
            $this->language = $this->redis->get($this->_chat_id . ':language');
0 ignored issues
show
Bug introduced by
The property redis does not exist. Did you maybe forget to declare it?

In PHP it is possible to write to properties without declaring them. For example, the following is perfectly valid PHP code:

class MyClass { }

$x = new MyClass();
$x->foo = true;

Generally, it is a good practice to explictly declare properties to avoid accidental typos and provide IDE auto-completion:

class MyClass {
    public $foo;
}

$x = new MyClass();
$x->foo = true;
Loading history...
98
            return $this->language;
99
        }
100
101
        // Set the value from the database
102
        $this->redis->setEx($this->_chat_id . ':language', $expiring_time,
103
                            $this->getLanguageDatabase($default_language));
104
        return $this->language;
105
    }
106
107
    /**
108
     * \brief Set the current user language in both Redis, database and internally.
109
     * \details Save it into database first, then create the expiring key on Redis.
110
     * @param $language The language to set.
111
     * @param $expiring_time <i>Optional</i>. Time for the language key in redis to expire.
112
     * @return On sucess, return true, throws exception otherwise.
113
     */
114
    public function setLanguageRedis($language, $expiring_time = '86400')
115
    {
116
        if (!isset($this->_database) && !isset($this->redis)) {
117
            throw new BotException('Database connection not set');
118
        }
119
120
        // Update the language in the database
121
        $sth = $this->pdo->prepare('UPDATE ' . $this->user_table . ' SET language = :language WHERE ' 
122
                                             . $this->id_column . ' = :id');
123
        $sth->bindParam(':language', $language);
124
        $sth->bindParam(':id', $this->_chat_id);
125
126
        try {
127
            $sth->execute();
128
        } catch (PDOException $e) {
0 ignored issues
show
Bug introduced by
The class PhpBotFramework\Localization\PDOException does not exist. Did you forget a USE statement, or did you not list all dependencies?

Scrutinizer analyzes your composer.json/composer.lock file if available to determine the classes, and functions that are defined by your dependencies.

It seems like the listed class was neither found in your dependencies, nor was it found in the analyzed files in your repository. If you are using some other form of dependency management, you might want to disable this analysis.

Loading history...
129
            throw new BotException($e->getMessage());
130
        }
131
132
        $sth = null;
0 ignored issues
show
Unused Code introduced by
$sth 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...
133
134
        // Set the language in Redis
135
        $this->redis->setEx($this->_chat_id . ':language', $expiring_time, $language);
136
137
        // Set language internally
138
        $this->language = $language;
139
    }
140
141
    /** @} */
142
}
143