]> CyberLeo.Net >> Repos - Github/sugarcrm.git/blob - include/database/DBManagerFactory.php
Release 6.4.0
[Github/sugarcrm.git] / include / database / DBManagerFactory.php
1 <?php
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-2011 SugarCRM Inc.
6  * 
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.
13  * 
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
17  * details.
18  * 
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
22  * 02110-1301 USA.
23  * 
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.
26  * 
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.
30  * 
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  ********************************************************************************/
37
38 /*********************************************************************************
39
40 * Description: This file generates the appropriate manager for the database
41 *
42 * Portions created by SugarCRM are Copyright (C) SugarCRM, Inc.
43 * All Rights Reserved.
44 * Contributor(s): ______________________________________..
45 ********************************************************************************/
46
47 require_once('include/database/DBManager.php');
48
49 /**
50  * Database driver factory
51  * @api
52  * Instantiates and configures appropriate DB drivers
53  */
54 class DBManagerFactory
55 {
56     static $instances = array();
57
58     /**
59      * Returns a reference to the DB object of specific type
60      *
61      * @param  string $type DB type
62      * @param array $config DB configuration
63      * @return object DBManager instance
64      */
65     public static function getTypeInstance($type, $config = array())
66     {
67         global $sugar_config;
68
69         if(empty($config['db_manager'])) {
70             // standard types
71             switch($type) {
72                 case "mysql":
73                     if (empty($sugar_config['mysqli_disabled']) && function_exists('mysqli_connect')) {
74                         $my_db_manager = 'MysqliManager';
75                     } else {
76                         $my_db_manager = "MysqlManager";
77                     }
78                     break;
79                 case "mssql":
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';
86                     } else {
87                         $my_db_manager = 'MssqlManager';
88                     }
89                     break;
90                 default:
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");
95                     }
96             }
97         } else {
98             $my_db_manager = $config['db_manager'];
99         }
100
101         // sanitize the name
102         $my_db_manager = preg_replace("/[^A-Za-z0-9_-]/", "", $my_db_manager);
103
104         if(!empty($config['db_manager_class'])){
105             $my_db_manager = $config['db_manager_class'];
106         } else {
107             if(file_exists("custom/include/database/{$my_db_manager}.php")) {
108                 require_once("custom/include/database/{$my_db_manager}.php");
109             } else {
110                 require_once("include/database/{$my_db_manager}.php");
111             }
112         }
113
114         if(class_exists($my_db_manager)) {
115             return new $my_db_manager();
116         } else {
117             return null;
118         }
119     }
120
121     /**
122          * Returns a reference to the DB object for instance $instanceName, or the default
123      * instance if one is not specified
124      *
125      * @param  string $instanceName optional, name of the instance
126      * @return object DBManager instance
127      */
128         public static function getInstance($instanceName = '')
129     {
130         global $sugar_config;
131         static $count = 0, $old_count = 0;
132
133         //fall back to the default instance name
134         if(empty($sugar_config['db'][$instanceName])){
135                 $instanceName = '';
136         }
137         if(!isset(self::$instances[$instanceName])){
138             $config = $sugar_config['dbconfig'];
139             $count++;
140                 self::$instances[$instanceName] = self::getTypeInstance($config['db_type'], $config);
141                 if(!empty($sugar_config['dbconfigoption'])) {
142                     self::$instances[$instanceName]->setOptions($sugar_config['dbconfigoption']);
143                 }
144                 self::$instances[$instanceName]->connect($config, true);
145                 self::$instances[$instanceName]->count_id = $count;
146                 self::$instances[$instanceName]->references = 0;
147         } else {
148             $old_count++;
149             self::$instances[$instanceName]->references = $old_count;
150         }
151         return self::$instances[$instanceName];
152     }
153
154     /**
155      * Disconnect all DB connections in the system
156      */
157     public static function disconnectAll()
158     {
159         foreach(self::$instances as $instance) {
160             $instance->disconnect();
161         }
162         self::$instances = array();
163     }
164
165
166     /**
167      * Get DB manager class name by type name
168      *
169      * For use in install
170      * @param string $type
171      * @param bool $validate Return only valid drivers or any?
172      * @return string
173      */
174     public static function getManagerByType($type, $validate = true)
175     {
176         $drivers = self::getDbDrivers($validate);
177         if(!empty($drivers[$type])) {
178             return get_class($drivers[$type]);
179         }
180         return false;
181     }
182
183     /**
184      * Scan directory for valid DB drivers
185      * @param string $dir
186      * @param array $drivers
187      * @param bool $validate Return only valid drivers or all of them?
188      */
189     protected static function scanDriverDir($dir, &$drivers, $validate = true)
190     {
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();
204                 }
205                 $drivers[$driver->dbType][] = $driver;
206             }
207         }
208
209     }
210
211     /**
212      * Compares two drivers by priority
213      * @internal
214      * @param object $a
215      * @param object $b
216      * @return int
217      */
218     public static function _compareDrivers($a, $b)
219     {
220         return $b->priority - $a->priority;
221     }
222
223     /**
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)
227      */
228     public static function getDbDrivers($validate = true)
229     {
230         $drivers = array();
231         self::scanDriverDir("include/database", $drivers, $validate);
232         self::scanDriverDir("custom/include/database", $drivers, $validate);
233
234         $result = array();
235         foreach($drivers as $type => $tdrivers) {
236             if(empty($tdrivers)) continue;
237             if(count($tdrivers) > 1) {
238                 usort($tdrivers, array(__CLASS__, "_compareDrivers"));
239             }
240             $result[$type] = $tdrivers[0];
241         }
242         return $result;
243     }
244
245     /**
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.
249      * @return bool
250      */
251     public static function isFreeTDS()
252     {
253         static $is_freetds = null;
254
255         if($is_freetds === null) {
256                 ob_start();
257                 phpinfo(INFO_MODULES);
258                 $info=ob_get_contents();
259                 ob_end_clean();
260
261                 $is_freetds = (strpos($info,'FreeTDS') !== false);
262         }
263
264         return $is_freetds;
265      }
266 }