blob: 7e6cf4fae064893eaec65ffe480979800c887b85 [file] [log] [blame]
Andrey Andreevc5536aa2012-11-01 17:33:58 +02001<?php
Derek Jones8dca0412010-03-05 13:01:44 -06002/**
3 * CodeIgniter
4 *
Andrey Andreevfe9309d2015-01-09 17:48:58 +02005 * An open source application development framework for PHP
Derek Jones8dca0412010-03-05 13:01:44 -06006 *
Andrey Andreevbdb96ca2014-10-28 00:13:31 +02007 * This content is released under the MIT License (MIT)
Andrey Andreev83d15052011-12-22 13:35:42 +02008 *
Instructor, BCIT0e59db62019-01-01 08:34:36 -08009 * Copyright (c) 2014 - 2019, British Columbia Institute of Technology
Andrey Andreev83d15052011-12-22 13:35:42 +020010 *
Andrey Andreevbdb96ca2014-10-28 00:13:31 +020011 * Permission is hereby granted, free of charge, to any person obtaining a copy
12 * of this software and associated documentation files (the "Software"), to deal
13 * in the Software without restriction, including without limitation the rights
14 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
15 * copies of the Software, and to permit persons to whom the Software is
16 * furnished to do so, subject to the following conditions:
Derek Jones8dca0412010-03-05 13:01:44 -060017 *
Andrey Andreevbdb96ca2014-10-28 00:13:31 +020018 * The above copyright notice and this permission notice shall be included in
19 * all copies or substantial portions of the Software.
20 *
21 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
22 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
23 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
24 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
25 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
26 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
27 * THE SOFTWARE.
28 *
29 * @package CodeIgniter
30 * @author EllisLab Dev Team
Andrey Andreev1924e872016-01-11 12:55:34 +020031 * @copyright Copyright (c) 2008 - 2014, EllisLab, Inc. (https://ellislab.com/)
Instructor, BCIT0e59db62019-01-01 08:34:36 -080032 * @copyright Copyright (c) 2014 - 2019, British Columbia Institute of Technology (https://bcit.ca/)
33 * @license https://opensource.org/licenses/MIT MIT License
Andrey Andreevbd202c92016-01-11 12:50:18 +020034 * @link https://codeigniter.com
Andrey Andreevbdb96ca2014-10-28 00:13:31 +020035 * @since Version 1.0.0
Derek Jones8dca0412010-03-05 13:01:44 -060036 * @filesource
37 */
Andrey Andreevc5536aa2012-11-01 17:33:58 +020038defined('BASEPATH') OR exit('No direct script access allowed');
Derek Jones8dca0412010-03-05 13:01:44 -060039
Derek Jones8dca0412010-03-05 13:01:44 -060040/**
41 * CodeIgniter Driver Library Class
42 *
43 * This class enables you to create "Driver" libraries that add runtime ability
44 * to extend the capabilities of a class via additional driver objects
45 *
46 * @package CodeIgniter
47 * @subpackage Libraries
48 * @category Libraries
49 * @author EllisLab Dev Team
Barry Mienydd671972010-10-04 16:33:58 +020050 * @link
Derek Jones8dca0412010-03-05 13:01:44 -060051 */
52class CI_Driver_Library {
53
Timothy Warren0688ac92012-04-20 10:25:04 -040054 /**
55 * Array of drivers that are available to use with the driver class
56 *
57 * @var array
58 */
59 protected $valid_drivers = array();
Andrey Andreev56454792012-05-17 14:32:19 +030060
Timothy Warren0688ac92012-04-20 10:25:04 -040061 /**
62 * Name of the current class - usually the driver class
63 *
64 * @var string
65 */
Darren Hillc4e266b2011-08-30 15:40:27 -040066 protected $lib_name;
Barry Mienydd671972010-10-04 16:33:58 +020067
Darren Hill6fbf6bd2011-08-31 14:15:35 -040068 /**
69 * Get magic method
70 *
Darren Hillc4e266b2011-08-30 15:40:27 -040071 * The first time a child is used it won't exist, so we instantiate it
72 * subsequents calls will go straight to the proper child.
Darren Hill6fbf6bd2011-08-31 14:15:35 -040073 *
dchill426262d052012-11-24 18:41:13 -050074 * @param string Child class name
75 * @return object Child class
Darren Hill6fbf6bd2011-08-31 14:15:35 -040076 */
Darren Hillc4e266b2011-08-30 15:40:27 -040077 public function __get($child)
Andrey Andreev2e3e2302012-10-09 15:52:34 +030078 {
Darren Hill6fbf6bd2011-08-31 14:15:35 -040079 // Try to load the driver
dchill42c5872252012-07-30 14:53:11 -040080 return $this->load_driver($child);
Darren Hill6fbf6bd2011-08-31 14:15:35 -040081 }
Darren Hillc4e266b2011-08-30 15:40:27 -040082
Darren Hill6fbf6bd2011-08-31 14:15:35 -040083 /**
84 * Load driver
85 *
Darren Hillc4e266b2011-08-30 15:40:27 -040086 * Separate load_driver call to support explicit driver load by library or user
Darren Hill6fbf6bd2011-08-31 14:15:35 -040087 *
dchill426262d052012-11-24 18:41:13 -050088 * @param string Driver name (w/o parent prefix)
89 * @return object Child class
Darren Hill6fbf6bd2011-08-31 14:15:35 -040090 */
Darren Hillc4e266b2011-08-30 15:40:27 -040091 public function load_driver($child)
Derek Jones8dca0412010-03-05 13:01:44 -060092 {
dchill426262d052012-11-24 18:41:13 -050093 // Get CodeIgniter instance and subclass prefix
Andrey Andreev662e3422013-01-28 21:19:13 +020094 $prefix = config_item('subclass_prefix');
dchill426262d052012-11-24 18:41:13 -050095
Pascal Kriete14287f32011-02-14 13:39:34 -050096 if ( ! isset($this->lib_name))
Derek Jones8dca0412010-03-05 13:01:44 -060097 {
dchill426262d052012-11-24 18:41:13 -050098 // Get library name without any prefix
99 $this->lib_name = str_replace(array('CI_', $prefix), '', get_class($this));
Derek Jones8dca0412010-03-05 13:01:44 -0600100 }
101
dchill426262d052012-11-24 18:41:13 -0500102 // The child will be prefixed with the parent lib
103 $child_name = $this->lib_name.'_'.$child;
Andrey Andreev83d15052011-12-22 13:35:42 +0200104
dchill426262d052012-11-24 18:41:13 -0500105 // See if requested child is a valid driver
Andrey Andreev7e83f322012-11-25 16:03:21 +0200106 if ( ! in_array($child, $this->valid_drivers))
Derek Jones8dca0412010-03-05 13:01:44 -0600107 {
dchill426262d052012-11-24 18:41:13 -0500108 // The requested driver isn't valid!
109 $msg = 'Invalid driver requested: '.$child_name;
110 log_message('error', $msg);
111 show_error($msg);
112 }
Derek Jones8dca0412010-03-05 13:01:44 -0600113
dchill426262d052012-11-24 18:41:13 -0500114 // Get package paths and filename case variations to search
Andrey Andreev662e3422013-01-28 21:19:13 +0200115 $CI = get_instance();
dchill426262d052012-11-24 18:41:13 -0500116 $paths = $CI->load->get_package_paths(TRUE);
dchill426262d052012-11-24 18:41:13 -0500117
118 // Is there an extension?
119 $class_name = $prefix.$child_name;
Andrey Andreev662e3422013-01-28 21:19:13 +0200120 $found = class_exists($class_name, FALSE);
dchill426262d052012-11-24 18:41:13 -0500121 if ( ! $found)
122 {
123 // Check for subclass file
124 foreach ($paths as $path)
125 {
Andrey Andreev7e83f322012-11-25 16:03:21 +0200126 // Does the file exist?
127 $file = $path.'libraries/'.$this->lib_name.'/drivers/'.$prefix.$child_name.'.php';
128 if (file_exists($file))
dchill426262d052012-11-24 18:41:13 -0500129 {
Andrey Andreev7e83f322012-11-25 16:03:21 +0200130 // Yes - require base class from BASEPATH
131 $basepath = BASEPATH.'libraries/'.$this->lib_name.'/drivers/'.$child_name.'.php';
132 if ( ! file_exists($basepath))
dchill426262d052012-11-24 18:41:13 -0500133 {
Andrey Andreev7e83f322012-11-25 16:03:21 +0200134 $msg = 'Unable to load the requested class: CI_'.$child_name;
135 log_message('error', $msg);
136 show_error($msg);
dchill426262d052012-11-24 18:41:13 -0500137 }
Andrey Andreev7e83f322012-11-25 16:03:21 +0200138
139 // Include both sources and mark found
Andrey Andreev662e3422013-01-28 21:19:13 +0200140 include_once($basepath);
141 include_once($file);
Andrey Andreev7e83f322012-11-25 16:03:21 +0200142 $found = TRUE;
143 break;
dchill426262d052012-11-24 18:41:13 -0500144 }
145 }
146 }
147
148 // Do we need to search for the class?
149 if ( ! $found)
150 {
151 // Use standard class name
152 $class_name = 'CI_'.$child_name;
Andrey Andreev662e3422013-01-28 21:19:13 +0200153 if ( ! class_exists($class_name, FALSE))
dchill426262d052012-11-24 18:41:13 -0500154 {
155 // Check package paths
156 foreach ($paths as $path)
157 {
Andrey Andreev7e83f322012-11-25 16:03:21 +0200158 // Does the file exist?
159 $file = $path.'libraries/'.$this->lib_name.'/drivers/'.$child_name.'.php';
160 if (file_exists($file))
dchill426262d052012-11-24 18:41:13 -0500161 {
Andrey Andreev7e83f322012-11-25 16:03:21 +0200162 // Include source
Andrey Andreev662e3422013-01-28 21:19:13 +0200163 include_once($file);
Andrey Andreev7e83f322012-11-25 16:03:21 +0200164 break;
Derek Jones8dca0412010-03-05 13:01:44 -0600165 }
166 }
Derek Jones8dca0412010-03-05 13:01:44 -0600167 }
Derek Jones8dca0412010-03-05 13:01:44 -0600168 }
Barry Mienydd671972010-10-04 16:33:58 +0200169
dchill426262d052012-11-24 18:41:13 -0500170 // Did we finally find the class?
Andrey Andreev662e3422013-01-28 21:19:13 +0200171 if ( ! class_exists($class_name, FALSE))
dchill426262d052012-11-24 18:41:13 -0500172 {
Andrey Andreev662e3422013-01-28 21:19:13 +0200173 if (class_exists($child_name, FALSE))
William Knauss401fb492012-11-27 00:01:03 -0500174 {
175 $class_name = $child_name;
176 }
177 else
178 {
179 $msg = 'Unable to load the requested driver: '.$class_name;
180 log_message('error', $msg);
181 show_error($msg);
182 }
dchill426262d052012-11-24 18:41:13 -0500183 }
184
Andrey Andreev7e83f322012-11-25 16:03:21 +0200185 // Instantiate, decorate and add child
186 $obj = new $class_name();
dchill426262d052012-11-24 18:41:13 -0500187 $obj->decorate($this);
188 $this->$child = $obj;
189 return $this->$child;
Derek Jones8dca0412010-03-05 13:01:44 -0600190 }
Derek Jones8dca0412010-03-05 13:01:44 -0600191
Derek Jones8dca0412010-03-05 13:01:44 -0600192}
Derek Jones8dca0412010-03-05 13:01:44 -0600193
Timothy Warren0688ac92012-04-20 10:25:04 -0400194// --------------------------------------------------------------------------
Derek Jones8dca0412010-03-05 13:01:44 -0600195
196/**
197 * CodeIgniter Driver Class
198 *
199 * This class enables you to create drivers for a Library based on the Driver Library.
200 * It handles the drivers' access to the parent library
201 *
202 * @package CodeIgniter
203 * @subpackage Libraries
204 * @category Libraries
205 * @author EllisLab Dev Team
Barry Mienydd671972010-10-04 16:33:58 +0200206 * @link
Derek Jones8dca0412010-03-05 13:01:44 -0600207 */
208class CI_Driver {
Barry Mienydd671972010-10-04 16:33:58 +0200209
Timothy Warren0688ac92012-04-20 10:25:04 -0400210 /**
211 * Instance of the parent class
212 *
213 * @var object
214 */
Andrey Andreev8486e9c2012-03-26 20:24:12 +0300215 protected $_parent;
Derek Jones8dca0412010-03-05 13:01:44 -0600216
Timothy Warren0688ac92012-04-20 10:25:04 -0400217 /**
218 * List of methods in the parent class
219 *
220 * @var array
221 */
Andrey Andreev8486e9c2012-03-26 20:24:12 +0300222 protected $_methods = array();
Andrey Andreev56454792012-05-17 14:32:19 +0300223
Timothy Warren0688ac92012-04-20 10:25:04 -0400224 /**
225 * List of properties in the parent class
226 *
227 * @var array
228 */
Andrey Andreev8486e9c2012-03-26 20:24:12 +0300229 protected $_properties = array();
Derek Jones8dca0412010-03-05 13:01:44 -0600230
Timothy Warren0688ac92012-04-20 10:25:04 -0400231 /**
232 * Array of methods and properties for the parent class(es)
233 *
Andrey Andreev5fd3ae82012-10-24 14:55:35 +0300234 * @static
235 * @var array
Timothy Warren0688ac92012-04-20 10:25:04 -0400236 */
Andrey Andreev8486e9c2012-03-26 20:24:12 +0300237 protected static $_reflections = array();
Derek Jones8dca0412010-03-05 13:01:44 -0600238
239 /**
240 * Decorate
241 *
242 * Decorates the child with the parent driver lib's methods and properties
243 *
Derek Jones8dca0412010-03-05 13:01:44 -0600244 * @param object
245 * @return void
246 */
Greg Akera9263282010-11-10 15:26:43 -0600247 public function decorate($parent)
Derek Jones8dca0412010-03-05 13:01:44 -0600248 {
Andrey Andreev8486e9c2012-03-26 20:24:12 +0300249 $this->_parent = $parent;
Barry Mienydd671972010-10-04 16:33:58 +0200250
Derek Jones8dca0412010-03-05 13:01:44 -0600251 // Lock down attributes to what is defined in the class
252 // and speed up references in magic methods
Barry Mienydd671972010-10-04 16:33:58 +0200253
Derek Jones8dca0412010-03-05 13:01:44 -0600254 $class_name = get_class($parent);
Barry Mienydd671972010-10-04 16:33:58 +0200255
Andrey Andreev8486e9c2012-03-26 20:24:12 +0300256 if ( ! isset(self::$_reflections[$class_name]))
Derek Jones8dca0412010-03-05 13:01:44 -0600257 {
258 $r = new ReflectionObject($parent);
Barry Mienydd671972010-10-04 16:33:58 +0200259
Derek Jones8dca0412010-03-05 13:01:44 -0600260 foreach ($r->getMethods() as $method)
261 {
262 if ($method->isPublic())
263 {
Andrey Andreev8486e9c2012-03-26 20:24:12 +0300264 $this->_methods[] = $method->getName();
Derek Jones8dca0412010-03-05 13:01:44 -0600265 }
266 }
267
Pascal Kriete14287f32011-02-14 13:39:34 -0500268 foreach ($r->getProperties() as $prop)
Derek Jones8dca0412010-03-05 13:01:44 -0600269 {
270 if ($prop->isPublic())
271 {
Andrey Andreev8486e9c2012-03-26 20:24:12 +0300272 $this->_properties[] = $prop->getName();
Derek Jones8dca0412010-03-05 13:01:44 -0600273 }
274 }
Barry Mienydd671972010-10-04 16:33:58 +0200275
Andrey Andreev8486e9c2012-03-26 20:24:12 +0300276 self::$_reflections[$class_name] = array($this->_methods, $this->_properties);
Derek Jones8dca0412010-03-05 13:01:44 -0600277 }
278 else
279 {
Andrey Andreev8486e9c2012-03-26 20:24:12 +0300280 list($this->_methods, $this->_properties) = self::$_reflections[$class_name];
Derek Jones8dca0412010-03-05 13:01:44 -0600281 }
282 }
Barry Mienydd671972010-10-04 16:33:58 +0200283
Derek Jones8dca0412010-03-05 13:01:44 -0600284 // --------------------------------------------------------------------
Barry Mienydd671972010-10-04 16:33:58 +0200285
Derek Jones8dca0412010-03-05 13:01:44 -0600286 /**
287 * __call magic method
288 *
289 * Handles access to the parent driver library's methods
290 *
Derek Jones8dca0412010-03-05 13:01:44 -0600291 * @param string
292 * @param array
293 * @return mixed
294 */
295 public function __call($method, $args = array())
296 {
Andrey Andreev8486e9c2012-03-26 20:24:12 +0300297 if (in_array($method, $this->_methods))
Derek Jones8dca0412010-03-05 13:01:44 -0600298 {
Andrey Andreev8486e9c2012-03-26 20:24:12 +0300299 return call_user_func_array(array($this->_parent, $method), $args);
Derek Jones8dca0412010-03-05 13:01:44 -0600300 }
301
Andrey Andreeva0471dc2014-11-04 19:22:38 +0200302 throw new BadMethodCallException('No such method: '.$method.'()');
Derek Jones8dca0412010-03-05 13:01:44 -0600303 }
304
305 // --------------------------------------------------------------------
Barry Mienydd671972010-10-04 16:33:58 +0200306
Derek Jones8dca0412010-03-05 13:01:44 -0600307 /**
308 * __get magic method
309 *
310 * Handles reading of the parent driver library's properties
311 *
Derek Jones8dca0412010-03-05 13:01:44 -0600312 * @param string
313 * @return mixed
314 */
Greg Akera9263282010-11-10 15:26:43 -0600315 public function __get($var)
Derek Jones8dca0412010-03-05 13:01:44 -0600316 {
Andrey Andreev8486e9c2012-03-26 20:24:12 +0300317 if (in_array($var, $this->_properties))
Derek Jones8dca0412010-03-05 13:01:44 -0600318 {
Andrey Andreev8486e9c2012-03-26 20:24:12 +0300319 return $this->_parent->$var;
Derek Jones8dca0412010-03-05 13:01:44 -0600320 }
321 }
322
323 // --------------------------------------------------------------------
Barry Mienydd671972010-10-04 16:33:58 +0200324
Derek Jones8dca0412010-03-05 13:01:44 -0600325 /**
326 * __set magic method
327 *
328 * Handles writing to the parent driver library's properties
329 *
Derek Jones8dca0412010-03-05 13:01:44 -0600330 * @param string
331 * @param array
332 * @return mixed
333 */
Greg Akera9263282010-11-10 15:26:43 -0600334 public function __set($var, $val)
Derek Jones8dca0412010-03-05 13:01:44 -0600335 {
Andrey Andreev8486e9c2012-03-26 20:24:12 +0300336 if (in_array($var, $this->_properties))
Derek Jones8dca0412010-03-05 13:01:44 -0600337 {
Andrey Andreev8486e9c2012-03-26 20:24:12 +0300338 $this->_parent->$var = $val;
Derek Jones8dca0412010-03-05 13:01:44 -0600339 }
340 }
Barry Mienydd671972010-10-04 16:33:58 +0200341
Derek Jones8dca0412010-03-05 13:01:44 -0600342}