Driver_PDO_SQLSRV::__construct()   B
last analyzed

Complexity

Conditions 5
Paths 13

Size

Total Lines 40
Code Lines 19

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 5
eloc 19
nc 13
nop 1
dl 0
loc 40
rs 8.439
c 0
b 0
f 0
1
<?php
2
3
/**
4
 * Adds support for Microsoft SQLSRV databases
5
 *
6
 * PHP Version 5
7
 *
8
 * @category  Core
9
 * @package   Database
10
 * @author    Hans-Joachim Piepereit <[email protected]>
11
 * @copyright 2013 cSphere Team
12
 * @license   http://opensource.org/licenses/bsd-license Simplified BSD License
13
 * @link      http://www.csphere.eu
14
 **/
15
16
namespace csphere\core\database;
17
18
/**
19
 * Adds support for Microsoft SQLSRV databases
20
 *
21
 * @category  Core
22
 * @package   Database
23
 * @author    Hans-Joachim Piepereit <[email protected]>
24
 * @copyright 2013 cSphere Team
25
 * @license   http://opensource.org/licenses/bsd-license Simplified BSD License
26
 * @link      http://www.csphere.eu
27
 **/
28
29
class Driver_PDO_SQLSRV extends Base_PDO
30
{
31
    /**
32
     * Creates the database handler object
33
     *
34
     * @param array $config Configuration details as an array
35
     *
36
     * @throws \Exception
37
     *
38
     * @return \csphere\core\database\Driver_PDO_SQLSRV
39
     **/
0 ignored issues
show
Comprehensibility Best Practice introduced by
Adding a @return annotation to constructors is generally not recommended as a constructor does not have a meaningful return value.

Adding a @return annotation to a constructor is not recommended, since a constructor does not have a meaningful return value.

Please refer to the PHP core documentation on constructors.

Loading history...
Coding Style introduced by
There must be no blank lines after the function comment
Loading history...
40
41
    public function __construct(array $config)
42
    {
43
        parent::__construct($config);
44
45
        if (!extension_loaded('pdo_sqlsrv')) {
46
47
            throw new \Exception('Extension "pdo_sqlsrv" not found');
48
        }
49
50
        $dsn = empty($config['host']) ? '' :
51
               'server=' . $config['host'] . '; ';
52
53
        // This adds support for passing the db file thats used
54
        if (!empty($config['file'])) {
55
56
            $file = \csphere\core\init\path()
57
                  . 'csphere/database/' . $config['file'];
58
59
            $dsn .= 'AttachDBFileName=' . $file . '; ';
60
        }
61
62
        $dsn .= 'Database=' . $config['schema'];
63
64
        $options = [];
65
66
        // Use try catch to hide connection details
67
        try {
68
69
            $this->con = new \PDO(
70
                'sqlsrv:' . $dsn, $config['username'],
71
                $config['password'], $options
72
            );
73
74
            $this->con->setAttribute(\PDO::ATTR_ERRMODE, \PDO::ERRMODE_EXCEPTION);
75
        }
76
        catch(\PDOException $pdo_error) {
77
78
            $this->error('Connect', [], $pdo_error->getMessage(), false);
79
        }
80
    }
81
82
    /**
83
     * Builds the query string part for limit and offset
84
     *
85
     * @param integer $first Number of the first dataset to show
86
     * @param integer $max   Number of datasets to show from first on
87
     *
88
     * @return string
89
     **/
0 ignored issues
show
Coding Style introduced by
There must be no blank lines after the function comment
Loading history...
90
91
    protected function limits($first, $max)
92
    {
93
        // This works since Microsoft SQL Server 2012
94
        $string = 'OFFSET ' . (int)$first . ' ROWS '
95
                . 'FETCH NEXT ' . (int)$max . ' ROWS ONLY';
96
97
        // Fix for selecting one result row without using ORDER BY
98
        if ($max == 1) {
99
100
            $string = 'ORDER BY NEWID() ' . $string;
101
        }
102
103
        return $string;
104
    }
105
106
    /**
107
     * Replaces driver specific query placeholders
108
     *
109
     * @param string $replace The string to use for replaces
110
     *
111
     * @return string
112
     **/
0 ignored issues
show
Coding Style introduced by
There must be no blank lines after the function comment
Loading history...
113
114
    protected function replace($replace)
115
    {
116
        $change_sqlsrv = ['{engine}' => '',
117
                          '{integer}' => 'int',
118
                          '{serial}' => 'int IDENTITY(1,1)',
119
                          '{text}' => 'text',
120
                          '{longtext}' => 'text',
121
                          '{varchar}' => 'varchar'];
122
123
        foreach ($change_sqlsrv AS $key => $sqlsrv) {
124
125
            $replace = str_replace($key, $sqlsrv, $replace);
126
        }
127
128
        // There is no support for manual table optimizations
129
        $replace = preg_replace("={optimize}(.*?[;])=si", '', $replace);
130
131
        // Workaround to have a check for existing tables
132
        $pattern = "=^DROP TABLE IF EXISTS ([\S]*?)$=si";
133
        $rewrite = "IF (SELECT COUNT(*) FROM sysobjects WHERE type = 'U'"
134
                 . " AND name = '\\1') > 0 DROP TABLE \\1";
135
136
        $replace = preg_replace($pattern, $rewrite, $replace);
137
138
        return $replace;
139
    }
140
141
    /**
142
     * Returns a formatted array with statistics
143
     *
144
     * @return array
145
     **/
0 ignored issues
show
Coding Style introduced by
There must be no blank lines after the function comment
Loading history...
146
147
    public function info()
148
    {
149
        // Get general PDO information
150
        $info = parent::info();
151
152
        // Client should be an array in this driver extension
153
        if (is_array($info['client'])) {
154
155
            $info['client'] = $info['client']['DriverVer'] . ' (ext '
156
                            . $info['client']['ExtensionVer'] . ')';
157
        }
158
159
        // Get encoding of database
160
        $query = 'SELECT collation_name AS encoding FROM sys.databases '
161
               . 'WHERE database_id = DB_ID()';
162
163
        $encoding = $this->query($query, [], 0, 0);
164
165
        $info['encoding'] = 'Collation ' . $encoding[0]['encoding'];
166
167
        // Get size of database
168
        $query = 'SELECT SUM(size) AS size FROM sys.master_files '
169
               . 'WHERE type = 0 AND database_id = DB_ID() GROUP BY database_id';
170
171
        $size = $this->query($query, [], 0, 0);
172
173
        $info['size'] = $size[0]['size'] * 8192;
174
175
        // Get amount of tables
176
        $query = 'SELECT COUNT(*) AS tables FROM information_schema.tables '
177
               . 'WHERE table_type = \'base table\'';
178
179
        $tables = $this->query($query, [], 0, 0);
180
181
        $info['tables'] = $tables[0]['tables'];
182
183
        return $info;
184
    }
185
}
186