Subversion-Projekte lars-tiefland.php_share

Revision

Details | Letzte Änderung | Log anzeigen | RSS feed

Revision Autor Zeilennr. Zeile
1 lars 1
<?php
2
/**
3
 * PHPUnit
4
 *
5
 * Copyright (c) 2002-2010, Sebastian Bergmann <sb@sebastian-bergmann.de>.
6
 * All rights reserved.
7
 *
8
 * Redistribution and use in source and binary forms, with or without
9
 * modification, are permitted provided that the following conditions
10
 * are met:
11
 *
12
 *   * Redistributions of source code must retain the above copyright
13
 *     notice, this list of conditions and the following disclaimer.
14
 *
15
 *   * Redistributions in binary form must reproduce the above copyright
16
 *     notice, this list of conditions and the following disclaimer in
17
 *     the documentation and/or other materials provided with the
18
 *     distribution.
19
 *
20
 *   * Neither the name of Sebastian Bergmann nor the names of his
21
 *     contributors may be used to endorse or promote products derived
22
 *     from this software without specific prior written permission.
23
 *
24
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
25
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
26
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
27
 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
28
 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
29
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
30
 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
31
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
32
 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
33
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
34
 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
35
 * POSSIBILITY OF SUCH DAMAGE.
36
 *
37
 * @category   Testing
38
 * @package    PHPUnit
39
 * @author     Sebastian Bergmann <sb@sebastian-bergmann.de>
40
 * @copyright  2002-2010 Sebastian Bergmann <sb@sebastian-bergmann.de>
41
 * @license    http://www.opensource.org/licenses/bsd-license.php  BSD License
42
 * @link       http://www.phpunit.de/
43
 * @since      File available since Release 3.1.4
44
 */
45
 
46
require_once 'PHPUnit/Util/Filter.php';
47
 
48
PHPUnit_Util_Filter::addFileToFilter(__FILE__, 'PHPUNIT');
49
 
50
/**
51
 * PDO helpers.
52
 *
53
 * @category   Testing
54
 * @package    PHPUnit
55
 * @author     Sebastian Bergmann <sb@sebastian-bergmann.de>
56
 * @copyright  2002-2010 Sebastian Bergmann <sb@sebastian-bergmann.de>
57
 * @license    http://www.opensource.org/licenses/bsd-license.php  BSD License
58
 * @version    Release: 3.4.15
59
 * @link       http://www.phpunit.de/
60
 * @since      Class available since Release 3.1.4
61
 */
62
class PHPUnit_Util_PDO
63
{
64
    public static function factory($dsn)
65
    {
66
        $parsed = self::parseDSN($dsn);
67
 
68
        switch ($parsed['phptype']) {
69
            case 'mysql': {
70
                $database      = NULL;
71
                $charset       = NULL;
72
                $host          = NULL;
73
                $port          = NULL;
74
                $socket        = NULL;
75
                $user          = NULL;
76
                $pass          = NULL;
77
                $driverOptions = NULL;
78
 
79
                foreach ( $parsed as $key => $val )
80
                {
81
                    switch ( $key )
82
                    {
83
                        case 'database':
84
                        case 'dbname':
85
                            $database = $val;
86
                            break;
87
 
88
                        case 'charset':
89
                            $charset = $val;
90
                            break;
91
 
92
                        case 'host':
93
                        case 'hostspec':
94
                            $host = $val;
95
                            break;
96
 
97
                        case 'port':
98
                            $port = $val;
99
                            break;
100
 
101
                        case 'socket':
102
                            $socket = $val;
103
                            break;
104
 
105
                        case 'user':
106
                        case 'username':
107
                            $user = $val;
108
                            break;
109
 
110
                        case 'pass':
111
                        case 'password':
112
                            $pass = $val;
113
                            break;
114
 
115
                        case 'driver-opts':
116
                            $driverOptions = $val;
117
                            break;
118
                    }
119
                }
120
 
121
                if ( !isset( $database ) )
122
                {
123
                    throw new InvalidArgumentException('Invalid DSN.');
124
                }
125
 
126
                $dsn = "mysql:dbname=$database";
127
 
128
                if ( isset( $host ) && $host )
129
                {
130
                    $dsn .= ";host=$host";
131
                }
132
 
133
                if ( isset( $port ) && $port )
134
                {
135
                    $dsn .= ";port=$port";
136
                }
137
 
138
                if ( isset( $charset ) && $charset )
139
                {
140
                    $dsn .= ";charset=$charset";
141
                }
142
 
143
                if ( isset( $socket ) && $socket )
144
                {
145
                    $dsn .= ";unix_socket=$socket";
146
                }
147
 
148
                $dbh = new PDO($dsn, $user, $pass, $driverOptions);
149
            }
150
            break;
151
 
152
            case 'sqlite': {
153
                $dbh = new PDO($dsn);
154
            }
155
            break;
156
 
157
            default: {
158
                throw new InvalidArgumentException('Invalid DSN.');
159
            }
160
        }
161
 
162
        $dbh->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
163
 
164
        return $dbh;
165
    }
166
 
167
    /**
168
     * Returns the Data Source Name as a structure containing the various parts of the DSN.
169
     *
170
     * Additional keys can be added by appending a URI query string to the
171
     * end of the DSN.
172
     *
173
     * The format of the supplied DSN is in its fullest form:
174
     * <code>
175
     *  phptype(dbsyntax)://username:password@protocol+hostspec/database?option=8&another=true
176
     * </code>
177
     *
178
     * Most variations are allowed:
179
     * <code>
180
     *  phptype://username:password@protocol+hostspec:110//usr/db_file.db?mode=0644
181
     *  phptype://username:password@hostspec/database_name
182
     *  phptype://username:password@hostspec
183
     *  phptype://username@hostspec
184
     *  phptype://hostspec/database
185
     *  phptype://hostspec
186
     *  phptype(dbsyntax)
187
     *  phptype
188
     * </code>
189
     *
190
     * This function is 'borrowed' from PEAR /DB.php .
191
     *
192
     * @param string $dsn Data Source Name to be parsed
193
     *
194
     * @return array an associative array with the following keys:
195
     *  + phptype:  Database backend used in PHP (mysql, odbc etc.)
196
     *  + dbsyntax: Database used with regards to SQL syntax etc.
197
     *  + protocol: Communication protocol to use (tcp, unix etc.)
198
     *  + hostspec: Host specification (hostname[:port])
199
     *  + database: Database to use on the DBMS server
200
     *  + username: User name for login
201
     *  + password: Password for login
202
     */
203
    public static function parseDSN( $dsn )
204
    {
205
        if ( $dsn == 'sqlite::memory:' )
206
        {
207
            $dsn = 'sqlite://:memory:';
208
        }
209
 
210
        $parsed = array(
211
            'phptype'  => FALSE,
212
            'dbsyntax' => FALSE,
213
            'username' => FALSE,
214
            'password' => FALSE,
215
            'protocol' => FALSE,
216
            'hostspec' => FALSE,
217
            'port'     => FALSE,
218
            'socket'   => FALSE,
219
            'database' => FALSE,
220
        );
221
 
222
        if ( is_array( $dsn ) )
223
        {
224
            $dsn = array_merge( $parsed, $dsn );
225
            if ( !$dsn['dbsyntax'] )
226
            {
227
                $dsn['dbsyntax'] = $dsn['phptype'];
228
            }
229
            return $dsn;
230
        }
231
 
232
        // Find phptype and dbsyntax
233
        if ( ( $pos = strpos( $dsn, '://' ) ) !== FALSE )
234
        {
235
            $str = substr( $dsn, 0, $pos );
236
            $dsn = substr( $dsn, $pos + 3 );
237
        }
238
        else
239
        {
240
            $str = $dsn;
241
            $dsn = NULL;
242
        }
243
 
244
        // Get phptype and dbsyntax
245
        // $str => phptype(dbsyntax)
246
        if ( preg_match( '|^(.+?)\((.*?)\)$|', $str, $arr ) )
247
        {
248
            $parsed['phptype']  = $arr[1];
249
            $parsed['dbsyntax'] = !$arr[2] ? $arr[1] : $arr[2];
250
        }
251
        else
252
        {
253
            $parsed['phptype']  = $str;
254
            $parsed['dbsyntax'] = $str;
255
        }
256
 
257
        if ( !count( $dsn ) )
258
        {
259
            return $parsed;
260
        }
261
 
262
        // Get (if found): username and password
263
        // $dsn => username:password@protocol+hostspec/database
264
        if ( ( $at = strrpos( (string) $dsn, '@' ) ) !== FALSE )
265
        {
266
            $str = substr( $dsn, 0, $at );
267
            $dsn = substr( $dsn, $at + 1 );
268
            if ( ( $pos = strpos( $str, ':' ) ) !== FALSE )
269
            {
270
                $parsed['username'] = rawurldecode( substr( $str, 0, $pos ) );
271
                $parsed['password'] = rawurldecode( substr( $str, $pos + 1 ) );
272
            }
273
            else
274
            {
275
                $parsed['username'] = rawurldecode( $str );
276
            }
277
        }
278
 
279
        // Find protocol and hostspec
280
 
281
        if ( preg_match( '|^([^(]+)\((.*?)\)/?(.*?)$|', $dsn, $match ) )
282
        {
283
            // $dsn => proto(proto_opts)/database
284
            $proto       = $match[1];
285
            $proto_opts  = $match[2] ? $match[2] : FALSE;
286
            $dsn         = $match[3];
287
        }
288
        else
289
        {
290
            // $dsn => protocol+hostspec/database (old format)
291
            if ( strpos( $dsn, '+' ) !== FALSE )
292
            {
293
                list( $proto, $dsn ) = explode( '+', $dsn, 2 );
294
            }
295
            if ( strpos( $dsn, '/' ) !== FALSE )
296
            {
297
                list( $proto_opts, $dsn ) = explode( '/', $dsn, 2 );
298
            }
299
            else
300
            {
301
                $proto_opts = $dsn;
302
                $dsn = NULL;
303
            }
304
        }
305
 
306
        // process the different protocol options
307
        $parsed['protocol'] = ( !empty( $proto ) ) ? $proto : 'tcp';
308
        $proto_opts = rawurldecode( $proto_opts );
309
        if ( $parsed['protocol'] == 'tcp' )
310
        {
311
            if ( strpos( $proto_opts, ':' ) !== FALSE )
312
            {
313
                list( $parsed['hostspec'], $parsed['port'] ) = explode( ':', $proto_opts );
314
            }
315
            else
316
            {
317
                $parsed['hostspec'] = $proto_opts;
318
            }
319
        }
320
        elseif ( $parsed['protocol'] == 'unix' )
321
        {
322
            $parsed['socket'] = $proto_opts;
323
        }
324
 
325
        // Get dabase if any
326
        // $dsn => database
327
        if ( $dsn )
328
        {
329
            if ( ( $pos = strpos( $dsn, '?' ) ) === FALSE )
330
            {
331
                // /database
332
                $parsed['database'] = rawurldecode( $dsn );
333
            }
334
            else
335
            {
336
                // /database?param1=value1&param2=value2
337
                $parsed['database'] = rawurldecode( substr( $dsn, 0, $pos ) );
338
                $dsn = substr( $dsn, $pos + 1 );
339
                if ( strpos( $dsn, '&') !== FALSE )
340
                {
341
                    $opts = explode( '&', $dsn );
342
                }
343
                else
344
                { // database?param1=value1
345
                    $opts = array( $dsn );
346
                }
347
                foreach ( $opts as $opt )
348
                {
349
                    list( $key, $value ) = explode( '=', $opt );
350
                    if ( !isset( $parsed[$key] ) )
351
                    {
352
                        // don't allow params overwrite
353
                        $parsed[$key] = rawurldecode( $value );
354
                    }
355
                }
356
            }
357
        }
358
        return $parsed;
359
    }
360
}
361
?>