2 if(!defined('sugarEntry') || !sugarEntry) die('Not A Valid Entry Point');
3 /*********************************************************************************
4 * SugarCRM Community Edition is a customer relationship management program developed by
5 * SugarCRM, Inc. Copyright (C) 2004-2012 SugarCRM Inc.
7 * This program is free software; you can redistribute it and/or modify it under
8 * the terms of the GNU Affero General Public License version 3 as published by the
9 * Free Software Foundation with the addition of the following permission added
10 * to Section 15 as permitted in Section 7(a): FOR ANY PART OF THE COVERED WORK
11 * IN WHICH THE COPYRIGHT IS OWNED BY SUGARCRM, SUGARCRM DISCLAIMS THE WARRANTY
12 * OF NON INFRINGEMENT OF THIRD PARTY RIGHTS.
14 * This program is distributed in the hope that it will be useful, but WITHOUT
15 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
16 * FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
19 * You should have received a copy of the GNU Affero General Public License along with
20 * this program; if not, see http://www.gnu.org/licenses or write to the Free
21 * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
24 * You can contact SugarCRM, Inc. headquarters at 10050 North Wolfe Road,
25 * SW2-130, Cupertino, CA 95014, USA. or at email address contact@sugarcrm.com.
27 * The interactive user interfaces in modified source and object code versions
28 * of this program must display Appropriate Legal Notices, as required under
29 * Section 5 of the GNU Affero General Public License version 3.
31 * In accordance with Section 7(b) of the GNU Affero General Public License version 3,
32 * these Appropriate Legal Notices must retain the display of the "Powered by
33 * SugarCRM" logo. If the display of the logo is not reasonably feasible for
34 * technical reasons, the Appropriate Legal Notices must display the words
35 * "Powered by SugarCRM".
36 ********************************************************************************/
38 /*********************************************************************************
40 * Description: This file generates the appropriate manager for the database
42 * Portions created by SugarCRM are Copyright (C) SugarCRM, Inc.
43 * All Rights Reserved.
44 * Contributor(s): ______________________________________..
45 ********************************************************************************/
47 require_once('include/database/DBManager.php');
50 * Database driver factory
52 * Instantiates and configures appropriate DB drivers
54 class DBManagerFactory
56 static $instances = array();
59 * Returns a reference to the DB object of specific type
61 * @param string $type DB type
62 * @param array $config DB configuration
63 * @return object DBManager instance
65 public static function getTypeInstance($type, $config = array())
69 if(empty($config['db_manager'])) {
73 if (empty($sugar_config['mysqli_disabled']) && function_exists('mysqli_connect')) {
74 $my_db_manager = 'MysqliManager';
76 $my_db_manager = "MysqlManager";
80 if ( function_exists('sqlsrv_connect')
81 && (empty($config['db_mssql_force_driver']) || $config['db_mssql_force_driver'] == 'sqlsrv' )) {
82 $my_db_manager = 'SqlsrvManager';
83 } elseif (self::isFreeTDS()
84 && (empty($config['db_mssql_force_driver']) || $config['db_mssql_force_driver'] == 'freetds' )) {
85 $my_db_manager = 'FreeTDSManager';
87 $my_db_manager = 'MssqlManager';
91 $my_db_manager = self::getManagerByType($type, false);
92 if(empty($my_db_manager)) {
93 $GLOBALS['log']->fatal("unable to load DB manager for: $type");
94 sugar_die("Cannot load DB manager");
98 $my_db_manager = $config['db_manager'];
102 $my_db_manager = preg_replace("/[^A-Za-z0-9_-]/", "", $my_db_manager);
104 if(!empty($config['db_manager_class'])){
105 $my_db_manager = $config['db_manager_class'];
107 if(file_exists("custom/include/database/{$my_db_manager}.php")) {
108 require_once("custom/include/database/{$my_db_manager}.php");
110 require_once("include/database/{$my_db_manager}.php");
114 if(class_exists($my_db_manager)) {
115 return new $my_db_manager();
122 * Returns a reference to the DB object for instance $instanceName, or the default
123 * instance if one is not specified
125 * @param string $instanceName optional, name of the instance
126 * @return object DBManager instance
128 public static function getInstance($instanceName = '')
130 global $sugar_config;
131 static $count = 0, $old_count = 0;
133 //fall back to the default instance name
134 if(empty($sugar_config['db'][$instanceName])){
137 if(!isset(self::$instances[$instanceName])){
138 $config = $sugar_config['dbconfig'];
140 self::$instances[$instanceName] = self::getTypeInstance($config['db_type'], $config);
141 if(!empty($sugar_config['dbconfigoption'])) {
142 self::$instances[$instanceName]->setOptions($sugar_config['dbconfigoption']);
144 self::$instances[$instanceName]->connect($config, true);
145 self::$instances[$instanceName]->count_id = $count;
146 self::$instances[$instanceName]->references = 0;
149 self::$instances[$instanceName]->references = $old_count;
151 return self::$instances[$instanceName];
155 * Disconnect all DB connections in the system
157 public static function disconnectAll()
159 foreach(self::$instances as $instance) {
160 $instance->disconnect();
162 self::$instances = array();
167 * Get DB manager class name by type name
170 * @param string $type
171 * @param bool $validate Return only valid drivers or any?
174 public static function getManagerByType($type, $validate = true)
176 $drivers = self::getDbDrivers($validate);
177 if(!empty($drivers[$type])) {
178 return get_class($drivers[$type]);
184 * Scan directory for valid DB drivers
186 * @param array $drivers
187 * @param bool $validate Return only valid drivers or all of them?
189 protected static function scanDriverDir($dir, &$drivers, $validate = true)
191 if(!is_dir($dir)) return;
192 $scandir = opendir($dir);
193 if($scandir === false) return;
194 while(($name = readdir($scandir)) !== false) {
195 if(substr($name, -11) != "Manager.php") continue;
196 if($name == "DBManager.php") continue;
197 require_once("$dir/$name");
198 $classname = substr($name, 0, -4);
199 if(!class_exists($classname)) continue;
200 $driver = new $classname;
201 if(!$validate || $driver->valid()) {
202 if(empty($drivers[$driver->dbType])) {
203 $drivers[$driver->dbType] = array();
205 $drivers[$driver->dbType][] = $driver;
212 * Compares two drivers by priority
218 public static function _compareDrivers($a, $b)
220 return $b->priority - $a->priority;
224 * Get list of all available DB drivers
225 * @param bool $validate Return only valid drivers or all of them?
226 * @return array List of Db drivers, key - variant (mysql, mysqli), value - driver type (mysql, mssql)
228 public static function getDbDrivers($validate = true)
231 self::scanDriverDir("include/database", $drivers, $validate);
232 self::scanDriverDir("custom/include/database", $drivers, $validate);
235 foreach($drivers as $type => $tdrivers) {
236 if(empty($tdrivers)) continue;
237 if(count($tdrivers) > 1) {
238 usort($tdrivers, array(__CLASS__, "_compareDrivers"));
240 $result[$type] = $tdrivers[0];
246 * Check if we have freeTDS driver installed
247 * Invoked when connected to mssql. checks if we have freetds version of mssql library.
248 * the response is put into a global variable.
251 public static function isFreeTDS()
253 static $is_freetds = null;
255 if($is_freetds === null) {
257 phpinfo(INFO_MODULES);
258 $info=ob_get_contents();
261 $is_freetds = (strpos($info,'FreeTDS') !== false);