summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--.travis.yml3
-rw-r--r--system/core/Loader.php13
-rw-r--r--system/database/DB_forge.php17
-rw-r--r--system/database/DB_utility.php2
-rw-r--r--system/database/drivers/cubrid/cubrid_forge.php15
-rw-r--r--system/database/drivers/mysql/mysql_forge.php15
-rw-r--r--system/database/drivers/mysqli/mysqli_forge.php15
-rw-r--r--system/database/drivers/pdo/subdrivers/pdo_cubrid_forge.php15
-rw-r--r--system/database/drivers/pdo/subdrivers/pdo_mysql_forge.php15
-rw-r--r--system/libraries/Cache/Cache.php12
-rw-r--r--system/libraries/Driver.php111
-rw-r--r--system/libraries/Session/Session.php20
-rw-r--r--tests/codeigniter/database/DB_driver_test.php5
-rw-r--r--tests/codeigniter/helpers/language_helper_test.php4
-rw-r--r--tests/codeigniter/libraries/Calendar_test.php13
-rw-r--r--tests/codeigniter/libraries/Driver_test.php176
-rw-r--r--tests/codeigniter/libraries/Session_test.php74
-rw-r--r--tests/codeigniter/libraries/Upload_test.php3
-rw-r--r--tests/mocks/core/lang.php15
-rw-r--r--tests/mocks/database/config/mysqli.php34
-rw-r--r--tests/mocks/database/drivers/mysqli.php17
-rw-r--r--tests/mocks/libraries/calendar.php25
-rw-r--r--tests/mocks/libraries/driver.php27
-rw-r--r--tests/mocks/libraries/session.php7
-rw-r--r--tests/travis/mysqli.phpunit.xml25
-rw-r--r--user_guide_src/source/changelog.rst1
-rw-r--r--user_guide_src/source/installation/upgrade_300.rst16
-rw-r--r--user_guide_src/source/libraries/sessions.rst5
28 files changed, 508 insertions, 192 deletions
diff --git a/.travis.yml b/.travis.yml
index a1635eaa8..070b23c8a 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -6,6 +6,7 @@ php:
env:
- DB=mysql
+ - DB=mysqli
- DB=pgsql
- DB=sqlite
- DB=pdo/mysql
@@ -17,7 +18,7 @@ before_script:
- php composer.phar install
- sh -c "if [ '$DB' = 'pgsql' ] || [ '$DB' = 'pdo/pgsql' ]; then psql -c 'DROP DATABASE IF EXISTS ci_test;' -U postgres; fi"
- sh -c "if [ '$DB' = 'pgsql' ] || [ '$DB' = 'pdo/pgsql' ]; then psql -c 'create database ci_test;' -U postgres; fi"
- - sh -c "if [ '$DB' = 'mysql' ] || [ '$DB' = 'pdo/mysql' ]; then mysql -e 'create database IF NOT EXISTS ci_test;'; fi"
+ - sh -c "if [ '$DB' = 'mysql' ] || [ '$DB' = 'mysqli' ] || [ '$DB' = 'pdo/mysql' ]; then mysql -e 'create database IF NOT EXISTS ci_test;'; fi"
script: phpunit --coverage-text --configuration tests/travis/$DB.phpunit.xml
diff --git a/system/core/Loader.php b/system/core/Loader.php
index 1e6eafe8a..651507470 100644
--- a/system/core/Loader.php
+++ b/system/core/Loader.php
@@ -669,6 +669,12 @@ class CI_Loader {
return FALSE;
}
+ if ( ! class_exists('CI_Driver_Library'))
+ {
+ // We aren't instantiating an object here, just making the base class available
+ require BASEPATH.'libraries/Driver.php';
+ }
+
// We can save the loader some time since Drivers will *always* be in a subfolder,
// and typically identically named to the library
if ( ! strpos($library, '/'))
@@ -949,13 +955,6 @@ class CI_Loader {
// Get the filename from the path
$class = substr($class, $last_slash);
-
- // Check for match and driver base class
- if (strtolower(trim($subdir, '/')) == strtolower($class) && ! class_exists('CI_Driver_Library'))
- {
- // We aren't instantiating an object here, just making the base class available
- require BASEPATH.'libraries/Driver.php';
- }
}
// We'll test for both lowercase and capitalized versions of the file name
diff --git a/system/database/DB_forge.php b/system/database/DB_forge.php
index bb1ee4809..59c3baf8b 100644
--- a/system/database/DB_forge.php
+++ b/system/database/DB_forge.php
@@ -402,7 +402,7 @@ abstract class CI_DB_forge {
// Are indexes created from within the CREATE TABLE statement? (e.g. in MySQL)
if ($this->_create_table_keys === TRUE)
{
- $columns .= $this->_process_indexes();
+ $columns .= $this->_process_indexes($table);
}
// _create_table will usually have the following format: "%s %s (%s\n)"
@@ -962,14 +962,25 @@ abstract class CI_DB_forge {
* @param string $table
* @return string
*/
- protected function _process_indexes($table = NULL)
+ protected function _process_indexes($table)
{
$table = $this->db->escape_identifiers($table);
$sqls = array();
for ($i = 0, $c = count($this->keys); $i < $c; $i++)
{
- if ( ! isset($this->fields[$this->keys[$i]]))
+ if (is_array($this->keys[$i]))
+ {
+ for ($i2 = 0, $c2 = count($this->keys[$i]); $i2 < $c2; $i2++)
+ {
+ if ( ! isset($this->fields[$this->keys[$i][$i2]]))
+ {
+ unset($this->keys[$i][$i2]);
+ continue;
+ }
+ }
+ }
+ elseif ( ! isset($this->fields[$this->keys[$i]]))
{
unset($this->keys[$i]);
continue;
diff --git a/system/database/DB_utility.php b/system/database/DB_utility.php
index a32fd4455..c4140aef3 100644
--- a/system/database/DB_utility.php
+++ b/system/database/DB_utility.php
@@ -146,7 +146,7 @@ abstract class CI_DB_utility {
if ($query !== FALSE)
{
$query = $query->result_array();
- return current($res);
+ return current($query);
}
return FALSE;
diff --git a/system/database/drivers/cubrid/cubrid_forge.php b/system/database/drivers/cubrid/cubrid_forge.php
index 9a7cdb805..2a737c5ed 100644
--- a/system/database/drivers/cubrid/cubrid_forge.php
+++ b/system/database/drivers/cubrid/cubrid_forge.php
@@ -179,13 +179,24 @@ class CI_DB_cubrid_forge extends CI_DB_forge {
* @param string $table (ignored)
* @return string
*/
- protected function _process_indexes($table = NULL)
+ protected function _process_indexes($table)
{
$sql = '';
for ($i = 0, $c = count($this->keys); $i < $c; $i++)
{
- if ( ! isset($this->fields[$this->keys[$i]]))
+ if (is_array($this->keys[$i]))
+ {
+ for ($i2 = 0, $c2 = count($this->keys[$i]); $i2 < $c2; $i2++)
+ {
+ if ( ! isset($this->fields[$this->keys[$i][$i2]]))
+ {
+ unset($this->keys[$i][$i2]);
+ continue;
+ }
+ }
+ }
+ elseif ( ! isset($this->fields[$this->keys[$i]]))
{
unset($this->keys[$i]);
continue;
diff --git a/system/database/drivers/mysql/mysql_forge.php b/system/database/drivers/mysql/mysql_forge.php
index 1e9145e4f..f4394c685 100644
--- a/system/database/drivers/mysql/mysql_forge.php
+++ b/system/database/drivers/mysql/mysql_forge.php
@@ -175,13 +175,24 @@ class CI_DB_mysql_forge extends CI_DB_forge {
* @param string $table (ignored)
* @return string
*/
- protected function _process_indexes($table = NULL)
+ protected function _process_indexes($table)
{
$sql = '';
for ($i = 0, $c = count($this->keys); $i < $c; $i++)
{
- if ( ! isset($this->fields[$this->keys[$i]]))
+ if (is_array($this->keys[$i]))
+ {
+ for ($i2 = 0, $c2 = count($this->keys[$i]); $i2 < $c2; $i2++)
+ {
+ if ( ! isset($this->fields[$this->keys[$i][$i2]]))
+ {
+ unset($this->keys[$i][$i2]);
+ continue;
+ }
+ }
+ }
+ elseif ( ! isset($this->fields[$this->keys[$i]]))
{
unset($this->keys[$i]);
continue;
diff --git a/system/database/drivers/mysqli/mysqli_forge.php b/system/database/drivers/mysqli/mysqli_forge.php
index 1a6e284ee..f29ea5ade 100644
--- a/system/database/drivers/mysqli/mysqli_forge.php
+++ b/system/database/drivers/mysqli/mysqli_forge.php
@@ -175,13 +175,24 @@ class CI_DB_mysqli_forge extends CI_DB_forge {
* @param string $table (ignored)
* @return string
*/
- protected function _process_indexes($table = NULL)
+ protected function _process_indexes($table)
{
$sql = '';
for ($i = 0, $c = count($this->keys); $i < $c; $i++)
{
- if ( ! isset($this->fields[$this->keys[$i]]))
+ if (is_array($this->keys[$i]))
+ {
+ for ($i2 = 0, $c2 = count($this->keys[$i]); $i2 < $c2; $i2++)
+ {
+ if ( ! isset($this->fields[$this->keys[$i][$i2]]))
+ {
+ unset($this->keys[$i][$i2]);
+ continue;
+ }
+ }
+ }
+ elseif ( ! isset($this->fields[$this->keys[$i]]))
{
unset($this->keys[$i]);
continue;
diff --git a/system/database/drivers/pdo/subdrivers/pdo_cubrid_forge.php b/system/database/drivers/pdo/subdrivers/pdo_cubrid_forge.php
index cb7d9e697..ebf4b15d6 100644
--- a/system/database/drivers/pdo/subdrivers/pdo_cubrid_forge.php
+++ b/system/database/drivers/pdo/subdrivers/pdo_cubrid_forge.php
@@ -179,13 +179,24 @@ class CI_DB_pdo_cubrid_forge extends CI_DB_pdo_forge {
* @param string $table (ignored)
* @return string
*/
- protected function _process_indexes($table = NULL)
+ protected function _process_indexes($table)
{
$sql = '';
for ($i = 0, $c = count($this->keys); $i < $c; $i++)
{
- if ( ! isset($this->fields[$this->keys[$i]]))
+ if (is_array($this->keys[$i]))
+ {
+ for ($i2 = 0, $c2 = count($this->keys[$i]); $i2 < $c2; $i2++)
+ {
+ if ( ! isset($this->fields[$this->keys[$i][$i2]]))
+ {
+ unset($this->keys[$i][$i2]);
+ continue;
+ }
+ }
+ }
+ elseif ( ! isset($this->fields[$this->keys[$i]]))
{
unset($this->keys[$i]);
continue;
diff --git a/system/database/drivers/pdo/subdrivers/pdo_mysql_forge.php b/system/database/drivers/pdo/subdrivers/pdo_mysql_forge.php
index 85d9445d3..5a6de6b2d 100644
--- a/system/database/drivers/pdo/subdrivers/pdo_mysql_forge.php
+++ b/system/database/drivers/pdo/subdrivers/pdo_mysql_forge.php
@@ -189,13 +189,24 @@ class CI_DB_pdo_mysql_forge extends CI_DB_pdo_forge {
* @param string $table (ignored)
* @return string
*/
- protected function _process_indexes($table = NULL)
+ protected function _process_indexes($table)
{
$sql = '';
for ($i = 0, $c = count($this->keys); $i < $c; $i++)
{
- if ( ! isset($this->fields[$this->keys[$i]]))
+ if (is_array($this->keys[$i]))
+ {
+ for ($i2 = 0, $c2 = count($this->keys[$i]); $i2 < $c2; $i2++)
+ {
+ if ( ! isset($this->fields[$this->keys[$i][$i2]]))
+ {
+ unset($this->keys[$i][$i2]);
+ continue;
+ }
+ }
+ }
+ elseif ( ! isset($this->fields[$this->keys[$i]]))
{
unset($this->keys[$i]);
continue;
diff --git a/system/libraries/Cache/Cache.php b/system/libraries/Cache/Cache.php
index e76fdc557..48bd9581a 100644
--- a/system/libraries/Cache/Cache.php
+++ b/system/libraries/Cache/Cache.php
@@ -43,12 +43,12 @@ class CI_Cache extends CI_Driver_Library {
* @var array
*/
protected $valid_drivers = array(
- 'cache_apc',
- 'cache_dummy',
- 'cache_file',
- 'cache_memcached',
- 'cache_redis',
- 'cache_wincache'
+ 'apc',
+ 'dummy',
+ 'file',
+ 'memcached',
+ 'redis',
+ 'wincache'
);
/**
diff --git a/system/libraries/Driver.php b/system/libraries/Driver.php
index 621d22631..72f376466 100644
--- a/system/libraries/Driver.php
+++ b/system/libraries/Driver.php
@@ -60,8 +60,8 @@ class CI_Driver_Library {
* The first time a child is used it won't exist, so we instantiate it
* subsequents calls will go straight to the proper child.
*
- * @param string Child class name
- * @return object Child class
+ * @param string Child class name
+ * @return object Child class
*/
public function __get($child)
{
@@ -74,61 +74,102 @@ class CI_Driver_Library {
*
* Separate load_driver call to support explicit driver load by library or user
*
- * @param string Child class name
- * @return object Child class
+ * @param string Driver name (w/o parent prefix)
+ * @return object Child class
*/
public function load_driver($child)
{
+ // Get CodeIgniter instance and subclass prefix
+ $CI = get_instance();
+ $prefix = (string) $CI->config->item('subclass_prefix');
+
if ( ! isset($this->lib_name))
{
- $this->lib_name = get_class($this);
+ // Get library name without any prefix
+ $this->lib_name = str_replace(array('CI_', $prefix), '', get_class($this));
}
- // The class will be prefixed with the parent lib
- $child_class = $this->lib_name.'_'.$child;
+ // The child will be prefixed with the parent lib
+ $child_name = $this->lib_name.'_'.$child;
+
+ // See if requested child is a valid driver
+ if ( ! in_array($child, $this->valid_drivers))
+ {
+ // The requested driver isn't valid!
+ $msg = 'Invalid driver requested: '.$child_name;
+ log_message('error', $msg);
+ show_error($msg);
+ }
- // Remove the CI_ prefix and lowercase
- $lib_name = ucfirst(strtolower(str_replace('CI_', '', $this->lib_name)));
- $driver_name = strtolower(str_replace('CI_', '', $child_class));
+ // Get package paths and filename case variations to search
+ $paths = $CI->load->get_package_paths(TRUE);
- if (in_array($driver_name, array_map('strtolower', $this->valid_drivers)))
+ // Is there an extension?
+ $class_name = $prefix.$child_name;
+ $found = class_exists($class_name);
+ if ( ! $found)
{
- // check and see if the driver is in a separate file
- if ( ! class_exists($child_class))
+ // Check for subclass file
+ foreach ($paths as $path)
{
- // check application path first
- foreach (get_instance()->load->get_package_paths(TRUE) as $path)
+ // Does the file exist?
+ $file = $path.'libraries/'.$this->lib_name.'/drivers/'.$prefix.$child_name.'.php';
+ if (file_exists($file))
{
- // loves me some nesting!
- foreach (array(ucfirst($driver_name), $driver_name) as $class)
+ // Yes - require base class from BASEPATH
+ $basepath = BASEPATH.'libraries/'.$this->lib_name.'/drivers/'.$child_name.'.php';
+ if ( ! file_exists($basepath))
{
- $filepath = $path.'libraries/'.$lib_name.'/drivers/'.$class.'.php';
-
- if (file_exists($filepath))
- {
- include_once $filepath;
- break 2;
- }
+ $msg = 'Unable to load the requested class: CI_'.$child_name;
+ log_message('error', $msg);
+ show_error($msg);
}
+
+ // Include both sources and mark found
+ include($basepath);
+ include($file);
+ $found = TRUE;
+ break;
}
+ }
+ }
- // it's a valid driver, but the file simply can't be found
- if ( ! class_exists($child_class))
+ // Do we need to search for the class?
+ if ( ! $found)
+ {
+ // Use standard class name
+ $class_name = 'CI_'.$child_name;
+ $found = class_exists($class_name);
+ if ( ! $found)
+ {
+ // Check package paths
+ foreach ($paths as $path)
{
- log_message('error', 'Unable to load the requested driver: '.$child_class);
- show_error('Unable to load the requested driver: '.$child_class);
+ // Does the file exist?
+ $file = $path.'libraries/'.$this->lib_name.'/drivers/'.$child_name.'.php';
+ if (file_exists($file))
+ {
+ // Include source
+ include($file);
+ break;
+ }
}
}
+ }
- $obj = new $child_class;
- $obj->decorate($this);
- $this->$child = $obj;
- return $this->$child;
+ // Did we finally find the class?
+ if ( ! class_exists($class_name))
+ {
+ $msg = 'Unable to load the requested driver: '.$class_name;
+ log_message('error', $msg);
+ show_error($msg);
}
- // The requested driver isn't valid!
- log_message('error', 'Invalid driver requested: '.$child_class);
- show_error('Invalid driver requested: '.$child_class);
+ // Instantiate, decorate and add child
+ $obj = new $class_name();
+ $obj->decorate($this);
+ $this->$child = $obj;
+ return $this->$child;
}
}
diff --git a/system/libraries/Session/Session.php b/system/libraries/Session/Session.php
index 9b011dea3..85a483592 100644
--- a/system/libraries/Session/Session.php
+++ b/system/libraries/Session/Session.php
@@ -107,17 +107,15 @@ class CI_Session extends CI_Driver_Library {
// Get valid drivers list
$this->valid_drivers = array(
- 'Session_native',
- 'Session_cookie'
+ 'native',
+ 'cookie'
);
$key = 'sess_valid_drivers';
$drivers = isset($params[$key]) ? $params[$key] : $CI->config->item($key);
if ($drivers)
{
- is_array($drivers) OR $drivers = array($drivers);
-
// Add driver names to valid list
- foreach ($drivers as $driver)
+ foreach ((array) $drivers as $driver)
{
if ( ! in_array(strtolower($driver), array_map('strtolower', $this->valid_drivers)))
{
@@ -134,9 +132,9 @@ class CI_Session extends CI_Driver_Library {
$driver = 'cookie';
}
- if ( ! in_array('session_'.strtolower($driver), array_map('strtolower', $this->valid_drivers)))
+ if ( ! in_array(strtolower($driver), array_map('strtolower', $this->valid_drivers)))
{
- $this->valid_drivers[] = 'Session_'.$driver;
+ $this->valid_drivers[] = $driver;
}
// Save a copy of parameters in case drivers need access
@@ -178,17 +176,17 @@ class CI_Session extends CI_Driver_Library {
/**
* Select default session storage driver
*
- * @param string Driver classname
+ * @param string Driver name
* @return void
*/
public function select_driver($driver)
{
// Validate driver name
- $lowername = strtolower(str_replace('CI_', '', $driver));
- if (in_array($lowername, array_map('strtolower', $this->valid_drivers)))
+ $prefix = (string) get_instance()->config->item('subclass_prefix');
+ $child = strtolower(str_replace(array('CI_', $prefix, $this->lib_name.'_'), '', $driver));
+ if (in_array($child, array_map('strtolower', $this->valid_drivers)))
{
// See if driver is loaded
- $child = str_replace($this->lib_name.'_', '', $driver);
if (isset($this->$child))
{
// See if driver is already current
diff --git a/tests/codeigniter/database/DB_driver_test.php b/tests/codeigniter/database/DB_driver_test.php
index 1f48ca984..c04c42b09 100644
--- a/tests/codeigniter/database/DB_driver_test.php
+++ b/tests/codeigniter/database/DB_driver_test.php
@@ -21,6 +21,11 @@ class DB_driver_test extends CI_TestCase {
return new Mock_Database_Drivers_Mysql($config);
}
+ protected function mysqli($config)
+ {
+ return new Mock_Database_Drivers_Mysqli($config);
+ }
+
protected function sqlite($config)
{
return new Mock_Database_Drivers_Sqlite($config);
diff --git a/tests/codeigniter/helpers/language_helper_test.php b/tests/codeigniter/helpers/language_helper_test.php
index 06932b9fd..1fe0ef17b 100644
--- a/tests/codeigniter/helpers/language_helper_test.php
+++ b/tests/codeigniter/helpers/language_helper_test.php
@@ -5,7 +5,9 @@ class Language_helper_test extends CI_TestCase {
public function test_lang()
{
$this->helper('language');
- $this->ci_instance_var('lang', new Mock_Core_Lang());
+ $lang = $this->getMock('CI_Lang', array('line'));
+ $lang->expects($this->any())->method('line')->will($this->returnValue(FALSE));
+ $this->ci_instance_var('lang', $lang);
$this->assertFalse(lang(1));
$this->assertEquals('<label for="foo"></label>', lang(1, 'foo'));
diff --git a/tests/codeigniter/libraries/Calendar_test.php b/tests/codeigniter/libraries/Calendar_test.php
index 95668d70d..952e8a8d2 100644
--- a/tests/codeigniter/libraries/Calendar_test.php
+++ b/tests/codeigniter/libraries/Calendar_test.php
@@ -2,12 +2,12 @@
class Calendar_test extends CI_TestCase {
- function __construct()
+ function set_up()
{
- $obj = new stdClass;
- $obj->calendar = new Mock_Libraries_Calendar();
-
- $this->calendar = $obj->calendar;
+ $lang = $this->getMock('CI_Lang', array('load', 'line'));
+ $lang->expects($this->any())->method('line')->will($this->returnValue(FALSE));
+ $this->ci_instance_var('lang', $lang);
+ $this->calendar = new CI_Calendar();
}
function test_initialize()
@@ -20,9 +20,6 @@ class Calendar_test extends CI_TestCase {
$this->assertEquals('monday', $this->calendar->start_day);
}
- /**
- * @covers Mock_Libraries_Calendar::parse_template
- */
function test_generate()
{
$no_events = '<table border="0" cellpadding="4" cellspacing="0">
diff --git a/tests/codeigniter/libraries/Driver_test.php b/tests/codeigniter/libraries/Driver_test.php
new file mode 100644
index 000000000..fb5f3f020
--- /dev/null
+++ b/tests/codeigniter/libraries/Driver_test.php
@@ -0,0 +1,176 @@
+<?php
+
+/**
+ * Driver library base class unit test
+ */
+class Driver_test extends CI_TestCase {
+ /**
+ * Set up test framework
+ */
+ public function set_up()
+ {
+ // Set our subclass prefix
+ $this->subclass = 'Mock_Libraries_';
+ $this->ci_set_config('subclass_prefix', $this->subclass);
+
+ // Mock Loader->get_package_paths
+ $paths = 'get_package_paths';
+ $ldr = $this->getMock('CI_Loader', array($paths));
+ $ldr->expects($this->any())->method($paths)->will($this->returnValue(array(APPPATH, BASEPATH)));
+ $this->ci_instance_var('load', $ldr);
+
+ // Create mock driver library
+ $this->name = 'Driver';
+ $this->lib = new Mock_Libraries_Driver();
+ }
+
+ /**
+ * Test driver child loading
+ */
+ public function test_load_driver()
+ {
+ // Create driver file
+ $driver = 'basic';
+ $file = $this->name.'_'.$driver;
+ $class = 'CI_'.$file;
+ $prop = 'called';
+ $content = '<?php class '.$class.' extends CI_Driver { public $'.$prop.' = FALSE; '.
+ 'public function decorate($parent) { $this->'.$prop.' = TRUE; } }';
+ $this->ci_vfs_create($file, $content, $this->ci_base_root, array('libraries', $this->name, 'drivers'));
+
+ // Make driver valid
+ $this->lib->driver_list($driver);
+
+ // Load driver
+ $this->assertNotNull($this->lib->load_driver($driver));
+
+ // Did lib name get set?
+ $this->assertEquals($this->name, $this->lib->get_name());
+
+ // Was driver loaded?
+ $this->assertObjectHasAttribute($driver, $this->lib);
+ $this->assertAttributeInstanceOf($class, $driver, $this->lib);
+ $this->assertAttributeInstanceOf('CI_Driver', $driver, $this->lib);
+
+ // Was decorate called?
+ $this->assertObjectHasAttribute($prop, $this->lib->$driver);
+ $this->assertTrue($this->lib->$driver->$prop);
+
+ // Do we get an error for an invalid driver?
+ $driver = 'unlisted';
+ $this->setExpectedException('RuntimeException', 'CI Error: Invalid driver requested: '.$this->name.'_'.$driver);
+ $this->lib->load_driver($driver);
+ }
+
+ /**
+ * Test loading lowercase from app path
+ */
+ public function test_load_app_driver()
+ {
+ // Create driver file
+ $driver = 'lowpack';
+ $file = $this->name.'_'.$driver;
+ $class = 'CI_'.$file;
+ $content = '<?php class '.$class.' extends CI_Driver { }';
+ $this->ci_vfs_create($file, $content, $this->ci_app_root,
+ array('libraries', $this->name, 'drivers'));
+
+ // Make valid list
+ $nodriver = 'absent';
+ $this->lib->driver_list(array($driver, $nodriver));
+
+ // Load driver
+ $this->assertNotNull($this->lib->load_driver($driver));
+
+ // Was driver loaded?
+ $this->assertObjectHasAttribute($driver, $this->lib);
+ $this->assertAttributeInstanceOf($class, $driver, $this->lib);
+ $this->assertAttributeInstanceOf('CI_Driver', $driver, $this->lib);
+
+ // Do we get an error for a non-existent driver?
+ $this->setExpectedException('RuntimeException', 'CI Error: Unable to load the requested driver: CI_'.
+ $this->name.'_'.$nodriver);
+ $this->lib->load_driver($nodriver);
+ }
+
+ /**
+ * Test loading driver extension
+ */
+ public function test_load_driver_ext()
+ {
+ // Create base file
+ $driver = 'extend';
+ $base = $this->name.'_'.$driver;
+ $baseclass = 'CI_'.$base;
+ $content = '<?php class '.$baseclass.' extends CI_Driver { }';
+ $this->ci_vfs_create($base, $content, $this->ci_base_root, array('libraries', $this->name, 'drivers'));
+
+ // Create driver file
+ $class = $this->subclass.$base;
+ $content = '<?php class '.$class.' extends '.$baseclass.' { }';
+ $this->ci_vfs_create($class, $content, $this->ci_app_root, array('libraries', $this->name, 'drivers'));
+
+ // Make valid list
+ $this->lib->driver_list($driver);
+
+ // Load driver
+ $this->assertNotNull($this->lib->load_driver($driver));
+
+ // Was driver loaded?
+ $this->assertObjectHasAttribute($driver, $this->lib);
+ $this->assertAttributeInstanceOf($class, $driver, $this->lib);
+ $this->assertAttributeInstanceOf($baseclass, $driver, $this->lib);
+ $this->assertAttributeInstanceOf('CI_Driver', $driver, $this->lib);
+
+ // Create driver extension without base
+ $driver = 'baseless';
+ $base = $this->name.'_'.$driver;
+ $class = $this->subclass.$base;
+ $content = '<?php class '.$class.' extends CI_Driver { }';
+ $this->ci_vfs_create($class, $content, $this->ci_app_root, array('libraries', $this->name, 'drivers'));
+ $this->lib->driver_list($driver);
+
+ // Do we get an error when base class isn't found?
+ $this->setExpectedException('RuntimeException', 'CI Error: Unable to load the requested class: CI_'.$base);
+ $this->lib->load_driver($driver);
+ }
+
+ /**
+ * Test decorating driver with parent attributes
+ */
+ public function test_decorate()
+ {
+ // Create parent with a method and property to access
+ $pclass = 'Test_Parent';
+ $prop = 'parent_prop';
+ $value = 'initial';
+ $method = 'parent_func';
+ $return = 'func return';
+ $code = 'class '.$pclass.' { public $'.$prop.' = \''.$value.'\'; '.
+ 'public function '.$method.'() { return \''.$return.'\'; } }';
+ eval($code);
+ $parent = new $pclass();
+
+ // Create child driver to decorate
+ $class = 'Test_Driver';
+ eval('class '.$class.' extends CI_Driver { }');
+ $child = new $class();
+
+ // Decorate child
+ $child->decorate($parent);
+
+ // Do we get the initial parent property value?
+ $this->assertEquals($value, $child->$prop);
+
+ // Can we change the parent property?
+ $newval = 'changed';
+ $child->$prop = $newval;
+ $this->assertEquals($newval, $parent->$prop);
+
+ // Do we get back the updated value?
+ $this->assertEquals($newval, $child->$prop);
+
+ // Can we call the parent method?
+ $this->assertEquals($return, $child->$method());
+ }
+}
diff --git a/tests/codeigniter/libraries/Session_test.php b/tests/codeigniter/libraries/Session_test.php
index 14469f7fa..e675b4ed7 100644
--- a/tests/codeigniter/libraries/Session_test.php
+++ b/tests/codeigniter/libraries/Session_test.php
@@ -6,8 +6,8 @@
class Session_test extends CI_TestCase {
protected $settings = array(
'use_cookies' => 0,
- 'use_only_cookies' => 0,
- 'cache_limiter' => false
+ 'use_only_cookies' => 0,
+ 'cache_limiter' => false
);
protected $setting_vals = array();
protected $cookie_vals;
@@ -28,11 +28,12 @@ class Session_test extends CI_TestCase {
$this->cookie_vals = $_COOKIE;
$_COOKIE = array();
+ // Set subclass prefix to match our mock
+ $this->ci_set_config('subclass_prefix', 'Mock_Libraries_');
+
// Establish necessary support classes
- $cfg = $this->ci_core_class('cfg');
- $ldr = $this->ci_core_class('load');
$ci = $this->ci_instance();
- $ci->config = new $cfg();
+ $ldr = $this->ci_core_class('load');
$ci->load = new $ldr();
$ci->input = new Mock_Core_Input(NULL, NULL);
@@ -56,11 +57,7 @@ class Session_test extends CI_TestCase {
'sess_time_to_update' => 300,
'time_reference' => 'local',
'cookie_prefix' => '',
- 'encryption_key' => 'foobar',
- 'sess_valid_drivers' => array(
- 'Mock_Libraries_Session_native',
- 'Mock_Libraries_Session_cookie'
- )
+ 'encryption_key' => 'foobar'
);
$this->session = new Mock_Libraries_Session($config);
}
@@ -83,9 +80,6 @@ class Session_test extends CI_TestCase {
/**
* Test set_userdata() function
- *
- * @covers CI_Session::set_userdata
- * @covers CI_Session::userdata
*/
public function test_set_userdata()
{
@@ -117,8 +111,6 @@ class Session_test extends CI_TestCase {
/**
* Test the has_userdata() function
- *
- * @covers CI_Session::has_userdata
*/
public function test_has_userdata()
{
@@ -141,8 +133,6 @@ class Session_test extends CI_TestCase {
/**
* Test the all_userdata() function
- *
- * @covers CI_Session::all_userdata
*/
public function test_all_userdata()
{
@@ -150,16 +140,16 @@ class Session_test extends CI_TestCase {
$cdata = array(
'one' => 'first',
'two' => 'second',
- 'three' => 'third',
- 'foo' => 'bar',
- 'bar' => 'baz'
+ 'three' => 'third',
+ 'foo' => 'bar',
+ 'bar' => 'baz'
);
$ndata = array(
'one' => 'gold',
- 'two' => 'silver',
- 'three' => 'bronze',
- 'foo' => 'baz',
- 'bar' => 'foo'
+ 'two' => 'silver',
+ 'three' => 'bronze',
+ 'foo' => 'baz',
+ 'bar' => 'foo'
);
$this->session->cookie->set_userdata($cdata);
$this->session->native->set_userdata($ndata);
@@ -177,8 +167,6 @@ class Session_test extends CI_TestCase {
/**
* Test the unset_userdata() function
- *
- * @covers CI_Session::unset_userdata
*/
public function test_unset_userdata()
{
@@ -202,9 +190,6 @@ class Session_test extends CI_TestCase {
/**
* Test the flashdata() functions
- *
- * @covers CI_Session::set_flashdata
- * @covers CI_Session::flashdata
*/
public function test_flashdata()
{
@@ -234,8 +219,6 @@ class Session_test extends CI_TestCase {
/**
* Test the keep_flashdata() function
- *
- * @covers CI_Session::keep_flashdata
*/
public function test_keep_flashdata()
{
@@ -271,25 +254,23 @@ class Session_test extends CI_TestCase {
/**
* Test the all_flashdata() function
- *
- * @covers CI_Session::all_flashdata
*/
public function test_all_flashdata()
{
// Set a specific series of data for each driver
$cdata = array(
'one' => 'first',
- 'two' => 'second',
- 'three' => 'third',
- 'foo' => 'bar',
- 'bar' => 'baz'
+ 'two' => 'second',
+ 'three' => 'third',
+ 'foo' => 'bar',
+ 'bar' => 'baz'
);
$ndata = array(
'one' => 'gold',
- 'two' => 'silver',
- 'three' => 'bronze',
- 'foo' => 'baz',
- 'bar' => 'foo'
+ 'two' => 'silver',
+ 'three' => 'bronze',
+ 'foo' => 'baz',
+ 'bar' => 'foo'
);
$this->session->cookie->set_flashdata($cdata);
$this->session->native->set_flashdata($ndata);
@@ -303,9 +284,6 @@ class Session_test extends CI_TestCase {
/**
* Test the tempdata() functions
- *
- * @covers CI_Session::set_tempdata
- * @covers CI_Session::tempdata
*/
public function test_set_tempdata()
{
@@ -332,8 +310,6 @@ class Session_test extends CI_TestCase {
/**
* Test the unset_tempdata() function
- *
- * @covers CI_Session::unset_tempdata
*/
public function test_unset_tempdata()
{
@@ -357,8 +333,6 @@ class Session_test extends CI_TestCase {
/**
* Test the sess_regenerate() function
- *
- * @covers CI_Session::sess_regenerate
*/
public function test_sess_regenerate()
{
@@ -378,8 +352,6 @@ class Session_test extends CI_TestCase {
/**
* Test the sess_destroy() function
- *
- * @covers CI_Session::sess_destroy
*/
public function test_sess_destroy()
{
@@ -399,4 +371,4 @@ class Session_test extends CI_TestCase {
$this->session->native->sess_destroy();
$this->assertNull($this->session->native->userdata($key));
}
-} \ No newline at end of file
+}
diff --git a/tests/codeigniter/libraries/Upload_test.php b/tests/codeigniter/libraries/Upload_test.php
index 546cebc59..1bd8f1430 100644
--- a/tests/codeigniter/libraries/Upload_test.php
+++ b/tests/codeigniter/libraries/Upload_test.php
@@ -7,7 +7,8 @@ class Upload_test extends CI_TestCase {
$ci = $this->ci_instance();
$ci->upload = new Mock_Libraries_Upload();
$ci->security = new Mock_Core_Security();
- $ci->lang = new Mock_Core_Lang();
+ $ci->lang = $this->getMock('CI_Lang', array('load', 'line'));
+ $ci->lang->expects($this->any())->method('line')->will($this->returnValue(FALSE));
$this->upload = $ci->upload;
}
diff --git a/tests/mocks/core/lang.php b/tests/mocks/core/lang.php
deleted file mode 100644
index 27ea3faba..000000000
--- a/tests/mocks/core/lang.php
+++ /dev/null
@@ -1,15 +0,0 @@
-<?php
-
-class Mock_Core_Lang extends CI_Lang {
-
- public function line($line = '')
- {
- return FALSE;
- }
-
- public function load($langfile, $idiom = '', $return = FALSE, $add_suffix = TRUE, $alt_path = '')
- {
- return;
- }
-
-} \ No newline at end of file
diff --git a/tests/mocks/database/config/mysqli.php b/tests/mocks/database/config/mysqli.php
new file mode 100644
index 000000000..5dd08abb2
--- /dev/null
+++ b/tests/mocks/database/config/mysqli.php
@@ -0,0 +1,34 @@
+<?php
+
+return array(
+
+ // Typical Database configuration
+ 'mysqli' => array(
+ 'dsn' => '',
+ 'hostname' => 'localhost',
+ 'username' => 'travis',
+ 'password' => '',
+ 'database' => 'ci_test',
+ 'dbdriver' => 'mysqli'
+ ),
+
+ // Database configuration with failover
+ 'mysqli_failover' => array(
+ 'dsn' => '',
+ 'hostname' => 'localhost',
+ 'username' => 'not_travis',
+ 'password' => 'wrong password',
+ 'database' => 'not_ci_test',
+ 'dbdriver' => 'mysqli',
+ 'failover' => array(
+ array(
+ 'dsn' => '',
+ 'hostname' => 'localhost',
+ 'username' => 'travis',
+ 'password' => '',
+ 'database' => 'ci_test',
+ 'dbdriver' => 'mysqli',
+ )
+ )
+ )
+); \ No newline at end of file
diff --git a/tests/mocks/database/drivers/mysqli.php b/tests/mocks/database/drivers/mysqli.php
new file mode 100644
index 000000000..73c35b609
--- /dev/null
+++ b/tests/mocks/database/drivers/mysqli.php
@@ -0,0 +1,17 @@
+<?php
+
+class Mock_Database_Drivers_Mysqli extends Mock_Database_DB_Driver {
+
+ /**
+ * Instantiate the database driver
+ *
+ * @param string DB Driver class name
+ * @param array DB configuration to set
+ * @return void
+ */
+ public function __construct($config = array())
+ {
+ parent::__construct('CI_DB_mysqli_driver', $config);
+ }
+
+} \ No newline at end of file
diff --git a/tests/mocks/libraries/calendar.php b/tests/mocks/libraries/calendar.php
deleted file mode 100644
index 8fee5365e..000000000
--- a/tests/mocks/libraries/calendar.php
+++ /dev/null
@@ -1,25 +0,0 @@
-<?php
-
-class Mock_Libraries_Calendar extends CI_Calendar {
-
- public function __construct($config = array())
- {
- $this->CI = new stdClass;
- $this->CI->lang = new Mock_Core_Lang();
-
- if ( ! in_array('calendar_lang.php', $this->CI->lang->is_loaded, TRUE))
- {
- $this->CI->lang->load('calendar');
- }
-
- $this->local_time = time();
-
- if (count($config) > 0)
- {
- $this->initialize($config);
- }
-
- log_message('debug', 'Calendar Class Initialized');
- }
-
-} \ No newline at end of file
diff --git a/tests/mocks/libraries/driver.php b/tests/mocks/libraries/driver.php
new file mode 100644
index 000000000..91bb01596
--- /dev/null
+++ b/tests/mocks/libraries/driver.php
@@ -0,0 +1,27 @@
+<?php
+
+/**
+ * Mock library to subclass Driver for testing
+ */
+class Mock_Libraries_Driver extends CI_Driver_Library {
+ /**
+ * Set valid drivers list
+ */
+ public function driver_list($drivers = NULL)
+ {
+ if (empty($drivers))
+ {
+ return $this->valid_drivers;
+ }
+
+ $this->valid_drivers = (array) $drivers;
+ }
+
+ /**
+ * Get library name
+ */
+ public function get_name()
+ {
+ return $this->lib_name;
+ }
+}
diff --git a/tests/mocks/libraries/session.php b/tests/mocks/libraries/session.php
index c6e194f58..11b27cf67 100644
--- a/tests/mocks/libraries/session.php
+++ b/tests/mocks/libraries/session.php
@@ -4,7 +4,6 @@
* Mock library to add testing features to Session driver library
*/
class Mock_Libraries_Session extends CI_Session {
-
/**
* Simulate new page load
*/
@@ -20,7 +19,6 @@ class Mock_Libraries_Session extends CI_Session {
* Mock cookie driver to overload cookie setting
*/
class Mock_Libraries_Session_cookie extends CI_Session_cookie {
-
/**
* Overload _setcookie to manage $_COOKIE values, since actual cookies can't be set in unit testing
*/
@@ -36,8 +34,3 @@ class Mock_Libraries_Session_cookie extends CI_Session_cookie {
}
}
}
-
-/**
- * Mock native driver (just for consistency in loading)
- */
-class Mock_Libraries_Session_native extends CI_Session_native { } \ No newline at end of file
diff --git a/tests/travis/mysqli.phpunit.xml b/tests/travis/mysqli.phpunit.xml
new file mode 100644
index 000000000..1364f8bfa
--- /dev/null
+++ b/tests/travis/mysqli.phpunit.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<phpunit
+ bootstrap="../Bootstrap.php"
+ colors="true"
+ convertNoticesToExceptions="true"
+ convertWarningsToExceptions="true"
+ stopOnError="false"
+ stopOnFailure="false"
+ stopOnIncomplete="false"
+ stopOnSkipped="false">
+ <php>
+ <const name="DB_DRIVER" value="mysqli"/>
+ </php>
+ <testsuites>
+ <testsuite name="CodeIgniter Core Test Suite">
+ <directory suffix="test.php">../codeigniter</directory>
+ </testsuite>
+ </testsuites>
+ <filter>
+ <whitelist addUncoveredFilesFromWhitelist="false">
+ <directory suffix=".php">../../system</directory>
+ </whitelist>
+ </filter>
+</phpunit> \ No newline at end of file
diff --git a/user_guide_src/source/changelog.rst b/user_guide_src/source/changelog.rst
index 5d4757a7e..92989af75 100644
--- a/user_guide_src/source/changelog.rst
+++ b/user_guide_src/source/changelog.rst
@@ -275,7 +275,6 @@ Release Date: Not Released
- Added method ``get_vars()`` to the Loader to retrieve all variables loaded with ``$this->load->vars()``.
- ``_ci_autoloader()`` is now a protected method.
- Added autoloading of drivers with ``$autoload['drivers']``.
- - ``library()`` method will now load drivers as well, for backward compatibility of converted libraries (like :doc:`Session <libraries/sessions>`).
- ``$config['rewrite_short_tags']`` now has no effect when using PHP 5.4 as ``<?=`` will always be available.
- Changed method ``config()`` to return whatever ``CI_Config::load()`` returns instead of always being void.
- :doc:`Input Library <libraries/input>` changes include:
diff --git a/user_guide_src/source/installation/upgrade_300.rst b/user_guide_src/source/installation/upgrade_300.rst
index 0af21b11e..ef5fbdf71 100644
--- a/user_guide_src/source/installation/upgrade_300.rst
+++ b/user_guide_src/source/installation/upgrade_300.rst
@@ -42,9 +42,13 @@ or extensions to work, you need to move them to **application/core/**::
application/libraries/Log.php -> application/core/Log.php
application/libraries/MY_Log.php -> application/core/MY_log.php
-**************************************************************
-Step 5: Add new session driver items to your config/config.php
-**************************************************************
+*********************************************************
+Step 5: Convert your Session usage from library to driver
+*********************************************************
+
+When you load (or autoload) the Session library, you must now load it as a driver instead of a library. This means
+calling ``$this->load->driver('session')`` instead of ``$this->load->library('session')`` and/or listing 'session'
+in ``$autoload['drivers']`` instead of ``$autoload['libraries']``.
With the change from a single Session Library to the new Session Driver, two new config items have been added:
@@ -58,6 +62,10 @@ As the new Session Driver library loads the classic Cookie driver by default and
available as valid drivers, neither of these configuration items are required. However, it is recommended that you
add them for clarity and ease of configuration in the future.
+If you have written a Session extension, you must move it into a 'Session' sub-directory of 'libraries', following the
+standard for Drivers. Also beware that some functions which are not part of the external Session API have moved into
+the drivers, so your extension may have to be broken down into separate library and driver class extensions.
+
***************************************
Step 6: Update your config/database.php
***************************************
@@ -314,4 +322,4 @@ You should now put AFTER clause field names in the field definition array instea
sooner rather than later.
.. note:: This is for MySQL and CUBRID databases only! Other drivers don't support this
- clause and will silently ignore it.
+ clause and will silently ignore it. \ No newline at end of file
diff --git a/user_guide_src/source/libraries/sessions.rst b/user_guide_src/source/libraries/sessions.rst
index aecad3164..36c7c1d32 100644
--- a/user_guide_src/source/libraries/sessions.rst
+++ b/user_guide_src/source/libraries/sessions.rst
@@ -28,10 +28,6 @@ use the $this->load->driver function::
Once loaded, the Sessions library object will be available using:
$this->session
-.. note:: For backward compatibility, the Session class may stil be loaded
- using the $this->load->library function, but converting your applications
- to use $this->load->driver is strongly recommended.
-
How do Sessions work?
=====================
@@ -487,4 +483,3 @@ without making it the initially loaded driver, set 'sess_valid_drivers' in
your config.php file to an array including your driver name::
$config['sess_valid_drivers'] = array('sess_driver');
-