Passed
Push — master ( bd4945...f42790 )
by Patrick
02:05
created

Database   B

Complexity

Total Complexity 43

Size/Duplication

Total Lines 294
Duplicated Lines 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
eloc 149
dl 0
loc 294
rs 8.96
c 1
b 0
f 0
wmc 43

7 Methods

Rating   Name   Duplication   Size   Complexity  
B create_schema() 0 47 8
A db_connect_ido() 0 18 4
A __construct() 0 11 2
A setupDSN() 0 19 6
A db_connect_trap() 0 19 4
C update_schema() 0 102 17
A setupIDO() 0 8 2

How to fix   Complexity   

Complex Class

Complex classes like Database often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

While breaking up the class, it is a good idea to analyze how other classes use Database, and based on these observations, apply Extract Interface, too.

1
<?php
2
3
namespace Trapdirector;
4
5
use Trapdirector\Logging;
6
7
use Exception;
8
use PDO;
9
use PDOException;
10
11
class Database
12
{
13
14
    // Databases
15
    protected $trapDB=null; //< trap database
16
    protected $idoDB=null; //< ido database
17
    public $trapDBType; //< Type of database for traps (mysql, pgsql)
18
    public $idoDBType; //< Type of database for ido (mysql, pgsql)
19
    
20
    protected $trapDSN; //< trap database connection params
21
    protected $trapUsername; //< trap database connection params
22
    protected $trapPass; //< trap database connection params
23
    public $dbPrefix; //< database tables prefix
24
    
25
    protected $idoSet; //< bool true is ido database set
26
    protected $idoDSN; //< trap database connection params
27
    protected $idoUsername; //< trap database connection params
28
    protected $idoPass; //< trap database connection params
29
    
30
    // Logging function
31
    
32
    protected $logging; //< logging class
33
    
34
    /**
35
     * @param Logging $logClass : where to log
36
     * @param array $dbParam : array of named params  type,host,dbname,username,[port],[password]
37
     */
38
    function __construct($logClass,$dbParam,$dbPrefix)
39
    {
40
        $this->logging=$logClass;
41
        $this->dbPrefix=$dbPrefix;
42
        
43
        $this->trapDSN=$this->setupDSN($dbParam);
44
        $this->trapUsername = $dbParam['username'];
45
        $this->trapPass = (array_key_exists('password', $dbParam)) ? $dbParam['password']:'';
46
        $this->trapDBType=$dbParam['db'];
47
        $this->logging->log('DSN : '.$this->trapDSN. ';user '.$this->trapUsername.' / prefix : '. $this->dbPrefix,INFO);
48
        $this->db_connect_trap();
49
        
50
    }
51
    
52
    /**
53
     * Setup and connect to IDO database
54
     * @param array $dbParam : array of named params
55
     */
56
    public function setupIDO($dbParam)
57
    {
58
        $this->idoDSN=$this->setupDSN($dbParam);
59
        $this->idoUsername = $dbParam['username'];
60
        $this->idoPass = (array_key_exists('password', $dbParam)) ? $dbParam['password']:'';
61
        $this->logging->log('DSN : '.$this->idoDSN. ';user '.$this->idoUsername,INFO);
62
        $this->idoDBType=$dbParam['db'];
63
        $this->db_connect_ido();
64
    }
65
    
66
    /**
67
     * Connect to IDO database
68
     * @return \PDO
69
     */
70
    public function db_connect_ido()
71
    {
72
        if ($this->idoDB != null) {
73
            // Check if connection is still alive
74
            try {
75
                $this->idoDB->query('select 1')->fetchColumn();
76
                return $this->idoDB;
77
            } catch (Exception $e) {
78
                // select 1 failed, try to reconnect.
79
                $this->logging->log('Database IDO connection lost, reconnecting',WARN);
80
            }
81
        }
82
        try {
83
            $this->idoDB = new PDO($this->idoDSN,$this->idoUsername,$this->idoPass);
84
        } catch (PDOException $e) {
85
            $this->logging->log('Connection failed to IDO : ' . $e->getMessage(),ERROR,'');
86
        }
87
        return $this->idoDB;
88
    }
89
    
90
    /**
91
     * Connect to Trap database
92
     * @return \PDO
93
     */
94
    public function db_connect_trap()
95
    {
96
        
97
        if ($this->trapDB != null) {
98
            // Check if connection is still alive
99
            try {
100
                $this->trapDB->query('select 1')->fetchColumn();
101
                return $this->trapDB;
0 ignored issues
show
Bug Best Practice introduced by
The expression return $this->trapDB also could return the type mixed which is incompatible with the documented return type PDO.
Loading history...
102
            } catch (Exception $e) {
103
                // select 1 failed, try to reconnect.
104
                $this->logging->log('Database connection lost, reconnecting',WARN);
105
            }           
106
        }       
107
        try {
108
            $this->trapDB = new PDO($this->trapDSN,$this->trapUsername,$this->trapPass);
109
        } catch (PDOException $e) {
110
            $this->logging->log('Connection failed : ' . $e->getMessage(),ERROR,'');
111
        }
112
        return $this->trapDB;
113
    }
114
    
115
    /**
116
     * Setup dsn and check parameters
117
     * @param array $configElmt
118
     * @return string
119
     */
120
    protected function setupDSN($configElmt)  
121
    {
122
        if (!array_key_exists('db',$configElmt) ||
123
            !array_key_exists('host',$configElmt) ||
124
            !array_key_exists('dbname',$configElmt) ||
125
            !array_key_exists('username',$configElmt))
126
        {
127
            $this->logging->log('Missing DB params',ERROR);
128
            return ''; 
129
        }
130
        
131
        //	$dsn = 'mysql:dbname=traps;host=127.0.0.1';
132
        $dsn= $configElmt['db'].':dbname='.$configElmt['dbname'].';host='.$configElmt['host'];
133
        
134
        if (array_key_exists('port', $configElmt))
135
        {
136
            $dsn .= ';port='.$configElmt['port'];
137
        }
138
        return $dsn;
139
    }
140
141
    
142
    /** Create database schema
143
     *	@param $schema_file	string File to read schema from
144
     *	@param $table_prefix string to replace #PREFIX# in schema file by this
145
     */
146
    public function create_schema($schema_file,$table_prefix)
147
    {
148
        //Read data from snmptrapd from stdin
149
        $input_stream=fopen($schema_file, 'r');
150
        
151
        if ($input_stream=== false)
152
        {
153
            $this->logging->log("Error reading schema !",ERROR,'');
154
            return;
155
        }
156
        $newline='';
157
        $cur_table='';
158
        $cur_table_array=array();
159
        $db_conn=$this->db_connect_trap();
160
        
161
        while (($line=fgets($input_stream)) !== false)
162
        {
163
            $newline.=chop(preg_replace('/#PREFIX#/',$table_prefix,$line));
164
            if (preg_match('/; *$/', $newline))
165
            {
166
                $sql= $newline;
167
                if ($db_conn->query($sql) === false) {
168
                    $this->logging->log('Error create schema : '.$sql,ERROR,'');
169
                    return;
170
                }
171
                if (preg_match('/^ *CREATE TABLE ([^ ]+)/',$newline,$cur_table_array))
172
                {
173
                    $cur_table='table '.$cur_table_array[1];
174
                }
175
                else
176
                {
177
                    $cur_table='secret SQL stuff :-)';
178
                }
179
                $this->logging->log('Creating : ' . $cur_table,INFO );
180
                $newline='';
181
            }
182
        }
183
        
184
        $sql= $newline;
185
        if ($sql != '' )
186
        {
187
            if ($db_conn->query($sql) === false) {
188
                $this->logging->log('Error create schema : '.$sql,ERROR,'');
189
                return;
190
            }
191
        }
192
        $this->logging->log('Schema created',INFO);
193
    }
194
    
195
    /**
196
     * Update database schema from current (as set in db) to $target_version
197
     *     @param $prefix string file prefix of sql update File
198
     *     @param $target_version int target db version number
199
     *     @param $table_prefix string to replace #PREFIX# in schema file by this
200
     *     @param bool $getmsg : only get messages from version upgrades
201
     *     @return string : if $getmsg=true, return messages.
202
     */
203
    public function update_schema($prefix,$target_version,$table_prefix,$getmsg=false)
204
    {
205
        // Get current db number
206
        $db_conn=$this->db_connect_trap();
207
        $sql='SELECT id,value from '.$this->dbPrefix.'db_config WHERE name=\'db_version\' ';
208
        $this->logging->log('SQL query : '.$sql,DEBUG );
209
        if (($ret_code=$db_conn->query($sql)) === false) {
210
            $this->logging->log('Cannot get db version. Query : ' . $sql,2,'');
211
            return 'ERROR';
212
        }
213
        $version=$ret_code->fetchAll();
214
        $cur_version=$version[0]['value'];
215
        $db_version_id=$version[0]['id'];
216
        
217
        if ($this->trapDBType == 'pgsql')
218
        {
219
            $prefix .= 'update_pgsql/schema_';
220
        }
221
        else
222
        {
223
            $prefix .= 'update_sql/schema_';
224
        }
225
        //echo "version all :\n";print_r($version);echo " \n $cur_ver \n";
226
        if ($getmsg === true)
227
        {
228
            $message='';
229
            $this->logging->log('getting message for upgrade',DEBUG );
230
            while($cur_version<$target_version)
231
            {
232
                $cur_version++;
233
                $updateFile=$prefix.'v'.($cur_version-1).'_v'.$cur_version.'.sql';
234
                $input_stream=fopen($updateFile, 'r');
235
                if ($input_stream=== false)
236
                {
237
                    $this->logging->log("Error reading update file ". $updateFile,2,'');
238
                    return 'ERROR';
239
                }
240
                do { $line=fgets($input_stream); }
241
                while ($line !== false && !preg_match('/#MESSAGE/',$line));
242
                if ($line === false)
243
                {
244
                    $this->logging->log("No message in file ". $updateFile,2,'');
245
                    return 'ERROR';
246
                }
247
                $message .= ($cur_version-1) . '->' . $cur_version. ' : ' . preg_replace('/#MESSAGE : /','',$line)."\n";
248
            }
249
            return $message;
250
        }
251
        while($cur_version<$target_version)
252
        { // tODO : execute pre & post scripts
253
            $cur_version++;
254
            $this->logging->log('Updating to version : ' .$cur_version ,INFO );
255
            $updateFile=$prefix.'v'.($cur_version-1).'_v'.$cur_version.'.sql';
256
            $input_stream=fopen($updateFile, 'r');
257
            if ($input_stream=== false)
258
            {
259
                $this->logging->log("Error reading update file ". $updateFile,2,'');
260
                return 'ERROR';
261
            }
262
            $newline='';
263
            $db_conn=$this->db_connect_trap();
264
            $db_conn->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
265
            while (($line=fgets($input_stream)) !== false)
266
            {
267
                if (preg_match('/^#/', $line)) continue; // ignore comment lines
268
                $newline.=chop(preg_replace('/#PREFIX#/',$table_prefix,$line));
269
                if (preg_match('/; *$/', $newline))
270
                {
271
                    $sql_req=$db_conn->prepare($newline);
272
                    if ($sql_req->execute() === false) {
273
                        $this->logging->log('Error create schema : '.$newline,1,'');
274
                    }
275
                    $cur_table_array=array();
276
                    if (preg_match('/^ *([^ ]+) TABLE ([^ ]+)/',$newline,$cur_table_array))
277
                    {
278
                        $cur_table=$cur_table_array[1] . ' SQL table '.$cur_table_array[2];
279
                    }
280
                    else
281
                    {
282
                        $cur_table='secret SQL stuff :-)';
283
                        //$cur_table=$newline;
284
                    }
285
                    $this->logging->log('Doing : ' . $cur_table,INFO );
286
                    
287
                    $newline='';
288
                }
289
            }
290
            fclose($input_stream);
291
            
292
            //$sql= $newline;
293
            //if ($db_conn->query($sql) === false) {
294
            //    $this->logging->log('Error updating schema : '.$sql,1,'');
295
            //}
296
            
297
            $sql='UPDATE '.$this->dbPrefix.'db_config SET value='.$cur_version.' WHERE ( id = '.$db_version_id.' )';
298
            $this->logging->log('SQL query : '.$sql,DEBUG );
299
            if ($db_conn->query($sql) === false) {
300
                $this->logging->log('Cannot update db version. Query : ' . $sql,2);
301
                return 'ERROR';
302
            }
303
            
304
            $this->logging->log('Schema updated to version : '.$cur_version ,INFO);
305
        }
306
    }
307
    
308
    
309
}