1 <?php
  2 /**
  3  * @package     Joomla.Platform
  4  * @subpackage  Database
  5  *
  6  * @copyright   Copyright (C) 2005 - 2017 Open Source Matters, Inc. All rights reserved.
  7  * @license     GNU General Public License version 2 or later; see LICENSE
  8  */
  9 
 10 defined('JPATH_PLATFORM') or die;
 11 
 12 /**
 13  * Joomla Platform Database Factory class
 14  *
 15  * @since  12.1
 16  */
 17 class JDatabaseFactory
 18 {
 19     /**
 20      * Contains the current JDatabaseFactory instance
 21      *
 22      * @var    JDatabaseFactory
 23      * @since  12.1
 24      */
 25     private static $_instance = null;
 26 
 27     /**
 28      * Method to return a JDatabaseDriver instance based on the given options. There are three global options and then
 29      * the rest are specific to the database driver. The 'database' option determines which database is to
 30      * be used for the connection. The 'select' option determines whether the connector should automatically select
 31      * the chosen database.
 32      *
 33      * Instances are unique to the given options and new objects are only created when a unique options array is
 34      * passed into the method.  This ensures that we don't end up with unnecessary database connection resources.
 35      *
 36      * @param   string  $name     Name of the database driver you'd like to instantiate
 37      * @param   array   $options  Parameters to be passed to the database driver.
 38      *
 39      * @return  JDatabaseDriver  A database driver object.
 40      *
 41      * @since   12.1
 42      * @throws  RuntimeException
 43      */
 44     public function getDriver($name = 'mysqli', $options = array())
 45     {
 46         // Sanitize the database connector options.
 47         $options['driver']   = preg_replace('/[^A-Z0-9_\.-]/i', '', $name);
 48         $options['database'] = (isset($options['database'])) ? $options['database'] : null;
 49         $options['select']   = (isset($options['select'])) ? $options['select'] : true;
 50 
 51         // Derive the class name from the driver.
 52         $class = 'JDatabaseDriver' . ucfirst(strtolower($options['driver']));
 53 
 54         // If the class still doesn't exist we have nothing left to do but throw an exception.  We did our best.
 55         if (!class_exists($class))
 56         {
 57             throw new JDatabaseExceptionUnsupported(sprintf('Unable to load Database Driver: %s', $options['driver']));
 58         }
 59 
 60         // Create our new JDatabaseDriver connector based on the options given.
 61         try
 62         {
 63             $instance = new $class($options);
 64         }
 65         catch (RuntimeException $e)
 66         {
 67             throw new JDatabaseExceptionConnecting(sprintf('Unable to connect to the Database: %s', $e->getMessage()), $e->getCode(), $e);
 68         }
 69 
 70         return $instance;
 71     }
 72 
 73     /**
 74      * Gets an exporter class object.
 75      *
 76      * @param   string           $name  Name of the driver you want an exporter for.
 77      * @param   JDatabaseDriver  $db    Optional JDatabaseDriver instance
 78      *
 79      * @return  JDatabaseExporter  An exporter object.
 80      *
 81      * @since   12.1
 82      * @throws  RuntimeException
 83      */
 84     public function getExporter($name, JDatabaseDriver $db = null)
 85     {
 86         // Derive the class name from the driver.
 87         $class = 'JDatabaseExporter' . ucfirst(strtolower($name));
 88 
 89         // Make sure we have an exporter class for this driver.
 90         if (!class_exists($class))
 91         {
 92             // If it doesn't exist we are at an impasse so throw an exception.
 93             throw new JDatabaseExceptionUnsupported('Database Exporter not found.');
 94         }
 95 
 96         $o = new $class;
 97 
 98         if ($db instanceof JDatabaseDriver)
 99         {
100             $o->setDbo($db);
101         }
102 
103         return $o;
104     }
105 
106     /**
107      * Gets an importer class object.
108      *
109      * @param   string           $name  Name of the driver you want an importer for.
110      * @param   JDatabaseDriver  $db    Optional JDatabaseDriver instance
111      *
112      * @return  JDatabaseImporter  An importer object.
113      *
114      * @since   12.1
115      * @throws  RuntimeException
116      */
117     public function getImporter($name, JDatabaseDriver $db = null)
118     {
119         // Derive the class name from the driver.
120         $class = 'JDatabaseImporter' . ucfirst(strtolower($name));
121 
122         // Make sure we have an importer class for this driver.
123         if (!class_exists($class))
124         {
125             // If it doesn't exist we are at an impasse so throw an exception.
126             throw new JDatabaseExceptionUnsupported('Database importer not found.');
127         }
128 
129         $o = new $class;
130 
131         if ($db instanceof JDatabaseDriver)
132         {
133             $o->setDbo($db);
134         }
135 
136         return $o;
137     }
138 
139     /**
140      * Gets an instance of the factory object.
141      *
142      * @return  JDatabaseFactory
143      *
144      * @since   12.1
145      */
146     public static function getInstance()
147     {
148         return self::$_instance ? self::$_instance : new JDatabaseFactory;
149     }
150 
151     /**
152      * Get the current query object or a new JDatabaseQuery object.
153      *
154      * @param   string           $name  Name of the driver you want an query object for.
155      * @param   JDatabaseDriver  $db    Optional JDatabaseDriver instance
156      *
157      * @return  JDatabaseQuery  The current query object or a new object extending the JDatabaseQuery class.
158      *
159      * @since   12.1
160      * @throws  RuntimeException
161      */
162     public function getQuery($name, JDatabaseDriver $db = null)
163     {
164         // Derive the class name from the driver.
165         $class = 'JDatabaseQuery' . ucfirst(strtolower($name));
166 
167         // Make sure we have a query class for this driver.
168         if (!class_exists($class))
169         {
170             // If it doesn't exist we are at an impasse so throw an exception.
171             throw new JDatabaseExceptionUnsupported('Database Query class not found');
172         }
173 
174         return new $class($db);
175     }
176 
177     /**
178      * Gets an instance of a factory object to return on subsequent calls of getInstance.
179      *
180      * @param   JDatabaseFactory  $instance  A JDatabaseFactory object.
181      *
182      * @return  void
183      *
184      * @since   12.1
185      */
186     public static function setInstance(JDatabaseFactory $instance = null)
187     {
188         self::$_instance = $instance;
189     }
190 }
191