Creole.php

Go to the documentation of this file.
00001 <?php 00002 /* 00003 * $Id: Creole.php,v 1.5 2004/03/20 04:16:49 hlellelid Exp $ 00004 * 00005 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 00006 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 00007 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 00008 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 00009 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 00010 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 00011 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 00012 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 00013 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 00014 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 00015 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 00016 * 00017 * This software consists of voluntary contributions made by many individuals 00018 * and is licensed under the LGPL. For more information please see 00019 * <http://creole.phpdb.org>. 00020 */ 00021 00022 include_once 'creole/SQLException.php'; 00023 include_once 'creole/Connection.php'; 00024 00025 // static: 00026 // track errors is used by drivers to get better error messages 00027 // make sure it's set. 00028 00029 @ini_set('track_errors', true); 00030 00047 class Creole { 00048 00052 const PERSISTENT = 1; 00053 00058 const NO_ASSOC_LOWER = 16; 00059 00066 private static $driverMap = array( 'mysql' => 'creole.drivers.mysql.MySQLConnection', 00067 'pgsql' => 'creole.drivers.pgsql.PgSQLConnection', 00068 'sqlite' => 'creole.drivers.sqlite.SQLiteConnection', 00069 'oracle' => 'creole.drivers.oracle.OCI8Connection', 00070 'mssql' => 'creole.drivers.mssql.MSSQLConnection', 00071 ); 00072 00100 public static function registerDriver($phptype, $dotpath) 00101 { 00102 self::$driverMap[$phptype] = $dotpath; 00103 } 00104 00112 public static function deregisterDriver($phptype) 00113 { 00114 unset(self::$driverMap[$phptype]); 00115 } 00116 00123 public static function getDriver($phptype) 00124 { 00125 if (isset(self::$driverMap[$phptype])) { 00126 return self::$driverMap[$phptype]; 00127 } else { 00128 return null; 00129 } 00130 } 00131 00146 public static function getConnection($dsn, $flags = 0) 00147 { 00148 if (is_array($dsn)) { 00149 $dsninfo = $dsn; 00150 } else { 00151 $dsninfo = self::parseDSN($dsn); 00152 } 00153 00154 // support "catchall" drivers which will themselves handle the details of connecting 00155 // using the proper RDBMS driver. 00156 if (isset(self::$driverMap['*'])) { 00157 $type = '*'; 00158 } else { 00159 $type = $dsninfo['phptype']; 00160 if (!isset(self::$driverMap[$type])) { 00161 throw new SQLException("No driver has been registered to handle connection type: $type"); 00162 } 00163 } 00164 00165 // may need to make this more complex if we add support 00166 // for 'dbsyntax' 00167 $clazz = self::import(self::$driverMap[$type]); 00168 $obj = new $clazz(); 00169 00170 if (!($obj instanceof Connection)) { 00171 throw new SQLException("Class does not implement creole.Connection interface: $clazz"); 00172 } 00173 00174 try { 00175 $obj->connect($dsninfo, $flags); 00176 } catch(SQLException $sqle) { 00177 $sqle->setUserInfo($dsninfo); 00178 throw $sqle; 00179 } 00180 00181 return $obj; 00182 } 00183 00216 public static function parseDSN($dsn) 00217 { 00218 if (is_array($dsn)) { 00219 return $dsn; 00220 } 00221 00222 $parsed = array( 00223 'phptype' => null, 00224 'username' => null, 00225 'password' => null, 00226 'protocol' => null, 00227 'hostspec' => null, 00228 'port' => null, 00229 'socket' => null, 00230 'database' => null 00231 ); 00232 00233 $info = parse_url($dsn); 00234 00235 if (count($info) === 1) { // if there's only one element in result, then it must be the phptype 00236 $parsed['phptype'] = array_pop($info); 00237 return $parsed; 00238 } 00239 00240 // some values can be copied directly 00241 $parsed['phptype'] = @$info['scheme']; 00242 $parsed['username'] = @$info['user']; 00243 $parsed['password'] = @$info['pass']; 00244 $parsed['port'] = @$info['port']; 00245 00246 $host = @$info['host']; 00247 if (false !== ($pluspos = strpos($host, '+'))) { 00248 $parsed['protocol'] = substr($host,0,$pluspos); 00249 if ($parsed['protocol'] === 'unix') { 00250 $parsed['socket'] = substr($host,$pluspos+1); 00251 } else { 00252 $parsed['hostspec'] = substr($host,$pluspos+1); 00253 } 00254 } else { 00255 $parsed['hostspec'] = $host; 00256 } 00257 00258 if (isset($info['path'])) { 00259 $parsed['database'] = substr($info['path'], 1); // remove first char, which is '/' 00260 } 00261 00262 if (isset($info['query'])) { 00263 $opts = explode('&', $info['query']); 00264 foreach ($opts as $opt) { 00265 list($key, $value) = explode('=', $opt); 00266 if (!isset($parsed[$key])) { // don't allow params overwrite 00267 $parsed[$key] = urldecode($value); 00268 } 00269 } 00270 } 00271 00272 return $parsed; 00273 } 00274 00284 public static function import($class) { 00285 if (!class_exists($class)) { 00286 $path = strtr($class, '.', DIRECTORY_SEPARATOR) . '.php'; 00287 $ret = include_once($path); 00288 if ($ret === false) { 00289 throw new SQLException("Unable to load driver class: " . $class); 00290 } 00291 // get just classname ('path.to.ClassName' -> 'ClassName') 00292 $pos = strrpos($class, '.'); 00293 if ($pos !== false) { 00294 $class = substr($class, $pos + 1); 00295 } 00296 if (!class_exists($class)) { 00297 throw new SQLException("Unable to find loaded class: $class (Hint: make sure classname matches filename)"); 00298 } 00299 } 00300 return $class; 00301 } 00302 00303 }

This file is part of the Creole[php5] library.


Copyright © 2004 Hans Lellelid  
Creole[php5] CVS