Completed
Pull Request — master (#20)
by
unknown
03:12
created

Localization::getLanguageRedis()   B

Complexity

Conditions 4
Paths 3

Size

Total Lines 26
Code Lines 8

Duplication

Lines 7
Ratio 26.92 %

Importance

Changes 0
Metric Value
dl 7
loc 26
rs 8.5806
c 0
b 0
f 0
cc 4
eloc 8
nc 3
nop 2
1
<?php
2
3
namespace PhpBotFramework\Utilities;
4
5
trait Localization {
6
7
    /**
8
     * \addtogroup Multilanguage Multilanguage
9
     * \brief Methods to create a localized bot.
10
     * @{
11
     */
12
13
    /** \brief Store the language for a multi-language bot */
14
    public $language;
15
16
    /** \brief Store localization data */
17
    public $local;
18
19
    /** \brief Table contaning bot users data in the sql database. */
20
    public $user_table = '"User"';
21
22
    /** \brief Name of the column that represents the user id in the sql database */
23
    public $id_column = 'chat_id';
24
25
    /** @} */
26
27
    /**
28
     * \brief Get current user language from the database, and set it in $language.
29
     * @param $default_language <i>Optional</i>. Default language to return in case of errors.
30
     * @return Language set for the current user, $default_language on errors.
31
     */
32
    public function getLanguageDatabase($default_language = 'en') {
33
34
        // If we have no database
35
        if (!isset($this->_database)) {
36
37
            // Set the language to english
38
            $this->language = $default_language;
39
40
            // Return english
41
            return $default_language;
42
43
        }
44
45
        // Get the language from the bot
46
        $sth = $this->pdo->prepare('SELECT language FROM ' . $this->user_table . ' WHERE ' . $this->id_column . ' = :chat_id');
0 ignored issues
show
Bug introduced by
The property pdo 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...
47
        $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...
48
49
        try {
50
51
            $sth->execute();
52
53
        } catch (PDOException $e) {
0 ignored issues
show
Bug introduced by
The class PhpBotFramework\Utilities\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...
54
55
            echo $e->getMessage();
56
57
        }
58
59
        $row = $sth->fetch();
60
61
        $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...
62
63
        // If we got the language
64
        if (isset($row['language'])) {
65
66
            // Set the language in the bot
67
            $this->language = $row['language'];
68
69
            // And return it
70
            return $row['language'];
71
72
        }
73
74
        // If we couldn't get it, set the language to english
75
        $this->language = $default_language;
76
77
        // and return english
78
        return $this->language;
79
80
    }
81
82
    /**
83
     * \brief Get current user language from redis, as a cache, and set it in language.
84
     * \details Using redis database as cache, seeks the language in it, if there isn't
85
     * then get the language from the sql database and store it (with default expiring of one day) in redis.
86
     * It also change $language parameter of the bot to the language returned.
87
     * @param $default_language <i>Optional</i>. Default language to return in case of errors.
88
     * @param $expiring_time <i>Optional</i>. Set the expiring time for the language on redis each time it is took from the sql database.
89
     * @return Language for the current user, $default_language on errors.
90
     */
91
    public function getLanguageRedis($default_language = 'en', $expiring_time = '86400') : string {
92
93
        // If redis or pdo connection are not set
94
        if (!isset($this->redis) || !isset($this->pdo)) {
95
96
            // return default language
97
            return $default_language;
98
99
        }
100
101
        // Does it exists on redis?
102 View Code Duplication
        if ($this->redis->exists($this->_chat_id . ':language')) {
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...
103
104
            // Get the value
105
            $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...
106
            return $this->language;
107
108
        }
109
110
        // Set the value from the db
111
        $this->redis->setEx($this->_chat_id . ':language', $expiring_time, $this->getLanguageDatabase($default_language));
112
113
        // and return it
114
        return $this->language;
115
116
    }
117
118
    /**
119
     * \brief Set the current user language in both redis, sql database and $language.
120
     * \details Save it on database first, then create the expiring key on redis.
121
     * @param $language The new language to set.
122
     * @param $expiring_time <i>Optional</i>. Time for the language key in redis to expire.
123
     * @return On sucess, return true, throw exception otherwise.
124
     */
125
    public function setLanguageRedis($language, $expiring_time = '86400') {
126
127
        // Check database connection
128
        if (!isset($this->_database) && !isset($this->redis)) {
129
            throw new BotException('Database connection not set');
130
        }
131
132
        // Update the language in the database
133
        $sth = $this->pdo->prepare('UPDATE ' . $this->user_table . ' SET language = :language WHERE ' . $this->id_column . ' = :id');
134
        $sth->bindParam(':language', $language);
135
        $sth->bindParam(':id', $this->_chat_id);
136
137
        try {
138
139
            $sth->execute();
140
141
        } catch (PDOException $e) {
0 ignored issues
show
Bug introduced by
The class PhpBotFramework\Utilities\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...
142
143
            throw new BotException($e->getMessage());
144
145
        }
146
147
        // Destroy statement
148
        $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...
149
150
        // Set the language in redis with expiring
151
        $this->redis->setEx($this->_chat_id . ':language', $expiring_time, $language);
152
153
        // Set language in the bot variable
154
        $this->language = $language;
155
    }
156
157
    /**
158
     * \brief Load localization files (JSON-serialized) from a folder and set them in $local variable.
159
     * \details Save all localization files, saved as json format, from a directory and put the contents in $local variable.
160
     * Each file will be saved into $local with the first two letters of the filename as the index.
161
     * Access the english data as $this->local["en"]["Your key"].
162
     * File <code>./localization/en.json</code>:
163
     *
164
     *     {"Hello_Msg": "Hello"}
165
     *
166
     * File <code>./localization/it.json</code>:
167
     *
168
     *     {"Hello_Msg": "Ciao"}
169
     *
170
     * Usage in <code>processMessage()</code>:
171
     *
172
     *     $sendMessage($this->local[$this->language]["Hello_Msg"]);
173
     *
174
     * @param $dir Directory where the localization files are saved.
175
     */
176
    public function loadLocalization($dir = './localization') {
177
178
        // Open directory
179
        if ($handle = opendir($dir)) {
180
181
            // Iterate over all files
182
            while (false !== ($file = readdir($handle))) {
183
184
                // If the file is a JSON data file
185
                if (strlen($file) > 6 && substr($file, -5) === '.json') {
186
187
                    try {
188
189
                        // Add the contents of the file to the $local variable, after deserializng it from JSON format
190
                        // The contents will be added with the 2 letter of the file as the index
191
                        $this->local[substr($file, 0, 2)] = json_decode(file_get_contents("$dir/$file"), true);
192
193
                    } catch (BotException $e) {
0 ignored issues
show
Bug introduced by
The class PhpBotFramework\Utilities\BotException 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...
194
195
                        echo $e->getMessage();
196
197
                    }
198
199
                }
200
201
            }
202
203
        }
204
205
    }
206
207
    /** @} */
208
}
209