summaryrefslogtreecommitdiffstats
path: root/system
diff options
context:
space:
mode:
Diffstat (limited to 'system')
-rw-r--r--system/.htaccess7
-rw-r--r--[-rwxr-xr-x]system/core/Benchmark.php50
-rw-r--r--[-rwxr-xr-x]system/core/CodeIgniter.php156
-rw-r--r--system/core/Common.php558
-rw-r--r--[-rwxr-xr-x]system/core/Config.php165
-rw-r--r--system/core/Controller.php28
-rw-r--r--[-rwxr-xr-x]system/core/Exceptions.php100
-rw-r--r--[-rwxr-xr-x]system/core/Hooks.php81
-rw-r--r--[-rwxr-xr-x]system/core/Input.php595
-rw-r--r--[-rwxr-xr-x]system/core/Lang.php109
-rw-r--r--system/core/Loader.php523
-rw-r--r--system/core/Log.php (renamed from system/libraries/Log.php)60
-rw-r--r--[-rwxr-xr-x]system/core/Model.php21
-rw-r--r--[-rwxr-xr-x]system/core/Output.php456
-rw-r--r--[-rwxr-xr-x]system/core/Router.php253
-rw-r--r--[-rwxr-xr-x]system/core/Security.php331
-rw-r--r--[-rwxr-xr-x]system/core/URI.php423
-rw-r--r--system/core/Utf8.php73
-rw-r--r--[-rwxr-xr-x]system/database/DB.php102
-rw-r--r--system/database/DB_cache.php80
-rw-r--r--system/database/DB_driver.php691
-rw-r--r--system/database/DB_forge.php778
-rw-r--r--system/database/DB_query_builder.php (renamed from system/database/DB_active_rec.php)1595
-rw-r--r--system/database/DB_result.php421
-rw-r--r--system/database/DB_utility.php104
-rw-r--r--system/database/drivers/cubrid/cubrid_driver.php259
-rw-r--r--system/database/drivers/cubrid/cubrid_forge.php275
-rw-r--r--system/database/drivers/cubrid/cubrid_result.php76
-rw-r--r--system/database/drivers/cubrid/cubrid_utility.php13
-rw-r--r--system/database/drivers/ibase/ibase_driver.php (renamed from system/database/drivers/interbase/interbase_driver.php)232
-rw-r--r--system/database/drivers/ibase/ibase_forge.php243
-rw-r--r--system/database/drivers/ibase/ibase_result.php154
-rw-r--r--system/database/drivers/ibase/ibase_utility.php (renamed from system/database/drivers/interbase/interbase_utility.php)15
-rw-r--r--system/database/drivers/ibase/index.html (renamed from system/database/drivers/interbase/index.html)0
-rw-r--r--system/database/drivers/interbase/interbase_forge.php224
-rw-r--r--system/database/drivers/interbase/interbase_result.php260
-rw-r--r--system/database/drivers/mssql/mssql_driver.php388
-rw-r--r--system/database/drivers/mssql/mssql_forge.php196
-rw-r--r--system/database/drivers/mssql/mssql_result.php49
-rw-r--r--system/database/drivers/mssql/mssql_utility.php22
-rw-r--r--system/database/drivers/mysql/mysql_driver.php231
-rw-r--r--system/database/drivers/mysql/mysql_forge.php228
-rw-r--r--system/database/drivers/mysql/mysql_result.php40
-rw-r--r--system/database/drivers/mysql/mysql_utility.php38
-rw-r--r--system/database/drivers/mysqli/mysqli_driver.php222
-rw-r--r--system/database/drivers/mysqli/mysqli_forge.php229
-rw-r--r--system/database/drivers/mysqli/mysqli_result.php20
-rw-r--r--system/database/drivers/mysqli/mysqli_utility.php145
-rw-r--r--system/database/drivers/oci8/oci8_driver.php305
-rw-r--r--system/database/drivers/oci8/oci8_forge.php146
-rw-r--r--system/database/drivers/oci8/oci8_result.php566
-rw-r--r--system/database/drivers/oci8/oci8_utility.php14
-rw-r--r--system/database/drivers/odbc/odbc_driver.php180
-rw-r--r--system/database/drivers/odbc/odbc_forge.php169
-rw-r--r--system/database/drivers/odbc/odbc_result.php177
-rw-r--r--system/database/drivers/odbc/odbc_utility.php11
-rw-r--r--system/database/drivers/pdo/pdo_driver.php444
-rw-r--r--system/database/drivers/pdo/pdo_forge.php165
-rw-r--r--system/database/drivers/pdo/pdo_result.php133
-rw-r--r--system/database/drivers/pdo/pdo_utility.php11
-rw-r--r--system/database/drivers/pdo/subdrivers/index.html10
-rw-r--r--system/database/drivers/pdo/subdrivers/pdo_4d_driver.php192
-rw-r--r--system/database/drivers/pdo/subdrivers/pdo_4d_forge.php209
-rw-r--r--system/database/drivers/pdo/subdrivers/pdo_cubrid_driver.php247
-rw-r--r--system/database/drivers/pdo/subdrivers/pdo_cubrid_forge.php219
-rw-r--r--system/database/drivers/pdo/subdrivers/pdo_dblib_driver.php329
-rw-r--r--system/database/drivers/pdo/subdrivers/pdo_dblib_forge.php136
-rw-r--r--system/database/drivers/pdo/subdrivers/pdo_firebird_driver.php260
-rw-r--r--system/database/drivers/pdo/subdrivers/pdo_firebird_forge.php229
-rw-r--r--system/database/drivers/pdo/subdrivers/pdo_ibm_driver.php236
-rw-r--r--system/database/drivers/pdo/subdrivers/pdo_ibm_forge.php146
-rw-r--r--system/database/drivers/pdo/subdrivers/pdo_informix_driver.php301
-rw-r--r--system/database/drivers/pdo/subdrivers/pdo_informix_forge.php155
-rw-r--r--system/database/drivers/pdo/subdrivers/pdo_mysql_driver.php283
-rw-r--r--system/database/drivers/pdo/subdrivers/pdo_mysql_forge.php229
-rw-r--r--system/database/drivers/pdo/subdrivers/pdo_oci_driver.php291
-rw-r--r--system/database/drivers/pdo/subdrivers/pdo_oci_forge.php133
-rw-r--r--system/database/drivers/pdo/subdrivers/pdo_odbc_driver.php258
-rw-r--r--system/database/drivers/pdo/subdrivers/pdo_odbc_forge.php62
-rw-r--r--system/database/drivers/pdo/subdrivers/pdo_pgsql_driver.php357
-rw-r--r--system/database/drivers/pdo/subdrivers/pdo_pgsql_forge.php195
-rw-r--r--system/database/drivers/pdo/subdrivers/pdo_sqlite_driver.php202
-rw-r--r--system/database/drivers/pdo/subdrivers/pdo_sqlite_forge.php229
-rw-r--r--system/database/drivers/pdo/subdrivers/pdo_sqlsrv_driver.php363
-rw-r--r--system/database/drivers/pdo/subdrivers/pdo_sqlsrv_forge.php136
-rw-r--r--system/database/drivers/postgre/postgre_driver.php355
-rw-r--r--system/database/drivers/postgre/postgre_forge.php280
-rw-r--r--system/database/drivers/postgre/postgre_result.php20
-rw-r--r--system/database/drivers/postgre/postgre_utility.php22
-rw-r--r--system/database/drivers/sqlite/sqlite_driver.php203
-rw-r--r--system/database/drivers/sqlite/sqlite_forge.php234
-rw-r--r--system/database/drivers/sqlite/sqlite_result.php30
-rw-r--r--system/database/drivers/sqlite/sqlite_utility.php11
-rw-r--r--system/database/drivers/sqlite3/sqlite3_driver.php173
-rw-r--r--system/database/drivers/sqlite3/sqlite3_forge.php207
-rw-r--r--system/database/drivers/sqlite3/sqlite3_result.php498
-rw-r--r--system/database/drivers/sqlite3/sqlite3_utility.php13
-rw-r--r--system/database/drivers/sqlsrv/sqlsrv_driver.php347
-rw-r--r--system/database/drivers/sqlsrv/sqlsrv_forge.php198
-rw-r--r--system/database/drivers/sqlsrv/sqlsrv_result.php27
-rw-r--r--system/database/drivers/sqlsrv/sqlsrv_utility.php26
-rw-r--r--system/helpers/array_helper.php67
-rw-r--r--system/helpers/captcha_helper.php33
-rw-r--r--system/helpers/cookie_helper.php67
-rw-r--r--system/helpers/date_helper.php624
-rw-r--r--system/helpers/directory_helper.php33
-rw-r--r--system/helpers/download_helper.php84
-rw-r--r--system/helpers/email_helper.php39
-rw-r--r--system/helpers/file_helper.php277
-rw-r--r--system/helpers/form_helper.php627
-rw-r--r--system/helpers/html_helper.php230
-rw-r--r--system/helpers/inflector_helper.php156
-rw-r--r--system/helpers/language_helper.php28
-rw-r--r--system/helpers/number_helper.php16
-rw-r--r--system/helpers/path_helper.php21
-rw-r--r--system/helpers/security_helper.php73
-rw-r--r--system/helpers/smiley_helper.php221
-rw-r--r--system/helpers/string_helper.php302
-rw-r--r--system/helpers/text_helper.php361
-rw-r--r--system/helpers/typography_helper.php53
-rw-r--r--system/helpers/url_helper.php388
-rw-r--r--system/helpers/xml_helper.php21
-rw-r--r--system/language/english/calendar_lang.php96
-rw-r--r--system/language/english/date_lang.php34
-rw-r--r--system/language/english/db_lang.php9
-rw-r--r--system/language/english/email_lang.php42
-rw-r--r--system/language/english/form_validation_lang.php57
-rw-r--r--system/language/english/ftp_lang.php30
-rw-r--r--system/language/english/imglib_lang.php42
-rw-r--r--system/language/english/migration_lang.php21
-rw-r--r--system/language/english/number_lang.php15
-rw-r--r--system/language/english/profiler_lang.php5
-rw-r--r--system/language/english/unit_test_lang.php6
-rw-r--r--system/language/english/upload_lang.php38
-rw-r--r--system/libraries/Cache/Cache.php140
-rw-r--r--system/libraries/Cache/drivers/Cache_apc.php22
-rw-r--r--system/libraries/Cache/drivers/Cache_dummy.php7
-rw-r--r--system/libraries/Cache/drivers/Cache_file.php37
-rw-r--r--system/libraries/Cache/drivers/Cache_memcached.php35
-rw-r--r--system/libraries/Cache/drivers/Cache_redis.php237
-rw-r--r--system/libraries/Cache/drivers/Cache_wincache.php17
-rw-r--r--system/libraries/Cache/drivers/index.html10
-rw-r--r--system/libraries/Cache/index.html10
-rw-r--r--system/libraries/Calendar.php156
-rw-r--r--system/libraries/Cart.php116
-rw-r--r--system/libraries/Driver.php177
-rw-r--r--system/libraries/Email.php1052
-rw-r--r--system/libraries/Encrypt.php58
-rw-r--r--system/libraries/Form_validation.php329
-rw-r--r--system/libraries/Ftp.php142
-rw-r--r--system/libraries/Image_lib.php609
-rw-r--r--system/libraries/Javascript.php51
-rw-r--r--system/libraries/Migration.php282
-rw-r--r--system/libraries/Pagination.php453
-rw-r--r--system/libraries/Parser.php62
-rw-r--r--system/libraries/Profiler.php89
-rw-r--r--system/libraries/Session.php819
-rw-r--r--system/libraries/Session/Session.php753
-rw-r--r--system/libraries/Session/drivers/Session_cookie.php845
-rw-r--r--system/libraries/Session/drivers/Session_native.php242
-rw-r--r--system/libraries/Session/drivers/index.html10
-rw-r--r--system/libraries/Session/index.html10
-rw-r--r--system/libraries/Table.php67
-rw-r--r--system/libraries/Trackback.php63
-rw-r--r--system/libraries/Typography.php47
-rw-r--r--system/libraries/Unit_test.php130
-rw-r--r--system/libraries/Upload.php391
-rw-r--r--system/libraries/User_agent.php134
-rw-r--r--system/libraries/Xmlrpc.php524
-rw-r--r--system/libraries/Xmlrpcs.php124
-rw-r--r--system/libraries/Zip.php45
-rw-r--r--system/libraries/javascript/Jquery.php231
-rw-r--r--system/libraries/javascript/index.html10
173 files changed, 22244 insertions, 12099 deletions
diff --git a/system/.htaccess b/system/.htaccess
index 14249c50b..97c65d2df 100644
--- a/system/.htaccess
+++ b/system/.htaccess
@@ -1 +1,6 @@
-Deny from all \ No newline at end of file
+<IfModule authz_core_module>
+ Require all denied
+</IfModule>
+<IfModule !authz_core_module>
+ Deny from all
+</IfModule> \ No newline at end of file
diff --git a/system/core/Benchmark.php b/system/core/Benchmark.php
index f6b634deb..e80ee54dd 100755..100644
--- a/system/core/Benchmark.php
+++ b/system/core/Benchmark.php
@@ -1,4 +1,4 @@
-<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');
+<?php
/**
* CodeIgniter
*
@@ -24,14 +24,13 @@
* @since Version 1.0
* @filesource
*/
-
-// ------------------------------------------------------------------------
+defined('BASEPATH') OR exit('No direct script access allowed');
/**
- * CodeIgniter Benchmark Class
+ * Benchmark Class
*
* This class enables you to mark points and calculate the time difference
- * between them. Memory consumption can also be displayed.
+ * between them. Memory consumption can also be displayed.
*
* @package CodeIgniter
* @subpackage Libraries
@@ -42,31 +41,31 @@
class CI_Benchmark {
/**
- * List of all benchmark markers and when they were added
+ * List of all benchmark markers
*
- * @var array
+ * @var array
*/
public $marker = array();
- // --------------------------------------------------------------------
-
/**
* Set a benchmark marker
*
* Multiple calls to this function can be made so that several
- * execution points can be timed
+ * execution points can be timed.
*
- * @param string $name name of the marker
+ * @param string $name Marker name
* @return void
*/
public function mark($name)
{
- $this->marker[$name] = microtime();
+ $this->marker[$name] = microtime(TRUE);
}
// --------------------------------------------------------------------
/**
+ * Elapsed time
+ *
* Calculates the time difference between two marked points.
*
* If the first parameter is empty this function instead returns the
@@ -74,14 +73,17 @@ class CI_Benchmark {
* execution time to be shown in a template. The output class will
* swap the real value for this variable.
*
- * @param string a particular marked point
- * @param string a particular marked point
- * @param integer the number of decimal places
- * @return mixed
+ * @param string $point1 A particular marked point
+ * @param string $point2 A particular marked point
+ * @param int $decimals Number of decimal places
+ *
+ * @return string Calculated elapsed time on success,
+ * an '{elapsed_string}' if $point1 is empty
+ * or an empty string if $point1 is not found.
*/
public function elapsed_time($point1 = '', $point2 = '', $decimals = 4)
{
- if ($point1 == '')
+ if ($point1 === '')
{
return '{elapsed_time}';
}
@@ -93,13 +95,10 @@ class CI_Benchmark {
if ( ! isset($this->marker[$point2]))
{
- $this->marker[$point2] = microtime();
+ $this->marker[$point2] = microtime(TRUE);
}
- list($sm, $ss) = explode(' ', $this->marker[$point1]);
- list($em, $es) = explode(' ', $this->marker[$point2]);
-
- return number_format(($em + $es) - ($sm + $ss), $decimals);
+ return number_format($this->marker[$point2] - $this->marker[$point1], $decimals);
}
// --------------------------------------------------------------------
@@ -107,12 +106,13 @@ class CI_Benchmark {
/**
* Memory Usage
*
- * This function returns the {memory_usage} pseudo-variable.
+ * Simply returns the {memory_usage} marker.
+ *
* This permits it to be put it anywhere in a template
* without the memory being calculated until the end.
* The output class will swap the real value for this variable.
*
- * @return string
+ * @return string '{memory_usage}'
*/
public function memory_usage()
{
@@ -122,4 +122,4 @@ class CI_Benchmark {
}
/* End of file Benchmark.php */
-/* Location: ./system/core/Benchmark.php */
+/* Location: ./system/core/Benchmark.php */ \ No newline at end of file
diff --git a/system/core/CodeIgniter.php b/system/core/CodeIgniter.php
index 4885f310c..89081b572 100755..100644
--- a/system/core/CodeIgniter.php
+++ b/system/core/CodeIgniter.php
@@ -1,4 +1,4 @@
-<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');
+<?php
/**
* CodeIgniter
*
@@ -24,8 +24,7 @@
* @since Version 1.0
* @filesource
*/
-
-// ------------------------------------------------------------------------
+defined('BASEPATH') OR exit('No direct script access allowed');
/**
* System Initialization File
@@ -33,7 +32,7 @@
* Loads the base classes and executes the request.
*
* @package CodeIgniter
- * @subpackage codeigniter
+ * @subpackage CodeIgniter
* @category Front-controller
* @author EllisLab Dev Team
* @link http://codeigniter.com/user_guide/
@@ -42,7 +41,7 @@
/**
* CodeIgniter Version
*
- * @var string
+ * @var string
*
*/
define('CI_VERSION', '3.0-dev');
@@ -52,7 +51,7 @@
* Load the global functions
* ------------------------------------------------------
*/
- require(BASEPATH.'core/Common.php');
+ require_once(BASEPATH.'core/Common.php');
/*
* ------------------------------------------------------
@@ -75,9 +74,9 @@
*/
set_error_handler('_exception_handler');
- if ( ! is_php('5.3'))
+ if ( ! is_php('5.4'))
{
- @set_magic_quotes_runtime(0); // Kill magic quotes
+ @ini_set('magic_quotes_runtime', 0); // Kill magic quotes
}
/*
@@ -96,24 +95,13 @@
* Note: Since the config file data is cached it doesn't
* hurt to load it here.
*/
- if (isset($assign_to_config['subclass_prefix']) && $assign_to_config['subclass_prefix'] != '')
+ if ( ! empty($assign_to_config['subclass_prefix']))
{
get_config(array('subclass_prefix' => $assign_to_config['subclass_prefix']));
}
/*
* ------------------------------------------------------
- * Set a liberal script execution time limit
- * ------------------------------------------------------
- */
- if (function_exists('set_time_limit') && @ini_get('safe_mode') == 0
- && php_sapi_name() !== 'cli') // Do not override the Time Limit value if running from Command Line
- {
- @set_time_limit(300);
- }
-
-/*
- * ------------------------------------------------------
* Start the timer... tick tock tick tock...
* ------------------------------------------------------
*/
@@ -143,9 +131,12 @@
$CFG =& load_class('Config', 'core');
// Do we have any manually set config items in the index.php file?
- if (isset($assign_to_config))
+ if (isset($assign_to_config) && is_array($assign_to_config))
{
- $CFG->_assign_to_config($assign_to_config);
+ foreach ($assign_to_config as $key => $value)
+ {
+ $CFG->set_item($key, $value);
+ }
}
/*
@@ -155,7 +146,7 @@
*
* Note: Order here is rather important as the UTF-8
* class needs to be used very early on, but it cannot
- * properly determine if UTf-8 can be supported until
+ * properly determine if UTF-8 can be supported until
* after the Config class is instantiated.
*
*/
@@ -195,7 +186,7 @@
* ------------------------------------------------------
*/
if ($EXT->call_hook('cache_override') === FALSE
- && $OUT->_display_cache($CFG, $URI) == TRUE)
+ && $OUT->_display_cache($CFG, $URI) === TRUE)
{
exit;
}
@@ -230,12 +221,18 @@
// Load the base controller class
require BASEPATH.'core/Controller.php';
+ /**
+ * Reference to the CI_Controller method.
+ *
+ * Returns current CI instance object
+ *
+ * @return object
+ */
function &get_instance()
{
return CI_Controller::get_instance();
}
-
if (file_exists(APPPATH.'core/'.$CFG->config['subclass_prefix'].'Controller.php'))
{
require APPPATH.'core/'.$CFG->config['subclass_prefix'].'Controller.php';
@@ -259,28 +256,27 @@
* Security check
* ------------------------------------------------------
*
- * None of the functions in the app controller or the
+ * None of the methods in the app controller or the
* loader class can be called via the URI, nor can
- * controller functions that begin with an underscore
+ * controller functions that begin with an underscore.
*/
$class = $RTR->fetch_class();
$method = $RTR->fetch_method();
- if ( ! class_exists($class)
- OR strpos($method, '_') === 0
- OR in_array(strtolower($method), array_map('strtolower', get_class_methods('CI_Controller')))
- )
+ if ( ! class_exists($class) OR $method[0] === '_' OR method_exists('CI_Controller', $method))
{
if ( ! empty($RTR->routes['404_override']))
{
- $x = explode('/', $RTR->routes['404_override'], 2);
- $class = $x[0];
- $method = (isset($x[1]) ? $x[1] : 'index');
+ if (sscanf($RTR->routes['404_override'], '%[^/]/%s', $class, $method) !== 2)
+ {
+ $method = 'index';
+ }
+
if ( ! class_exists($class))
{
if ( ! file_exists(APPPATH.'controllers/'.$class.'.php'))
{
- show_404("{$class}/{$method}");
+ show_404($class.'/'.$method);
}
include_once(APPPATH.'controllers/'.$class.'.php');
@@ -288,10 +284,46 @@
}
else
{
- show_404("{$class}/{$method}");
+ show_404($class.'/'.$method);
}
}
+ if (method_exists($class, '_remap'))
+ {
+ $params = array($method, array_slice($URI->rsegments, 2));
+ $method = '_remap';
+ }
+ else
+ {
+ // WARNING: It appears that there are issues with is_callable() even in PHP 5.2!
+ // Furthermore, there are bug reports and feature/change requests related to it
+ // that make it unreliable to use in this context. Please, DO NOT change this
+ // work-around until a better alternative is available.
+ if ( ! in_array(strtolower($method), array_map('strtolower', get_class_methods($class)), TRUE))
+ {
+ if (empty($RTR->routes['404_override']))
+ {
+ show_404($class.'/'.$method);
+ }
+ elseif (sscanf($RTR->routes['404_override'], '%[^/]/%s', $class, $method) !== 2)
+ {
+ $method = 'index';
+ }
+
+ if ( ! class_exists($class))
+ {
+ if ( ! file_exists(APPPATH.'controllers/'.$class.'.php'))
+ {
+ show_404($class.'/'.$method);
+ }
+
+ include_once(APPPATH.'controllers/'.$class.'.php');
+ }
+ }
+
+ $params = array_slice($URI->rsegments, 2);
+ }
+
/*
* ------------------------------------------------------
* Is there a "pre_controller" hook?
@@ -321,45 +353,7 @@
* Call the requested method
* ------------------------------------------------------
*/
- // Is there a "remap" function? If so, we call it instead
- if (method_exists($CI, '_remap'))
- {
- $CI->_remap($method, array_slice($URI->rsegments, 2));
- }
- else
- {
- // is_callable() returns TRUE on some versions of PHP 5 for private and protected
- // methods, so we'll use this workaround for consistent behavior
- if ( ! in_array(strtolower($method), array_map('strtolower', get_class_methods($CI))))
- {
- // Check and see if we are using a 404 override and use it.
- if ( ! empty($RTR->routes['404_override']))
- {
- $x = explode('/', $RTR->routes['404_override'], 2);
- $class = $x[0];
- $method = (isset($x[1]) ? $x[1] : 'index');
- if ( ! class_exists($class))
- {
- if ( ! file_exists(APPPATH.'controllers/'.$class.'.php'))
- {
- show_404("{$class}/{$method}");
- }
-
- include_once(APPPATH.'controllers/'.$class.'.php');
- unset($CI);
- $CI = new $class();
- }
- }
- else
- {
- show_404("{$class}/{$method}");
- }
- }
-
- // Call the requested method.
- // Any URI segments present (besides the class/function) will be passed to the method for convenience
- call_user_func_array(array(&$CI, $method), array_slice($URI->rsegments, 2));
- }
+ call_user_func_array(array(&$CI, $method), $params);
// Mark a benchmark end point
$BM->mark('controller_execution_time_( '.$class.' / '.$method.' )_end');
@@ -388,15 +382,5 @@
*/
$EXT->call_hook('post_system');
-/*
- * ------------------------------------------------------
- * Close the DB connection if one exists
- * ------------------------------------------------------
- */
- if (class_exists('CI_DB') && isset($CI->db))
- {
- $CI->db->close();
- }
-
/* End of file CodeIgniter.php */
-/* Location: ./system/core/CodeIgniter.php */
+/* Location: ./system/core/CodeIgniter.php */ \ No newline at end of file
diff --git a/system/core/Common.php b/system/core/Common.php
index aeb784bbe..7feb16bfd 100644
--- a/system/core/Common.php
+++ b/system/core/Common.php
@@ -1,4 +1,4 @@
-<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');
+<?php
/**
* CodeIgniter
*
@@ -24,6 +24,7 @@
* @since Version 1.0
* @filesource
*/
+defined('BASEPATH') OR exit('No direct script access allowed');
/**
* Common Functions
@@ -31,7 +32,7 @@
* Loads the base classes and executes the request.
*
* @package CodeIgniter
- * @subpackage codeigniter
+ * @subpackage CodeIgniter
* @category Common Functions
* @author EllisLab Dev Team
* @link http://codeigniter.com/user_guide/
@@ -39,25 +40,25 @@
// ------------------------------------------------------------------------
-/**
- * Determines if the current version of PHP is greater then the supplied value
- *
- * Since there are a few places where we conditionally test for PHP > 5
- * we'll set a static variable.
- *
- * @param string
- * @return bool TRUE if the current version is $version or higher
- */
if ( ! function_exists('is_php'))
{
- function is_php($version = '5.0.0')
+ /**
+ * Determines if the current version of PHP is greater then the supplied value
+ *
+ * Since there are a few places where we conditionally test for PHP > 5.3
+ * we'll set a static variable.
+ *
+ * @param string
+ * @return bool TRUE if the current version is $version or higher
+ */
+ function is_php($version = '5.3.0')
{
static $_is_php;
$version = (string) $version;
if ( ! isset($_is_php[$version]))
{
- $_is_php[$version] = (version_compare(PHP_VERSION, $version) < 0) ? FALSE : TRUE;
+ $_is_php[$version] = (version_compare(PHP_VERSION, $version) >= 0);
}
return $_is_php[$version];
@@ -66,18 +67,18 @@ if ( ! function_exists('is_php'))
// ------------------------------------------------------------------------
-/**
- * Tests for file writability
- *
- * is_writable() returns TRUE on Windows servers when you really can't write to
- * the file, based on the read-only attribute. is_writable() is also unreliable
- * on Unix servers if safe_mode is on.
- *
- * @param string
- * @return void
- */
if ( ! function_exists('is_really_writable'))
{
+ /**
+ * Tests for file writability
+ *
+ * is_writable() returns TRUE on Windows servers when you really can't write to
+ * the file, based on the read-only attribute. is_writable() is also unreliable
+ * on Unix servers if safe_mode is on.
+ *
+ * @param string
+ * @return void
+ */
function is_really_writable($file)
{
// If we're on a Unix server with safe_mode off we call is_writable
@@ -114,20 +115,20 @@ if ( ! function_exists('is_really_writable'))
// ------------------------------------------------------------------------
-/**
- * Class registry
- *
- * This function acts as a singleton. If the requested class does not
- * exist it is instantiated and set to a static variable. If it has
- * previously been instantiated the variable is returned.
- *
- * @param string the class name being requested
- * @param string the directory where the class should be found
- * @param string the class name prefix
- * @return object
- */
if ( ! function_exists('load_class'))
{
+ /**
+ * Class registry
+ *
+ * This function acts as a singleton. If the requested class does not
+ * exist it is instantiated and set to a static variable. If it has
+ * previously been instantiated the variable is returned.
+ *
+ * @param string the class name being requested
+ * @param string the directory where the class should be found
+ * @param string the class name prefix
+ * @return object
+ */
function &load_class($class, $directory = 'libraries', $prefix = 'CI_')
{
static $_classes = array();
@@ -150,7 +151,7 @@ if ( ! function_exists('load_class'))
if (class_exists($name) === FALSE)
{
- require($path.$directory.'/'.$class.'.php');
+ require_once($path.$directory.'/'.$class.'.php');
}
break;
@@ -164,7 +165,7 @@ if ( ! function_exists('load_class'))
if (class_exists($name) === FALSE)
{
- require(APPPATH.$directory.'/'.config_item('subclass_prefix').$class.'.php');
+ require_once(APPPATH.$directory.'/'.config_item('subclass_prefix').$class.'.php');
}
}
@@ -172,7 +173,7 @@ if ( ! function_exists('load_class'))
if ($name === FALSE)
{
// Note: We use exit() rather then show_error() in order to avoid a
- // self-referencing loop with the Excptions class
+ // self-referencing loop with the Exceptions class
set_status_header(503);
exit('Unable to locate the specified class: '.$class.'.php');
}
@@ -187,20 +188,20 @@ if ( ! function_exists('load_class'))
// --------------------------------------------------------------------
-/**
- * Keeps track of which libraries have been loaded. This function is
- * called by the load_class() function above
- *
- * @param string
- * @return array
- */
if ( ! function_exists('is_loaded'))
{
+ /**
+ * Keeps track of which libraries have been loaded. This function is
+ * called by the load_class() function above
+ *
+ * @param string
+ * @return array
+ */
function &is_loaded($class = '')
{
static $_is_loaded = array();
- if ($class != '')
+ if ($class !== '')
{
$_is_loaded[strtolower($class)] = $class;
}
@@ -211,17 +212,17 @@ if ( ! function_exists('is_loaded'))
// ------------------------------------------------------------------------
-/**
- * Loads the main config.php file
- *
- * This function lets us grab the config file even if the Config class
- * hasn't been instantiated yet
- *
- * @param array
- * @return array
- */
if ( ! function_exists('get_config'))
{
+ /**
+ * Loads the main config.php file
+ *
+ * This function lets us grab the config file even if the Config class
+ * hasn't been instantiated yet
+ *
+ * @param array
+ * @return array
+ */
function &get_config($replace = array())
{
static $_config;
@@ -231,21 +232,25 @@ if ( ! function_exists('get_config'))
return $_config[0];
}
- // Is the config file in the environment folder?
- if ( ! defined('ENVIRONMENT') OR ! file_exists($file_path = APPPATH.'config/'.ENVIRONMENT.'/config.php'))
+ $file_path = APPPATH.'config/config.php';
+ $found = FALSE;
+ if (file_exists($file_path))
{
- $file_path = APPPATH.'config/config.php';
+ $found = TRUE;
+ require($file_path);
}
- // Fetch the config file
- if ( ! file_exists($file_path))
+ // Is the config file in the environment folder?
+ if (defined('ENVIRONMENT') && file_exists($file_path = APPPATH.'config/'.ENVIRONMENT.'/config.php'))
+ {
+ require($file_path);
+ }
+ elseif ( ! $found)
{
set_status_header(503);
exit('The configuration file does not exist.');
}
- require($file_path);
-
// Does the $config array exist in the file?
if ( ! isset($config) OR ! is_array($config))
{
@@ -271,14 +276,14 @@ if ( ! function_exists('get_config'))
// ------------------------------------------------------------------------
-/**
- * Returns the specified config item
- *
- * @param string
- * @return mixed
- */
if ( ! function_exists('config_item'))
{
+ /**
+ * Returns the specified config item
+ *
+ * @param string
+ * @return mixed
+ */
function config_item($item)
{
static $_config_item = array();
@@ -300,22 +305,66 @@ if ( ! function_exists('config_item'))
// ------------------------------------------------------------------------
-/**
- * Error Handler
- *
- * This function lets us invoke the exception class and
- * display errors using the standard error template located
- * in application/errors/errors.php
- * This function will send the error page directly to the
- * browser and exit.
- *
- * @param string
- * @param int
- * @param string
- * @return void
- */
+if ( ! function_exists('get_mimes'))
+{
+ /**
+ * Returns the MIME types array from config/mimes.php
+ *
+ * @return array
+ */
+ function &get_mimes()
+ {
+ static $_mimes = array();
+
+ if (defined('ENVIRONMENT') && is_file(APPPATH.'config/'.ENVIRONMENT.'/mimes.php'))
+ {
+ $_mimes = include(APPPATH.'config/'.ENVIRONMENT.'/mimes.php');
+ }
+ elseif (is_file(APPPATH.'config/mimes.php'))
+ {
+ $_mimes = include(APPPATH.'config/mimes.php');
+ }
+
+ return $_mimes;
+ }
+}
+
+// ------------------------------------------------------------------------
+
+if ( ! function_exists('is_https'))
+{
+ /**
+ * Is HTTPS?
+ *
+ * Determines if the application is accessed via an encrypted
+ * (HTTPS) connection.
+ *
+ * @return bool
+ */
+ function is_https()
+ {
+ return ( ! empty($_SERVER['HTTPS']) && strtolower($_SERVER['HTTPS']) !== 'off');
+ }
+}
+
+// ------------------------------------------------------------------------
+
if ( ! function_exists('show_error'))
{
+ /**
+ * Error Handler
+ *
+ * This function lets us invoke the exception class and
+ * display errors using the standard error template located
+ * in application/errors/errors.php
+ * This function will send the error page directly to the
+ * browser and exit.
+ *
+ * @param string
+ * @param int
+ * @param string
+ * @return void
+ */
function show_error($message, $status_code = 500, $heading = 'An Error Was Encountered')
{
$_error =& load_class('Exceptions', 'core');
@@ -326,19 +375,19 @@ if ( ! function_exists('show_error'))
// ------------------------------------------------------------------------
-/**
- * 404 Page Handler
- *
- * This function is similar to the show_error() function above
- * However, instead of the standard error template it displays
- * 404 errors.
- *
- * @param string
- * @param bool
- * @return void
- */
if ( ! function_exists('show_404'))
{
+ /**
+ * 404 Page Handler
+ *
+ * This function is similar to the show_error() function above
+ * However, instead of the standard error template it displays
+ * 404 errors.
+ *
+ * @param string
+ * @param bool
+ * @return void
+ */
function show_404($page = '', $log_error = TRUE)
{
$_error =& load_class('Exceptions', 'core');
@@ -349,102 +398,107 @@ if ( ! function_exists('show_404'))
// ------------------------------------------------------------------------
-/**
- * Error Logging Interface
- *
- * We use this as a simple mechanism to access the logging
- * class and send messages to be logged.
- *
- * @param string
- * @param string
- * @param bool
- * @return void
- */
if ( ! function_exists('log_message'))
{
+ /**
+ * Error Logging Interface
+ *
+ * We use this as a simple mechanism to access the logging
+ * class and send messages to be logged.
+ *
+ * @param string
+ * @param string
+ * @param bool
+ * @return void
+ */
function log_message($level = 'error', $message, $php_error = FALSE)
{
static $_log;
- if (config_item('log_threshold') == 0)
+ if (config_item('log_threshold') === 0)
{
return;
}
- $_log =& load_class('Log');
+ $_log =& load_class('Log', 'core');
$_log->write_log($level, $message, $php_error);
}
}
// ------------------------------------------------------------------------
-/**
- * Set HTTP Status Header
- *
- * @param int the status code
- * @param string
- * @return void
- */
if ( ! function_exists('set_status_header'))
{
+ /**
+ * Set HTTP Status Header
+ *
+ * @param int the status code
+ * @param string
+ * @return void
+ */
function set_status_header($code = 200, $text = '')
{
$stati = array(
- 200 => 'OK',
- 201 => 'Created',
- 202 => 'Accepted',
- 203 => 'Non-Authoritative Information',
- 204 => 'No Content',
- 205 => 'Reset Content',
- 206 => 'Partial Content',
-
- 300 => 'Multiple Choices',
- 301 => 'Moved Permanently',
- 302 => 'Found',
- 304 => 'Not Modified',
- 305 => 'Use Proxy',
- 307 => 'Temporary Redirect',
-
- 400 => 'Bad Request',
- 401 => 'Unauthorized',
- 403 => 'Forbidden',
- 404 => 'Not Found',
- 405 => 'Method Not Allowed',
- 406 => 'Not Acceptable',
- 407 => 'Proxy Authentication Required',
- 408 => 'Request Timeout',
- 409 => 'Conflict',
- 410 => 'Gone',
- 411 => 'Length Required',
- 412 => 'Precondition Failed',
- 413 => 'Request Entity Too Large',
- 414 => 'Request-URI Too Long',
- 415 => 'Unsupported Media Type',
- 416 => 'Requested Range Not Satisfiable',
- 417 => 'Expectation Failed',
- 422 => 'Unprocessable Entity',
-
- 500 => 'Internal Server Error',
- 501 => 'Not Implemented',
- 502 => 'Bad Gateway',
- 503 => 'Service Unavailable',
- 504 => 'Gateway Timeout',
- 505 => 'HTTP Version Not Supported'
- );
-
- if ($code == '' OR ! is_numeric($code))
+ 200 => 'OK',
+ 201 => 'Created',
+ 202 => 'Accepted',
+ 203 => 'Non-Authoritative Information',
+ 204 => 'No Content',
+ 205 => 'Reset Content',
+ 206 => 'Partial Content',
+
+ 300 => 'Multiple Choices',
+ 301 => 'Moved Permanently',
+ 302 => 'Found',
+ 303 => 'See Other',
+ 304 => 'Not Modified',
+ 305 => 'Use Proxy',
+ 307 => 'Temporary Redirect',
+
+ 400 => 'Bad Request',
+ 401 => 'Unauthorized',
+ 403 => 'Forbidden',
+ 404 => 'Not Found',
+ 405 => 'Method Not Allowed',
+ 406 => 'Not Acceptable',
+ 407 => 'Proxy Authentication Required',
+ 408 => 'Request Timeout',
+ 409 => 'Conflict',
+ 410 => 'Gone',
+ 411 => 'Length Required',
+ 412 => 'Precondition Failed',
+ 413 => 'Request Entity Too Large',
+ 414 => 'Request-URI Too Long',
+ 415 => 'Unsupported Media Type',
+ 416 => 'Requested Range Not Satisfiable',
+ 417 => 'Expectation Failed',
+ 422 => 'Unprocessable Entity',
+
+ 500 => 'Internal Server Error',
+ 501 => 'Not Implemented',
+ 502 => 'Bad Gateway',
+ 503 => 'Service Unavailable',
+ 504 => 'Gateway Timeout',
+ 505 => 'HTTP Version Not Supported'
+ );
+
+ if (empty($code) OR ! is_numeric($code))
{
show_error('Status codes must be numeric', 500);
}
- if (isset($stati[$code]) && $text == '')
- {
- $text = $stati[$code];
- }
+ is_int($code) OR $code = (int) $code;
- if ($text == '')
+ if (empty($text))
{
- show_error('No status text available. Please check your status code number or supply your own message text.', 500);
+ if (isset($stati[$code]))
+ {
+ $text = $stati[$code];
+ }
+ else
+ {
+ show_error('No status text available. Please check your status code number or supply your own message text.', 500);
+ }
}
$server_protocol = isset($_SERVER['SERVER_PROTOCOL']) ? $_SERVER['SERVER_PROTOCOL'] : FALSE;
@@ -453,63 +507,49 @@ if ( ! function_exists('set_status_header'))
{
header('Status: '.$code.' '.$text, TRUE);
}
- elseif ($server_protocol === 'HTTP/1.0')
- {
- header('HTTP/1.0 '.$code.' '.$text, TRUE, $code);
- }
else
{
- header('HTTP/1.1 '.$code.' '.$text, TRUE, $code);
+ header(($server_protocol ? $server_protocol : 'HTTP/1.1').' '.$code.' '.$text, TRUE, $code);
}
}
}
// --------------------------------------------------------------------
-/**
- * Exception Handler
- *
- * This is the custom exception handler that is declaired at the top
- * of Codeigniter.php. The main reason we use this is to permit
- * PHP errors to be logged in our own log files since the user may
- * not have access to server logs. Since this function
- * effectively intercepts PHP errors, however, we also need
- * to display errors based on the current error_reporting level.
- * We do that with the use of a PHP error template.
- *
- * @param int
- * @param string
- * @param string
- * @param int
- * @return void
- */
if ( ! function_exists('_exception_handler'))
{
+ /**
+ * Exception Handler
+ *
+ * This is the custom exception handler that is declaired at the top
+ * of Codeigniter.php. The main reason we use this is to permit
+ * PHP errors to be logged in our own log files since the user may
+ * not have access to server logs. Since this function
+ * effectively intercepts PHP errors, however, we also need
+ * to display errors based on the current error_reporting level.
+ * We do that with the use of a PHP error template.
+ *
+ * @param int
+ * @param string
+ * @param string
+ * @param int
+ * @return void
+ */
function _exception_handler($severity, $message, $filepath, $line)
{
- // We don't bother with "strict" notices since they tend to fill up
- // the log file with excess information that isn't normally very helpful.
- // For example, if you are running PHP 5 and you use version 4 style
- // class functions (without prefixes like "public", "private", etc.)
- // you'll get notices telling you that these have been deprecated.
- if ($severity == E_STRICT)
- {
- return;
- }
-
$_error =& load_class('Exceptions', 'core');
- // Should we display the error? We'll get the current error_reporting
+ // Should we ignore the error? We'll get the current error_reporting
// level and add its bits with the severity bits to find out.
- if (($severity & error_reporting()) == $severity)
+ if (($severity & error_reporting()) !== $severity)
{
- $_error->show_php_error($severity, $message, $filepath, $line);
+ return;
}
- // Should we log the error? No? We're done...
- if (config_item('log_threshold') == 0)
+ // Should we display the error?
+ if ((bool) ini_get('display_errors') === TRUE)
{
- return;
+ $_error->show_php_error($severity, $message, $filepath, $line);
}
$_error->log_exception($severity, $message, $filepath, $line);
@@ -518,18 +558,18 @@ if ( ! function_exists('_exception_handler'))
// --------------------------------------------------------------------
-/**
- * Remove Invisible Characters
- *
- * This prevents sandwiching null characters
- * between ascii characters, like Java\0script.
- *
- * @param string
- * @param bool
- * @return string
- */
if ( ! function_exists('remove_invisible_characters'))
{
+ /**
+ * Remove Invisible Characters
+ *
+ * This prevents sandwiching null characters
+ * between ascii characters, like Java\0script.
+ *
+ * @param string
+ * @param bool
+ * @return string
+ */
function remove_invisible_characters($str, $url_encoded = TRUE)
{
$non_displayables = array();
@@ -556,14 +596,14 @@ if ( ! function_exists('remove_invisible_characters'))
// ------------------------------------------------------------------------
-/**
- * Returns HTML escaped variable
- *
- * @param mixed
- * @return mixed
- */
if ( ! function_exists('html_escape'))
{
+ /**
+ * Returns HTML escaped variable
+ *
+ * @param mixed
+ * @return mixed
+ */
function html_escape($var)
{
return is_array($var)
@@ -572,5 +612,91 @@ if ( ! function_exists('html_escape'))
}
}
+// ------------------------------------------------------------------------
+
+if ( ! function_exists('_stringify_attributes'))
+{
+ /**
+ * Stringify attributes for use in HTML tags.
+ *
+ * Helper function used to convert a string, array, or object
+ * of attributes to a string.
+ *
+ * @param mixed string, array, object
+ * @param bool
+ * @return string
+ */
+ function _stringify_attributes($attributes, $js = FALSE)
+ {
+ $atts = NULL;
+
+ if (empty($attributes))
+ {
+ return $atts;
+ }
+
+ if (is_string($attributes))
+ {
+ return ' '.$attributes;
+ }
+
+ $attributes = (array) $attributes;
+
+ foreach ($attributes as $key => $val)
+ {
+ $atts .= ($js) ? $key.'='.$val.',' : ' '.$key.'="'.$val.'"';
+ }
+
+ return rtrim($atts, ',');
+ }
+}
+
+// ------------------------------------------------------------------------
+
+if ( ! function_exists('function_usable'))
+{
+ /**
+ * Function usable
+ *
+ * Executes a function_exists() check, and if the Suhosin PHP
+ * extension is loaded - checks whether the function that is
+ * checked might be disabled in there as well.
+ *
+ * This is useful as function_exists() will return FALSE for
+ * functions disabled via the *disable_functions* php.ini
+ * setting, but not for *suhosin.executor.func.blacklist* and
+ * *suhosin.executor.disable_eval*. These settings will just
+ * terminate script execution if a disabled function is executed.
+ *
+ * @link http://www.hardened-php.net/suhosin/
+ * @param string $function_name Function to check for
+ * @return bool TRUE if the function exists and is safe to call,
+ * FALSE otherwise.
+ */
+ function function_usable($function_name)
+ {
+ static $_suhosin_func_blacklist;
+
+ if (function_exists($function_name))
+ {
+ if ( ! isset($_suhosin_func_blacklist))
+ {
+ $_suhosin_func_blacklist = extension_loaded('suhosin')
+ ? array()
+ : explode(',', trim(@ini_get('suhosin.executor.func.blacklist')));
+
+ if ( ! in_array('eval', $_suhosin_func_blacklist, TRUE) && @ini_get('suhosin.executor.disable_eval'))
+ {
+ $_suhosin_func_blacklist[] = 'eval';
+ }
+ }
+
+ return in_array($function_name, $_suhosin_func_blacklist, TRUE);
+ }
+
+ return FALSE;
+ }
+}
+
/* End of file Common.php */
/* Location: ./system/core/Common.php */ \ No newline at end of file
diff --git a/system/core/Config.php b/system/core/Config.php
index 91826bd41..38bcd5c8f 100755..100644
--- a/system/core/Config.php
+++ b/system/core/Config.php
@@ -1,4 +1,4 @@
-<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');
+<?php
/**
* CodeIgniter
*
@@ -24,11 +24,10 @@
* @since Version 1.0
* @filesource
*/
-
-// ------------------------------------------------------------------------
+defined('BASEPATH') OR exit('No direct script access allowed');
/**
- * CodeIgniter Config Class
+ * Config Class
*
* This class contains functions that enable config files to be managed
*
@@ -43,32 +42,31 @@ class CI_Config {
/**
* List of all loaded config values
*
- * @var array
+ * @var array
*/
public $config = array();
+
/**
* List of all loaded config files
*
- * @var array
+ * @var array
*/
- public $is_loaded = array();
+ public $is_loaded = array();
+
/**
* List of paths to search when trying to load a config file.
- * This must be public as it's used by the Loader class.
*
- * @var array
+ * @used-by CI_Loader
+ * @var array
*/
- public $_config_paths = array(APPPATH);
+ public $_config_paths = array(APPPATH);
/**
- * Constructor
+ * Class constructor
*
- * Sets the $config data from the primary config.php file as a class variable
+ * Sets the $config data from the primary config.php file as a class variable.
*
- * @param string the config file name
- * @param boolean if configuration values should be loaded into their own section
- * @param boolean true if errors should just return false, false if an error message should be displayed
- * @return boolean if the file was successfully loaded or not
+ * @return void
*/
public function __construct()
{
@@ -80,9 +78,9 @@ class CI_Config {
{
if (isset($_SERVER['HTTP_HOST']))
{
- $base_url = ! empty($_SERVER['HTTPS']) && strtolower($_SERVER['HTTPS']) !== 'off' ? 'https' : 'http';
- $base_url .= '://'. $_SERVER['HTTP_HOST']
- . str_replace(basename($_SERVER['SCRIPT_NAME']), '', $_SERVER['SCRIPT_NAME']);
+ $base_url = is_https() ? 'https' : 'http';
+ $base_url .= '://'.$_SERVER['HTTP_HOST']
+ .str_replace(basename($_SERVER['SCRIPT_NAME']), '', $_SERVER['SCRIPT_NAME']);
}
else
{
@@ -98,22 +96,22 @@ class CI_Config {
/**
* Load Config File
*
- * @param string the config file name
- * @param boolean if configuration values should be loaded into their own section
- * @param boolean true if errors should just return false, false if an error message should be displayed
- * @return boolean if the file was loaded correctly
+ * @param string $file Configuration file name
+ * @param bool $use_sections Whether configuration values should be loaded into their own section
+ * @param bool $fail_gracefully Whether to just return FALSE or display an error message
+ * @return bool TRUE if the file was loaded correctly or FALSE on failure
*/
public function load($file = '', $use_sections = FALSE, $fail_gracefully = FALSE)
{
- $file = ($file == '') ? 'config' : str_replace('.php', '', $file);
+ $file = ($file === '') ? 'config' : str_replace('.php', '', $file);
$found = $loaded = FALSE;
+ $check_locations = defined('ENVIRONMENT')
+ ? array(ENVIRONMENT.'/'.$file, $file)
+ : array($file);
+
foreach ($this->_config_paths as $path)
{
- $check_locations = defined('ENVIRONMENT')
- ? array(ENVIRONMENT.'/'.$file, $file)
- : array($file);
-
foreach ($check_locations as $location)
{
$file_path = $path.'config/'.$location.'.php';
@@ -177,7 +175,7 @@ class CI_Config {
{
return FALSE;
}
- show_error('The configuration file '.$file.'.php'.' does not exist.');
+ show_error('The configuration file '.$file.'.php does not exist.');
}
return TRUE;
@@ -188,11 +186,9 @@ class CI_Config {
/**
* Fetch a config file item
*
- *
- * @param string the config item name
- * @param string the index name
- * @param bool
- * @return string
+ * @param string $item Config item name
+ * @param string $index Index name
+ * @return string|bool The configuration item or FALSE on failure
*/
public function item($item, $index = '')
{
@@ -207,11 +203,10 @@ class CI_Config {
// --------------------------------------------------------------------
/**
- * Fetch a config file item - adds slash after item (if item is not empty)
+ * Fetch a config file item with slash appended (if not empty)
*
- * @param string the config item name
- * @param bool
- * @return string
+ * @param string $item Config item name
+ * @return string|bool The configuration item or FALSE on failure
*/
public function slash_item($item)
{
@@ -219,7 +214,7 @@ class CI_Config {
{
return FALSE;
}
- elseif (trim($this->config[$item]) == '')
+ elseif (trim($this->config[$item]) === '')
{
return '';
}
@@ -231,54 +226,80 @@ class CI_Config {
/**
* Site URL
+ *
* Returns base_url . index_page [. uri_string]
*
- * @param string the URI string
+ * @uses CI_Config::_uri_string()
+ *
+ * @param string|string[] $uri URI string or an array of segments
* @return string
*/
public function site_url($uri = '')
{
- if ($uri == '')
+ if (empty($uri))
{
return $this->slash_item('base_url').$this->item('index_page');
}
- if ($this->item('enable_query_strings') == FALSE)
+ $uri = $this->_uri_string($uri);
+
+ if ($this->item('enable_query_strings') === FALSE)
{
- $suffix = ($this->item('url_suffix') == FALSE) ? '' : $this->item('url_suffix');
- return $this->slash_item('base_url').$this->slash_item('index_page').$this->_uri_string($uri).$suffix;
+ $suffix = isset($this->config['url_suffix']) ? $this->config['url_suffix'] : '';
+
+ if ($suffix !== '')
+ {
+ if (($offset = strpos($uri, '?')) !== FALSE)
+ {
+ $uri = substr($uri, 0, $offset).$suffix.substr($uri, $offset);
+ }
+ else
+ {
+ $uri .= $suffix;
+ }
+ }
+
+ return $this->slash_item('base_url').$this->slash_item('index_page').$uri;
}
- else
+ elseif (strpos($uri, '?') === FALSE)
{
- return $this->slash_item('base_url').$this->item('index_page').'?'.$this->_uri_string($uri);
+ $uri = '?'.$uri;
}
+
+ return $this->slash_item('base_url').$this->item('index_page').$uri;
}
// -------------------------------------------------------------
/**
* Base URL
+ *
* Returns base_url [. uri_string]
*
- * @param string $uri
- * @return string
+ * @uses CI_Config::_uri_string()
+ *
+ * @param string|string[] $uri URI string or an array of segments
+ * @return string
*/
public function base_url($uri = '')
{
- return $this->slash_item('base_url').ltrim($this->_uri_string($uri),'/');
+ return $this->slash_item('base_url').ltrim($this->_uri_string($uri), '/');
}
// -------------------------------------------------------------
/**
- * Build URI string for use in Config::site_url() and Config::base_url()
+ * Build URI string
+ *
+ * @used-by CI_Config::site_url()
+ * @used-by CI_Config::base_url()
*
- * @param mixed $uri
- * @return string
+ * @param string|string[] $uri URI string or an array of segments
+ * @return string
*/
protected function _uri_string($uri)
{
- if ($this->item('enable_query_strings') == FALSE)
+ if ($this->item('enable_query_strings') === FALSE)
{
if (is_array($uri))
{
@@ -288,15 +309,7 @@ class CI_Config {
}
elseif (is_array($uri))
{
- $i = 0;
- $str = '';
- foreach ($uri as $key => $val)
- {
- $prefix = ($i === 0) ? '' : '&';
- $str .= $prefix.$key.'='.$val;
- $i++;
- }
- return $str;
+ return http_build_query($uri);
}
return $uri;
@@ -320,8 +333,8 @@ class CI_Config {
/**
* Set a config file item
*
- * @param string the config item key
- * @param string the config item value
+ * @param string $item Config item key
+ * @param string $value Config item value
* @return void
*/
public function set_item($item, $value)
@@ -329,29 +342,7 @@ class CI_Config {
$this->config[$item] = $value;
}
- // --------------------------------------------------------------------
-
- /**
- * Assign to Config
- *
- * This function is called by the front controller (CodeIgniter.php)
- * after the Config class is instantiated. It permits config items
- * to be assigned or overriden by variables contained in the index.php file
- *
- * @param array
- * @return void
- */
- public function _assign_to_config($items = array())
- {
- if (is_array($items))
- {
- foreach ($items as $key => $val)
- {
- $this->set_item($key, $val);
- }
- }
- }
}
/* End of file Config.php */
-/* Location: ./system/core/Config.php */
+/* Location: ./system/core/Config.php */ \ No newline at end of file
diff --git a/system/core/Controller.php b/system/core/Controller.php
index 05e1bf5bf..ee6fec8d5 100644
--- a/system/core/Controller.php
+++ b/system/core/Controller.php
@@ -1,4 +1,4 @@
-<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');
+<?php
/**
* CodeIgniter
*
@@ -24,11 +24,10 @@
* @since Version 1.0
* @filesource
*/
-
-// ------------------------------------------------------------------------
+defined('BASEPATH') OR exit('No direct script access allowed');
/**
- * CodeIgniter Application Controller Class
+ * Application Controller Class
*
* This class object is the super class that every library in
* CodeIgniter will be assigned to.
@@ -41,8 +40,18 @@
*/
class CI_Controller {
+ /**
+ * Reference to the CI singleton
+ *
+ * @var object
+ */
private static $instance;
+ /**
+ * Class constructor
+ *
+ * @return void
+ */
public function __construct()
{
self::$instance =& $this;
@@ -60,11 +69,20 @@ class CI_Controller {
log_message('debug', 'Controller Class Initialized');
}
+ // --------------------------------------------------------------------
+
+ /**
+ * Get the CI singleton
+ *
+ * @static
+ * @return object
+ */
public static function &get_instance()
{
return self::$instance;
}
+
}
/* End of file Controller.php */
-/* Location: ./system/core/Controller.php */
+/* Location: ./system/core/Controller.php */ \ No newline at end of file
diff --git a/system/core/Exceptions.php b/system/core/Exceptions.php
index f36b31598..ced65ece4 100755..100644
--- a/system/core/Exceptions.php
+++ b/system/core/Exceptions.php
@@ -1,4 +1,4 @@
-<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');
+<?php
/**
* CodeIgniter
*
@@ -24,6 +24,7 @@
* @since Version 1.0
* @filesource
*/
+defined('BASEPATH') OR exit('No direct script access allowed');
/**
* Exceptions Class
@@ -36,39 +37,38 @@
*/
class CI_Exceptions {
- public $action;
- public $severity;
- public $message;
- public $filename;
- public $line;
-
/**
* Nesting level of the output buffering mechanism
*
- * @var int
+ * @var int
*/
public $ob_level;
/**
* List if available error levels
*
- * @var array
+ * @var array
*/
public $levels = array(
- E_ERROR => 'Error',
- E_WARNING => 'Warning',
- E_PARSE => 'Parsing Error',
- E_NOTICE => 'Notice',
- E_CORE_ERROR => 'Core Error',
- E_CORE_WARNING => 'Core Warning',
- E_COMPILE_ERROR => 'Compile Error',
- E_COMPILE_WARNING => 'Compile Warning',
- E_USER_ERROR => 'User Error',
- E_USER_WARNING => 'User Warning',
- E_USER_NOTICE => 'User Notice',
- E_STRICT => 'Runtime Notice'
- );
+ E_ERROR => 'Error',
+ E_WARNING => 'Warning',
+ E_PARSE => 'Parsing Error',
+ E_NOTICE => 'Notice',
+ E_CORE_ERROR => 'Core Error',
+ E_CORE_WARNING => 'Core Warning',
+ E_COMPILE_ERROR => 'Compile Error',
+ E_COMPILE_WARNING => 'Compile Warning',
+ E_USER_ERROR => 'User Error',
+ E_USER_WARNING => 'User Warning',
+ E_USER_NOTICE => 'User Notice',
+ E_STRICT => 'Runtime Notice'
+ );
+ /**
+ * Class constructor
+ *
+ * @return void
+ */
public function __construct()
{
$this->ob_level = ob_get_level();
@@ -80,28 +80,30 @@ class CI_Exceptions {
/**
* Exception Logger
*
- * This function logs PHP generated error messages
+ * Logs PHP generated error messages
*
- * @param string the error severity
- * @param string the error string
- * @param string the error filepath
- * @param string the error line number
+ * @param int $severity Log level
+ * @param string $message Error message
+ * @param string $filepath File path
+ * @param int $line Line number
* @return void
*/
public function log_exception($severity, $message, $filepath, $line)
{
- $severity = ( ! isset($this->levels[$severity])) ? $severity : $this->levels[$severity];
+ $severity = isset($this->levels[$severity]) ? $this->levels[$severity] : $severity;
log_message('error', 'Severity: '.$severity.' --> '.$message. ' '.$filepath.' '.$line, TRUE);
}
// --------------------------------------------------------------------
/**
- * 404 Page Not Found Handler
+ * 404 Error Handler
+ *
+ * @uses CI_Exceptions::show_error()
*
- * @param string the page
- * @param bool log error yes/no
- * @return string
+ * @param string $page Page URI
+ * @param bool $log_error Whether to log the error
+ * @return void
*/
public function show_404($page = '', $log_error = TRUE)
{
@@ -123,28 +125,28 @@ class CI_Exceptions {
/**
* General Error Page
*
- * This function takes an error message as input
- * (either as a string or an array) and displays
- * it using the specified template.
+ * Takes an error message as input (either as a string or an array)
+ * and displays it using the specified template.
+ *
+ * @param string $heading Page heading
+ * @param string|string[] $message Error message
+ * @param string $template Template name
+ * @param int $status_code (default: 500)
*
- * @param string the heading
- * @param string the message
- * @param string the template name
- * @param int the status code
- * @return string
+ * @return string Error page output
*/
public function show_error($heading, $message, $template = 'error_general', $status_code = 500)
{
set_status_header($status_code);
- $message = '<p>'.implode('</p><p>', ( ! is_array($message)) ? array($message) : $message).'</p>';
+ $message = '<p>'.implode('</p><p>', is_array($message) ? $message : array($message)).'</p>';
if (ob_get_level() > $this->ob_level + 1)
{
ob_end_flush();
}
ob_start();
- include(APPPATH.'errors/'.$template.'.php');
+ include(VIEWPATH.'errors/'.$template.'.php');
$buffer = ob_get_contents();
ob_end_clean();
return $buffer;
@@ -155,15 +157,15 @@ class CI_Exceptions {
/**
* Native PHP error handler
*
- * @param string the error severity
- * @param string the error string
- * @param string the error filepath
- * @param string the error line number
- * @return string
+ * @param int $severity Error level
+ * @param string $message Error message
+ * @param string $filepath File path
+ * @param int $line Line number
+ * @return string Error page output
*/
public function show_php_error($severity, $message, $filepath, $line)
{
- $severity = ( ! isset($this->levels[$severity])) ? $severity : $this->levels[$severity];
+ $severity = isset($this->levels[$severity]) ? $this->levels[$severity] : $severity;
$filepath = str_replace('\\', '/', $filepath);
// For safety reasons we do not show the full file path
@@ -178,7 +180,7 @@ class CI_Exceptions {
ob_end_flush();
}
ob_start();
- include(APPPATH.'errors/'.'error_php.php');
+ include(VIEWPATH.'errors/error_php.php');
$buffer = ob_get_contents();
ob_end_clean();
echo $buffer;
diff --git a/system/core/Hooks.php b/system/core/Hooks.php
index 68e30ef0f..3c28ec9ba 100755..100644
--- a/system/core/Hooks.php
+++ b/system/core/Hooks.php
@@ -1,4 +1,4 @@
-<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');
+<?php
/**
* CodeIgniter
*
@@ -24,9 +24,10 @@
* @since Version 1.0
* @filesource
*/
+defined('BASEPATH') OR exit('No direct script access allowed');
/**
- * CodeIgniter Hooks Class
+ * Hooks Class
*
* Provides a mechanism to extend the base system without hacking.
*
@@ -39,26 +40,30 @@
class CI_Hooks {
/**
- * Determines wether hooks are enabled
+ * Determines whether hooks are enabled
*
- * @var bool
+ * @var bool
*/
- public $enabled = FALSE;
+ public $enabled = FALSE;
+
/**
* List of all hooks set in config/hooks.php
*
- * @var array
+ * @var array
*/
- public $hooks = array();
+ public $hooks = array();
+
/**
- * Determines wether hook is in progress, used to prevent infinte loops
+ * In progress flag
+ *
+ * Determines whether hook is in progress, used to prevent infinte loops
*
- * @var bool
+ * @var bool
*/
- public $in_progress = FALSE;
+ protected $_in_progress = FALSE;
/**
- * Initialize the Hooks Preferences
+ * Class constructor
*
* @return void
*/
@@ -70,7 +75,7 @@ class CI_Hooks {
// If hooks are not enabled in the config file
// there is nothing else to do
- if ($CFG->item('enable_hooks') == FALSE)
+ if ($CFG->item('enable_hooks') === FALSE)
{
return;
}
@@ -102,8 +107,10 @@ class CI_Hooks {
*
* Calls a particular hook. Called by CodeIgniter.php.
*
- * @param string the hook name
- * @return mixed
+ * @uses CI_Hooks::_run_hook()
+ *
+ * @param string $which Hook name
+ * @return bool TRUE on success or FALSE on failure
*/
public function call_hook($which = '')
{
@@ -134,8 +141,8 @@ class CI_Hooks {
*
* Runs a particular hook
*
- * @param array the hook details
- * @return bool
+ * @param array $data Hook details
+ * @return bool TRUE on success or FALSE on failure
*/
protected function _run_hook($data)
{
@@ -150,7 +157,7 @@ class CI_Hooks {
// If the script being called happens to have the same
// hook call within it a loop can happen
- if ($this->in_progress == TRUE)
+ if ($this->_in_progress === TRUE)
{
return;
}
@@ -171,44 +178,20 @@ class CI_Hooks {
return FALSE;
}
- // -----------------------------------
- // Set class/function name
- // -----------------------------------
-
- $class = FALSE;
- $function = FALSE;
- $params = '';
-
- if ( ! empty($data['class']))
- {
- $class = $data['class'];
- }
-
- if ( ! empty($data['function']))
- {
- $function = $data['function'];
- }
-
- if (isset($data['params']))
- {
- $params = $data['params'];
- }
+ // Determine and class and/or function names
+ $class = empty($data['class']) ? FALSE : $data['class'];
+ $function = empty($data['function']) ? FALSE : $data['function'];
+ $params = isset($data['params']) ? $data['params'] : '';
if ($class === FALSE && $function === FALSE)
{
return FALSE;
}
- // -----------------------------------
- // Set the in_progress flag
- // -----------------------------------
-
- $this->in_progress = TRUE;
+ // Set the _in_progress flag
+ $this->_in_progress = TRUE;
- // -----------------------------------
// Call the requested class and/or function
- // -----------------------------------
-
if ($class !== FALSE)
{
if ( ! class_exists($class))
@@ -216,7 +199,7 @@ class CI_Hooks {
require($filepath);
}
- $HOOK = new $class;
+ $HOOK = new $class();
$HOOK->$function($params);
}
else
@@ -229,7 +212,7 @@ class CI_Hooks {
$function($params);
}
- $this->in_progress = FALSE;
+ $this->_in_progress = FALSE;
return TRUE;
}
diff --git a/system/core/Input.php b/system/core/Input.php
index 6e6885992..a3ad14e24 100755..100644
--- a/system/core/Input.php
+++ b/system/core/Input.php
@@ -1,4 +1,4 @@
-<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');
+<?php
/**
* CodeIgniter
*
@@ -24,6 +24,7 @@
* @since Version 1.0
* @filesource
*/
+defined('BASEPATH') OR exit('No direct script access allowed');
/**
* Input Class
@@ -41,53 +42,80 @@ class CI_Input {
/**
* IP address of the current user
*
- * @var string
+ * @var string
*/
- public $ip_address = FALSE;
+ public $ip_address = FALSE;
+
/**
- * user agent (web browser) being used by the current user
+ * User agent strin
*
- * @var string
+ * @var string
*/
- public $user_agent = FALSE;
+ public $user_agent = FALSE;
+
/**
- * If FALSE, then $_GET will be set to an empty array
+ * Allow GET array flag
+ *
+ * If set to FALSE, then $_GET will be set to an empty array.
*
- * @var bool
+ * @var bool
*/
- protected $_allow_get_array = TRUE;
+ protected $_allow_get_array = TRUE;
+
/**
- * If TRUE, then newlines are standardized
+ * Standartize new lines flag
+ *
+ * If set to TRUE, then newlines are standardized.
*
- * @var bool
+ * @var bool
*/
- protected $_standardize_newlines = TRUE;
+ protected $_standardize_newlines = TRUE;
+
/**
- * Determines whether the XSS filter is always active when GET, POST or COOKIE data is encountered
- * Set automatically based on config setting
+ * Enable XSS flag
+ *
+ * Determines whether the XSS filter is always active when
+ * GET, POST or COOKIE data is encountered.
+ * Set automatically based on config setting.
*
- * @var bool
+ * @var bool
*/
- protected $_enable_xss = FALSE;
+ protected $_enable_xss = FALSE;
+
/**
+ * Enable CSRF flag
+ *
* Enables a CSRF cookie token to be set.
- * Set automatically based on config setting
+ * Set automatically based on config setting.
*
- * @var bool
+ * @var bool
*/
- protected $_enable_csrf = FALSE;
+ protected $_enable_csrf = FALSE;
+
/**
* List of all HTTP request headers
*
* @var array
*/
- protected $headers = array();
+ protected $headers = array();
/**
- * Constructor
+ * Input stream data
*
- * Sets whether to globally enable the XSS processing
- * and whether to allow the $_GET array
+ * Parsed from php://input at runtime
+ *
+ * @see CI_Input::input_stream()
+ * @var array
+ */
+ protected $_input_stream = NULL;
+
+ /**
+ * Class constructor
+ *
+ * Determines whether to globally enable the XSS processing
+ * and whether to allow the $_GET array.
+ *
+ * @return void
*/
public function __construct()
{
@@ -116,18 +144,18 @@ class CI_Input {
/**
* Fetch from array
*
- * This is a helper function to retrieve values from global arrays
+ * Internal method used to retrieve values from global arrays.
*
- * @param array
- * @param string
- * @param bool
- * @return string
+ * @param array &$array $_GET, $_POST, $_COOKIE, $_SERVER, etc.
+ * @param string $index Index for item to be fetched from $array
+ * @param bool $xss_clean Whether to apply XSS filtering
+ * @return mixed
*/
protected function _fetch_from_array(&$array, $index = '', $xss_clean = FALSE)
{
if ( ! isset($array[$index]))
{
- return FALSE;
+ return NULL;
}
if ($xss_clean === TRUE)
@@ -141,17 +169,22 @@ class CI_Input {
// --------------------------------------------------------------------
/**
- * Fetch an item from the GET array
- *
- * @param string
- * @param bool
- * @return string
- */
+ * Fetch an item from the GET array
+ *
+ * @param string $index Index for item to be fetched from $_GET
+ * @param bool $xss_clean Whether to apply XSS filtering
+ * @return mixed
+ */
public function get($index = NULL, $xss_clean = FALSE)
{
// Check if a field has been provided
- if ($index === NULL && ! empty($_GET))
+ if ($index === NULL)
{
+ if (empty($_GET))
+ {
+ return array();
+ }
+
$get = array();
// loop through the full _GET array
@@ -168,17 +201,22 @@ class CI_Input {
// --------------------------------------------------------------------
/**
- * Fetch an item from the POST array
- *
- * @param string
- * @param bool
- * @return string
- */
+ * Fetch an item from the POST array
+ *
+ * @param string $index Index for item to be fetched from $_POST
+ * @param bool $xss_clean Whether to apply XSS filtering
+ * @return mixed
+ */
public function post($index = NULL, $xss_clean = FALSE)
{
// Check if a field has been provided
- if ($index === NULL && ! empty($_POST))
+ if ($index === NULL)
{
+ if (empty($_POST))
+ {
+ return array();
+ }
+
$post = array();
// Loop through the full _POST array and return it
@@ -192,16 +230,15 @@ class CI_Input {
return $this->_fetch_from_array($_POST, $index, $xss_clean);
}
-
// --------------------------------------------------------------------
/**
- * Fetch an item from either the GET array or the POST
- *
- * @param string The index key
- * @param bool XSS cleaning
- * @return string
- */
+ * Fetch an item from POST data with fallback to GET
+ *
+ * @param string $index Index for item to be fetched from $_POST or $_GET
+ * @param bool $xss_clean Whether to apply XSS filtering
+ * @return mixed
+ */
public function get_post($index = '', $xss_clean = FALSE)
{
return isset($_POST[$index])
@@ -212,35 +249,80 @@ class CI_Input {
// --------------------------------------------------------------------
/**
- * Fetch an item from the COOKIE array
- *
- * @param string
- * @param bool
- * @return string
- */
+ * Fetch an item from the COOKIE array
+ *
+ * @param string $index Index for item to be fetched from $_COOKIE
+ * @param bool $xss_clean Whether to apply XSS filtering
+ * @return mixed
+ */
public function cookie($index = '', $xss_clean = FALSE)
{
return $this->_fetch_from_array($_COOKIE, $index, $xss_clean);
}
+ // --------------------------------------------------------------------
+
+ /**
+ * Fetch an item from the SERVER array
+ *
+ * @param string $index Index for item to be fetched from $_SERVER
+ * @param bool $xss_clean Whether to apply XSS filtering
+ * @return mixed
+ */
+ public function server($index = '', $xss_clean = FALSE)
+ {
+ return $this->_fetch_from_array($_SERVER, $index, $xss_clean);
+ }
+
+ // ------------------------------------------------------------------------
+
+ /**
+ * Fetch an item from the php://input stream
+ *
+ * Useful when you need to access PUT, DELETE or PATCH request data.
+ *
+ * @param string $index Index for item to be fetched
+ * @param bool $xss_clean Whether to apply XSS filtering
+ * @return mixed
+ */
+ public function input_stream($index = '', $xss_clean = FALSE)
+ {
+ // The input stream can only be read once, so we'll need to check
+ // if we have already done that first.
+ if (is_array($this->_input_stream))
+ {
+ return $this->_fetch_from_array($this->_input_stream, $index, $xss_clean);
+ }
+
+ // Parse the input stream in our cache var
+ parse_str(file_get_contents('php://input'), $this->_input_stream);
+ if ( ! is_array($this->_input_stream))
+ {
+ $this->_input_stream = array();
+ return NULL;
+ }
+
+ return $this->_fetch_from_array($this->_input_stream, $index, $xss_clean);
+ }
+
// ------------------------------------------------------------------------
/**
- * Set cookie
- *
- * Accepts seven parameters, or you can submit an associative
- * array in the first parameter containing all the values.
- *
- * @param mixed
- * @param string the value of the cookie
- * @param string the number of seconds until expiration
- * @param string the cookie domain. Usually: .yourdomain.com
- * @param string the cookie path
- * @param string the cookie prefix
- * @param bool true makes the cookie secure
- * @param bool true makes the cookie accessible via http(s) only (no javascript)
- * @return void
- */
+ * Set cookie
+ *
+ * Accepts an arbitrary number of parameters (up to 7) or an associative
+ * array in the first parameter containing all the values.
+ *
+ * @param string|mixed[] $name Cookie name or an array containing parameters
+ * @param string $value Cookie value
+ * @param int $expire Cookie expiration time in seconds
+ * @param string $domain Cookie domain (e.g.: '.yourdomain.com')
+ * @param string $path Cookie path (default: '/')
+ * @param string $prefix Cookie name prefix
+ * @param bool $secure Whether to only transfer cookies via SSL
+ * @param bool $httponly Whether to only makes the cookie accessible via HTTP (no javascript)
+ * @return void
+ */
public function set_cookie($name = '', $value = '', $expire = '', $domain = '', $path = '/', $prefix = '', $secure = FALSE, $httponly = FALSE)
{
if (is_array($name))
@@ -255,23 +337,27 @@ class CI_Input {
}
}
- if ($prefix == '' && config_item('cookie_prefix') != '')
+ if ($prefix === '' && config_item('cookie_prefix') !== '')
{
$prefix = config_item('cookie_prefix');
}
+
if ($domain == '' && config_item('cookie_domain') != '')
{
$domain = config_item('cookie_domain');
}
- if ($path == '/' && config_item('cookie_path') !== '/')
+
+ if ($path === '/' && config_item('cookie_path') !== '/')
{
$path = config_item('cookie_path');
}
- if ($secure == FALSE && config_item('cookie_secure') != FALSE)
+
+ if ($secure === FALSE && config_item('cookie_secure') !== FALSE)
{
$secure = config_item('cookie_secure');
}
- if ($httponly == FALSE && config_item('cookie_httponly') != FALSE)
+
+ if ($httponly === FALSE && config_item('cookie_httponly') !== FALSE)
{
$httponly = config_item('cookie_httponly');
}
@@ -291,24 +377,12 @@ class CI_Input {
// --------------------------------------------------------------------
/**
- * Fetch an item from the SERVER array
- *
- * @param string
- * @param bool
- * @return string
- */
- public function server($index = '', $xss_clean = FALSE)
- {
- return $this->_fetch_from_array($_SERVER, $index, $xss_clean);
- }
-
- // --------------------------------------------------------------------
-
- /**
- * Fetch the IP Address
- *
- * @return string
- */
+ * Fetch the IP Address
+ *
+ * Determines and validates the visitor's IP address.
+ *
+ * @return string IP address
+ */
public function ip_address()
{
if ($this->ip_address !== FALSE)
@@ -316,39 +390,117 @@ class CI_Input {
return $this->ip_address;
}
- if (config_item('proxy_ips') != '' && $this->server('HTTP_X_FORWARDED_FOR') && $this->server('REMOTE_ADDR'))
+ $proxy_ips = config_item('proxy_ips');
+ if ( ! empty($proxy_ips) && ! is_array($proxy_ips))
{
- $proxies = preg_split('/[\s,]/', config_item('proxy_ips'), -1, PREG_SPLIT_NO_EMPTY);
- $proxies = is_array($proxies) ? $proxies : array($proxies);
-
- $this->ip_address = in_array($_SERVER['REMOTE_ADDR'], $proxies) ? $_SERVER['HTTP_X_FORWARDED_FOR'] : $_SERVER['REMOTE_ADDR'];
- }
- elseif ( ! $this->server('HTTP_CLIENT_IP') && $this->server('REMOTE_ADDR'))
- {
- $this->ip_address = $_SERVER['REMOTE_ADDR'];
- }
- elseif ($this->server('REMOTE_ADDR') && $this->server('HTTP_CLIENT_IP'))
- {
- $this->ip_address = $_SERVER['HTTP_CLIENT_IP'];
- }
- elseif ($this->server('HTTP_CLIENT_IP'))
- {
- $this->ip_address = $_SERVER['HTTP_CLIENT_IP'];
- }
- elseif ($this->server('HTTP_X_FORWARDED_FOR'))
- {
- $this->ip_address = $_SERVER['HTTP_X_FORWARDED_FOR'];
+ $proxy_ips = explode(',', str_replace(' ', '', $proxy_ips));
}
- if ($this->ip_address === FALSE)
- {
- return $this->ip_address = '0.0.0.0';
- }
+ $this->ip_address = $this->server('REMOTE_ADDR');
- if (strpos($this->ip_address, ',') !== FALSE)
+ if ($proxy_ips)
{
- $x = explode(',', $this->ip_address);
- $this->ip_address = trim(end($x));
+ foreach (array('HTTP_X_FORWARDED_FOR', 'HTTP_CLIENT_IP', 'HTTP_X_CLIENT_IP', 'HTTP_X_CLUSTER_CLIENT_IP') as $header)
+ {
+ if (($spoof = $this->server($header)) !== NULL)
+ {
+ // Some proxies typically list the whole chain of IP
+ // addresses through which the client has reached us.
+ // e.g. client_ip, proxy_ip1, proxy_ip2, etc.
+ sscanf($spoof, '%[^,]', $spoof);
+
+ if ( ! $this->valid_ip($spoof))
+ {
+ $spoof = NULL;
+ }
+ else
+ {
+ break;
+ }
+ }
+ }
+
+ if ($spoof)
+ {
+ for ($i = 0, $c = count($proxy_ips); $i < $c; $i++)
+ {
+ // Check if we have an IP address or a subnet
+ if (strpos($proxy_ips[$i], '/') === FALSE)
+ {
+ // An IP address (and not a subnet) is specified.
+ // We can compare right away.
+ if ($proxy_ips[$i] === $this->ip_address)
+ {
+ $this->ip_address = $spoof;
+ break;
+ }
+
+ continue;
+ }
+
+ // We have a subnet ... now the heavy lifting begins
+ isset($separator) OR $separator = $this->valid_ip($this->ip_address, 'ipv6') ? ':' : '.';
+
+ // If the proxy entry doesn't match the IP protocol - skip it
+ if (strpos($proxy_ips[$i], $separator) === FALSE)
+ {
+ continue;
+ }
+
+ // Convert the REMOTE_ADDR IP address to binary, if needed
+ if ( ! isset($ip, $sprintf))
+ {
+ if ($separator === ':')
+ {
+ // Make sure we're have the "full" IPv6 format
+ $ip = explode(':',
+ str_replace('::',
+ str_repeat(':', 9 - substr_count($this->ip_address, ':')),
+ $this->ip_address
+ )
+ );
+
+ for ($i = 0; $i < 8; $i++)
+ {
+ $ip[$i] = intval($ip[$i], 16);
+ }
+
+ $sprintf = '%016b%016b%016b%016b%016b%016b%016b%016b';
+ }
+ else
+ {
+ $ip = explode('.', $this->ip_address);
+ $sprintf = '%08b%08b%08b%08b';
+ }
+
+ $ip = vsprintf($sprintf, $ip);
+ }
+
+ // Split the netmask length off the network address
+ sscanf($proxy_ips[$i], '%[^/]/%d', $netaddr, $masklen);
+
+ // Again, an IPv6 address is most likely in a compressed form
+ if ($separator === ':')
+ {
+ $netaddr = explode(':', str_replace('::', str_repeat(':', 9 - substr_count($netaddr, ':')), $netaddr));
+ for ($i = 0; $i < 8; $i++)
+ {
+ $netaddr[$i] = intval($netaddr[$i], 16);
+ }
+ }
+ else
+ {
+ $netaddr = explode('.', $netaddr);
+ }
+
+ // Convert to binary and finally compare
+ if (strncmp($ip, vsprintf($sprintf, $netaddr), $masklen) === 0)
+ {
+ $this->ip_address = $spoof;
+ break;
+ }
+ }
+ }
}
if ( ! $this->valid_ip($this->ip_address))
@@ -362,25 +514,37 @@ class CI_Input {
// --------------------------------------------------------------------
/**
- * Validate IP Address
- *
- * Updated version suggested by Geert De Deckere
- *
- * @param string
- * @return bool
- */
- public function valid_ip($ip)
+ * Validate IP Address
+ *
+ * @param string $ip IP address
+ * @param string $which IP protocol: 'ipv4' or 'ipv6'
+ * @return bool
+ */
+ public function valid_ip($ip, $which = '')
{
- return (bool) filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_IPV4);
+ switch (strtolower($which))
+ {
+ case 'ipv4':
+ $which = FILTER_FLAG_IPV4;
+ break;
+ case 'ipv6':
+ $which = FILTER_FLAG_IPV6;
+ break;
+ default:
+ $which = NULL;
+ break;
+ }
+
+ return (bool) filter_var($ip, FILTER_VALIDATE_IP, $which);
}
// --------------------------------------------------------------------
/**
- * User Agent
- *
- * @return string
- */
+ * Fetch User Agent string
+ *
+ * @return string|null User Agent string or NULL if it doesn't exist
+ */
public function user_agent()
{
if ($this->user_agent !== FALSE)
@@ -388,58 +552,75 @@ class CI_Input {
return $this->user_agent;
}
- return $this->user_agent = isset($_SERVER['HTTP_USER_AGENT']) ? $_SERVER['HTTP_USER_AGENT'] : FALSE;
+ return $this->user_agent = isset($_SERVER['HTTP_USER_AGENT']) ? $_SERVER['HTTP_USER_AGENT'] : NULL;
}
// --------------------------------------------------------------------
/**
- * Sanitize Globals
- *
- * This function does the following:
- *
- * - Unsets $_GET data (if query strings are not enabled)
- * - Unsets all globals if register_globals is enabled
- * - Standardizes newline characters to \n
- *
- * @return void
- */
+ * Sanitize Globals
+ *
+ * Internal method serving for the following purposes:
+ *
+ * - Unsets $_GET data (if query strings are not enabled)
+ * - Unsets all globals if register_globals is enabled
+ * - Cleans POST, COOKIE and SERVER data
+ * - Standardizes newline characters to PHP_EOL
+ *
+ * @return void
+ */
protected function _sanitize_globals()
{
// It would be "wrong" to unset any of these GLOBALS.
- $protected = array('_SERVER', '_GET', '_POST', '_FILES', '_REQUEST',
- '_SESSION', '_ENV', 'GLOBALS', 'HTTP_RAW_POST_DATA',
- 'system_folder', 'application_folder', 'BM', 'EXT',
- 'CFG', 'URI', 'RTR', 'OUT', 'IN'
- );
-
- // Unset globals for securiy.
+ $protected = array(
+ '_SERVER',
+ '_GET',
+ '_POST',
+ '_FILES',
+ '_REQUEST',
+ '_SESSION',
+ '_ENV',
+ 'GLOBALS',
+ 'HTTP_RAW_POST_DATA',
+ 'system_folder',
+ 'application_folder',
+ 'BM',
+ 'EXT',
+ 'CFG',
+ 'URI',
+ 'RTR',
+ 'OUT',
+ 'IN'
+ );
+
+ // Unset globals for security.
// This is effectively the same as register_globals = off
- foreach (array($_GET, $_POST, $_COOKIE) as $global)
+ // PHP 5.4 no longer has the register_globals functionality.
+ if ( ! is_php('5.4'))
{
- if ( ! is_array($global))
+ foreach (array($_GET, $_POST, $_COOKIE) as $global)
{
- if ( ! in_array($global, $protected))
+ if (is_array($global))
{
- global $$global;
- $$global = NULL;
- }
- }
- else
- {
- foreach ($global as $key => $val)
- {
- if ( ! in_array($key, $protected))
+ foreach ($global as $key => $val)
{
- global $$key;
- $$key = NULL;
+ if ( ! in_array($key, $protected))
+ {
+ global $$key;
+ $$key = NULL;
+ }
}
}
+ elseif ( ! in_array($global, $protected))
+ {
+ global $$global;
+ $$global = NULL;
+ }
}
}
// Is $_GET data allowed? If not we'll set the $_GET to an empty array
- if ($this->_allow_get_array == FALSE)
+ if ($this->_allow_get_array === FALSE)
{
$_GET = array();
}
@@ -482,7 +663,7 @@ class CI_Input {
$_SERVER['PHP_SELF'] = strip_tags($_SERVER['PHP_SELF']);
// CSRF Protection check
- if ($this->_enable_csrf == TRUE)
+ if ($this->_enable_csrf === TRUE && ! $this->is_cli_request())
{
$this->security->csrf_verify();
}
@@ -493,22 +674,22 @@ class CI_Input {
// --------------------------------------------------------------------
/**
- * Clean Input Data
- *
- * This is a helper function. It escapes data and
- * standardizes newline characters to \n
- *
- * @param string
- * @return string
- */
+ * Clean Input Data
+ *
+ * Internal method that aids in escaping data and
+ * standardizing newline characters to PHP_EOL.
+ *
+ * @param string|string[] $str Input string(s)
+ * @return string
+ */
protected function _clean_input_data($str)
{
if (is_array($str))
{
$new_array = array();
- foreach ($str as $key => $val)
+ foreach (array_keys($str) as $key)
{
- $new_array[$this->_clean_input_keys($key)] = $this->_clean_input_data($val);
+ $new_array[$this->_clean_input_keys($key)] = $this->_clean_input_data($str[$key]);
}
return $new_array;
}
@@ -539,7 +720,7 @@ class CI_Input {
}
// Standardize newlines if needed
- if ($this->_standardize_newlines == TRUE && strpos($str, "\r") !== FALSE)
+ if ($this->_standardize_newlines === TRUE && strpos($str, "\r") !== FALSE)
{
return str_replace(array("\r\n", "\r", "\r\n\n"), PHP_EOL, $str);
}
@@ -550,18 +731,18 @@ class CI_Input {
// --------------------------------------------------------------------
/**
- * Clean Keys
- *
- * This is a helper function. To prevent malicious users
- * from trying to exploit keys we make sure that keys are
- * only named with alpha-numeric text and a few other items.
- *
- * @param string
- * @return string
- */
+ * Clean Keys
+ *
+ * Internal method that helps to prevent malicious users
+ * from trying to exploit keys we make sure that keys are
+ * only named with alpha-numeric text and a few other items.
+ *
+ * @param string $str Input string
+ * @return string
+ */
protected function _clean_input_keys($str)
{
- if ( ! preg_match('/^[a-z0-9:_\/-]+$/i', $str))
+ if ( ! preg_match('/^[a-z0-9:_\/|-]+$/i', $str))
{
set_status_header(503);
exit('Disallowed Key Characters.');
@@ -581,15 +762,12 @@ class CI_Input {
/**
* Request Headers
*
- * In Apache, you can simply call apache_request_headers(), however for
- * people running other webservers the function is undefined.
- *
- * @param bool XSS cleaning
+ * @param bool $xss_clean Whether to apply XSS filtering
* @return array
*/
public function request_headers($xss_clean = FALSE)
{
- // Look at Apache go!
+ // In Apache, you can simply call apache_request_headers()
if (function_exists('apache_request_headers'))
{
$headers = apache_request_headers();
@@ -600,9 +778,9 @@ class CI_Input {
foreach ($_SERVER as $key => $val)
{
- if (strpos($key, 'HTTP_') === 0)
+ if (sscanf($key, 'HTTP_%s', $header) === 1)
{
- $headers[substr($key, 5)] = $this->_fetch_from_array($_SERVER, $key, $xss_clean);
+ $headers[$header] = $this->_fetch_from_array($_SERVER, $key, $xss_clean);
}
}
}
@@ -626,9 +804,9 @@ class CI_Input {
*
* Returns the value of a single member of the headers class member
*
- * @param string array key for $this->headers
- * @param bool XSS Clean or not
- * @return mixed FALSE on failure, string on success
+ * @param string $index Header name
+ * @param bool $xss_clean Whether to apply XSS filtering
+ * @return string|bool The requested header on success or FALSE on failure
*/
public function get_request_header($index, $xss_clean = FALSE)
{
@@ -639,7 +817,7 @@ class CI_Input {
if ( ! isset($this->headers[$index]))
{
- return FALSE;
+ return NULL;
}
return ($xss_clean === TRUE)
@@ -650,9 +828,9 @@ class CI_Input {
// --------------------------------------------------------------------
/**
- * Is ajax Request?
+ * Is AJAX request?
*
- * Test to see if a request contains the HTTP_X_REQUESTED_WITH header
+ * Test to see if a request contains the HTTP_X_REQUESTED_WITH header.
*
* @return bool
*/
@@ -664,9 +842,9 @@ class CI_Input {
// --------------------------------------------------------------------
/**
- * Is cli Request?
+ * Is CLI request?
*
- * Test to see if a request was made from the command line
+ * Test to see if a request was made from the command line.
*
* @return bool
*/
@@ -680,10 +858,11 @@ class CI_Input {
/**
* Get Request Method
*
- * Return the Request Method
+ * Return the request method
*
- * @param bool uppercase or lowercase
- * @return bool
+ * @param bool $upper Whether to return in upper or lower case
+ * (default: FALSE)
+ * @return string
*/
public function method($upper = FALSE)
{
@@ -695,4 +874,4 @@ class CI_Input {
}
/* End of file Input.php */
-/* Location: ./system/core/Input.php */
+/* Location: ./system/core/Input.php */ \ No newline at end of file
diff --git a/system/core/Lang.php b/system/core/Lang.php
index 9ef76f4d6..9e6f43716 100755..100644
--- a/system/core/Lang.php
+++ b/system/core/Lang.php
@@ -1,4 +1,4 @@
-<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');
+<?php
/**
* CodeIgniter
*
@@ -24,8 +24,7 @@
* @since Version 1.0
* @filesource
*/
-
-// ------------------------------------------------------------------------
+defined('BASEPATH') OR exit('No direct script access allowed');
/**
* Language Class
@@ -41,16 +40,22 @@ class CI_Lang {
/**
* List of translations
*
- * @var array
+ * @var array
*/
- public $language = array();
+ public $language = array();
+
/**
* List of loaded language files
*
- * @var array
+ * @var array
*/
- public $is_loaded = array();
+ public $is_loaded = array();
+ /**
+ * Class constructor
+ *
+ * @return void
+ */
public function __construct()
{
log_message('debug', 'Language Class Initialized');
@@ -61,77 +66,90 @@ class CI_Lang {
/**
* Load a language file
*
- * @param mixed the name of the language file to be loaded. Can be an array
- * @param string the language (english, etc.)
- * @param bool return loaded array of translations
- * @param bool add suffix to $langfile
- * @param string alternative path to look for language file
- * @return mixed
+ * @param mixed $langfile Language file name
+ * @param string $idiom Language name (english, etc.)
+ * @param bool $return Whether to return the loaded array of translations
+ * @param bool $add_suffix Whether to add suffix to $langfile
+ * @param string $alt_path Alternative path to look for the language file
+ *
+ * @return void|string[] Array containing translations, if $return is set to TRUE
*/
- public function load($langfile = '', $idiom = '', $return = FALSE, $add_suffix = TRUE, $alt_path = '')
+ public function load($langfile, $idiom = '', $return = FALSE, $add_suffix = TRUE, $alt_path = '')
{
$langfile = str_replace('.php', '', $langfile);
- if ($add_suffix == TRUE)
+ if ($add_suffix === TRUE)
{
- $langfile = str_replace('_lang.', '', $langfile).'_lang';
+ $langfile = str_replace('_lang', '', $langfile).'_lang';
}
$langfile .= '.php';
- if (in_array($langfile, $this->is_loaded, TRUE))
+ if (empty($idiom) OR ! ctype_alpha($idiom))
{
- return;
+ $config =& get_config();
+ $idiom = empty($config['language']) ? 'english' : $config['language'];
}
- $config =& get_config();
+ if ($return === FALSE && isset($this->is_loaded[$langfile]) && $this->is_loaded[$langfile] === $idiom)
+ {
+ return;
+ }
- if ($idiom == '')
+ // Load the base file, so any others found can override it
+ $basepath = BASEPATH.'language/'.$idiom.'/'.$langfile;
+ if (($found = file_exists($basepath)) === TRUE)
{
- $deft_lang = ( ! isset($config['language'])) ? 'english' : $config['language'];
- $idiom = ($deft_lang == '') ? 'english' : $deft_lang;
+ include($basepath);
}
- // Determine where the language file is and load it
- if ($alt_path != '' && file_exists($alt_path.'language/'.$idiom.'/'.$langfile))
+ // Do we have an alternative path to look in?
+ if ($alt_path !== '')
{
- include($alt_path.'language/'.$idiom.'/'.$langfile);
+ $alt_path .= 'language/'.$idiom.'/'.$langfile;
+ if (file_exists($alt_path))
+ {
+ include($alt_path);
+ $found = TRUE;
+ }
}
else
{
- $found = FALSE;
-
foreach (get_instance()->load->get_package_paths(TRUE) as $package_path)
{
- if (file_exists($package_path.'language/'.$idiom.'/'.$langfile))
+ $package_path .= 'language/'.$idiom.'/'.$langfile;
+ if ($basepath !== $package_path && file_exists($package_path))
{
- include($package_path.'language/'.$idiom.'/'.$langfile);
+ include($package_path);
$found = TRUE;
break;
}
}
-
- if ($found !== TRUE)
- {
- show_error('Unable to load the requested language file: language/'.$idiom.'/'.$langfile);
- }
}
+ if ($found !== TRUE)
+ {
+ show_error('Unable to load the requested language file: language/'.$idiom.'/'.$langfile);
+ }
if ( ! isset($lang) OR ! is_array($lang))
{
log_message('error', 'Language file contains no data: language/'.$idiom.'/'.$langfile);
+
+ if ($return === TRUE)
+ {
+ return array();
+ }
return;
}
- if ($return == TRUE)
+ if ($return === TRUE)
{
return $lang;
}
- $this->is_loaded[] = $langfile;
+ $this->is_loaded[$langfile] = $idiom;
$this->language = array_merge($this->language, $lang);
- unset($lang);
log_message('debug', 'Language file loaded: language/'.$idiom.'/'.$langfile);
return TRUE;
@@ -140,17 +158,20 @@ class CI_Lang {
// --------------------------------------------------------------------
/**
- * Fetch a single line of text from the language array
+ * Language line
+ *
+ * Fetches a single line of text from the language array
*
- * @param string $line the language line
- * @return string
+ * @param string $line Language line key
+ * @param bool $log_errors Whether to log an error message if the line is not found
+ * @return string Translation
*/
- public function line($line = '')
+ public function line($line = '', $log_errors = TRUE)
{
- $value = ($line == '' OR ! isset($this->language[$line])) ? FALSE : $this->language[$line];
+ $value = ($line === '' OR ! isset($this->language[$line])) ? FALSE : $this->language[$line];
// Because killer robots like unicorns!
- if ($value === FALSE)
+ if ($value === FALSE && $log_errors === TRUE)
{
log_message('error', 'Could not find the language line "'.$line.'"');
}
@@ -161,4 +182,4 @@ class CI_Lang {
}
/* End of file Lang.php */
-/* Location: ./system/core/Lang.php */
+/* Location: ./system/core/Lang.php */ \ No newline at end of file
diff --git a/system/core/Loader.php b/system/core/Loader.php
index 027ed20e5..651507470 100644
--- a/system/core/Loader.php
+++ b/system/core/Loader.php
@@ -1,4 +1,4 @@
-<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');
+<?php
/**
* CodeIgniter
*
@@ -24,16 +24,17 @@
* @since Version 1.0
* @filesource
*/
+defined('BASEPATH') OR exit('No direct script access allowed');
/**
* Loader Class
*
- * Loads views and files
+ * Loads framework components.
*
* @package CodeIgniter
* @subpackage Libraries
- * @author EllisLab Dev Team
* @category Loader
+ * @author EllisLab Dev Team
* @link http://codeigniter.com/user_guide/libraries/loader.html
*/
class CI_Loader {
@@ -42,83 +43,96 @@ class CI_Loader {
/**
* Nesting level of the output buffering mechanism
*
- * @var int
+ * @var int
*/
protected $_ci_ob_level;
+
/**
* List of paths to load views from
*
- * @var array
+ * @var array
*/
- protected $_ci_view_paths = array();
+ protected $_ci_view_paths = array();
+
/**
* List of paths to load libraries from
*
- * @var array
+ * @var array
*/
- protected $_ci_library_paths = array();
+ protected $_ci_library_paths = array();
+
/**
* List of paths to load models from
*
- * @var array
+ * @var array
*/
- protected $_ci_model_paths = array();
+ protected $_ci_model_paths = array();
+
/**
* List of paths to load helpers from
*
- * @var array
+ * @var array
*/
- protected $_ci_helper_paths = array();
+ protected $_ci_helper_paths = array();
+
/**
* List of loaded base classes
*
- * @var array
+ * @var array
*/
- protected $_base_classes = array(); // Set by the controller class
+ protected $_base_classes = array(); // Set by the controller class
+
/**
* List of cached variables
*
- * @var array
+ * @var array
*/
- protected $_ci_cached_vars = array();
+ protected $_ci_cached_vars = array();
+
/**
* List of loaded classes
*
- * @var array
+ * @var array
*/
- protected $_ci_classes = array();
+ protected $_ci_classes = array();
+
/**
* List of loaded files
*
- * @var array
+ * @var array
*/
- protected $_ci_loaded_files = array();
+ protected $_ci_loaded_files = array();
+
/**
* List of loaded models
*
- * @var array
+ * @var array
*/
- protected $_ci_models = array();
+ protected $_ci_models = array();
+
/**
* List of loaded helpers
*
- * @var array
+ * @var array
*/
- protected $_ci_helpers = array();
+ protected $_ci_helpers = array();
+
/**
* List of class name mappings
*
- * @var array
+ * @var array
*/
- protected $_ci_varmap = array(
- 'unit_test' => 'unit',
- 'user_agent' => 'agent'
- );
+ protected $_ci_varmap = array(
+ 'unit_test' => 'unit',
+ 'user_agent' => 'agent'
+ );
/**
- * Constructor
+ * Class constructor
+ *
+ * Sets component load paths, gets the initial output buffering level.
*
- * Sets the path to the view files and gets the initial output buffering level
+ * @return void
*/
public function __construct()
{
@@ -134,22 +148,18 @@ class CI_Loader {
// --------------------------------------------------------------------
/**
- * Initialize the Loader
+ * Initializer
*
- * This method is called once in CI_Controller.
- *
- * @param array
- * @return object
+ * @todo Figure out a way to move this to the constructor
+ * without breaking *package_path*() methods.
+ * @uses CI_Loader::_ci_autoloader()
+ * @used-by CI_Controller::__construct()
+ * @return void
*/
public function initialize()
{
- $this->_ci_classes = array();
- $this->_ci_loaded_files = array();
- $this->_ci_models = array();
$this->_base_classes =& is_loaded();
-
$this->_ci_autoloader();
- return $this;
}
// --------------------------------------------------------------------
@@ -157,36 +167,29 @@ class CI_Loader {
/**
* Is Loaded
*
- * A utility function to test if a class is in the self::$_ci_classes array.
- * This function returns the object name if the class tested for is loaded,
- * and returns FALSE if it isn't.
+ * A utility method to test if a class is in the self::$_ci_classes array.
*
- * It is mainly used in the form_helper -> _get_validation_object()
+ * @used-by Mainly used by Form Helper function _get_validation_object().
*
- * @param string class being checked for
- * @return mixed class object name on the CI SuperObject or FALSE
+ * @param string $class Class name to check for
+ * @return string|bool Class object name if loaded or FALSE
*/
public function is_loaded($class)
{
- if (isset($this->_ci_classes[$class]))
- {
- return $this->_ci_classes[$class];
- }
-
- return FALSE;
+ return isset($this->_ci_classes[$class]) ? $this->_ci_classes[$class] : FALSE;
}
// --------------------------------------------------------------------
/**
- * Class Loader
+ * Library Loader
*
- * This function lets users load and instantiate classes.
- * It is designed to be called from a user's app controllers.
+ * Loads and instantiates libraries.
+ * Designed to be called from application controllers.
*
- * @param string the name of the class
- * @param mixed the optional parameters
- * @param string an optional object name
+ * @param string $library Library name
+ * @param array $params Optional parameters to pass to the library class constructor
+ * @param string $object_name An optional object name to assign to
* @return void
*/
public function library($library = '', $params = NULL, $object_name = NULL)
@@ -201,9 +204,9 @@ class CI_Loader {
return;
}
- if ($library == '' OR isset($this->_base_classes[$library]))
+ if ($library === '' OR isset($this->_base_classes[$library]))
{
- return FALSE;
+ return;
}
if ( ! is_null($params) && ! is_array($params))
@@ -219,26 +222,25 @@ class CI_Loader {
/**
* Model Loader
*
- * This function lets users load and instantiate models.
+ * Loads and instantiates libraries.
*
- * @param string the name of the class
- * @param string name for the model
- * @param bool database connection
+ * @param string $model Model name
+ * @param string $name An optional object name to assign to
+ * @param bool $db_conn An optional database connection configuration to initialize
* @return void
*/
public function model($model, $name = '', $db_conn = FALSE)
{
- if (is_array($model))
+ if (empty($model))
{
- foreach ($model as $babe)
- {
- $this->model($babe);
- }
return;
}
-
- if ($model == '')
+ elseif (is_array($model))
{
+ foreach ($model as $class)
+ {
+ $this->model($class);
+ }
return;
}
@@ -254,7 +256,7 @@ class CI_Loader {
$model = substr($model, $last_slash);
}
- if ($name == '')
+ if (empty($name))
{
$name = $model;
}
@@ -311,18 +313,21 @@ class CI_Loader {
/**
* Database Loader
*
- * @param string the DB credentials
- * @param bool whether to return the DB object
- * @param bool whether to enable active record (this allows us to override the config setting)
- * @return object
+ * @param mixed $params Database configuration options
+ * @param bool $return Whether to return the database object
+ * @param bool $query_builder Whether to enable Query Builder
+ * (overrides the configuration setting)
+ *
+ * @return void|object|bool Database object if $return is set to TRUE,
+ * FALSE on failure, void in any other case
*/
- public function database($params = '', $return = FALSE, $active_record = NULL)
+ public function database($params = '', $return = FALSE, $query_builder = NULL)
{
// Grab the super object
$CI =& get_instance();
// Do we even need to load the database class?
- if (class_exists('CI_DB') && $return == FALSE && $active_record == NULL && isset($CI->db) && is_object($CI->db))
+ if ($return === FALSE && $query_builder === NULL && isset($CI->db) && is_object($CI->db) && ! empty($CI->db->conn_id))
{
return FALSE;
}
@@ -331,7 +336,7 @@ class CI_Loader {
if ($return === TRUE)
{
- return DB($params, $active_record);
+ return DB($params, $query_builder);
}
// Initialize the db variable. Needed to prevent
@@ -339,34 +344,38 @@ class CI_Loader {
$CI->db = '';
// Load the DB class
- $CI->db =& DB($params, $active_record);
+ $CI->db =& DB($params, $query_builder);
}
// --------------------------------------------------------------------
/**
- * Load the Utilities Class
+ * Load the Database Utilities Class
*
- * @return string
+ * @param object $db Database object
+ * @param bool $return Whether to return the DB Forge class object or not
+ * @return void|object
*/
- public function dbutil()
+ public function dbutil($db = NULL, $return = FALSE)
{
- if ( ! class_exists('CI_DB'))
- {
- $this->database();
- }
-
$CI =& get_instance();
- // for backwards compatibility, load dbforge so we can extend dbutils off it
- // this use is deprecated and strongly discouraged
- $CI->load->dbforge();
+ if ( ! is_object($db) OR ! ($db instanceof CI_DB))
+ {
+ class_exists('CI_DB', FALSE) OR $this->database();
+ $db =& $CI->db;
+ }
require_once(BASEPATH.'database/DB_utility.php');
- require_once(BASEPATH.'database/drivers/'.$CI->db->dbdriver.'/'.$CI->db->dbdriver.'_utility.php');
- $class = 'CI_DB_'.$CI->db->dbdriver.'_utility';
+ require_once(BASEPATH.'database/drivers/'.$db->dbdriver.'/'.$db->dbdriver.'_utility.php');
+ $class = 'CI_DB_'.$db->dbdriver.'_utility';
+
+ if ($return === TRUE)
+ {
+ return new $class($db);
+ }
- $CI->dbutil = new $class();
+ $CI->dbutil = new $class($db);
}
// --------------------------------------------------------------------
@@ -374,40 +383,56 @@ class CI_Loader {
/**
* Load the Database Forge Class
*
- * @return string
+ * @param object $db Database object
+ * @param bool $return Whether to return the DB Forge class object or not
+ * @return void|object
*/
- public function dbforge()
+ public function dbforge($db = NULL, $return = FALSE)
{
- if ( ! class_exists('CI_DB'))
+ $CI =& get_instance();
+ if ( ! is_object($db) OR ! ($db instanceof CI_DB))
{
- $this->database();
+ class_exists('CI_DB', FALSE) OR $this->database();
+ $db =& $CI->db;
}
- $CI =& get_instance();
-
require_once(BASEPATH.'database/DB_forge.php');
- require_once(BASEPATH.'database/drivers/'.$CI->db->dbdriver.'/'.$CI->db->dbdriver.'_forge.php');
- $class = 'CI_DB_'.$CI->db->dbdriver.'_forge';
+ require_once(BASEPATH.'database/drivers/'.$db->dbdriver.'/'.$db->dbdriver.'_forge.php');
- $CI->dbforge = new $class();
+ if ( ! empty($db->subdriver))
+ {
+ $driver_path = BASEPATH.'database/drivers/'.$db->dbdriver.'/subdrivers/'.$db->dbdriver.'_'.$db->subdriver.'_forge.php';
+ if (file_exists($driver_path))
+ {
+ require_once($driver_path);
+ $class = 'CI_DB_'.$db->dbdriver.'_'.$db->subdriver.'_forge';
+ }
+ }
+ else
+ {
+ $class = 'CI_DB_'.$db->dbdriver.'_forge';
+ }
+
+ if ($return === TRUE)
+ {
+ return new $class($db);
+ }
+
+ $CI->dbforge = new $class($db);
}
// --------------------------------------------------------------------
/**
- * Load View
- *
- * This function is used to load a "view" file. It has three parameters:
+ * View Loader
*
- * 1. The name of the "view" file to be included.
- * 2. An associative array of data to be extracted for use in the view.
- * 3. TRUE/FALSE - whether to return the data or load it. In
- * some cases it's advantageous to be able to return data so that
- * a developer can process it in some way.
+ * Loads "view" files.
*
- * @param string
- * @param array
- * @param bool
+ * @param string $view View name
+ * @param array $vars An associative array of data
+ * to be extracted for use in the view
+ * @param bool $return Whether to return the view output
+ * or leave it to the Output class
* @return void
*/
public function view($view, $vars = array(), $return = FALSE)
@@ -418,13 +443,11 @@ class CI_Loader {
// --------------------------------------------------------------------
/**
- * Load File
+ * Generic File Loader
*
- * This is a generic file loader
- *
- * @param string
- * @param bool
- * @return string
+ * @param string $path File path
+ * @param bool $return Whether to return the file output
+ * @return void|string
*/
public function file($path, $return = FALSE)
{
@@ -439,13 +462,15 @@ class CI_Loader {
* Once variables are set they become available within
* the controller class and its "view" files.
*
- * @param array
- * @param string
+ * @param array|object|string $vars
+ * An associative array or object containing values
+ * to be set, or a value's name if string
+ * @param string $val Value to set, only used if $vars is a string
* @return void
*/
public function vars($vars = array(), $val = '')
{
- if ($val != '' && is_string($vars))
+ if ($val !== '' && is_string($vars))
{
$vars = array($vars => $val);
}
@@ -468,8 +493,8 @@ class CI_Loader {
*
* Check if a variable is set and retrieve it.
*
- * @param array
- * @return void
+ * @param string $key Variable name
+ * @return mixed The variable or NULL if not found
*/
public function get_var($key)
{
@@ -481,7 +506,7 @@ class CI_Loader {
/**
* Get Variables
*
- * Retrieve all loaded variables
+ * Retrieves all loaded variables.
*
* @return array
*/
@@ -493,11 +518,9 @@ class CI_Loader {
// --------------------------------------------------------------------
/**
- * Load Helper
- *
- * This function loads the specified helper file.
+ * Helper Loader
*
- * @param mixed
+ * @param string|string[] $helpers Helper name(s)
* @return void
*/
public function helper($helpers = array())
@@ -509,27 +532,34 @@ class CI_Loader {
continue;
}
- $ext_helper = APPPATH.'helpers/'.config_item('subclass_prefix').$helper.'.php';
-
// Is this a helper extension request?
- if (file_exists($ext_helper))
+ $ext_helper = config_item('subclass_prefix').$helper;
+ $ext_loaded = FALSE;
+ foreach ($this->_ci_helper_paths as $path)
{
- $base_helper = BASEPATH.'helpers/'.$helper.'.php';
+ if (file_exists($path.'helpers/'.$ext_helper.'.php'))
+ {
+ include_once($path.'helpers/'.$ext_helper.'.php');
+ $ext_loaded = TRUE;
+ }
+ }
+ // If we have loaded extensions - check if the base one is here
+ if ($ext_loaded === TRUE)
+ {
+ $base_helper = BASEPATH.'helpers/'.$helper.'.php';
if ( ! file_exists($base_helper))
{
show_error('Unable to load the requested file: helpers/'.$helper.'.php');
}
- include_once($ext_helper);
include_once($base_helper);
-
$this->_ci_helpers[$helper] = TRUE;
log_message('debug', 'Helper loaded: '.$helper);
continue;
}
- // Try to load the helper
+ // No extensions found ... try loading regular helpers and/or overrides
foreach ($this->_ci_helper_paths as $path)
{
if (file_exists($path.'helpers/'.$helper.'.php'))
@@ -555,10 +585,11 @@ class CI_Loader {
/**
* Load Helpers
*
- * This is simply an alias to the above function in case the
- * user has written the plural form of this function.
+ * An alias for the helper() method in case the developer has
+ * written the plural form of it.
*
- * @param array
+ * @uses CI_Loader::helper()
+ * @param string|string[] $helpers Helper name(s)
* @return void
*/
public function helpers($helpers = array())
@@ -569,22 +600,21 @@ class CI_Loader {
// --------------------------------------------------------------------
/**
- * Loads a language file
+ * Language Loader
*
- * @param array
- * @param string
+ * Loads language files.
+ *
+ * @param string|string[] $files List of language file names to load
+ * @param string Language name
* @return void
*/
- public function language($file = array(), $lang = '')
+ public function language($files = array(), $lang = '')
{
$CI =& get_instance();
- if ( ! is_array($file))
- {
- $file = array($file);
- }
+ is_array($files) OR $files = array($files);
- foreach ($file as $langfile)
+ foreach ($files as $langfile)
{
$CI->lang->load($langfile, $lang);
}
@@ -593,30 +623,35 @@ class CI_Loader {
// --------------------------------------------------------------------
/**
- * Loads a config file
+ * Config Loader
*
- * @param string
- * @param bool
- * @param bool
- * @return void
+ * Loads a config file (an alias for CI_Config::load()).
+ *
+ * @uses CI_Config::load()
+ * @param string $file Configuration file name
+ * @param bool $use_sections Whether configuration values should be loaded into their own section
+ * @param bool $fail_gracefully Whether to just return FALSE or display an error message
+ * @return bool TRUE if the file was loaded correctly or FALSE on failure
*/
public function config($file = '', $use_sections = FALSE, $fail_gracefully = FALSE)
{
$CI =& get_instance();
- $CI->config->load($file, $use_sections, $fail_gracefully);
+ return $CI->config->load($file, $use_sections, $fail_gracefully);
}
// --------------------------------------------------------------------
/**
- * Driver
+ * Driver Loader
*
- * Loads a driver library
+ * Loads a driver library.
*
- * @param mixed the name of the class or array of classes
- * @param mixed the optional parameters
- * @param string an optional object name
- * @return void
+ * @param string|string[] $library Driver name(s)
+ * @param array $params Optional parameters to pass to the driver
+ * @param string $object_name An optional object name to assign to
+ *
+ * @return void|object|bool Object or FALSE on failure if $library is a string
+ * and $object_name is set. void otherwise.
*/
public function driver($library = '', $params = NULL, $object_name = NULL)
{
@@ -626,18 +661,18 @@ class CI_Loader {
{
$this->driver($driver);
}
- return FALSE;
+ return;
}
- if ( ! class_exists('CI_Driver_Library'))
+ if ($library === '')
{
- // we aren't instantiating an object here, that'll be done by the Library itself
- require BASEPATH.'libraries/Driver.php';
+ return FALSE;
}
- if ($library == '')
+ if ( ! class_exists('CI_Driver_Library'))
{
- return FALSE;
+ // 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,
@@ -655,13 +690,19 @@ class CI_Loader {
/**
* Add Package Path
*
- * Prepends a parent path to the library, model, helper, and config path arrays
+ * Prepends a parent path to the library, model, helper and config
+ * path arrays.
*
- * @param string
- * @param bool
+ * @see CI_Loader::$_ci_library_paths
+ * @see CI_Loader::$_ci_model_paths
+ * @see CI_Loader::$_ci_helper_paths
+ * @see CI_Config::$_config_paths
+ *
+ * @param string $path Path to add
+ * @param bool $view_cascade (default: TRUE)
* @return void
*/
- public function add_package_path($path, $view_cascade=TRUE)
+ public function add_package_path($path, $view_cascade = TRUE)
{
$path = rtrim($path, '/').'/';
@@ -673,7 +714,7 @@ class CI_Loader {
// Add config file path
$config =& $this->_ci_get_component('config');
- array_unshift($config->_config_paths, $path);
+ array_push($config->_config_paths, $path);
}
// --------------------------------------------------------------------
@@ -681,14 +722,14 @@ class CI_Loader {
/**
* Get Package Paths
*
- * Return a list of all package paths, by default it will ignore BASEPATH.
+ * Return a list of all package paths.
*
- * @param string
- * @return void
+ * @param bool $include_base Whether to include BASEPATH (default: TRUE)
+ * @return array
*/
public function get_package_paths($include_base = FALSE)
{
- return $include_base === TRUE ? $this->_ci_library_paths : $this->_ci_model_paths;
+ return ($include_base === TRUE) ? $this->_ci_library_paths : $this->_ci_model_paths;
}
// --------------------------------------------------------------------
@@ -696,24 +737,24 @@ class CI_Loader {
/**
* Remove Package Path
*
- * Remove a path from the library, model, and helper path arrays if it exists
- * If no path is provided, the most recently added path is removed.
+ * Remove a path from the library, model, helper and/or config
+ * path arrays if it exists. If no path is provided, the most recently
+ * added path will be removed removed.
*
- * @param string
- * @param bool
+ * @param string $path Path to remove
* @return void
*/
- public function remove_package_path($path = '', $remove_config_path = TRUE)
+ public function remove_package_path($path = '')
{
$config =& $this->_ci_get_component('config');
- if ($path == '')
+ if ($path === '')
{
array_shift($this->_ci_library_paths);
array_shift($this->_ci_model_paths);
array_shift($this->_ci_helper_paths);
array_shift($this->_ci_view_paths);
- array_shift($config->_config_paths);
+ array_pop($config->_config_paths);
}
else
{
@@ -748,13 +789,16 @@ class CI_Loader {
// --------------------------------------------------------------------
/**
- * Loader
+ * Internal CI Data Loader
+ *
+ * Used to load views and files.
*
- * This function is used to load views and files.
* Variables are prefixed with _ci_ to avoid symbol collision with
- * variables made available to view files
+ * variables made available to view files.
*
- * @param array
+ * @used-by CI_Loader::view()
+ * @used-by CI_Loader::file()
+ * @param array $_ci_data Data to load
* @return void
*/
protected function _ci_load($_ci_data)
@@ -768,7 +812,7 @@ class CI_Loader {
$file_exists = FALSE;
// Set the path to the requested file
- if ($_ci_path != '')
+ if (is_string($_ci_path) && $_ci_path !== '')
{
$_ci_x = explode('/', $_ci_path);
$_ci_file = end($_ci_x);
@@ -776,13 +820,13 @@ class CI_Loader {
else
{
$_ci_ext = pathinfo($_ci_view, PATHINFO_EXTENSION);
- $_ci_file = ($_ci_ext == '') ? $_ci_view.'.php' : $_ci_view;
+ $_ci_file = ($_ci_ext === '') ? $_ci_view.'.php' : $_ci_view;
- foreach ($this->_ci_view_paths as $view_file => $cascade)
+ foreach ($this->_ci_view_paths as $_ci_view_file => $cascade)
{
- if (file_exists($view_file.$_ci_file))
+ if (file_exists($_ci_view_file.$_ci_file))
{
- $_ci_path = $view_file.$_ci_file;
+ $_ci_path = $_ci_view_file.$_ci_file;
$file_exists = TRUE;
break;
}
@@ -813,7 +857,7 @@ class CI_Loader {
/*
* Extract and cache variables
*
- * You can either set variables using the dedicated $this->load_vars()
+ * You can either set variables using the dedicated $this->load->vars()
* function or via the second parameter of this function. We'll merge
* the two types and cache them so that views that are embedded within
* other views can have access to these variables.
@@ -830,17 +874,19 @@ class CI_Loader {
* We buffer the output for two reasons:
* 1. Speed. You get a significant speed boost.
* 2. So that the final rendered template can be post-processed by
- * the output class. Why do we need post processing? For one thing,
- * in order to show the elapsed page load time. Unless we can
- * intercept the content right before it's sent to the browser and
- * then stop the timer it won't be accurate.
+ * the output class. Why do we need post processing? For one thing,
+ * in order to show the elapsed page load time. Unless we can
+ * intercept the content right before it's sent to the browser and
+ * then stop the timer it won't be accurate.
*/
ob_start();
// If the PHP installation does not support short tags we'll
// do a little string replacement, changing the short tags
// to standard PHP echo statements.
- if ( ! is_php('5.4') && (bool) @ini_get('short_open_tag') === FALSE && config_item('rewrite_short_tags') == TRUE)
+ if ( ! is_php('5.4') && (bool) @ini_get('short_open_tag') === FALSE
+ && config_item('rewrite_short_tags') === TRUE && function_usable('eval')
+ )
{
echo eval('?>'.preg_replace('/;*\s*\?>/', '; ?>', str_replace('<?=', '<?php echo ', file_get_contents($_ci_path))));
}
@@ -882,13 +928,14 @@ class CI_Loader {
// --------------------------------------------------------------------
/**
- * Load class
+ * Internal CI Class Loader
*
- * This function loads the requested class.
+ * @used-by CI_Loader::library()
+ * @uses CI_Loader::_ci_init_class()
*
- * @param string the item that is being loaded
- * @param mixed any additional parameters
- * @param string an optional object name
+ * @param string $class Class name to load
+ * @param mixed $params Optional parameters to pass to the class constructor
+ * @param string $object_name Optional object name to assign to
* @return void
*/
protected function _ci_load_class($class, $params = NULL, $object_name = NULL)
@@ -989,19 +1036,24 @@ class CI_Loader {
$this->_ci_loaded_files[] = $filepath;
return $this->_ci_init_class($class, '', $params, $object_name);
}
-
} // END FOREACH
// One last attempt. Maybe the library is in a subdirectory, but it wasn't specified?
- if ($subdir == '')
+ if ($subdir === '')
{
$path = strtolower($class).'/'.$class;
- return $this->_ci_load_class($path, $params);
+ return $this->_ci_load_class($path, $params, $object_name);
+ }
+ elseif (ucfirst($subdir) != $subdir)
+ {
+ // Lowercase subdir failed - retry capitalized
+ $path = ucfirst($subdir).$class;
+ return $this->_ci_load_class($path, $params, $object_name);
}
// If we got this far we were unable to find the requested class.
// We do not issue errors if the load call failed due to a duplicate request
- if ($is_duplicate == FALSE)
+ if ($is_duplicate === FALSE)
{
log_message('error', 'Unable to load the requested class: '.$class);
show_error('Unable to load the requested class: '.$class);
@@ -1011,12 +1063,17 @@ class CI_Loader {
// --------------------------------------------------------------------
/**
- * Instantiates a class
+ * Internal CI Class Instantiator
+ *
+ * @used-by CI_Loader::_ci_load_class()
*
- * @param string
- * @param string
- * @param bool
- * @param string an optional object name
+ * @param string $class Class name
+ * @param string $prefix Class name prefix
+ * @param array|null|bool $config Optional configuration to pass to the class constructor:
+ * FALSE to skip;
+ * NULL to search in config paths;
+ * array containing configuration data
+ * @param string $object_name Optional object name to assign to
* @return void
*/
protected function _ci_init_class($class, $prefix = '', $config = FALSE, $object_name = NULL)
@@ -1060,7 +1117,7 @@ class CI_Loader {
}
}
- if ($prefix == '')
+ if ($prefix === '')
{
if (class_exists('CI_'.$class))
{
@@ -1084,7 +1141,7 @@ class CI_Loader {
if ( ! class_exists($name))
{
log_message('error', 'Non-existent class: '.$name);
- show_error('Non-existent class: '.$class);
+ show_error('Non-existent class: '.$name);
}
// Set the variable name we will assign the class to
@@ -1118,12 +1175,11 @@ class CI_Loader {
// --------------------------------------------------------------------
/**
- * Autoloader
+ * CI Autoloader
*
- * The config/autoload.php file contains an array that permits sub-systems,
- * libraries, and helpers to be loaded automatically.
+ * Loads component listed in the config/autoload.php file.
*
- * @param array
+ * @used-by CI_Loader::initialize()
* @return void
*/
protected function _ci_autoloader()
@@ -1187,6 +1243,15 @@ class CI_Loader {
}
}
+ // Autoload drivers
+ if (isset($autoload['drivers']))
+ {
+ foreach ($autoload['drivers'] as $item)
+ {
+ $this->driver($item);
+ }
+ }
+
// Autoload models
if (isset($autoload['model']))
{
@@ -1197,11 +1262,12 @@ class CI_Loader {
// --------------------------------------------------------------------
/**
- * Object to Array
+ * CI Object to Array translator
*
- * Takes an object as input and converts the class variables to array key/vals
+ * Takes an object as input and converts the class variables to
+ * an associative array with key/value pairs.
*
- * @param object
+ * @param object $object Object data to translate
* @return array
*/
protected function _ci_object_to_array($object)
@@ -1212,9 +1278,11 @@ class CI_Loader {
// --------------------------------------------------------------------
/**
- * Get a reference to a specific library or model
+ * CI Component getter
+ *
+ * Get a reference to a specific library or model.
*
- * @param string
+ * @param string $component Component name
* @return bool
*/
protected function &_ci_get_component($component)
@@ -1228,10 +1296,11 @@ class CI_Loader {
/**
* Prep filename
*
- * This function preps the name of various items to make loading them more reliable.
+ * This function prepares filenames of various items to
+ * make their loading more reliable.
*
- * @param mixed
- * @param string
+ * @param string|string[] $filename Filename(s)
+ * @param string $extension Filename extension
* @return array
*/
protected function _ci_prep_filename($filename, $extension)
diff --git a/system/libraries/Log.php b/system/core/Log.php
index 66f9ebff9..718f50587 100644
--- a/system/libraries/Log.php
+++ b/system/core/Log.php
@@ -1,4 +1,4 @@
-<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');
+<?php
/**
* CodeIgniter
*
@@ -24,6 +24,7 @@
* @since Version 1.0
* @filesource
*/
+defined('BASEPATH') OR exit('No direct script access allowed');
/**
* Logging Class
@@ -36,19 +37,65 @@
*/
class CI_Log {
+ /**
+ * Path to save log files
+ *
+ * @var string
+ */
protected $_log_path;
+
+ /**
+ * Level of logging
+ *
+ * @var int
+ */
protected $_threshold = 1;
+
+ /**
+ * Highest level of logging
+ *
+ * @var int
+ */
protected $_threshold_max = 0;
+
+ /**
+ * Array of threshold levels to log
+ *
+ * @var array
+ */
protected $_threshold_array = array();
+
+ /**
+ * Format of timestamp for log files
+ *
+ * @var string
+ */
protected $_date_fmt = 'Y-m-d H:i:s';
+
+ /**
+ * Whether or not the logger can write to the log files
+ *
+ * @var bool
+ */
protected $_enabled = TRUE;
- protected $_levels = array('ERROR' => 1, 'DEBUG' => 2, 'INFO' => 3, 'ALL' => 4);
+ /**
+ * Predefined logging levels
+ *
+ * @var array
+ */
+ protected $_levels = array('ERROR' => 1, 'DEBUG' => 2, 'INFO' => 3, 'ALL' => 4);
+
+ /**
+ * Initialize Logging class
+ *
+ * @return void
+ */
public function __construct()
{
$config =& get_config();
- $this->_log_path = ($config['log_path'] != '') ? $config['log_path'] : APPPATH.'logs/';
+ $this->_log_path = ($config['log_path'] !== '') ? $config['log_path'] : APPPATH.'logs/';
if ( ! is_dir($this->_log_path) OR ! is_really_writable($this->_log_path))
{
@@ -65,7 +112,7 @@ class CI_Log {
$this->_threshold_array = array_flip($config['log_threshold']);
}
- if ($config['log_date_format'] != '')
+ if ($config['log_date_format'] !== '')
{
$this->_date_fmt = $config['log_date_format'];
}
@@ -98,14 +145,13 @@ class CI_Log {
return FALSE;
}
-
$filepath = $this->_log_path.'log-'.date('Y-m-d').'.php';
$message = '';
if ( ! file_exists($filepath))
{
$newfile = TRUE;
- $message .= "<"."?php if ( ! defined('BASEPATH')) exit('No direct script access allowed'); ?".">\n\n";
+ $message .= '<'."?php defined('BASEPATH') OR exit('No direct script access allowed'); ?".">\n\n";
}
if ( ! $fp = @fopen($filepath, FOPEN_WRITE_CREATE))
@@ -113,7 +159,7 @@ class CI_Log {
return FALSE;
}
- $message .= $level.' '.(($level == 'INFO') ? ' -' : '-').' '.date($this->_date_fmt). ' --> '.$msg."\n";
+ $message .= $level.' '.($level === 'INFO' ? ' -' : '-').' '.date($this->_date_fmt).' --> '.$msg."\n";
flock($fp, LOCK_EX);
fwrite($fp, $message);
diff --git a/system/core/Model.php b/system/core/Model.php
index 49b8d34e4..28fdfbb69 100755..100644
--- a/system/core/Model.php
+++ b/system/core/Model.php
@@ -1,4 +1,4 @@
-<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');
+<?php
/**
* CodeIgniter
*
@@ -24,11 +24,10 @@
* @since Version 1.0
* @filesource
*/
-
-// ------------------------------------------------------------------------
+defined('BASEPATH') OR exit('No direct script access allowed');
/**
- * CodeIgniter Model Class
+ * Model Class
*
* @package CodeIgniter
* @subpackage Libraries
@@ -38,25 +37,33 @@
*/
class CI_Model {
+ /**
+ * Class constructor
+ *
+ * @return void
+ */
public function __construct()
{
log_message('debug', 'Model Class Initialized');
}
+ // --------------------------------------------------------------------
+
/**
- * __get
+ * __get magic
*
* Allows models to access CI's loaded classes using the same
* syntax as controllers.
*
- * @param string
+ * @param string $key
*/
public function __get($key)
{
$CI =& get_instance();
return $CI->$key;
}
+
}
/* End of file Model.php */
-/* Location: ./system/core/Model.php */
+/* Location: ./system/core/Model.php */ \ No newline at end of file
diff --git a/system/core/Output.php b/system/core/Output.php
index 3cb40626a..98deff55c 100755..100644
--- a/system/core/Output.php
+++ b/system/core/Output.php
@@ -1,4 +1,4 @@
-<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');
+<?php
/**
* CodeIgniter
*
@@ -24,11 +24,12 @@
* @since Version 1.0
* @filesource
*/
+defined('BASEPATH') OR exit('No direct script access allowed');
/**
* Output Class
*
- * Responsible for sending final output to browser
+ * Responsible for sending final output to the browser.
*
* @package CodeIgniter
* @subpackage Libraries
@@ -39,70 +40,84 @@
class CI_Output {
/**
- * Current output string
+ * Final output string
*
- * @var string
+ * @var string
*/
public $final_output;
+
/**
* Cache expiration time
*
- * @var int
+ * @var int
*/
- public $cache_expiration = 0;
+ public $cache_expiration = 0;
+
/**
* List of server headers
*
- * @var array
+ * @var array
*/
- public $headers = array();
+ public $headers = array();
+
/**
* List of mime types
*
- * @var array
+ * @var array
*/
- public $mime_types = array();
+ public $mimes = array();
+
/**
- * Determines wether profiler is enabled
+ * Mime-type for the current page
*
- * @var book
+ * @var string
*/
- public $enable_profiler = FALSE;
+ protected $mime_type = 'text/html';
+
/**
- * Determines if output compression is enabled
+ * Enable Profiler flag
*
- * @var bool
+ * @var bool
*/
- protected $_zlib_oc = FALSE;
+ public $enable_profiler = FALSE;
+
+ /**
+ * zLib output compression flag
+ *
+ * @var bool
+ */
+ protected $_zlib_oc = FALSE;
+
/**
* List of profiler sections
*
- * @var array
+ * @var array
*/
- protected $_profiler_sections = array();
+ protected $_profiler_sections = array();
+
/**
- * Whether or not to parse variables like {elapsed_time} and {memory_usage}
+ * Parse markers flag
*
- * @var bool
+ * Whether or not to parse variables like {elapsed_time} and {memory_usage}.
+ *
+ * @var bool
*/
- public $parse_exec_vars = TRUE;
+ public $parse_exec_vars = TRUE;
+ /**
+ * Class constructor
+ *
+ * Determines whether zLib output compression will be used.
+ *
+ * @return void
+ */
public function __construct()
{
- $this->_zlib_oc = @ini_get('zlib.output_compression');
+ $this->_zlib_oc = (bool) @ini_get('zlib.output_compression');
// Get mime types for later
- if (defined('ENVIRONMENT') && file_exists(APPPATH.'config/'.ENVIRONMENT.'/mimes.php'))
- {
- include APPPATH.'config/'.ENVIRONMENT.'/mimes.php';
- }
- else
- {
- include APPPATH.'config/mimes.php';
- }
-
+ $this->mimes =& get_mimes();
- $this->mime_types = $mimes;
log_message('debug', 'Output Class Initialized');
}
@@ -111,7 +126,7 @@ class CI_Output {
/**
* Get Output
*
- * Returns the current output string
+ * Returns the current output string.
*
* @return string
*/
@@ -125,10 +140,10 @@ class CI_Output {
/**
* Set Output
*
- * Sets the output string
+ * Sets the output string.
*
- * @param string
- * @return void
+ * @param string $output Output data
+ * @return object $this
*/
public function set_output($output)
{
@@ -141,14 +156,14 @@ class CI_Output {
/**
* Append Output
*
- * Appends data onto the output string
+ * Appends data onto the output string.
*
- * @param string
- * @return void
+ * @param string $output Data to append
+ * @return object $this
*/
public function append_output($output)
{
- if ($this->final_output == '')
+ if (empty($this->final_output))
{
$this->final_output = $output;
}
@@ -165,14 +180,14 @@ class CI_Output {
/**
* Set Header
*
- * Lets you set a server header which will be outputted with the final display.
+ * Lets you set a server header which will be sent with the final output.
*
- * Note: If a file is cached, headers will not be sent. We need to figure out
- * how to permit header data to be saved with the cache data...
+ * Note: If a file is cached, headers will not be sent.
+ * @todo We need to figure out how to permit headers to be cached.
*
- * @param string
- * @param bool
- * @return void
+ * @param string $header Header
+ * @param bool $replace Whether to replace the old header value, if already set
+ * @return object $this
*/
public function set_header($header, $replace = TRUE)
{
@@ -180,9 +195,9 @@ class CI_Output {
// but it will not modify the content-length header to compensate for
// the reduction, causing the browser to hang waiting for more data.
// We'll just skip content-length in those cases.
- if ($this->_zlib_oc && strncasecmp($header, 'content-length', 14) == 0)
+ if ($this->_zlib_oc && strncasecmp($header, 'content-length', 14) === 0)
{
- return;
+ return $this;
}
$this->headers[] = array($header, $replace);
@@ -192,21 +207,22 @@ class CI_Output {
// --------------------------------------------------------------------
/**
- * Set Content Type Header
+ * Set Content-Type Header
*
- * @param string extension of the file we're outputting
- * @return void
+ * @param string $mime_type Extension of the file we're outputting
+ * @param string $charset Character set (default: NULL)
+ * @return object $this
*/
- public function set_content_type($mime_type)
+ public function set_content_type($mime_type, $charset = NULL)
{
if (strpos($mime_type, '/') === FALSE)
{
$extension = ltrim($mime_type, '.');
// Is this extension supported?
- if (isset($this->mime_types[$extension]))
+ if (isset($this->mimes[$extension]))
{
- $mime_type =& $this->mime_types[$extension];
+ $mime_type =& $this->mimes[$extension];
if (is_array($mime_type))
{
@@ -215,7 +231,15 @@ class CI_Output {
}
}
- $header = 'Content-Type: '.$mime_type;
+ $this->mime_type = $mime_type;
+
+ if (empty($charset))
+ {
+ $charset = config_item('charset');
+ }
+
+ $header = 'Content-Type: '.$mime_type
+ .(empty($charset) ? NULL : '; charset='.strtolower($charset));
$this->headers[] = array($header, TRUE);
return $this;
@@ -224,7 +248,7 @@ class CI_Output {
// --------------------------------------------------------------------
/**
- * Get Current Content Type Header
+ * Get Current Content-Type Header
*
* @return string 'text/html', if not already set
*/
@@ -232,9 +256,9 @@ class CI_Output {
{
for ($i = 0, $c = count($this->headers); $i < $c; $i++)
{
- if (preg_match('/^Content-Type:\s(.+)$/', $this->headers[$i][0], $matches))
+ if (sscanf($this->headers[$i][0], 'Content-Type: %[^;]', $content_type) === 1)
{
- return $matches[1];
+ return $content_type;
}
}
@@ -244,12 +268,47 @@ class CI_Output {
// --------------------------------------------------------------------
/**
+ * Get Header
+ *
+ * @param string $header_name
+ * @return string
+ */
+ public function get_header($header)
+ {
+ // Combine headers already sent with our batched headers
+ $headers = array_merge(
+ // We only need [x][0] from our multi-dimensional array
+ array_map('array_shift', $this->headers),
+ headers_list()
+ );
+
+ if (empty($headers) OR empty($header))
+ {
+ return NULL;
+ }
+
+ for ($i = 0, $c = count($headers); $i < $c; $i++)
+ {
+ if (strncasecmp($header, $headers[$i], $l = strlen($header)) === 0)
+ {
+ return trim(substr($headers[$i], $l+1));
+ }
+ }
+
+ return NULL;
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
* Set HTTP Status Header
- * moved to Common procedural functions in 1.7.2
*
- * @param int the status code
- * @param string
- * @return void
+ * As of version 1.7.2, this is an alias for common function
+ * set_status_header().
+ *
+ * @param int $code Status code (default: 200)
+ * @param string $text Optional message
+ * @return object $this
*/
public function set_status_header($code = 200, $text = '')
{
@@ -262,8 +321,8 @@ class CI_Output {
/**
* Enable/disable Profiler
*
- * @param bool
- * @return void
+ * @param bool $val TRUE to enable or FALSE to disable
+ * @return object $this
*/
public function enable_profiler($val = TRUE)
{
@@ -276,13 +335,20 @@ class CI_Output {
/**
* Set Profiler Sections
*
- * Allows override of default / config settings for Profiler section display
+ * Allows override of default/config settings for
+ * Profiler section display.
*
- * @param array
- * @return void
+ * @param array $sections Profiler sections
+ * @return object $this
*/
public function set_profiler_sections($sections)
{
+ if (isset($sections['query_toggle_count']))
+ {
+ $this->_profiler_sections['query_toggle_count'] = (int) $sections['query_toggle_count'];
+ unset($sections['query_toggle_count']);
+ }
+
foreach ($sections as $section => $enable)
{
$this->_profiler_sections[$section] = ($enable !== FALSE);
@@ -296,8 +362,8 @@ class CI_Output {
/**
* Set Cache
*
- * @param int
- * @return void
+ * @param int $time Cache expiration time in seconds
+ * @return object $this
*/
public function cache($time)
{
@@ -310,16 +376,16 @@ class CI_Output {
/**
* Display Output
*
- * All "view" data is automatically put into this variable by the controller class:
- *
- * $this->final_output
+ * Processes sends the sends finalized output data to the browser along
+ * with any server headers and profile data. It also stops benchmark
+ * timers so the page rendering speed and memory usage can be shown.
*
- * This function sends the finalized output data to the browser along
- * with any server headers and profile data. It also stops the
- * benchmark timer so the page rendering speed and memory usage can be shown.
+ * Note: All "view" data is automatically put into $this->final_output
+ * by controller class.
*
- * @param string
- * @return mixed
+ * @uses CI_Output::$final_output
+ * @param string $output Output data override
+ * @return void
*/
public function _display($output = '')
{
@@ -337,14 +403,22 @@ class CI_Output {
// --------------------------------------------------------------------
// Set the output data
- if ($output == '')
+ if ($output === '')
{
$output =& $this->final_output;
}
// --------------------------------------------------------------------
- // Do we need to write a cache file? Only if the controller does not have its
+ // Is minify requested?
+ if ($CFG->item('minify_output') === TRUE)
+ {
+ $output = $this->minify($output, $this->mime_type);
+ }
+
+ // --------------------------------------------------------------------
+
+ // Do we need to write a cache file? Only if the controller does not have its
// own _output() method and we are not dealing with a cache file, which we
// can determine by the existence of the $CI object above
if ($this->cache_expiration > 0 && isset($CI) && ! method_exists($CI, '_output'))
@@ -361,7 +435,7 @@ class CI_Output {
if ($this->parse_exec_vars === TRUE)
{
- $memory = function_exists('memory_get_usage') ? round(memory_get_usage()/1024/1024, 2).'MB' : '0';
+ $memory = round(memory_get_usage() / 1024 / 1024, 2).'MB';
$output = str_replace(array('{elapsed_time}', '{memory_usage}'), array($elapsed, $memory), $output);
}
@@ -369,7 +443,7 @@ class CI_Output {
// --------------------------------------------------------------------
// Is compression requested?
- if ($CFG->item('compress_output') === TRUE && $this->_zlib_oc == FALSE
+ if ($CFG->item('compress_output') === TRUE && $this->_zlib_oc === FALSE
&& extension_loaded('zlib')
&& isset($_SERVER['HTTP_ACCEPT_ENCODING']) && strpos($_SERVER['HTTP_ACCEPT_ENCODING'], 'gzip') !== FALSE)
{
@@ -397,14 +471,14 @@ class CI_Output {
echo $output;
log_message('debug', 'Final output sent to browser');
log_message('debug', 'Total execution time: '.$elapsed);
- return TRUE;
+ return;
}
// --------------------------------------------------------------------
// Do we need to generate profile data?
// If so, load the Profile class and run it.
- if ($this->enable_profiler == TRUE)
+ if ($this->enable_profiler === TRUE)
{
$CI->load->library('profiler');
if ( ! empty($this->_profiler_sections))
@@ -439,16 +513,16 @@ class CI_Output {
// --------------------------------------------------------------------
/**
- * Write a Cache File
+ * Write Cache
*
- * @param string
+ * @param string $output Output data to cache
* @return void
*/
public function _write_cache($output)
{
$CI =& get_instance();
$path = $CI->config->item('cache_path');
- $cache_path = ($path == '') ? APPPATH.'cache/' : $path;
+ $cache_path = ($path === '') ? APPPATH.'cache/' : $path;
if ( ! is_dir($cache_path) OR ! is_really_writable($cache_path))
{
@@ -484,20 +558,26 @@ class CI_Output {
@chmod($cache_path, FILE_WRITE_MODE);
log_message('debug', 'Cache file written: '.$cache_path);
+
+ // Send HTTP cache-control headers to browser to match file cache settings.
+ $this->set_cache_header($_SERVER['REQUEST_TIME'], $expire);
}
// --------------------------------------------------------------------
/**
- * Update/serve a cached file
+ * Update/serve cached output
*
- * @param object config class
- * @param object uri class
- * @return void
+ * @uses CI_Config
+ * @uses CI_URI
+ *
+ * @param object &$CFG CI_Config class instance
+ * @param object &$URI CI_URI class instance
+ * @return bool TRUE on success or FALSE on failure
*/
public function _display_cache(&$CFG, &$URI)
{
- $cache_path = ($CFG->item('cache_path') == '') ? APPPATH.'cache/' : $CFG->item('cache_path');
+ $cache_path = ($CFG->item('cache_path') === '') ? APPPATH.'cache/' : $CFG->item('cache_path');
// Build the file path. The file name is an MD5 hash of the full URI
$uri = $CFG->item('base_url').$CFG->item('index_page').$URI->uri_string;
@@ -516,25 +596,211 @@ class CI_Output {
fclose($fp);
// Strip out the embedded timestamp
- if ( ! preg_match('/(\d+TS--->)/', $cache, $match))
+ if ( ! preg_match('/^(\d+)TS--->/', $cache, $match))
{
return FALSE;
}
- // Has the file expired? If so we'll delete it.
- if (time() >= trim(str_replace('TS--->', '', $match[1])) && is_really_writable($cache_path))
+ $last_modified = filemtime($cache_path);
+ $expire = $match[1];
+
+ // Has the file expired?
+ if ($_SERVER['REQUEST_TIME'] >= $expire && is_really_writable($cache_path))
{
+ // If so we'll delete it.
@unlink($filepath);
log_message('debug', 'Cache file has expired. File deleted.');
return FALSE;
}
+ else
+ {
+ // Or else send the HTTP cache control headers.
+ $this->set_cache_header($last_modified, $expire);
+ }
// Display the cache
- $this->_display(str_replace($match[0], '', $cache));
+ $this->_display(substr($cache, strlen($match[0])));
log_message('debug', 'Cache file is current. Sending it to browser.');
return TRUE;
}
+ // --------------------------------------------------------------------
+
+ /**
+ * Delete cache
+ *
+ * @param string $uri URI string
+ * @return bool
+ */
+ public function delete_cache($uri = '')
+ {
+ $CI =& get_instance();
+ $cache_path = $CI->config->item('cache_path');
+ if ($cache_path === '')
+ {
+ $cache_path = APPPATH.'cache/';
+ }
+
+ if ( ! is_dir($cache_path))
+ {
+ log_message('error', 'Unable to find cache path: '.$cache_path);
+ return FALSE;
+ }
+
+ if (empty($uri))
+ {
+ $uri = $CI->uri->uri_string();
+ }
+
+ $cache_path .= md5($CI->config->item('base_url').$CI->config->item('index_page').$uri);
+
+ if ( ! @unlink($cache_path))
+ {
+ log_message('error', 'Unable to delete cache file for '.$uri);
+ return FALSE;
+ }
+
+ return TRUE;
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Set Cache Header
+ *
+ * Set the HTTP headers to match the server-side file cache settings
+ * in order to reduce bandwidth.
+ *
+ * @param int $last_modified Timestamp of when the page was last modified
+ * @param int $expiration Timestamp of when should the requested page expire from cache
+ * @return void
+ */
+ public function set_cache_header($last_modified, $expiration)
+ {
+ $max_age = $expiration - $_SERVER['REQUEST_TIME'];
+
+ if (isset($_SERVER['HTTP_IF_MODIFIED_SINCE']) && $last_modified <= strtotime($_SERVER['HTTP_IF_MODIFIED_SINCE']))
+ {
+ $this->set_status_header(304);
+ exit;
+ }
+ else
+ {
+ header('Pragma: public');
+ header('Cache-Control: max-age=' . $max_age . ', public');
+ header('Expires: '.gmdate('D, d M Y H:i:s', $expiration).' GMT');
+ header('Last-modified: '.gmdate('D, d M Y H:i:s', $last_modified).' GMT');
+ }
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Minify
+ *
+ * Reduce excessive size of HTML/CSS/JavaScript content.
+ *
+ * @param string $output Output to minify
+ * @param string $type Output content MIME type
+ * @return string Minified output
+ */
+ public function minify($output, $type = 'text/html')
+ {
+ switch ($type)
+ {
+ case 'text/html':
+
+ $size_before = strlen($output);
+
+ if ($size_before === 0)
+ {
+ return '';
+ }
+
+ // Find all the <pre>,<code>,<textarea>, and <javascript> tags
+ // We'll want to return them to this unprocessed state later.
+ preg_match_all('{<pre.+</pre>}msU', $output, $pres_clean);
+ preg_match_all('{<code.+</code>}msU', $output, $codes_clean);
+ preg_match_all('{<textarea.+</textarea>}msU', $output, $textareas_clean);
+ preg_match_all('{<script.+</script>}msU', $output, $javascript_clean);
+
+ // Minify the CSS in all the <style> tags.
+ preg_match_all('{<style.+</style>}msU', $output, $style_clean);
+ foreach ($style_clean[0] as $s)
+ {
+ $output = str_replace($s, $this->minify($s, 'text/css'), $output);
+ }
+
+ // Minify the javascript in <script> tags.
+ foreach ($javascript_clean[0] as $s)
+ {
+ $javascript_mini[] = $this->minify($s, 'text/javascript');
+ }
+
+ // Replace multiple spaces with a single space.
+ $output = preg_replace('!\s{2,}!', ' ', $output);
+
+ // Remove comments (non-MSIE conditionals)
+ $output = preg_replace('{\s*<!--[^\[].*-->\s*}msU', '', $output);
+
+ // Remove spaces around block-level elements.
+ $output = preg_replace('/\s*(<\/?(html|head|title|meta|script|link|style|body|h[1-6]|div|p|br)[^>]*>)\s*/is', '$1', $output);
+
+ // Replace mangled <pre> etc. tags with unprocessed ones.
+
+ if ( ! empty($pres_clean))
+ {
+ preg_match_all('{<pre.+</pre>}msU', $output, $pres_messed);
+ $output = str_replace($pres_messed[0], $pres_clean[0], $output);
+ }
+
+ if ( ! empty($codes_clean))
+ {
+ preg_match_all('{<code.+</code>}msU', $output, $codes_messed);
+ $output = str_replace($codes_messed[0], $codes_clean[0], $output);
+ }
+
+ if ( ! empty($codes_clean))
+ {
+ preg_match_all('{<textarea.+</textarea>}msU', $output, $textareas_messed);
+ $output = str_replace($textareas_messed[0], $textareas_clean[0], $output);
+ }
+
+ if (isset($javascript_mini))
+ {
+ preg_match_all('{<script.+</script>}msU', $output, $javascript_messed);
+ $output = str_replace($javascript_messed[0], $javascript_mini, $output);
+ }
+
+ $size_removed = $size_before - strlen($output);
+ $savings_percent = round(($size_removed / $size_before * 100));
+
+ log_message('debug', 'Minifier shaved '.($size_removed / 1000).'KB ('.$savings_percent.'%) off final HTML output.');
+
+ break;
+
+ case 'text/css':
+
+ //Remove CSS comments
+ $output = preg_replace('!/\*[^*]*\*+([^/][^*]*\*+)*/!', '', $output);
+
+ // Remove spaces around curly brackets, colons,
+ // semi-colons, parenthesis, commas
+ $output = preg_replace('!\s*(:|;|,|}|{|\(|\))\s*!', '$1', $output);
+
+ break;
+
+ case 'text/javascript':
+
+ // Currently leaves JavaScript untouched.
+ break;
+
+ default: break;
+ }
+
+ return $output;
+ }
+
}
/* End of file Output.php */
diff --git a/system/core/Router.php b/system/core/Router.php
index 5477fed5d..76772a0fb 100755..100644
--- a/system/core/Router.php
+++ b/system/core/Router.php
@@ -1,4 +1,4 @@
-<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');
+<?php
/**
* CodeIgniter
*
@@ -24,6 +24,7 @@
* @since Version 1.0
* @filesource
*/
+defined('BASEPATH') OR exit('No direct script access allowed');
/**
* Router Class
@@ -32,59 +33,60 @@
*
* @package CodeIgniter
* @subpackage Libraries
- * @author EllisLab Dev Team
* @category Libraries
+ * @author EllisLab Dev Team
* @link http://codeigniter.com/user_guide/general/routing.html
*/
class CI_Router {
/**
- * Config class
+ * CI_Config class object
*
- * @var object
+ * @var object
*/
public $config;
+
/**
* List of routes
*
- * @var array
+ * @var array
*/
- public $routes = array();
- /**
- * List of error routes
- *
- * @var array
- */
- public $error_routes = array();
+ public $routes = array();
+
/**
* Current class name
*
- * @var string
+ * @var string
*/
- public $class = '';
+ public $class = '';
+
/**
* Current method name
*
- * @var string
+ * @var string
*/
- public $method = 'index';
+ public $method = 'index';
+
/**
* Sub-directory that contains the requested controller class
*
- * @var string
+ * @var string
*/
- public $directory = '';
+ public $directory = '';
+
/**
* Default controller (and method if specific)
*
- * @var string
+ * @var string
*/
public $default_controller;
/**
- * Constructor
+ * Class constructor
*
* Runs the route mapping function.
+ *
+ * @return void
*/
public function __construct()
{
@@ -96,9 +98,9 @@ class CI_Router {
// --------------------------------------------------------------------
/**
- * Set the route mapping
+ * Set route mapping
*
- * This function determines what should be served based on the URI request,
+ * Determines what should be served based on the URI request,
* as well as any "routes" that have been set in the routing config file.
*
* @return void
@@ -109,21 +111,21 @@ class CI_Router {
// since URI segments are more search-engine friendly, but they can optionally be used.
// If this feature is enabled, we will gather the directory/class/method a little differently
$segments = array();
- if ($this->config->item('enable_query_strings') === TRUE && isset($_GET[$this->config->item('controller_trigger')]))
+ if ($this->config->item('enable_query_strings') === TRUE
+ && ! empty($_GET[$this->config->item('controller_trigger')])
+ && is_string($_GET[$this->config->item('controller_trigger')])
+ )
{
- if (isset($_GET[$this->config->item('directory_trigger')]))
+ if (isset($_GET[$this->config->item('directory_trigger')]) && is_string($_GET[$this->config->item('directory_trigger')]))
{
$this->set_directory(trim($this->uri->_filter_uri($_GET[$this->config->item('directory_trigger')])));
$segments[] = $this->fetch_directory();
}
- if (isset($_GET[$this->config->item('controller_trigger')]))
- {
- $this->set_class(trim($this->uri->_filter_uri($_GET[$this->config->item('controller_trigger')])));
- $segments[] = $this->fetch_class();
- }
+ $this->set_class(trim($this->uri->_filter_uri($_GET[$this->config->item('controller_trigger')])));
+ $segments[] = $this->fetch_class();
- if (isset($_GET[$this->config->item('function_trigger')]))
+ if ( ! empty($_GET[$this->config->item('function_trigger')]) && is_string($_GET[$this->config->item('function_trigger')]))
{
$this->set_method(trim($this->uri->_filter_uri($_GET[$this->config->item('function_trigger')])));
$segments[] = $this->fetch_method();
@@ -140,12 +142,12 @@ class CI_Router {
include(APPPATH.'config/routes.php');
}
- $this->routes = ( ! isset($route) OR ! is_array($route)) ? array() : $route;
+ $this->routes = (empty($route) OR ! is_array($route)) ? array() : $route;
unset($route);
// Set the default controller so we can display it in the event
// the URI doesn't correlated to a valid controller.
- $this->default_controller = empty($this->routes['default_controller']) ? FALSE : strtolower($this->routes['default_controller']);
+ $this->default_controller = empty($this->routes['default_controller']) ? FALSE : $this->routes['default_controller'];
// Were there any query string segments? If so, we'll validate them and bail out since we're done.
if (count($segments) > 0)
@@ -171,31 +173,27 @@ class CI_Router {
// --------------------------------------------------------------------
/**
- * Set the default controller
+ * Set default controller
*
* @return void
*/
protected function _set_default_controller()
{
- if ($this->default_controller === FALSE)
+ if (empty($this->default_controller))
{
show_error('Unable to determine what should be displayed. A default route has not been specified in the routing file.');
}
+
// Is the method being specified?
- if (strpos($this->default_controller, '/') !== FALSE)
- {
- $x = explode('/', $this->default_controller);
- $this->set_class($x[0]);
- $this->set_method($x[1]);
- $this->_set_request($x);
- }
- else
+ if (sscanf($this->default_controller, '%[^/]/%s', $class, $method) !== 2)
{
- $this->set_class($this->default_controller);
- $this->set_method('index');
- $this->_set_request(array($this->default_controller, 'index'));
+ $method = 'index';
}
+ $this->set_class($class);
+ $this->set_method($method);
+ $this->_set_request(array($class, $method));
+
// re-index the routed segments array so it starts with 1 rather than 0
$this->uri->_reindex_segments();
@@ -205,13 +203,12 @@ class CI_Router {
// --------------------------------------------------------------------
/**
- * Set the Route
+ * Set request route
*
- * This function takes an array of URI segments as
- * input, and sets the current class/method
+ * Takes an array of URI segments as input and sets the class/method
+ * to be called.
*
- * @param array
- * @param bool
+ * @param array $segments URI segments
* @return void
*/
protected function _set_request($segments = array())
@@ -225,17 +222,8 @@ class CI_Router {
$this->set_class($segments[0]);
- if (isset($segments[1]))
- {
- // A standard method request
- $this->set_method($segments[1]);
- }
- else
- {
- // This lets the "routed" segment array identify that the default
- // index method is being used.
- $segments[1] = 'index';
- }
+ isset($segments[1]) OR $segments[1] = 'index';
+ $this->set_method($segments[1]);
// Update our "routed" segment array to contain the segments.
// Note: If there is no custom routing, this array will be
@@ -246,11 +234,12 @@ class CI_Router {
// --------------------------------------------------------------------
/**
- * Validates the supplied segments.
- * Attempts to determine the path to the controller.
+ * Validate request
+ *
+ * Attempts validate the URI request and determine the controller path.
*
- * @param array
- * @return array
+ * @param array $segments URI segments
+ * @return array URI segments
*/
protected function _validate_request($segments)
{
@@ -259,9 +248,13 @@ class CI_Router {
return $segments;
}
+ $temp = str_replace('-', '_', $segments[0]);
+
// Does the requested controller exist in the root folder?
- if (file_exists(APPPATH.'controllers/'.$segments[0].'.php'))
+ if (file_exists(APPPATH.'controllers/'.$temp.'.php'))
{
+ $segments[0] = $temp;
+ empty($segments[1]) OR $segments[1] = str_replace('-', '_', $segments[1]);
return $segments;
}
@@ -269,22 +262,19 @@ class CI_Router {
if (is_dir(APPPATH.'controllers/'.$segments[0]))
{
// Set the directory and remove it from the segment array
- $this->set_directory($segments[0]);
- $segments = array_slice($segments, 1);
-
+ $this->set_directory(array_shift($segments));
if (count($segments) > 0)
{
+ $segments[0] = str_replace('-', '_', $segments[0]);
+ empty($segments[1]) OR $segments[1] = str_replace('-', '_', $segments[1]);
+
// Does the requested controller exist in the sub-folder?
if ( ! file_exists(APPPATH.'controllers/'.$this->fetch_directory().$segments[0].'.php'))
{
if ( ! empty($this->routes['404_override']))
{
- $x = explode('/', $this->routes['404_override']);
- $this->set_directory('');
- $this->set_class($x[0]);
- $this->set_method(isset($x[1]) ? $x[1] : 'index');
-
- return $x;
+ $this->directory = '';
+ return explode('/', $this->routes['404_override'], 2);
}
else
{
@@ -295,40 +285,26 @@ class CI_Router {
else
{
// Is the method being specified in the route?
- if (strpos($this->default_controller, '/') !== FALSE)
- {
- $x = explode('/', $this->default_controller);
- $this->set_class($x[0]);
- $this->set_method($x[1]);
- }
- else
- {
- $this->set_class($this->default_controller);
- $this->set_method('index');
- }
-
- // Does the default controller exist in the sub-folder?
- if ( ! file_exists(APPPATH.'controllers/'.$this->fetch_directory().$this->default_controller.'.php'))
+ $segments = explode('/', $this->default_controller);
+ if ( ! file_exists(APPPATH.'controllers/'.$this->fetch_directory().$segments[0].'.php'))
{
$this->directory = '';
- return array();
}
-
}
return $segments;
}
-
// If we've gotten this far it means that the URI does not correlate to a valid
// controller class. We will now see if there is an override
if ( ! empty($this->routes['404_override']))
{
- $x = explode('/', $this->routes['404_override']);
- $this->set_class($x[0]);
- $this->set_method(isset($x[1]) ? $x[1] : 'index');
+ if (sscanf($this->routes['404_override'], '%[^/]/%s', $class, $method) !== 2)
+ {
+ $method = 'index';
+ }
- return $x;
+ return array($class, $method);
}
// Nothing else to do at this point but show a 404
@@ -340,9 +316,8 @@ class CI_Router {
/**
* Parse Routes
*
- * This function matches any routes that may exist in
- * the config/routes.php file against the URI to
- * determine if the class/method need to be remapped.
+ * Matches any routes that may exist in the config/routes.php file
+ * against the URI to determine if the class/method need to be remapped.
*
* @return void
*/
@@ -352,7 +327,7 @@ class CI_Router {
$uri = implode('/', $this->uri->segments);
// Is there a literal match? If so we're done
- if (isset($this->routes[$uri]))
+ if (isset($this->routes[$uri]) && is_string($this->routes[$uri]))
{
return $this->_set_request(explode('/', $this->routes[$uri]));
}
@@ -361,13 +336,51 @@ class CI_Router {
foreach ($this->routes as $key => $val)
{
// Convert wild-cards to RegEx
- $key = str_replace(array(':any', ':num'), array('.+', '[0-9]+'), $key);
+ $key = str_replace(array(':any', ':num'), array('[^/]+', '[0-9]+'), $key);
// Does the RegEx match?
- if (preg_match('#^'.$key.'$#', $uri))
+ if (preg_match('#^'.$key.'$#', $uri, $matches))
{
- // Do we have a back-reference?
- if (strpos($val, '$') !== FALSE && strpos($key, '(') !== FALSE)
+ // Are we using callbacks to process back-references?
+ if ( ! is_string($val) && is_callable($val))
+ {
+ // Remove the original string from the matches array.
+ array_shift($matches);
+
+ // Get the match count.
+ $match_count = count($matches);
+
+ // Determine how many parameters the callback has.
+ $reflection = new ReflectionFunction($val);
+ $param_count = $reflection->getNumberOfParameters();
+
+ // Are there more parameters than matches?
+ if ($param_count > $match_count)
+ {
+ // Any params without matches will be set to an empty string.
+ $matches = array_merge($matches, array_fill($match_count, $param_count - $match_count, ''));
+
+ $match_count = $param_count;
+ }
+
+ // Get the parameters so we can use their default values.
+ $params = $reflection->getParameters();
+
+ for ($m = 0; $m < $match_count; $m++)
+ {
+ // Is the match empty and does a default value exist?
+ if (empty($matches[$m]) && $params[$m]->isDefaultValueAvailable())
+ {
+ // Substitute the empty match for the default value.
+ $matches[$m] = $params[$m]->getDefaultValue();
+ }
+ }
+
+ // Execute the callback using the values in matches as its parameters.
+ $val = call_user_func_array($val, $matches);
+ }
+ // Are we using the default routing method for back-references?
+ elseif (strpos($val, '$') !== FALSE && strpos($key, '(') !== FALSE)
{
$val = preg_replace('#^'.$key.'$#', $val, $uri);
}
@@ -384,9 +397,9 @@ class CI_Router {
// --------------------------------------------------------------------
/**
- * Set the class name
+ * Set class name
*
- * @param string
+ * @param string $class Class name
* @return void
*/
public function set_class($class)
@@ -409,9 +422,9 @@ class CI_Router {
// --------------------------------------------------------------------
/**
- * Set the method name
+ * Set method name
*
- * @param string
+ * @param string $method Method name
* @return void
*/
public function set_method($method)
@@ -428,20 +441,15 @@ class CI_Router {
*/
public function fetch_method()
{
- if ($this->method == $this->fetch_class())
- {
- return 'index';
- }
-
- return $this->method;
+ return ($this->method === $this->fetch_class()) ? 'index' : $this->method;
}
// --------------------------------------------------------------------
/**
- * Set the directory name
+ * Set directory name
*
- * @param string
+ * @param string $dir Directory name
* @return void
*/
public function set_directory($dir)
@@ -452,7 +460,10 @@ class CI_Router {
// --------------------------------------------------------------------
/**
- * Fetch the sub-directory (if any) that contains the requested controller class
+ * Fetch directory
+ *
+ * Feches the sub-directory (if any) that contains the requested
+ * controller class.
*
* @return string
*/
@@ -464,9 +475,9 @@ class CI_Router {
// --------------------------------------------------------------------
/**
- * Set the controller overrides
+ * Set controller overrides
*
- * @param array
+ * @param array $routing Route overrides
* @return void
*/
public function _set_overrides($routing)
@@ -481,14 +492,14 @@ class CI_Router {
$this->set_directory($routing['directory']);
}
- if (isset($routing['controller']) && $routing['controller'] != '')
+ if ( ! empty($routing['controller']))
{
$this->set_class($routing['controller']);
}
if (isset($routing['function']))
{
- $routing['function'] = ($routing['function'] == '') ? 'index' : $routing['function'];
+ $routing['function'] = empty($routing['function']) ? 'index' : $routing['function'];
$this->set_method($routing['function']);
}
}
diff --git a/system/core/Security.php b/system/core/Security.php
index ac39ce97b..c415544b6 100755..100644
--- a/system/core/Security.php
+++ b/system/core/Security.php
@@ -1,4 +1,4 @@
-<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');
+<?php
/**
* CodeIgniter
*
@@ -24,6 +24,7 @@
* @since Version 1.0
* @filesource
*/
+defined('BASEPATH') OR exit('No direct script access allowed');
/**
* Security Class
@@ -37,71 +38,87 @@
class CI_Security {
/**
- * Random Hash for protecting URLs
+ * XSS Hash
*
- * @var string
+ * Random Hash for protecting URLs.
+ *
+ * @var string
*/
- protected $_xss_hash = '';
+ protected $_xss_hash = '';
/**
- * Random Hash for Cross Site Request Forgery Protection Cookie
+ * CSRF Hash
+ *
+ * Random hash for Cross Site Request Forgery protection cookie
*
- * @var string
+ * @var string
*/
- protected $_csrf_hash = '';
+ protected $_csrf_hash = '';
/**
- * Expiration time for Cross Site Request Forgery Protection Cookie
- * Defaults to two hours (in seconds)
+ * CSRF Expire time
+ *
+ * Expiration time for Cross Site Request Forgery protection cookie.
+ * Defaults to two hours (in seconds).
*
- * @var int
+ * @var int
*/
- protected $_csrf_expire = 7200;
+ protected $_csrf_expire = 7200;
/**
- * Token name for Cross Site Request Forgery Protection Cookie
+ * CSRF Token name
*
- * @var string
+ * Token name for Cross Site Request Forgery protection cookie.
+ *
+ * @var string
*/
- protected $_csrf_token_name = 'ci_csrf_token';
+ protected $_csrf_token_name = 'ci_csrf_token';
/**
- * Cookie name for Cross Site Request Forgery Protection Cookie
+ * CSRF Cookie name
+ *
+ * Cookie name for Cross Site Request Forgery protection cookie.
*
- * @var string
+ * @var string
*/
- protected $_csrf_cookie_name = 'ci_csrf_token';
+ protected $_csrf_cookie_name = 'ci_csrf_token';
/**
* List of never allowed strings
*
- * @var array
+ * @var array
*/
- protected $_never_allowed_str = array(
- 'document.cookie' => '[removed]',
- 'document.write' => '[removed]',
- '.parentNode' => '[removed]',
- '.innerHTML' => '[removed]',
- 'window.location' => '[removed]',
- '-moz-binding' => '[removed]',
- '<!--' => '&lt;!--',
- '-->' => '--&gt;',
- '<![CDATA[' => '&lt;![CDATA[',
- '<comment>' => '&lt;comment&gt;'
- );
+ protected $_never_allowed_str = array(
+ 'document.cookie' => '[removed]',
+ 'document.write' => '[removed]',
+ '.parentNode' => '[removed]',
+ '.innerHTML' => '[removed]',
+ 'window.location' => '[removed]',
+ '-moz-binding' => '[removed]',
+ '<!--' => '&lt;!--',
+ '-->' => '--&gt;',
+ '<![CDATA[' => '&lt;![CDATA[',
+ '<comment>' => '&lt;comment&gt;'
+ );
/**
- * List of never allowed regex replacement
+ * List of never allowed regex replacements
*
- * @var array
+ * @var array
*/
protected $_never_allowed_regex = array(
- 'javascript\s*:',
- 'expression\s*(\(|&\#40;)', // CSS and IE
- 'vbscript\s*:', // IE, surprise!
- 'Redirect\s+302'
- );
+ 'javascript\s*:',
+ 'expression\s*(\(|&\#40;)', // CSS and IE
+ 'vbscript\s*:', // IE, surprise!
+ 'Redirect\s+302',
+ "([\"'])?data\s*:[^\\1]*?base64[^\\1]*?,[^\\1]*?\\1?"
+ );
+ /**
+ * Class constructor
+ *
+ * @return void
+ */
public function __construct()
{
// Is CSRF protection enabled?
@@ -132,7 +149,7 @@ class CI_Security {
// --------------------------------------------------------------------
/**
- * Verify Cross Site Request Forgery Protection
+ * CSRF Verify
*
* @return object
*/
@@ -155,8 +172,8 @@ class CI_Security {
}
// Do the tokens exist in both the _POST and _COOKIE arrays?
- if ( ! isset($_POST[$this->_csrf_token_name]) OR ! isset($_COOKIE[$this->_csrf_cookie_name])
- OR $_POST[$this->_csrf_token_name] != $_COOKIE[$this->_csrf_cookie_name]) // Do the tokens match?
+ if ( ! isset($_POST[$this->_csrf_token_name], $_COOKIE[$this->_csrf_cookie_name])
+ OR $_POST[$this->_csrf_token_name] !== $_COOKIE[$this->_csrf_cookie_name]) // Do the tokens match?
{
$this->csrf_show_error();
}
@@ -182,8 +199,9 @@ class CI_Security {
// --------------------------------------------------------------------
/**
- * Set Cross Site Request Forgery Protection Cookie
+ * CSRF Set Cookie
*
+ * @codeCoverageIgnore
* @return object
*/
public function csrf_set_cookie()
@@ -191,17 +209,17 @@ class CI_Security {
$expire = time() + $this->_csrf_expire;
$secure_cookie = (bool) config_item('cookie_secure');
- if ($secure_cookie && (empty($_SERVER['HTTPS']) OR strtolower($_SERVER['HTTPS']) === 'off'))
+ if ($secure_cookie && ! is_https())
{
return FALSE;
}
setcookie(
- $this->_csrf_cookie_name,
- $this->_csrf_hash,
- $expire,
- config_item('cookie_path'),
- config_item('cookie_domain'),
+ $this->_csrf_cookie_name,
+ $this->_csrf_hash,
+ $expire,
+ config_item('cookie_path'),
+ config_item('cookie_domain'),
$secure_cookie,
config_item('cookie_httponly')
);
@@ -227,9 +245,8 @@ class CI_Security {
/**
* Get CSRF Hash
*
- * Getter Method
- *
- * @return string self::_csrf_hash
+ * @see CI_Security::$_csrf_hash
+ * @return string CSRF hash
*/
public function get_csrf_hash()
{
@@ -241,9 +258,8 @@ class CI_Security {
/**
* Get CSRF Token Name
*
- * Getter Method
- *
- * @return string self::_csrf_token_name
+ * @see CI_Security::$_csrf_token_name
+ * @return string CSRF token name
*/
public function get_csrf_token_name()
{
@@ -256,26 +272,26 @@ class CI_Security {
* XSS Clean
*
* Sanitizes data so that Cross Site Scripting Hacks can be
- * prevented. This function does a fair amount of work but
+ * prevented. This method does a fair amount of work but
* it is extremely thorough, designed to prevent even the
* most obscure XSS attempts. Nothing is ever 100% foolproof,
* of course, but I haven't been able to get anything passed
* the filter.
*
- * Note: This function should only be used to deal with data
- * upon submission. It's not something that should
- * be used for general runtime processing.
+ * Note: Should only be used to deal with data upon submission.
+ * It's not something that should be used for general
+ * runtime processing.
*
- * This function was based in part on some code and ideas I
- * got from Bitflux: http://channel.bitflux.ch/wiki/XSS_Prevention
+ * @link http://channel.bitflux.ch/wiki/XSS_Prevention
+ * Based in part on some code and ideas from Bitflux.
*
- * To help develop this script I used this great list of
- * vulnerabilities along with a few other hacks I've
- * harvested from examining vulnerabilities in other programs:
- * http://ha.ckers.org/xss.html
+ * @link http://ha.ckers.org/xss.html
+ * To help develop this script I used this great list of
+ * vulnerabilities along with a few other hacks I've
+ * harvested from examining vulnerabilities in other programs.
*
- * @param mixed string or array
- * @param bool
+ * @param string|string[] $str Input data
+ * @param bool $is_image Whether the input is an image
* @return string
*/
public function xss_clean($str, $is_image = FALSE)
@@ -352,7 +368,7 @@ class CI_Security {
}
else
{
- $str = str_replace(array('<?', '?'.'>'), array('&lt;?', '?&gt;'), $str);
+ $str = str_replace(array('<?', '?'.'>'), array('&lt;?', '?&gt;'), $str);
}
/*
@@ -362,9 +378,9 @@ class CI_Security {
* These words are compacted back to their correct state.
*/
$words = array(
- 'javascript', 'expression', 'vbscript', 'script',
- 'applet', 'alert', 'document', 'write', 'cookie', 'window'
- );
+ 'javascript', 'expression', 'vbscript', 'script', 'base64',
+ 'applet', 'alert', 'document', 'write', 'cookie', 'window'
+ );
foreach ($words as $word)
{
@@ -387,20 +403,20 @@ class CI_Security {
if (preg_match('/<a/i', $str))
{
- $str = preg_replace_callback('#<a\s+([^>]*?)(>|$)#si', array($this, '_js_link_removal'), $str);
+ $str = preg_replace_callback('#<a\s+([^>]*?)(?:>|$)#si', array($this, '_js_link_removal'), $str);
}
if (preg_match('/<img/i', $str))
{
- $str = preg_replace_callback('#<img\s+([^>]*?)(\s?/?>|$)#si', array($this, '_js_img_removal'), $str);
+ $str = preg_replace_callback('#<img\s+([^>]*?)(?:\s?/?>|$)#si', array($this, '_js_img_removal'), $str);
}
- if (preg_match('/(script|xss)/i', $str))
+ if (preg_match('/script|xss/i', $str))
{
- $str = preg_replace('#<(/*)(script|xss)(.*?)\>#si', '[removed]', $str);
+ $str = preg_replace('#</*(?:script|xss).*?>#si', '[removed]', $str);
}
}
- while($original != $str);
+ while ($original !== $str);
unset($original);
@@ -461,13 +477,16 @@ class CI_Security {
// --------------------------------------------------------------------
/**
- * Random Hash for protecting URLs
+ * XSS Hash
*
- * @return string
+ * Generates the XSS hash if needed and returns it.
+ *
+ * @see CI_Security::$_xss_hash
+ * @return string XSS hash
*/
public function xss_hash()
{
- if ($this->_xss_hash == '')
+ if ($this->_xss_hash === '')
{
mt_srand();
$this->_xss_hash = md5(time() + mt_rand(0, 1999999999));
@@ -481,7 +500,7 @@ class CI_Security {
/**
* HTML Entities Decode
*
- * This function is a replacement for html_entity_decode()
+ * A replacement for html_entity_decode()
*
* The reason we are not using html_entity_decode() by itself is because
* while it is not technically correct to leave out the semicolon
@@ -489,8 +508,10 @@ class CI_Security {
* correctly. html_entity_decode() does not convert entities without
* semicolons, so we are left with our own little solution here. Bummer.
*
- * @param string
- * @param string
+ * @link http://php.net/html-entity-decode
+ *
+ * @param string $str Input
+ * @param string $charset Character set
* @return string
*/
public function entity_decode($str, $charset = NULL)
@@ -513,32 +534,32 @@ class CI_Security {
// --------------------------------------------------------------------
/**
- * Filename Security
+ * Sanitize Filename
*
- * @param string
- * @param bool
+ * @param string $str Input file name
+ * @param bool $relative_path Whether to preserve paths
* @return string
*/
public function sanitize_filename($str, $relative_path = FALSE)
{
$bad = array(
- '../', '<!--', '-->', '<', '>',
- "'", '"', '&', '$', '#',
- '{', '}', '[', ']', '=',
- ';', '?', '%20', '%22',
- '%3c', // <
- '%253c', // <
- '%3e', // >
- '%0e', // >
- '%28', // (
- '%29', // )
- '%2528', // (
- '%26', // &
- '%24', // $
- '%3f', // ?
- '%3b', // ;
- '%3d' // =
- );
+ '../', '<!--', '-->', '<', '>',
+ "'", '"', '&', '$', '#',
+ '{', '}', '[', ']', '=',
+ ';', '?', '%20', '%22',
+ '%3c', // <
+ '%253c', // <
+ '%3e', // >
+ '%0e', // >
+ '%28', // (
+ '%29', // )
+ '%2528', // (
+ '%26', // &
+ '%24', // $
+ '%3f', // ?
+ '%3b', // ;
+ '%3d' // =
+ );
if ( ! $relative_path)
{
@@ -553,13 +574,27 @@ class CI_Security {
// ----------------------------------------------------------------
/**
+ * Strip Image Tags
+ *
+ * @param string $str
+ * @return string
+ */
+ public function strip_image_tags($str)
+ {
+ return preg_replace(array('#<img\s+.*?src\s*=\s*["\'](.+?)["\'].*?\>#', '#<img\s+.*?src\s*=\s*(.+?).*?\>#'), '\\1', $str);
+ }
+
+ // ----------------------------------------------------------------
+
+ /**
* Compact Exploded Words
*
- * Callback function for xss_clean() to remove whitespace from
- * things like j a v a s c r i p t
+ * Callback method for xss_clean() to remove whitespace from
+ * things like 'j a v a s c r i p t'.
*
- * @param type
- * @return type
+ * @used-by CI_Security::xss_clean()
+ * @param array $matches
+ * @return string
*/
protected function _compact_exploded_words($matches)
{
@@ -568,20 +603,26 @@ class CI_Security {
// --------------------------------------------------------------------
- /*
- * Remove Evil HTML Attributes (like evenhandlers and style)
+ /**
+ * Remove Evil HTML Attributes (like event handlers and style)
*
* It removes the evil attribute and either:
- * - Everything up until a space
- * For example, everything between the pipes:
+ *
+ * - Everything up until a space. For example, everything between the pipes:
+ *
+ * <code>
* <a |style=document.write('hello');alert('world');| class=link>
- * - Everything inside the quotes
- * For example, everything between the pipes:
+ * </code>
+ *
+ * - Everything inside the quotes. For example, everything between the pipes:
+ *
+ * <code>
* <a |style="document.write('hello'); alert('world');"| class="link">
+ * </code>
*
- * @param string $str The string to check
- * @param boolean $is_image TRUE if this is an image
- * @return string The string with the evil attributes removed
+ * @param string $str The string to check
+ * @param bool $is_image Whether the input is an image
+ * @return string The string with the evil attributes removed
*/
protected function _remove_evil_attributes($str, $is_image)
{
@@ -602,10 +643,11 @@ class CI_Security {
$attribs = array();
// find occurrences of illegal attribute strings without quotes
- preg_match_all('/('.implode('|', $evil_attributes).')\s*=\s*([^\s]*)/is', $str, $matches, PREG_SET_ORDER);
+ preg_match_all('/('.implode('|', $evil_attributes).')\s*=\s*([^\s>]*)/is', $str, $matches, PREG_SET_ORDER);
foreach ($matches as $attr)
{
+
$attribs[] = preg_quote($attr[0], '/');
}
@@ -620,7 +662,7 @@ class CI_Security {
// replace illegal attribute strings that are inside an html tag
if (count($attribs) > 0)
{
- $str = preg_replace('/<(\/?[^><]+?)([^A-Za-z\-])('.implode('|', $attribs).')([\s><])([><]*)/i', '<$1$2$4$5', $str, -1, $count);
+ $str = preg_replace('/<(\/?[^><]+?)([^A-Za-z<>\-])(.*?)('.implode('|', $attribs).')(.*?)([\s><])([><]*)/i', '<$1 $3$5$6$7', $str, -1, $count);
}
} while ($count);
@@ -633,9 +675,10 @@ class CI_Security {
/**
* Sanitize Naughty HTML
*
- * Callback function for xss_clean() to remove naughty HTML elements
+ * Callback method for xss_clean() to remove naughty HTML elements.
*
- * @param array
+ * @used-by CI_Security::xss_clean()
+ * @param array $matches
* @return string
*/
protected function _sanitize_naughty_html($matches)
@@ -650,18 +693,20 @@ class CI_Security {
/**
* JS Link Removal
*
- * Callback function for xss_clean() to sanitize links
+ * Callback method for xss_clean() to sanitize links.
+ *
* This limits the PCRE backtracks, making it more performance friendly
* and prevents PREG_BACKTRACK_LIMIT_ERROR from being triggered in
- * PHP 5.2+ on link-heavy strings
+ * PHP 5.2+ on link-heavy strings.
*
- * @param array
+ * @used-by CI_Security::xss_clean()
+ * @param array $match
* @return string
*/
protected function _js_link_removal($match)
{
return str_replace($match[1],
- preg_replace('#href=.*?(alert\(|alert&\#40;|javascript\:|livescript\:|mocha\:|charset\=|window\.|document\.|\.cookie|<script|<xss|base64\s*,)#si',
+ preg_replace('#href=.*?(?:alert\(|alert&\#40;|javascript:|livescript:|mocha:|charset=|window\.|document\.|\.cookie|<script|<xss|data\s*:)#si',
'',
$this->_filter_attributes(str_replace(array('<', '>'), '', $match[1]))
),
@@ -673,18 +718,20 @@ class CI_Security {
/**
* JS Image Removal
*
- * Callback function for xss_clean() to sanitize image tags
+ * Callback method for xss_clean() to sanitize image tags.
+ *
* This limits the PCRE backtracks, making it more performance friendly
* and prevents PREG_BACKTRACK_LIMIT_ERROR from being triggered in
- * PHP 5.2+ on image tag heavy strings
+ * PHP 5.2+ on image tag heavy strings.
*
- * @param array
+ * @used-by CI_Security::xss_clean()
+ * @param array $match
* @return string
*/
protected function _js_img_removal($match)
{
return str_replace($match[1],
- preg_replace('#src=.*?(alert\(|alert&\#40;|javascript\:|livescript\:|mocha\:|charset\=|window\.|document\.|\.cookie|<script|<xss|base64\s*,)#si',
+ preg_replace('#src=.*?(?:alert\(|alert&\#40;|javascript:|livescript:|mocha:|charset=|window\.|document\.|\.cookie|<script|<xss|base64\s*,)#si',
'',
$this->_filter_attributes(str_replace(array('<', '>'), '', $match[1]))
),
@@ -696,9 +743,8 @@ class CI_Security {
/**
* Attribute Conversion
*
- * Used as a callback for XSS Clean
- *
- * @param array
+ * @used-by CI_Security::xss_clean()
+ * @param array $match
* @return string
*/
protected function _convert_attribute($match)
@@ -711,9 +757,11 @@ class CI_Security {
/**
* Filter Attributes
*
- * Filters tag attributes for consistency and safety
+ * Filters tag attributes for consistency and safety.
*
- * @param string
+ * @used-by CI_Security::_js_img_removal()
+ * @used-by CI_Security::_js_link_removal()
+ * @param string $str
* @return string
*/
protected function _filter_attributes($str)
@@ -735,9 +783,8 @@ class CI_Security {
/**
* HTML Entity Decode Callback
*
- * Used as a callback for XSS Clean
- *
- * @param array
+ * @used-by CI_Security::xss_clean()
+ * @param array $match
* @return string
*/
protected function _decode_entity($match)
@@ -750,9 +797,8 @@ class CI_Security {
/**
* Validate URL entities
*
- * Called by xss_clean()
- *
- * @param string
+ * @used-by CI_Security::xss_clean()
+ * @param string $str
* @return string
*/
protected function _validate_entities($str)
@@ -790,8 +836,7 @@ class CI_Security {
/**
* Do Never Allowed
*
- * A utility function for xss_clean()
- *
+ * @used-by CI_Security::xss_clean()
* @param string
* @return string
*/
@@ -801,7 +846,7 @@ class CI_Security {
foreach ($this->_never_allowed_regex as $regex)
{
- $str = preg_replace('#'.$regex.'#i', '[removed]', $str);
+ $str = preg_replace('#'.$regex.'#is', '[removed]', $str);
}
return $str;
@@ -810,20 +855,20 @@ class CI_Security {
// --------------------------------------------------------------------
/**
- * Set Cross Site Request Forgery Protection Cookie
+ * Set CSRF Hash and Cookie
*
* @return string
*/
protected function _csrf_set_hash()
{
- if ($this->_csrf_hash == '')
+ if ($this->_csrf_hash === '')
{
// If the cookie exists we will use it's value.
// We don't necessarily want to regenerate it with
// each page load since a page could contain embedded
// sub-pages causing this feature to fail
if (isset($_COOKIE[$this->_csrf_cookie_name]) &&
- $_COOKIE[$this->_csrf_cookie_name] != '')
+ preg_match('#^[0-9a-f]{32}$#iS', $_COOKIE[$this->_csrf_cookie_name]) === 1)
{
return $this->_csrf_hash = $_COOKIE[$this->_csrf_cookie_name];
}
@@ -838,4 +883,4 @@ class CI_Security {
}
/* End of file Security.php */
-/* Location: ./system/core/Security.php */
+/* Location: ./system/core/Security.php */ \ No newline at end of file
diff --git a/system/core/URI.php b/system/core/URI.php
index 48bb7ae3c..900472b61 100755..100644
--- a/system/core/URI.php
+++ b/system/core/URI.php
@@ -1,4 +1,4 @@
-<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');
+<?php
/**
* CodeIgniter
*
@@ -22,9 +22,9 @@
* @license http://opensource.org/licenses/OSL-3.0 Open Software License (OSL 3.0)
* @link http://codeigniter.com
* @since Version 1.0
+ * @filesource
*/
-
-// ------------------------------------------------------------------------
+defined('BASEPATH') OR exit('No direct script access allowed');
/**
* URI Class
@@ -40,37 +40,43 @@
class CI_URI {
/**
- * List of cached uri segments
+ * List of cached URI segments
*
- * @var array
+ * @var array
*/
- public $keyval = array();
+ public $keyval = array();
+
/**
- * Current uri string
+ * Current URI string
*
- * @var string
+ * @var string
*/
public $uri_string;
+
/**
- * List of uri segments
+ * List of URI segments
*
- * @var array
+ * @var array
*/
- public $segments = array();
+ public $segments = array();
+
/**
- * Re-indexed list of uri segments
- * Starts at 1 instead of 0
+ * Re-indexed list of URI segments
+ *
+ * Starts at 1 instead of 0.
*
- * @var array
+ * @var array
*/
- public $rsegments = array();
+ public $rsegments = array();
/**
- * Constructor
+ * Class constructor
*
* Simply globalizes the $RTR object. The front
* loads the Router class early on so it's not available
* normally as other classes are.
+ *
+ * @return void
*/
public function __construct()
{
@@ -81,10 +87,9 @@ class CI_URI {
// --------------------------------------------------------------------
/**
- * Get the URI String
- *
- * Called by CI_Router
+ * Fetch URI String
*
+ * @used-by CI_Router
* @return void
*/
public function _fetch_uri_string()
@@ -94,36 +99,33 @@ class CI_URI {
// Is the request coming from the command line?
if ($this->_is_cli_request())
{
- $this->_set_uri_string($this->_parse_cli_args());
+ $this->_set_uri_string($this->_parse_argv());
return;
}
- // Let's try the REQUEST_URI first, this will work in most situations
- if ($uri = $this->_detect_uri())
+ // Is there a PATH_INFO variable? This should be the easiest solution.
+ if (isset($_SERVER['PATH_INFO']))
{
- $this->_set_uri_string($uri);
+ $this->_set_uri_string($_SERVER['PATH_INFO']);
return;
}
- // Is there a PATH_INFO variable?
- // Note: some servers seem to have trouble with getenv() so we'll test it two ways
- $path = (isset($_SERVER['PATH_INFO'])) ? $_SERVER['PATH_INFO'] : @getenv('PATH_INFO');
- if (trim($path, '/') != '' && $path !== '/'.SELF)
+ // Let's try REQUEST_URI then, this will work in most situations
+ if (($uri = $this->_parse_request_uri()) !== '')
{
- $this->_set_uri_string($path);
+ $this->_set_uri_string($uri);
return;
}
- // No PATH_INFO?... What about QUERY_STRING?
- $path = (isset($_SERVER['QUERY_STRING'])) ? $_SERVER['QUERY_STRING'] : @getenv('QUERY_STRING');
- if (trim($path, '/') != '')
+ // No REQUEST_URI either?... What about QUERY_STRING?
+ if (($uri = $this->_parse_query_string()) !== '')
{
- $this->_set_uri_string($path);
+ $this->_set_uri_string($uri);
return;
}
// As a last ditch effort lets try using the $_GET array
- if (is_array($_GET) && count($_GET) === 1 && trim(key($_GET), '/') != '')
+ if (is_array($_GET) && count($_GET) === 1 && trim(key($_GET), '/') !== '')
{
$this->_set_uri_string(key($_GET));
return;
@@ -136,138 +138,191 @@ class CI_URI {
$uri = strtoupper($this->config->item('uri_protocol'));
- if ($uri === 'REQUEST_URI')
+ if ($uri === 'CLI')
{
- $this->_set_uri_string($this->_detect_uri());
+ $this->_set_uri_string($this->_parse_argv());
return;
}
- elseif ($uri === 'CLI')
+ elseif (method_exists($this, ($method = '_parse_'.strtolower($uri))))
{
- $this->_set_uri_string($this->_parse_cli_args());
+ $this->_set_uri_string($this->$method());
return;
}
- $path = (isset($_SERVER[$uri])) ? $_SERVER[$uri] : @getenv($uri);
- $this->_set_uri_string($path);
+ $uri = isset($_SERVER[$uri]) ? $_SERVER[$uri] : @getenv($uri);
+ $this->_set_uri_string($uri);
}
// --------------------------------------------------------------------
/**
- * Set the URI String
+ * Set URI String
*
- * @param string
+ * @param string $str
* @return void
*/
- public function _set_uri_string($str)
+ protected function _set_uri_string($str)
{
- // Filter out control characters
- $str = remove_invisible_characters($str, FALSE);
-
- // If the URI contains only a slash we'll kill it
- $this->uri_string = ($str === '/') ? '' : $str;
+ // Filter out control characters and trim slashes
+ $this->uri_string = trim(remove_invisible_characters($str, FALSE), '/');
}
// --------------------------------------------------------------------
/**
- * Detects the URI
+ * Parse REQUEST_URI
*
- * This function will detect the URI automatically and fix the query string
- * if necessary.
+ * Will parse REQUEST_URI and automatically detect the URI from it,
+ * while fixing the query string if necessary.
*
+ * @used-by CI_URI::_fetch_uri_string()
* @return string
*/
- protected function _detect_uri()
+ protected function _parse_request_uri()
{
- if ( ! isset($_SERVER['REQUEST_URI']) OR ! isset($_SERVER['SCRIPT_NAME']))
+ if ( ! isset($_SERVER['REQUEST_URI'], $_SERVER['SCRIPT_NAME']))
{
return '';
}
- $uri = $_SERVER['REQUEST_URI'];
+ $uri = parse_url($_SERVER['REQUEST_URI']);
+ $query = isset($uri['query']) ? $uri['query'] : '';
+ $uri = isset($uri['path']) ? rawurldecode($uri['path']) : '';
+
if (strpos($uri, $_SERVER['SCRIPT_NAME']) === 0)
{
- $uri = substr($uri, strlen($_SERVER['SCRIPT_NAME']));
+ $uri = (string) substr($uri, strlen($_SERVER['SCRIPT_NAME']));
}
elseif (strpos($uri, dirname($_SERVER['SCRIPT_NAME'])) === 0)
{
- $uri = substr($uri, strlen(dirname($_SERVER['SCRIPT_NAME'])));
+ $uri = (string) substr($uri, strlen(dirname($_SERVER['SCRIPT_NAME'])));
}
// This section ensures that even on servers that require the URI to be in the query string (Nginx) a correct
// URI is found, and also fixes the QUERY_STRING server var and $_GET array.
- if (strncmp($uri, '?/', 2) === 0)
- {
- $uri = substr($uri, 2);
- }
- $parts = preg_split('#\?#i', $uri, 2);
- $uri = $parts[0];
- if (isset($parts[1]))
+ if (trim($uri, '/') === '' && strncmp($query, '/', 1) === 0)
{
- $_SERVER['QUERY_STRING'] = $parts[1];
- parse_str($_SERVER['QUERY_STRING'], $_GET);
+ $query = explode('?', $query, 2);
+ $uri = rawurldecode($query[0]);
+ $_SERVER['QUERY_STRING'] = isset($query[1]) ? $query[1] : '';
}
else
{
- $_SERVER['QUERY_STRING'] = '';
- $_GET = array();
+ $_SERVER['QUERY_STRING'] = $query;
}
- if ($uri == '/' OR empty($uri))
+ parse_str($_SERVER['QUERY_STRING'], $_GET);
+
+ if ($uri === '/' OR $uri === '')
{
return '/';
}
- $uri = parse_url($uri, PHP_URL_PATH);
-
// Do some final cleaning of the URI and return it
- return str_replace(array('//', '../'), '/', trim($uri, '/'));
+ return $this->_remove_relative_directory($uri);
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Remove relative directory (../) and multi slashes (///)
+ *
+ * Do some final cleaning of the URI and return it, currently only used in self::_parse_request_uri()
+ *
+ * @param string $url
+ * @return string
+ */
+ protected function _remove_relative_directory($uri)
+ {
+ $uris = array();
+ $tok = strtok($uri, '/');
+ while ($tok !== FALSE)
+ {
+ if (( ! empty($tok) OR $tok === '0') && $tok !== '..')
+ {
+ $uris[] = $tok;
+ }
+ $tok = strtok('/');
+ }
+ return implode('/', $uris);
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Parse QUERY_STRING
+ *
+ * Will parse QUERY_STRING and automatically detect the URI from it.
+ *
+ * @used-by CI_URI::_fetch_uri_string()
+ * @return string
+ */
+ protected function _parse_query_string()
+ {
+ $uri = isset($_SERVER['QUERY_STRING']) ? $_SERVER['QUERY_STRING'] : @getenv('QUERY_STRING');
+
+ if (trim($uri, '/') === '')
+ {
+ return '';
+ }
+ elseif (strncmp($uri, '/', 1) === 0)
+ {
+ $uri = explode('?', $uri, 2);
+ $_SERVER['QUERY_STRING'] = isset($uri[1]) ? $uri[1] : '';
+ $uri = rawurldecode($uri[0]);
+ }
+
+ parse_str($_SERVER['QUERY_STRING'], $_GET);
+
+ return $this->_remove_relative_directory($uri);
}
// --------------------------------------------------------------------
-
+
/**
- * Is cli Request?
+ * Is CLI Request?
*
- * Duplicate of function from the Input class to test to see if a request was made from the command line
+ * Duplicate of method from the Input class to test to see if
+ * a request was made from the command line.
*
- * @return boolean
+ * @see CI_Input::is_cli_request()
+ * @used-by CI_URI::_fetch_uri_string()
+ * @return bool
*/
protected function _is_cli_request()
{
- return (php_sapi_name() == 'cli') OR defined('STDIN');
+ return (php_sapi_name() === 'cli') OR defined('STDIN');
}
-
// --------------------------------------------------------------------
/**
- * Parse cli arguments
+ * Parse CLI arguments
*
* Take each command line argument and assume it is a URI segment.
*
* @return string
*/
- protected function _parse_cli_args()
+ protected function _parse_argv()
{
$args = array_slice($_SERVER['argv'], 1);
- return $args ? '/' . implode('/', $args) : '';
+ return $args ? implode('/', $args) : '';
}
// --------------------------------------------------------------------
/**
- * Filter segments for malicious characters
+ * Filter URI
*
- * Called by CI_Router
+ * Filters segments for malicious characters.
*
- * @param string
+ * @used-by CI_Router
+ * @param string $str
* @return string
*/
public function _filter_uri($str)
{
- if ($str != '' && $this->config->item('permitted_uri_chars') != '' && $this->config->item('enable_query_strings') == FALSE)
+ if ($str !== '' && $this->config->item('permitted_uri_chars') != '' && $this->config->item('enable_query_strings') === FALSE)
{
// preg_quote() in PHP 5.3 escapes -, so the str_replace() and addition of - to preg_quote() is to maintain backwards
// compatibility as many are unaware of how characters in the permitted_uri_chars will be parsed as a regex pattern
@@ -287,28 +342,32 @@ class CI_URI {
// --------------------------------------------------------------------
/**
- * Remove the suffix from the URL if needed
+ * Remove URL suffix
*
- * Called by CI_Router
+ * Removes the suffix from the URL if needed.
*
+ * @used-by CI_Router
* @return void
*/
public function _remove_url_suffix()
{
- if ($this->config->item('url_suffix') != '')
+ $suffix = (string) $this->config->item('url_suffix');
+
+ if ($suffix !== '' && ($offset = strrpos($this->uri_string, $suffix)) !== FALSE)
{
- $this->uri_string = preg_replace('|'.preg_quote($this->config->item('url_suffix')).'$|', '', $this->uri_string);
+ $this->uri_string = substr_replace($this->uri_string, '', $offset, strlen($suffix));
}
}
// --------------------------------------------------------------------
/**
- * Explode the URI Segments. The individual segments will
- * be stored in the $this->segments array.
+ * Explode URI segments
*
- * Called by CI_Router
+ * The individual segments will be stored in the $this->segments array.
*
+ * @see CI_URI::$segments
+ * @used-by CI_Router
* @return void
*/
public function _explode_segments()
@@ -318,7 +377,7 @@ class CI_URI {
// Filter segments for security
$val = trim($this->_filter_uri($val));
- if ($val != '')
+ if ($val !== '')
{
$this->segments[] = $val;
}
@@ -326,16 +385,16 @@ class CI_URI {
}
// --------------------------------------------------------------------
+
/**
* Re-index Segments
*
- * This function re-indexes the $this->segment array so that it
- * starts at 1 rather than 0. Doing so makes it simpler to
- * use functions like $this->uri->segment(n) since there is
- * a 1:1 relationship between the segment array and the actual segments.
- *
- * Called by CI_Router
+ * Re-indexes the CI_URI::$segment array so that it starts at 1 rather
+ * than 0. Doing so makes it simpler to use methods like
+ * CI_URI::segment(n) since there is a 1:1 relationship between the
+ * segment array and the actual segments.
*
+ * @used-by CI_Router
* @return void
*/
public function _reindex_segments()
@@ -349,68 +408,76 @@ class CI_URI {
// --------------------------------------------------------------------
/**
- * Fetch a URI Segment
- *
- * This function returns the URI segment based on the number provided.
+ * Fetch URI Segment
*
- * @param integer
- * @param bool
- * @return string
+ * @see CI_URI::$segments
+ * @param int $n Index
+ * @param mixed $no_result What to return if the segment index is not found
+ * @return mixed
*/
- public function segment($n, $no_result = FALSE)
+ public function segment($n, $no_result = NULL)
{
- return ( ! isset($this->segments[$n])) ? $no_result : $this->segments[$n];
+ return isset($this->segments[$n]) ? $this->segments[$n] : $no_result;
}
// --------------------------------------------------------------------
/**
- * Fetch a URI "routed" Segment
+ * Fetch URI "routed" Segment
*
- * This function returns the re-routed URI segment (assuming routing rules are used)
- * based on the number provided. If there is no routing this function returns the
- * same result as $this->segment()
+ * Returns the re-routed URI segment (assuming routing rules are used)
+ * based on the index provided. If there is no routing, will return
+ * the same result as CI_URI::segment().
*
- * @param integer
- * @param bool
- * @return string
+ * @see CI_URI::$rsegments
+ * @see CI_URI::segment()
+ * @param int $n Index
+ * @param mixed $no_result What to return if the segment index is not found
+ * @return mixed
*/
- public function rsegment($n, $no_result = FALSE)
+ public function rsegment($n, $no_result = NULL)
{
- return ( ! isset($this->rsegments[$n])) ? $no_result : $this->rsegments[$n];
+ return isset($this->rsegments[$n]) ? $this->rsegments[$n] : $no_result;
}
// --------------------------------------------------------------------
/**
- * Generate a key value pair from the URI string
+ * URI to assoc
*
- * This function generates and associative array of URI data starting
- * at the supplied segment. For example, if this is your URI:
+ * Generates an associative array of URI data starting at the supplied
+ * segment index. For example, if this is your URI:
*
* example.com/user/search/name/joe/location/UK/gender/male
*
- * You can use this function to generate an array with this prototype:
+ * You can use this method to generate an array with this prototype:
*
- * array (
- * name => joe
- * location => UK
- * gender => male
- * )
+ * array (
+ * name => joe
+ * location => UK
+ * gender => male
+ * )
*
- * @param integer the starting segment number
- * @param array an array of default values
+ * @param int $n Index (default: 3)
+ * @param array $default Default values
* @return array
*/
public function uri_to_assoc($n = 3, $default = array())
{
return $this->_uri_to_assoc($n, $default, 'segment');
}
+
+ // --------------------------------------------------------------------
+
/**
- * Identical to above only it uses the re-routed segment array
+ * Routed URI to assoc
*
- * @param integer the starting segment number
- * @param array an array of default values
+ * Identical to CI_URI::uri_to_assoc(), only it uses the re-routed
+ * segment array.
+ *
+ * @see CI_URI::uri_to_assoc()
+ * @param int $n Index (default: 3)
+ * @param array $default Default values
* @return array
*/
public function ruri_to_assoc($n = 3, $default = array())
@@ -421,11 +488,15 @@ class CI_URI {
// --------------------------------------------------------------------
/**
- * Generate a key value pair from the URI string or Re-routed URI string
+ * Internal URI-to-assoc
+ *
+ * Generates a key/value pair from the URI string or re-routed URI string.
*
- * @param integer the starting segment number
- * @param array an array of default values
- * @param string which array we should use
+ * @used-by CI_URI::uri_to_assoc()
+ * @used-by CI_URI::ruri_to_assoc()
+ * @param int $n Index (default: 3)
+ * @param array $default Default values
+ * @param string $which Array name ('segment' or 'rsegment')
* @return array
*/
protected function _uri_to_assoc($n = 3, $default = array(), $which = 'segment')
@@ -435,9 +506,11 @@ class CI_URI {
return $default;
}
- if (isset($this->keyval[$n]))
+ in_array($which, array('segment', 'rsegment'), TRUE) OR $which = 'segment';
+
+ if (isset($this->keyval[$which], $this->keyval[$which][$n]))
{
- return $this->keyval[$n];
+ return $this->keyval[$which][$n];
}
if ($which === 'segment')
@@ -453,18 +526,15 @@ class CI_URI {
if ($this->$total_segments() < $n)
{
- if (count($default) === 0)
- {
- return array();
- }
-
- return array_fill_keys($default, FALSE);
+ return (count($default) === 0)
+ ? array()
+ : array_fill_keys($default, NULL);
}
$segments = array_slice($this->$segment_array(), ($n - 1));
$i = 0;
$lastval = '';
- $retval = array();
+ $retval = array();
foreach ($segments as $seg)
{
if ($i % 2)
@@ -473,7 +543,7 @@ class CI_URI {
}
else
{
- $retval[$seg] = FALSE;
+ $retval[$seg] = NULL;
$lastval = $seg;
}
@@ -486,29 +556,31 @@ class CI_URI {
{
if ( ! array_key_exists($val, $retval))
{
- $retval[$val] = FALSE;
+ $retval[$val] = NULL;
}
}
}
// Cache the array for reuse
- $this->keyval[$n] = $retval;
+ isset($this->keyval[$which]) OR $this->keyval[$which] = array();
+ $this->keyval[$which][$n] = $retval;
return $retval;
}
// --------------------------------------------------------------------
/**
- * Generate a URI string from an associative array
+ * Assoc to URI
*
+ * Generates a URI string from an associative array.
*
- * @param array an associative array of key/values
- * @return array
+ * @param array $array Input array of key/value pairs
+ * @return string URI string
*/
public function assoc_to_uri($array)
{
$temp = array();
- foreach ((array)$array as $key => $val)
+ foreach ((array) $array as $key => $val)
{
$temp[] = $key;
$temp[] = $val;
@@ -520,10 +592,12 @@ class CI_URI {
// --------------------------------------------------------------------
/**
- * Fetch a URI Segment and add a trailing slash
+ * Slash segment
+ *
+ * Fetches an URI segment with a slash.
*
- * @param integer
- * @param string
+ * @param int $n Index
+ * @param string $where Where to add the slash ('trailing' or 'leading')
* @return string
*/
public function slash_segment($n, $where = 'trailing')
@@ -534,10 +608,12 @@ class CI_URI {
// --------------------------------------------------------------------
/**
- * Fetch a URI Segment and add a trailing slash
+ * Slash routed segment
*
- * @param integer
- * @param string
+ * Fetches an URI routed segment with a slash.
+ *
+ * @param int $n Index
+ * @param string $where Where to add the slash ('trailing' or 'leading')
* @return string
*/
public function slash_rsegment($n, $where = 'trailing')
@@ -548,11 +624,16 @@ class CI_URI {
// --------------------------------------------------------------------
/**
- * Fetch a URI Segment and add a trailing slash - helper function
+ * Internal Slash segment
+ *
+ * Fetches an URI Segment and adds a slash to it.
*
- * @param integer
- * @param string
- * @param string
+ * @used-by CI_URI::slash_segment()
+ * @used-by CI_URI::slash_rsegment()
+ *
+ * @param int $n Index
+ * @param string $where Where to add the slash ('trailing' or 'leading')
+ * @param string $which Array name ('segment' or 'rsegment')
* @return string
*/
protected function _slash_segment($n, $where = 'trailing', $which = 'segment')
@@ -576,7 +657,7 @@ class CI_URI {
/**
* Segment Array
*
- * @return array
+ * @return array CI_URI::$segments
*/
public function segment_array()
{
@@ -588,7 +669,7 @@ class CI_URI {
/**
* Routed Segment Array
*
- * @return array
+ * @return array CI_URI::$rsegments
*/
public function rsegment_array()
{
@@ -600,7 +681,7 @@ class CI_URI {
/**
* Total number of segments
*
- * @return integer
+ * @return int
*/
public function total_segments()
{
@@ -612,7 +693,7 @@ class CI_URI {
/**
* Total number of routed segments
*
- * @return integer
+ * @return int
*/
public function total_rsegments()
{
@@ -622,29 +703,35 @@ class CI_URI {
// --------------------------------------------------------------------
/**
- * Fetch the entire URI string
+ * Fetch URI string
*
- * @return string
+ * @return string CI_URI::$uri_string
*/
public function uri_string()
{
return $this->uri_string;
}
-
// --------------------------------------------------------------------
/**
- * Fetch the entire Re-routed URI string
+ * Fetch Re-routed URI string
*
* @return string
*/
public function ruri_string()
{
- return '/'.implode('/', $this->rsegment_array());
+ global $RTR;
+
+ if (($dir = $RTR->fetch_directory()) === '/')
+ {
+ $dir = '';
+ }
+
+ return $dir.implode('/', $this->rsegment_array());
}
}
/* End of file URI.php */
-/* Location: ./system/core/URI.php */
+/* Location: ./system/core/URI.php */ \ No newline at end of file
diff --git a/system/core/Utf8.php b/system/core/Utf8.php
index ba3567453..5bc2dd5c9 100644
--- a/system/core/Utf8.php
+++ b/system/core/Utf8.php
@@ -1,4 +1,4 @@
-<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');
+<?php
/**
* CodeIgniter
*
@@ -24,8 +24,7 @@
* @since Version 2.0
* @filesource
*/
-
-// ------------------------------------------------------------------------
+defined('BASEPATH') OR exit('No direct script access allowed');
/**
* Utf8 Class
@@ -41,38 +40,40 @@
class CI_Utf8 {
/**
- * Constructor
+ * Class constructor
+ *
+ * Determines if UTF-8 support is to be enabled.
*
- * Determines if UTF-8 support is to be enabled
+ * @return void
*/
public function __construct()
{
log_message('debug', 'Utf8 Class Initialized');
- global $CFG;
+ $charset = strtoupper(config_item('charset'));
+
+ // set internal encoding for multibyte string functions if necessary
+ // and set a flag so we don't have to repeatedly use extension_loaded()
+ // or function_exists()
+ if (extension_loaded('mbstring'))
+ {
+ define('MB_ENABLED', TRUE);
+ mb_internal_encoding($charset);
+ }
+ else
+ {
+ define('MB_ENABLED', FALSE);
+ }
if (
- @preg_match('/./u', 'é') === 1 // PCRE must support UTF-8
- && function_exists('iconv') // iconv must be installed
- && @ini_get('mbstring.func_overload') != 1 // Multibyte string function overloading cannot be enabled
- && $CFG->item('charset') === 'UTF-8' // Application charset must be UTF-8
+ @preg_match('/./u', 'é') === 1 // PCRE must support UTF-8
+ && function_exists('iconv') // iconv must be installed
+ && MB_ENABLED === TRUE // mbstring must be enabled
+ && $charset === 'UTF-8' // Application charset must be UTF-8
)
{
define('UTF8_ENABLED', TRUE);
log_message('debug', 'UTF-8 Support Enabled');
-
- // set internal encoding for multibyte string functions if necessary
- // and set a flag so we don't have to repeatedly use extension_loaded()
- // or function_exists()
- if (extension_loaded('mbstring'))
- {
- define('MB_ENABLED', TRUE);
- mb_internal_encoding('UTF-8');
- }
- else
- {
- define('MB_ENABLED', FALSE);
- }
}
else
{
@@ -86,9 +87,11 @@ class CI_Utf8 {
/**
* Clean UTF-8 strings
*
- * Ensures strings are UTF-8
+ * Ensures strings contain only valid UTF-8 characters.
*
- * @param string
+ * @uses CI_Utf8::_is_ascii() Decide whether a conversion is needed
+ *
+ * @param string $str String to clean
* @return string
*/
public function clean_string($str)
@@ -108,9 +111,9 @@ class CI_Utf8 {
*
* Removes all ASCII control characters except horizontal tabs,
* line feeds, and carriage returns, as all others can cause
- * problems in XML
+ * problems in XML.
*
- * @param string
+ * @param string $str String to clean
* @return string
*/
public function safe_ascii_for_xml($str)
@@ -123,11 +126,11 @@ class CI_Utf8 {
/**
* Convert to UTF-8
*
- * Attempts to convert a string to UTF-8
+ * Attempts to convert a string to UTF-8.
*
- * @param string
- * @param string - input encoding
- * @return string
+ * @param string $str Input string
+ * @param string $encoding Input encoding
+ * @return string $str encoded in UTF-8 or FALSE on failure
*/
public function convert_to_utf8($str, $encoding)
{
@@ -135,7 +138,7 @@ class CI_Utf8 {
{
return @iconv($encoding, 'UTF-8', $str);
}
- elseif (function_exists('mb_convert_encoding'))
+ elseif (MB_ENABLED === TRUE)
{
return @mb_convert_encoding($str, 'UTF-8', $encoding);
}
@@ -148,9 +151,9 @@ class CI_Utf8 {
/**
* Is ASCII?
*
- * Tests if a string is standard 7-bit ASCII or not
+ * Tests if a string is standard 7-bit ASCII or not.
*
- * @param string
+ * @param string $str String to check
* @return bool
*/
protected function _is_ascii($str)
@@ -161,4 +164,4 @@ class CI_Utf8 {
}
/* End of file Utf8.php */
-/* Location: ./system/core/Utf8.php */
+/* Location: ./system/core/Utf8.php */ \ No newline at end of file
diff --git a/system/database/DB.php b/system/database/DB.php
index 0d81e40d3..f4062fa73 100755..100644
--- a/system/database/DB.php
+++ b/system/database/DB.php
@@ -1,4 +1,4 @@
-<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');
+<?php
/**
* CodeIgniter
*
@@ -24,17 +24,20 @@
* @since Version 1.0
* @filesource
*/
+defined('BASEPATH') OR exit('No direct script access allowed');
/**
* Initialize the database
*
* @category Database
- * @author EllisLab Dev Team
- * @link http://codeigniter.com/user_guide/database/
- * @param string
- * @param bool Determines if active record should be used or not
+ * @author EllisLab Dev Team
+ * @link http://codeigniter.com/user_guide/database/
+ *
+ * @param string|string[] $params
+ * @param bool $query_builder_override
+ * Determines if query builder should be used or not
*/
-function &DB($params = '', $active_record_override = NULL)
+function &DB($params = '', $query_builder_override = NULL)
{
// Load the DB config file if a DSN string wasn't passed
if (is_string($params) && strpos($params, '://') === FALSE)
@@ -47,13 +50,28 @@ function &DB($params = '', $active_record_override = NULL)
}
include($file_path);
+ // Make packages contain database config files
+ foreach (get_instance()->load->get_package_paths() as $path)
+ {
+ if ($path !== APPPATH)
+ {
+ if (file_exists($file_path = $path.'config/'.ENVIRONMENT.'/database.php'))
+ {
+ include($file_path);
+ }
+ elseif (file_exists($file_path = $path.'config/database.php'))
+ {
+ include($file_path);
+ }
+ }
+ }
if ( ! isset($db) OR count($db) === 0)
{
show_error('No database connection settings were found in the database config file.');
}
- if ($params != '')
+ if ($params !== '')
{
$active_group = $params;
}
@@ -67,12 +85,12 @@ function &DB($params = '', $active_record_override = NULL)
}
elseif (is_string($params))
{
-
- /* parse the URL from the DSN string
- * Database settings can be passed as discreet
- * parameters or as a data source name in the first
- * parameter. DSNs must have this prototype:
- * $dsn = 'driver://username:password@hostname/database';
+ /**
+ * Parse the URL from the DSN string
+ * Database settings can be passed as discreet
+ * parameters or as a data source name in the first
+ * parameter. DSNs must have this prototype:
+ * $dsn = 'driver://username:password@hostname/database';
*/
if (($dsn = @parse_url($params)) === FALSE)
{
@@ -88,7 +106,7 @@ function &DB($params = '', $active_record_override = NULL)
'database' => isset($dsn['path']) ? rawurldecode(substr($dsn['path'], 1)) : ''
);
- // were additional config items set?
+ // Were additional config items set?
if (isset($dsn['query']))
{
parse_str($dsn['query'], $extra);
@@ -106,38 +124,59 @@ function &DB($params = '', $active_record_override = NULL)
}
// No DB specified yet? Beat them senseless...
- if ( ! isset($params['dbdriver']) OR $params['dbdriver'] == '')
+ if (empty($params['dbdriver']))
{
show_error('You have not selected a database type to connect to.');
}
- // Load the DB classes. Note: Since the active record class is optional
+ // Load the DB classes. Note: Since the query builder class is optional
// we need to dynamically create a class that extends proper parent class
- // based on whether we're using the active record class or not.
- if ($active_record_override !== NULL)
+ // based on whether we're using the query builder class or not.
+ if ($query_builder_override !== NULL)
{
- $active_record = $active_record_override;
+ $query_builder = $query_builder_override;
+ }
+ // Backwards compatibility work-around for keeping the
+ // $active_record config variable working. Should be
+ // removed in v3.1
+ elseif ( ! isset($query_builder) && isset($active_record))
+ {
+ $query_builder = $active_record;
}
require_once(BASEPATH.'database/DB_driver.php');
- if ( ! isset($active_record) OR $active_record == TRUE)
+ if ( ! isset($query_builder) OR $query_builder === TRUE)
{
- require_once(BASEPATH.'database/DB_active_rec.php');
+ require_once(BASEPATH.'database/DB_query_builder.php');
if ( ! class_exists('CI_DB'))
{
- class CI_DB extends CI_DB_active_record { }
+ /**
+ * CI_DB
+ *
+ * Acts as an alias for both CI_DB_driver and CI_DB_query_builder.
+ *
+ * @see CI_DB_query_builder
+ * @see CI_DB_driver
+ */
+ class CI_DB extends CI_DB_query_builder { }
}
}
elseif ( ! class_exists('CI_DB'))
{
+ /**
+ * @ignore
+ */
class CI_DB extends CI_DB_driver { }
}
// Load the DB driver
$driver_file = BASEPATH.'database/drivers/'.$params['dbdriver'].'/'.$params['dbdriver'].'_driver.php';
- if ( ! file_exists($driver_file)) show_error('Invalid DB driver');
+ if ( ! file_exists($driver_file))
+ {
+ show_error('Invalid DB driver');
+ }
require_once($driver_file);
@@ -145,12 +184,25 @@ function &DB($params = '', $active_record_override = NULL)
$driver = 'CI_DB_'.$params['dbdriver'].'_driver';
$DB = new $driver($params);
- if ($DB->autoinit == TRUE)
+ // Check for a subdriver
+ if ( ! empty($DB->subdriver))
+ {
+ $driver_file = BASEPATH.'database/drivers/'.$DB->dbdriver.'/subdrivers/'.$DB->dbdriver.'_'.$DB->subdriver.'_driver.php';
+
+ if (file_exists($driver_file))
+ {
+ require_once($driver_file);
+ $driver = 'CI_DB_'.$DB->dbdriver.'_'.$DB->subdriver.'_driver';
+ $DB = new $driver($params);
+ }
+ }
+
+ if ($DB->autoinit === TRUE)
{
$DB->initialize();
}
- if (isset($params['stricton']) && $params['stricton'] == TRUE)
+ if ( ! empty($params['stricton']))
{
$DB->query('SET SESSION sql_mode="STRICT_ALL_TABLES"');
}
diff --git a/system/database/DB_cache.php b/system/database/DB_cache.php
index ff942856b..fd01dc2d8 100644
--- a/system/database/DB_cache.php
+++ b/system/database/DB_cache.php
@@ -1,4 +1,4 @@
-<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');
+<?php
/**
* CodeIgniter
*
@@ -24,6 +24,7 @@
* @since Version 1.0
* @filesource
*/
+defined('BASEPATH') OR exit('No direct script access allowed');
/**
* Database Cache Class
@@ -34,15 +35,39 @@
*/
class CI_DB_Cache {
+ /**
+ * CI Singleton
+ *
+ * @var object
+ */
public $CI;
- public $db; // allows passing of db object so that multiple database connections and returned db objects can be supported
+ /**
+ * Database object
+ *
+ * Allows passing of DB object so that multiple database connections
+ * and returned DB objects can be supported.
+ *
+ * @var object
+ */
+ public $db;
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Constructor
+ *
+ * @param object &$db
+ * @return void
+ */
public function __construct(&$db)
{
// Assign the main CI object to $this->CI and load the file helper since we use it a lot
$this->CI =& get_instance();
$this->db =& $db;
$this->CI->load->helper('file');
+
+ $this->check_path();
}
// --------------------------------------------------------------------
@@ -50,14 +75,14 @@ class CI_DB_Cache {
/**
* Set Cache Directory Path
*
- * @param string the path to the cache directory
+ * @param string $path Path to the cache directory
* @return bool
*/
public function check_path($path = '')
{
- if ($path == '')
+ if ($path === '')
{
- if ($this->db->cachedir == '')
+ if ($this->db->cachedir === '')
{
return $this->db->cache_off();
}
@@ -66,14 +91,26 @@ class CI_DB_Cache {
}
// Add a trailing slash to the path if needed
- $path = preg_replace('/(.+?)\/*$/', '\\1/', $path);
+ $path = realpath($path)
+ ? rtrim(realpath($path), DIRECTORY_SEPARATOR).DIRECTORY_SEPARATOR
+ : rtrim($path, '/').'/';
- if ( ! is_dir($path) OR ! is_really_writable($path))
+ if ( ! is_dir($path))
{
+ log_message('debug', 'DB cache path error: '.$path);
+
// If the path is wrong we'll turn off caching
return $this->db->cache_off();
}
+ if ( ! is_really_writable($path))
+ {
+ log_message('debug', 'DB cache dir not writable: '.$path);
+
+ // If the path is not really writable we'll turn off caching
+ return $this->db->cache_off();
+ }
+
$this->db->cachedir = $path;
return TRUE;
}
@@ -84,22 +121,18 @@ class CI_DB_Cache {
* Retrieve a cached query
*
* The URI being requested will become the name of the cache sub-folder.
- * An MD5 hash of the SQL statement will become the cache file name
+ * An MD5 hash of the SQL statement will become the cache file name.
*
+ * @param string $sql
* @return string
*/
public function read($sql)
{
- if ( ! $this->check_path())
- {
- return $this->db->cache_off();
- }
-
$segment_one = ($this->CI->uri->segment(1) == FALSE) ? 'default' : $this->CI->uri->segment(1);
$segment_two = ($this->CI->uri->segment(2) == FALSE) ? 'index' : $this->CI->uri->segment(2);
$filepath = $this->db->cachedir.$segment_one.'+'.$segment_two.'/'.md5($sql);
- if (FALSE === ($cachedata = read_file($filepath)))
+ if (FALSE === ($cachedata = @file_get_contents($filepath)))
{
return FALSE;
}
@@ -112,15 +145,12 @@ class CI_DB_Cache {
/**
* Write a query to a cache file
*
+ * @param string $sql
+ * @param object $object
* @return bool
*/
public function write($sql, $object)
{
- if ( ! $this->check_path())
- {
- return $this->db->cache_off();
- }
-
$segment_one = ($this->CI->uri->segment(1) == FALSE) ? 'default' : $this->CI->uri->segment(1);
$segment_two = ($this->CI->uri->segment(2) == FALSE) ? 'index' : $this->CI->uri->segment(2);
$dir_path = $this->db->cachedir.$segment_one.'+'.$segment_two.'/';
@@ -150,16 +180,18 @@ class CI_DB_Cache {
/**
* Delete cache files within a particular directory
*
- * @return bool
+ * @param string $segment_one
+ * @param string $segment_two
+ * @return void
*/
public function delete($segment_one = '', $segment_two = '')
{
- if ($segment_one == '')
+ if ($segment_one === '')
{
$segment_one = ($this->CI->uri->segment(1) == FALSE) ? 'default' : $this->CI->uri->segment(1);
}
- if ($segment_two == '')
+ if ($segment_two === '')
{
$segment_two = ($this->CI->uri->segment(2) == FALSE) ? 'index' : $this->CI->uri->segment(2);
}
@@ -173,11 +205,11 @@ class CI_DB_Cache {
/**
* Delete all existing cache files
*
- * @return bool
+ * @return void
*/
public function delete_all()
{
- delete_files($this->db->cachedir, TRUE, 0, TRUE);
+ delete_files($this->db->cachedir, TRUE, TRUE);
}
}
diff --git a/system/database/DB_driver.php b/system/database/DB_driver.php
index 61b05d52b..2d5b91541 100644
--- a/system/database/DB_driver.php
+++ b/system/database/DB_driver.php
@@ -1,4 +1,4 @@
-<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');
+<?php
/**
* CodeIgniter
*
@@ -24,6 +24,7 @@
* @since Version 1.0
* @filesource
*/
+defined('BASEPATH') OR exit('No direct script access allowed');
/**
* Database Driver Class
@@ -40,43 +41,316 @@
*/
abstract class CI_DB_driver {
+ /**
+ * Data Source Name / Connect string
+ *
+ * @var string
+ */
public $dsn;
+
+ /**
+ * Username
+ *
+ * @var string
+ */
public $username;
+
+ /**
+ * Password
+ *
+ * @var string
+ */
public $password;
+
+ /**
+ * Hostname
+ *
+ * @var string
+ */
public $hostname;
+
+ /**
+ * Database name
+ *
+ * @var string
+ */
public $database;
- public $dbdriver = 'mysql';
+
+ /**
+ * Database driver
+ *
+ * @var string
+ */
+ public $dbdriver = 'mysqli';
+
+ /**
+ * Sub-driver
+ *
+ * @used-by CI_DB_pdo_driver
+ * @var string
+ */
+ public $subdriver;
+
+ /**
+ * Table prefix
+ *
+ * @var string
+ */
public $dbprefix = '';
+
+ /**
+ * Character set
+ *
+ * @var string
+ */
public $char_set = 'utf8';
+
+ /**
+ * Collation
+ *
+ * @var string
+ */
public $dbcollat = 'utf8_general_ci';
- public $autoinit = TRUE; // Whether to automatically initialize the DB
+
+ /**
+ * Auto-init flag
+ *
+ * Whether to automatically initialize the DB connection.
+ *
+ * @var bool
+ */
+ public $autoinit = TRUE;
+
+ /**
+ * Encryption flag/data
+ *
+ * @var mixed
+ */
+ public $encrypt = FALSE;
+
+ /**
+ * Swap Prefix
+ *
+ * @var string
+ */
public $swap_pre = '';
+
+ /**
+ * Database port
+ *
+ * @var int
+ */
public $port = '';
+
+ /**
+ * Persistent connection flag
+ *
+ * @var bool
+ */
public $pconnect = FALSE;
+
+ /**
+ * Connection ID
+ *
+ * @var object|resource
+ */
public $conn_id = FALSE;
+
+ /**
+ * Result ID
+ *
+ * @var object|resource
+ */
public $result_id = FALSE;
+
+ /**
+ * Debug flag
+ *
+ * Whether to display error messages.
+ *
+ * @var bool
+ */
public $db_debug = FALSE;
+
+ /**
+ * Benchmark time
+ *
+ * @var int
+ */
public $benchmark = 0;
+
+ /**
+ * Executed queries count
+ *
+ * @var int
+ */
public $query_count = 0;
+
+ /**
+ * Bind marker
+ *
+ * Character used to identify values in a prepared statement.
+ *
+ * @var string
+ */
public $bind_marker = '?';
+
+ /**
+ * Save queries flag
+ *
+ * Whether to keep an in-memory history of queries for debugging purposes.
+ *
+ * @var bool
+ */
public $save_queries = TRUE;
+
+ /**
+ * Queries list
+ *
+ * @see CI_DB_driver::$save_queries
+ * @var string[]
+ */
public $queries = array();
+
+ /**
+ * Query times
+ *
+ * A list of times that queries took to execute.
+ *
+ * @var array
+ */
public $query_times = array();
+
+ /**
+ * Data cache
+ *
+ * An internal generic value cache.
+ *
+ * @var array
+ */
public $data_cache = array();
+ /**
+ * Transaction enabled flag
+ *
+ * @var bool
+ */
public $trans_enabled = TRUE;
+
+ /**
+ * Strict transaction mode flag
+ *
+ * @var bool
+ */
public $trans_strict = TRUE;
+
+ /**
+ * Transaction depth level
+ *
+ * @var int
+ */
protected $_trans_depth = 0;
- protected $_trans_status = TRUE; // Used with transactions to determine if a rollback should occur
+ /**
+ * Transaction status flag
+ *
+ * Used with transactions to determine if a rollback should occur.
+ *
+ * @var bool
+ */
+ protected $_trans_status = TRUE;
+
+ /**
+ * Cache On flag
+ *
+ * @var bool
+ */
public $cache_on = FALSE;
+
+ /**
+ * Cache directory path
+ *
+ * @var bool
+ */
public $cachedir = '';
+
+ /**
+ * Cache auto-delete flag
+ *
+ * @var bool
+ */
public $cache_autodel = FALSE;
- public $CACHE; // The cache class object
+ /**
+ * DB Cache object
+ *
+ * @see CI_DB_cache
+ * @var object
+ */
+ public $CACHE;
+
+ /**
+ * Protect identifiers flag
+ *
+ * @var bool
+ */
protected $_protect_identifiers = TRUE;
- protected $_reserved_identifiers = array('*'); // Identifiers that should NOT be escaped
+ /**
+ * List of reserved identifiers
+ *
+ * Identifiers that must NOT be escaped.
+ *
+ * @var string[]
+ */
+ protected $_reserved_identifiers = array('*');
+
+ /**
+ * Identifier escape character
+ *
+ * @var string
+ */
+ protected $_escape_char = '"';
+
+ /**
+ * ESCAPE statement string
+ *
+ * @var string
+ */
+ protected $_like_escape_str = " ESCAPE '%s' ";
+
+ /**
+ * ESCAPE character
+ *
+ * @var string
+ */
+ protected $_like_escape_chr = '!';
+
+ /**
+ * ORDER BY random keyword
+ *
+ * @var array
+ */
+ protected $_random_keyword = array('RAND()', 'RAND(%d)');
+
+ /**
+ * COUNT string
+ *
+ * @used-by CI_DB_driver::count_all()
+ * @used-by CI_DB_query_builder::count_all_results()
+ *
+ * @var string
+ */
+ protected $_count_string = 'SELECT COUNT(*) AS ';
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Class constructor
+ *
+ * @param array $params
+ * @return void
+ */
public function __construct($params)
{
if (is_array($params))
@@ -113,7 +387,7 @@ abstract class CI_DB_driver {
// ----------------------------------------------------------------
// Connect to the database and set the connection ID
- $this->conn_id = ($this->pconnect == FALSE) ? $this->db_connect() : $this->db_pconnect();
+ $this->conn_id = ($this->pconnect === FALSE) ? $this->db_connect() : $this->db_pconnect();
// No connection resource? Check if there is a failover else throw an error
if ( ! $this->conn_id)
@@ -131,7 +405,7 @@ abstract class CI_DB_driver {
}
// Try to connect
- $this->conn_id = ($this->pconnect == FALSE) ? $this->db_connect() : $this->db_pconnect();
+ $this->conn_id = ($this->pconnect === FALSE) ? $this->db_connect() : $this->db_pconnect();
// If a connection is made break the foreach loop
if ($this->conn_id)
@@ -291,21 +565,26 @@ abstract class CI_DB_driver {
* FALSE upon failure, and if the $db_debug variable is set to TRUE
* will raise an error.
*
- * @param string An SQL query string
- * @param array An array of binding data
+ * @param string $sql
+ * @param array $binds = FALSE An array of binding data
+ * @param bool $return_object = NULL
* @return mixed
*/
- public function query($sql, $binds = FALSE, $return_object = TRUE)
+ public function query($sql, $binds = FALSE, $return_object = NULL)
{
- if ($sql == '')
+ if ($sql === '')
{
log_message('error', 'Invalid query: '.$sql);
return ($this->db_debug) ? $this->display_error('db_invalid_query') : FALSE;
}
+ elseif ( ! is_bool($return_object))
+ {
+ $return_object = ! $this->is_write_type($sql);
+ }
// Verify table prefix and replace if necessary
- if ($this->dbprefix != '' && $this->swap_pre != '' && $this->dbprefix != $this->swap_pre)
+ if ($this->dbprefix !== '' && $this->swap_pre !== '' && $this->dbprefix !== $this->swap_pre)
{
$sql = preg_replace('/(\W)'.$this->swap_pre.'(\S+?)/', '\\1'.$this->dbprefix.'\\2', $sql);
}
@@ -319,7 +598,7 @@ abstract class CI_DB_driver {
// Is query caching enabled? If the query is a "read type"
// we will load the caching class and return the previously
// cached query if it exists
- if ($this->cache_on == TRUE && stripos($sql, 'SELECT') !== FALSE && $this->_cache_init())
+ if ($this->cache_on === TRUE && $return_object === TRUE && $this->_cache_init())
{
$this->load_rdriver();
if (FALSE !== ($cache = $this->CACHE->read($sql)))
@@ -328,19 +607,19 @@ abstract class CI_DB_driver {
}
}
- // Save the query for debugging
- if ($this->save_queries == TRUE)
+ // Save the query for debugging
+ if ($this->save_queries === TRUE)
{
$this->queries[] = $sql;
}
// Start the Query Timer
- $time_start = list($sm, $ss) = explode(' ', microtime());
+ $time_start = microtime(TRUE);
// Run the Query
if (FALSE === ($this->result_id = $this->simple_query($sql)))
{
- if ($this->save_queries == TRUE)
+ if ($this->save_queries === TRUE)
{
$this->query_times[] = 0;
}
@@ -352,7 +631,7 @@ abstract class CI_DB_driver {
$error = $this->error();
// Log errors
- log_message('error', 'Query error: '.$error['message']);
+ log_message('error', 'Query error: '.$error['message'].' - Invalid query: '.$sql);
if ($this->db_debug)
{
@@ -370,24 +649,22 @@ abstract class CI_DB_driver {
}
// Stop and aggregate the query time results
- $time_end = list($em, $es) = explode(' ', microtime());
- $this->benchmark += ($em + $es) - ($sm + $ss);
+ $time_end = microtime(TRUE);
+ $this->benchmark += $time_end - $time_start;
- if ($this->save_queries == TRUE)
+ if ($this->save_queries === TRUE)
{
- $this->query_times[] = ($em + $es) - ($sm + $ss);
+ $this->query_times[] = $time_end - $time_start;
}
// Increment the query counter
$this->query_count++;
- // Was the query a "write" type?
- // If so we'll simply return true
- if ($this->is_write_type($sql) === TRUE)
+ // Will we have a result object instantiated? If not - we'll simply return TRUE
+ if ($return_object !== TRUE)
{
- // If caching is enabled we'll auto-cleanup any
- // existing files related to this particular URI
- if ($this->cache_on == TRUE && $this->cache_autodel == TRUE && $this->_cache_init())
+ // If caching is enabled we'll auto-cleanup any existing files related to this particular URI
+ if ($this->cache_on === TRUE && $this->cache_autodel === TRUE && $this->_cache_init())
{
$this->CACHE->delete();
}
@@ -396,8 +673,6 @@ abstract class CI_DB_driver {
}
// Return TRUE if we don't need to create a result object
- // Currently only the Oracle driver uses this when stored
- // procedures are used
if ($return_object !== TRUE)
{
return TRUE;
@@ -409,7 +684,7 @@ abstract class CI_DB_driver {
// Is query caching enabled? If so, we'll serialize the
// result object and save it to a cache file.
- if ($this->cache_on == TRUE && $this->_cache_init())
+ if ($this->cache_on === TRUE && $this->_cache_init())
{
// We'll create a new instance of the result object
// only without the platform specific driver since
@@ -417,7 +692,7 @@ abstract class CI_DB_driver {
// resource ID won't be any good once we've cached the
// result object, so we'll have to compile the data
// and save it)
- $CR = new CI_DB_result();
+ $CR = new CI_DB_result($this);
$CR->result_object = $RES->result_object();
$CR->result_array = $RES->result_array();
$CR->num_rows = $RES->num_rows();
@@ -495,6 +770,7 @@ abstract class CI_DB_driver {
* If strict mode is disabled, each group is treated autonomously, meaning
* a failure of one group will not affect any others
*
+ * @param bool $mode = TRUE
* @return void
*/
public function trans_strict($mode = TRUE)
@@ -507,6 +783,7 @@ abstract class CI_DB_driver {
/**
* Start Transaction
*
+ * @param bool $test_mode = FALSE
* @return void
*/
public function trans_start($test_mode = FALSE)
@@ -596,35 +873,53 @@ abstract class CI_DB_driver {
*/
public function compile_binds($sql, $binds)
{
- if (strpos($sql, $this->bind_marker) === FALSE)
+ if (empty($binds) OR empty($this->bind_marker) OR strpos($sql, $this->bind_marker) === FALSE)
{
return $sql;
}
-
- if ( ! is_array($binds))
+ elseif ( ! is_array($binds))
{
$binds = array($binds);
+ $bind_count = 1;
+ }
+ else
+ {
+ // Make sure we're using numeric keys
+ $binds = array_values($binds);
+ $bind_count = count($binds);
}
- // Get the sql segments around the bind markers
- $segments = explode($this->bind_marker, $sql);
+ // We'll need the marker length later
+ $ml = strlen($this->bind_marker);
- // The count of bind should be 1 less then the count of segments
- // If there are more bind arguments trim it down
- if (count($binds) >= count($segments))
+ // Make sure not to replace a chunk inside a string that happens to match the bind marker
+ if ($c = preg_match_all("/'[^']*'/i", $sql, $matches))
{
- $binds = array_slice($binds, 0, count($segments)-1);
+ $c = preg_match_all('/'.preg_quote($this->bind_marker, '/').'/i',
+ str_replace($matches[0],
+ str_replace($this->bind_marker, str_repeat(' ', $ml), $matches[0]),
+ $sql, $c),
+ $matches, PREG_OFFSET_CAPTURE);
+
+ // Bind values' count must match the count of markers in the query
+ if ($bind_count !== $c)
+ {
+ return $sql;
+ }
+ }
+ elseif (($c = preg_match_all('/'.preg_quote($this->bind_marker, '/').'/i', $sql, $matches, PREG_OFFSET_CAPTURE)) !== $bind_count)
+ {
+ return $sql;
}
- // Construct the binded query
- $result = $segments[0];
- $i = 0;
- foreach ($binds as $bind)
+ do
{
- $result .= $this->escape($bind).$segments[++$i];
+ $c--;
+ $sql = substr_replace($sql, $this->escape($binds[$c]), $matches[0][$c][1], $ml);
}
+ while ($c !== 0);
- return $result;
+ return $sql;
}
// --------------------------------------------------------------------
@@ -637,7 +932,7 @@ abstract class CI_DB_driver {
*/
public function is_write_type($sql)
{
- return (bool) preg_match('/^\s*"?(SET|INSERT|UPDATE|DELETE|REPLACE|CREATE|DROP|TRUNCATE|LOAD DATA|COPY|ALTER|RENAME|GRANT|REVOKE|LOCK|UNLOCK|REINDEX)\s+/i', $sql);
+ return (bool) preg_match('/^\s*"?(SET|INSERT|UPDATE|DELETE|REPLACE|CREATE|DROP|TRUNCATE|LOAD|COPY|ALTER|RENAME|GRANT|REVOKE|LOCK|UNLOCK|REINDEX)\s+/i', $sql);
}
// --------------------------------------------------------------------
@@ -690,7 +985,7 @@ abstract class CI_DB_driver {
*/
public function escape($str)
{
- if (is_string($str) OR method_exists($str, '__toString'))
+ if (is_string($str) OR (is_object($str) && method_exists($str, '__toString')))
{
return "'".$this->escape_str($str)."'";
}
@@ -742,8 +1037,38 @@ abstract class CI_DB_driver {
// --------------------------------------------------------------------
/**
+ * "Count All" query
+ *
+ * Generates a platform-specific query string that counts all records in
+ * the specified database
+ *
+ * @param string
+ * @return int
+ */
+ public function count_all($table = '')
+ {
+ if ($table === '')
+ {
+ return 0;
+ }
+
+ $query = $this->query($this->_count_string.$this->escape_identifiers('numrows').' FROM '.$this->protect_identifiers($table, TRUE, NULL, FALSE));
+ if ($query->num_rows() === 0)
+ {
+ return 0;
+ }
+
+ $query = $query->row();
+ $this->_reset_select();
+ return (int) $query->numrows;
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
* Returns an array of table names
*
+ * @param string $constrain_by_prefix = FALSE
* @return array
*/
public function list_tables($constrain_by_prefix = FALSE)
@@ -798,6 +1123,7 @@ abstract class CI_DB_driver {
/**
* Determine if a particular table exists
*
+ * @param string $table_name
* @return bool
*/
public function table_exists($table_name)
@@ -808,7 +1134,7 @@ abstract class CI_DB_driver {
// --------------------------------------------------------------------
/**
- * Fetch MySQL Field Names
+ * Fetch Field Names
*
* @param string the table name
* @return array
@@ -821,7 +1147,7 @@ abstract class CI_DB_driver {
return $this->data_cache['field_names'][$table];
}
- if ($table == '')
+ if ($table === '')
{
return ($this->db_debug) ? $this->display_error('db_field_param_missing') : FALSE;
}
@@ -889,7 +1215,7 @@ abstract class CI_DB_driver {
*/
public function field_data($table = '')
{
- if ($table == '')
+ if ($table === '')
{
return ($this->db_debug) ? $this->display_error('db_field_param_missing') : FALSE;
}
@@ -905,34 +1231,57 @@ abstract class CI_DB_driver {
*
* This function escapes column and table names
*
- * @param string
- * @return string
+ * @param mixed
+ * @return mixed
*/
public function escape_identifiers($item)
{
- if ($this->_escape_char == '')
+ if ($this->_escape_char === '' OR empty($item) OR in_array($item, $this->_reserved_identifiers))
{
return $item;
}
-
- foreach ($this->_reserved_identifiers as $id)
+ elseif (is_array($item))
{
- if (strpos($item, '.'.$id) !== FALSE)
+ foreach ($item as $key => $value)
{
- $item = str_replace('.', $this->_escape_char.'.', $item);
+ $item[$key] = $this->escape_identifiers($value);
+ }
+
+ return $item;
+ }
+ // Avoid breaking functions and literal values inside queries
+ elseif (ctype_digit($item) OR $item[0] === "'" OR ($this->_escape_char !== '"' && $item[0] === '"') OR strpos($item, '(') !== FALSE)
+ {
+ return $item;
+ }
- // remove duplicates if the user already included the escape
- return preg_replace('/['.$this->_escape_char.']+/', $this->_escape_char, $this->_escape_char.$item);
+ static $preg_ec = array();
+
+ if (empty($preg_ec))
+ {
+ if (is_array($this->_escape_char))
+ {
+ $preg_ec = array(
+ preg_quote($this->_escape_char[0], '/'), preg_quote($this->_escape_char[1], '/'),
+ $this->_escape_char[0], $this->_escape_char[1]
+ );
+ }
+ else
+ {
+ $preg_ec[0] = $preg_ec[1] = preg_quote($this->_escape_char, '/');
+ $preg_ec[2] = $preg_ec[3] = $this->_escape_char;
}
}
- if (strpos($item, '.') !== FALSE)
+ foreach ($this->_reserved_identifiers as $id)
{
- $item = str_replace('.', $this->_escape_char.'.'.$this->_escape_char, $item);
+ if (strpos($item, '.'.$id) !== FALSE)
+ {
+ return preg_replace('/'.$preg_ec[0].'?([^'.$preg_ec[1].'\.]+)'.$preg_ec[1].'?\./i', $preg_ec[2].'$1'.$preg_ec[3].'.', $item);
+ }
}
- // remove duplicates if the user already included the escape
- return preg_replace('/['.$this->_escape_char.']+/', $this->_escape_char, $this->_escape_char.$item.$this->_escape_char);
+ return preg_replace('/'.$preg_ec[0].'?([^'.$preg_ec[1].'\.]+)'.$preg_ec[1].'?(\.)?/i', $preg_ec[2].'$1'.$preg_ec[3].'$2', $item);
}
// --------------------------------------------------------------------
@@ -960,6 +1309,23 @@ abstract class CI_DB_driver {
// --------------------------------------------------------------------
/**
+ * Insert statement
+ *
+ * Generates a platform-specific insert string from the supplied data
+ *
+ * @param string the table name
+ * @param array the insert keys
+ * @param array the insert values
+ * @return string
+ */
+ protected function _insert($table, $keys, $values)
+ {
+ return 'INSERT INTO '.$table.' ('.implode(', ', $keys).') VALUES ('.implode(', ', $values).')';
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
* Generate an update string
*
* @param string the table upon which the query will be performed
@@ -969,44 +1335,44 @@ abstract class CI_DB_driver {
*/
public function update_string($table, $data, $where)
{
- if ($where == '')
+ if (empty($where))
{
return FALSE;
}
+ $this->where($where);
+
$fields = array();
foreach ($data as $key => $val)
{
$fields[$this->protect_identifiers($key)] = $this->escape($val);
}
- if ( ! is_array($where))
- {
- $dest = array($where);
- }
- else
- {
- $dest = array();
- foreach ($where as $key => $val)
- {
- $prefix = (count($dest) == 0) ? '' : ' AND ';
- $key = $this->protect_identifiers($key);
-
- if ($val !== '')
- {
- if ( ! $this->_has_operator($key))
- {
- $key .= ' =';
- }
+ return $this->_update($this->protect_identifiers($table, TRUE, NULL, FALSE), $fields);
+ }
- $val = ' '.$this->escape($val);
- }
+ // --------------------------------------------------------------------
- $dest[] = $prefix.$key.$val;
- }
+ /**
+ * Update statement
+ *
+ * Generates a platform-specific update string from the supplied data
+ *
+ * @param string the table name
+ * @param array the update data
+ * @return string
+ */
+ protected function _update($table, $values)
+ {
+ foreach ($values as $key => $val)
+ {
+ $valstr[] = $key.' = '.$val;
}
- return $this->_update($this->protect_identifiers($table, TRUE, NULL, FALSE), $fields, $dest);
+ return 'UPDATE '.$table.' SET '.implode(', ', $valstr)
+ .$this->_compile_wh('qb_where')
+ .$this->_compile_order_by()
+ .($this->qb_limit ? ' LIMIT '.$this->qb_limit : '');
}
// --------------------------------------------------------------------
@@ -1019,7 +1385,43 @@ abstract class CI_DB_driver {
*/
protected function _has_operator($str)
{
- return (bool) preg_match('/(\s|<|>|!|=|IS NULL|IS NOT NULL)/i', trim($str));
+ return (bool) preg_match('/(<|>|!|=|\sIS NULL|\sIS NOT NULL|\sBETWEEN|\sLIKE|\sIN\s*\(|\s)/i', trim($str));
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Returns the SQL string operator
+ *
+ * @param string
+ * @return string
+ */
+ protected function _get_operator($str)
+ {
+ static $_operators;
+
+ if (empty($_operators))
+ {
+ $_les = ($this->_like_escape_str !== '')
+ ? '\s+'.preg_quote(trim(sprintf($this->_like_escape_str, $this->_like_escape_chr)), '/')
+ : '';
+ $_operators = array(
+ '\s*(?:<|>|!)?=\s*', // =, <=, >=, !=
+ '\s*<>?\s*', // <, <>
+ '\s*>\s*', // >
+ '\s+IS NULL', // IS NULL
+ '\s+IS NOT NULL', // IS NOT NULL
+ '\s+BETWEEN\s+\S+\s+AND\s+\S+', // BETWEEN value AND value
+ '\s+IN\s*\([^\)]+\)', // IN(list)
+ '\s+NOT IN\s*\([^\)]+\)', // NOT IN (list)
+ '\s+LIKE\s+\S+'.$_les, // LIKE 'expr'[ ESCAPE '%s']
+ '\s+NOT LIKE\s+\S+'.$_les // NOT LIKE 'expr'[ ESCAPE '%s']
+ );
+
+ }
+
+ return preg_match('/'.implode('|', $_operators).'/i', $str, $match)
+ ? $match[0] : FALSE;
}
// --------------------------------------------------------------------
@@ -1027,13 +1429,12 @@ abstract class CI_DB_driver {
/**
* Enables a native PHP function to be run, using a platform agnostic wrapper.
*
- * @param string the function name
- * @param mixed any parameters needed by the function
+ * @param string $function Function name
* @return mixed
*/
public function call_function($function)
{
- $driver = ($this->dbdriver == 'postgre') ? 'pg_' : $this->dbdriver.'_';
+ $driver = ($this->dbdriver === 'postgre') ? 'pg_' : $this->dbdriver.'_';
if (FALSE === strpos($driver, $function))
{
@@ -1087,12 +1488,13 @@ abstract class CI_DB_driver {
return $this->cache_on = FALSE;
}
-
// --------------------------------------------------------------------
/**
* Delete the cache files associated with a particular URI
*
+ * @param string $segment_one = ''
+ * @param string $segment_two = ''
* @return bool
*/
public function cache_delete($segment_one = '', $segment_two = '')
@@ -1152,7 +1554,7 @@ abstract class CI_DB_driver {
{
if ($this->conn_id)
{
- $this->_close($this->conn_id);
+ $this->_close();
$this->conn_id = FALSE;
}
}
@@ -1160,6 +1562,20 @@ abstract class CI_DB_driver {
// --------------------------------------------------------------------
/**
+ * Close DB Connection
+ *
+ * This method would be overriden by most of the drivers.
+ *
+ * @return void
+ */
+ protected function _close()
+ {
+ $this->conn_id = FALSE;
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
* Display an error message
*
* @param string the error message
@@ -1174,13 +1590,13 @@ abstract class CI_DB_driver {
$heading = $LANG->line('db_error_heading');
- if ($native == TRUE)
+ if ($native === TRUE)
{
$message = (array) $error;
}
else
{
- $message = ( ! is_array($error)) ? array(str_replace('%s', $swap, $LANG->line($error))) : $error;
+ $message = is_array($error) ? $error : array(str_replace('%s', $swap, $LANG->line($error)));
}
// Find the most likely culprit of the error by going through
@@ -1189,12 +1605,21 @@ abstract class CI_DB_driver {
$trace = debug_backtrace();
foreach ($trace as $call)
{
- if (isset($call['file']) && strpos($call['file'], BASEPATH.'database') === FALSE)
+ if (isset($call['file'], $call['class']))
{
- // Found it - use a relative path for safety
- $message[] = 'Filename: '.str_replace(array(BASEPATH, APPPATH), '', $call['file']);
- $message[] = 'Line Number: '.$call['line'];
- break;
+ // We'll need this on Windows, as APPPATH and BASEPATH will always use forward slashes
+ if (DIRECTORY_SEPARATOR !== '/')
+ {
+ $call['file'] = str_replace('\\', '/', $call['file']);
+ }
+
+ if (strpos($call['file'], BASEPATH.'database') === FALSE && strpos($call['class'], 'Loader') === FALSE)
+ {
+ // Found it - use a relative path for safety
+ $message[] = 'Filename: '.str_replace(array(APPPATH, BASEPATH), '', $call['file']);
+ $message[] = 'Line Number: '.$call['line'];
+ break;
+ }
}
}
@@ -1208,7 +1633,7 @@ abstract class CI_DB_driver {
/**
* Protect Identifiers
*
- * This function is used extensively by the Active Record class, and by
+ * This function is used extensively by the Query Builder class, and by
* a couple functions in this class.
* It takes a column or table name (optionally with an alias) and inserts
* the table prefix onto it. Some logic is necessary in order to deal with
@@ -1243,34 +1668,43 @@ abstract class CI_DB_driver {
$escaped_array = array();
foreach ($item as $k => $v)
{
- $escaped_array[$this->protect_identifiers($k)] = $this->protect_identifiers($v);
+ $escaped_array[$this->protect_identifiers($k)] = $this->protect_identifiers($v, $prefix_single, $protect_identifiers, $field_exists);
}
return $escaped_array;
}
+ // This is basically a bug fix for queries that use MAX, MIN, etc.
+ // If a parenthesis is found we know that we do not need to
+ // escape the data or add a prefix. There's probably a more graceful
+ // way to deal with this, but I'm not thinking of it -- Rick
+ if (strpos($item, '(') !== FALSE)
+ {
+ return $item;
+ }
+
// Convert tabs or multiple spaces into single spaces
- $item = preg_replace('/[\t ]+/', ' ', $item);
+ $item = preg_replace('/\s+/', ' ', $item);
// If the item has an alias declaration we remove it and set it aside.
- // Basically we remove everything to the right of the first space
- if (strpos($item, ' ') !== FALSE)
+ // Note: strripos() is used in order to support spaces in table names
+ if ($offset = strripos($item, ' AS '))
{
- $alias = strstr($item, ' ');
- $item = substr($item, 0, - strlen($alias));
+ $alias = ($protect_identifiers)
+ ? substr($item, $offset, 4).$this->escape_identifiers(substr($item, $offset + 4))
+ : substr($item, $offset);
+ $item = substr($item, 0, $offset);
}
- else
+ elseif ($offset = strrpos($item, ' '))
{
- $alias = '';
+ $alias = ($protect_identifiers)
+ ? ' '.$this->escape_identifiers(substr($item, $offset + 1))
+ : substr($item, $offset);
+ $item = substr($item, 0, $offset);
}
-
- // This is basically a bug fix for queries that use MAX, MIN, etc.
- // If a parenthesis is found we know that we do not need to
- // escape the data or add a prefix. There's probably a more graceful
- // way to deal with this, but I'm not thinking of it -- Rick
- if (strpos($item, '(') !== FALSE)
+ else
{
- return $item.$alias;
+ $alias = '';
}
// Break the string apart if it contains periods, then insert the table prefix
@@ -1283,7 +1717,7 @@ abstract class CI_DB_driver {
// Does the first segment of the exploded item match
// one of the aliases previously identified? If so,
// we have nothing more to do other than escape the item
- if (in_array($parts[0], $this->ar_aliased_tables))
+ if (in_array($parts[0], $this->qb_aliased_tables))
{
if ($protect_identifiers === TRUE)
{
@@ -1302,7 +1736,7 @@ abstract class CI_DB_driver {
}
// Is there a table prefix defined in the config file? If not, no need to do anything
- if ($this->dbprefix != '')
+ if ($this->dbprefix !== '')
{
// We now add the table prefix based on some logic.
// Do we have 4 segments (hostname.database.table.column)?
@@ -1326,13 +1760,13 @@ abstract class CI_DB_driver {
// This flag is set when the supplied $item does not contain a field name.
// This can happen when this function is being called from a JOIN.
- if ($field_exists == FALSE)
+ if ($field_exists === FALSE)
{
$i++;
}
// Verify table prefix and replace if necessary
- if ($this->swap_pre != '' && strpos($parts[$i], $this->swap_pre) === 0)
+ if ($this->swap_pre !== '' && strpos($parts[$i], $this->swap_pre) === 0)
{
$parts[$i] = preg_replace('/^'.$this->swap_pre.'(\S+?)/', $this->dbprefix.'\\1', $parts[$i]);
}
@@ -1355,15 +1789,15 @@ abstract class CI_DB_driver {
}
// Is there a table prefix? If not, no need to insert it
- if ($this->dbprefix != '')
+ if ($this->dbprefix !== '')
{
// Verify table prefix and replace if necessary
- if ($this->swap_pre != '' && strpos($item, $this->swap_pre) === 0)
+ if ($this->swap_pre !== '' && strpos($item, $this->swap_pre) === 0)
{
$item = preg_replace('/^'.$this->swap_pre.'(\S+?)/', $this->dbprefix.'\\1', $item);
}
// Do we prefix an item with no segments?
- elseif ($prefix_single == TRUE && strpos($item, $this->dbprefix) !== 0)
+ elseif ($prefix_single === TRUE && strpos($item, $this->dbprefix) !== 0)
{
$item = $this->dbprefix.$item;
}
@@ -1380,9 +1814,8 @@ abstract class CI_DB_driver {
// --------------------------------------------------------------------
/**
- * Dummy method that allows Active Record class to be disabled
- *
- * This function is used extensively by every db driver.
+ * Dummy method that allows Query Builder class to be disabled
+ * and keep count_all() working.
*
* @return void
*/
diff --git a/system/database/DB_forge.php b/system/database/DB_forge.php
index a519575f0..59c3baf8b 100644
--- a/system/database/DB_forge.php
+++ b/system/database/DB_forge.php
@@ -1,4 +1,4 @@
-<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');
+<?php
/**
* CodeIgniter
*
@@ -24,6 +24,7 @@
* @since Version 1.0
* @filesource
*/
+defined('BASEPATH') OR exit('No direct script access allowed');
/**
* Database Forge Class
@@ -34,22 +35,127 @@
*/
abstract class CI_DB_forge {
+ /**
+ * Database object
+ *
+ * @var object
+ */
+ protected $db;
+
+ /**
+ * Fields data
+ *
+ * @var array
+ */
public $fields = array();
+
+ /**
+ * Keys data
+ *
+ * @var array
+ */
public $keys = array();
+
+ /**
+ * Primary Keys data
+ *
+ * @var array
+ */
public $primary_keys = array();
- public $db_char_set = '';
- // Platform specific SQL strings
+ /**
+ * Database character set
+ *
+ * @var string
+ */
+ public $db_char_set = '';
+
+ // --------------------------------------------------------------------
+
+ /**
+ * CREATE DATABASE statement
+ *
+ * @var string
+ */
protected $_create_database = 'CREATE DATABASE %s';
+
+ /**
+ * DROP DATABASE statement
+ *
+ * @var string
+ */
protected $_drop_database = 'DROP DATABASE %s';
- protected $_drop_table = 'DROP TABLE IF EXISTS %s';
- protected $_rename_table = 'ALTER TABLE %s RENAME TO %s';
- public function __construct()
+ /**
+ * CREATE TABLE statement
+ *
+ * @var string
+ */
+ protected $_create_table = "%s %s (%s\n)";
+
+ /**
+ * CREATE TABLE IF statement
+ *
+ * @var string
+ */
+ protected $_create_table_if = 'CREATE TABLE IF NOT EXISTS';
+
+ /**
+ * CREATE TABLE keys flag
+ *
+ * Whether table keys are created from within the
+ * CREATE TABLE statement.
+ *
+ * @var bool
+ */
+ protected $_create_table_keys = FALSE;
+
+ /**
+ * DROP TABLE IF EXISTS statement
+ *
+ * @var string
+ */
+ protected $_drop_table_if = 'DROP TABLE IF EXISTS';
+
+ /**
+ * RENAME TABLE statement
+ *
+ * @var string
+ */
+ protected $_rename_table = 'ALTER TABLE %s RENAME TO %s;';
+
+ /**
+ * UNSIGNED support
+ *
+ * @var bool|array
+ */
+ protected $_unsigned = TRUE;
+
+ /**
+ * NULL value representatin in CREATE/ALTER TABLE statements
+ *
+ * @var string
+ */
+ protected $_null = '';
+
+ /**
+ * DEFAULT value representation in CREATE/ALTER TABLE statements
+ *
+ * @var string
+ */
+ protected $_default = ' DEFAULT ';
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Class constructor
+ *
+ * @param object &$db Database object
+ * @return void
+ */
+ public function __construct(&$db)
{
- // Assign the main database object to $this->db
- $CI =& get_instance();
- $this->db =& $CI->db;
+ $this->db =& $db;
log_message('debug', 'Database Forge Class Initialized');
}
@@ -58,20 +164,25 @@ abstract class CI_DB_forge {
/**
* Create database
*
- * @param string the database name
+ * @param string $db_name
* @return bool
*/
public function create_database($db_name)
{
if ($this->_create_database === FALSE)
{
- return ($this->db->db_debug) ? $this->db->display_error('db_unsuported_feature') : FALSE;
+ return ($this->db->db_debug) ? $this->db->display_error('db_unsupported_feature') : FALSE;
}
elseif ( ! $this->db->query(sprintf($this->_create_database, $db_name, $this->db->char_set, $this->db->dbcollat)))
{
return ($this->db->db_debug) ? $this->db->display_error('db_unable_to_drop') : FALSE;
}
+ if ( ! empty($this->db->data_cache['db_names']))
+ {
+ $this->db->data_cache['db_names'][] = $db_name;
+ }
+
return TRUE;
}
@@ -80,25 +191,34 @@ abstract class CI_DB_forge {
/**
* Drop database
*
- * @param string the database name
+ * @param string $db_name
* @return bool
*/
public function drop_database($db_name)
{
- if ($db_name == '')
+ if ($db_name === '')
{
show_error('A table name is required for that operation.');
return FALSE;
}
elseif ($this->_drop_database === FALSE)
{
- return ($this->db->db_debug) ? $this->db->display_error('db_unsuported_feature') : FALSE;
+ return ($this->db->db_debug) ? $this->db->display_error('db_unsupported_feature') : FALSE;
}
elseif ( ! $this->db->query(sprintf($this->_drop_database, $db_name)))
{
return ($this->db->db_debug) ? $this->db->display_error('db_unable_to_drop') : FALSE;
}
+ if ( ! empty($this->db->data_cache['db_names']))
+ {
+ $key = array_search(strtolower($db_name), array_map('strtolower', $this->db->data_cache['db_names']), TRUE);
+ if ($key !== FALSE)
+ {
+ unset($this->db->data_cache['db_names'][$key]);
+ }
+ }
+
return TRUE;
}
@@ -107,25 +227,25 @@ abstract class CI_DB_forge {
/**
* Add Key
*
- * @param string key
- * @param string type
+ * @param string $key
+ * @param bool $primary
* @return object
*/
public function add_key($key = '', $primary = FALSE)
{
- if (is_array($key))
+ if (empty($key))
+ {
+ show_error('Key information is required for that operation.');
+ }
+
+ if ($primary === TRUE && is_array($key))
{
foreach ($key as $one)
{
$this->add_key($one, $primary);
}
- return;
- }
-
- if ($key == '')
- {
- show_error('Key information is required for that operation.');
+ return $this;
}
if ($primary === TRUE)
@@ -145,12 +265,12 @@ abstract class CI_DB_forge {
/**
* Add Field
*
- * @param string collation
+ * @param array $field
* @return object
*/
public function add_field($field = '')
{
- if ($field == '')
+ if (empty($field))
{
show_error('Field information is required.');
}
@@ -192,24 +312,107 @@ abstract class CI_DB_forge {
/**
* Create Table
*
- * @param string the table name
+ * @param string $table Table name
+ * @param bool $if_not_exists Whether to add IF NOT EXISTS condition
* @return bool
*/
public function create_table($table = '', $if_not_exists = FALSE)
{
- if ($table == '')
+ if ($table === '')
{
show_error('A table name is required for that operation.');
}
+ else
+ {
+ $table = $this->db->dbprefix.$table;
+ }
if (count($this->fields) === 0)
{
show_error('Field information is required.');
}
- $sql = $this->_create_table($this->db->dbprefix.$table, $this->fields, $this->primary_keys, $this->keys, $if_not_exists);
+ $sql = $this->_create_table($table, $if_not_exists);
+
+ if (is_bool($sql))
+ {
+ $this->_reset();
+ if ($sql === FALSE)
+ {
+ return ($this->db->db_debug) ? $this->db->display_error('db_unsupported_feature') : FALSE;
+ }
+ }
+
+ if (($result = $this->db->query($sql)) !== FALSE)
+ {
+ empty($this->db->data_cache['table_names']) OR $this->db->data_cache['table_names'][] = $table;
+
+ // Most databases don't support creating indexes from within the CREATE TABLE statement
+ if ( ! empty($this->keys))
+ {
+ for ($i = 0, $sqls = $this->_process_indexes($table), $c = count($sqls); $i < $c; $i++)
+ {
+ $this->db->query($sqls[$i]);
+ }
+ }
+ }
+
$this->_reset();
- return is_bool($sql) ? $sql : $this->db->query($sql);
+ return $result;
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Create Table
+ *
+ * @param string $table Table name
+ * @param bool $if_not_exists Whether to add 'IF NOT EXISTS' condition
+ * @return mixed
+ */
+ protected function _create_table($table, $if_not_exists)
+ {
+ if ($if_not_exists === TRUE && $this->_create_table_if === FALSE)
+ {
+ if ($this->db->table_exists($table))
+ {
+ return TRUE;
+ }
+ else
+ {
+ $if_not_exists = FALSE;
+ }
+ }
+
+ $sql = ($if_not_exists)
+ ? sprintf($this->_create_table_if, $this->db->escape_identifiers($table))
+ : 'CREATE TABLE';
+
+ $columns = $this->_process_fields(TRUE);
+ for ($i = 0, $c = count($columns); $i < $c; $i++)
+ {
+ $columns[$i] = ($columns[$i]['_literal'] !== FALSE)
+ ? "\n\t".$columns[$i]['_literal']
+ : "\n\t".$this->_process_column($columns[$i]);
+ }
+
+ $columns = implode(',', $columns)
+ .$this->_process_primary_keys($table);
+
+ // Are indexes created from within the CREATE TABLE statement? (e.g. in MySQL)
+ if ($this->_create_table_keys === TRUE)
+ {
+ $columns .= $this->_process_indexes($table);
+ }
+
+ // _create_table will usually have the following format: "%s %s (%s\n)"
+ $sql = sprintf($this->_create_table.';',
+ $sql,
+ $this->db->escape_identifiers($table),
+ $columns
+ );
+
+ return $sql;
}
// --------------------------------------------------------------------
@@ -217,21 +420,73 @@ abstract class CI_DB_forge {
/**
* Drop Table
*
- * @param string the table name
+ * @param string $table_name Table name
+ * @param bool $if_exists Whether to add an IF EXISTS condition
* @return bool
*/
- public function drop_table($table_name)
+ public function drop_table($table_name, $if_exists = FALSE)
{
- if ($table_name == '')
+ if ($table_name === '')
{
return ($this->db->db_debug) ? $this->db->display_error('db_table_name_required') : FALSE;
}
- elseif ($this->_drop_table === FALSE)
+
+ $query = $this->_drop_table($this->db->dbprefix.$table_name, $if_exists);
+ if ($query === FALSE)
+ {
+ return ($this->db->db_debug) ? $this->db->display_error('db_unsupported_feature') : FALSE;
+ }
+ elseif ($query === TRUE)
+ {
+ return TRUE;
+ }
+
+ $query = $this->db->query($query);
+
+ // Update table list cache
+ if ($query && ! empty($this->db->data_cache['table_names']))
+ {
+ $key = array_search(strtolower($this->db->dbprefix.$table_name), array_map('strtolower', $this->db->data_cache['table_names']), TRUE);
+ if ($key !== FALSE)
+ {
+ unset($this->db->data_cache['table_names'][$key]);
+ }
+ }
+
+ return $query;
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Drop Table
+ *
+ * Generates a platform-specific DROP TABLE string
+ *
+ * @param string $table Table name
+ * @param bool $if_exists Whether to add an IF EXISTS condition
+ * @return string
+ */
+ protected function _drop_table($table, $if_exists)
+ {
+ $sql = 'DROP TABLE';
+
+ if ($if_exists)
{
- return ($this->db->db_debug) ? $this->db->display_error('db_unsuported_feature') : FALSE;
+ if ($this->_drop_table_if === FALSE)
+ {
+ if ( ! $this->db->table_exists($table))
+ {
+ return TRUE;
+ }
+ }
+ else
+ {
+ $sql = sprintf($this->_drop_table_if, $this->db->escape_identifiers($table));
+ }
}
- return $this->db->query(sprintf($this->_drop_table, $this->db->escape_identifiers($this->db->dbprefix.$table_name)));
+ return $sql.' '.$this->db->escape_identifiers($table);
}
// --------------------------------------------------------------------
@@ -239,26 +494,37 @@ abstract class CI_DB_forge {
/**
* Rename Table
*
- * @param string the old table name
- * @param string the new table name
+ * @param string $table_name Old table name
+ * @param string $new_table_name New table name
* @return bool
*/
public function rename_table($table_name, $new_table_name)
{
- if ($table_name == '' OR $new_table_name == '')
+ if ($table_name === '' OR $new_table_name === '')
{
show_error('A table name is required for that operation.');
return FALSE;
}
elseif ($this->_rename_table === FALSE)
{
- return ($this->db->db_debug) ? $this->db->display_error('db_unsuported_feature') : FALSE;
+ return ($this->db->db_debug) ? $this->db->display_error('db_unsupported_feature') : FALSE;
}
- return $this->db->query(sprintf($this->_rename_table,
+ $result = $this->db->query(sprintf($this->_rename_table,
$this->db->escape_identifiers($this->db->dbprefix.$table_name),
$this->db->escape_identifiers($this->db->dbprefix.$new_table_name))
);
+
+ if ($result && ! empty($this->db->data_cache['table_names']))
+ {
+ $key = array_search(strtolower($this->db->dbprefix.$table_name), array_map('strtolower', $this->db->data_cache['table_names']), TRUE);
+ if ($key !== FALSE)
+ {
+ $this->db->data_cache['table_names'][$key] = $this->db->dbprefix.$new_table_name;
+ }
+ }
+
+ return $result;
}
// --------------------------------------------------------------------
@@ -266,33 +532,46 @@ abstract class CI_DB_forge {
/**
* Column Add
*
- * @param string the table name
- * @param string the column name
- * @param string the column definition
+ * @todo Remove deprecated $_after option in 3.1+
+ * @param string $table Table name
+ * @param array $field Column definition
+ * @param string $_after Column for AFTER clause (deprecated)
* @return bool
*/
- public function add_column($table = '', $field = array(), $after_field = '')
+ public function add_column($table = '', $field = array(), $_after = NULL)
{
- if ($table == '')
+ if ($table === '')
{
show_error('A table name is required for that operation.');
}
- // add field info into field array, but we can only do one at a time
- // so we cycle through
- foreach (array_keys($field) as $k)
+ // Work-around for literal column definitions
+ if ( ! is_array($field))
{
- $this->add_field(array($k => $field[$k]));
+ $field = array($field);
+ }
- if (count($this->fields) == 0)
+ foreach (array_keys($field) as $k)
+ {
+ // Backwards-compatibility work-around for MySQL/CUBRID AFTER clause (remove in 3.1+)
+ if ($_after !== NULL && is_array($field[$k]) && ! isset($field[$k]['after']))
{
- show_error('Field information is required.');
+ $field[$k]['after'] = $_after;
}
- $sql = $this->_alter_table('ADD', $this->db->dbprefix.$table, $this->fields, $after_field);
- $this->_reset();
+ $this->add_field(array($k => $field[$k]));
+ }
- if ($this->db->query($sql) === FALSE)
+ $sqls = $this->_alter_table('ADD', $this->db->dbprefix.$table, $this->_process_fields());
+ $this->_reset();
+ if ($sqls === FALSE)
+ {
+ return ($this->db->db_debug) ? $this->db->display_error('db_unsupported_feature') : FALSE;
+ }
+
+ for ($i = 0, $c = count($sqls); $i < $c; $i++)
+ {
+ if ($this->db->query($sqls[$i]) === FALSE)
{
return FALSE;
}
@@ -306,23 +585,29 @@ abstract class CI_DB_forge {
/**
* Column Drop
*
- * @param string the table name
- * @param string the column name
+ * @param string $table Table name
+ * @param string $column_name Column name
* @return bool
*/
public function drop_column($table = '', $column_name = '')
{
- if ($table == '')
+ if ($table === '')
{
show_error('A table name is required for that operation.');
}
- if ($column_name == '')
+ if ($column_name === '')
{
show_error('A column name is required for that operation.');
}
- return $this->db->query($this->_alter_table('DROP', $this->db->dbprefix.$table, $column_name));
+ $sql = $this->_alter_table('DROP', $this->db->dbprefix.$table, $column_name);
+ if ($sql === FALSE)
+ {
+ return ($this->db->db_debug) ? $this->db->display_error('db_unsupported_feature') : FALSE;
+ }
+
+ return $this->db->query($sql);
}
// --------------------------------------------------------------------
@@ -330,44 +615,385 @@ abstract class CI_DB_forge {
/**
* Column Modify
*
- * @param string the table name
- * @param string the column name
- * @param string the column definition
+ * @param string $table Table name
+ * @param string $field Column definition
* @return bool
*/
public function modify_column($table = '', $field = array())
{
- if ($table == '')
+ if ($table === '')
{
show_error('A table name is required for that operation.');
}
- // add field info into field array, but we can only do one at a time
- // so we cycle through
+ // Work-around for literal column definitions
+ if ( ! is_array($field))
+ {
+ $field = array($field);
+ }
+
foreach (array_keys($field) as $k)
{
- // If no name provided, use the current name
- if ( ! isset($field[$k]['name']))
+ $this->add_field(array($k => $field[$k]));
+ }
+
+ if (count($this->fields) === 0)
+ {
+ show_error('Field information is required.');
+ }
+
+ $sqls = $this->_alter_table('CHANGE', $this->db->dbprefix.$table, $this->_process_fields());
+ $this->_reset();
+ if ($sqls === FALSE)
+ {
+ return ($this->db->db_debug) ? $this->db->display_error('db_unsupported_feature') : FALSE;
+ }
+
+ for ($i = 0, $c = count($sqls); $i < $c; $i++)
+ {
+ if ($this->db->query($sqls[$i]) === FALSE)
{
- $field[$k]['name'] = $k;
+ return FALSE;
}
+ }
- $this->add_field(array($k => $field[$k]));
- if (count($this->fields) === 0)
+ return TRUE;
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * ALTER TABLE
+ *
+ * @param string $alter_type ALTER type
+ * @param string $table Table name
+ * @param mixed $field Column definition
+ * @return string|string[]
+ */
+ protected function _alter_table($alter_type, $table, $field)
+ {
+ $sql = 'ALTER TABLE '.$this->db->escape_identifiers($table).' ';
+
+ // DROP has everything it needs now.
+ if ($alter_type === 'DROP')
+ {
+ return $sql.'DROP COLUMN '.$this->db->escape_identifiers($field);
+ }
+
+ $sqls = array();
+ for ($i = 0, $c = count($field), $sql .= $alter_type.' COLUMN '; $i < $c; $i++)
+ {
+ $sqls[] = $sql
+ .($field[$i]['_literal'] !== FALSE ? $field[$i]['_literal'] : $this->_process_column($field[$i]));
+ }
+
+ return $sqls;
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Process fields
+ *
+ * @param bool $create_table
+ * @return array
+ */
+ protected function _process_fields($create_table = FALSE)
+ {
+ $fields = array();
+
+ foreach ($this->fields as $key => $attributes)
+ {
+ if (is_int($key) && ! is_array($attributes))
{
- show_error('Field information is required.');
+ $fields[] = array('_literal' => $attributes);
+ continue;
}
- $sql = $this->_alter_table('CHANGE', $this->db->dbprefix.$table, $this->fields);
- $this->_reset();
+ $attributes = array_change_key_case($attributes, CASE_UPPER);
- if ($this->db->query($sql) === FALSE)
+ if ($create_table === TRUE && empty($attributes['TYPE']))
{
- return FALSE;
+ continue;
}
+
+ if (isset($attributes['TYPE']))
+ {
+ $this->_attr_type($attributes);
+ $this->_attr_unsigned($attributes, $field);
+ }
+
+ $field = array(
+ 'name' => $key,
+ 'new_name' => isset($attributes['NAME']) ? $attributes['NAME'] : NULL,
+ 'type' => isset($attributes['TYPE']) ? $attributes['TYPE'] : NULL,
+ 'length' => '',
+ 'unsigned' => '',
+ 'null' => '',
+ 'unique' => '',
+ 'default' => '',
+ 'auto_increment' => '',
+ '_literal' => FALSE
+ );
+
+ $this->_attr_default($attributes, $field);
+
+ if (isset($attributes['NULL']))
+ {
+ if ($attributes['NULL'] === TRUE)
+ {
+ $field['null'] = empty($this->_null) ? '' : ' '.$this->_null;
+ }
+ elseif ($create_table === TRUE)
+ {
+ $field['null'] = ' NOT NULL';
+ }
+ }
+
+ $this->_attr_auto_increment($attributes, $field);
+ $this->_attr_unique($attributes, $field);
+
+ if (isset($attributes['TYPE']) && ! empty($attributes['CONSTRAINT']))
+ {
+ switch (strtoupper($attributes['TYPE']))
+ {
+ case 'ENUM':
+ case 'SET':
+ $attributes['CONSTRAINT'] = $this->db->escape($attributes['CONSTRAINT']);
+ default:
+ $field['length'] = is_array($attributes['CONSTRAINT'])
+ ? "('".implode("','", $attributes['CONSTRAINT'])."')"
+ : '('.$attributes['CONSTRAINT'].')';
+ break;
+ }
+ }
+
+ $fields[] = $field;
}
- return TRUE;
+ return $fields;
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Process column
+ *
+ * @param array $field
+ * @return string
+ */
+ protected function _process_column($field)
+ {
+ return $this->db->escape_identifiers($field['name'])
+ .' '.$field['type'].$field['length']
+ .$field['unsigned']
+ .$field['default']
+ .$field['null']
+ .$field['auto_increment']
+ .$field['unique'];
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Field attribute TYPE
+ *
+ * Performs a data type mapping between different databases.
+ *
+ * @param array &$attributes
+ * @return void
+ */
+ protected function _attr_type(&$attributes)
+ {
+ // Usually overriden by drivers
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Field attribute UNSIGNED
+ *
+ * Depending on the _unsigned property value:
+ *
+ * - TRUE will always set $field['unsigned'] to 'UNSIGNED'
+ * - FALSE will always set $field['unsigned'] to ''
+ * - array(TYPE) will set $field['unsigned'] to 'UNSIGNED',
+ * if $attributes['TYPE'] is found in the array
+ * - array(TYPE => UTYPE) will change $field['type'],
+ * from TYPE to UTYPE in case of a match
+ *
+ * @param array &$attributes
+ * @param array &$field
+ * @return void
+ */
+ protected function _attr_unsigned(&$attributes, &$field)
+ {
+ if (empty($attributes['UNSIGNED']) OR $attributes['UNSIGNED'] !== TRUE)
+ {
+ return;
+ }
+
+ // Reset the attribute in order to avoid issues if we do type conversion
+ $attributes['UNSIGNED'] = FALSE;
+
+ if (is_array($this->_unsigned))
+ {
+ foreach (array_keys($this->_unsigned) as $key)
+ {
+ if (is_int($key) && strcasecmp($attributes['TYPE'], $this->_unsigned[$key]) === 0)
+ {
+ $field['unsigned'] = ' UNSIGNED';
+ return;
+ }
+ elseif (is_string($key) && strcasecmp($attributes['TYPE'], $key) === 0)
+ {
+ $field['type'] = $key;
+ return;
+ }
+ }
+
+ return;
+ }
+
+ $field['unsigned'] = ($this->_unsigned === TRUE) ? ' UNSIGNED' : '';
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Field attribute DEFAULT
+ *
+ * @param array &$attributes
+ * @param array &$field
+ * @return void
+ */
+ protected function _attr_default(&$attributes, &$field)
+ {
+ if ($this->_default === FALSE)
+ {
+ return;
+ }
+
+ if (array_key_exists('DEFAULT', $attributes))
+ {
+ if ($attributes['DEFAULT'] === NULL)
+ {
+ $field['default'] = empty($this->_null) ? '' : $this->_default.$this->_null;
+
+ // Override the NULL attribute if that's our default
+ $attributes['NULL'] = NULL;
+ $field['null'] = empty($this->_null) ? '' : ' '.$this->_null;
+ }
+ else
+ {
+ $field['default'] = $this->_default.$this->db->escape($attributes['DEFAULT']);
+ }
+ }
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Field attribute UNIQUE
+ *
+ * @param array &$attributes
+ * @param array &$field
+ * @return void
+ */
+ protected function _attr_unique(&$attributes, &$field)
+ {
+ if ( ! empty($attributes['UNIQUE']) && $attributes['UNIQUE'] === TRUE)
+ {
+ $field['unique'] = ' UNIQUE';
+ }
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Field attribute AUTO_INCREMENT
+ *
+ * @param array &$attributes
+ * @param array &$field
+ * @return void
+ */
+ protected function _attr_auto_increment(&$attributes, &$field)
+ {
+ if ( ! empty($attributes['AUTO_INCREMENT']) && $attributes['AUTO_INCREMENT'] === TRUE && stripos($field['type'], 'int') !== FALSE)
+ {
+ $field['auto_increment'] = ' AUTO_INCREMENT';
+ }
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Process primary keys
+ *
+ * @param string $table Table name
+ * @return string
+ */
+ protected function _process_primary_keys($table)
+ {
+ $sql = '';
+
+ for ($i = 0, $c = count($this->primary_keys); $i < $c; $i++)
+ {
+ if ( ! isset($this->fields[$this->primary_keys[$i]]))
+ {
+ unset($this->primary_keys[$i]);
+ }
+ }
+
+ if (count($this->primary_keys) > 0)
+ {
+ $sql .= ",\n\tCONSTRAINT ".$this->db->escape_identifiers('pk_'.$table)
+ .' PRIMARY KEY('.implode(', ', $this->db->escape_identifiers($this->primary_keys)).')';
+ }
+
+ return $sql;
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Process indexes
+ *
+ * @param string $table
+ * @return string
+ */
+ protected function _process_indexes($table)
+ {
+ $table = $this->db->escape_identifiers($table);
+ $sqls = array();
+
+ for ($i = 0, $c = count($this->keys); $i < $c; $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;
+ }
+
+ is_array($this->keys[$i]) OR $this->keys[$i] = array($this->keys[$i]);
+
+ $sqls[] = 'CREATE INDEX '.$this->db->escape_identifiers(implode('_', $this->keys[$i]))
+ .' ON '.$this->db->escape_identifiers($table)
+ .' ('.implode(', ', $this->db->escape_identifiers($this->keys[$i])).');';
+ }
+
+ return $sqls;
}
// --------------------------------------------------------------------
diff --git a/system/database/DB_active_rec.php b/system/database/DB_query_builder.php
index a5df7f31a..b0e86ed2c 100644
--- a/system/database/DB_active_rec.php
+++ b/system/database/DB_query_builder.php
@@ -1,4 +1,4 @@
-<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');
+<?php
/**
* CodeIgniter
*
@@ -24,11 +24,12 @@
* @since Version 1.0
* @filesource
*/
+defined('BASEPATH') OR exit('No direct script access allowed');
/**
- * Active Record Class
+ * Query Builder Class
*
- * This is the platform-independent base Active Record implementation class.
+ * This is the platform-independent base Query Builder implementation class.
*
* @package CodeIgniter
* @subpackage Drivers
@@ -36,46 +37,215 @@
* @author EllisLab Dev Team
* @link http://codeigniter.com/user_guide/database/
*/
-abstract class CI_DB_active_record extends CI_DB_driver {
+abstract class CI_DB_query_builder extends CI_DB_driver {
+
+ /**
+ * Return DELETE SQL flag
+ *
+ * @var bool
+ */
protected $return_delete_sql = FALSE;
+
+ /**
+ * Reset DELETE data flag
+ *
+ * @var bool
+ */
protected $reset_delete_data = FALSE;
- protected $ar_select = array();
- protected $ar_distinct = FALSE;
- protected $ar_from = array();
- protected $ar_join = array();
- protected $ar_where = array();
- protected $ar_like = array();
- protected $ar_groupby = array();
- protected $ar_having = array();
- protected $ar_keys = array();
- protected $ar_limit = FALSE;
- protected $ar_offset = FALSE;
- protected $ar_order = FALSE;
- protected $ar_orderby = array();
- protected $ar_set = array();
- protected $ar_wherein = array();
- protected $ar_aliased_tables = array();
- protected $ar_store_array = array();
- protected $ar_where_group_started = FALSE;
- protected $ar_where_group_count = 0;
-
- // Active Record Caching variables
- protected $ar_caching = FALSE;
- protected $ar_cache_exists = array();
- protected $ar_cache_select = array();
- protected $ar_cache_from = array();
- protected $ar_cache_join = array();
- protected $ar_cache_where = array();
- protected $ar_cache_like = array();
- protected $ar_cache_groupby = array();
- protected $ar_cache_having = array();
- protected $ar_cache_orderby = array();
- protected $ar_cache_set = array();
-
- protected $ar_no_escape = array();
- protected $ar_cache_no_escape = array();
+ /**
+ * QB SELECT data
+ *
+ * @var array
+ */
+ protected $qb_select = array();
+
+ /**
+ * QB DISTINCT flag
+ *
+ * @var bool
+ */
+ protected $qb_distinct = FALSE;
+
+ /**
+ * QB FROM data
+ *
+ * @var array
+ */
+ protected $qb_from = array();
+
+ /**
+ * QB JOIN data
+ *
+ * @var array
+ */
+ protected $qb_join = array();
+
+ /**
+ * QB WHERE data
+ *
+ * @var array
+ */
+ protected $qb_where = array();
+
+ /**
+ * QB GROUP BY data
+ *
+ * @var array
+ */
+ protected $qb_groupby = array();
+
+ /**
+ * QB HAVING data
+ *
+ * @var array
+ */
+ protected $qb_having = array();
+
+ /**
+ * QB keys
+ *
+ * @var array
+ */
+ protected $qb_keys = array();
+
+ /**
+ * QB LIMIT data
+ *
+ * @var int
+ */
+ protected $qb_limit = FALSE;
+
+ /**
+ * QB OFFSET data
+ *
+ * @var int
+ */
+ protected $qb_offset = FALSE;
+
+ /**
+ * QB ORDER BY data
+ *
+ * @var array
+ */
+ protected $qb_orderby = array();
+
+ /**
+ * QB data sets
+ *
+ * @var array
+ */
+ protected $qb_set = array();
+
+ /**
+ * QB aliased tables list
+ *
+ * @var array
+ */
+ protected $qb_aliased_tables = array();
+
+ /**
+ * QB WHERE group started flag
+ *
+ * @var bool
+ */
+ protected $qb_where_group_started = FALSE;
+
+ /**
+ * QB WHERE group count
+ *
+ * @var int
+ */
+ protected $qb_where_group_count = 0;
+
+ // Query Builder Caching variables
+
+ /**
+ * QB Caching flag
+ *
+ * @var bool
+ */
+ protected $qb_caching = FALSE;
+
+ /**
+ * QB Cache exists list
+ *
+ * @var array
+ */
+ protected $qb_cache_exists = array();
+
+ /**
+ * QB Cache SELECT data
+ *
+ * @var array
+ */
+ protected $qb_cache_select = array();
+
+ /**
+ * QB Cache FROM data
+ *
+ * @var array
+ */
+ protected $qb_cache_from = array();
+
+ /**
+ * QB Cache JOIN data
+ *
+ * @var array
+ */
+ protected $qb_cache_join = array();
+
+ /**
+ * QB Cache WHERE data
+ *
+ * @var array
+ */
+ protected $qb_cache_where = array();
+
+ /**
+ * QB Cache GROUP BY data
+ *
+ * @var array
+ */
+ protected $qb_cache_groupby = array();
+
+ /**
+ * QB Cache HAVING data
+ *
+ * @var array
+ */
+ protected $qb_cache_having = array();
+
+ /**
+ * QB Cache ORDER BY data
+ *
+ * @var array
+ */
+ protected $qb_cache_orderby = array();
+
+ /**
+ * QB Cache data sets
+ *
+ * @var array
+ */
+ protected $qb_cache_set = array();
+
+ /**
+ * QB No Escape data
+ *
+ * @var array
+ */
+ protected $qb_no_escape = array();
+
+ /**
+ * QB Cache No Escape data
+ *
+ * @var array
+ */
+ protected $qb_cache_no_escape = array();
+
+ // --------------------------------------------------------------------
/**
* Select
@@ -83,6 +253,7 @@ abstract class CI_DB_active_record extends CI_DB_driver {
* Generates the SELECT portion of the query
*
* @param string
+ * @param mixed
* @return object
*/
public function select($select = '*', $escape = NULL)
@@ -92,20 +263,23 @@ abstract class CI_DB_active_record extends CI_DB_driver {
$select = explode(',', $select);
}
+ // If the escape value was not set will will base it on the global setting
+ is_bool($escape) OR $escape = $this->_protect_identifiers;
+
foreach ($select as $val)
{
$val = trim($val);
- if ($val != '')
+ if ($val !== '')
{
- $this->ar_select[] = $val;
- $this->ar_no_escape[] = $escape;
+ $this->qb_select[] = $val;
+ $this->qb_no_escape[] = $escape;
- if ($this->ar_caching === TRUE)
+ if ($this->qb_caching === TRUE)
{
- $this->ar_cache_select[] = $val;
- $this->ar_cache_exists[] = 'select';
- $this->ar_cache_no_escape[] = $escape;
+ $this->qb_cache_select[] = $val;
+ $this->qb_cache_exists[] = 'select';
+ $this->qb_cache_no_escape[] = $escape;
}
}
}
@@ -180,20 +354,21 @@ abstract class CI_DB_active_record extends CI_DB_driver {
// --------------------------------------------------------------------
/**
- * Processing Function for the four functions above:
+ * SELECT [MAX|MIN|AVG|SUM]()
*
- * select_max()
- * select_min()
- * select_avg()
- * select_sum()
+ * @used-by select_max()
+ * @used-by select_min()
+ * @used-by select_avg()
+ * @used-by select_sum()
*
- * @param string the field
- * @param string an alias
+ * @param string $select Field name
+ * @param string $alias
+ * @param string $type
* @return object
*/
protected function _max_min_avg_sum($select = '', $alias = '', $type = 'MAX')
{
- if ( ! is_string($select) OR $select == '')
+ if ( ! is_string($select) OR $select === '')
{
$this->display_error('db_invalid_query');
}
@@ -205,19 +380,20 @@ abstract class CI_DB_active_record extends CI_DB_driver {
show_error('Invalid function type: '.$type);
}
- if ($alias == '')
+ if ($alias === '')
{
$alias = $this->_create_alias_from_table(trim($select));
}
- $sql = $this->protect_identifiers($type.'('.trim($select).')').' AS '.$this->protect_identifiers(trim($alias));
- $this->ar_select[] = $sql;
- $this->ar_no_escape[] = NULL;
+ $sql = $this->protect_identifiers($type.'('.trim($select).')').' AS '.$this->escape_identifiers(trim($alias));
- if ($this->ar_caching === TRUE)
+ $this->qb_select[] = $sql;
+ $this->qb_no_escape[] = NULL;
+
+ if ($this->qb_caching === TRUE)
{
- $this->ar_cache_select[] = $sql;
- $this->ar_cache_exists[] = 'select';
+ $this->qb_cache_select[] = $sql;
+ $this->qb_cache_exists[] = 'select';
}
return $this;
@@ -228,7 +404,7 @@ abstract class CI_DB_active_record extends CI_DB_driver {
/**
* Determines the alias name based on the table
*
- * @param string
+ * @param string $item
* @return string
*/
protected function _create_alias_from_table($item)
@@ -249,12 +425,12 @@ abstract class CI_DB_active_record extends CI_DB_driver {
*
* Sets a flag which tells the query string compiler to add DISTINCT
*
- * @param bool
+ * @param bool $val
* @return object
*/
public function distinct($val = TRUE)
{
- $this->ar_distinct = (is_bool($val)) ? $val : TRUE;
+ $this->qb_distinct = is_bool($val) ? $val : TRUE;
return $this;
}
@@ -265,12 +441,12 @@ abstract class CI_DB_active_record extends CI_DB_driver {
*
* Generates the FROM portion of the query
*
- * @param mixed can be a string or array
+ * @param mixed $from can be a string or array
* @return object
*/
public function from($from)
{
- foreach ((array)$from as $val)
+ foreach ((array) $from as $val)
{
if (strpos($val, ',') !== FALSE)
{
@@ -278,12 +454,13 @@ abstract class CI_DB_active_record extends CI_DB_driver {
{
$v = trim($v);
$this->_track_aliases($v);
- $v = $this->ar_from[] = $this->protect_identifiers($v, TRUE, NULL, FALSE);
- if ($this->ar_caching === TRUE)
+ $this->qb_from[] = $v = $this->protect_identifiers($v, TRUE, NULL, FALSE);
+
+ if ($this->qb_caching === TRUE)
{
- $this->ar_cache_from[] = $v;
- $this->ar_cache_exists[] = 'from';
+ $this->qb_cache_from[] = $v;
+ $this->qb_cache_exists[] = 'from';
}
}
}
@@ -292,14 +469,15 @@ abstract class CI_DB_active_record extends CI_DB_driver {
$val = trim($val);
// Extract any aliases that might exist. We use this information
- // in the _protect_identifiers to know whether to add a table prefix
+ // in the protect_identifiers to know whether to add a table prefix
$this->_track_aliases($val);
- $this->ar_from[] = $val = $this->protect_identifiers($val, TRUE, NULL, FALSE);
- if ($this->ar_caching === TRUE)
+ $this->qb_from[] = $val = $this->protect_identifiers($val, TRUE, NULL, FALSE);
+
+ if ($this->qb_caching === TRUE)
{
- $this->ar_cache_from[] = $val;
- $this->ar_cache_exists[] = 'from';
+ $this->qb_cache_from[] = $val;
+ $this->qb_cache_exists[] = 'from';
}
}
}
@@ -310,22 +488,23 @@ abstract class CI_DB_active_record extends CI_DB_driver {
// --------------------------------------------------------------------
/**
- * Join
+ * JOIN
*
* Generates the JOIN portion of the query
*
* @param string
* @param string the join condition
* @param string the type of join
+ * @param string whether not to try to escape identifiers
* @return object
*/
- public function join($table, $cond, $type = '')
+ public function join($table, $cond, $type = '', $escape = NULL)
{
- if ($type != '')
+ if ($type !== '')
{
$type = strtoupper(trim($type));
- if ( ! in_array($type, array('LEFT', 'RIGHT', 'OUTER', 'INNER', 'LEFT OUTER', 'RIGHT OUTER')))
+ if ( ! in_array($type, array('LEFT', 'RIGHT', 'OUTER', 'INNER', 'LEFT OUTER', 'RIGHT OUTER'), TRUE))
{
$type = '';
}
@@ -336,22 +515,59 @@ abstract class CI_DB_active_record extends CI_DB_driver {
}
// Extract any aliases that might exist. We use this information
- // in the _protect_identifiers to know whether to add a table prefix
+ // in the protect_identifiers to know whether to add a table prefix
$this->_track_aliases($table);
- // Strip apart the condition and protect the identifiers
- if (preg_match('/([\[\w\.]+)([\W\s]+)(.+)/', $cond, $match))
+ is_bool($escape) OR $escape = $this->_protect_identifiers;
+
+ // Split multiple conditions
+ if ($escape === TRUE && preg_match_all('/\sAND\s|\sOR\s/i', $cond, $m, PREG_OFFSET_CAPTURE))
{
- $cond = $this->protect_identifiers($match[1]).$match[2].$this->protect_identifiers($match[3]);
+ $newcond = '';
+ $m[0][] = array('', strlen($cond));
+
+ for ($i = 0, $c = count($m[0]), $s = 0;
+ $i < $c;
+ $s = $m[0][$i][1] + strlen($m[0][$i][0]), $i++)
+ {
+ $temp = substr($cond, $s, ($m[0][$i][1] - $s));
+
+ $newcond .= preg_match("/([\[\]\w\.'-]+)(\s*[^\"\[`'\w]+\s*)(.+)/i", $temp, $match)
+ ? $this->protect_identifiers($match[1]).$match[2].$this->protect_identifiers($match[3])
+ : $temp;
+
+ $newcond .= $m[0][$i][0];
+ }
+
+ $cond = ' ON '.$newcond;
+ }
+ // Split apart the condition and protect the identifiers
+ elseif ($escape === TRUE && preg_match("/([\[\]\w\.'-]+)(\s*[^\"\[`'\w]+\s*)(.+)/i", $cond, $match))
+ {
+ $cond = ' ON '.$this->protect_identifiers($match[1]).$match[2].$this->protect_identifiers($match[3]);
+ }
+ elseif ( ! $this->_has_operator($cond))
+ {
+ $cond = ' USING ('.($escape ? $this->escape_identifiers($cond) : $cond).')';
+ }
+ else
+ {
+ $cond = ' ON '.$cond;
+ }
+
+ // Do we want to escape the table name?
+ if ($escape === TRUE)
+ {
+ $table = $this->protect_identifiers($table, TRUE, NULL, FALSE);
}
// Assemble the JOIN statement
- $this->ar_join[] = $join = $type.'JOIN '.$this->protect_identifiers($table, TRUE, NULL, FALSE).' ON '.$cond;
+ $this->qb_join[] = $join = $type.'JOIN '.$table.$cond;
- if ($this->ar_caching === TRUE)
+ if ($this->qb_caching === TRUE)
{
- $this->ar_cache_join[] = $join;
- $this->ar_cache_exists[] = 'join';
+ $this->qb_cache_join[] = $join;
+ $this->qb_cache_exists[] = 'join';
}
return $this;
@@ -360,52 +576,59 @@ abstract class CI_DB_active_record extends CI_DB_driver {
// --------------------------------------------------------------------
/**
- * Where
+ * WHERE
*
- * Generates the WHERE portion of the query. Separates
- * multiple calls with AND
+ * Generates the WHERE portion of the query.
+ * Separates multiple calls with 'AND'.
*
* @param mixed
* @param mixed
+ * @param bool
* @return object
*/
- public function where($key, $value = NULL, $escape = TRUE)
+ public function where($key, $value = NULL, $escape = NULL)
{
- return $this->_where($key, $value, 'AND ', $escape);
+ return $this->_wh('qb_where', $key, $value, 'AND ', $escape);
}
// --------------------------------------------------------------------
/**
- * OR Where
+ * OR WHERE
*
- * Generates the WHERE portion of the query. Separates
- * multiple calls with OR
+ * Generates the WHERE portion of the query.
+ * Separates multiple calls with 'OR'.
*
* @param mixed
* @param mixed
+ * @param bool
* @return object
*/
- public function or_where($key, $value = NULL, $escape = TRUE)
+ public function or_where($key, $value = NULL, $escape = NULL)
{
- return $this->_where($key, $value, 'OR ', $escape);
+ return $this->_wh('qb_where', $key, $value, 'OR ', $escape);
}
// --------------------------------------------------------------------
/**
- * Where
+ * WHERE, HAVING
*
- * Called by where() or or_where()
+ * @used-by where()
+ * @used-by or_where()
+ * @used-by having()
+ * @used-by or_having()
*
- * @param mixed
- * @param mixed
- * @param string
+ * @param string $qb_key 'qb_where' or 'qb_having'
+ * @param mixed $key
+ * @param mixed $value
+ * @param string $type
+ * @param bool $escape
* @return object
*/
- protected function _where($key, $value = NULL, $type = 'AND ', $escape = NULL)
+ protected function _wh($qb_key, $key, $value = NULL, $type = 'AND ', $escape = NULL)
{
- $type = $this->_group_get_type($type);
+ $qb_cache_key = ($qb_key === 'qb_having') ? 'qb_cache_having' : 'qb_cache_where';
if ( ! is_array($key))
{
@@ -413,26 +636,18 @@ abstract class CI_DB_active_record extends CI_DB_driver {
}
// If the escape value was not set will will base it on the global setting
- if ( ! is_bool($escape))
- {
- $escape = $this->_protect_identifiers;
- }
+ is_bool($escape) OR $escape = $this->_protect_identifiers;
foreach ($key as $k => $v)
{
- $prefix = (count($this->ar_where) === 0 && count($this->ar_cache_where) === 0) ? '' : $type;
-
- if (is_null($v) && ! $this->_has_operator($k))
- {
- // value appears not to have been set, assign the test to IS NULL
- $k .= ' IS NULL';
- }
+ $prefix = (count($this->$qb_key) === 0 && count($this->$qb_cache_key) === 0)
+ ? $this->_group_get_type('')
+ : $this->_group_get_type($type);
if ( ! is_null($v))
{
if ($escape === TRUE)
{
- $k = $this->protect_identifiers($k, FALSE, $escape);
$v = ' '.$this->escape($v);
}
@@ -441,16 +656,17 @@ abstract class CI_DB_active_record extends CI_DB_driver {
$k .= ' = ';
}
}
- else
+ elseif ( ! $this->_has_operator($k))
{
- $k = $this->protect_identifiers($k, FALSE, $escape);
+ // value appears not to have been set, assign the test to IS NULL
+ $k .= ' IS NULL';
}
- $this->ar_where[] = $prefix.$k.$v;
- if ($this->ar_caching === TRUE)
+ $this->{$qb_key}[] = array('condition' => $prefix.$k.$v, 'escape' => $escape);
+ if ($this->qb_caching === TRUE)
{
- $this->ar_cache_where[] = $prefix.$k.$v;
- $this->ar_cache_exists[] = 'where';
+ $this->{$qb_cache_key}[] = array('condition' => $prefix.$k.$v, 'escape' => $escape);
+ $this->qb_cache_exists[] = substr($qb_key, 3);
}
}
@@ -461,244 +677,269 @@ abstract class CI_DB_active_record extends CI_DB_driver {
// --------------------------------------------------------------------
/**
- * Where_in
+ * WHERE IN
*
- * Generates a WHERE field IN ('item', 'item') SQL query joined with
- * AND if appropriate
+ * Generates a WHERE field IN('item', 'item') SQL query,
+ * joined with 'AND' if appropriate.
*
- * @param string The field to search
- * @param array The values searched on
+ * @param string $key The field to search
+ * @param array $values The values searched on
+ * @param bool $escape
* @return object
*/
- public function where_in($key = NULL, $values = NULL)
+ public function where_in($key = NULL, $values = NULL, $escape = NULL)
{
- return $this->_where_in($key, $values);
+ return $this->_where_in($key, $values, FALSE, 'AND ', $escape);
}
// --------------------------------------------------------------------
/**
- * Where_in_or
+ * OR WHERE IN
*
- * Generates a WHERE field IN ('item', 'item') SQL query joined with
- * OR if appropriate
+ * Generates a WHERE field IN('item', 'item') SQL query,
+ * joined with 'OR' if appropriate.
*
- * @param string The field to search
- * @param array The values searched on
+ * @param string $key The field to search
+ * @param array $values The values searched on
+ * @param bool $escape
* @return object
*/
- public function or_where_in($key = NULL, $values = NULL)
+ public function or_where_in($key = NULL, $values = NULL, $escape = NULL)
{
- return $this->_where_in($key, $values, FALSE, 'OR ');
+ return $this->_where_in($key, $values, FALSE, 'OR ', $escape);
}
// --------------------------------------------------------------------
/**
- * Where_not_in
+ * WHERE NOT IN
*
- * Generates a WHERE field NOT IN ('item', 'item') SQL query joined
- * with AND if appropriate
+ * Generates a WHERE field NOT IN('item', 'item') SQL query,
+ * joined with 'AND' if appropriate.
*
- * @param string The field to search
- * @param array The values searched on
+ * @param string $key The field to search
+ * @param array $values The values searched on
+ * @param bool $escape
* @return object
*/
- public function where_not_in($key = NULL, $values = NULL)
+ public function where_not_in($key = NULL, $values = NULL, $escape = NULL)
{
- return $this->_where_in($key, $values, TRUE);
+ return $this->_where_in($key, $values, TRUE, 'AND ', $escape);
}
// --------------------------------------------------------------------
/**
- * Where_not_in_or
+ * OR WHERE NOT IN
*
- * Generates a WHERE field NOT IN ('item', 'item') SQL query joined
- * with OR if appropriate
+ * Generates a WHERE field NOT IN('item', 'item') SQL query,
+ * joined with 'OR' if appropriate.
*
- * @param string The field to search
- * @param array The values searched on
+ * @param string $key The field to search
+ * @param array $values The values searched on
+ * @param bool $escape
* @return object
*/
- public function or_where_not_in($key = NULL, $values = NULL)
+ public function or_where_not_in($key = NULL, $values = NULL, $escape = NULL)
{
- return $this->_where_in($key, $values, TRUE, 'OR ');
+ return $this->_where_in($key, $values, TRUE, 'OR ', $escape);
}
// --------------------------------------------------------------------
/**
- * Where_in
+ * Internal WHERE IN
*
- * Called by where_in, where_in_or, where_not_in, where_not_in_or
+ * @used-by where_in()
+ * @used-by or_where_in()
+ * @used-by where_not_in()
+ * @used-by or_where_not_in()
*
- * @param string The field to search
- * @param array The values searched on
- * @param bool If the statement would be IN or NOT IN
- * @param string
+ * @param string $key The field to search
+ * @param array $values The values searched on
+ * @param bool $not If the statement would be IN or NOT IN
+ * @param string $type
+ * @param bool $escape
* @return object
*/
- protected function _where_in($key = NULL, $values = NULL, $not = FALSE, $type = 'AND ')
+ protected function _where_in($key = NULL, $values = NULL, $not = FALSE, $type = 'AND ', $escape = NULL)
{
if ($key === NULL OR $values === NULL)
{
- return;
+ return $this;
}
- $type = $this->_group_get_type($type);
-
if ( ! is_array($values))
{
$values = array($values);
}
+ is_bool($escape) OR $escape = $this->_protect_identifiers;
+
$not = ($not) ? ' NOT' : '';
+ $where_in = array();
foreach ($values as $value)
{
- $this->ar_wherein[] = $this->escape($value);
+ $where_in[] = $this->escape($value);
}
- $prefix = (count($this->ar_where) === 0) ? '' : $type;
- $this->ar_where[] = $where_in = $prefix.$this->protect_identifiers($key).$not.' IN ('.implode(', ', $this->ar_wherein).') ';
+ $prefix = (count($this->qb_where) === 0) ? $this->_group_get_type('') : $this->_group_get_type($type);
+ $where_in = array(
+ 'condition' => $prefix.$key.$not.' IN('.implode(', ', $where_in).')',
+ 'escape' => $escape
+ );
- if ($this->ar_caching === TRUE)
+ $this->qb_where[] = $where_in;
+ if ($this->qb_caching === TRUE)
{
- $this->ar_cache_where[] = $where_in;
- $this->ar_cache_exists[] = 'where';
+ $this->qb_cache_where[] = $where_in;
+ $this->qb_cache_exists[] = 'where';
}
- // reset the array for multiple calls
- $this->ar_wherein = array();
return $this;
}
// --------------------------------------------------------------------
/**
- * Like
+ * LIKE
*
- * Generates a %LIKE% portion of the query. Separates
- * multiple calls with AND
+ * Generates a %LIKE% portion of the query.
+ * Separates multiple calls with 'AND'.
*
- * @param mixed
- * @param mixed
+ * @param mixed $field
+ * @param string $match
+ * @param string $side
+ * @param bool $escape
* @return object
*/
- public function like($field, $match = '', $side = 'both')
+ public function like($field, $match = '', $side = 'both', $escape = NULL)
{
- return $this->_like($field, $match, 'AND ', $side);
+ return $this->_like($field, $match, 'AND ', $side, '', $escape);
}
// --------------------------------------------------------------------
/**
- * Not Like
+ * NOT LIKE
*
- * Generates a NOT LIKE portion of the query. Separates
- * multiple calls with AND
+ * Generates a NOT LIKE portion of the query.
+ * Separates multiple calls with 'AND'.
*
- * @param mixed
- * @param mixed
+ * @param mixed $field
+ * @param string $match
+ * @param string $side
+ * @param bool $escape
* @return object
*/
- public function not_like($field, $match = '', $side = 'both')
+ public function not_like($field, $match = '', $side = 'both', $escape = NULL)
{
- return $this->_like($field, $match, 'AND ', $side, 'NOT');
+ return $this->_like($field, $match, 'AND ', $side, 'NOT', $escape);
}
// --------------------------------------------------------------------
/**
- * OR Like
+ * OR LIKE
*
- * Generates a %LIKE% portion of the query. Separates
- * multiple calls with OR
+ * Generates a %LIKE% portion of the query.
+ * Separates multiple calls with 'OR'.
*
- * @param mixed
- * @param mixed
+ * @param mixed $field
+ * @param string $match
+ * @param string $side
+ * @param bool $escape
* @return object
*/
- public function or_like($field, $match = '', $side = 'both')
+ public function or_like($field, $match = '', $side = 'both', $escape = NULL)
{
- return $this->_like($field, $match, 'OR ', $side);
+ return $this->_like($field, $match, 'OR ', $side, '', $escape);
}
// --------------------------------------------------------------------
/**
- * OR Not Like
+ * OR NOT LIKE
*
- * Generates a NOT LIKE portion of the query. Separates
- * multiple calls with OR
+ * Generates a NOT LIKE portion of the query.
+ * Separates multiple calls with 'OR'.
*
- * @param mixed
- * @param mixed
+ * @param mixed $field
+ * @param string $match
+ * @param string $side
+ * @param bool $escape
* @return object
*/
- public function or_not_like($field, $match = '', $side = 'both')
+ public function or_not_like($field, $match = '', $side = 'both', $escape = NULL)
{
- return $this->_like($field, $match, 'OR ', $side, 'NOT');
+ return $this->_like($field, $match, 'OR ', $side, 'NOT', $escape);
}
// --------------------------------------------------------------------
/**
- * Like
+ * Internal LIKE
*
- * Called by like() or orlike()
+ * @used-by like()
+ * @used-by or_like()
+ * @used-by not_like()
+ * @used-by or_not_like()
*
- * @param mixed
- * @param mixed
- * @param string
+ * @param mixed $field
+ * @param string $match
+ * @param string $type
+ * @param string $side
+ * @param string $not
+ * @param bool $escape
* @return object
*/
- protected function _like($field, $match = '', $type = 'AND ', $side = 'both', $not = '')
+ protected function _like($field, $match = '', $type = 'AND ', $side = 'both', $not = '', $escape = NULL)
{
- $type = $this->_group_get_type($type);
-
if ( ! is_array($field))
{
$field = array($field => $match);
}
+ is_bool($escape) OR $escape = $this->_protect_identifiers;
+
foreach ($field as $k => $v)
{
- $k = $this->protect_identifiers($k);
- $prefix = (count($this->ar_like) === 0) ? '' : $type;
+ $prefix = (count($this->qb_where) === 0 && count($this->qb_cache_where) === 0)
+ ? $this->_group_get_type('') : $this->_group_get_type($type);
+
$v = $this->escape_like_str($v);
if ($side === 'none')
{
- $like_statement = $prefix." $k $not LIKE '{$v}'";
+ $like_statement = "{$prefix} {$k} {$not} LIKE '{$v}'";
}
elseif ($side === 'before')
{
- $like_statement = $prefix." $k $not LIKE '%{$v}'";
+ $like_statement = "{$prefix} {$k} {$not} LIKE '%{$v}'";
}
elseif ($side === 'after')
{
- $like_statement = $prefix." $k $not LIKE '{$v}%'";
+ $like_statement = "{$prefix} {$k} {$not} LIKE '{$v}%'";
}
else
{
- $like_statement = $prefix." $k $not LIKE '%{$v}%'";
+ $like_statement = "{$prefix} {$k} {$not} LIKE '%{$v}%'";
}
// some platforms require an escape sequence definition for LIKE wildcards
- if ($this->_like_escape_str != '')
+ if ($this->_like_escape_str !== '')
{
- $like_statement = $like_statement.sprintf($this->_like_escape_str, $this->_like_escape_chr);
+ $like_statement .= sprintf($this->_like_escape_str, $this->_like_escape_chr);
}
- $this->ar_like[] = $like_statement;
- if ($this->ar_caching === TRUE)
+ $this->qb_where[] = array('condition' => $like_statement, 'escape' => $escape);
+ if ($this->qb_caching === TRUE)
{
- $this->ar_cache_like[] = $like_statement;
- $this->ar_cache_exists[] = 'like';
+ $this->qb_cache_where[] = $like_statement;
+ $this->qb_cache_exists[] = 'where';
}
-
}
return $this;
@@ -709,20 +950,25 @@ abstract class CI_DB_active_record extends CI_DB_driver {
/**
* Starts a query group.
*
- * @param string (Internal use only)
- * @param string (Internal use only)
+ * @param string $not (Internal use only)
+ * @param string $type (Internal use only)
* @return object
*/
public function group_start($not = '', $type = 'AND ')
{
$type = $this->_group_get_type($type);
- $this->ar_where_group_started = TRUE;
- $prefix = (count($this->ar_where) === 0 && count($this->ar_cache_where) === 0) ? '' : $type;
- $this->ar_where[] = $value = $prefix.$not.str_repeat(' ', ++$this->ar_where_group_count).' (';
- if ($this->ar_caching)
+ $this->qb_where_group_started = TRUE;
+ $prefix = (count($this->qb_where) === 0 && count($this->qb_cache_where) === 0) ? '' : $type;
+ $where = array(
+ 'condition' => $prefix.$not.str_repeat(' ', ++$this->qb_where_group_count).' (',
+ 'escape' => FALSE
+ );
+
+ $this->qb_where[] = $where;
+ if ($this->qb_caching)
{
- $this->ar_cache_where[] = $value;
+ $this->qb_cache_where[] = $where;
}
return $this;
@@ -773,12 +1019,16 @@ abstract class CI_DB_active_record extends CI_DB_driver {
*/
public function group_end()
{
- $this->ar_where_group_started = FALSE;
- $this->ar_where[] = $value = str_repeat(' ', $this->ar_where_group_count--) . ')';
+ $this->qb_where_group_started = FALSE;
+ $where = array(
+ 'condition' => str_repeat(' ', $this->qb_where_group_count--).')',
+ 'escape' => FALSE
+ );
- if ($this->ar_caching)
+ $this->qb_where[] = $where;
+ if ($this->qb_caching)
{
- $this->ar_cache_where[] = $value;
+ $this->qb_cache_where[] = $where;
}
return $this;
@@ -789,17 +1039,20 @@ abstract class CI_DB_active_record extends CI_DB_driver {
/**
* Group_get_type
*
- * Called by group_start(), _like(), _where() and _where_in()
+ * @used-by group_start()
+ * @used-by _like()
+ * @used-by _wh()
+ * @used-by _where_in()
*
- * @param string
+ * @param string $type
* @return string
*/
protected function _group_get_type($type)
{
- if ($this->ar_where_group_started)
+ if ($this->qb_where_group_started)
{
$type = '';
- $this->ar_where_group_started = FALSE;
+ $this->qb_where_group_started = FALSE;
}
return $type;
@@ -810,28 +1063,34 @@ abstract class CI_DB_active_record extends CI_DB_driver {
/**
* GROUP BY
*
- * @param string
+ * @param string $by
+ * @param bool $escape
* @return object
*/
- public function group_by($by)
+ public function group_by($by, $escape = NULL)
{
+ is_bool($escape) OR $escape = $this->_protect_identifiers;
+
if (is_string($by))
{
- $by = explode(',', $by);
+ $by = ($escape === TRUE)
+ ? explode(',', $by)
+ : array($by);
}
foreach ($by as $val)
{
$val = trim($val);
- if ($val != '')
+ if ($val !== '')
{
- $this->ar_groupby[] = $val = $this->protect_identifiers($val);
+ $val = array('field' => $val, 'escape' => $escape);
- if ($this->ar_caching === TRUE)
+ $this->qb_groupby[] = $val;
+ if ($this->qb_caching === TRUE)
{
- $this->ar_cache_groupby[] = $val;
- $this->ar_cache_exists[] = 'groupby';
+ $this->qb_cache_groupby[] = $val;
+ $this->qb_cache_exists[] = 'groupby';
}
}
}
@@ -842,136 +1101,91 @@ abstract class CI_DB_active_record extends CI_DB_driver {
// --------------------------------------------------------------------
/**
- * Sets the HAVING value
+ * HAVING
*
- * Separates multiple calls with AND
+ * Separates multiple calls with 'AND'.
*
- * @param string
- * @param string
+ * @param string $key
+ * @param string $value
+ * @param bool $escape
* @return object
*/
- public function having($key, $value = '', $escape = TRUE)
+ public function having($key, $value = NULL, $escape = NULL)
{
- return $this->_having($key, $value, 'AND ', $escape);
+ return $this->_wh('qb_having', $key, $value, 'AND ', $escape);
}
// --------------------------------------------------------------------
/**
- * Sets the OR HAVING value
+ * OR HAVING
*
- * Separates multiple calls with OR
+ * Separates multiple calls with 'OR'.
*
- * @param string
- * @param string
+ * @param string $key
+ * @param string $value
+ * @param bool $escape
* @return object
*/
- public function or_having($key, $value = '', $escape = TRUE)
+ public function or_having($key, $value = NULL, $escape = NULL)
{
- return $this->_having($key, $value, 'OR ', $escape);
+ return $this->_wh('qb_having', $key, $value, 'OR ', $escape);
}
// --------------------------------------------------------------------
/**
- * Sets the HAVING values
+ * ORDER BY
*
- * Called by having() or or_having()
- *
- * @param string
- * @param string
+ * @param string $orderby
+ * @param string $direction ASC or DESC
+ * @param bool $escape
* @return object
*/
- protected function _having($key, $value = '', $type = 'AND ', $escape = TRUE)
+ public function order_by($orderby, $direction = '', $escape = NULL)
{
- if ( ! is_array($key))
- {
- $key = array($key => $value);
- }
+ $direction = strtoupper(trim($direction));
- foreach ($key as $k => $v)
+ if ($direction === 'RANDOM')
{
- $prefix = (count($this->ar_having) === 0) ? '' : $type;
+ $direction = '';
- if ($escape === TRUE)
- {
- $k = $this->protect_identifiers($k);
- }
-
- if ( ! $this->_has_operator($k))
- {
- $k .= ' = ';
- }
-
- if ($v != '')
- {
- $v = ' '.$this->escape($v);
- }
-
- $this->ar_having[] = $prefix.$k.$v;
- if ($this->ar_caching === TRUE)
- {
- $this->ar_cache_having[] = $prefix.$k.$v;
- $this->ar_cache_exists[] = 'having';
- }
+ // Do we have a seed value?
+ $orderby = ctype_digit((string) $orderby)
+ ? $orderby = sprintf($this->_random_keyword[1], $orderby)
+ : $this->_random_keyword[0];
}
-
- return $this;
- }
-
- // --------------------------------------------------------------------
-
- /**
- * Sets the ORDER BY value
- *
- * @param string
- * @param string direction: asc or desc
- * @param bool enable field name escaping
- * @return object
- */
- public function order_by($orderby, $direction = '', $escape = TRUE)
- {
- if (strtolower($direction) === 'random')
+ elseif (empty($orderby))
{
- $orderby = ''; // Random results want or don't need a field name
- $direction = $this->_random_keyword;
+ return $this;
}
- elseif (trim($direction) != '')
+ elseif ($direction !== '')
{
- $direction = (in_array(strtoupper(trim($direction)), array('ASC', 'DESC'), TRUE)) ? ' '.$direction : ' ASC';
+ $direction = in_array($direction, array('ASC', 'DESC'), TRUE) ? ' '.$direction : '';
}
+ is_bool($escape) OR $escape = $this->_protect_identifiers;
- if ((strpos($orderby, ',') !== FALSE) && $escape === TRUE)
+ if ($escape === FALSE)
{
- $temp = array();
- foreach (explode(',', $orderby) as $part)
- {
- $part = trim($part);
- if ( ! in_array($part, $this->ar_aliased_tables))
- {
- $part = $this->protect_identifiers(trim($part));
- }
-
- $temp[] = $part;
- }
-
- $orderby = implode(', ', $temp);
+ $qb_orderby[] = array('field' => $orderby, 'direction' => $direction, 'escape' => FALSE);
}
- elseif ($direction != $this->_random_keyword)
+ else
{
- if ($escape === TRUE)
+ $qb_orderby = array();
+ foreach (explode(',', $orderby) as $field)
{
- $orderby = $this->protect_identifiers($orderby);
+ $qb_orderby[] = ($direction === '' && preg_match('/\s+(ASC|DESC)$/i', rtrim($field), $match, PREG_OFFSET_CAPTURE))
+ ? array('field' => ltrim(substr($field, 0, $match[0][1])), 'direction' => ' '.$match[1][0], 'escape' => TRUE)
+ : array('field' => trim($field), 'direction' => $direction, 'escape' => TRUE);
}
}
- $this->ar_orderby[] = $orderby_statement = $orderby.$direction;
-
- if ($this->ar_caching === TRUE)
+ $this->qb_orderby = array_merge($this->qb_orderby, $qb_orderby);
+ if ($this->qb_caching === TRUE)
{
- $this->ar_cache_orderby[] = $orderby_statement;
- $this->ar_cache_exists[] = 'orderby';
+ $this->qb_cache_orderby = array_merge($this->qb_cache_orderby, $qb_orderby);
+ $this->qb_cache_exists[] = 'orderby';
}
return $this;
@@ -980,20 +1194,16 @@ abstract class CI_DB_active_record extends CI_DB_driver {
// --------------------------------------------------------------------
/**
- * Sets the LIMIT value
+ * LIMIT
*
- * @param int the limit value
- * @param int the offset value
+ * @param int $value LIMIT value
+ * @param int $offset OFFSET value
* @return object
*/
- public function limit($value, $offset = NULL)
+ public function limit($value, $offset = FALSE)
{
- $this->ar_limit = (int) $value;
-
- if ( ! is_null($offset))
- {
- $this->ar_offset = (int) $offset;
- }
+ is_null($value) OR $this->qb_limit = (int) $value;
+ empty($offset) OR $this->qb_offset = (int) $offset;
return $this;
}
@@ -1003,26 +1213,43 @@ abstract class CI_DB_active_record extends CI_DB_driver {
/**
* Sets the OFFSET value
*
- * @param int the offset value
+ * @param int $offset OFFSET value
* @return object
*/
public function offset($offset)
{
- $this->ar_offset = (int) $offset;
+ empty($offset) OR $this->qb_offset = (int) $offset;
return $this;
}
// --------------------------------------------------------------------
/**
- * The "set" function. Allows key/value pairs to be set for inserting or updating
+ * LIMIT string
+ *
+ * Generates a platform-specific LIMIT clause.
+ *
+ * @param string $sql SQL Query
+ * @return string
+ */
+ protected function _limit($sql)
+ {
+ return $sql.' LIMIT '.($this->qb_offset ? $this->qb_offset.', ' : '').$this->qb_limit;
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * The "set" function.
+ *
+ * Allows key/value pairs to be set for inserting or updating
*
* @param mixed
* @param string
* @param bool
* @return object
*/
- public function set($key, $value = '', $escape = TRUE)
+ public function set($key, $value = '', $escape = NULL)
{
$key = $this->_object_to_array($key);
@@ -1031,16 +1258,12 @@ abstract class CI_DB_active_record extends CI_DB_driver {
$key = array($key => $value);
}
+ is_bool($escape) OR $escape = $this->_protect_identifiers;
+
foreach ($key as $k => $v)
{
- if ($escape === FALSE)
- {
- $this->ar_set[$this->protect_identifiers($k)] = $v;
- }
- else
- {
- $this->ar_set[$this->protect_identifiers($k, FALSE, TRUE)] = $this->escape($v);
- }
+ $this->qb_set[$this->protect_identifiers($k, FALSE, $escape)] = ($escape)
+ ? $this->escape($v) : $v;
}
return $this;
@@ -1054,18 +1277,18 @@ abstract class CI_DB_active_record extends CI_DB_driver {
* Compiles a SELECT query string and returns the sql.
*
* @param string the table name to select from (optional)
- * @param bool TRUE: resets AR values; FALSE: leave AR vaules alone
+ * @param bool TRUE: resets QB values; FALSE: leave QB vaules alone
* @return string
*/
public function get_compiled_select($table = '', $reset = TRUE)
{
- if ($table != '')
+ if ($table !== '')
{
$this->_track_aliases($table);
$this->from($table);
}
- $select = $this->_compile_select();
+ $select = $this->_compile_select();
if ($reset === TRUE)
{
@@ -1088,15 +1311,15 @@ abstract class CI_DB_active_record extends CI_DB_driver {
* @param string the offset clause
* @return object
*/
- public function get($table = '', $limit = null, $offset = null)
+ public function get($table = '', $limit = NULL, $offset = NULL)
{
- if ($table != '')
+ if ($table !== '')
{
$this->_track_aliases($table);
$this->from($table);
}
- if ( ! is_null($limit))
+ if ( ! empty($limit))
{
$this->limit($limit, $offset);
}
@@ -1106,24 +1329,28 @@ abstract class CI_DB_active_record extends CI_DB_driver {
return $result;
}
+ // --------------------------------------------------------------------
+
/**
* "Count All Results" query
*
* Generates a platform-specific query string that counts all records
- * returned by an Active Record query.
+ * returned by an Query Builder query.
*
* @param string
* @return string
*/
public function count_all_results($table = '')
{
- if ($table != '')
+ if ($table !== '')
{
$this->_track_aliases($table);
$this->from($table);
}
- $result = $this->query($this->_compile_select($this->_count_string.$this->protect_identifiers('numrows')));
+ $result = ($this->qb_distinct === TRUE)
+ ? $this->query($this->_count_string.$this->protect_identifiers('numrows')."\nFROM (\n".$this->_compile_select()."\n) CI_count_all_results")
+ : $this->query($this->_compile_select($this->_count_string.$this->protect_identifiers('numrows')));
$this->_reset_select();
if ($result->num_rows() === 0)
@@ -1134,6 +1361,7 @@ abstract class CI_DB_active_record extends CI_DB_driver {
$row = $result->row();
return (int) $row->numrows;
}
+
// --------------------------------------------------------------------
/**
@@ -1141,14 +1369,15 @@ abstract class CI_DB_active_record extends CI_DB_driver {
*
* Allows the where clause, limit and offset to be added directly
*
- * @param string the where clause
- * @param string the limit clause
- * @param string the offset clause
+ * @param string $table
+ * @param string $where
+ * @param int $limit
+ * @param int $offset
* @return object
*/
- public function get_where($table = '', $where = null, $limit = null, $offset = null)
+ public function get_where($table = '', $where = NULL, $limit = NULL, $offset = NULL)
{
- if ($table != '')
+ if ($table !== '')
{
$this->from($table);
}
@@ -1158,7 +1387,7 @@ abstract class CI_DB_active_record extends CI_DB_driver {
$this->where($where);
}
- if ( ! is_null($limit))
+ if ( ! empty($limit))
{
$this->limit($limit, $offset);
}
@@ -1175,57 +1404,56 @@ abstract class CI_DB_active_record extends CI_DB_driver {
*
* Compiles batch insert strings and runs the queries
*
- * @param string the table to retrieve the results from
- * @param array an associative array of insert values
- * @return object
+ * @param string $table Table to insert into
+ * @param array $set An associative array of insert values
+ * @param bool $escape Whether to escape values and identifiers
+ * @return int Number of rows inserted or FALSE on failure
*/
- public function insert_batch($table = '', $set = NULL)
+ public function insert_batch($table = '', $set = NULL, $escape = NULL)
{
if ( ! is_null($set))
{
- $this->set_insert_batch($set);
+ $this->set_insert_batch($set, '', $escape);
}
- if (count($this->ar_set) === 0)
+ if (count($this->qb_set) === 0)
{
- if ($this->db_debug)
- {
- // No valid data array. Folds in cases where keys and values did not match up
- return $this->display_error('db_must_use_set');
- }
- return FALSE;
+ // No valid data array. Folds in cases where keys and values did not match up
+ return ($this->db_debug) ? $this->display_error('db_must_use_set') : FALSE;
}
- if ($table == '')
+ if ($table === '')
{
- if ( ! isset($this->ar_from[0]))
+ if ( ! isset($this->qb_from[0]))
{
return ($this->db_debug) ? $this->display_error('db_must_set_table') : FALSE;
}
- $table = $this->ar_from[0];
+ $table = $this->qb_from[0];
}
// Batch this baby
- for ($i = 0, $total = count($this->ar_set); $i < $total; $i += 100)
+ $affected_rows = 0;
+ for ($i = 0, $total = count($this->qb_set); $i < $total; $i += 100)
{
- $this->query($this->_insert_batch($this->protect_identifiers($table, TRUE, NULL, FALSE), $this->ar_keys, array_slice($this->ar_set, $i, 100)));
+ $this->query($this->_insert_batch($this->protect_identifiers($table, TRUE, $escape, FALSE), $this->qb_keys, array_slice($this->qb_set, $i, 100)));
+ $affected_rows += $this->affected_rows();
}
$this->_reset_write();
- return TRUE;
+ return $affected_rows;
}
// --------------------------------------------------------------------
/**
- * Insert_batch statement
+ * Insert batch statement
*
* Generates a platform-specific insert string from the supplied data.
*
- * @param string the table name
- * @param array the insert keys
- * @param array the insert values
+ * @param string $table Table name
+ * @param array $keys INSERT keys
+ * @param array $values INSERT values
* @return string
*/
protected function _insert_batch($table, $keys, $values)
@@ -1243,7 +1471,7 @@ abstract class CI_DB_active_record extends CI_DB_driver {
* @param bool
* @return object
*/
- public function set_insert_batch($key, $value = '', $escape = TRUE)
+ public function set_insert_batch($key, $value = '', $escape = NULL)
{
$key = $this->_object_to_array_batch($key);
@@ -1252,25 +1480,24 @@ abstract class CI_DB_active_record extends CI_DB_driver {
$key = array($key => $value);
}
- $keys = array_keys(current($key));
+ is_bool($escape) OR $escape = $this->_protect_identifiers;
+
+ $keys = array_keys($this->_object_to_array(current($key)));
sort($keys);
foreach ($key as $row)
{
+ $row = $this->_object_to_array($row);
if (count(array_diff($keys, array_keys($row))) > 0 OR count(array_diff(array_keys($row), $keys)) > 0)
{
// batch function above returns an error on an empty array
- $this->ar_set[] = array();
+ $this->qb_set[] = array();
return;
}
ksort($row); // puts $row in the same order as our keys
- if ($escape === FALSE)
- {
- $this->ar_set[] = '('.implode(',', $row).')';
- }
- else
+ if ($escape !== FALSE)
{
$clean = array();
foreach ($row as $value)
@@ -1278,13 +1505,15 @@ abstract class CI_DB_active_record extends CI_DB_driver {
$clean[] = $this->escape($value);
}
- $this->ar_set[] = '('.implode(',', $clean).')';
+ $row = $clean;
}
+
+ $this->qb_set[] = '('.implode(',', $row).')';
}
foreach ($keys as $k)
{
- $this->ar_keys[] = $this->protect_identifiers($k);
+ $this->qb_keys[] = $this->protect_identifiers($k, FALSE, $escape);
}
return $this;
@@ -1298,7 +1527,7 @@ abstract class CI_DB_active_record extends CI_DB_driver {
* Compiles an insert query and returns the sql
*
* @param string the table to insert into
- * @param bool TRUE: reset AR values; FALSE: leave AR values alone
+ * @param bool TRUE: reset QB values; FALSE: leave QB values alone
* @return string
*/
public function get_compiled_insert($table = '', $reset = TRUE)
@@ -1309,9 +1538,11 @@ abstract class CI_DB_active_record extends CI_DB_driver {
}
$sql = $this->_insert(
- $this->protect_identifiers($this->ar_from[0], TRUE, NULL, FALSE),
- array_keys($this->ar_set),
- array_values($this->ar_set)
+ $this->protect_identifiers(
+ $this->qb_from[0], TRUE, NULL, FALSE
+ ),
+ array_keys($this->qb_set),
+ array_values($this->qb_set)
);
if ($reset === TRUE)
@@ -1331,13 +1562,14 @@ abstract class CI_DB_active_record extends CI_DB_driver {
*
* @param string the table to insert data into
* @param array an associative array of insert values
+ * @param bool $escape Whether to escape values and identifiers
* @return object
*/
- public function insert($table = '', $set = NULL)
+ public function insert($table = '', $set = NULL, $escape = NULL)
{
if ( ! is_null($set))
{
- $this->set($set);
+ $this->set($set, '', $escape);
}
if ($this->_validate_insert($table) === FALSE)
@@ -1346,9 +1578,11 @@ abstract class CI_DB_active_record extends CI_DB_driver {
}
$sql = $this->_insert(
- $this->protect_identifiers($this->ar_from[0], TRUE, NULL, FALSE),
- array_keys($this->ar_set),
- array_values($this->ar_set)
+ $this->protect_identifiers(
+ $this->qb_from[0], TRUE, $escape, FALSE
+ ),
+ array_keys($this->qb_set),
+ array_values($this->qb_set)
);
$this->_reset_write();
@@ -1358,23 +1592,6 @@ abstract class CI_DB_active_record extends CI_DB_driver {
// --------------------------------------------------------------------
/**
- * Insert statement
- *
- * Generates a platform-specific insert string from the supplied data
- *
- * @param string the table name
- * @param array the insert keys
- * @param array the insert values
- * @return string
- */
- protected function _insert($table, $keys, $values)
- {
- return 'INSERT INTO '.$table.' ('.implode(', ', $keys).') VALUES ('.implode(', ', $values).')';
- }
-
- // --------------------------------------------------------------------
-
- /**
* Validate Insert
*
* This method is used by both insert() and get_compiled_insert() to
@@ -1386,21 +1603,18 @@ abstract class CI_DB_active_record extends CI_DB_driver {
*/
protected function _validate_insert($table = '')
{
- if (count($this->ar_set) === 0)
+ if (count($this->qb_set) === 0)
{
return ($this->db_debug) ? $this->display_error('db_must_use_set') : FALSE;
}
- if ($table == '')
+ if ($table !== '')
{
- if ( ! isset($this->ar_from[0]))
- {
- return ($this->db_debug) ? $this->display_error('db_must_set_table') : FALSE;
- }
+ $this->qb_from[0] = $table;
}
- else
+ elseif ( ! isset($this->qb_from[0]))
{
- $this->ar_from[0] = $table;
+ return ($this->db_debug) ? $this->display_error('db_must_set_table') : FALSE;
}
return TRUE;
@@ -1424,22 +1638,23 @@ abstract class CI_DB_active_record extends CI_DB_driver {
$this->set($set);
}
- if (count($this->ar_set) === 0)
+ if (count($this->qb_set) === 0)
{
return ($this->db_debug) ? $this->display_error('db_must_use_set') : FALSE;
}
- if ($table == '')
+ if ($table === '')
{
- if ( ! isset($this->ar_from[0]))
+ if ( ! isset($this->qb_from[0]))
{
return ($this->db_debug) ? $this->display_error('db_must_set_table') : FALSE;
}
- $table = $this->ar_from[0];
+ $table = $this->qb_from[0];
}
- $sql = $this->_replace($this->protect_identifiers($table, TRUE, NULL, FALSE), array_keys($this->ar_set), array_values($this->ar_set));
+ $sql = $this->_replace($this->protect_identifiers($table, TRUE, NULL, FALSE), array_keys($this->qb_set), array_values($this->qb_set));
+
$this->_reset_write();
return $this->query($sql);
}
@@ -1464,12 +1679,29 @@ abstract class CI_DB_active_record extends CI_DB_driver {
// --------------------------------------------------------------------
/**
+ * FROM tables
+ *
+ * Groups tables in FROM clauses if needed, so there is no confusion
+ * about operator precedence.
+ *
+ * Note: This is only used (and overriden) by MySQL and CUBRID.
+ *
+ * @return string
+ */
+ protected function _from_tables()
+ {
+ return implode(', ', $this->qb_from);
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
* Get UPDATE query string
*
* Compiles an update query and returns the sql
*
* @param string the table to update
- * @param bool TRUE: reset AR values; FALSE: leave AR values alone
+ * @param bool TRUE: reset QB values; FALSE: leave QB values alone
* @return string
*/
public function get_compiled_update($table = '', $reset = TRUE)
@@ -1482,7 +1714,7 @@ abstract class CI_DB_active_record extends CI_DB_driver {
return FALSE;
}
- $sql = $this->_update($this->protect_identifiers($this->ar_from[0], TRUE, NULL, FALSE), $this->ar_set, $this->ar_where, $this->ar_orderby, $this->ar_limit);
+ $sql = $this->_update($this->protect_identifiers($this->qb_from[0], TRUE, NULL, FALSE), $this->qb_set);
if ($reset === TRUE)
{
@@ -1495,13 +1727,14 @@ abstract class CI_DB_active_record extends CI_DB_driver {
// --------------------------------------------------------------------
/**
- * Update
+ * UPDATE
*
- * Compiles an update string and runs the query
+ * Compiles an update string and runs the query.
*
- * @param string the table to retrieve the results from
- * @param array an associative array of update values
- * @param mixed the where clause
+ * @param string $table
+ * @param array $set An associative array of update values
+ * @param mixed $where
+ * @param int $limit
* @return object
*/
public function update($table = '', $set = NULL, $where = NULL, $limit = NULL)
@@ -1519,17 +1752,17 @@ abstract class CI_DB_active_record extends CI_DB_driver {
return FALSE;
}
- if ($where != NULL)
+ if ($where !== NULL)
{
$this->where($where);
}
- if ($limit != NULL)
+ if ( ! empty($limit))
{
$this->limit($limit);
}
- $sql = $this->_update($this->protect_identifiers($this->ar_from[0], TRUE, NULL, FALSE), $this->ar_set, $this->ar_where, $this->ar_orderby, $this->ar_limit, $this->ar_like);
+ $sql = $this->_update($this->protect_identifiers($this->qb_from[0], TRUE, NULL, FALSE), $this->qb_set);
$this->_reset_write();
return $this->query($sql);
}
@@ -1537,41 +1770,6 @@ abstract class CI_DB_active_record extends CI_DB_driver {
// --------------------------------------------------------------------
/**
- * Update statement
- *
- * Generates a platform-specific update string from the supplied data
- *
- * @param string the table name
- * @param array the update data
- * @param array the where clause
- * @param array the orderby clause
- * @param array the limit clause
- * @param array the like clause
- * @return string
- */
- protected function _update($table, $values, $where, $orderby = array(), $limit = FALSE, $like = array())
- {
- foreach ($values as $key => $val)
- {
- $valstr[] = $key.' = '.$val;
- }
-
- $where = empty($where) ? '' : ' WHERE '.implode(' ', $where);
-
- if ( ! empty($like))
- {
- $where .= ($where === '' ? ' WHERE ' : ' AND ').implode(' ', $like);
- }
-
- return 'UPDATE '.$table.' SET '.implode(', ', $valstr)
- .$where
- .(count($orderby) > 0 ? ' ORDER BY '.implode(', ', $orderby) : '')
- .($limit ? ' LIMIT '.$limit : '');
- }
-
- // --------------------------------------------------------------------
-
- /**
* Validate Update
*
* This method is used by both update() and get_compiled_update() to
@@ -1583,21 +1781,18 @@ abstract class CI_DB_active_record extends CI_DB_driver {
*/
protected function _validate_update($table = '')
{
- if (count($this->ar_set) == 0)
+ if (count($this->qb_set) === 0)
{
return ($this->db_debug) ? $this->display_error('db_must_use_set') : FALSE;
}
- if ($table == '')
+ if ($table !== '')
{
- if ( ! isset($this->ar_from[0]))
- {
- return ($this->db_debug) ? $this->display_error('db_must_set_table') : FALSE;
- }
+ $this->qb_from[0] = $table;
}
- else
+ elseif ( ! isset($this->qb_from[0]))
{
- $this->ar_from[0] = $table;
+ return ($this->db_debug) ? $this->display_error('db_must_set_table') : FALSE;
}
return TRUE;
@@ -1613,7 +1808,7 @@ abstract class CI_DB_active_record extends CI_DB_driver {
* @param string the table to retrieve the results from
* @param array an associative array of update values
* @param string the where key
- * @return bool
+ * @return int number of rows affected or FALSE on failure
*/
public function update_batch($table = '', $set = NULL, $index = NULL)
{
@@ -1630,29 +1825,31 @@ abstract class CI_DB_active_record extends CI_DB_driver {
$this->set_update_batch($set, $index);
}
- if (count($this->ar_set) === 0)
+ if (count($this->qb_set) === 0)
{
return ($this->db_debug) ? $this->display_error('db_must_use_set') : FALSE;
}
- if ($table == '')
+ if ($table === '')
{
- if ( ! isset($this->ar_from[0]))
+ if ( ! isset($this->qb_from[0]))
{
return ($this->db_debug) ? $this->display_error('db_must_set_table') : FALSE;
}
- $table = $this->ar_from[0];
+ $table = $this->qb_from[0];
}
// Batch this baby
- for ($i = 0, $total = count($this->ar_set); $i < $total; $i += 100)
+ $affected_rows = 0;
+ for ($i = 0, $total = count($this->qb_set); $i < $total; $i += 100)
{
- $this->query($this->_update_batch($this->protect_identifiers($table, TRUE, NULL, FALSE), array_slice($this->ar_set, $i, 100), $this->protect_identifiers($index), $this->ar_where));
+ $this->query($this->_update_batch($this->protect_identifiers($table, TRUE, NULL, FALSE), array_slice($this->qb_set, $i, 100), $this->protect_identifiers($index)));
+ $affected_rows += $this->affected_rows();
}
$this->_reset_write();
- return TRUE;
+ return $affected_rows;
}
// --------------------------------------------------------------------
@@ -1665,7 +1862,7 @@ abstract class CI_DB_active_record extends CI_DB_driver {
* @param bool
* @return object
*/
- public function set_update_batch($key, $index = '', $escape = TRUE)
+ public function set_update_batch($key, $index = '', $escape = NULL)
{
$key = $this->_object_to_array_batch($key);
@@ -1674,30 +1871,28 @@ abstract class CI_DB_active_record extends CI_DB_driver {
// @todo error
}
+ is_bool($escape) OR $escape = $this->_protect_identifiers;
+
foreach ($key as $k => $v)
{
$index_set = FALSE;
$clean = array();
foreach ($v as $k2 => $v2)
{
- if ($k2 == $index)
+ if ($k2 === $index)
{
$index_set = TRUE;
}
- else
- {
- $not[] = $k.'-'.$v;
- }
- $clean[$this->protect_identifiers($k2)] = ($escape === FALSE) ? $v2 : $this->escape($v2);
+ $clean[$this->protect_identifiers($k2, FALSE, $escape)] = ($escape === FALSE) ? $v2 : $this->escape($v2);
}
- if ($index_set == FALSE)
+ if ($index_set === FALSE)
{
return $this->display_error('db_batch_missing_index');
}
- $this->ar_set[] = $clean;
+ $this->qb_set[] = $clean;
}
return $this;
@@ -1715,14 +1910,14 @@ abstract class CI_DB_active_record extends CI_DB_driver {
*/
public function empty_table($table = '')
{
- if ($table == '')
+ if ($table === '')
{
- if ( ! isset($this->ar_from[0]))
+ if ( ! isset($this->qb_from[0]))
{
return ($this->db_debug) ? $this->display_error('db_must_set_table') : FALSE;
}
- $table = $this->ar_from[0];
+ $table = $this->qb_from[0];
}
else
{
@@ -1748,14 +1943,14 @@ abstract class CI_DB_active_record extends CI_DB_driver {
*/
public function truncate($table = '')
{
- if ($table == '')
+ if ($table === '')
{
- if ( ! isset($this->ar_from[0]))
+ if ( ! isset($this->qb_from[0]))
{
return ($this->db_debug) ? $this->display_error('db_must_set_table') : FALSE;
}
- $table = $this->ar_from[0];
+ $table = $this->qb_from[0];
}
else
{
@@ -1793,7 +1988,7 @@ abstract class CI_DB_active_record extends CI_DB_driver {
* Compiles a delete query string and returns the sql
*
* @param string the table to delete from
- * @param bool TRUE: reset AR values; FALSE: leave AR values alone
+ * @param bool TRUE: reset QB values; FALSE: leave QB values alone
* @return string
*/
public function get_compiled_delete($table = '', $reset = TRUE)
@@ -1815,30 +2010,28 @@ abstract class CI_DB_active_record extends CI_DB_driver {
* @param mixed the where clause
* @param mixed the limit clause
* @param bool
- * @return object
+ * @return mixed
*/
public function delete($table = '', $where = '', $limit = NULL, $reset_data = TRUE)
{
// Combine any cached components with the current statements
$this->_merge_cache();
- if ($table == '')
+ if ($table === '')
{
- if ( ! isset($this->ar_from[0]))
+ if ( ! isset($this->qb_from[0]))
{
return ($this->db_debug) ? $this->display_error('db_must_set_table') : FALSE;
}
- $table = $this->ar_from[0];
+ $table = $this->qb_from[0];
}
elseif (is_array($table))
{
foreach ($table as $single_table)
{
- $this->delete($single_table, $where, $limit, FALSE);
+ $this->delete($single_table, $where, $limit, $reset_data);
}
-
- $this->_reset_write();
return;
}
else
@@ -1846,22 +2039,22 @@ abstract class CI_DB_active_record extends CI_DB_driver {
$table = $this->protect_identifiers($table, TRUE, NULL, FALSE);
}
- if ($where != '')
+ if ($where !== '')
{
$this->where($where);
}
- if ($limit != NULL)
+ if ( ! empty($limit))
{
$this->limit($limit);
}
- if (count($this->ar_where) === 0 && count($this->ar_wherein) === 0 && count($this->ar_like) === 0)
+ if (count($this->qb_where) === 0)
{
return ($this->db_debug) ? $this->display_error('db_del_must_use_where') : FALSE;
}
- $sql = $this->_delete($table, $this->ar_where, $this->ar_like, $this->ar_limit);
+ $sql = $this->_delete($table);
if ($reset_data)
{
$this->_reset_write();
@@ -1878,21 +2071,12 @@ abstract class CI_DB_active_record extends CI_DB_driver {
* Generates a platform-specific delete string from the supplied data
*
* @param string the table name
- * @param array the where clause
- * @param array the like clause
- * @param string the limit clause
* @return string
*/
- protected function _delete($table, $where = array(), $like = array(), $limit = FALSE)
+ protected function _delete($table)
{
- $conditions = array();
-
- empty($where) OR $conditions[] = implode(' ', $where);
- empty($like) OR $conditions[] = implode(' ', $like);
-
- return 'DELETE FROM '.$table
- .(count($conditions) > 0 ? ' WHERE '.implode(' AND ', $conditions) : '')
- .($limit ? ' LIMIT '.$limit : '');
+ return 'DELETE FROM '.$table.$this->_compile_wh('qb_where')
+ .($this->qb_limit ? ' LIMIT '.$this->qb_limit : '');
}
// --------------------------------------------------------------------
@@ -1907,7 +2091,7 @@ abstract class CI_DB_active_record extends CI_DB_driver {
*/
public function dbprefix($table = '')
{
- if ($table == '')
+ if ($table === '')
{
$this->display_error('db_table_name_required');
}
@@ -1962,15 +2146,15 @@ abstract class CI_DB_active_record extends CI_DB_driver {
if (strpos($table, ' ') !== FALSE)
{
// if the alias is written with the AS keyword, remove it
- $table = preg_replace('/ AS /i', ' ', $table);
+ $table = preg_replace('/\s+AS\s+/i', ' ', $table);
// Grab the alias
$table = trim(strrchr($table, ' '));
// Store the alias, if it doesn't already exist
- if ( ! in_array($table, $this->ar_aliased_tables))
+ if ( ! in_array($table, $this->qb_aliased_tables))
{
- $this->ar_aliased_tables[] = $table;
+ $this->qb_aliased_tables[] = $table;
}
}
}
@@ -1981,8 +2165,9 @@ abstract class CI_DB_active_record extends CI_DB_driver {
* Compile the SELECT statement
*
* Generates a query string based on which functions were used.
- * Should not be called directly. The get() function calls it.
+ * Should not be called directly.
*
+ * @param bool $select_override
* @return string
*/
protected function _compile_select($select_override = FALSE)
@@ -1997,9 +2182,9 @@ abstract class CI_DB_active_record extends CI_DB_driver {
}
else
{
- $sql = ( ! $this->ar_distinct) ? 'SELECT ' : 'SELECT DISTINCT ';
+ $sql = ( ! $this->qb_distinct) ? 'SELECT ' : 'SELECT DISTINCT ';
- if (count($this->ar_select) === 0)
+ if (count($this->qb_select) === 0)
{
$sql .= '*';
}
@@ -2008,76 +2193,178 @@ abstract class CI_DB_active_record extends CI_DB_driver {
// Cycle through the "select" portion of the query and prep each column name.
// The reason we protect identifiers here rather then in the select() function
// is because until the user calls the from() function we don't know if there are aliases
- foreach ($this->ar_select as $key => $val)
+ foreach ($this->qb_select as $key => $val)
{
- $no_escape = isset($this->ar_no_escape[$key]) ? $this->ar_no_escape[$key] : NULL;
- $this->ar_select[$key] = $this->protect_identifiers($val, FALSE, $no_escape);
+ $no_escape = isset($this->qb_no_escape[$key]) ? $this->qb_no_escape[$key] : NULL;
+ $this->qb_select[$key] = $this->protect_identifiers($val, FALSE, $no_escape);
}
- $sql .= implode(', ', $this->ar_select);
+ $sql .= implode(', ', $this->qb_select);
}
}
// Write the "FROM" portion of the query
- if (count($this->ar_from) > 0)
+ if (count($this->qb_from) > 0)
{
- $sql .= "\nFROM ".$this->_from_tables($this->ar_from);
+ $sql .= "\nFROM ".$this->_from_tables();
}
// Write the "JOIN" portion of the query
- if (count($this->ar_join) > 0)
+ if (count($this->qb_join) > 0)
{
- $sql .= "\n".implode("\n", $this->ar_join);
+ $sql .= "\n".implode("\n", $this->qb_join);
}
- // Write the "WHERE" portion of the query
- if (count($this->ar_where) > 0 OR count($this->ar_like) > 0)
+ $sql .= $this->_compile_wh('qb_where')
+ .$this->_compile_group_by()
+ .$this->_compile_wh('qb_having')
+ .$this->_compile_order_by(); // ORDER BY
+
+ // LIMIT
+ if ($this->qb_limit)
{
- $sql .= "\nWHERE ";
+ return $this->_limit($sql."\n");
}
- $sql .= implode("\n", $this->ar_where);
+ return $sql;
+ }
- // Write the "LIKE" portion of the query
- if (count($this->ar_like) > 0)
+ // --------------------------------------------------------------------
+
+ /**
+ * Compile WHERE, HAVING statements
+ *
+ * Escapes identifiers in WHERE and HAVING statements at execution time.
+ *
+ * Required so that aliases are tracked properly, regardless of wether
+ * where(), or_where(), having(), or_having are called prior to from(),
+ * join() and dbprefix is added only if needed.
+ *
+ * @param string $qb_key 'qb_where' or 'qb_having'
+ * @return string SQL statement
+ */
+ protected function _compile_wh($qb_key)
+ {
+ if (count($this->$qb_key) > 0)
{
- if (count($this->ar_where) > 0)
+ for ($i = 0, $c = count($this->$qb_key); $i < $c; $i++)
{
- $sql .= "\nAND ";
+ if ($this->{$qb_key}[$i]['escape'] === FALSE)
+ {
+ $this->{$qb_key}[$i] = $this->{$qb_key}[$i]['condition'];
+ continue;
+ }
+
+ // Split multiple conditions
+ $conditions = preg_split(
+ '/(\s*AND\s+|\s*OR\s+)/i',
+ $this->{$qb_key}[$i]['condition'],
+ -1,
+ PREG_SPLIT_DELIM_CAPTURE | PREG_SPLIT_NO_EMPTY
+ );
+
+ for ($ci = 0, $cc = count($conditions); $ci < $cc; $ci++)
+ {
+ if (($op = $this->_get_operator($conditions[$ci])) === FALSE
+ OR ! preg_match('/^(\(?)(.*)('.preg_quote($op, '/').')\s*(.*(?<!\)))?(\)?)$/i', $conditions[$ci], $matches))
+ {
+ continue;
+ }
+
+ // $matches = array(
+ // 0 => '(test <= foo)', /* the whole thing */
+ // 1 => '(', /* optional */
+ // 2 => 'test', /* the field name */
+ // 3 => ' <= ', /* $op */
+ // 4 => 'foo', /* optional, if $op is e.g. 'IS NULL' */
+ // 5 => ')' /* optional */
+ // );
+
+ if ( ! empty($matches[4]))
+ {
+ $this->_is_literal($matches[4]) OR $matches[4] = $this->protect_identifiers(trim($matches[4]));
+ $matches[4] = ' '.$matches[4];
+ }
+
+ $conditions[$ci] = $matches[1].$this->protect_identifiers(trim($matches[2]))
+ .' '.trim($matches[3]).$matches[4].$matches[5];
+ }
+
+ $this->{$qb_key}[$i] = implode('', $conditions);
}
- $sql .= implode("\n", $this->ar_like);
+ return ($qb_key === 'qb_having' ? "\nHAVING " : "\nWHERE ")
+ .implode("\n", $this->$qb_key);
}
- // Write the "GROUP BY" portion of the query
- if (count($this->ar_groupby) > 0)
- {
- $sql .= "\nGROUP BY ".implode(', ', $this->ar_groupby);
- }
+ return '';
+ }
- // Write the "HAVING" portion of the query
- if (count($this->ar_having) > 0)
+ // --------------------------------------------------------------------
+
+ /**
+ * Compile GROUP BY
+ *
+ * Escapes identifiers in GROUP BY statements at execution time.
+ *
+ * Required so that aliases are tracked properly, regardless of wether
+ * group_by() is called prior to from(), join() and dbprefix is added
+ * only if needed.
+ *
+ * @return string SQL statement
+ */
+ protected function _compile_group_by()
+ {
+ if (count($this->qb_groupby) > 0)
{
- $sql .= "\nHAVING ".implode("\n", $this->ar_having);
+ for ($i = 0, $c = count($this->qb_groupby); $i < $c; $i++)
+ {
+ $this->qb_groupby[$i] = ($this->qb_groupby[$i]['escape'] === FALSE OR $this->_is_literal($this->qb_groupby[$i]['field']))
+ ? $this->qb_groupby[$i]['field']
+ : $this->protect_identifiers($this->qb_groupby[$i]['field']);
+ }
+
+ return "\nGROUP BY ".implode(', ', $this->qb_groupby);
}
- // Write the "ORDER BY" portion of the query
- if (count($this->ar_orderby) > 0)
+ return '';
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Compile ORDER BY
+ *
+ * Escapes identifiers in ORDER BY statements at execution time.
+ *
+ * Required so that aliases are tracked properly, regardless of wether
+ * order_by() is called prior to from(), join() and dbprefix is added
+ * only if needed.
+ *
+ * @return string SQL statement
+ */
+ protected function _compile_order_by()
+ {
+ if (is_array($this->qb_orderby) && count($this->qb_orderby) > 0)
{
- $sql .= "\nORDER BY ".implode(', ', $this->ar_orderby);
- if ($this->ar_order !== FALSE)
+ for ($i = 0, $c = count($this->qb_orderby); $i < $c; $i++)
{
- $sql .= ($this->ar_order == 'desc') ? ' DESC' : ' ASC';
+ if ($this->qb_orderby[$i]['escape'] !== FALSE && ! $this->_is_literal($this->qb_orderby[$i]['field']))
+ {
+ $this->qb_orderby[$i]['field'] = $this->protect_identifiers($this->qb_orderby[$i]['field']);
+ }
+
+ $this->qb_orderby[$i] = $this->qb_orderby[$i]['field'].$this->qb_orderby[$i]['direction'];
}
- }
- // Write the "LIMIT" portion of the query
- if (is_numeric($this->ar_limit))
+ return $this->qb_orderby = "\nORDER BY ".implode(', ', $this->qb_orderby);
+ }
+ elseif (is_string($this->qb_orderby))
{
- return $this->_limit($sql."\n", $this->ar_limit, $this->ar_offset);
+ return $this->qb_orderby;
}
- return $sql;
+ return '';
}
// --------------------------------------------------------------------
@@ -2090,7 +2377,7 @@ abstract class CI_DB_active_record extends CI_DB_driver {
* @param object
* @return array
*/
- public function _object_to_array($object)
+ protected function _object_to_array($object)
{
if ( ! is_object($object))
{
@@ -2101,7 +2388,7 @@ abstract class CI_DB_active_record extends CI_DB_driver {
foreach (get_object_vars($object) as $key => $val)
{
// There are some built in keys we need to ignore for this conversion
- if ( ! is_object($val) && ! is_array($val) && $key != '_parent_name')
+ if ( ! is_object($val) && ! is_array($val) && $key !== '_parent_name')
{
$array[$key] = $val;
}
@@ -2120,7 +2407,7 @@ abstract class CI_DB_active_record extends CI_DB_driver {
* @param object
* @return array
*/
- public function _object_to_array_batch($object)
+ protected function _object_to_array_batch($object)
{
if ( ! is_object($object))
{
@@ -2152,13 +2439,13 @@ abstract class CI_DB_active_record extends CI_DB_driver {
/**
* Start Cache
*
- * Starts AR caching
+ * Starts QB caching
*
* @return void
*/
public function start_cache()
{
- $this->ar_caching = TRUE;
+ $this->qb_caching = TRUE;
}
// --------------------------------------------------------------------
@@ -2166,13 +2453,13 @@ abstract class CI_DB_active_record extends CI_DB_driver {
/**
* Stop Cache
*
- * Stops AR caching
+ * Stops QB caching
*
* @return void
*/
public function stop_cache()
{
- $this->ar_caching = FALSE;
+ $this->qb_caching = FALSE;
}
// --------------------------------------------------------------------
@@ -2180,24 +2467,23 @@ abstract class CI_DB_active_record extends CI_DB_driver {
/**
* Flush Cache
*
- * Empties the AR cache
+ * Empties the QB cache
*
* @return void
*/
public function flush_cache()
{
$this->_reset_run(array(
- 'ar_cache_select' => array(),
- 'ar_cache_from' => array(),
- 'ar_cache_join' => array(),
- 'ar_cache_where' => array(),
- 'ar_cache_like' => array(),
- 'ar_cache_groupby' => array(),
- 'ar_cache_having' => array(),
- 'ar_cache_orderby' => array(),
- 'ar_cache_set' => array(),
- 'ar_cache_exists' => array(),
- 'ar_cache_no_escape' => array()
+ 'qb_cache_select' => array(),
+ 'qb_cache_from' => array(),
+ 'qb_cache_join' => array(),
+ 'qb_cache_where' => array(),
+ 'qb_cache_groupby' => array(),
+ 'qb_cache_having' => array(),
+ 'qb_cache_orderby' => array(),
+ 'qb_cache_set' => array(),
+ 'qb_cache_exists' => array(),
+ 'qb_cache_no_escape' => array()
));
}
@@ -2206,47 +2492,76 @@ abstract class CI_DB_active_record extends CI_DB_driver {
/**
* Merge Cache
*
- * When called, this function merges any cached AR arrays with
+ * When called, this function merges any cached QB arrays with
* locally called ones.
*
* @return void
*/
protected function _merge_cache()
{
- if (count($this->ar_cache_exists) === 0)
+ if (count($this->qb_cache_exists) === 0)
{
return;
}
- foreach ($this->ar_cache_exists as $val)
+ foreach ($this->qb_cache_exists as $val)
{
- $ar_variable = 'ar_'.$val;
- $ar_cache_var = 'ar_cache_'.$val;
+ $qb_variable = 'qb_'.$val;
+ $qb_cache_var = 'qb_cache_'.$val;
- if (count($this->$ar_cache_var) === 0)
+ if (count($this->$qb_cache_var) === 0)
{
continue;
}
-
- $this->$ar_variable = array_unique(array_merge($this->$ar_cache_var, $this->$ar_variable));
+ $this->$qb_variable = array_merge($this->$qb_variable, array_diff($this->$qb_cache_var, $this->$qb_variable));
}
// If we are "protecting identifiers" we need to examine the "from"
// portion of the query to determine if there are any aliases
- if ($this->_protect_identifiers === TRUE && count($this->ar_cache_from) > 0)
+ if ($this->_protect_identifiers === TRUE && count($this->qb_cache_from) > 0)
+ {
+ $this->_track_aliases($this->qb_from);
+ }
+
+ $this->qb_no_escape = array_merge($this->qb_no_escape, array_diff($this->qb_cache_no_escape, $this->qb_no_escape));
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Is literal
+ *
+ * Determines if a string represents a literal value or a field name
+ *
+ * @param string $str
+ * @return bool
+ */
+ protected function _is_literal($str)
+ {
+ $str = trim($str);
+
+ if (empty($str) OR ctype_digit($str) OR (string) (float) $str === $str OR in_array(strtoupper($str), array('TRUE', 'FALSE'), TRUE))
{
- $this->_track_aliases($this->ar_from);
+ return TRUE;
}
- $this->ar_no_escape = $this->ar_cache_no_escape;
+ static $_str;
+
+ if (empty($_str))
+ {
+ $_str = ($this->_escape_char !== '"')
+ ? array('"', "'") : array("'");
+ }
+
+ return in_array($str[0], $_str, TRUE);
}
// --------------------------------------------------------------------
/**
- * Reset Active Record values.
+ * Reset Query Builder values.
*
- * Publicly-visible method to reset the AR values.
+ * Publicly-visible method to reset the QB values.
*
* @return void
*/
@@ -2259,47 +2574,41 @@ abstract class CI_DB_active_record extends CI_DB_driver {
// --------------------------------------------------------------------
/**
- * Resets the active record values. Called by the get() function
+ * Resets the query builder values. Called by the get() function
*
* @param array An array of fields to reset
* @return void
*/
- protected function _reset_run($ar_reset_items)
+ protected function _reset_run($qb_reset_items)
{
- foreach ($ar_reset_items as $item => $default_value)
+ foreach ($qb_reset_items as $item => $default_value)
{
- if ( ! in_array($item, $this->ar_store_array))
- {
- $this->$item = $default_value;
- }
+ $this->$item = $default_value;
}
}
// --------------------------------------------------------------------
/**
- * Resets the active record values. Called by the get() function
+ * Resets the query builder values. Called by the get() function
*
* @return void
*/
protected function _reset_select()
{
$this->_reset_run(array(
- 'ar_select' => array(),
- 'ar_from' => array(),
- 'ar_join' => array(),
- 'ar_where' => array(),
- 'ar_like' => array(),
- 'ar_groupby' => array(),
- 'ar_having' => array(),
- 'ar_orderby' => array(),
- 'ar_wherein' => array(),
- 'ar_aliased_tables' => array(),
- 'ar_no_escape' => array(),
- 'ar_distinct' => FALSE,
- 'ar_limit' => FALSE,
- 'ar_offset' => FALSE,
- 'ar_order' => FALSE
+ 'qb_select' => array(),
+ 'qb_from' => array(),
+ 'qb_join' => array(),
+ 'qb_where' => array(),
+ 'qb_groupby' => array(),
+ 'qb_having' => array(),
+ 'qb_orderby' => array(),
+ 'qb_aliased_tables' => array(),
+ 'qb_no_escape' => array(),
+ 'qb_distinct' => FALSE,
+ 'qb_limit' => FALSE,
+ 'qb_offset' => FALSE
)
);
}
@@ -2307,7 +2616,7 @@ abstract class CI_DB_active_record extends CI_DB_driver {
// --------------------------------------------------------------------
/**
- * Resets the active record "write" values.
+ * Resets the query builder "write" values.
*
* Called by the insert() update() insert_batch() update_batch() and delete() functions
*
@@ -2316,19 +2625,17 @@ abstract class CI_DB_active_record extends CI_DB_driver {
protected function _reset_write()
{
$this->_reset_run(array(
- 'ar_set' => array(),
- 'ar_from' => array(),
- 'ar_where' => array(),
- 'ar_like' => array(),
- 'ar_orderby' => array(),
- 'ar_keys' => array(),
- 'ar_limit' => FALSE,
- 'ar_order' => FALSE
+ 'qb_set' => array(),
+ 'qb_from' => array(),
+ 'qb_where' => array(),
+ 'qb_orderby' => array(),
+ 'qb_keys' => array(),
+ 'qb_limit' => FALSE
)
);
}
}
-/* End of file DB_active_rec.php */
-/* Location: ./system/database/DB_active_rec.php */ \ No newline at end of file
+/* End of file DB_query_builder.php */
+/* Location: ./system/database/DB_query_builder.php */ \ No newline at end of file
diff --git a/system/database/DB_result.php b/system/database/DB_result.php
index 196febe2c..e1ef341a5 100644
--- a/system/database/DB_result.php
+++ b/system/database/DB_result.php
@@ -1,4 +1,4 @@
-<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');
+<?php
/**
* CodeIgniter
*
@@ -24,6 +24,7 @@
* @since Version 1.0
* @filesource
*/
+defined('BASEPATH') OR exit('No direct script access allowed');
/**
* Database Result Class
@@ -38,32 +39,123 @@
*/
class CI_DB_result {
- public $conn_id = NULL;
- public $result_id = NULL;
+ /**
+ * Connection ID
+ *
+ * @var resource|object
+ */
+ public $conn_id;
+
+ /**
+ * Result ID
+ *
+ * @var resource|object
+ */
+ public $result_id;
+
+ /**
+ * Result Array
+ *
+ * @var array[]
+ */
public $result_array = array();
+
+ /**
+ * Result Object
+ *
+ * @var object[]
+ */
public $result_object = array();
+
+ /**
+ * Custom Result Object
+ *
+ * @var object[]
+ */
public $custom_result_object = array();
+
+ /**
+ * Current Row index
+ *
+ * @var int
+ */
public $current_row = 0;
- public $num_rows = 0;
- public $row_data = NULL;
+ /**
+ * Number of rows
+ *
+ * @var int
+ */
+ public $num_rows;
+
+ /**
+ * Row data
+ *
+ * @var array
+ */
+ public $row_data;
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Constructor
+ *
+ * @param object $driver_object
+ * @return void
+ */
public function __construct(&$driver_object)
{
$this->conn_id = $driver_object->conn_id;
$this->result_id = $driver_object->result_id;
}
+ // --------------------------------------------------------------------
+
/**
- * Query result. Acts as a wrapper function for the following functions.
+ * Number of rows in the result set
*
- * @param string can be "object" or "array"
- * @return object
+ * @return int
+ */
+ public function num_rows()
+ {
+ if (is_int($this->num_rows))
+ {
+ return $this->num_rows;
+ }
+ elseif (count($this->result_array) > 0)
+ {
+ return $this->num_rows = count($this->result_array);
+ }
+ elseif (count($this->result_object) > 0)
+ {
+ return $this->num_rows = count($this->result_object);
+ }
+
+ return $this->num_rows = count($this->result_array());
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Query result. Acts as a wrapper function for the following functions.
+ *
+ * @param string $type 'object', 'array' or a custom class name
+ * @return array
*/
public function result($type = 'object')
{
- if ($type === 'array') return $this->result_array();
- elseif ($type === 'object') return $this->result_object();
- else return $this->custom_result_object($type);
+ if ($type === 'array')
+ {
+ return $this->result_array();
+ }
+ elseif ($type === 'object')
+ {
+ return $this->result_object();
+ }
+ else
+ {
+ return $this->custom_result_object($type);
+ }
}
// --------------------------------------------------------------------
@@ -71,38 +163,55 @@ class CI_DB_result {
/**
* Custom query result.
*
- * @param string A string that represents the type of object you want back
- * @return array of objects
+ * @param string $class_name
+ * @return array
*/
public function custom_result_object($class_name)
{
- if (array_key_exists($class_name, $this->custom_result_object))
+ if (isset($this->custom_result_object[$class_name]))
{
return $this->custom_result_object[$class_name];
}
-
- if ($this->result_id === FALSE OR $this->num_rows() == 0)
+ elseif ( ! $this->result_id OR $this->num_rows === 0)
{
return array();
}
- // add the data to the object
- $this->_data_seek(0);
- $result_object = array();
+ // Don't fetch the result set again if we already have it
+ $_data = NULL;
+ if (($c = count($this->result_array)) > 0)
+ {
+ $_data = 'result_array';
+ }
+ elseif (($c = count($this->result_object)) > 0)
+ {
+ $_data = 'result_object';
+ }
- while ($row = $this->_fetch_object())
+ if ($_data !== NULL)
{
- $object = new $class_name();
- foreach ($row as $key => $value)
+ for ($i = 0; $i < $c; $i++)
{
- $object->$key = $value;
+ $this->custom_result_object[$class_name][$i] = new $class_name();
+
+ foreach ($this->{$_data}[$i] as $key => $value)
+ {
+ $this->custom_result_object[$class_name][$i]->$key = $value;
+ }
}
- $result_object[] = $object;
+ return $this->custom_result_object[$class_name];
}
- // return the array
- return $this->custom_result_object[$class_name] = $result_object;
+ $this->data_seek(0);
+ $this->custom_result_object[$class_name] = array();
+
+ while ($row = $this->_fetch_object($class_name))
+ {
+ $this->custom_result_object[$class_name][] = $row;
+ }
+
+ return $this->custom_result_object[$class_name];
}
// --------------------------------------------------------------------
@@ -119,15 +228,25 @@ class CI_DB_result {
return $this->result_object;
}
- // In the event that query caching is on the result_id variable
- // will return FALSE since there isn't a valid SQL resource so
- // we'll simply return an empty array.
- if ($this->result_id === FALSE OR $this->num_rows() == 0)
+ // In the event that query caching is on, the result_id variable
+ // will not be a valid resource so we'll simply return an empty
+ // array.
+ if ( ! $this->result_id OR $this->num_rows === 0)
{
return array();
}
- $this->_data_seek(0);
+ if (($c = count($this->result_array)) > 0)
+ {
+ for ($i = 0; $i < $c; $i++)
+ {
+ $this->result_object[$i] = (object) $this->result_array[$i];
+ }
+
+ return $this->result_object;
+ }
+
+ $this->data_seek(0);
while ($row = $this->_fetch_object())
{
$this->result_object[] = $row;
@@ -139,7 +258,7 @@ class CI_DB_result {
// --------------------------------------------------------------------
/**
- * Query result. "array" version.
+ * Query result. "array" version.
*
* @return array
*/
@@ -150,15 +269,25 @@ class CI_DB_result {
return $this->result_array;
}
- // In the event that query caching is on the result_id variable
- // will return FALSE since there isn't a valid SQL resource so
- // we'll simply return an empty array.
- if ($this->result_id === FALSE OR $this->num_rows() == 0)
+ // In the event that query caching is on, the result_id variable
+ // will not be a valid resource so we'll simply return an empty
+ // array.
+ if ( ! $this->result_id OR $this->num_rows === 0)
{
return array();
}
- $this->_data_seek(0);
+ if (($c = count($this->result_object)) > 0)
+ {
+ for ($i = 0; $i < $c; $i++)
+ {
+ $this->result_array[$i] = (array) $this->result_object[$i];
+ }
+
+ return $this->result_array;
+ }
+
+ $this->data_seek(0);
while ($row = $this->_fetch_assoc())
{
$this->result_array[] = $row;
@@ -170,29 +299,28 @@ class CI_DB_result {
// --------------------------------------------------------------------
/**
- * Query result. Acts as a wrapper function for the following functions.
+ * Row
*
- * @param string
- * @param string can be "object" or "array"
- * @return mixed either a result object or array
+ * A wrapper method.
+ *
+ * @param mixed $n
+ * @param string $type 'object' or 'array'
+ * @return mixed
*/
public function row($n = 0, $type = 'object')
{
if ( ! is_numeric($n))
{
// We cache the row data for subsequent uses
- if ( ! is_array($this->row_data))
- {
- $this->row_data = $this->row_array(0);
- }
+ is_array($this->row_data) OR $this->row_data = $this->row_array(0);
- // array_key_exists() instead of isset() to allow for MySQL NULL values
- if (array_key_exists($n, $this->row_data))
+ // array_key_exists() instead of isset() to allow for NULL values
+ if (empty($this->row_data) OR ! array_key_exists($n, $this->row_data))
{
- return $this->row_data[$n];
+ return NULL;
}
- // reset the $n variable if the result was not achieved
- $n = 0;
+
+ return $this->row_data[$n];
}
if ($type === 'object') return $this->row_object($n);
@@ -205,6 +333,8 @@ class CI_DB_result {
/**
* Assigns an item into a particular column slot
*
+ * @param mixed $key
+ * @param mixed $value
* @return void
*/
public function set_row($key, $value = NULL)
@@ -224,7 +354,7 @@ class CI_DB_result {
return;
}
- if ($key != '' && ! is_null($value))
+ if ($key !== '' && ! is_null($value))
{
$this->row_data[$key] = $value;
}
@@ -235,27 +365,33 @@ class CI_DB_result {
/**
* Returns a single result row - custom object version
*
+ * @param int $n
+ * @param string $type
* @return object
*/
public function custom_row_object($n, $type)
{
- $result = $this->custom_result_object($type);
- if (count($result) === 0)
+ isset($this->custom_result_object[$type]) OR $this->custom_result_object($type);
+
+ if (count($this->custom_result_object[$type]) === 0)
{
- return $result;
+ return NULL;
}
- if ($n != $this->current_row && isset($result[$n]))
+ if ($n !== $this->current_row && isset($this->custom_result_object[$type][$n]))
{
$this->current_row = $n;
}
- return $result[$this->current_row];
+ return $this->custom_result_object[$type][$this->current_row];
}
+ // --------------------------------------------------------------------
+
/**
* Returns a single result row - object version
*
+ * @param int $n
* @return object
*/
public function row_object($n = 0)
@@ -263,10 +399,10 @@ class CI_DB_result {
$result = $this->result_object();
if (count($result) === 0)
{
- return $result;
+ return NULL;
}
- if ($n != $this->current_row && isset($result[$n]))
+ if ($n !== $this->current_row && isset($result[$n]))
{
$this->current_row = $n;
}
@@ -279,6 +415,7 @@ class CI_DB_result {
/**
* Returns a single result row - array version
*
+ * @param int $n
* @return array
*/
public function row_array($n = 0)
@@ -286,10 +423,10 @@ class CI_DB_result {
$result = $this->result_array();
if (count($result) === 0)
{
- return $result;
+ return NULL;
}
- if ($n != $this->current_row && isset($result[$n]))
+ if ($n !== $this->current_row && isset($result[$n]))
{
$this->current_row = $n;
}
@@ -302,12 +439,13 @@ class CI_DB_result {
/**
* Returns the "first" row
*
- * @return object
+ * @param string $type
+ * @return mixed
*/
public function first_row($type = 'object')
{
$result = $this->result($type);
- return (count($result) === 0) ? $result : $result[0];
+ return (count($result) === 0) ? NULL : $result[0];
}
// --------------------------------------------------------------------
@@ -315,12 +453,13 @@ class CI_DB_result {
/**
* Returns the "last" row
*
- * @return object
+ * @param string $type
+ * @return mixed
*/
public function last_row($type = 'object')
{
$result = $this->result($type);
- return (count($result) === 0) ? $result : $result[count($result) - 1];
+ return (count($result) === 0) ? NULL : $result[count($result) - 1];
}
// --------------------------------------------------------------------
@@ -328,14 +467,15 @@ class CI_DB_result {
/**
* Returns the "next" row
*
- * @return object
+ * @param string $type
+ * @return mixed
*/
public function next_row($type = 'object')
{
$result = $this->result($type);
if (count($result) === 0)
{
- return $result;
+ return NULL;
}
if (isset($result[$this->current_row + 1]))
@@ -351,14 +491,15 @@ class CI_DB_result {
/**
* Returns the "previous" row
*
- * @return object
+ * @param string $type
+ * @return mixed
*/
public function previous_row($type = 'object')
{
$result = $this->result($type);
if (count($result) === 0)
{
- return $result;
+ return NULL;
}
if (isset($result[$this->current_row - 1]))
@@ -371,7 +512,29 @@ class CI_DB_result {
// --------------------------------------------------------------------
/**
- * The following functions are normally overloaded by the identically named
+ * Returns an unbuffered row and move pointer to next row
+ *
+ * @param string $type 'array', 'object' or a custom class name
+ * @return mixed
+ */
+ public function unbuffered_row($type = 'object')
+ {
+ if ($type === 'array')
+ {
+ return $this->_fetch_assoc();
+ }
+ elseif ($type === 'object')
+ {
+ return $this->_fetch_object();
+ }
+
+ return $this->_fetch_object($type);
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * The following methods are normally overloaded by the identically named
* methods in the platform-specific driver -- except when query caching
* is used. When caching is enabled we do not load the other driver.
* These functions are primarily here to prevent undefined function errors
@@ -379,14 +542,118 @@ class CI_DB_result {
* operational due to the unavailability of the database resource IDs with
* cached results.
*/
- public function num_rows() { return $this->num_rows; }
- public function num_fields() { return 0; }
- public function list_fields() { return array(); }
- public function field_data() { return array(); }
- public function free_result() { $this->result_id = FALSE; }
- protected function _data_seek() { return FALSE; }
- protected function _fetch_assoc() { return array(); }
- protected function _fetch_object() { return array(); }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Number of fields in the result set
+ *
+ * Overriden by driver result classes.
+ *
+ * @return int
+ */
+ public function num_fields()
+ {
+ return 0;
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Fetch Field Names
+ *
+ * Generates an array of column names.
+ *
+ * Overriden by driver result classes.
+ *
+ * @return array
+ */
+ public function list_fields()
+ {
+ return array();
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Field data
+ *
+ * Generates an array of objects containing field meta-data.
+ *
+ * Overriden by driver result classes.
+ *
+ * @return array
+ */
+ public function field_data()
+ {
+ return array();
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Free the result
+ *
+ * Overriden by driver result classes.
+ *
+ * @return void
+ */
+ public function free_result()
+ {
+ $this->result_id = FALSE;
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Data Seek
+ *
+ * Moves the internal pointer to the desired offset. We call
+ * this internally before fetching results to make sure the
+ * result set starts at zero.
+ *
+ * Overriden by driver result classes.
+ *
+ * @param int $n
+ * @return bool
+ */
+ public function data_seek($n = 0)
+ {
+ return FALSE;
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Result - associative array
+ *
+ * Returns the result set as an array.
+ *
+ * Overriden by driver result classes.
+ *
+ * @return array
+ */
+ protected function _fetch_assoc()
+ {
+ return array();
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Result - object
+ *
+ * Returns the result set as an object.
+ *
+ * Overriden by driver result classes.
+ *
+ * @param string $class_name
+ * @return object
+ */
+ protected function _fetch_object($class_name = 'stdClass')
+ {
+ return array();
+ }
}
diff --git a/system/database/DB_utility.php b/system/database/DB_utility.php
index 587dfdc01..c4140aef3 100644
--- a/system/database/DB_utility.php
+++ b/system/database/DB_utility.php
@@ -1,4 +1,4 @@
-<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');
+<?php
/**
* CodeIgniter
*
@@ -24,6 +24,7 @@
* @since Version 1.0
* @filesource
*/
+defined('BASEPATH') OR exit('No direct script access allowed');
/**
* Database Utility Class
@@ -32,21 +33,49 @@
* @author EllisLab Dev Team
* @link http://codeigniter.com/user_guide/database/
*/
-abstract class CI_DB_utility extends CI_DB_forge {
+abstract class CI_DB_utility {
- public $db;
- public $data_cache = array();
+ /**
+ * Database object
+ *
+ * @var object
+ */
+ protected $db;
+
+ // --------------------------------------------------------------------
+
+ /**
+ * List databases statement
+ *
+ * @var string
+ */
+ protected $_list_databases = FALSE;
- // Platform specific SQL strings
- // Just setting those defaults to FALSE as they are mostly MySQL-specific
+ /**
+ * OPTIMIZE TABLE statement
+ *
+ * @var string
+ */
protected $_optimize_table = FALSE;
+
+ /**
+ * REPAIR TABLE statement
+ *
+ * @var string
+ */
protected $_repair_table = FALSE;
- public function __construct()
+ // --------------------------------------------------------------------
+
+ /**
+ * Class constructor
+ *
+ * @param object &$db Database object
+ * @return void
+ */
+ public function __construct(&$db)
{
- // Assign the main database object to $this->db
- $CI =& get_instance();
- $this->db =& $CI->db;
+ $this->db =& $db;
log_message('debug', 'Database Utility Class Initialized');
}
@@ -60,29 +89,29 @@ abstract class CI_DB_utility extends CI_DB_forge {
public function list_databases()
{
// Is there a cached result?
- if (isset($this->data_cache['db_names']))
+ if (isset($this->db->data_cache['db_names']))
{
- return $this->data_cache['db_names'];
+ return $this->db->data_cache['db_names'];
}
elseif ($this->_list_databases === FALSE)
{
- return ($this->db->db_debug) ? $this->db->display_error('db_unsuported_feature') : FALSE;
+ return ($this->db->db_debug) ? $this->db->display_error('db_unsupported_feature') : FALSE;
}
- $this->data_cache['db_names'] = array();
+ $this->db->data_cache['db_names'] = array();
$query = $this->db->query($this->_list_databases);
if ($query === FALSE)
{
- return $this->data_cache['db_names'];
+ return $this->db->data_cache['db_names'];
}
- for ($i = 0, $c = count($query); $i < $c; $i++)
+ for ($i = 0, $query = $query->result_array(), $c = count($query); $i < $c; $i++)
{
- $this->data_cache['db_names'] = current($query[$i]);
+ $this->db->data_cache['db_names'][] = current($query[$i]);
}
- return $this->data_cache['db_names'];
+ return $this->db->data_cache['db_names'];
}
// --------------------------------------------------------------------
@@ -90,7 +119,7 @@ abstract class CI_DB_utility extends CI_DB_forge {
/**
* Determine if a particular database exists
*
- * @param string
+ * @param string $database_name
* @return bool
*/
public function database_exists($database_name)
@@ -103,21 +132,21 @@ abstract class CI_DB_utility extends CI_DB_forge {
/**
* Optimize Table
*
- * @param string the table name
+ * @param string $table_name
* @return mixed
*/
public function optimize_table($table_name)
{
if ($this->_optimize_table === FALSE)
{
- return ($this->db->db_debug) ? $this->db->display_error('db_unsuported_feature') : FALSE;
+ return ($this->db->db_debug) ? $this->db->display_error('db_unsupported_feature') : FALSE;
}
$query = $this->db->query(sprintf($this->_optimize_table, $this->db->escape_identifiers($table_name)));
if ($query !== FALSE)
{
$query = $query->result_array();
- return current($res);
+ return current($query);
}
return FALSE;
@@ -134,7 +163,7 @@ abstract class CI_DB_utility extends CI_DB_forge {
{
if ($this->_optimize_table === FALSE)
{
- return ($this->db->db_debug) ? $this->db->display_error('db_unsuported_feature') : FALSE;
+ return ($this->db->db_debug) ? $this->db->display_error('db_unsupported_feature') : FALSE;
}
$result = array();
@@ -164,14 +193,14 @@ abstract class CI_DB_utility extends CI_DB_forge {
/**
* Repair Table
*
- * @param string the table name
+ * @param string $table_name
* @return mixed
*/
public function repair_table($table_name)
{
if ($this->_repair_table === FALSE)
{
- return ($this->db->db_debug) ? $this->db->display_error('db_unsuported_feature') : FALSE;
+ return ($this->db->db_debug) ? $this->db->display_error('db_unsupported_feature') : FALSE;
}
$query = $this->db->query(sprintf($this->_repair_table, $this->db->escape_identifiers($table_name)));
@@ -189,10 +218,10 @@ abstract class CI_DB_utility extends CI_DB_forge {
/**
* Generate CSV from a query result object
*
- * @param object The query result object
- * @param string The delimiter - comma by default
- * @param string The newline character - \n by default
- * @param string The enclosure - double quote by default
+ * @param object $query Query result object
+ * @param string $delim Delimiter (default: ,)
+ * @param string $newline Newline character (default: \n)
+ * @param string $enclosure Enclosure (default: ")
* @return string
*/
public function csv_from_result($query, $delim = ',', $newline = "\n", $enclosure = '"')
@@ -212,7 +241,7 @@ abstract class CI_DB_utility extends CI_DB_forge {
$out = rtrim($out).$newline;
// Next blast through the result array and build out the rows
- foreach ($query->result_array() as $row)
+ while ($row = $query->unbuffered_row('array'))
{
foreach ($row as $item)
{
@@ -229,8 +258,8 @@ abstract class CI_DB_utility extends CI_DB_forge {
/**
* Generate XML data from a query result object
*
- * @param object The query result object
- * @param array Any preferences
+ * @param object $query Query result object
+ * @param array $params Any preferences
* @return string
*/
public function xml_from_result($query, $params = array())
@@ -258,7 +287,7 @@ abstract class CI_DB_utility extends CI_DB_forge {
// Generate the result
$xml = '<'.$root.'>'.$newline;
- foreach ($query->result_array() as $row)
+ while ($row = $query->unbuffered_row())
{
$xml .= $tab.'<'.$element.'>'.$newline;
foreach ($row as $key => $val)
@@ -276,6 +305,7 @@ abstract class CI_DB_utility extends CI_DB_forge {
/**
* Database Backup
*
+ * @param array $params
* @return void
*/
public function backup($params = array())
@@ -288,8 +318,6 @@ abstract class CI_DB_utility extends CI_DB_forge {
$params = array('tables' => $params);
}
- // ------------------------------------------------------
-
// Set up our default preferences
$prefs = array(
'tables' => array(),
@@ -333,7 +361,7 @@ abstract class CI_DB_utility extends CI_DB_forge {
{
if ($this->db->db_debug)
{
- return $this->db->display_error('db_unsuported_compression');
+ return $this->db->display_error('db_unsupported_compression');
}
$prefs['format'] = 'txt';
@@ -343,7 +371,7 @@ abstract class CI_DB_utility extends CI_DB_forge {
if ($prefs['format'] === 'zip')
{
// Set the filename if not provided (only needed with Zip files)
- if ($prefs['filename'] == '')
+ if ($prefs['filename'] === '')
{
$prefs['filename'] = (count($prefs['tables']) === 1 ? $prefs['tables'] : $this->db->database)
.date('Y-m-d_H-i', time()).'.sql';
@@ -369,7 +397,7 @@ abstract class CI_DB_utility extends CI_DB_forge {
$CI->zip->add_data($prefs['filename'], $this->_backup($prefs));
return $CI->zip->get_zip();
}
- elseif ($prefs['format'] == 'txt') // Was a text file requested?
+ elseif ($prefs['format'] === 'txt') // Was a text file requested?
{
return $this->_backup($prefs);
}
diff --git a/system/database/drivers/cubrid/cubrid_driver.php b/system/database/drivers/cubrid/cubrid_driver.php
index 7a5c048f9..21994b093 100644
--- a/system/database/drivers/cubrid/cubrid_driver.php
+++ b/system/database/drivers/cubrid/cubrid_driver.php
@@ -1,4 +1,4 @@
-<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');
+<?php
/**
* CodeIgniter
*
@@ -21,15 +21,16 @@
* @copyright Copyright (c) 2008 - 2012, EllisLab, Inc. (http://ellislab.com/)
* @license http://opensource.org/licenses/OSL-3.0 Open Software License (OSL 3.0)
* @link http://codeigniter.com
- * @since Version 2.0.2
+ * @since Version 2.1
* @filesource
*/
+defined('BASEPATH') OR exit('No direct script access allowed');
/**
* CUBRID Database Adapter Class
*
* Note: _DB is an extender class that the app controller
- * creates dynamically based on whether the active record
+ * creates dynamically based on whether the query builder
* class is being used or not.
*
* @package CodeIgniter
@@ -40,26 +41,44 @@
*/
class CI_DB_cubrid_driver extends CI_DB {
+ /**
+ * Database driver
+ *
+ * @var string
+ */
public $dbdriver = 'cubrid';
- // The character used for escaping - no need in CUBRID
- protected $_escape_char = '';
+ /**
+ * Auto-commit flag
+ *
+ * @var bool
+ */
+ public $auto_commit = TRUE;
- // clause and character used for LIKE escape sequences - not used in CUBRID
- protected $_like_escape_str = '';
- protected $_like_escape_chr = '';
+ // --------------------------------------------------------------------
/**
- * The syntax to count rows is slightly different across different
- * database engines, so this string appears in each driver and is
- * used for the count_all() and count_all_results() functions.
+ * Identifier escape character
+ *
+ * @var string
*/
- protected $_count_string = 'SELECT COUNT(*) AS ';
- protected $_random_keyword = ' RAND()'; // database specific random keyword
+ protected $_escape_char = '`';
- // CUBRID-specific properties
- public $auto_commit = TRUE;
+ /**
+ * ORDER BY random keyword
+ *
+ * @var array
+ */
+ protected $_random_keyword = array('RANDOM()', 'RANDOM(%d)');
+
+ // --------------------------------------------------------------------
+ /**
+ * Class constructor
+ *
+ * @param array $params
+ * @return void
+ */
public function __construct($params)
{
parent::__construct($params);
@@ -74,10 +93,12 @@ class CI_DB_cubrid_driver extends CI_DB {
else
{
// If no port is defined by the user, use the default value
- $this->port == '' OR $this->port = 33000;
+ empty($this->port) OR $this->port = 33000;
}
}
+ // --------------------------------------------------------------------
+
/**
* Non-persistent database connection
*
@@ -115,7 +136,7 @@ class CI_DB_cubrid_driver extends CI_DB {
* Except for determining if a persistent connection should be used,
* the rest of the logic is the same for db_connect() and db_pconnect().
*
- * @param bool
+ * @param bool $persistent
* @return resource
*/
protected function _cubrid_connect($persistent = FALSE)
@@ -165,9 +186,18 @@ class CI_DB_cubrid_driver extends CI_DB {
*/
public function version()
{
- return isset($this->data_cache['version'])
- ? $this->data_cache['version']
- : $this->data_cache['version'] = cubrid_get_server_info($this->conn_id);
+ if (isset($this->data_cache['version']))
+ {
+ return $this->data_cache['version'];
+ }
+ elseif ( ! $this->conn_id)
+ {
+ $this->initialize();
+ }
+
+ return ( ! $this->conn_id OR ($version = cubrid_get_server_info($this->conn_id)) === FALSE)
+ ? FALSE
+ : $this->data_cache['version'] = $version;
}
// --------------------------------------------------------------------
@@ -175,7 +205,7 @@ class CI_DB_cubrid_driver extends CI_DB {
/**
* Execute the query
*
- * @param string an SQL query
+ * @param string $sql an SQL query
* @return resource
*/
protected function _execute($sql)
@@ -188,17 +218,13 @@ class CI_DB_cubrid_driver extends CI_DB {
/**
* Begin Transaction
*
+ * @param bool $test_mode
* @return bool
*/
public function trans_begin($test_mode = FALSE)
{
- if ( ! $this->trans_enabled)
- {
- return TRUE;
- }
-
// When transactions are nested we only begin/commit/rollback the outermost ones
- if ($this->_trans_depth > 0)
+ if ( ! $this->trans_enabled OR $this->_trans_depth > 0)
{
return TRUE;
}
@@ -206,7 +232,7 @@ class CI_DB_cubrid_driver extends CI_DB {
// Reset the transaction failure flag.
// If the $test_mode flag is set to TRUE transactions will be rolled back
// even if the queries produce a successful result.
- $this->_trans_failure = ($test_mode === TRUE) ? TRUE : FALSE;
+ $this->_trans_failure = ($test_mode === TRUE);
if (cubrid_get_autocommit($this->conn_id))
{
@@ -225,13 +251,8 @@ class CI_DB_cubrid_driver extends CI_DB {
*/
public function trans_commit()
{
- if ( ! $this->trans_enabled)
- {
- return TRUE;
- }
-
// When transactions are nested we only begin/commit/rollback the outermost ones
- if ($this->_trans_depth > 0)
+ if ( ! $this->trans_enabled OR $this->_trans_depth > 0)
{
return TRUE;
}
@@ -255,13 +276,8 @@ class CI_DB_cubrid_driver extends CI_DB {
*/
public function trans_rollback()
{
- if ( ! $this->trans_enabled)
- {
- return TRUE;
- }
-
// When transactions are nested we only begin/commit/rollback the outermost ones
- if ($this->_trans_depth > 0)
+ if ( ! $this->trans_enabled OR $this->_trans_depth > 0)
{
return TRUE;
}
@@ -281,8 +297,8 @@ class CI_DB_cubrid_driver extends CI_DB {
/**
* Escape String
*
- * @param string
- * @param bool whether or not the string will be used in a LIKE condition
+ * @param string $str
+ * @param bool $like Whether or not the string will be used in a LIKE condition
* @return string
*/
public function escape_str($str, $like = FALSE)
@@ -297,7 +313,9 @@ class CI_DB_cubrid_driver extends CI_DB {
return $str;
}
- if (function_exists('cubrid_real_escape_string') AND is_resource($this->conn_id))
+ if (function_exists('cubrid_real_escape_string') &&
+ (is_resource($this->conn_id)
+ OR (get_resource_type($this->conn_id) === 'Unknown' && preg_match('/Resource id #/', strval($this->conn_id)))))
{
$str = cubrid_real_escape_string($str, $this->conn_id);
}
@@ -309,7 +327,7 @@ class CI_DB_cubrid_driver extends CI_DB {
// escape LIKE condition wildcards
if ($like === TRUE)
{
- $str = str_replace(array('%', '_'), array('\\%', '\\_'), $str);
+ return str_replace(array('%', '_'), array('\\%', '\\_'), $str);
}
return $str;
@@ -342,49 +360,20 @@ class CI_DB_cubrid_driver extends CI_DB {
// --------------------------------------------------------------------
/**
- * "Count All" query
- *
- * Generates a platform-specific query string that counts all records in
- * the specified table
- *
- * @param string
- * @return int
- */
- public function count_all($table = '')
- {
- if ($table == '')
- {
- return 0;
- }
-
- $query = $this->query($this->_count_string.$this->protect_identifiers('numrows').' FROM '.$this->protect_identifiers($table, TRUE, NULL, FALSE));
- if ($query->num_rows() == 0)
- {
- return 0;
- }
-
- $row = $query->row();
- $this->_reset_select();
- return (int) $row->numrows;
- }
-
- // --------------------------------------------------------------------
-
- /**
* List table query
*
* Generates a platform-specific query string so that the table names can be fetched
*
- * @param bool
+ * @param bool $prefix_limit
* @return string
*/
protected function _list_tables($prefix_limit = FALSE)
{
- $sql = "SHOW TABLES";
+ $sql = 'SHOW TABLES';
- if ($prefix_limit !== FALSE AND $this->dbprefix != '')
+ if ($prefix_limit !== FALSE && $this->dbprefix !== '')
{
- $sql .= " LIKE '".$this->escape_like_str($this->dbprefix)."%'";
+ return $sql." LIKE '".$this->escape_like_str($this->dbprefix)."%'";
}
return $sql;
@@ -397,7 +386,7 @@ class CI_DB_cubrid_driver extends CI_DB {
*
* Generates a platform-specific query string so that the column names can be fetched
*
- * @param string the table name
+ * @param string $table
* @return string
*/
protected function _list_columns($table = '')
@@ -408,16 +397,40 @@ class CI_DB_cubrid_driver extends CI_DB {
// --------------------------------------------------------------------
/**
- * Field data query
- *
- * Generates a platform-specific query so that the column data can be retrieved
+ * Returns an object with field data
*
- * @param string the table name
- * @return string
+ * @param string $table
+ * @return array
*/
- protected function _field_data($table)
+ public function field_data($table = '')
{
- return "SELECT * FROM ".$table." LIMIT 1";
+ if ($table === '')
+ {
+ return ($this->db_debug) ? $this->display_error('db_field_param_missing') : FALSE;
+ }
+
+ if (($query = $this->query('SHOW COLUMNS FROM '.$this->protect_identifiers($table, TRUE, NULL, FALSE))) === FALSE)
+ {
+ return FALSE;
+ }
+ $query = $query->result_object();
+
+ $retval = array();
+ for ($i = 0, $c = count($query); $i < $c; $i++)
+ {
+ $retval[$i] = new stdClass();
+ $retval[$i]->name = $query[$i]->Field;
+
+ sscanf($query[$i]->Type, '%[a-z](%d)',
+ $retval[$i]->type,
+ $retval[$i]->max_length
+ );
+
+ $retval[$i]->default = $query[$i]->Default;
+ $retval[$i]->primary_key = (int) ($query[$i]->Key === 'PRI');
+ }
+
+ return $retval;
}
// --------------------------------------------------------------------
@@ -438,99 +451,62 @@ class CI_DB_cubrid_driver extends CI_DB {
// --------------------------------------------------------------------
/**
- * From Tables
- *
- * This function implicitly groups FROM tables so there is no confusion
- * about operator precedence in harmony with SQL standards
- *
- * @param array
- * @return string
- */
- protected function _from_tables($tables)
- {
- if ( ! is_array($tables))
- {
- $tables = array($tables);
- }
-
- return '('.implode(', ', $tables).')';
- }
-
- // --------------------------------------------------------------------
-
- /**
* Update_Batch statement
*
* Generates a platform-specific batch update string from the supplied data
*
- * @param string the table name
- * @param array the update data
- * @param array the where clause
+ * @param string $table Table name
+ * @param array $values Update data
+ * @param string $index WHERE key
* @return string
*/
- protected function _update_batch($table, $values, $index, $where = NULL)
+ protected function _update_batch($table, $values, $index)
{
$ids = array();
- $where = ($where != '' AND count($where) >=1) ? implode(" ", $where).' AND ' : '';
-
foreach ($values as $key => $val)
{
$ids[] = $val[$index];
foreach (array_keys($val) as $field)
{
- if ($field != $index)
+ if ($field !== $index)
{
$final[$field][] = 'WHEN '.$index.' = '.$val[$index].' THEN '.$val[$field];
}
}
}
- $sql = "UPDATE ".$table." SET ";
$cases = '';
-
foreach ($final as $k => $v)
{
- $cases .= $k.' = CASE '."\n";
- foreach ($v as $row)
- {
- $cases .= $row."\n";
- }
-
- $cases .= 'ELSE '.$k.' END, ';
+ $cases .= $k." = CASE \n"
+ .implode("\n", $v)
+ .'ELSE '.$k.' END, ';
}
- $sql .= substr($cases, 0, -2);
+ $this->where($index.' IN('.implode(',', $ids).')', NULL, FALSE);
- $sql .= ' WHERE '.$where.$index.' IN ('.implode(',', $ids).')';
-
- return $sql;
+ return 'UPDATE '.$table.' SET '.substr($cases, 0, -2).$this->_compile_wh('qb_where');
}
// --------------------------------------------------------------------
/**
- * Limit string
+ * FROM tables
*
- * Generates a platform-specific LIMIT clause
+ * Groups tables in FROM clauses if needed, so there is no confusion
+ * about operator precedence.
*
- * @param string the sql query string
- * @param int the number of rows to limit the query to
- * @param int the offset value
* @return string
*/
- protected function _limit($sql, $limit, $offset)
+ protected function _from_tables()
{
- if ($offset == 0)
- {
- $offset = '';
- }
- else
+ if ( ! empty($this->qb_join) && count($this->qb_from) > 1)
{
- $offset .= ", ";
+ return '('.implode(', ', $this->qb_from).')';
}
- return $sql."LIMIT ".$offset.$limit;
+ return implode(', ', $this->qb_from);
}
// --------------------------------------------------------------------
@@ -538,12 +514,11 @@ class CI_DB_cubrid_driver extends CI_DB {
/**
* Close DB Connection
*
- * @param resource
* @return void
*/
- protected function _close($conn_id)
+ protected function _close()
{
- @cubrid_close($conn_id);
+ @cubrid_close($this->conn_id);
}
}
diff --git a/system/database/drivers/cubrid/cubrid_forge.php b/system/database/drivers/cubrid/cubrid_forge.php
index 16478ee11..2a737c5ed 100644
--- a/system/database/drivers/cubrid/cubrid_forge.php
+++ b/system/database/drivers/cubrid/cubrid_forge.php
@@ -1,4 +1,4 @@
-<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');
+<?php
/**
* CodeIgniter
*
@@ -21,9 +21,10 @@
* @copyright Copyright (c) 2008 - 2012, EllisLab, Inc. (http://ellislab.com/)
* @license http://opensource.org/licenses/OSL-3.0 Open Software License (OSL 3.0)
* @link http://codeigniter.com
- * @since Version 1.0
+ * @since Version 2.1
* @filesource
*/
+defined('BASEPATH') OR exit('No direct script access allowed');
/**
* CUBRID Forge Class
@@ -34,195 +35,181 @@
*/
class CI_DB_cubrid_forge extends CI_DB_forge {
+ /**
+ * CREATE DATABASE statement
+ *
+ * @var string
+ */
protected $_create_database = FALSE;
- protected $_drop_database = FALSE;
/**
- * Process Fields
+ * CREATE TABLE keys flag
*
- * @param mixed the fields
- * @return string
+ * Whether table keys are created from within the
+ * CREATE TABLE statement.
+ *
+ * @var bool
*/
- protected function _process_fields($fields)
- {
- $current_field_count = 0;
- $sql = '';
+ protected $_create_table_keys = TRUE;
- foreach ($fields as $field => $attributes)
- {
- // Numeric field names aren't allowed in databases, so if the key is
- // numeric, we know it was assigned by PHP and the developer manually
- // entered the field information, so we'll simply add it to the list
- if (is_numeric($field))
- {
- $sql .= "\n\t$attributes";
- }
- else
- {
- $attributes = array_change_key_case($attributes, CASE_UPPER);
-
- $sql .= "\n\t\"".$this->db->protect_identifiers($field).'"';
-
- if (array_key_exists('NAME', $attributes))
- {
- $sql .= ' '.$this->db->protect_identifiers($attributes['NAME']).' ';
- }
-
- if (array_key_exists('TYPE', $attributes))
- {
- $sql .= ' '.$attributes['TYPE'];
-
- if (array_key_exists('CONSTRAINT', $attributes))
- {
- switch ($attributes['TYPE'])
- {
- case 'decimal':
- case 'float':
- case 'numeric':
- $sql .= '('.implode(',', $attributes['CONSTRAINT']).')';
- break;
- case 'enum': // As of version 8.4.0 CUBRID does not support
- // enum data type.
- break;
- case 'set':
- $sql .= '("'.implode('","', $attributes['CONSTRAINT']).'")';
- break;
- default:
- $sql .= '('.$attributes['CONSTRAINT'].')';
- }
- }
- }
+ /**
+ * DROP DATABASE statement
+ *
+ * @var string
+ */
+ protected $_drop_database = FALSE;
- if (array_key_exists('UNSIGNED', $attributes) && $attributes['UNSIGNED'] === TRUE)
- {
- //$sql .= ' UNSIGNED';
- // As of version 8.4.0 CUBRID does not support UNSIGNED INTEGER data type.
- // Will be supported in the next release as a part of MySQL Compatibility.
- }
+ /**
+ * CREATE TABLE IF statement
+ *
+ * @var string
+ */
+ protected $_create_table_if = FALSE;
- if (array_key_exists('DEFAULT', $attributes))
- {
- $sql .= ' DEFAULT \''.$attributes['DEFAULT'].'\'';
- }
+ /**
+ * UNSIGNED support
+ *
+ * @var array
+ */
+ protected $_unsigned = array(
+ 'SHORT' => 'INTEGER',
+ 'SMALLINT' => 'INTEGER',
+ 'INT' => 'BIGINT',
+ 'INTEGER' => 'BIGINT',
+ 'BIGINT' => 'NUMERIC',
+ 'FLOAT' => 'DOUBLE',
+ 'REAL' => 'DOUBLE'
+ );
- if (array_key_exists('NULL', $attributes) && $attributes['NULL'] === TRUE)
- {
- $sql .= ' NULL';
- }
- else
- {
- $sql .= ' NOT NULL';
- }
+ // --------------------------------------------------------------------
- if (array_key_exists('AUTO_INCREMENT', $attributes) && $attributes['AUTO_INCREMENT'] === TRUE)
- {
- $sql .= ' AUTO_INCREMENT';
- }
+ /**
+ * ALTER TABLE
+ *
+ * @param string $alter_type ALTER type
+ * @param string $table Table name
+ * @param mixed $field Column definition
+ * @return string|string[]
+ */
+ protected function _alter_table($alter_type, $table, $field)
+ {
+ if (in_array($alter_type, array('DROP', 'ADD'), TRUE))
+ {
+ return parent::_alter_table($alter_type, $table, $field);
+ }
- if (array_key_exists('UNIQUE', $attributes) && $attributes['UNIQUE'] === TRUE)
- {
- $sql .= ' UNIQUE';
- }
+ $sql = 'ALTER TABLE '.$this->db->escape_identifiers($table);
+ $sqls = array();
+ for ($i = 0, $c = count($field); $i < $c; $i++)
+ {
+ if ($field[$i]['_literal'] !== FALSE)
+ {
+ $sqls[] = $sql.' CHANGE '.$field[$i]['_literal'];
}
-
- // don't add a comma on the end of the last field
- if (++$current_field_count < count($fields))
+ else
{
- $sql .= ',';
+ $alter_type = empty($field[$i]['new_name']) ? ' MODIFY ' : ' CHANGE ';
+ $sqls[] = $sql.$alter_type$this->_process_column($field[$i]);
}
}
- return $sql;
+ return $sqls;
}
// --------------------------------------------------------------------
/**
- * Create Table
+ * Process column
*
- * @param string the table name
- * @param mixed the fields
- * @param mixed primary key(s)
- * @param mixed key(s)
- * @param bool should 'IF NOT EXISTS' be added to the SQL
- * @return bool
+ * @param array $field
+ * @return string
*/
- protected function _create_table($table, $fields, $primary_keys, $keys, $if_not_exists)
+ protected function _process_column($field)
{
- $sql = 'CREATE TABLE ';
+ $extra_clause = isset($field['after'])
+ ? ' AFTER '.$this->db->escape_identifiers($field['after']) : '';
- if ($if_not_exists === TRUE)
+ if (empty($extra_clause) && isset($field['first']) && $field['first'] === TRUE)
{
- //$sql .= 'IF NOT EXISTS ';
- // As of version 8.4.0 CUBRID does not support this SQL syntax.
+ $extra_clause = ' FIRST';
}
- $sql .= $this->db->escape_identifiers($table).' ('.$this->_process_fields($fields);
-
- // If there is a PK defined
- if (count($primary_keys) > 0)
- {
- $key_name = 'pk_'.$table.'_'.$this->db->protect_identifiers(implode('_', $primary_keys));
+ return $this->db->escape_identifiers($field['name'])
+ .(empty($field['new_name']) ? '' : ' '.$this->db->escape_identifiers($field['new_name']))
+ .' '.$field['type'].$field['length']
+ .$field['unsigned']
+ .$field['null']
+ .$field['default']
+ .$field['auto_increment']
+ .$field['unique']
+ .$extra_clause;
+ }
- $primary_keys = $this->db->protect_identifiers($primary_keys);
- $sql .= ",\n\tCONSTRAINT " . $key_name . " PRIMARY KEY(" . implode(', ', $primary_keys) . ")";
- }
+ // --------------------------------------------------------------------
- if (is_array($keys) && count($keys) > 0)
+ /**
+ * Field attribute TYPE
+ *
+ * Performs a data type mapping between different databases.
+ *
+ * @param array &$attributes
+ * @return void
+ */
+ protected function _attr_type(&$attributes)
+ {
+ switch (strtoupper($attributes['TYPE']))
{
- foreach ($keys as $key)
- {
- if (is_array($key))
- {
- $key_name = $this->db->protect_identifiers(implode('_', $key));
- $key = $this->db->protect_identifiers($key);
- }
- else
- {
- $key_name = $this->db->protect_identifiers($key);
- $key = array($key_name);
- }
-
- $sql .= ",\n\tKEY \"{$key_name}\" (" . implode(', ', $key) . ")";
- }
+ case 'TINYINT':
+ $attributes['TYPE'] = 'SMALLINT';
+ $attributes['UNSIGNED'] = FALSE;
+ return;
+ case 'MEDIUMINT':
+ $attributes['TYPE'] = 'INTEGER';
+ $attributes['UNSIGNED'] = FALSE;
+ return;
+ default: return;
}
-
- $sql .= "\n);";
-
- return $sql;
}
// --------------------------------------------------------------------
/**
- * Alter table query
+ * Process indexes
*
- * Generates a platform-specific query so that a table can be altered
- * Called by add_column(), drop_column(), and column_alter(),
- *
- * @param string the ALTER type (ADD, DROP, CHANGE)
- * @param string the column name
- * @param array fields
- * @param string the field after which we should add the new field
+ * @param string $table (ignored)
* @return string
*/
- protected function _alter_table($alter_type, $table, $fields, $after_field = '')
+ protected function _process_indexes($table)
{
- $sql = 'ALTER TABLE '.$this->db->protect_identifiers($table).' '.$alter_type.' ';
+ $sql = '';
- // DROP has everything it needs now.
- if ($alter_type == 'DROP')
+ for ($i = 0, $c = count($this->keys); $i < $c; $i++)
{
- return $sql.$this->db->protect_identifiers($fields);
- }
+ 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;
+ }
- $sql .= $this->_process_fields($fields);
+ is_array($this->keys[$i]) OR $this->keys[$i] = array($this->keys[$i]);
- if ($after_field != '')
- {
- return $sql.' AFTER '.$this->db->protect_identifiers($after_field);
+ $sql .= ",\n\tKEY ".$this->db->escape_identifiers(implode('_', $this->keys[$i]))
+ .' ('.implode(', ', $this->db->escape_identifiers($this->keys[$i])).')';
}
+ $this->keys = array();
+
return $sql;
}
diff --git a/system/database/drivers/cubrid/cubrid_result.php b/system/database/drivers/cubrid/cubrid_result.php
index 58dcff29a..793b35b74 100644
--- a/system/database/drivers/cubrid/cubrid_result.php
+++ b/system/database/drivers/cubrid/cubrid_result.php
@@ -1,4 +1,4 @@
-<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');
+<?php
/**
* CodeIgniter
*
@@ -21,9 +21,10 @@
* @copyright Copyright (c) 2008 - 2012, EllisLab, Inc. (http://ellislab.com/)
* @license http://opensource.org/licenses/OSL-3.0 Open Software License (OSL 3.0)
* @link http://codeigniter.com
- * @since Version 2.0.2
+ * @since Version 2.1
* @filesource
*/
+defined('BASEPATH') OR exit('No direct script access allowed');
/**
* CUBRID Result Class
@@ -33,6 +34,7 @@
* @category Database
* @author Esen Sagynov
* @link http://codeigniter.com/user_guide/database/
+ * @since 2.1
*/
class CI_DB_cubrid_result extends CI_DB_result {
@@ -43,7 +45,9 @@ class CI_DB_cubrid_result extends CI_DB_result {
*/
public function num_rows()
{
- return @cubrid_num_rows($this->result_id);
+ return is_int($this->num_rows)
+ ? $this->num_rows
+ : $this->num_rows = @cubrid_num_rows($this->result_id);
}
// --------------------------------------------------------------------
@@ -85,52 +89,13 @@ class CI_DB_cubrid_result extends CI_DB_result {
{
$retval = array();
- $tablePrimaryKeys = array();
-
- while ($field = cubrid_fetch_field($this->result_id))
+ for ($i = 0, $c = $this->num_fields(); $i < $c; $i++)
{
- $F = new stdClass();
- $F->name = $field->name;
- $F->type = $field->type;
- $F->default = $field->def;
- $F->max_length = $field->max_length;
-
- // At this moment primary_key property is not returned when
- // cubrid_fetch_field is called. The following code will
- // provide a patch for it. primary_key property will be added
- // in the next release.
-
- // TODO: later version of CUBRID will provide primary_key
- // property.
- // When PK is defined in CUBRID, an index is automatically
- // created in the db_index system table in the form of
- // pk_tblname_fieldname. So the following will count how many
- // columns are there which satisfy this format.
- // The query will search for exact single columns, thus
- // compound PK is not supported.
- $res = cubrid_query($this->conn_id,
- "SELECT COUNT(*) FROM db_index WHERE class_name = '" . $field->table .
- "' AND is_primary_key = 'YES' AND index_name = 'pk_" .
- $field->table . "_" . $field->name . "'"
- );
-
- if ($res)
- {
- $row = cubrid_fetch_array($res, CUBRID_NUM);
- $F->primary_key = ($row[0] > 0 ? 1 : null);
- }
- else
- {
- $F->primary_key = null;
- }
-
- if (is_resource($res))
- {
- cubrid_close_request($res);
- $this->result_id = FALSE;
- }
-
- $retval[] = $F;
+ $retval[$i] = new stdClass();
+ $retval[$i]->name = cubrid_field_name($this->result_id, $i);
+ $retval[$i]->type = cubrid_field_type($this->result_id, $i);
+ $retval[$i]->max_length = cubrid_field_len($this->result_id, $i);
+ $retval[$i]->primary_key = (int) (strpos(cubrid_field_flags($this->result_id, $i), 'primary_key') !== FALSE);
}
return $retval;
@@ -145,9 +110,8 @@ class CI_DB_cubrid_result extends CI_DB_result {
*/
public function free_result()
{
- if(is_resource($this->result_id) ||
- get_resource_type($this->result_id) == "Unknown" &&
- preg_match('/Resource id #/', strval($this->result_id)))
+ if (is_resource($this->result_id) OR
+ (get_resource_type($this->result_id) === 'Unknown' && preg_match('/Resource id #/', strval($this->result_id))))
{
cubrid_close_request($this->result_id);
$this->result_id = FALSE;
@@ -161,11 +125,12 @@ class CI_DB_cubrid_result extends CI_DB_result {
*
* Moves the internal pointer to the desired offset. We call
* this internally before fetching results to make sure the
- * result set starts at zero
+ * result set starts at zero.
*
+ * @param int $n
* @return bool
*/
- protected function _data_seek($n = 0)
+ public function data_seek($n = 0)
{
return cubrid_data_seek($this->result_id, $n);
}
@@ -191,11 +156,12 @@ class CI_DB_cubrid_result extends CI_DB_result {
*
* Returns the result set as an object
*
+ * @param string $class_name
* @return object
*/
- protected function _fetch_object()
+ protected function _fetch_object($class_name = 'stdClass')
{
- return cubrid_fetch_object($this->result_id);
+ return cubrid_fetch_object($this->result_id, $class_name);
}
}
diff --git a/system/database/drivers/cubrid/cubrid_utility.php b/system/database/drivers/cubrid/cubrid_utility.php
index 274ff6a48..d76eca432 100644
--- a/system/database/drivers/cubrid/cubrid_utility.php
+++ b/system/database/drivers/cubrid/cubrid_utility.php
@@ -1,4 +1,4 @@
-<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');
+<?php
/**
* CodeIgniter
*
@@ -21,9 +21,10 @@
* @copyright Copyright (c) 2008 - 2012, EllisLab, Inc. (http://ellislab.com/)
* @license http://opensource.org/licenses/OSL-3.0 Open Software License (OSL 3.0)
* @link http://codeigniter.com
- * @since Version 1.0
+ * @since Version 2.1
* @filesource
*/
+defined('BASEPATH') OR exit('No direct script access allowed');
/**
* CUBRID Utility Class
@@ -41,12 +42,12 @@ class CI_DB_cubrid_utility extends CI_DB_utility {
*/
public function list_databases()
{
- if (isset($this->data_cache['db_names']))
+ if (isset($this->db->data_cache['db_names']))
{
- return $this->data_cache['db_names'];
+ return $this->db->data_cache['db_names'];
}
- return $this->data_cache['db_names'] = cubrid_list_dbs($this->db->conn_id);
+ return $this->db->data_cache['db_names'] = cubrid_list_dbs($this->db->conn_id);
}
// --------------------------------------------------------------------
@@ -62,7 +63,7 @@ class CI_DB_cubrid_utility extends CI_DB_utility {
// No SQL based support in CUBRID as of version 8.4.0. Database or
// table backup can be performed using CUBRID Manager
// database administration tool.
- return $this->db->display_error('db_unsuported_feature');
+ return $this->db->display_error('db_unsupported_feature');
}
}
diff --git a/system/database/drivers/interbase/interbase_driver.php b/system/database/drivers/ibase/ibase_driver.php
index 6587d72ff..15c2a4630 100644
--- a/system/database/drivers/interbase/interbase_driver.php
+++ b/system/database/drivers/ibase/ibase_driver.php
@@ -1,4 +1,4 @@
-<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');
+<?php
/**
* CodeIgniter
*
@@ -24,12 +24,13 @@
* @since Version 3.0
* @filesource
*/
+defined('BASEPATH') OR exit('No direct script access allowed');
/**
* Firebird/Interbase Database Adapter Class
*
* Note: _DB is an extender class that the app controller
- * creates dynamically based on whether the active record
+ * creates dynamically based on whether the query builder
* class is being used or not.
*
* @package CodeIgniter
@@ -38,27 +39,32 @@
* @author EllisLab Dev Team
* @link http://codeigniter.com/user_guide/database/
*/
-class CI_DB_interbase_driver extends CI_DB {
+class CI_DB_ibase_driver extends CI_DB {
- public $dbdriver = 'interbase';
+ /**
+ * Database driver
+ *
+ * @var string
+ */
+ public $dbdriver = 'ibase';
- // The character used to escape with
- protected $_escape_char = '"';
+ // --------------------------------------------------------------------
- // clause and character used for LIKE escape sequences
- protected $_like_escape_str = " ESCAPE '%s' ";
- protected $_like_escape_chr = '!';
+ /**
+ * ORDER BY random keyword
+ *
+ * @var array
+ */
+ protected $_random_keyword = array('RAND()', 'RAND()');
/**
- * The syntax to count rows is slightly different across different
- * database engines, so this string appears in each driver and is
- * used for the count_all() and count_all_results() functions.
+ * IBase Transaction status flag
+ *
+ * @var resource
*/
- protected $_count_string = 'SELECT COUNT(*) AS ';
- protected $_random_keyword = ' Random()'; // database specific random keyword
+ protected $_ibase_trans;
- // Keeps track of the resource for the current transaction
- protected $trans;
+ // --------------------------------------------------------------------
/**
* Non-persistent database connection
@@ -113,7 +119,7 @@ class CI_DB_interbase_driver extends CI_DB {
/**
* Execute the query
*
- * @param string an SQL query
+ * @param string $sql an SQL query
* @return resource
*/
protected function _execute($sql)
@@ -126,6 +132,7 @@ class CI_DB_interbase_driver extends CI_DB {
/**
* Begin Transaction
*
+ * @param bool $test_mode
* @return bool
*/
public function trans_begin($test_mode = FALSE)
@@ -141,7 +148,7 @@ class CI_DB_interbase_driver extends CI_DB {
// even if the queries produce a successful result.
$this->_trans_failure = ($test_mode === TRUE);
- $this->trans = @ibase_trans($this->conn_id);
+ $this->_ibase_trans = @ibase_trans($this->conn_id);
return TRUE;
}
@@ -161,7 +168,7 @@ class CI_DB_interbase_driver extends CI_DB {
return TRUE;
}
- return @ibase_commit($this->trans);
+ return @ibase_commit($this->_ibase_trans);
}
// --------------------------------------------------------------------
@@ -179,7 +186,7 @@ class CI_DB_interbase_driver extends CI_DB {
return TRUE;
}
- return @ibase_rollback($this->trans);
+ return @ibase_rollback($this->_ibase_trans);
}
// --------------------------------------------------------------------
@@ -187,8 +194,8 @@ class CI_DB_interbase_driver extends CI_DB {
/**
* Escape String
*
- * @param string
- * @param bool whether or not the string will be used in a LIKE condition
+ * @param string $str
+ * @param bool $like Whether or not the string will be used in a LIKE condition
* @return string
*/
public function escape_str($str, $like = FALSE)
@@ -235,7 +242,7 @@ class CI_DB_interbase_driver extends CI_DB {
* @param int $inc_by
* @return int
*/
- public function insert_id($generator_name, $inc_by=0)
+ public function insert_id($generator_name, $inc_by = 0)
{
//If a generator hasn't been used before it will return 0
return ibase_gen_id('"'.$generator_name.'"', $inc_by);
@@ -244,49 +251,21 @@ class CI_DB_interbase_driver extends CI_DB {
// --------------------------------------------------------------------
/**
- * "Count All" query
- *
- * Generates a platform-specific query string that counts all records in
- * the specified database
- *
- * @param string
- * @return string
- */
- public function count_all($table = '')
- {
- if ($table == '')
- {
- return 0;
- }
-
- $query = $this->query($this->_count_string.$this->protect_identifiers('numrows').' FROM '.$this->protect_identifiers($table, TRUE, NULL, FALSE));
- if ($query->num_rows() == 0)
- {
- return 0;
- }
-
- $query = $query->row();
- $this->_reset_select();
- return (int) $query->numrows;
- }
-
- // --------------------------------------------------------------------
-
- /**
* List table query
*
* Generates a platform-specific query string so that the table names can be fetched
*
- * @param bool
+ * @param bool $prefix_limit
* @return string
*/
protected function _list_tables($prefix_limit = FALSE)
{
$sql = 'SELECT "RDB$RELATION_NAME" FROM "RDB$RELATIONS" WHERE "RDB$RELATION_NAME" NOT LIKE \'RDB$%\' AND "RDB$RELATION_NAME" NOT LIKE \'MON$%\'';
- if ($prefix_limit !== FALSE && $this->dbprefix != '')
+ if ($prefix_limit !== FALSE && $this->dbprefix !== '')
{
- return $sql.' AND "RDB$RELATION_NAME" LIKE \''.$this->escape_like_str($this->dbprefix)."%' ".sprintf($this->_like_escape_str, $this->_like_escape_chr);
+ return $sql.' AND "RDB$RELATION_NAME" LIKE \''.$this->escape_like_str($this->dbprefix)."%' "
+ .sprintf($this->_like_escape_str, $this->_like_escape_chr);
}
return $sql;
@@ -299,30 +278,57 @@ class CI_DB_interbase_driver extends CI_DB {
*
* Generates a platform-specific query string so that the column names can be fetched
*
- * @param string the table name
+ * @param string $table
* @return string
*/
protected function _list_columns($table = '')
{
- return 'SELECT "RDB$FIELD_NAME" FROM "RDB$RELATION_FIELDS" WHERE "RDB$RELATION_NAME" = \''.$this->escape_str($table)."'";
+ return 'SELECT "RDB$FIELD_NAME" FROM "RDB$RELATION_FIELDS" WHERE "RDB$RELATION_NAME" = '.$this->escape($table);
}
// --------------------------------------------------------------------
/**
- * Field data query
- *
- * Generates a platform-specific query so that the column data can be retrieved
+ * Returns an object with field data
*
- * @param string the table name
- * @return string
+ * @param string $table
+ * @return array
*/
- protected function _field_data($table)
+ public function field_data($table = '')
{
- // Need to find a more efficient way to do this
- // but Interbase/Firebird seems to lack the
- // limit clause
- return 'SELECT * FROM '.$table;
+ if ($table === '')
+ {
+ return ($this->db_debug) ? $this->display_error('db_field_param_missing') : FALSE;
+ }
+
+ $sql = 'SELECT "rfields"."RDB$FIELD_NAME" AS "name",
+ CASE "fields"."RDB$FIELD_TYPE"
+ WHEN 7 THEN \'SMALLINT\'
+ WHEN 8 THEN \'INTEGER\'
+ WHEN 9 THEN \'QUAD\'
+ WHEN 10 THEN \'FLOAT\'
+ WHEN 11 THEN \'DFLOAT\'
+ WHEN 12 THEN \'DATE\'
+ WHEN 13 THEN \'TIME\'
+ WHEN 14 THEN \'CHAR\'
+ WHEN 16 THEN \'INT64\'
+ WHEN 27 THEN \'DOUBLE\'
+ WHEN 35 THEN \'TIMESTAMP\'
+ WHEN 37 THEN \'VARCHAR\'
+ WHEN 40 THEN \'CSTRING\'
+ WHEN 261 THEN \'BLOB\'
+ ELSE NULL
+ END AS "type",
+ "fields"."RDB$FIELD_LENGTH" AS "max_length",
+ "rfields"."RDB$DEFAULT_VALUE" AS "default"
+ FROM "RDB$RELATION_FIELDS" "rfields"
+ JOIN "RDB$FIELDS" "fields" ON "rfields"."RDB$FIELD_SOURCE" = "fields"."RDB$FIELD_NAME"
+ WHERE "rfields"."RDB$RELATION_NAME" = '.$this->escape($table).'
+ ORDER BY "rfields"."RDB$FIELD_POSITION"';
+
+ return (($query = $this->query($sql)) !== FALSE)
+ ? $query->result_object()
+ : FALSE;
}
// --------------------------------------------------------------------
@@ -343,60 +349,20 @@ class CI_DB_interbase_driver extends CI_DB {
// --------------------------------------------------------------------
/**
- * From Tables
- *
- * This public function implicitly groups FROM tables so there is no confusion
- * about operator precedence in harmony with SQL standards
- *
- * @param array
- * @return string
- */
- protected function _from_tables($tables)
- {
- if ( ! is_array($tables))
- {
- $tables = array($tables);
- }
-
- //Interbase/Firebird doesn't like grouped tables
- return implode(', ', $tables);
- }
-
- // --------------------------------------------------------------------
-
- /**
* Update statement
*
* Generates a platform-specific update string from the supplied data
*
- * @param string the table name
- * @param array the update data
- * @param array the where clause
- * @param array the orderby clause
- * @param array the limit clause (ignored)
- * @param array the like clause
+ * @param string $table
+ * @param array $values
* @return string
*/
- protected function _update($table, $values, $where, $orderby = array(), $limit = FALSE, $like = array())
+ protected function _update($table, $values)
{
- foreach ($values as $key => $val)
- {
- $valstr[] = $key.' = '.$val;
- }
-
- $where = empty($where) ? '' : ' WHERE '.implode(' ', $where);
-
- if ( ! empty($like))
- {
- $where .= ($where === '' ? ' WHERE ' : ' AND ').implode(' ', $like);
- }
-
- return 'UPDATE '.$table.' SET '.implode(', ', $valstr)
- .$where
- .(count($orderby) > 0 ? ' ORDER BY '.implode(', ', $orderby) : '');
+ $this->qb_limit = FALSE;
+ return parent::_update($table, $values);
}
-
// --------------------------------------------------------------------
/**
@@ -404,10 +370,10 @@ class CI_DB_interbase_driver extends CI_DB {
*
* Generates a platform-specific truncate string from the supplied data
*
- * If the database does not support the truncate() command,
+ * If the database does not support the TRUNCATE statement,
* then this method maps to 'DELETE FROM table'
*
- * @param string the table name
+ * @param string $table
* @return string
*/
protected function _truncate($table)
@@ -422,46 +388,37 @@ class CI_DB_interbase_driver extends CI_DB {
*
* Generates a platform-specific delete string from the supplied data
*
- * @param string the table name
- * @param array the where clause
- * @param array the like clause
- * @param string the limit clause (ignored)
+ * @param string $table
* @return string
*/
- protected function _delete($table, $where = array(), $like = array(), $limit = FALSE)
+ protected function _delete($table)
{
- $conditions = array();
-
- empty($where) OR $conditions[] = implode(' ', $where);
- empty($like) OR $conditions[] = implode(' ', $like);
-
- return 'DELETE FROM '.$table.(count($conditions) > 0 ? ' WHERE '.implode(' AND ', $conditions) : '');
+ $this->qb_limit = FALSE;
+ return parent::_delete($table);
}
// --------------------------------------------------------------------
/**
- * Limit string
+ * LIMIT
*
* Generates a platform-specific LIMIT clause
*
- * @param string the sql query string
- * @param int the number of rows to limit the query to
- * @param int the offset value
+ * @param string $sql SQL Query
* @return string
*/
- protected function _limit($sql, $limit, $offset)
+ protected function _limit($sql)
{
// Limit clause depends on if Interbase or Firebird
if (stripos($this->version(), 'firebird') !== FALSE)
{
- $select = 'FIRST '. (int) $limit
- .($offset > 0 ? ' SKIP '. (int) $offset : '');
+ $select = 'FIRST '.$this->qb_limit
+ .($this->qb_offset ? ' SKIP '.$this->qb_offset : '');
}
else
{
$select = 'ROWS '
- .($offset > 0 ? (int) $offset.' TO '.($limit + $offset) : (int) $limit);
+ .($this->qb_offset ? $this->qb_offset.' TO '.($this->qb_limit + $this->qb_offset) : $this->qb_limit);
}
return preg_replace('`SELECT`i', 'SELECT '.$select, $sql);
@@ -472,15 +429,14 @@ class CI_DB_interbase_driver extends CI_DB {
/**
* Close DB Connection
*
- * @param resource
* @return void
*/
- protected function _close($conn_id)
+ protected function _close()
{
- @ibase_close($conn_id);
+ @ibase_close($this->conn_id);
}
}
-/* End of file interbase_driver.php */
-/* Location: ./system/database/drivers/interbase/interbase_driver.php */ \ No newline at end of file
+/* End of file ibase_driver.php */
+/* Location: ./system/database/drivers/ibase/ibase_driver.php */ \ No newline at end of file
diff --git a/system/database/drivers/ibase/ibase_forge.php b/system/database/drivers/ibase/ibase_forge.php
new file mode 100644
index 000000000..39c782816
--- /dev/null
+++ b/system/database/drivers/ibase/ibase_forge.php
@@ -0,0 +1,243 @@
+<?php
+/**
+ * CodeIgniter
+ *
+ * An open source application development framework for PHP 5.2.4 or newer
+ *
+ * NOTICE OF LICENSE
+ *
+ * Licensed under the Open Software License version 3.0
+ *
+ * This source file is subject to the Open Software License (OSL 3.0) that is
+ * bundled with this package in the files license.txt / license.rst. It is
+ * also available through the world wide web at this URL:
+ * http://opensource.org/licenses/OSL-3.0
+ * If you did not receive a copy of the license and are unable to obtain it
+ * through the world wide web, please send an email to
+ * licensing@ellislab.com so we can send you a copy immediately.
+ *
+ * @package CodeIgniter
+ * @author EllisLab Dev Team
+ * @copyright Copyright (c) 2008 - 2012, EllisLab, Inc. (http://ellislab.com/)
+ * @license http://opensource.org/licenses/OSL-3.0 Open Software License (OSL 3.0)
+ * @link http://codeigniter.com
+ * @since Version 3.0
+ * @filesource
+ */
+defined('BASEPATH') OR exit('No direct script access allowed');
+
+/**
+ * Interbase/Firebird Forge Class
+ *
+ * @category Database
+ * @author EllisLab Dev Team
+ * @link http://codeigniter.com/user_guide/database/
+ */
+class CI_DB_ibase_forge extends CI_DB_forge {
+
+ /**
+ * CREATE TABLE IF statement
+ *
+ * @var string
+ */
+ protected $_create_table_if = FALSE;
+
+ /**
+ * RENAME TABLE statement
+ *
+ * @var string
+ */
+ protected $_rename_table = FALSE;
+
+ /**
+ * DROP TABLE IF statement
+ *
+ * @var string
+ */
+ protected $_drop_table_if = FALSE;
+
+ /**
+ * UNSIGNED support
+ *
+ * @var array
+ */
+ protected $_unsigned = array(
+ 'SMALLINT' => 'INTEGER',
+ 'INTEGER' => 'INT64',
+ 'FLOAT' => 'DOUBLE PRECISION'
+ );
+
+ /**
+ * NULL value representation in CREATE/ALTER TABLE statements
+ *
+ * @var string
+ */
+ protected $_null = 'NULL';
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Create database
+ *
+ * @param string $db_name
+ * @return string
+ */
+ public function create_database($db_name)
+ {
+ // Firebird databases are flat files, so a path is required
+
+ // Hostname is needed for remote access
+ empty($this->db->hostname) OR $db_name = $this->hostname.':'.$db_name;
+
+ return parent::create_database('"'.$db_name.'"');
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Drop database
+ *
+ * @param string $db_name (ignored)
+ * @return bool
+ */
+ public function drop_database($db_name = '')
+ {
+ if ( ! ibase_drop_db($this->conn_id))
+ {
+ return ($this->db->db_debug) ? $this->db->display_error('db_unable_to_drop') : FALSE;
+ }
+ elseif ( ! empty($this->db->data_cache['db_names']))
+ {
+ $key = array_search(strtolower($this->db->database), array_map('strtolower', $this->db->data_cache['db_names']), TRUE);
+ if ($key !== FALSE)
+ {
+ unset($this->db->data_cache['db_names'][$key]);
+ }
+ }
+
+ return TRUE;
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * ALTER TABLE
+ *
+ * @param string $alter_type ALTER type
+ * @param string $table Table name
+ * @param mixed $field Column definition
+ * @return string|string[]
+ */
+ protected function _alter_table($alter_type, $table, $field)
+ {
+ if (in_array($alter_type, array('DROP', 'ADD'), TRUE))
+ {
+ return parent::_alter_table($alter_type, $table, $field);
+ }
+
+ $sql = 'ALTER TABLE '.$this->db->escape_identifiers($table);
+ $sqls = array();
+ for ($i = 0, $c = count($field); $i < $c; $i++)
+ {
+ if ($field[$i]['_literal'] !== FALSE)
+ {
+ return FALSE;
+ }
+
+ if (isset($field[$i]['type']))
+ {
+ $sqls[] = $sql.' ALTER COLUMN '.$this->db->escape_identififers($field[$i]['name'])
+ .' TYPE '.$field[$i]['type'].$field[$i]['length'];
+ }
+
+ if ( ! empty($field[$i]['default']))
+ {
+ $sqls[] = $sql.' ALTER COLUMN '.$this->db->escape_identifiers($field[$i]['name'])
+ .' SET DEFAULT '.$field[$i]['default'];
+ }
+
+ if (isset($field[$i]['null']))
+ {
+ $sqls[] = 'UPDATE "RDB$RELATION_FIELDS" SET "RDB$NULL_FLAG" = '
+ .($field[$i]['null'] === TRUE ? 'NULL' : '1')
+ .' WHERE "RDB$FIELD_NAME" = '.$this->db->escape($field[$i]['name'])
+ .' AND "RDB$RELATION_NAME" = '.$this->db->escape($table);
+ }
+
+ if ( ! empty($field[$i]['new_name']))
+ {
+ $sqls[] = $sql.' ALTER COLUMN '.$this->db->escape_identifiers($field[$i]['name'])
+ .' TO '.$this->db->escape_identifiers($field[$i]['new_name']);
+ }
+ }
+
+ return $sqls;
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Process column
+ *
+ * @param array $field
+ * @return string
+ */
+ protected function _process_column($field)
+ {
+ return $this->db->escape_identifiers($field['name'])
+ .' '.$field['type'].$field['length']
+ .$field['null']
+ .$field['unique']
+ .$field['default'];
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Field attribute TYPE
+ *
+ * Performs a data type mapping between different databases.
+ *
+ * @param array &$attributes
+ * @return void
+ */
+ protected function _attr_type(&$attributes)
+ {
+ switch (strtoupper($attributes['TYPE']))
+ {
+ case 'TINYINT':
+ $attributes['TYPE'] = 'SMALLINT';
+ $attributes['UNSIGNED'] = FALSE;
+ return;
+ case 'MEDIUMINT':
+ $attributes['TYPE'] = 'INTEGER';
+ $attributes['UNSIGNED'] = FALSE;
+ return;
+ case 'INT':
+ $attributes['TYPE'] = 'INTEGER';
+ return;
+ case 'BIGINT':
+ $attributes['TYPE'] = 'INT64';
+ return;
+ default: return;
+ }
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Field attribute AUTO_INCREMENT
+ *
+ * @param array &$attributes
+ * @param array &$field
+ * @return void
+ */
+ protected function _attr_auto_increment(&$attributes, &$field)
+ {
+ // Not supported
+ }
+
+}
+
+/* End of file ibase_forge.php */
+/* Location: ./system/database/drivers/ibase/ibase_forge.php */ \ No newline at end of file
diff --git a/system/database/drivers/ibase/ibase_result.php b/system/database/drivers/ibase/ibase_result.php
new file mode 100644
index 000000000..4f5637a72
--- /dev/null
+++ b/system/database/drivers/ibase/ibase_result.php
@@ -0,0 +1,154 @@
+<?php
+/**
+ * CodeIgniter
+ *
+ * An open source application development framework for PHP 5.2.4 or newer
+ *
+ * NOTICE OF LICENSE
+ *
+ * Licensed under the Open Software License version 3.0
+ *
+ * This source file is subject to the Open Software License (OSL 3.0) that is
+ * bundled with this package in the files license.txt / license.rst. It is
+ * also available through the world wide web at this URL:
+ * http://opensource.org/licenses/OSL-3.0
+ * If you did not receive a copy of the license and are unable to obtain it
+ * through the world wide web, please send an email to
+ * licensing@ellislab.com so we can send you a copy immediately.
+ *
+ * @package CodeIgniter
+ * @author EllisLab Dev Team
+ * @copyright Copyright (c) 2008 - 2012, EllisLab, Inc. (http://ellislab.com/)
+ * @license http://opensource.org/licenses/OSL-3.0 Open Software License (OSL 3.0)
+ * @link http://codeigniter.com
+ * @since Version 1.0
+ * @filesource
+ */
+defined('BASEPATH') OR exit('No direct script access allowed');
+
+/**
+ * Interbase/Firebird Result Class
+ *
+ * This class extends the parent result class: CI_DB_result
+ *
+ * @category Database
+ * @author EllisLab Dev Team
+ * @link http://codeigniter.com/user_guide/database/
+ * @since 3.0
+ */
+class CI_DB_ibase_result extends CI_DB_result {
+
+ /**
+ * Number of fields in the result set
+ *
+ * @return int
+ */
+ public function num_fields()
+ {
+ return @ibase_num_fields($this->result_id);
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Fetch Field Names
+ *
+ * Generates an array of column names
+ *
+ * @return array
+ */
+ public function list_fields()
+ {
+ $field_names = array();
+ for ($i = 0, $num_fields = $this->num_fields(); $i < $num_fields; $i++)
+ {
+ $info = ibase_field_info($this->result_id, $i);
+ $field_names[] = $info['name'];
+ }
+
+ return $field_names;
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Field data
+ *
+ * Generates an array of objects containing field meta-data
+ *
+ * @return array
+ */
+ public function field_data()
+ {
+ $retval = array();
+ for ($i = 0, $c = $this->num_fields(); $i < $c; $i++)
+ {
+ $info = ibase_field_info($this->result_id, $i);
+
+ $retval[$i] = new stdClass();
+ $retval[$i]->name = $info['name'];
+ $retval[$i]->type = $info['type'];
+ $retval[$i]->max_length = $info['length'];
+ }
+
+ return $retval;
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Free the result
+ *
+ * @return void
+ */
+ public function free_result()
+ {
+ @ibase_free_result($this->result_id);
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Result - associative array
+ *
+ * Returns the result set as an array
+ *
+ * @return array
+ */
+ protected function _fetch_assoc()
+ {
+ return @ibase_fetch_assoc($this->result_id, IBASE_FETCH_BLOBS);
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Result - object
+ *
+ * Returns the result set as an object
+ *
+ * @param string $class_name
+ * @return object
+ */
+ protected function _fetch_object($class_name = 'stdClass')
+ {
+ $row = @ibase_fetch_object($this->result_id, IBASE_FETCH_BLOBS);
+
+ if ($class_name === 'stdClass' OR ! $row)
+ {
+ return $row;
+ }
+
+ $class_name = new $class_name();
+ foreach ($row as $key => $value)
+ {
+ $class_name->$key = $value;
+ }
+
+ return $class_name;
+ }
+
+}
+
+/* End of file ibase_result.php */
+/* Location: ./system/database/drivers/ibase/ibase_result.php */ \ No newline at end of file
diff --git a/system/database/drivers/interbase/interbase_utility.php b/system/database/drivers/ibase/ibase_utility.php
index 1b92af9b6..5eb209ae1 100644
--- a/system/database/drivers/interbase/interbase_utility.php
+++ b/system/database/drivers/ibase/ibase_utility.php
@@ -1,4 +1,4 @@
-<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');
+<?php
/**
* CodeIgniter
*
@@ -24,6 +24,7 @@
* @since Version 3.0
* @filesource
*/
+defined('BASEPATH') OR exit('No direct script access allowed');
/**
* Interbase/Firebird Utility Class
@@ -32,17 +33,15 @@
* @author EllisLab Dev Team
* @link http://codeigniter.com/user_guide/database/
*/
-class CI_DB_interbase_utility extends CI_DB_utility {
-
- protected $_list_databases = FALSE;
+class CI_DB_ibase_utility extends CI_DB_utility {
/**
- * Interbase/Firebird Export
+ * Export
*
* @param string $filename
* @return mixed
*/
- protected function backup($filename)
+ protected function _backup($filename)
{
if ($service = ibase_service_attach($this->db->hostname, $this->db->username, $this->db->password))
{
@@ -58,5 +57,5 @@ class CI_DB_interbase_utility extends CI_DB_utility {
}
-/* End of file interbase_utility.php */
-/* Location: ./system/database/drivers/interbase/interbase_utility.php */ \ No newline at end of file
+/* End of file ibase_utility.php */
+/* Location: ./system/database/drivers/ibase/ibase_utility.php */ \ No newline at end of file
diff --git a/system/database/drivers/interbase/index.html b/system/database/drivers/ibase/index.html
index c942a79ce..c942a79ce 100644
--- a/system/database/drivers/interbase/index.html
+++ b/system/database/drivers/ibase/index.html
diff --git a/system/database/drivers/interbase/interbase_forge.php b/system/database/drivers/interbase/interbase_forge.php
deleted file mode 100644
index c850656a8..000000000
--- a/system/database/drivers/interbase/interbase_forge.php
+++ /dev/null
@@ -1,224 +0,0 @@
-<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');
-/**
- * CodeIgniter
- *
- * An open source application development framework for PHP 5.2.4 or newer
- *
- * NOTICE OF LICENSE
- *
- * Licensed under the Open Software License version 3.0
- *
- * This source file is subject to the Open Software License (OSL 3.0) that is
- * bundled with this package in the files license.txt / license.rst. It is
- * also available through the world wide web at this URL:
- * http://opensource.org/licenses/OSL-3.0
- * If you did not receive a copy of the license and are unable to obtain it
- * through the world wide web, please send an email to
- * licensing@ellislab.com so we can send you a copy immediately.
- *
- * @package CodeIgniter
- * @author EllisLab Dev Team
- * @copyright Copyright (c) 2008 - 2012, EllisLab, Inc. (http://ellislab.com/)
- * @license http://opensource.org/licenses/OSL-3.0 Open Software License (OSL 3.0)
- * @link http://codeigniter.com
- * @since Version 3.0
- * @filesource
- */
-
-/**
- * Interbase/Firebird Forge Class
- *
- * @category Database
- * @author EllisLab Dev Team
- * @link http://codeigniter.com/user_guide/database/
- */
-class CI_DB_interbase_forge extends CI_DB_forge {
-
- protected $_drop_table = 'DROP TABLE %s';
-
- /**
- * Create database
- *
- * @param string the database name
- * @return string
- */
- public function create_database($db_name)
- {
- // Firebird databases are flat files, so a path is required
-
- // Hostname is needed for remote access
- empty($this->db->hostname) OR $db_name = $this->hostname.':'.$db_name;
-
- return parent::create_database('"'.$db_name.'"');
- }
-
- // --------------------------------------------------------------------
-
- /**
- * Drop database
- *
- * @param string the database name
- * - not used in this driver, the current db is dropped
- * @return bool
- */
- public function drop_database($db_name = '')
- {
- if ( ! ibase_drop_db($this->conn_id))
- {
- return ($this->db->db_debug) ? $this->db->display_error('db_unable_to_drop') : FALSE;
- }
-
- return TRUE;
- }
-
- // --------------------------------------------------------------------
-
- /**
- * Create Table
- *
- * @param string the table name
- * @param array the fields
- * @param mixed primary key(s)
- * @param mixed key(s)
- * @param bool should 'IF NOT EXISTS' be added to the SQL
- * @return string
- */
- protected function _create_table($table, $fields, $primary_keys, $keys, $if_not_exists)
- {
- $sql = 'CREATE TABLE ';
-
- $sql .= $this->db->protect_identifiers($table)."(";
- $current_field_count = 0;
-
- foreach ($fields as $field => $attributes)
- {
- // Numeric field names aren't allowed in databases, so if the key is
- // numeric, we know it was assigned by PHP and the developer manually
- // entered the field information, so we'll simply add it to the list
- if (is_numeric($field))
- {
- $sql .= "\n\t$attributes";
- }
- else
- {
- $attributes = array_change_key_case($attributes, CASE_UPPER);
-
- $sql .= "\n\t".$this->db->protect_identifiers($field);
-
- $sql .= ' '.$attributes['TYPE'];
-
- if (array_key_exists('CONSTRAINT', $attributes))
- {
- $sql .= '('.$attributes['CONSTRAINT'].')';
- }
-
- if (array_key_exists('UNSIGNED', $attributes) && $attributes['UNSIGNED'] === TRUE)
- {
- $sql .= ' UNSIGNED';
- }
-
- if (array_key_exists('DEFAULT', $attributes))
- {
- $sql .= ' DEFAULT \''.$attributes['DEFAULT'].'\'';
- }
-
- if (array_key_exists('NULL', $attributes) && $attributes['NULL'] === TRUE)
- {
- $sql .= ' NULL';
- }
- else
- {
- $sql .= ' NOT NULL';
- }
-
- if (array_key_exists('AUTO_INCREMENT', $attributes) && $attributes['AUTO_INCREMENT'] === TRUE)
- {
- $sql .= ' AUTO_INCREMENT';
- }
- }
-
- // don't add a comma on the end of the last field
- if (++$current_field_count < count($fields))
- {
- $sql .= ',';
- }
- }
-
- if (count($primary_keys) > 0)
- {
- $primary_keys = $this->db->protect_identifiers($primary_keys);
- $sql .= ",\n\tPRIMARY KEY (" . implode(', ', $primary_keys) . ")";
- }
-
- if (is_array($keys) && count($keys) > 0)
- {
- foreach ($keys as $key)
- {
- if (is_array($key))
- {
- $key = $this->db->protect_identifiers($key);
- }
- else
- {
- $key = array($this->db->protect_identifiers($key));
- }
-
- $sql .= ",\n\tUNIQUE (" . implode(', ', $key) . ")";
- }
- }
-
- $sql .= "\n)";
-
- return $sql;
- }
-
- // --------------------------------------------------------------------
-
- /**
- * Alter table query
- *
- * Generates a platform-specific query so that a table can be altered
- * Called by add_column(), drop_column(), and column_alter(),
- *
- * @param string the ALTER type (ADD, DROP, CHANGE)
- * @param string the column name
- * @param string the table name
- * @param string the column definition
- * @param string the default value
- * @param bool should 'NOT NULL' be added
- * @param string the field after which we should add the new field
- * @return string
- */
- protected function _alter_table($alter_type, $table, $column_name, $column_definition = '', $default_value = '', $null = '', $after_field = '')
- {
- $sql = 'ALTER TABLE '.$this->db->protect_identifiers($table)." $alter_type ".$this->db->protect_identifiers($column_name);
-
- $sql .= " {$column_definition}";
-
- if ($default_value != '')
- {
- $sql .= " DEFAULT \"{$default_value}\"";
- }
-
- if ($null === NULL)
- {
- $sql .= ' NULL';
- }
- else
- {
- $sql .= ' NOT NULL';
- }
-
- if ($after_field != '')
- {
- $sql .= ' AFTER ' . $this->db->protect_identifiers($after_field);
- }
-
- return $sql;
-
- }
-
-}
-
-/* End of file interbase_forge.php */
-/* Location: ./system/database/drivers/interbase/interbase_forge.php */ \ No newline at end of file
diff --git a/system/database/drivers/interbase/interbase_result.php b/system/database/drivers/interbase/interbase_result.php
deleted file mode 100644
index 5ddb6fa47..000000000
--- a/system/database/drivers/interbase/interbase_result.php
+++ /dev/null
@@ -1,260 +0,0 @@
-<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');
-/**
- * CodeIgniter
- *
- * An open source application development framework for PHP 5.2.4 or newer
- *
- * NOTICE OF LICENSE
- *
- * Licensed under the Open Software License version 3.0
- *
- * This source file is subject to the Open Software License (OSL 3.0) that is
- * bundled with this package in the files license.txt / license.rst. It is
- * also available through the world wide web at this URL:
- * http://opensource.org/licenses/OSL-3.0
- * If you did not receive a copy of the license and are unable to obtain it
- * through the world wide web, please send an email to
- * licensing@ellislab.com so we can send you a copy immediately.
- *
- * @package CodeIgniter
- * @author EllisLab Dev Team
- * @copyright Copyright (c) 2008 - 2012, EllisLab, Inc. (http://ellislab.com/)
- * @license http://opensource.org/licenses/OSL-3.0 Open Software License (OSL 3.0)
- * @link http://codeigniter.com
- * @since Version 3.0
- * @filesource
- */
-
-/**
- * Interbase/Firebird Result Class
- *
- * This class extends the parent result class: CI_DB_result
- *
- * @category Database
- * @author EllisLab Dev Team
- * @link http://codeigniter.com/user_guide/database/
- */
-class CI_DB_interbase_result extends CI_DB_result {
-
- public $num_rows;
-
- /**
- * Number of rows in the result set
- *
- * @return int
- */
- public function num_rows()
- {
- if (is_int($this->num_rows))
- {
- return $this->num_rows;
- }
-
- // Get the results so that you can get an accurate rowcount
- $this->result();
-
- return $this->num_rows;
- }
-
- // --------------------------------------------------------------------
-
- /**
- * Number of fields in the result set
- *
- * @return int
- */
- public function num_fields()
- {
- return @ibase_num_fields($this->result_id);
- }
-
- // --------------------------------------------------------------------
-
- /**
- * Fetch Field Names
- *
- * Generates an array of column names
- *
- * @return array
- */
- public function list_fields()
- {
- $field_names = array();
- for ($i = 0, $num_fields = $this->num_fields(); $i < $num_fields; $i++)
- {
- $info = ibase_field_info($this->result_id, $i);
- $field_names[] = $info['name'];
- }
-
- return $field_names;
- }
-
- // --------------------------------------------------------------------
-
- /**
- * Field data
- *
- * Generates an array of objects containing field meta-data
- *
- * @return array
- */
- public function field_data()
- {
- $retval = array();
- for ($i = 0, $c = $this->num_fields(); $i < $c; $i++)
- {
- $info = ibase_field_info($this->result_id, $i);
-
- $retval[$i] = new stdClass();
- $retval[$i]->name = $info['name'];
- $retval[$i]->type = $info['type'];
- $retval[$i]->max_length = $info['length'];
- $retval[$i]->primary_key = 0;
- $retval[$i]->default = '';
- }
-
- return $retval;
- }
-
- // --------------------------------------------------------------------
-
- /**
- * Free the result
- *
- * @return void
- */
- public function free_result()
- {
- @ibase_free_result($this->result_id);
- }
-
- // --------------------------------------------------------------------
-
- /**
- * Result - associative array
- *
- * Returns the result set as an array
- *
- * @return array
- */
- protected function _fetch_assoc()
- {
- if (($row = @ibase_fetch_assoc($this->result_id, IBASE_FETCH_BLOBS)) !== FALSE)
- {
- //Increment row count
- $this->num_rows++;
- }
-
- return $row;
- }
-
- // --------------------------------------------------------------------
-
- /**
- * Result - object
- *
- * Returns the result set as an object
- *
- * @return object
- */
- protected function _fetch_object()
- {
- if (($row = @ibase_fetch_object($this->result_id, IBASE_FETCH_BLOBS)) !== FALSE)
- {
- //Increment row count
- $this->num_rows++;
- }
-
- return $row;
- }
-
- // --------------------------------------------------------------------
-
- /**
- * Query result. "object" version.
- *
- * @return object
- */
- public function result_object()
- {
- if (count($this->result_object) === $this->num_rows)
- {
- return $this->result_object;
- }
-
- // Convert result array to object so that
- // We don't have to get the result again
- if (($c = count($this->result_array)) > 0)
- {
- for ($i = 0; $i < $c; $i++)
- {
- $this->result_object[$i] = (object) $this->result_array[$i];
- }
-
- return $this->result_object;
- }
-
- // In the event that query caching is on the result_id variable
- // will return FALSE since there isn't a valid SQL resource so
- // we'll simply return an empty array.
- if ($this->result_id === FALSE)
- {
- return array();
- }
-
- $this->num_rows = 0;
- while ($row = $this->_fetch_object())
- {
- $this->result_object[] = $row;
- }
-
- return $this->result_object;
- }
-
- // --------------------------------------------------------------------
-
- /**
- * Query result. "array" version.
- *
- * @return array
- */
- public function result_array()
- {
- if (count($this->result_array) === $this->num_rows)
- {
- return $this->result_array;
- }
-
- // Since the object and array are really similar, just case
- // the result object to an array if need be
- if (($c = count($this->result_object)) > 0)
- {
- for ($i = 0; $i < $c; $i++)
- {
- $this->result_array[$i] = (array) $this->result_object[$i];
- }
-
- return $this->result_array;
- }
-
- // In the event that query caching is on the result_id variable
- // will return FALSE since there isn't a valid SQL resource so
- // we'll simply return an empty array.
- if ($this->result_id === FALSE)
- {
- return array();
- }
-
- $this->num_rows = 0;
- while ($row = $this->_fetch_assoc())
- {
- $this->result_array[] = $row;
- }
-
- return $this->result_array;
- }
-
-}
-
-/* End of file interbase_result.php */
-/* Location: ./system/database/drivers/interbase/interbase_result.php */ \ No newline at end of file
diff --git a/system/database/drivers/mssql/mssql_driver.php b/system/database/drivers/mssql/mssql_driver.php
index 90609a84d..d3e439d69 100644
--- a/system/database/drivers/mssql/mssql_driver.php
+++ b/system/database/drivers/mssql/mssql_driver.php
@@ -1,4 +1,4 @@
-<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');
+<?php
/**
* CodeIgniter
*
@@ -24,12 +24,13 @@
* @since Version 1.0
* @filesource
*/
+defined('BASEPATH') OR exit('No direct script access allowed');
/**
* MS SQL Database Adapter Class
*
* Note: _DB is an extender class that the app controller
- * creates dynamically based on whether the active record
+ * creates dynamically based on whether the query builder
* class is being used or not.
*
* @package CodeIgniter
@@ -40,36 +41,78 @@
*/
class CI_DB_mssql_driver extends CI_DB {
+ /**
+ * Database driver
+ *
+ * @var string
+ */
public $dbdriver = 'mssql';
- // The character used for escaping
- protected $_escape_char = '';
+ // --------------------------------------------------------------------
- // clause and character used for LIKE escape sequences
- protected $_like_escape_str = " ESCAPE '%s' ";
- protected $_like_escape_chr = '!';
+ /**
+ * ORDER BY random keyword
+ *
+ * @var array
+ */
+ protected $_random_keyword = array('NEWID()', 'RAND(%d)');
/**
- * The syntax to count rows is slightly different across different
- * database engines, so this string appears in each driver and is
- * used for the count_all() and count_all_results() methods.
+ * Quoted identifier flag
+ *
+ * Whether to use SQL-92 standard quoted identifier
+ * (double quotes) or brackets for identifier escaping.
+ *
+ * @var bool
*/
- protected $_count_string = 'SELECT COUNT(*) AS ';
- protected $_random_keyword = ' NEWID()';
+ protected $_quoted_identifier = TRUE;
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Class constructor
+ *
+ * Appends the port number to the hostname, if needed.
+ *
+ * @param array $params
+ * @return void
+ */
+ public function __construct($params)
+ {
+ parent::__construct($params);
+
+ if ( ! empty($this->port))
+ {
+ $this->hostname .= (DIRECTORY_SEPARATOR === '\\' ? ',' : ':').$this->port;
+ }
+ }
+
+ // --------------------------------------------------------------------
/**
* Non-persistent database connection
*
+ * @param bool $persistent
* @return resource
*/
- public function db_connect()
+ public function db_connect($persistent = FALSE)
{
- if ($this->port != '')
+ $this->conn_id = ($persistent)
+ ? @mssql_pconnect($this->hostname, $this->username, $this->password)
+ : @mssql_connect($this->hostname, $this->username, $this->password);
+
+ if ( ! $this->conn_id)
{
- $this->hostname .= ','.$this->port;
+ return FALSE;
}
- return @mssql_connect($this->hostname, $this->username, $this->password);
+ // Determine how identifiers are escaped
+ $query = $this->query('SELECT CASE WHEN (@@OPTIONS | 256) = @@OPTIONS THEN 1 ELSE 0 END AS qi');
+ $query = $query->row_array();
+ $this->_quoted_identifier = empty($query) ? FALSE : (bool) $query['qi'];
+ $this->_escape_char = ($this->_quoted_identifier) ? '"' : array('[', ']');
+
+ return $this->conn_id;
}
// --------------------------------------------------------------------
@@ -81,12 +124,7 @@ class CI_DB_mssql_driver extends CI_DB {
*/
public function db_pconnect()
{
- if ($this->port != '')
- {
- $this->hostname .= ','.$this->port;
- }
-
- return @mssql_pconnect($this->hostname, $this->username, $this->password);
+ return $this->db_connect(TRUE);
}
// --------------------------------------------------------------------
@@ -94,7 +132,7 @@ class CI_DB_mssql_driver extends CI_DB {
/**
* Select the database
*
- * @param string database name
+ * @param string $database
* @return bool
*/
public function db_select($database = '')
@@ -106,7 +144,7 @@ class CI_DB_mssql_driver extends CI_DB {
// Note: The brackets are required in the event that the DB name
// contains reserved characters
- if (@mssql_select_db('['.$database.']', $this->conn_id))
+ if (@mssql_select_db($this->escape_identifiers($database), $this->conn_id))
{
$this->database = $database;
return TRUE;
@@ -120,8 +158,8 @@ class CI_DB_mssql_driver extends CI_DB {
/**
* Execute the query
*
- * @param string an SQL query
- * @return resource
+ * @param string $sql an SQL query
+ * @return mixed resource if rows are returned, bool otherwise
*/
protected function _execute($sql)
{
@@ -133,17 +171,13 @@ class CI_DB_mssql_driver extends CI_DB {
/**
* Begin Transaction
*
+ * @param bool $test_mode
* @return bool
*/
public function trans_begin($test_mode = FALSE)
{
- if ( ! $this->trans_enabled)
- {
- return TRUE;
- }
-
// When transactions are nested we only begin/commit/rollback the outermost ones
- if ($this->_trans_depth > 0)
+ if ( ! $this->trans_enabled OR $this->_trans_depth > 0)
{
return TRUE;
}
@@ -151,10 +185,9 @@ class CI_DB_mssql_driver extends CI_DB {
// Reset the transaction failure flag.
// If the $test_mode flag is set to TRUE transactions will be rolled back
// even if the queries produce a successful result.
- $this->_trans_failure = ($test_mode === TRUE) ? TRUE : FALSE;
+ $this->_trans_failure = ($test_mode === TRUE);
- $this->simple_query('BEGIN TRAN');
- return TRUE;
+ return $this->simple_query('BEGIN TRAN');
}
// --------------------------------------------------------------------
@@ -166,19 +199,13 @@ class CI_DB_mssql_driver extends CI_DB {
*/
public function trans_commit()
{
- if ( ! $this->trans_enabled)
- {
- return TRUE;
- }
-
// When transactions are nested we only begin/commit/rollback the outermost ones
- if ($this->_trans_depth > 0)
+ if ( ! $this->trans_enabled OR $this->_trans_depth > 0)
{
return TRUE;
}
- $this->simple_query('COMMIT TRAN');
- return TRUE;
+ return $this->simple_query('COMMIT TRAN');
}
// --------------------------------------------------------------------
@@ -190,19 +217,13 @@ class CI_DB_mssql_driver extends CI_DB {
*/
public function trans_rollback()
{
- if ( ! $this->trans_enabled)
- {
- return TRUE;
- }
-
// When transactions are nested we only begin/commit/rollback the outermost ones
- if ($this->_trans_depth > 0)
+ if ( ! $this->trans_enabled OR $this->_trans_depth > 0)
{
return TRUE;
}
- $this->simple_query('ROLLBACK TRAN');
- return TRUE;
+ return $this->simple_query('ROLLBACK TRAN');
}
// --------------------------------------------------------------------
@@ -210,8 +231,8 @@ class CI_DB_mssql_driver extends CI_DB {
/**
* Escape String
*
- * @param string
- * @param bool whether or not the string will be used in a LIKE condition
+ * @param string $str
+ * @param bool $like Whether or not the string will be used in a LIKE condition
* @return string
*/
public function escape_str($str, $like = FALSE)
@@ -232,7 +253,7 @@ class CI_DB_mssql_driver extends CI_DB {
// escape LIKE condition wildcards
if ($like === TRUE)
{
- $str = str_replace(
+ return str_replace(
array($this->_like_escape_chr, '%', '_'),
array($this->_like_escape_chr.$this->_like_escape_chr, $this->_like_escape_chr.'%', $this->_like_escape_chr.'_'),
$str
@@ -265,28 +286,26 @@ class CI_DB_mssql_driver extends CI_DB {
*/
public function insert_id()
{
- $ver = self::_parse_major_version($this->version());
- $sql = ($ver >= 8 ? "SELECT SCOPE_IDENTITY() AS last_id" : "SELECT @@IDENTITY AS last_id");
- $query = $this->query($sql);
- $row = $query->row();
- return $row->last_id;
+ $query = version_compare($this->version(), '8', '>=')
+ ? 'SELECT SCOPE_IDENTITY() AS last_id'
+ : 'SELECT @@IDENTITY AS last_id';
+
+ $query = $this->query($query);
+ $query = $query->row();
+ return $query->last_id;
}
// --------------------------------------------------------------------
/**
- * Parse major version
- *
- * Grabs the major version number from the
- * database server version string passed in.
+ * Set client character set
*
- * @param string $version
- * @return int major version number
+ * @param string $charset
+ * @return bool
*/
- protected function _parse_major_version($version)
+ protected function _db_set_charset($charset)
{
- preg_match('/([0-9]+)\.([0-9]+)\.([0-9]+)/', $version, $ver_info);
- return $ver_info[1]; // return the major version b/c that's all we're interested in.
+ return (@ini_set('mssql.charset', $charset) !== FALSE);
}
// --------------------------------------------------------------------
@@ -304,54 +323,26 @@ class CI_DB_mssql_driver extends CI_DB {
// --------------------------------------------------------------------
/**
- * "Count All" query
- *
- * Generates a platform-specific query string that counts all records in
- * the specified database
- *
- * @param string
- * @return string
- */
- public function count_all($table = '')
- {
- if ($table == '')
- {
- return 0;
- }
-
- $query = $this->query($this->_count_string.$this->protect_identifiers('numrows').' FROM '.$this->protect_identifiers($table, TRUE, NULL, FALSE));
- if ($query->num_rows() == 0)
- {
- return 0;
- }
-
- $row = $query->row();
- $this->_reset_select();
- return (int) $row->numrows;
- }
-
- // --------------------------------------------------------------------
-
- /**
* List table query
*
* Generates a platform-specific query string so that the table names can be fetched
*
- * @param bool
+ * @param bool $prefix_limit
* @return string
*/
protected function _list_tables($prefix_limit = FALSE)
{
- $sql = "SELECT name FROM sysobjects WHERE type = 'U' ORDER BY name";
+ $sql = 'SELECT '.$this->escape_identifiers('name')
+ .' FROM '.$this->escape_identifiers('sysobjects')
+ .' WHERE '.$this->escape_identifiers('type')." = 'U'";
- // for future compatibility
- if ($prefix_limit !== FALSE AND $this->dbprefix != '')
+ if ($prefix_limit !== FALSE AND $this->dbprefix !== '')
{
- //$sql .= " LIKE '".$this->escape_like_str($this->dbprefix)."%' ".sprintf($this->_like_escape_str, $this->_like_escape_chr);
- return FALSE; // not currently supported
+ $sql .= ' AND '.$this->escape_identifiers('name')." LIKE '".$this->escape_like_str($this->dbprefix)."%' "
+ .sprintf($this->_like_escape_str, $this->_like_escape_chr);
}
- return $sql;
+ return $sql.' ORDER BY '.$this->escape_identifiers('name');
}
// --------------------------------------------------------------------
@@ -361,27 +352,52 @@ class CI_DB_mssql_driver extends CI_DB {
*
* Generates a platform-specific query string so that the column names can be fetched
*
- * @param string the table name
+ * @param string $table
* @return string
*/
protected function _list_columns($table = '')
{
- return "SELECT * FROM INFORMATION_SCHEMA.Columns WHERE TABLE_NAME = '".$table."'";
+ return 'SELECT COLUMN_NAME
+ FROM INFORMATION_SCHEMA.Columns
+ WHERE UPPER(TABLE_NAME) = '.$this->escape(strtoupper($table));
}
// --------------------------------------------------------------------
/**
- * Field data query
- *
- * Generates a platform-specific query so that the column data can be retrieved
+ * Returns an object with field data
*
- * @param string the table name
- * @return string
+ * @param string $table
+ * @return array
*/
- protected function _field_data($table)
+ public function field_data($table = '')
{
- return "SELECT TOP 1 * FROM ".$table;
+ if ($table === '')
+ {
+ return ($this->db_debug) ? $this->display_error('db_field_param_missing') : FALSE;
+ }
+
+ $sql = 'SELECT COLUMN_NAME, DATA_TYPE, CHARACTER_MAXIMUM_LENGTH, NUMERIC_PRECISION, COLUMN_DEFAULT
+ FROM INFORMATION_SCHEMA.Columns
+ WHERE UPPER(TABLE_NAME) = '.$this->escape(strtoupper($table));
+
+ if (($query = $this->query($sql)) === FALSE)
+ {
+ return FALSE;
+ }
+ $query = $query->result_object();
+
+ $retval = array();
+ for ($i = 0, $c = count($query); $i < $c; $i++)
+ {
+ $retval[$i] = new stdClass();
+ $retval[$i]->name = $query[$i]->COLUMN_NAME;
+ $retval[$i]->type = $query[$i]->DATA_TYPE;
+ $retval[$i]->max_length = ($query[$i]->CHARACTER_MAXIMUM_LENGTH > 0) ? $query[$i]->CHARACTER_MAXIMUM_LENGTH : $query[$i]->NUMERIC_PRECISION;
+ $retval[$i]->default = $query[$i]->COLUMN_DEFAULT;
+ }
+
+ return $retval;
}
// --------------------------------------------------------------------
@@ -404,54 +420,19 @@ class CI_DB_mssql_driver extends CI_DB {
// --------------------------------------------------------------------
/**
- * From Tables
- *
- * This function implicitly groups FROM tables so there is no confusion
- * about operator precedence in harmony with SQL standards
- *
- * @param array
- * @return string
- */
- protected function _from_tables($tables)
- {
- if ( ! is_array($tables))
- {
- $tables = array($tables);
- }
-
- return implode(', ', $tables);
- }
-
- // --------------------------------------------------------------------
-
- /**
* Update statement
*
* Generates a platform-specific update string from the supplied data
*
- * @param string the table name
- * @param array the update data
- * @param array the where clause
- * @param array the orderby clause (ignored)
- * @param array the limit clause (ignored)
- * @param array the like clause
+ * @param string $table
+ * @param array $values
* @return string
*/
- protected function _update($table, $values, $where, $orderby = array(), $limit = FALSE, $like = array())
+ protected function _update($table, $values)
{
- foreach($values as $key => $val)
- {
- $valstr[] = $key.' = '.$val;
- }
-
- $where = empty($where) ? '' : ' WHERE '.implode(' ', $where);
-
- if ( ! empty($like))
- {
- $where .= ($where === '' ? ' WHERE ' : ' AND ').implode(' ', $like);
- }
-
- return 'UPDATE '.$table.' SET '.implode(', ', $valstr).' WHERE '.$where;
+ $this->qb_limit = FALSE;
+ $this->qb_orderby = array();
+ return parent::_update($table, $values);
}
// --------------------------------------------------------------------
@@ -461,10 +442,10 @@ class CI_DB_mssql_driver extends CI_DB {
*
* Generates a platform-specific truncate string from the supplied data
*
- * If the database does not support the truncate() command,
+ * If the database does not support the TRUNCATE statement,
* then this method maps to 'DELETE FROM table'
*
- * @param string the table name
+ * @param string $table
* @return string
*/
protected function _truncate($table)
@@ -479,43 +460,91 @@ class CI_DB_mssql_driver extends CI_DB {
*
* Generates a platform-specific delete string from the supplied data
*
- * @param string the table name
- * @param array the where clause
- * @param array the like clause
- * @param string the limit clause
+ * @param string $table
* @return string
*/
- protected function _delete($table, $where = array(), $like = array(), $limit = FALSE)
+ protected function _delete($table)
{
- $conditions = array();
-
- empty($where) OR $conditions[] = implode(' ', $where);
- empty($like) OR $conditions[] = implode(' ', $like);
-
- $conditions = (count($conditions) > 0) ? ' WHERE '.implode(' AND ', $conditions) : '';
+ if ($this->qb_limit)
+ {
+ return 'WITH ci_delete AS (SELECT TOP '.$this->qb_limit.' * FROM '.$table.$this->_compile_wh('qb_where').') DELETE FROM ci_delete';
+ }
- return ($limit)
- ? 'WITH ci_delete AS (SELECT TOP '.$limit.' * FROM '.$table.$conditions.') DELETE FROM ci_delete'
- : 'DELETE FROM '.$table.$conditions;
+ return parent::_delete($table);
}
// --------------------------------------------------------------------
/**
- * Limit string
+ * LIMIT
*
* Generates a platform-specific LIMIT clause
*
- * @param string the sql query string
- * @param int the number of rows to limit the query to
- * @param int the offset value
+ * @param string $sql SQL Query
* @return string
*/
- protected function _limit($sql, $limit, $offset)
+ protected function _limit($sql)
+ {
+ $limit = $this->qb_offset + $this->qb_limit;
+
+ // As of SQL Server 2005 (9.0.*) ROW_NUMBER() is supported,
+ // however an ORDER BY clause is required for it to work
+ if (version_compare($this->version(), '9', '>=') && $this->qb_offset && ! empty($this->qb_orderby))
+ {
+ $orderby = $this->_compile_order_by();
+
+ // We have to strip the ORDER BY clause
+ $sql = trim(substr($sql, 0, strrpos($sql, $orderby)));
+
+ // Get the fields to select from our subquery, so that we can avoid CI_rownum appearing in the actual results
+ if (count($this->qb_select) === 0)
+ {
+ $select = '*'; // Inevitable
+ }
+ else
+ {
+ // Use only field names and their aliases, everything else is out of our scope.
+ $select = array();
+ $field_regexp = ($this->_quoted_identifier)
+ ? '("[^\"]+")' : '(\[[^\]]+\])';
+ for ($i = 0, $c = count($this->qb_select); $i < $c; $i++)
+ {
+ $select[] = preg_match('/(?:\s|\.)'.$field_regexp.'$/i', $this->qb_select[$i], $m)
+ ? $m[1] : $this->qb_select[$i];
+ }
+ $select = implode(', ', $select);
+ }
+
+ return 'SELECT '.$select." FROM (\n\n"
+ .preg_replace('/^(SELECT( DISTINCT)?)/i', '\\1 ROW_NUMBER() OVER('.trim($orderby).') AS '.$this->escape_identifiers('CI_rownum').', ', $sql)
+ ."\n\n) ".$this->escape_identifiers('CI_subquery')
+ ."\nWHERE ".$this->escape_identifiers('CI_rownum').' BETWEEN '.($this->qb_offset + 1).' AND '.$limit;
+ }
+
+ return preg_replace('/(^\SELECT (DISTINCT)?)/i','\\1 TOP '.$limit.' ', $sql);
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Insert batch statement
+ *
+ * Generates a platform-specific insert string from the supplied data.
+ *
+ * @param string $table Table name
+ * @param array $keys INSERT keys
+ * @param array $values INSERT values
+ * @return string|bool
+ */
+ protected function _insert_batch($table, $keys, $values)
{
- $i = $limit + $offset;
+ // Multiple-value inserts are only supported as of SQL Server 2008
+ if (version_compare($this->version(), '10', '>='))
+ {
+ return parent::_insert_batch($table, $keys, $values);
+ }
- return preg_replace('/(^\SELECT (DISTINCT)?)/i','\\1 TOP '.$i.' ', $sql);
+ return ($this->db->db_debug) ? $this->db->display_error('db_unsupported_feature') : FALSE;
}
// --------------------------------------------------------------------
@@ -523,12 +552,11 @@ class CI_DB_mssql_driver extends CI_DB {
/**
* Close DB Connection
*
- * @param resource
* @return void
*/
- protected function _close($conn_id)
+ protected function _close()
{
- @mssql_close($conn_id);
+ @mssql_close($this->conn_id);
}
}
diff --git a/system/database/drivers/mssql/mssql_forge.php b/system/database/drivers/mssql/mssql_forge.php
index 8f8e7c5b9..5eebedbf7 100644
--- a/system/database/drivers/mssql/mssql_forge.php
+++ b/system/database/drivers/mssql/mssql_forge.php
@@ -1,4 +1,4 @@
-<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');
+<?php
/**
* CodeIgniter
*
@@ -24,6 +24,7 @@
* @since Version 1.0
* @filesource
*/
+defined('BASEPATH') OR exit('No direct script access allowed');
/**
* MS SQL Forge Class
@@ -34,162 +35,99 @@
*/
class CI_DB_mssql_forge extends CI_DB_forge {
- protected $_drop_table = 'DROP TABLE %s';
-
/**
- * Create Table
+ * CREATE TABLE IF statement
*
- * @param string the table name
- * @param array the fields
- * @param mixed primary key(s)
- * @param mixed key(s)
- * @param bool should 'IF NOT EXISTS' be added to the SQL
- * @return string
+ * @var string
*/
- protected function _create_table($table, $fields, $primary_keys, $keys, $if_not_exists)
- {
- $sql = 'CREATE TABLE ';
-
- if ($if_not_exists === TRUE)
- {
- $sql .= 'IF NOT EXISTS ';
- }
-
- $sql .= $this->db->escape_identifiers($table).' (';
- $current_field_count = 0;
-
- foreach ($fields as $field => $attributes)
- {
- // Numeric field names aren't allowed in databases, so if the key is
- // numeric, we know it was assigned by PHP and the developer manually
- // entered the field information, so we'll simply add it to the list
- if (is_numeric($field))
- {
- $sql .= "\n\t$attributes";
- }
- else
- {
- $attributes = array_change_key_case($attributes, CASE_UPPER);
-
- $sql .= "\n\t".$this->db->protect_identifiers($field);
-
- $sql .= ' '.$attributes['TYPE'];
-
- if (array_key_exists('CONSTRAINT', $attributes))
- {
- $sql .= '('.$attributes['CONSTRAINT'].')';
- }
+ protected $_create_table_if = "IF NOT EXISTS (SELECT * FROM sysobjects WHERE ID = object_id(N'%s') AND OBJECTPROPERTY(id, N'IsUserTable') = 1)\nCREATE TABLE";
- if (array_key_exists('UNSIGNED', $attributes) && $attributes['UNSIGNED'] === TRUE)
- {
- $sql .= ' UNSIGNED';
- }
-
- if (array_key_exists('DEFAULT', $attributes))
- {
- $sql .= ' DEFAULT \''.$attributes['DEFAULT'].'\'';
- }
-
- if (array_key_exists('NULL', $attributes) && $attributes['NULL'] === TRUE)
- {
- $sql .= ' NULL';
- }
- else
- {
- $sql .= ' NOT NULL';
- }
+ /**
+ * DROP TABLE IF statement
+ *
+ * @var string
+ */
+ protected $_drop_table_if = "IF EXISTS (SELECT * FROM sysobjects WHERE ID = object_id(N'%s') AND OBJECTPROPERTY(id, N'IsUserTable') = 1)\nDROP TABLE";
- if (array_key_exists('AUTO_INCREMENT', $attributes) && $attributes['AUTO_INCREMENT'] === TRUE)
- {
- $sql .= ' AUTO_INCREMENT';
- }
- }
+ /**
+ * UNSIGNED support
+ *
+ * @var array
+ */
+ protected $_unsigned = array(
+ 'TINYINT' => 'SMALLINT',
+ 'SMALLINT' => 'INT',
+ 'INT' => 'BIGINT',
+ 'REAL' => 'FLOAT'
+ );
- // don't add a comma on the end of the last field
- if (++$current_field_count < count($fields))
- {
- $sql .= ',';
- }
- }
+ // --------------------------------------------------------------------
- if (count($primary_keys) > 0)
+ /**
+ * ALTER TABLE
+ *
+ * @param string $alter_type ALTER type
+ * @param string $table Table name
+ * @param mixed $field Column definition
+ * @return string|string[]
+ */
+ protected function _alter_table($alter_type, $table, $field)
+ {
+ if (in_array($alter_type, array('ADD', 'DROP'), TRUE))
{
- $primary_keys = $this->db->protect_identifiers($primary_keys);
- $sql .= ",\n\tPRIMARY KEY (" . implode(', ', $primary_keys) . ")";
+ return parent::_alter_table($alter_type, $table, $field);
}
- if (is_array($keys) && count($keys) > 0)
+ $sql = 'ALTER TABLE '.$this->db->escape_identifiers($table).' ALTER COLUMN ';
+ $sqls = array();
+ for ($i = 0, $c = count($field); $i < $c; $i++)
{
- foreach ($keys as $key)
- {
- if (is_array($key))
- {
- $key = $this->db->protect_identifiers($key);
- }
- else
- {
- $key = array($this->db->protect_identifiers($key));
- }
-
- $sql .= ",\n\tFOREIGN KEY (" . implode(', ', $key) . ")";
- }
+ $sqls[] = $sql.$this->_process_column($field[$i]);
}
- $sql .= "\n)";
-
- return $sql;
+ return $sqls;
}
// --------------------------------------------------------------------
/**
- * Alter table query
+ * Field attribute TYPE
*
- * Generates a platform-specific query so that a table can be altered
- * Called by add_column(), drop_column(), and column_alter(),
+ * Performs a data type mapping between different databases.
*
- * @param string the ALTER type (ADD, DROP, CHANGE)
- * @param string the column name
- * @param string the table name
- * @param string the column definition
- * @param string the default value
- * @param bool should 'NOT NULL' be added
- * @param string the field after which we should add the new field
- * @return string
+ * @param array &$attributes
+ * @return void
*/
- protected function _alter_table($alter_type, $table, $column_name, $column_definition = '', $default_value = '', $null = '', $after_field = '')
+ protected function _attr_type(&$attributes)
{
- $sql = 'ALTER TABLE '.$this->db->protect_identifiers($table).' '.$alter_type.' '.$this->db->protect_identifiers($column_name);
-
- // DROP has everything it needs now.
- if ($alter_type == 'DROP')
+ switch (strtoupper($attributes['TYPE']))
{
- return $sql;
- }
-
- $sql .= " $column_definition";
-
- if ($default_value != '')
- {
- $sql .= " DEFAULT \"$default_value\"";
+ case 'MEDIUMINT':
+ $attributes['TYPE'] = 'INTEGER';
+ $attributes['UNSIGNED'] = FALSE;
+ return;
+ case 'INTEGER':
+ $attributes['TYPE'] = 'INT';
+ return;
+ default: return;
}
+ }
- if ($null === NULL)
- {
- $sql .= ' NULL';
- }
- else
- {
- $sql .= ' NOT NULL';
- }
+ // --------------------------------------------------------------------
- if ($after_field != '')
+ /**
+ * Field attribute AUTO_INCREMENT
+ *
+ * @param array &$attributes
+ * @param array &$field
+ * @return void
+ */
+ protected function _attr_auto_increment(&$attributes, &$field)
+ {
+ if ( ! empty($attributes['AUTO_INCREMENT']) && $attributes['AUTO_INCREMENT'] === TRUE && stripos($field['type'], 'int') !== FALSE)
{
- return $sql.' AFTER '.$this->db->protect_identifiers($after_field);
+ $field['auto_increment'] = ' IDENTITY(1,1)';
}
-
- return $sql;
-
}
}
diff --git a/system/database/drivers/mssql/mssql_result.php b/system/database/drivers/mssql/mssql_result.php
index 4cc87f4cf..ca222aed4 100644
--- a/system/database/drivers/mssql/mssql_result.php
+++ b/system/database/drivers/mssql/mssql_result.php
@@ -1,4 +1,4 @@
-<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');
+<?php
/**
* CodeIgniter
*
@@ -24,15 +24,17 @@
* @since Version 1.0
* @filesource
*/
+defined('BASEPATH') OR exit('No direct script access allowed');
/**
- * MS SQL Result Class
+ * MSSQL Result Class
*
* This class extends the parent result class: CI_DB_result
*
* @category Database
* @author EllisLab Dev Team
* @link http://codeigniter.com/user_guide/database/
+ * @since 1.3
*/
class CI_DB_mssql_result extends CI_DB_result {
@@ -43,7 +45,9 @@ class CI_DB_mssql_result extends CI_DB_result {
*/
public function num_rows()
{
- return @mssql_num_rows($this->result_id);
+ return is_int($this->num_rows)
+ ? $this->num_rows
+ : $this->num_rows = @mssql_num_rows($this->result_id);
}
// --------------------------------------------------------------------
@@ -90,16 +94,14 @@ class CI_DB_mssql_result extends CI_DB_result {
public function field_data()
{
$retval = array();
- while ($field = mssql_fetch_field($this->result_id))
+ for ($i = 0, $c = $this->num_field(); $i < $c; $i++)
{
- $F = new stdClass();
- $F->name = $field->name;
- $F->type = $field->type;
- $F->max_length = $field->max_length;
- $F->primary_key = 0;
- $F->default = '';
-
- $retval[] = $F;
+ $field = mssql_fetch_field($this->result_id, $i);
+
+ $retval[$i] = new stdClass();
+ $retval[$i]->name = $field->name;
+ $retval[$i]->type = $field->type;
+ $retval[$i]->max_length = $field->max_length;
}
return $retval;
@@ -128,11 +130,12 @@ class CI_DB_mssql_result extends CI_DB_result {
*
* Moves the internal pointer to the desired offset. We call
* this internally before fetching results to make sure the
- * result set starts at zero
+ * result set starts at zero.
*
+ * @param int $n
* @return bool
*/
- protected function _data_seek($n = 0)
+ public function data_seek($n = 0)
{
return mssql_data_seek($this->result_id, $n);
}
@@ -158,11 +161,25 @@ class CI_DB_mssql_result extends CI_DB_result {
*
* Returns the result set as an object
*
+ * @param string $class_name
* @return object
*/
- protected function _fetch_object()
+ protected function _fetch_object($class_name = 'stdClass')
{
- return mssql_fetch_object($this->result_id);
+ $row = @mssql_fetch_object($this->result_id);
+
+ if ($class_name === 'stdClass' OR ! $row)
+ {
+ return $row;
+ }
+
+ $class_name = new $class_name();
+ foreach ($row as $key => $value)
+ {
+ $class_name->$key = $value;
+ }
+
+ return $class_name;
}
}
diff --git a/system/database/drivers/mssql/mssql_utility.php b/system/database/drivers/mssql/mssql_utility.php
index 6d47618ce..76c7cb9c2 100644
--- a/system/database/drivers/mssql/mssql_utility.php
+++ b/system/database/drivers/mssql/mssql_utility.php
@@ -1,4 +1,4 @@
-<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');
+<?php
/**
* CodeIgniter
*
@@ -24,6 +24,7 @@
* @since Version 1.0
* @filesource
*/
+defined('BASEPATH') OR exit('No direct script access allowed');
/**
* MS SQL Utility Class
@@ -34,19 +35,30 @@
*/
class CI_DB_mssql_utility extends CI_DB_utility {
+ /**
+ * List databases statement
+ *
+ * @var string
+ */
protected $_list_databases = 'EXEC sp_helpdb'; // Can also be: EXEC sp_databases
+
+ /**
+ * OPTIMIZE TABLE statement
+ *
+ * @var string
+ */
protected $_optimize_table = 'ALTER INDEX all ON %s REORGANIZE';
/**
- * MSSQL Export
+ * Export
*
- * @param array Preferences
- * @return mixed
+ * @param array $params Preferences
+ * @return bool
*/
protected function _backup($params = array())
{
// Currently unsupported
- return $this->db->display_error('db_unsuported_feature');
+ return $this->db->display_error('db_unsupported_feature');
}
}
diff --git a/system/database/drivers/mysql/mysql_driver.php b/system/database/drivers/mysql/mysql_driver.php
index c2fccc1f7..5af44371c 100644
--- a/system/database/drivers/mysql/mysql_driver.php
+++ b/system/database/drivers/mysql/mysql_driver.php
@@ -1,4 +1,4 @@
-<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');
+<?php
/**
* CodeIgniter
*
@@ -24,12 +24,13 @@
* @since Version 1.0
* @filesource
*/
+defined('BASEPATH') OR exit('No direct script access allowed');
/**
* MySQL Database Adapter Class
*
* Note: _DB is an extender class that the app controller
- * creates dynamically based on whether the active record
+ * creates dynamically based on whether the query builder
* class is being used or not.
*
* @package CodeIgniter
@@ -40,48 +41,78 @@
*/
class CI_DB_mysql_driver extends CI_DB {
+ /**
+ * Database driver
+ *
+ * @var string
+ */
public $dbdriver = 'mysql';
- // The character used for escaping
- protected $_escape_char = '`';
-
- // clause and character used for LIKE escape sequences - not used in MySQL
- protected $_like_escape_str = '';
- protected $_like_escape_chr = '';
-
/**
- * The syntax to count rows is slightly different across different
- * database engines, so this string appears in each driver and is
- * used for the count_all() and count_all_results() functions.
+ * Compression flag
+ *
+ * @var bool
*/
- protected $_count_string = 'SELECT COUNT(*) AS ';
- protected $_random_keyword = ' RAND()'; // database specific random keyword
+ public $compress = FALSE;
/**
+ * DELETE hack flag
+ *
* Whether to use the MySQL "delete hack" which allows the number
* of affected rows to be shown. Uses a preg_replace when enabled,
* adding a bit more processing to all queries.
+ *
+ * @var bool
*/
public $delete_hack = TRUE;
+ // --------------------------------------------------------------------
+
+ /**
+ * Identifier escape character
+ *
+ * @var string
+ */
+ protected $_escape_char = '`';
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Class constructor
+ *
+ * @param array $params
+ * @return void
+ */
public function __construct($params)
{
parent::__construct($params);
- if ($this->port != '')
+ if ( ! empty($this->port))
{
$this->hostname .= ':'.$this->port;
}
}
+ // --------------------------------------------------------------------
+
/**
* Non-persistent database connection
*
+ * @param bool $persistent
* @return resource
*/
- public function db_connect()
+ public function db_connect($persistent = FALSE)
{
- return @mysql_connect($this->hostname, $this->username, $this->password, TRUE);
+ $client_flags = ($this->compress === FALSE) ? 0 : MYSQL_CLIENT_COMPRESS;
+
+ if ($this->encrypt === TRUE)
+ {
+ $client_flags = $client_flags | MYSQL_CLIENT_SSL;
+ }
+
+ return ($persistent === TRUE)
+ ? @mysql_pconnect($this->hostname, $this->username, $this->password, $client_flags)
+ : @mysql_connect($this->hostname, $this->username, $this->password, TRUE, $client_flags);
}
// --------------------------------------------------------------------
@@ -93,7 +124,7 @@ class CI_DB_mysql_driver extends CI_DB {
*/
public function db_pconnect()
{
- return @mysql_pconnect($this->hostname, $this->username, $this->password);
+ return $this->db_connect(TRUE);
}
// --------------------------------------------------------------------
@@ -119,7 +150,7 @@ class CI_DB_mysql_driver extends CI_DB {
/**
* Select the database
*
- * @param string database name
+ * @param string $database
* @return bool
*/
public function db_select($database = '')
@@ -143,7 +174,7 @@ class CI_DB_mysql_driver extends CI_DB {
/**
* Set client character set
*
- * @param string
+ * @param string $charset
* @return bool
*/
protected function _db_set_charset($charset)
@@ -160,9 +191,21 @@ class CI_DB_mysql_driver extends CI_DB {
*/
public function version()
{
- return isset($this->data_cache['version'])
- ? $this->data_cache['version']
- : $this->data_cache['version'] = @mysql_get_server_info($this->conn_id);
+ if (isset($this->data_cache['version']))
+ {
+ return $this->data_cache['version'];
+ }
+ elseif ( ! $this->conn_id)
+ {
+ $this->initialize();
+ }
+
+ if ( ! $this->conn_id OR ($version = @mysql_get_server_info($this->conn_id)) === FALSE)
+ {
+ return FALSE;
+ }
+
+ return $this->data_cache['version'] = $version;
}
// --------------------------------------------------------------------
@@ -170,7 +213,7 @@ class CI_DB_mysql_driver extends CI_DB {
/**
* Execute the query
*
- * @param string an SQL query
+ * @param string $sql an SQL query
* @return mixed
*/
protected function _execute($sql)
@@ -185,7 +228,7 @@ class CI_DB_mysql_driver extends CI_DB {
*
* If needed, each database adapter can prep the query string
*
- * @param string an SQL query
+ * @param string $sql an SQL query
* @return string
*/
protected function _prep_query($sql)
@@ -205,6 +248,7 @@ class CI_DB_mysql_driver extends CI_DB {
/**
* Begin Transaction
*
+ * @param bool $test_mode
* @return bool
*/
public function trans_begin($test_mode = FALSE)
@@ -270,8 +314,8 @@ class CI_DB_mysql_driver extends CI_DB {
/**
* Escape String
*
- * @param string
- * @param bool whether or not the string will be used in a LIKE condition
+ * @param string $str
+ * @param bool $like Whether or not the string will be used in a LIKE condition
* @return string
*/
public function escape_str($str, $like = FALSE)
@@ -279,19 +323,21 @@ class CI_DB_mysql_driver extends CI_DB {
if (is_array($str))
{
foreach ($str as $key => $val)
- {
+ {
$str[$key] = $this->escape_str($val, $like);
- }
+ }
- return $str;
- }
+ return $str;
+ }
$str = is_resource($this->conn_id) ? mysql_real_escape_string($str, $this->conn_id) : addslashes($str);
// escape LIKE condition wildcards
if ($like === TRUE)
{
- return str_replace(array('%', '_'), array('\\%', '\\_'), $str);
+ return str_replace(array($this->_like_escape_chr, '%', '_'),
+ array($this->_like_escape_chr.$this->_like_escape_chr, $this->_like_escape_chr.'%', $this->_like_escape_chr.'_'),
+ $str);
}
return $str;
@@ -324,47 +370,18 @@ class CI_DB_mysql_driver extends CI_DB {
// --------------------------------------------------------------------
/**
- * "Count All" query
- *
- * Generates a platform-specific query string that counts all records in
- * the specified database
- *
- * @param string
- * @return string
- */
- public function count_all($table = '')
- {
- if ($table == '')
- {
- return 0;
- }
-
- $query = $this->query($this->_count_string.$this->protect_identifiers('numrows').' FROM '.$this->protect_identifiers($table, TRUE, NULL, FALSE));
- if ($query->num_rows() == 0)
- {
- return 0;
- }
-
- $query = $query->row();
- $this->_reset_select();
- return (int) $query->numrows;
- }
-
- // --------------------------------------------------------------------
-
- /**
* List table query
*
* Generates a platform-specific query string so that the table names can be fetched
*
- * @param bool
+ * @param bool $prefix_limit
* @return string
*/
protected function _list_tables($prefix_limit = FALSE)
{
- $sql = 'SHOW TABLES FROM '.$this->_escape_char.$this->database.$this->_escape_char;
+ $sql = 'SHOW TABLES FROM '.$this->escape_identifiers($this->database);
- if ($prefix_limit !== FALSE && $this->dbprefix != '')
+ if ($prefix_limit !== FALSE && $this->dbprefix !== '')
{
return $sql." LIKE '".$this->escape_like_str($this->dbprefix)."%'";
}
@@ -379,10 +396,10 @@ class CI_DB_mysql_driver extends CI_DB {
*
* Generates a platform-specific query string so that the column names can be fetched
*
- * @param string the table name
+ * @param string $table
* @return string
*/
- public function _list_columns($table = '')
+ protected function _list_columns($table = '')
{
return 'SHOW COLUMNS FROM '.$this->protect_identifiers($table, TRUE, NULL, FALSE);
}
@@ -392,29 +409,34 @@ class CI_DB_mysql_driver extends CI_DB {
/**
* Returns an object with field data
*
- * @param string the table name
- * @return object
+ * @param string $table
+ * @return array
*/
public function field_data($table = '')
{
- if ($table == '')
+ if ($table === '')
{
return ($this->db_debug) ? $this->display_error('db_field_param_missing') : FALSE;
}
- $query = $this->query('DESCRIBE '.$this->protect_identifiers($table, TRUE, NULL, FALSE));
+ if (($query = $this->query('SHOW COLUMNS FROM '.$this->protect_identifiers($table, TRUE, NULL, FALSE))) === FALSE)
+ {
+ return FALSE;
+ }
$query = $query->result_object();
$retval = array();
for ($i = 0, $c = count($query); $i < $c; $i++)
{
- preg_match('/([a-z]+)(\(\d+\))?/', $query[$i]->Type, $matches);
-
$retval[$i] = new stdClass();
$retval[$i]->name = $query[$i]->Field;
- $retval[$i]->type = empty($matches[1]) ? NULL : $matches[1];
+
+ sscanf($query[$i]->Type, '%[a-z](%d)',
+ $retval[$i]->type,
+ $retval[$i]->max_length
+ );
+
$retval[$i]->default = $query[$i]->Default;
- $retval[$i]->max_length = empty($matches[2]) ? NULL : preg_replace('/[^\d]/', '', $matches[2]);
$retval[$i]->primary_key = (int) ($query[$i]->Key === 'PRI');
}
@@ -439,37 +461,16 @@ class CI_DB_mysql_driver extends CI_DB {
// --------------------------------------------------------------------
/**
- * From Tables
- *
- * This function implicitly groups FROM tables so there is no confusion
- * about operator precedence in harmony with SQL standards
- *
- * @param string table name
- * @return string
- */
- protected function _from_tables($tables)
- {
- if ( ! is_array($tables))
- {
- $tables = array($tables);
- }
-
- return '('.implode(', ', $tables).')';
- }
-
- // --------------------------------------------------------------------
-
- /**
* Update_Batch statement
*
* Generates a platform-specific batch update string from the supplied data
*
- * @param string the table name
- * @param array the update data
- * @param array the where clause
+ * @param string $table Table name
+ * @param array $values Update data
+ * @param string $index WHERE key
* @return string
*/
- protected function _update_batch($table, $values, $index, $where = NULL)
+ protected function _update_batch($table, $values, $index)
{
$ids = array();
foreach ($values as $key => $val)
@@ -478,9 +479,9 @@ class CI_DB_mysql_driver extends CI_DB {
foreach (array_keys($val) as $field)
{
- if ($field != $index)
+ if ($field !== $index)
{
- $final[$field][] = 'WHEN '.$index.' = '.$val[$index].' THEN '.$val[$field];
+ $final[$field][] = 'WHEN '.$index.' = '.$val[$index].' THEN '.$val[$field];
}
}
}
@@ -493,26 +494,29 @@ class CI_DB_mysql_driver extends CI_DB {
.'ELSE '.$k.' END, ';
}
- return 'UPDATE '.$table.' SET '.substr($cases, 0, -2)
- .' WHERE '.(($where != '' && count($where) > 0) ? implode(' ', $where).' AND ' : '')
- .$index.' IN('.implode(',', $ids).')';
+ $this->where($index.' IN('.implode(',', $ids).')', NULL, FALSE);
+
+ return 'UPDATE '.$table.' SET '.substr($cases, 0, -2).$this->_compile_wh('qb_where');
}
// --------------------------------------------------------------------
/**
- * Limit string
+ * FROM tables
*
- * Generates a platform-specific LIMIT clause
+ * Groups tables in FROM clauses if needed, so there is no confusion
+ * about operator precedence.
*
- * @param string the sql query string
- * @param int the number of rows to limit the query to
- * @param int the offset value
* @return string
*/
- protected function _limit($sql, $limit, $offset)
+ protected function _from_tables()
{
- return $sql.' LIMIT '.($offset == 0 ? '' : $offset.', ').$limit;
+ if ( ! empty($this->qb_join) && count($this->qb_from) > 1)
+ {
+ return '('.implode(', ', $this->qb_from).')';
+ }
+
+ return implode(', ', $this->qb_from);
}
// --------------------------------------------------------------------
@@ -520,12 +524,11 @@ class CI_DB_mysql_driver extends CI_DB {
/**
* Close DB Connection
*
- * @param resource
* @return void
*/
- protected function _close($conn_id)
+ protected function _close()
{
- @mysql_close($conn_id);
+ @mysql_close($this->conn_id);
}
}
diff --git a/system/database/drivers/mysql/mysql_forge.php b/system/database/drivers/mysql/mysql_forge.php
index 0e39affa7..f4394c685 100644
--- a/system/database/drivers/mysql/mysql_forge.php
+++ b/system/database/drivers/mysql/mysql_forge.php
@@ -1,4 +1,4 @@
-<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');
+<?php
/**
* CodeIgniter
*
@@ -24,6 +24,7 @@
* @since Version 1.0
* @filesource
*/
+defined('BASEPATH') OR exit('No direct script access allowed');
/**
* MySQL Forge Class
@@ -34,151 +35,178 @@
*/
class CI_DB_mysql_forge extends CI_DB_forge {
+ /**
+ * CREATE DATABASE statement
+ *
+ * @var string
+ */
protected $_create_database = 'CREATE DATABASE %s CHARACTER SET %s COLLATE %s';
/**
- * Process Fields
+ * CREATE TABLE keys flag
*
- * @param mixed the fields
- * @return string
+ * Whether table keys are created from within the
+ * CREATE TABLE statement.
+ *
+ * @var bool
*/
- protected function _process_fields($fields)
- {
- $current_field_count = 0;
- $sql = '';
-
- foreach ($fields as $field => $attributes)
- {
- // Numeric field names aren't allowed in databases, so if the key is
- // numeric, we know it was assigned by PHP and the developer manually
- // entered the field information, so we'll simply add it to the list
- if (is_numeric($field))
- {
- $sql .= "\n\t".$attributes;
- }
- else
- {
- $attributes = array_change_key_case($attributes, CASE_UPPER);
-
- $sql .= "\n\t".$this->db->protect_identifiers($field)
- .( ! empty($attributes['NAME']) ? ' '.$this->db->protect_identifiers($attributes['NAME']).' ' : '');
+ protected $_create_table_keys = TRUE;
- if ( ! empty($attributes['TYPE']))
- {
- $sql .= ' '.$attributes['TYPE'];
+ /**
+ * UNSIGNED support
+ *
+ * @var array
+ */
+ protected $_unsigned = array(
+ 'TINYINT',
+ 'SMALLINT',
+ 'MEDIUMINT',
+ 'INT',
+ 'INTEGER',
+ 'BIGINT',
+ 'REAL',
+ 'DOUBLE',
+ 'DOUBLE PRECISION',
+ 'FLOAT',
+ 'DECIMAL',
+ 'NUMERIC'
+ );
- if ( ! empty($attributes['CONSTRAINT']))
- {
- switch (strtolower($attributes['TYPE']))
- {
- case 'decimal':
- case 'float':
- case 'numeric':
- $sql .= '('.implode(',', $attributes['CONSTRAINT']).')';
- break;
- case 'enum':
- case 'set':
- $sql .= '("'.implode('","', $attributes['CONSTRAINT']).'")';
- break;
- default:
- $sql .= '('.$attributes['CONSTRAINT'].')';
- }
- }
- }
+ /**
+ * NULL value representation in CREATE/ALTER TABLE statements
+ *
+ * @var string
+ */
+ protected $_null = 'NULL';
- $sql .= (( ! empty($attributes['UNSIGNED']) && $attributes['UNSIGNED'] === TRUE) ? ' UNSIGNED' : '')
- .(isset($attributes['DEFAULT']) ? " DEFAULT '".$attributes['DEFAULT']."'" : '')
- .(( ! empty($attributes['NULL']) && $attributes['NULL'] === TRUE) ? ' NULL' : ' NOT NULL')
- .(( ! empty($attributes['AUTO_INCREMENT']) && $attributes['AUTO_INCREMENT'] === TRUE) ? ' AUTO_INCREMENT' : '');
- }
+ // --------------------------------------------------------------------
- // don't add a comma on the end of the last field
- if (++$current_field_count < count($fields))
- {
- $sql .= ',';
- }
- }
+ /**
+ * Class constructor
+ *
+ * @param object &$db Database object
+ * @return void
+ */
+ public function __construct(&$db)
+ {
+ parent::__construct($db);
- return $sql;
+ $this->_create_table .= ' DEFAULT CHARSET '.$this->db->char_set.' COLLATE '.$this->db->dbcollat;
}
// --------------------------------------------------------------------
/**
- * Create Table
+ * ALTER TABLE
*
- * @param string the table name
- * @param mixed the fields
- * @param mixed primary key(s)
- * @param mixed key(s)
- * @param bool should 'IF NOT EXISTS' be added to the SQL
- * @return bool
+ * @param string $alter_type ALTER type
+ * @param string $table Table name
+ * @param mixed $field Column definition
+ * @return string|string[]
*/
- protected function _create_table($table, $fields, $primary_keys, $keys, $if_not_exists)
+ protected function _alter_table($alter_type, $table, $field)
{
- $sql = 'CREATE TABLE ';
-
- if ($if_not_exists === TRUE)
- {
- $sql .= 'IF NOT EXISTS ';
- }
-
- $sql .= $this->db->protect_identifiers($table).' ('.$this->_process_fields($fields);
-
- if (count($primary_keys) > 0)
+ if ($alter_type === 'DROP')
{
- $key_name = $this->db->protect_identifiers(implode('_', $primary_keys));
- $sql .= ",\n\tPRIMARY KEY ".$key_name.' ('.implode(', ', $this->db->protect_identifiers($primary_keys)).')';
+ return parent::_alter_table($alter_type, $table, $field);
}
- if (is_array($keys) && count($keys) > 0)
+ $sql = 'ALTER TABLE '.$this->db->escape_identifiers($table);
+ for ($i = 0, $c = count($field); $i < $c; $i++)
{
- foreach ($keys as $key)
+ if ($field[$i]['_literal'] !== FALSE)
{
- if (is_array($key))
+ $field[$i] = ($alter_type === 'ADD')
+ ? "\n\tADD ".$field[$i]['_literal']
+ : "\n\tMODIFY ".$field[$i]['_literal'];
+ }
+ else
+ {
+ if ($alter_type === 'ADD')
{
- $key_name = $this->db->protect_identifiers(implode('_', $key));
- $key = $this->db->protect_identifiers($key);
+ $field[$i]['_literal'] = "\n\tADD ";
}
else
{
- $key_name = $this->db->protect_identifiers($key);
- $key = array($key_name);
+ $field[$i]['_literal'] = empty($field[$i]['new_name']) ? "\n\tMODIFY " : "\n\tCHANGE ";
}
- $sql .= ",\n\tKEY ".$key_name.' ('.implode(', ', $key).')';
+ $field[$i] = $field[$i]['_literal'].$this->_process_column($field[$i]);
}
}
- return $sql."\n) DEFAULT CHARACTER SET ".$this->db->char_set.' COLLATE '.$this->db->dbcollat.';';
+ return array($sql.implode(',', $field));
}
// --------------------------------------------------------------------
/**
- * Alter table query
+ * Process column
*
- * Generates a platform-specific query so that a table can be altered
- * Called by add_column(), drop_column() and column_alter()
+ * @param array $field
+ * @return string
+ */
+ protected function _process_column($field)
+ {
+ $extra_clause = isset($field['after'])
+ ? ' AFTER '.$this->db->escape_identifiers($field['after']) : '';
+
+ if (empty($extra_clause) && isset($field['first']) && $field['first'] === TRUE)
+ {
+ $extra_clause = ' FIRST';
+ }
+
+ return $this->db->escape_identifiers($field['name'])
+ .(empty($field['new_name']) ? '' : ' '.$this->db->escape_identifiers($field['new_name']))
+ .' '.$field['type'].$field['length']
+ .$field['unsigned']
+ .$field['null']
+ .$field['default']
+ .$field['auto_increment']
+ .$field['unique']
+ .$extra_clause;
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Process indexes
*
- * @param string the ALTER type (ADD, DROP, CHANGE)
- * @param string the column name
- * @param array fields
- * @param string the field after which we should add the new field
+ * @param string $table (ignored)
* @return string
*/
- protected function _alter_table($alter_type, $table, $fields, $after_field = '')
+ protected function _process_indexes($table)
{
- $sql = 'ALTER TABLE '.$this->db->protect_identifiers($table).' '.$alter_type.' ';
+ $sql = '';
- // DROP has everything it needs now.
- if ($alter_type === 'DROP')
+ for ($i = 0, $c = count($this->keys); $i < $c; $i++)
{
- return $sql.$this->db->protect_identifiers($fields);
+ 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;
+ }
+
+ is_array($this->keys[$i]) OR $this->keys[$i] = array($this->keys[$i]);
+
+ $sql .= ",\n\tKEY ".$this->db->escape_identifiers(implode('_', $this->keys[$i]))
+ .' ('.implode(', ', $this->db->escape_identifiers($this->keys[$i])).')';
}
- return $sql.$this->_process_fields($fields)
- .($after_field != '' ? ' AFTER '.$this->db->protect_identifiers($after_field) : '');
+ $this->keys = array();
+
+ return $sql;
}
}
diff --git a/system/database/drivers/mysql/mysql_result.php b/system/database/drivers/mysql/mysql_result.php
index 14d6d072a..293980e97 100644
--- a/system/database/drivers/mysql/mysql_result.php
+++ b/system/database/drivers/mysql/mysql_result.php
@@ -1,4 +1,4 @@
-<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');
+<?php
/**
* CodeIgniter
*
@@ -24,6 +24,7 @@
* @since Version 1.0
* @filesource
*/
+defined('BASEPATH') OR exit('No direct script access allowed');
/**
* MySQL Result Class
@@ -33,17 +34,35 @@
* @category Database
* @author EllisLab Dev Team
* @link http://codeigniter.com/user_guide/database/
+ * @since 1.0
*/
class CI_DB_mysql_result extends CI_DB_result {
/**
+ * Class constructor
+ *
+ * @param object &$driver_object
+ * @return void
+ */
+ public function __construct(&$driver_object)
+ {
+ parent::__construct($driver_object);
+
+ // Required, due to mysql_data_seek() causing nightmares
+ // with empty result sets
+ $this->num_rows = @mysql_num_rows($this->result_id);
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
* Number of rows in the result set
*
* @return int
*/
public function num_rows()
{
- return @mysql_num_rows($this->result_id);
+ return $this->num_rows;
}
// --------------------------------------------------------------------
@@ -96,8 +115,7 @@ class CI_DB_mysql_result extends CI_DB_result {
$retval[$i]->name = mysql_field_name($this->result_id, $i);
$retval[$i]->type = mysql_field_type($this->result_id, $i);
$retval[$i]->max_length = mysql_field_len($this->result_id, $i);
- $retval[$i]->primary_key = (strpos(mysql_field_flags($this->result_id, $i), 'primary_key') === FALSE) ? 0 : 1;
- $retval[$i]->default = '';
+ $retval[$i]->primary_key = (int) (strpos(mysql_field_flags($this->result_id, $i), 'primary_key') !== FALSE);
}
return $retval;
@@ -126,13 +144,16 @@ class CI_DB_mysql_result extends CI_DB_result {
*
* Moves the internal pointer to the desired offset. We call
* this internally before fetching results to make sure the
- * result set starts at zero
+ * result set starts at zero.
*
+ * @param int $n
* @return bool
*/
- protected function _data_seek($n = 0)
+ public function data_seek($n = 0)
{
- return mysql_data_seek($this->result_id, $n);
+ return $this->num_rows
+ ? @mysql_data_seek($this->result_id, $n)
+ : FALSE;
}
// --------------------------------------------------------------------
@@ -156,11 +177,12 @@ class CI_DB_mysql_result extends CI_DB_result {
*
* Returns the result set as an object
*
+ * @param string $class_name
* @return object
*/
- protected function _fetch_object()
+ protected function _fetch_object($class_name = 'stdClass')
{
- return mysql_fetch_object($this->result_id);
+ return mysql_fetch_object($this->result_id, $class_name);
}
}
diff --git a/system/database/drivers/mysql/mysql_utility.php b/system/database/drivers/mysql/mysql_utility.php
index 642323dbd..8aa051755 100644
--- a/system/database/drivers/mysql/mysql_utility.php
+++ b/system/database/drivers/mysql/mysql_utility.php
@@ -1,4 +1,4 @@
-<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');
+<?php
/**
* CodeIgniter
*
@@ -24,6 +24,7 @@
* @since Version 1.0
* @filesource
*/
+defined('BASEPATH') OR exit('No direct script access allowed');
/**
* MySQL Utility Class
@@ -34,14 +35,33 @@
*/
class CI_DB_mysql_utility extends CI_DB_utility {
+ /**
+ * List databases statement
+ *
+ * @var string
+ */
protected $_list_databases = 'SHOW DATABASES';
+
+ /**
+ * OPTIMIZE TABLE statement
+ *
+ * @var string
+ */
protected $_optimize_table = 'OPTIMIZE TABLE %s';
+
+ /**
+ * REPAIR TABLE statement
+ *
+ * @var string
+ */
protected $_repair_table = 'REPAIR TABLE %s';
+ // --------------------------------------------------------------------
+
/**
- * MySQL Export
+ * Export
*
- * @param array Preferences
+ * @param array $params Preferences
* @return mixed
*/
protected function _backup($params = array())
@@ -65,7 +85,7 @@ class CI_DB_mysql_utility extends CI_DB_utility {
}
// Get the table schema
- $query = $this->db->query('SHOW CREATE TABLE '.$this->db->protect_identifiers($this->db->database).'.'.$this->db->protect_identifiers($table));
+ $query = $this->db->query('SHOW CREATE TABLE '.$this->db->escape_identifiers($this->db->database.'.'.$table));
// No result means the table name was invalid
if ($query === FALSE)
@@ -76,7 +96,7 @@ class CI_DB_mysql_utility extends CI_DB_utility {
// Write out the table schema
$output .= '#'.$newline.'# TABLE STRUCTURE FOR: '.$table.$newline.'#'.$newline.$newline;
- if ($add_drop == TRUE)
+ if ($add_drop === TRUE)
{
$output .= 'DROP TABLE IF EXISTS '.$this->db->protect_identifiers($table).';'.$newline.$newline;
}
@@ -92,7 +112,7 @@ class CI_DB_mysql_utility extends CI_DB_utility {
}
// If inserts are not needed we're done...
- if ($add_insert == FALSE)
+ if ($add_insert === FALSE)
{
continue;
}
@@ -100,7 +120,7 @@ class CI_DB_mysql_utility extends CI_DB_utility {
// Grab all the data from the current table
$query = $this->db->query('SELECT * FROM '.$this->db->protect_identifiers($table));
- if ($query->num_rows() == 0)
+ if ($query->num_rows() === 0)
{
continue;
}
@@ -120,7 +140,7 @@ class CI_DB_mysql_utility extends CI_DB_utility {
TRUE);
// Create a string of field names
- $field_str .= $this->db->protect_identifiers($field->name).', ';
+ $field_str .= $this->db->escape_identifiers($field->name).', ';
$i++;
}
@@ -143,7 +163,7 @@ class CI_DB_mysql_utility extends CI_DB_utility {
else
{
// Escape the data if it's not an integer
- $val_str .= ($is_int[$i] == FALSE) ? $this->db->escape($v) : $v;
+ $val_str .= ($is_int[$i] === FALSE) ? $this->db->escape($v) : $v;
}
// Append a comma
diff --git a/system/database/drivers/mysqli/mysqli_driver.php b/system/database/drivers/mysqli/mysqli_driver.php
index a690682be..17f025f61 100644
--- a/system/database/drivers/mysqli/mysqli_driver.php
+++ b/system/database/drivers/mysqli/mysqli_driver.php
@@ -1,4 +1,4 @@
-<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');
+<?php
/**
* CodeIgniter
*
@@ -24,12 +24,13 @@
* @since Version 1.0
* @filesource
*/
+defined('BASEPATH') OR exit('No direct script access allowed');
/**
* MySQLi Database Adapter Class
*
* Note: _DB is an extender class that the app controller
- * creates dynamically based on whether the active record
+ * creates dynamically based on whether the query builder
* class is being used or not.
*
* @package CodeIgniter
@@ -40,40 +41,60 @@
*/
class CI_DB_mysqli_driver extends CI_DB {
+ /**
+ * Database driver
+ *
+ * @var string
+ */
public $dbdriver = 'mysqli';
- // The character used for escaping
- protected $_escape_char = '`';
-
- // clause and character used for LIKE escape sequences - not used in MySQL
- protected $_like_escape_str = '';
- protected $_like_escape_chr = '';
-
/**
- * The syntax to count rows is slightly different across different
- * database engines, so this string appears in each driver and is
- * used for the count_all() and count_all_results() functions.
+ * Compression flag
+ *
+ * @var bool
*/
- protected $_count_string = 'SELECT COUNT(*) AS ';
- protected $_random_keyword = ' RAND()'; // database specific random keyword
+ public $compress = FALSE;
/**
+ * DELETE hack flag
+ *
* Whether to use the MySQL "delete hack" which allows the number
* of affected rows to be shown. Uses a preg_replace when enabled,
* adding a bit more processing to all queries.
+ *
+ * @var bool
*/
public $delete_hack = TRUE;
+ // --------------------------------------------------------------------
+
/**
- * Non-persistent database connection
+ * Identifier escape character
*
+ * @var string
+ */
+ protected $_escape_char = '`';
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Database connection
+ *
+ * @param bool $persistent
* @return object
+ * @todo SSL support
*/
- public function db_connect()
+ public function db_connect($persistent = FALSE)
{
- return ($this->port != '')
- ? @new mysqli($this->hostname, $this->username, $this->password, $this->database, $this->port)
- : @new mysqli($this->hostname, $this->username, $this->password, $this->database);
+ // Persistent connection support was added in PHP 5.3.0
+ $hostname = ($persistent === TRUE && is_php('5.3'))
+ ? 'p:'.$this->hostname : $this->hostname;
+ $port = empty($this->port) ? NULL : $this->port;
+ $client_flags = ($this->compress === TRUE) ? MYSQLI_CLIENT_COMPRESS : 0;
+ $mysqli = mysqli_init();
+
+ return @$mysqli->real_connect($hostname, $this->username, $this->password, $this->database, $port, NULL, $client_flags)
+ ? $mysqli : FALSE;
}
// --------------------------------------------------------------------
@@ -85,15 +106,7 @@ class CI_DB_mysqli_driver extends CI_DB {
*/
public function db_pconnect()
{
- // Persistent connection support was added in PHP 5.3.0
- if ( ! is_php('5.3'))
- {
- return $this->db_connect();
- }
-
- return ($this->port != '')
- ? @new mysqli('p:'.$this->hostname, $this->username, $this->password, $this->database, $this->port)
- : @new mysqli('p:'.$this->hostname, $this->username, $this->password, $this->database);
+ return $this->db_connect(TRUE);
}
// --------------------------------------------------------------------
@@ -119,7 +132,7 @@ class CI_DB_mysqli_driver extends CI_DB {
/**
* Select the database
*
- * @param string database name
+ * @param string $database
* @return bool
*/
public function db_select($database = '')
@@ -143,7 +156,7 @@ class CI_DB_mysqli_driver extends CI_DB {
/**
* Set client character set
*
- * @param string
+ * @param string $charset
* @return bool
*/
protected function _db_set_charset($charset)
@@ -160,9 +173,16 @@ class CI_DB_mysqli_driver extends CI_DB {
*/
public function version()
{
- return isset($this->data_cache['version'])
- ? $this->data_cache['version']
- : $this->data_cache['version'] = $this->conn_id->server_info;
+ if (isset($this->data_cache['version']))
+ {
+ return $this->data_cache['version'];
+ }
+ elseif ( ! $this->conn_id)
+ {
+ $this->initialize();
+ }
+
+ return $this->data_cache['version'] = $this->conn_id->server_info;
}
// --------------------------------------------------------------------
@@ -170,7 +190,7 @@ class CI_DB_mysqli_driver extends CI_DB {
/**
* Execute the query
*
- * @param string an SQL query
+ * @param string $sql an SQL query
* @return mixed
*/
protected function _execute($sql)
@@ -185,7 +205,7 @@ class CI_DB_mysqli_driver extends CI_DB {
*
* If needed, each database adapter can prep the query string
*
- * @param string an SQL query
+ * @param string $sql an SQL query
* @return string
*/
protected function _prep_query($sql)
@@ -205,6 +225,7 @@ class CI_DB_mysqli_driver extends CI_DB {
/**
* Begin Transaction
*
+ * @param bool $test_mode
* @return bool
*/
public function trans_begin($test_mode = FALSE)
@@ -270,8 +291,8 @@ class CI_DB_mysqli_driver extends CI_DB {
/**
* Escape String
*
- * @param string
- * @param bool whether or not the string will be used in a LIKE condition
+ * @param string $str
+ * @param bool $like Whether or not the string will be used in a LIKE condition
* @return string
*/
public function escape_str($str, $like = FALSE)
@@ -291,7 +312,9 @@ class CI_DB_mysqli_driver extends CI_DB {
// escape LIKE condition wildcards
if ($like === TRUE)
{
- return str_replace(array('%', '_'), array('\\%', '\\_'), $str);
+ return str_replace(array($this->_like_escape_chr, '%', '_'),
+ array($this->_like_escape_chr.$this->_like_escape_chr, $this->_like_escape_chr.'%', $this->_like_escape_chr.'_'),
+ $str);
}
return $str;
@@ -324,47 +347,18 @@ class CI_DB_mysqli_driver extends CI_DB {
// --------------------------------------------------------------------
/**
- * "Count All" query
- *
- * Generates a platform-specific query string that counts all records in
- * the specified database
- *
- * @param string
- * @return string
- */
- public function count_all($table = '')
- {
- if ($table == '')
- {
- return 0;
- }
-
- $query = $this->query($this->_count_string.$this->protect_identifiers('numrows').' FROM '.$this->protect_identifiers($table, TRUE, NULL, FALSE));
- if ($query->num_rows() == 0)
- {
- return 0;
- }
-
- $query = $query->row();
- $this->_reset_select();
- return (int) $query->numrows;
- }
-
- // --------------------------------------------------------------------
-
- /**
* List table query
*
* Generates a platform-specific query string so that the table names can be fetched
*
- * @param bool
+ * @param bool $prefix_limit
* @return string
*/
protected function _list_tables($prefix_limit = FALSE)
{
- $sql = 'SHOW TABLES FROM '.$this->_escape_char.$this->database.$this->_escape_char;
+ $sql = 'SHOW TABLES FROM '.$this->escape_identifiers($this->database);
- if ($prefix_limit !== FALSE && $this->dbprefix != '')
+ if ($prefix_limit !== FALSE && $this->dbprefix !== '')
{
return $sql." LIKE '".$this->escape_like_str($this->dbprefix)."%'";
}
@@ -379,7 +373,7 @@ class CI_DB_mysqli_driver extends CI_DB {
*
* Generates a platform-specific query string so that the column names can be fetched
*
- * @param string the table name
+ * @param string $table
* @return string
*/
protected function _list_columns($table = '')
@@ -392,29 +386,34 @@ class CI_DB_mysqli_driver extends CI_DB {
/**
* Returns an object with field data
*
- * @param string the table name
- * @return object
+ * @param string $table
+ * @return array
*/
public function field_data($table = '')
{
- if ($table == '')
+ if ($table === '')
{
return ($this->db_debug) ? $this->display_error('db_field_param_missing') : FALSE;
}
- $query = $this->query('DESCRIBE '.$this->protect_identifiers($table, TRUE, NULL, FALSE));
+ if (($query = $this->query('SHOW COLUMNS FROM '.$this->protect_identifiers($table, TRUE, NULL, FALSE))) === FALSE)
+ {
+ return FALSE;
+ }
$query = $query->result_object();
$retval = array();
for ($i = 0, $c = count($query); $i < $c; $i++)
{
- preg_match('/([a-z]+)(\(\d+\))?/', $query[$i]->Type, $matches);
-
$retval[$i] = new stdClass();
$retval[$i]->name = $query[$i]->Field;
- $retval[$i]->type = empty($matches[1]) ? NULL : $matches[1];
+
+ sscanf($query[$i]->Type, '%[a-z](%d)',
+ $retval[$i]->type,
+ $retval[$i]->max_length
+ );
+
$retval[$i]->default = $query[$i]->Default;
- $retval[$i]->max_length = empty($matches[2]) ? NULL : preg_replace('/[^\d]/', '', $matches[2]);
$retval[$i]->primary_key = (int) ($query[$i]->Key === 'PRI');
}
@@ -433,28 +432,15 @@ class CI_DB_mysqli_driver extends CI_DB {
*/
public function error()
{
- return array('code' => $this->conn_id->errno, 'message' => $this->conn_id->error);
- }
-
- // --------------------------------------------------------------------
-
- /**
- * From Tables
- *
- * This function implicitly groups FROM tables so there is no confusion
- * about operator precedence in harmony with SQL standards
- *
- * @param string
- * @return string
- */
- protected function _from_tables($tables)
- {
- if ( ! is_array($tables))
+ if ( ! empty($this->conn_id->connect_errno))
{
- $tables = array($tables);
+ return array(
+ 'code' => $this->conn_id->connect_errno,
+ 'message' => is_php('5.2.9') ? $this->conn_id->connect_error : mysqli_connect_error()
+ );
}
- return '('.implode(', ', $tables).')';
+ return array('code' => $this->conn_id->errno, 'message' => $this->conn_id->error);
}
// --------------------------------------------------------------------
@@ -464,12 +450,12 @@ class CI_DB_mysqli_driver extends CI_DB {
*
* Generates a platform-specific batch update string from the supplied data
*
- * @param string the table name
- * @param array the update data
- * @param array the where clause
+ * @param string $table Table name
+ * @param array $values Update data
+ * @param string $index WHERE key
* @return string
*/
- protected function _update_batch($table, $values, $index, $where = NULL)
+ protected function _update_batch($table, $values, $index)
{
$ids = array();
foreach ($values as $key => $val)
@@ -478,9 +464,9 @@ class CI_DB_mysqli_driver extends CI_DB {
foreach (array_keys($val) as $field)
{
- if ($field != $index)
+ if ($field !== $index)
{
- $final[$field][] = 'WHEN '.$index.' = '.$val[$index].' THEN '.$val[$field];
+ $final[$field][] = 'WHEN '.$index.' = '.$val[$index].' THEN '.$val[$field];
}
}
}
@@ -493,29 +479,29 @@ class CI_DB_mysqli_driver extends CI_DB {
.'ELSE '.$k.' END, ';
}
- $where = ($where != '' && count($where) > 0) ? implode(' ', $where).' AND ' : '';
+ $this->where($index.' IN('.implode(',', $ids).')', NULL, FALSE);
- return 'UPDATE '.$table.' SET '.substr($cases, 0, -2)
- .' WHERE '.(($where != '' && count($where) > 0) ? implode(' ', $where).' AND ' : '')
- .$index.' IN('.implode(',', $ids).')';
+ return 'UPDATE '.$table.' SET '.substr($cases, 0, -2).$this->_compile_wh('qb_where');
}
// --------------------------------------------------------------------
/**
- * Limit string
+ * FROM tables
*
- * Generates a platform-specific LIMIT clause
+ * Groups tables in FROM clauses if needed, so there is no confusion
+ * about operator precedence.
*
- * @param string the sql query string
- * @param int the number of rows to limit the query to
- * @param int the offset value
* @return string
*/
- protected function _limit($sql, $limit, $offset)
+ protected function _from_tables()
{
- return $sql.' LIMIT '.$limit
- .($offset > 0 ? ' OFFSET '.$offset : '');
+ if ( ! empty($this->qb_join) && count($this->qb_from) > 1)
+ {
+ return '('.implode(', ', $this->qb_from).')';
+ }
+
+ return implode(', ', $this->qb_from);
}
// --------------------------------------------------------------------
@@ -523,13 +509,11 @@ class CI_DB_mysqli_driver extends CI_DB {
/**
* Close DB Connection
*
- * @param object
* @return void
*/
- protected function _close($conn_id)
+ protected function _close()
{
$this->conn_id->close();
- $this->conn_id = FALSE;
}
}
diff --git a/system/database/drivers/mysqli/mysqli_forge.php b/system/database/drivers/mysqli/mysqli_forge.php
index 503574dfc..f29ea5ade 100644
--- a/system/database/drivers/mysqli/mysqli_forge.php
+++ b/system/database/drivers/mysqli/mysqli_forge.php
@@ -1,4 +1,4 @@
-<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');
+<?php
/**
* CodeIgniter
*
@@ -24,6 +24,7 @@
* @since Version 1.0
* @filesource
*/
+defined('BASEPATH') OR exit('No direct script access allowed');
/**
* MySQLi Forge Class
@@ -34,152 +35,178 @@
*/
class CI_DB_mysqli_forge extends CI_DB_forge {
+ /**
+ * CREATE DATABASE statement
+ *
+ * @var string
+ */
protected $_create_database = 'CREATE DATABASE %s CHARACTER SET %s COLLATE %s';
/**
- * Process Fields
+ * CREATE TABLE keys flag
*
- * @param mixed the fields
- * @return string
+ * Whether table keys are created from within the
+ * CREATE TABLE statement.
+ *
+ * @var bool
*/
- protected function _process_fields($fields)
- {
- $current_field_count = 0;
- $sql = '';
-
- foreach ($fields as $field => $attributes)
- {
- // Numeric field names aren't allowed in databases, so if the key is
- // numeric, we know it was assigned by PHP and the developer manually
- // entered the field information, so we'll simply add it to the list
- if (is_numeric($field))
- {
- $sql .= "\n\t".$attributes;
- }
- else
- {
- $attributes = array_change_key_case($attributes, CASE_UPPER);
-
- $sql .= "\n\t".$this->db->protect_identifiers($field)
- .( ! empty($attributes['NAME']) ? ' '.$this->db->protect_identifiers($attributes['NAME']).' ' : '')
- ;
+ protected $_create_table_keys = TRUE;
- if ( ! empty($attributes['TYPE']))
- {
- $sql .= ' '.$attributes['TYPE'];
+ /**
+ * UNSIGNED support
+ *
+ * @var array
+ */
+ protected $_unsigned = array(
+ 'TINYINT',
+ 'SMALLINT',
+ 'MEDIUMINT',
+ 'INT',
+ 'INTEGER',
+ 'BIGINT',
+ 'REAL',
+ 'DOUBLE',
+ 'DOUBLE PRECISION',
+ 'FLOAT',
+ 'DECIMAL',
+ 'NUMERIC'
+ );
- if ( ! empty($attributes['CONSTRAINT']))
- {
- switch (strtolower($attributes['TYPE']))
- {
- case 'decimal':
- case 'float':
- case 'numeric':
- $sql .= '('.implode(',', $attributes['CONSTRAINT']).')';
- break;
- case 'enum':
- case 'set':
- $sql .= '("'.implode('","', $attributes['CONSTRAINT']).'")';
- break;
- default:
- $sql .= '('.$attributes['CONSTRAINT'].')';
- }
- }
- }
+ /**
+ * NULL value representation in CREATE/ALTER TABLE statements
+ *
+ * @var string
+ */
+ protected $_null = 'NULL';
- $sql .= (( ! empty($attributes['UNSIGNED']) && $attributes['UNSIGNED'] === TRUE) ? ' UNSIGNED' : '')
- .(isset($attributes['DEFAULT']) ? " DEFAULT '".$attributes['DEFAULT']."'" : '')
- .(( ! empty($attributes['NULL']) && $attributes['NULL'] === TRUE) ? ' NULL' : ' NOT NULL')
- .(( ! empty($attributes['AUTO_INCREMENT']) && $attributes['AUTO_INCREMENT'] === TRUE) ? ' AUTO_INCREMENT' : '');
- }
+ // --------------------------------------------------------------------
- // don't add a comma on the end of the last field
- if (++$current_field_count < count($fields))
- {
- $sql .= ',';
- }
- }
+ /**
+ * Class constructor
+ *
+ * @param object &$db Database object
+ * @return void
+ */
+ public function __construct(&$db)
+ {
+ parent::__construct($db);
- return $sql;
+ $this->_create_table .= ' DEFAULT CHARSET '.$this->db->char_set.' COLLATE '.$this->db->dbcollat;
}
// --------------------------------------------------------------------
/**
- * Create Table
+ * ALTER TABLE
*
- * @param string the table name
- * @param mixed the fields
- * @param mixed primary key(s)
- * @param mixed key(s)
- * @param bool should 'IF NOT EXISTS' be added to the SQL
- * @return bool
+ * @param string $alter_type ALTER type
+ * @param string $table Table name
+ * @param mixed $field Column definition
+ * @return string|string[]
*/
- protected function _create_table($table, $fields, $primary_keys, $keys, $if_not_exists)
+ protected function _alter_table($alter_type, $table, $field)
{
- $sql = 'CREATE TABLE ';
-
- if ($if_not_exists === TRUE)
- {
- $sql .= 'IF NOT EXISTS ';
- }
-
- $sql .= $this->db->escape_identifiers($table).' ('.$this->_process_fields($fields);
-
- if (count($primary_keys) > 0)
+ if ($alter_type === 'DROP')
{
- $key_name = $this->db->protect_identifiers(implode('_', $primary_keys));
- $sql .= ",\n\tPRIMARY KEY ".$key_name.' ('.implode(', ', $this->db->protect_identifiers($primary_keys)).')';
+ return parent::_alter_table($alter_type, $table, $field);
}
- if (is_array($keys) && count($keys) > 0)
+ $sql = 'ALTER TABLE '.$this->db->escape_identifiers($table);
+ for ($i = 0, $c = count($field); $i < $c; $i++)
{
- foreach ($keys as $key)
+ if ($field[$i]['_literal'] !== FALSE)
{
- if (is_array($key))
+ $field[$i] = ($alter_type === 'ADD')
+ ? "\n\tADD ".$field[$i]['_literal']
+ : "\n\tMODIFY ".$field[$i]['_literal'];
+ }
+ else
+ {
+ if ($alter_type === 'ADD')
{
- $key_name = $this->db->protect_identifiers(implode('_', $key));
- $key = $this->db->protect_identifiers($key);
+ $field[$i]['_literal'] = "\n\tADD ";
}
else
{
- $key_name = $this->db->protect_identifiers($key);
- $key = array($key_name);
+ $field[$i]['_literal'] = empty($field[$i]['new_name']) ? "\n\tMODIFY " : "\n\tCHANGE ";
}
- $sql .= ",\n\tKEY ".$key_name.' ('.implode(', ', $key).')';
+ $field[$i] = $field[$i]['_literal'].$this->_process_column($field[$i]);
}
}
- return $sql."\n) DEFAULT CHARACTER SET ".$this->db->char_set.' COLLATE '.$this->db->dbcollat.';';
+ return array($sql.implode(',', $field));
}
// --------------------------------------------------------------------
/**
- * Alter table query
+ * Process column
*
- * Generates a platform-specific query so that a table can be altered
- * Called by add_column(), drop_column(), and column_alter(),
+ * @param array $field
+ * @return string
+ */
+ protected function _process_column($field)
+ {
+ $extra_clause = isset($field['after'])
+ ? ' AFTER '.$this->db->escape_identifiers($field['after']) : '';
+
+ if (empty($extra_clause) && isset($field['first']) && $field['first'] === TRUE)
+ {
+ $extra_clause = ' FIRST';
+ }
+
+ return $this->db->escape_identifiers($field['name'])
+ .(empty($field['new_name']) ? '' : ' '.$this->db->escape_identifiers($field['new_name']))
+ .' '.$field['type'].$field['length']
+ .$field['unsigned']
+ .$field['null']
+ .$field['default']
+ .$field['auto_increment']
+ .$field['unique']
+ .$extra_clause;
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Process indexes
*
- * @param string the ALTER type (ADD, DROP, CHANGE)
- * @param string the column name
- * @param array fields
- * @param string the field after which we should add the new field
+ * @param string $table (ignored)
* @return string
*/
- protected function _alter_table($alter_type, $table, $fields, $after_field = '')
+ protected function _process_indexes($table)
{
- $sql = 'ALTER TABLE '.$this->db->protect_identifiers($table).' '.$alter_type.' ';
+ $sql = '';
- // DROP has everything it needs now.
- if ($alter_type === 'DROP')
+ for ($i = 0, $c = count($this->keys); $i < $c; $i++)
{
- return $sql.$this->db->protect_identifiers($fields);
+ 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;
+ }
+
+ is_array($this->keys[$i]) OR $this->keys[$i] = array($this->keys[$i]);
+
+ $sql .= ",\n\tKEY ".$this->db->escape_identifiers(implode('_', $this->keys[$i]))
+ .' ('.implode(', ', $this->db->escape_identifiers($this->keys[$i])).')';
}
- return $sql.$this->_process_fields($fields)
- .($after_field != '' ? ' AFTER '.$this->db->protect_identifiers($after_field) : '');
+ $this->keys = array();
+
+ return $sql;
}
}
diff --git a/system/database/drivers/mysqli/mysqli_result.php b/system/database/drivers/mysqli/mysqli_result.php
index 9b4d494d4..ac0f1a8d1 100644
--- a/system/database/drivers/mysqli/mysqli_result.php
+++ b/system/database/drivers/mysqli/mysqli_result.php
@@ -1,4 +1,4 @@
-<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');
+<?php
/**
* CodeIgniter
*
@@ -24,6 +24,7 @@
* @since Version 1.0
* @filesource
*/
+defined('BASEPATH') OR exit('No direct script access allowed');
/**
* MySQLi Result Class
@@ -33,6 +34,7 @@
* @category Database
* @author EllisLab Dev Team
* @link http://codeigniter.com/user_guide/database/
+ * @since 1.3
*/
class CI_DB_mysqli_result extends CI_DB_result {
@@ -43,7 +45,9 @@ class CI_DB_mysqli_result extends CI_DB_result {
*/
public function num_rows()
{
- return $this->result_id->num_rows;
+ return is_int($this->num_rows)
+ ? $this->num_rows
+ : $this->num_rows = $this->result_id->num_rows;
}
// --------------------------------------------------------------------
@@ -98,7 +102,7 @@ class CI_DB_mysqli_result extends CI_DB_result {
$retval[$i]->type = $field_data[$i]->type;
$retval[$i]->max_length = $field_data[$i]->max_length;
$retval[$i]->primary_key = (int) ($field_data[$i]->flags & 2);
- $retval[$i]->default = '';
+ $retval[$i]->default = $field_data[$i]->def;
}
return $retval;
@@ -127,11 +131,12 @@ class CI_DB_mysqli_result extends CI_DB_result {
*
* Moves the internal pointer to the desired offset. We call
* this internally before fetching results to make sure the
- * result set starts at zero
+ * result set starts at zero.
*
+ * @param int $n
* @return bool
*/
- protected function _data_seek($n = 0)
+ public function data_seek($n = 0)
{
return $this->result_id->data_seek($n);
}
@@ -157,11 +162,12 @@ class CI_DB_mysqli_result extends CI_DB_result {
*
* Returns the result set as an object
*
+ * @param string $class_name
* @return object
*/
- protected function _fetch_object()
+ protected function _fetch_object($class_name = 'stdClass')
{
- return $this->result_id->fetch_object();
+ return $this->result_id->fetch_object($class_name);
}
}
diff --git a/system/database/drivers/mysqli/mysqli_utility.php b/system/database/drivers/mysqli/mysqli_utility.php
index 27d4ef817..345691e84 100644
--- a/system/database/drivers/mysqli/mysqli_utility.php
+++ b/system/database/drivers/mysqli/mysqli_utility.php
@@ -1,4 +1,4 @@
-<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');
+<?php
/**
* CodeIgniter
*
@@ -24,6 +24,7 @@
* @since Version 1.0
* @filesource
*/
+defined('BASEPATH') OR exit('No direct script access allowed');
/**
* MySQLi Utility Class
@@ -34,21 +35,155 @@
*/
class CI_DB_mysqli_utility extends CI_DB_utility {
+ /**
+ * List databases statement
+ *
+ * @var string
+ */
protected $_list_databases = 'SHOW DATABASES';
+
+ /**
+ * OPTIMIZE TABLE statement
+ *
+ * @var string
+ */
protected $_optimize_table = 'OPTIMIZE TABLE %s';
+
+ /**
+ * REPAIR TABLE statement
+ *
+ * @var string
+ */
protected $_repair_table = 'REPAIR TABLE %s';
+ // --------------------------------------------------------------------
+
/**
- * MySQLi Export
+ * Export
*
- * @param array Preferences
+ * @param array $params Preferences
* @return mixed
*/
protected function _backup($params = array())
{
- // Currently unsupported
- return $this->db->display_error('db_unsuported_feature');
+ if (count($params) === 0)
+ {
+ return FALSE;
+ }
+
+ // Extract the prefs for simplicity
+ extract($params);
+
+ // Build the output
+ $output = '';
+ foreach ( (array) $tables as $table)
+ {
+ // Is the table in the "ignore" list?
+ if (in_array($table, (array) $ignore, TRUE))
+ {
+ continue;
+ }
+
+ // Get the table schema
+ $query = $this->db->query('SHOW CREATE TABLE '.$this->db->escape_identifiers($this->db->database.'.'.$table));
+
+ // No result means the table name was invalid
+ if ($query === FALSE)
+ {
+ continue;
+ }
+
+ // Write out the table schema
+ $output .= '#'.$newline.'# TABLE STRUCTURE FOR: '.$table.$newline.'#'.$newline.$newline;
+
+ if ($add_drop === TRUE)
+ {
+ $output .= 'DROP TABLE IF EXISTS '.$this->db->protect_identifiers($table).';'.$newline.$newline;
+ }
+
+ $i = 0;
+ $result = $query->result_array();
+ foreach ($result[0] as $val)
+ {
+ if ($i++ % 2)
+ {
+ $output .= $val.';'.$newline.$newline;
+ }
+ }
+
+ // If inserts are not needed we're done...
+ if ($add_insert === FALSE)
+ {
+ continue;
+ }
+
+ // Grab all the data from the current table
+ $query = $this->db->query('SELECT * FROM '.$this->db->protect_identifiers($table));
+
+ if ($query->num_rows() === 0)
+ {
+ continue;
+ }
+
+ // Fetch the field names and determine if the field is an
+ // integer type. We use this info to decide whether to
+ // surround the data with quotes or not
+
+ $i = 0;
+ $field_str = '';
+ $is_int = array();
+ while ($field = $query->result_id->fetch_field())
+ {
+ // Most versions of MySQL store timestamp as a string
+ $is_int[$i] = in_array(strtolower($field->type),
+ array('tinyint', 'smallint', 'mediumint', 'int', 'bigint'), //, 'timestamp'),
+ TRUE);
+
+ // Create a string of field names
+ $field_str .= $this->db->escape_identifiers($field->name).', ';
+ $i++;
+ }
+
+ // Trim off the end comma
+ $field_str = preg_replace('/, $/' , '', $field_str);
+
+ // Build the insert string
+ foreach ($query->result_array() as $row)
+ {
+ $val_str = '';
+
+ $i = 0;
+ foreach ($row as $v)
+ {
+ // Is the value NULL?
+ if ($v === NULL)
+ {
+ $val_str .= 'NULL';
+ }
+ else
+ {
+ // Escape the data if it's not an integer
+ $val_str .= ($is_int[$i] === FALSE) ? $this->db->escape($v) : $v;
+ }
+
+ // Append a comma
+ $val_str .= ', ';
+ $i++;
+ }
+
+ // Remove the comma at the end of the string
+ $val_str = preg_replace('/, $/' , '', $val_str);
+
+ // Build the INSERT string
+ $output .= 'INSERT INTO '.$this->db->protect_identifiers($table).' ('.$field_str.') VALUES ('.$val_str.');'.$newline;
+ }
+
+ $output .= $newline.$newline;
+ }
+
+ return $output;
}
+
}
/* End of file mysqli_utility.php */
diff --git a/system/database/drivers/oci8/oci8_driver.php b/system/database/drivers/oci8/oci8_driver.php
index 1b66178c6..706211a01 100644
--- a/system/database/drivers/oci8/oci8_driver.php
+++ b/system/database/drivers/oci8/oci8_driver.php
@@ -1,4 +1,4 @@
-<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');
+<?php
/**
* CodeIgniter
*
@@ -24,12 +24,13 @@
* @since Version 1.0
* @filesource
*/
+defined('BASEPATH') OR exit('No direct script access allowed');
/**
* oci8 Database Adapter Class
*
* Note: _DB is an extender class that the app controller
- * creates dynamically based on whether the active record
+ * creates dynamically based on whether the query builder
* class is being used or not.
*
* @package CodeIgniter
@@ -49,34 +50,80 @@
*/
class CI_DB_oci8_driver extends CI_DB {
+ /**
+ * Database driver
+ *
+ * @var string
+ */
public $dbdriver = 'oci8';
- // The character used for excaping
- protected $_escape_char = '"';
-
- // clause and character used for LIKE escape sequences
- protected $_like_escape_str = " ESCAPE '%s' ";
- protected $_like_escape_chr = '!';
+ /**
+ * Statement ID
+ *
+ * @var resource
+ */
+ public $stmt_id;
/**
- * The syntax to count rows is slightly different across different
- * database engines, so this string appears in each driver and is
- * used for the count_all() and count_all_results() functions.
+ * Cursor ID
+ *
+ * @var resource
*/
- protected $_count_string = 'SELECT COUNT(1) AS ';
- protected $_random_keyword = ' ASC'; // not currently supported
+ public $curs_id;
- // Set "auto commit" by default
+ /**
+ * Commit mode flag
+ *
+ * @var int
+ */
public $commit_mode = OCI_COMMIT_ON_SUCCESS;
- // need to track statement id and cursor id
- public $stmt_id;
- public $curs_id;
-
- // if we use a limit, we will add a field that will
- // throw off num_fields later
+ /**
+ * Limit used flag
+ *
+ * If we use LIMIT, we'll add a field that will
+ * throw off num_fields later.
+ *
+ * @var bool
+ */
public $limit_used;
+ // --------------------------------------------------------------------
+
+ /**
+ * List of reserved identifiers
+ *
+ * Identifiers that must NOT be escaped.
+ *
+ * @var string[]
+ */
+ protected $_reserved_identifiers = array('*', 'rownum');
+
+ /**
+ * ORDER BY random keyword
+ *
+ * @var array
+ */
+ protected $_random_keyword = array('ASC', 'ASC'); // not currently supported
+
+ /**
+ * COUNT string
+ *
+ * @used-by CI_DB_driver::count_all()
+ * @used-by CI_DB_query_builder::count_all_results()
+ *
+ * @var string
+ */
+ protected $_count_string = 'SELECT COUNT(1) AS ';
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Class constructor
+ *
+ * @param array $params
+ * @return void
+ */
public function __construct($params)
{
parent::__construct($params);
@@ -156,6 +203,8 @@ class CI_DB_oci8_driver extends CI_DB {
$this->dsn = '';
}
+ // --------------------------------------------------------------------
+
/**
* Non-persistent database connection
*
@@ -177,9 +226,9 @@ class CI_DB_oci8_driver extends CI_DB {
*/
public function db_pconnect()
{
- return ( ! empty($this->char_set))
- ? @oci_pconnect($this->username, $this->password, $this->dsn, $this->char_set)
- : @oci_pconnect($this->username, $this->password, $this->dsn);
+ return empty($this->char_set)
+ ? @oci_pconnect($this->username, $this->password, $this->dsn)
+ : @oci_pconnect($this->username, $this->password, $this->dsn, $this->char_set);
}
// --------------------------------------------------------------------
@@ -191,9 +240,21 @@ class CI_DB_oci8_driver extends CI_DB {
*/
public function version()
{
- return isset($this->data_cache['version'])
- ? $this->data_cache['version']
- : $this->data_cache['version'] = oci_server_version($this->conn_id);
+ if (isset($this->data_cache['version']))
+ {
+ return $this->data_cache['version'];
+ }
+ elseif ( ! $this->conn_id)
+ {
+ $this->initialize();
+ }
+
+ if ( ! $this->conn_id OR ($version = oci_server_version($this->conn_id)) === FALSE)
+ {
+ return FALSE;
+ }
+
+ return $this->data_cache['version'] = $version;
}
// --------------------------------------------------------------------
@@ -201,7 +262,7 @@ class CI_DB_oci8_driver extends CI_DB {
/**
* Execute the query
*
- * @param string an SQL query
+ * @param string $sql an SQL query
* @return resource
*/
protected function _execute($sql)
@@ -215,10 +276,12 @@ class CI_DB_oci8_driver extends CI_DB {
return @oci_execute($this->stmt_id, $this->commit_mode);
}
+ // --------------------------------------------------------------------
+
/**
* Generate a statement ID
*
- * @param string an SQL query
+ * @param string $sql an SQL query
* @return void
*/
protected function _set_stmt_id($sql)
@@ -234,7 +297,7 @@ class CI_DB_oci8_driver extends CI_DB {
/**
* Get cursor. Returns a cursor from the database
*
- * @return cursor id
+ * @return resource
*/
public function get_cursor()
{
@@ -262,7 +325,7 @@ class CI_DB_oci8_driver extends CI_DB {
*/
public function stored_procedure($package, $procedure, $params)
{
- if ($package == '' OR $procedure == '' OR ! is_array($params))
+ if ($package === '' OR $procedure === '' OR ! is_array($params))
{
if ($this->db_debug)
{
@@ -298,6 +361,7 @@ class CI_DB_oci8_driver extends CI_DB {
/**
* Bind parameters
*
+ * @param array $params
* @return void
*/
protected function _bind_params($params)
@@ -326,6 +390,7 @@ class CI_DB_oci8_driver extends CI_DB {
/**
* Begin Transaction
*
+ * @param bool $test_mode
* @return bool
*/
public function trans_begin($test_mode = FALSE)
@@ -398,8 +463,8 @@ class CI_DB_oci8_driver extends CI_DB {
/**
* Escape String
*
- * @param string
- * @param bool whether or not the string will be used in a LIKE condition
+ * @param string $str
+ * @param bool $like Whether or not the string will be used in a LIKE condition
* @return string
*/
public function escape_str($str, $like = FALSE)
@@ -455,49 +520,21 @@ class CI_DB_oci8_driver extends CI_DB {
// --------------------------------------------------------------------
/**
- * "Count All" query
- *
- * Generates a platform-specific query string that counts all records in
- * the specified database
- *
- * @param string
- * @return int
- */
- public function count_all($table = '')
- {
- if ($table == '')
- {
- return 0;
- }
-
- $query = $this->query($this->_count_string.$this->protect_identifiers('numrows').' FROM '.$this->protect_identifiers($table, TRUE, NULL, FALSE));
- if ($query == FALSE)
- {
- return 0;
- }
-
- $row = $query->row();
- $this->_reset_select();
- return (int) $row->numrows;
- }
-
- // --------------------------------------------------------------------
-
- /**
* Show table query
*
* Generates a platform-specific query string so that the table names can be fetched
*
- * @param bool
+ * @param bool $prefix_limit
* @return string
*/
protected function _list_tables($prefix_limit = FALSE)
{
- $sql = 'SELECT TABLE_NAME FROM ALL_TABLES';
+ $sql = 'SELECT "TABLE_NAME" FROM "ALL_TABLES"';
- if ($prefix_limit !== FALSE && $this->dbprefix != '')
+ if ($prefix_limit !== FALSE && $this->dbprefix !== '')
{
- return $sql." WHERE TABLE_NAME LIKE '".$this->escape_like_str($this->dbprefix)."%' ".sprintf($this->_like_escape_str, $this->_like_escape_chr);
+ return $sql.' WHERE "TABLE_NAME" LIKE \''.$this->escape_like_str($this->dbprefix)."%' "
+ .sprintf($this->_like_escape_str, $this->_like_escape_chr);
}
return $sql;
@@ -510,27 +547,83 @@ class CI_DB_oci8_driver extends CI_DB {
*
* Generates a platform-specific query string so that the column names can be fetched
*
- * @param string the table name
+ * @param string $table
* @return string
*/
protected function _list_columns($table = '')
{
- return 'SELECT COLUMN_NAME FROM all_tab_columns WHERE table_name = \''.$table.'\'';
+ if (strpos($table, '.') !== FALSE)
+ {
+ sscanf($table, '%[^.].%s', $owner, $table);
+ }
+ else
+ {
+ $owner = $this->username;
+ }
+
+ return 'SELECT COLUMN_NAME FROM ALL_TAB_COLUMNS
+ WHERE UPPER(OWNER) = '.$this->escape(strtoupper($owner)).'
+ AND UPPER(TABLE_NAME) = '.$this->escape(strtoupper($table));
}
// --------------------------------------------------------------------
/**
- * Field data query
- *
- * Generates a platform-specific query so that the column data can be retrieved
+ * Returns an object with field data
*
- * @param string the table name
- * @return string
+ * @param string $table
+ * @return array
*/
- protected function _field_data($table)
+ public function field_data($table = '')
{
- return 'SELECT * FROM '.$table.' WHERE rownum = 1';
+ if ($table === '')
+ {
+ return ($this->db_debug) ? $this->display_error('db_field_param_missing') : FALSE;
+ }
+ elseif (strpos($table, '.') !== FALSE)
+ {
+ sscanf($table, '%[^.].%s', $owner, $table);
+ }
+ else
+ {
+ $owner = $this->username;
+ }
+
+ $sql = 'SELECT COLUMN_NAME, DATA_TYPE, CHAR_LENGTH, DATA_PRECISION, DATA_LENGTH, DATA_DEFAULT, NULLABLE
+ FROM ALL_TAB_COLUMNS
+ WHERE UPPER(OWNER) = '.$this->escape(strtoupper($owner)).'
+ AND UPPER(TABLE_NAME) = '.$this->escape(strtoupper($table));
+
+ if (($query = $this->query($sql)) === FALSE)
+ {
+ return FALSE;
+ }
+ $query = $query->result_object();
+
+ $retval = array();
+ for ($i = 0, $c = count($query); $i < $c; $i++)
+ {
+ $retval[$i] = new stdClass();
+ $retval[$i]->name = $query[$i]->COLUMN_NAME;
+ $retval[$i]->type = $query[$i]->DATA_TYPE;
+
+ $length = ($query[$i]->CHAR_LENGTH > 0)
+ ? $query[$i]->CHAR_LENGTH : $query[$i]->DATA_PRECISION;
+ if ($length === NULL)
+ {
+ $length = $query[$i]->DATA_LENGTH;
+ }
+ $retval[$i]->max_length = $length;
+
+ $default = $query[$i]->DATA_DEFAULT;
+ if ($default === NULL && $query[$i]->NULLABLE === 'N')
+ {
+ $default = '';
+ }
+ $retval[$i]->default = $query[$i]->COLUMN_DEFAULT;
+ }
+
+ return $retval;
}
// --------------------------------------------------------------------
@@ -567,29 +660,13 @@ class CI_DB_oci8_driver extends CI_DB {
// --------------------------------------------------------------------
/**
- * From Tables
- *
- * This function implicitly groups FROM tables so there is no confusion
- * about operator precedence in harmony with SQL standards
- *
- * @param array
- * @return string
- */
- protected function _from_tables($tables)
- {
- return is_array($tables) ? implode(', ', $tables) : $tables;
- }
-
- // --------------------------------------------------------------------
-
- /**
- * Insert_batch statement
+ * Insert batch statement
*
* Generates a platform-specific insert string from the supplied data
*
- * @param string the table name
- * @param array the insert keys
- * @param array the insert values
+ * @param string $table Table name
+ * @param array $keys INSERT keys
+ * @param array $values INSERT values
* @return string
*/
protected function _insert_batch($table, $keys, $values)
@@ -612,10 +689,10 @@ class CI_DB_oci8_driver extends CI_DB {
*
* Generates a platform-specific truncate string from the supplied data
*
- * If the database does not support the truncate() command,
+ * If the database does not support the TRUNCATE statement,
* then this method maps to 'DELETE FROM table'
*
- * @param string the table name
+ * @param string $table
* @return string
*/
protected function _truncate($table)
@@ -630,40 +707,35 @@ class CI_DB_oci8_driver extends CI_DB {
*
* Generates a platform-specific delete string from the supplied data
*
- * @param string the table name
- * @param array the where clause
- * @param array the like clause
- * @param string the limit clause
+ * @param string $table
* @return string
*/
- protected function _delete($table, $where = array(), $like = array(), $limit = FALSE)
+ protected function _delete($table)
{
- $conditions = array();
-
- empty($where) OR $conditions[] = implode(' ', $where);
- empty($like) OR $conditions[] = implode(' ', $like);
- empty($limit) OR $conditions[] = 'rownum <= '.$limit;
+ if ($this->qb_limit)
+ {
+ $this->where('rownum <= ',$this->qb_limit, FALSE);
+ $this->qb_limit = FALSE;
+ }
- return 'DELETE FROM '.$table.(count($conditions) > 0 ? ' WHERE '.implode(' AND ', $conditions) : '');
+ return parent::_delete($table);
}
// --------------------------------------------------------------------
/**
- * Limit string
+ * LIMIT
*
* Generates a platform-specific LIMIT clause
*
- * @param string the sql query string
- * @param int the number of rows to limit the query to
- * @param int the offset value
+ * @param string $sql SQL Query
* @return string
*/
- protected function _limit($sql, $limit, $offset)
+ protected function _limit($sql)
{
$this->limit_used = TRUE;
- return 'SELECT * FROM (SELECT inner_query.*, rownum rnum FROM ('.$sql.') inner_query WHERE rownum < '.($offset + $limit).')'
- .($offset != 0 ? ' WHERE rnum >= '.$offset : '');
+ return 'SELECT * FROM (SELECT inner_query.*, rownum rnum FROM ('.$sql.') inner_query WHERE rownum < '.($this->qb_offset + $this->qb_limit + 1).')'
+ .($this->qb_offset ? ' WHERE rnum >= '.($this->qb_offset + 1): '');
}
// --------------------------------------------------------------------
@@ -671,12 +743,11 @@ class CI_DB_oci8_driver extends CI_DB {
/**
* Close DB Connection
*
- * @param resource
* @return void
*/
- protected function _close($conn_id)
+ protected function _close()
{
- @oci_close($conn_id);
+ @oci_close($this->conn_id);
}
}
diff --git a/system/database/drivers/oci8/oci8_forge.php b/system/database/drivers/oci8/oci8_forge.php
index bd265b6e0..a0efa95ea 100644
--- a/system/database/drivers/oci8/oci8_forge.php
+++ b/system/database/drivers/oci8/oci8_forge.php
@@ -1,4 +1,4 @@
-<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');
+<?php
/**
* CodeIgniter
*
@@ -24,6 +24,7 @@
* @since Version 1.0
* @filesource
*/
+defined('BASEPATH') OR exit('No direct script access allowed');
/**
* Oracle Forge Class
@@ -34,117 +35,96 @@
*/
class CI_DB_oci8_forge extends CI_DB_forge {
+ /**
+ * CREATE DATABASE statement
+ *
+ * @var string
+ */
protected $_create_database = FALSE;
+
+ /**
+ * DROP DATABASE statement
+ *
+ * @var string
+ */
protected $_drop_database = FALSE;
- protected $_drop_table = 'DROP TABLE %s';
/**
- * Create Table
+ * DROP TABLE IF statement
*
- * @param string the table name
- * @param array the fields
- * @param mixed primary key(s)
- * @param mixed key(s)
- * @param bool should 'IF NOT EXISTS' be added to the SQL
- * @return string
+ * @var string
*/
- protected function _create_table($table, $fields, $primary_keys, $keys, $if_not_exists)
- {
- $sql = 'CREATE TABLE ';
+ protected $_drop_table_if = FALSE;
- if ($if_not_exists === TRUE)
- {
- $sql .= 'IF NOT EXISTS ';
- }
+ /**
+ * UNSIGNED support
+ *
+ * @var bool|array
+ */
+ protected $_unsigned = FALSE;
- $sql .= $this->db->escape_identifiers($table).' (';
- $current_field_count = 0;
+ // --------------------------------------------------------------------
- foreach ($fields as $field => $attributes)
+ /**
+ * ALTER TABLE
+ *
+ * @param string $alter_type ALTER type
+ * @param string $table Table name
+ * @param mixed $field Column definition
+ * @return string|string[]
+ */
+ protected function _alter_table($alter_type, $table, $field)
+ {
+ if ($alter_type === 'DROP')
{
- // Numeric field names aren't allowed in databases, so if the key is
- // numeric, we know it was assigned by PHP and the developer manually
- // entered the field information, so we'll simply add it to the list
- if (is_numeric($field))
- {
- $sql .= "\n\t".$attributes;
- }
- else
- {
- $attributes = array_change_key_case($attributes, CASE_UPPER);
-
- $sql .= "\n\t".$this->db->protect_identifiers($field).' '.$attributes['TYPE']
- .((isset($attributes['UNSINGED']) && $attributes['UNSIGNED'] === TRUE) ? ' UNSIGNED' : '')
- .(isset($attributes['DEFAULT']) ? " DEFAULT '".$attributes['DEFAULT']."'" : '')
- .((isset($attributes['NULL']) && $attributes['NULL'] === TRUE) ? '' : ' NOT NULL')
- .(isset($attributes['CONSTRAINT']) ? ' CONSTRAINT '.$attributes['CONSTRAINT'] : '');
- }
-
- // don't add a comma on the end of the last field
- if (++$current_field_count < count($fields))
- {
- $sql .= ',';
- }
+ return parent::_alter_table($alter_type, $table, $field);
}
-
- if (count($primary_keys) > 0)
+ elseif ($alter_type === 'CHANGE')
{
- $primary_keys = $this->db->protect_identifiers($primary_keys);
- $sql .= ",\n\tCONSTRAINT ".$table.' PRIMARY KEY ('.implode(', ', $primary_keys).')';
+ $alter_type = 'MODIFY';
}
- if (is_array($keys) && count($keys) > 0)
+ $sql = 'ALTER TABLE '.$this->db->escape_identifiers($table);
+ $sqls = array();
+ for ($i = 0, $c = count($field); $i < $c; $i++)
{
- foreach ($keys as $key)
+ if ($field[$i]['_literal'] !== FALSE)
{
- if (is_array($key))
- {
- $key = $this->db->protect_identifiers($key);
- }
- else
+ $field[$i] = "\n\t".$field[$i]['_literal'];
+ }
+ else
+ {
+ $field[$i]['_literal'] = "\n\t".$this->_process_column($field[$i]);
+ if ($alter_type === 'MODIFY' && ! empty($field[$i]['new_name']))
{
- $key = array($this->db->protect_identifiers($key));
+ $sqls[] = $sql.' RENAME COLUMN '.$this->db->escape_identifiers($field[$i]['name'])
+ .' '.$this->db->escape_identifiers($field[$i]['new_name']);
}
-
- $sql .= ",\n\tUNIQUE COLUMNS (".implode(', ', $key).')';
}
}
- return $sql."\n)";
+ $sql .= ' '.$alter_type.' ';
+ $sql .= (count($field) === 1)
+ ? $field[0]
+ : '('.implode(',', $field).')';
+
+ // RENAME COLUMN must be executed after MODIFY
+ array_unshift($sqls, $sql);
+ return $sql;
}
// --------------------------------------------------------------------
/**
- * Alter table query
+ * Field attribute AUTO_INCREMENT
*
- * Generates a platform-specific query so that a table can be altered
- * Called by add_column(), drop_column(), and column_alter(),
- *
- * @param string the ALTER type (ADD, DROP, CHANGE)
- * @param string the column name
- * @param string the table name
- * @param string the column definition
- * @param string the default value
- * @param bool should 'NOT NULL' be added
- * @param string the field after which we should add the new field
- * @return string
+ * @param array &$attributes
+ * @param array &$field
+ * @return void
*/
- protected function _alter_table($alter_type, $table, $column_name, $column_definition = '', $default_value = '', $null = '', $after_field = '')
+ protected function _attr_auto_increment(&$attributes, &$field)
{
- $sql = 'ALTER TABLE '.$this->db->protect_identifiers($table).' '.$alter_type.' '.$this->db->protect_identifiers($column_name);
-
- // DROP has everything it needs now.
- if ($alter_type === 'DROP')
- {
- return $sql;
- }
-
- return $sql.' '.$column_definition
- .($default_value != '' ? ' DEFAULT "'.$default_value.'"' : '')
- .($null === NULL ? ' NULL' : ' NOT NULL')
- .($after_field != '' ? ' AFTER '.$this->db->protect_identifiers($after_field) : '');
-
+ // Not supported - sequences and triggers must be used instead
}
}
diff --git a/system/database/drivers/oci8/oci8_result.php b/system/database/drivers/oci8/oci8_result.php
index 7b05e0a43..84d46f82a 100644
--- a/system/database/drivers/oci8/oci8_result.php
+++ b/system/database/drivers/oci8/oci8_result.php
@@ -1,4 +1,4 @@
-<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');
+<?php
/**
* CodeIgniter
*
@@ -24,6 +24,7 @@
* @since Version 1.0
* @filesource
*/
+defined('BASEPATH') OR exit('No direct script access allowed');
/**
* oci8 Result Class
@@ -33,22 +34,50 @@
* @category Database
* @author EllisLab Dev Team
* @link http://codeigniter.com/user_guide/database/
+ * @since 1.4.1
*/
class CI_DB_oci8_result extends CI_DB_result {
+ /**
+ * Statement ID
+ *
+ * @var resource
+ */
public $stmt_id;
+
+ /**
+ * Cursor ID
+ *
+ * @var resource
+ */
public $curs_id;
+
+ /**
+ * Limit used flag
+ *
+ * @var bool
+ */
public $limit_used;
- public $commit_mode;
- /* Overwriting the parent here, so we have a way to know if it's
- * already called or not:
+ /**
+ * Commit mode flag
+ *
+ * @var int
*/
- public $num_rows;
+ public $commit_mode;
+
+ // --------------------------------------------------------------------
+ /**
+ * Class constructor
+ *
+ * @param object &$driver_object
+ * @return void
+ */
public function __construct(&$driver_object)
{
parent::__construct($driver_object);
+
$this->stmt_id = $driver_object->stmt_id;
$this->curs_id = $driver_object->curs_id;
$this->limit_used = $driver_object->limit_used;
@@ -56,33 +85,6 @@ class CI_DB_oci8_result extends CI_DB_result {
$driver_object->stmt_id = FALSE;
}
- /**
- * Number of rows in the result set.
- *
- * Oracle doesn't have a graceful way to return the number of rows
- * so we have to use what amounts to a hack.
- *
- * @return int
- */
- public function num_rows()
- {
- if ( ! is_int($this->num_rows))
- {
- if (count($this->result_array) > 0)
- {
- return $this->num_rows = count($this->result_array);
- }
- elseif (count($this->result_object) > 0)
- {
- return $this->num_rows = count($this->result_object);
- }
-
- return $this->num_rows = count($this->result_array());
- }
-
- return $this->num_rows;
- }
-
// --------------------------------------------------------------------
/**
@@ -181,7 +183,7 @@ class CI_DB_oci8_result extends CI_DB_result {
protected function _fetch_assoc()
{
$id = ($this->curs_id) ? $this->curs_id : $this->stmt_id;
- return oci_fetch_assoc($id);
+ return @oci_fetch_assoc($id);
}
// --------------------------------------------------------------------
@@ -191,507 +193,27 @@ class CI_DB_oci8_result extends CI_DB_result {
*
* Returns the result set as an object
*
+ * @param string $class_name
* @return object
*/
- protected function _fetch_object()
- {
- $id = ($this->curs_id) ? $this->curs_id : $this->stmt_id;
- return oci_fetch_object($id);
- }
-
- // --------------------------------------------------------------------
-
- /**
- * Query result. Array version.
- *
- * @return array
- */
- public function result_array()
- {
- if (count($this->result_array) > 0)
- {
- return $this->result_array;
- }
- elseif (count($this->result_object) > 0)
- {
- for ($i = 0, $c = count($this->result_object); $i < $c; $i++)
- {
- $this->result_array[$i] = (array) $this->result_object[$i];
- }
-
- return $this->result_array;
- }
- elseif (is_array($this->row_data))
- {
- if (count($this->row_data) === 0)
- {
- return $this->result_array;
- }
- else
- {
- $row_index = count($this->row_data);
- }
- }
- else
- {
- $row_index = 0;
- $this->row_data = array();
- }
-
- $row = NULL;
- while ($row = $this->_fetch_assoc())
- {
- $this->row_data[$row_index++] = $row;
- }
-
- return $this->result_array = $this->row_data;
- }
-
- // --------------------------------------------------------------------
-
- /**
- * Query result. "object" version.
- *
- * @return array
- */
- public function result_object()
- {
- if (count($this->result_object) > 0)
- {
- return $this->result_object;
- }
- elseif (count($this->result_array) > 0)
- {
- for ($i = 0, $c = count($this->result_array); $i < $c; $i++)
- {
- $this->result_object[] = (object) $this->result_array[$i];
- }
-
- return $this->result_object;
- }
- elseif (is_array($this->row_data))
- {
- if (count($this->row_data) === 0)
- {
- return $this->result_object;
- }
- else
- {
- $row_index = count($this->row_data);
- for ($i = 0; $i < $row_index; $i++)
- {
- $this->result_object[$i] = (object) $this->row_data[$i];
- }
- }
- }
- else
- {
- $row_index = 0;
- $this->row_data = array();
- }
-
- $row = NULL;
- while ($row = $this->_fetch_object())
- {
- $this->row_data[$row_index] = (array) $row;
- $this->result_object[$row_index++] = $row;
- }
-
- return $this->result_object;
- }
-
- // --------------------------------------------------------------------
-
- /**
- * Query result. Custom object version.
- *
- * @param string class name used to instantiate rows to
- * @return array
- */
- public function custom_result_object($class_name)
+ protected function _fetch_object($class_name = 'stdClass')
{
- if (isset($this->custom_result_object[$class_name]))
- {
- return $this->custom_result_object[$class_name];
- }
-
- if ( ! class_exists($class_name) OR $this->result_id === FALSE OR $this->num_rows() === 0)
- {
- return array();
- }
-
- /* Even if we didn't have result_array or result_object
- * set prior to custom_result_object() being called,
- * num_rows() has already done so.
- * Pass by reference, as we don't know how
- * large it might be and we don't want 1000 row
- * sets being copied.
- */
- if (count($this->result_array) > 0)
- {
- $data = &$this->result_array;
- }
- elseif (count($this->result_object) > 0)
- {
- $data = &$this->result_object;
- }
+ $row = ($this->curs_id)
+ ? oci_fetch_object($this->curs_id)
+ : oci_fetch_object($this->stmt_id);
- $this->custom_result_object[$class_name] = array();
- for ($i = 0, $c = count($data); $i < $c; $i++)
- {
- $this->custom_result_object[$class_name][$i] = new $class_name();
- foreach ($data[$i] as $key => $value)
- {
- $this->custom_result_object[$class_name][$i]->$key = $value;
- }
- }
-
- return $this->custom_result_object[$class_name];
- }
-
- // --------------------------------------------------------------------
-
- /* Single row result.
- *
- * Acts as a wrapper for row_object(), row_array()
- * and custom_row_object(). Also used by first_row(), next_row()
- * and previous_row().
- *
- * @param int row index
- * @param string ('object', 'array' or a custom class name)
- * @return mixed whatever was passed to the second parameter
- */
- public function row($n = 0, $type = 'object')
- {
- if ($type === 'object')
- {
- return $this->row_object($n);
- }
- elseif ($type === 'array')
- {
- return $this->row_array($n);
- }
-
- return $this->custom_row_object($n, $type);
- }
-
- // --------------------------------------------------------------------
-
- /* Single row result. Array version.
- *
- * @param int row index
- * @return array
- */
- public function row_array($n = 0)
- {
- // Make sure $n is not a string
- if ( ! is_int($n))
- {
- $n = (int) $n;
- }
-
- /* If row_data is initialized, it means that we've already tried
- * (at least) to fetch some data, so ... check if we already have
- * this row.
- */
- if (is_array($this->row_data))
- {
- /* If we already have row_data[$n] - return it.
- *
- * If we enter the elseif, there's a number of reasons to
- * return an empty array:
- *
- * - count($this->row_data) === 0 means there are no results
- * - num_rows being set, result_array and/or result_object
- * having count() > 0 means that we've already fetched all
- * data and $n is greater than our highest row index available
- * - $n < $this->current_row means that if such row existed,
- * we would've already returned it, therefore $n is an
- * invalid index
- */
- if (isset($this->row_data[$n])) // We already have this row
- {
- $this->current_row = $n;
- return $this->row_data[$n];
- }
- elseif (count($this->row_data) === 0 OR is_int($this->num_rows)
- OR count($this->result_array) > 0 OR count($this->result_object) > 0
- OR $n < $this->current_row)
- {
- // No such row exists
- return array();
- }
-
- // Get the next row index that would actually need to be fetched
- $current_row = ($this->current_row < count($this->row_data)) ? count($this->row_data) : $this->current_row + 1;
- }
- else
- {
- $current_row = $this->current_row = 0;
- $this->row_data = array();
- }
-
- /* Fetch more data, if available
- *
- * NOTE: Operator precedence is important here, if you change
- * 'AND' with '&&' - it WILL BREAK the results, as
- * $row will be assigned the scalar value of both
- * expressions!
- */
- while ($row = $this->_fetch_assoc() AND $current_row <= $n)
- {
- $this->row_data[$current_row++] = $row;
- }
-
- // This would mean that there's no (more) data to fetch
- if ( ! is_array($this->row_data) OR ! isset($this->row_data[$n]))
- {
- // Cache what we already have
- if (is_array($this->row_data))
- {
- $this->num_rows = count($this->row_data);
- /* Usually, row_data could have less elements than result_array,
- * but at this point - they should be exactly the same.
- */
- $this->result_array = $this->row_data;
- }
- else
- {
- $this->num_rows = 0;
- }
-
- return array();
- }
-
- $this->current_row = $n;
- return $this->row_data[$n];
- }
-
- // --------------------------------------------------------------------
-
- /* Single row result. Object version.
- *
- * @param int row index
- * @return mixed object if row found; empty array if not
- */
- public function row_object($n = 0)
- {
- // Make sure $n is not a string
- if ( ! is_int($n))
- {
- $n = (int) $n;
- }
- /* Logic here is exactly the same as in row_array,
- * except we have to cast row_data[$n] to an object.
- *
- * If we already have result_object though - we can
- * directly return from it.
- */
- if (isset($this->result_object[$n]))
- {
- $this->current_row = $n;
- // Set this, if not already done.
- if ( ! is_int($this->num_rows))
- {
- $this->num_rows = count($this->result_object);
- }
-
- return $this->result_object[$n];
- }
-
- $row = $this->row_array($n);
- // Cast only if the row exists
- if (count($row) > 0)
- {
- $this->current_row = $n;
- return (object) $row;
- }
-
- return array();
- }
-
- // --------------------------------------------------------------------
-
- /* Single row result. Custom object version.
- *
- * @param int row index
- * @param string custom class name
- * @return mixed custom object if row found; empty array otherwise
- */
- public function custom_row_object($n = 0, $class_name)
- {
- // Make sure $n is not a string
- if ( ! is_int($n))
- {
- $n = (int) $n;
- }
-
- if (array_key_exists($class_name, $this->custom_result_object))
- {
- /* We already have a the whole result set with this class_name,
- * return the specified row if it exists, and an empty array if
- * it doesn't.
- */
- if (isset($this->custom_result_object[$class_name][$n]))
- {
- $this->current_row = $n;
- return $this->custom_result_object[$class_name][$n];
- }
- else
- {
- return array();
- }
- }
- elseif ( ! class_exists($class_name)) // No such class exists
- {
- return array();
- }
-
- $row = $this->row_array($n);
- // An array would mean that the row doesn't exist
- if (is_array($row))
+ if ($class_name === 'stdClass' OR ! $row)
{
return $row;
}
- // Convert to the desired class and return
- $row_object = new $class_name();
+ $class_name = new $class_name();
foreach ($row as $key => $value)
{
- $row_object->$key = $value;
- }
-
- $this->current_row = $n;
- return $row_object;
- }
-
- // --------------------------------------------------------------------
-
- /* First row result.
- *
- * @param string ('object', 'array' or a custom class name)
- * @return mixed whatever was passed to the second parameter
- */
- public function first_row($type = 'object')
- {
- return $this->row(0, $type);
- }
-
- // --------------------------------------------------------------------
-
- /* Last row result.
- *
- * @param string ('object', 'array' or a custom class name)
- * @return mixed whatever was passed to the second parameter
- */
- public function last_row($type = 'object')
- {
- $result = &$this->result($type);
- if ( ! isset($this->num_rows))
- {
- $this->num_rows = count($result);
- }
- $this->current_row = $this->num_rows - 1;
- return $result[$this->current_row];
- }
-
- // --------------------------------------------------------------------
-
- /* Next row result.
- *
- * @param string ('object', 'array' or a custom class name)
- * @return mixed whatever was passed to the second parameter
- */
- public function next_row($type = 'object')
- {
- if (is_array($this->row_data))
- {
- $count = count($this->row_data);
- if ($this->current_row > $count OR ($this->current_row === 0 && $count === 0))
- {
- $n = $count;
- }
- else
- {
- $n = $this->current_row + 1;
- }
- }
- else
- {
- $n = 0;
- }
-
- return $this->row($n, $type);
- }
-
- // --------------------------------------------------------------------
-
- /* Previous row result.
- *
- * @param string ('object', 'array' or a custom class name)
- * @return mixed whatever was passed to the second parameter
- */
- public function previous_row($type = 'object')
- {
- $n = ($this->current_row !== 0) ? $this->current_row - 1 : 0;
- return $this->row($n, $type);
- }
-
- // --------------------------------------------------------------------
-
- /**
- * Data Seek
- *
- * Moves the internal pointer to the desired offset. We call
- * this internally before fetching results to make sure the
- * result set starts at zero.
- *
- * Oracle's PHP extension doesn't have an easy way of doing this
- * and the only workaround is to (re)execute the statement or cursor
- * in order to go to the first (zero) index of the result set.
- * Then, we would need to "dummy" fetch ($n - 1) rows to get to the
- * right one.
- *
- * This is as ridiculous as it sounds and it's the reason why every
- * other method that is fetching data tries to use an already "cached"
- * result set. Keeping this just in case it becomes needed at
- * some point in the future, but it will only work for resetting the
- * pointer to zero.
- *
- * @return bool
- */
- protected function _data_seek()
- {
- /* The PHP manual says that if OCI_NO_AUTO_COMMIT mode
- * is used, and oci_rollback() and/or oci_commit() are
- * not subsequently called - this will cause an unnecessary
- * rollback to be triggered at the end of the script execution.
- *
- * Therefore we'll try to avoid using that mode flag
- * if we're not currently in the middle of a transaction.
- */
- if ($this->commit_mode !== OCI_COMMIT_ON_SUCCESS)
- {
- $result = @oci_execute($this->stmt_id, $this->commit_mode);
- }
- else
- {
- $result = @oci_execute($this->stmt_id);
- }
-
- if ($result && $this->curs_id)
- {
- if ($this->commit_mode !== OCI_COMMIT_ON_SUCCESS)
- {
- return @oci_execute($this->curs_id, $this->commit_mode);
- }
- else
- {
- return @oci_execute($this->curs_id);
- }
+ $class_name->$key = $value;
}
- return $result;
+ return $class_name;
}
}
diff --git a/system/database/drivers/oci8/oci8_utility.php b/system/database/drivers/oci8/oci8_utility.php
index 0183eda26..d15537fdf 100644
--- a/system/database/drivers/oci8/oci8_utility.php
+++ b/system/database/drivers/oci8/oci8_utility.php
@@ -1,4 +1,4 @@
-<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');
+<?php
/**
* CodeIgniter
*
@@ -24,6 +24,7 @@
* @since Version 1.0
* @filesource
*/
+defined('BASEPATH') OR exit('No direct script access allowed');
/**
* Oracle Utility Class
@@ -34,18 +35,23 @@
*/
class CI_DB_oci8_utility extends CI_DB_utility {
+ /**
+ * List databases statement
+ *
+ * @var string
+ */
protected $_list_databases = 'SELECT username FROM dba_users'; // Schemas are actual usernames
/**
- * Oracle Export
+ * Export
*
- * @param array Preferences
+ * @param array $params Preferences
* @return mixed
*/
protected function _backup($params = array())
{
// Currently unsupported
- return $this->db->display_error('db_unsuported_feature');
+ return $this->db->display_error('db_unsupported_feature');
}
}
diff --git a/system/database/drivers/odbc/odbc_driver.php b/system/database/drivers/odbc/odbc_driver.php
index 38416cf90..29b2281cc 100644
--- a/system/database/drivers/odbc/odbc_driver.php
+++ b/system/database/drivers/odbc/odbc_driver.php
@@ -1,4 +1,4 @@
-<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');
+<?php
/**
* CodeIgniter
*
@@ -24,12 +24,13 @@
* @since Version 1.0
* @filesource
*/
+defined('BASEPATH') OR exit('No direct script access allowed');
/**
* ODBC Database Adapter Class
*
* Note: _DB is an extender class that the app controller
- * creates dynamically based on whether the active record
+ * creates dynamically based on whether the query builder
* class is being used or not.
*
* @package CodeIgniter
@@ -40,36 +41,66 @@
*/
class CI_DB_odbc_driver extends CI_DB {
+ /**
+ * Database driver
+ *
+ * @var string
+ */
public $dbdriver = 'odbc';
- // the character used to excape - not necessary for ODBC
+ /**
+ * Database schema
+ *
+ * @var string
+ */
+ public $schema = 'public';
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Identifier escape character
+ *
+ * Must be empty for ODBC.
+ *
+ * @var string
+ */
protected $_escape_char = '';
- // clause and character used for LIKE escape sequences
+ /**
+ * ESCAPE statement string
+ *
+ * @var string
+ */
protected $_like_escape_str = " {escape '%s'} ";
- protected $_like_escape_chr = '!';
/**
- * The syntax to count rows is slightly different across different
- * database engines, so this string appears in each driver and is
- * used for the count_all() and count_all_results() functions.
+ * ORDER BY random keyword
+ *
+ * @var array
*/
- protected $_count_string = 'SELECT COUNT(*) AS ';
- protected $_random_keyword;
+ protected $_random_keyword = array('RND()', 'RND(%d)');
+
+ // --------------------------------------------------------------------
+ /**
+ * Class constructor
+ *
+ * @param array $params
+ * @return void
+ */
public function __construct($params)
{
parent::__construct($params);
- $this->_random_keyword = ' RND('.time().')'; // database specific random keyword
-
// Legacy support for DSN in the hostname field
- if ($this->dsn == '')
+ if (empty($this->dsn))
{
$this->dsn = $this->hostname;
}
}
+ // --------------------------------------------------------------------
+
/**
* Non-persistent database connection
*
@@ -97,7 +128,7 @@ class CI_DB_odbc_driver extends CI_DB {
/**
* Execute the query
*
- * @param string an SQL query
+ * @param string $sql an SQL query
* @return resource
*/
protected function _execute($sql)
@@ -110,17 +141,13 @@ class CI_DB_odbc_driver extends CI_DB {
/**
* Begin Transaction
*
+ * @param bool $test_mode
* @return bool
*/
public function trans_begin($test_mode = FALSE)
{
- if ( ! $this->trans_enabled)
- {
- return TRUE;
- }
-
// When transactions are nested we only begin/commit/rollback the outermost ones
- if ($this->_trans_depth > 0)
+ if ( ! $this->trans_enabled OR $this->_trans_depth > 0)
{
return TRUE;
}
@@ -128,7 +155,7 @@ class CI_DB_odbc_driver extends CI_DB {
// Reset the transaction failure flag.
// If the $test_mode flag is set to TRUE transactions will be rolled back
// even if the queries produce a successful result.
- $this->_trans_failure = ($test_mode === TRUE) ? TRUE : FALSE;
+ $this->_trans_failure = ($test_mode === TRUE);
return odbc_autocommit($this->conn_id, FALSE);
}
@@ -142,13 +169,8 @@ class CI_DB_odbc_driver extends CI_DB {
*/
public function trans_commit()
{
- if ( ! $this->trans_enabled)
- {
- return TRUE;
- }
-
// When transactions are nested we only begin/commit/rollback the outermost ones
- if ($this->_trans_depth > 0)
+ if ( ! $this->trans_enabled OR $this->_trans_depth > 0)
{
return TRUE;
}
@@ -167,13 +189,8 @@ class CI_DB_odbc_driver extends CI_DB {
*/
public function trans_rollback()
{
- if ( ! $this->trans_enabled)
- {
- return TRUE;
- }
-
// When transactions are nested we only begin/commit/rollback the outermost ones
- if ($this->_trans_depth > 0)
+ if ( ! $this->trans_enabled OR $this->_trans_depth > 0)
{
return TRUE;
}
@@ -188,8 +205,8 @@ class CI_DB_odbc_driver extends CI_DB {
/**
* Escape String
*
- * @param string
- * @param bool whether or not the string will be used in a LIKE condition
+ * @param string $str
+ * @param bool $like Whether or not the string will be used in a LIKE condition
* @return string
*/
public function escape_str($str, $like = FALSE)
@@ -204,7 +221,6 @@ class CI_DB_odbc_driver extends CI_DB {
return $str;
}
- // ODBC doesn't require escaping
$str = remove_invisible_characters($str);
// escape LIKE condition wildcards
@@ -239,37 +255,7 @@ class CI_DB_odbc_driver extends CI_DB {
*/
public function insert_id()
{
- return ($this->db->db_debug) ? $this->db->display_error('db_unsuported_feature') : FALSE;
- }
-
- // --------------------------------------------------------------------
-
- /**
- * "Count All" query
- *
- * Generates a platform-specific query string that counts all records in
- * the specified database
- *
- * @param string
- * @return string
- */
- public function count_all($table = '')
- {
- if ($table == '')
- {
- return 0;
- }
-
- $query = $this->query($this->_count_string . $this->protect_identifiers('numrows') . " FROM " . $this->protect_identifiers($table, TRUE, NULL, FALSE));
-
- if ($query->num_rows() == 0)
- {
- return 0;
- }
-
- $row = $query->row();
- $this->_reset_select();
- return (int) $row->numrows;
+ return ($this->db->db_debug) ? $this->db->display_error('db_unsupported_feature') : FALSE;
}
// --------------------------------------------------------------------
@@ -279,17 +265,17 @@ class CI_DB_odbc_driver extends CI_DB {
*
* Generates a platform-specific query string so that the table names can be fetched
*
- * @param bool
+ * @param bool $prefix_limit
* @return string
*/
protected function _list_tables($prefix_limit = FALSE)
{
- $sql = "SHOW TABLES FROM `".$this->database."`";
+ $sql = "SELECT table_name FROM information_schema.tables WHERE table_schema = '".$this->schema."'";
- if ($prefix_limit !== FALSE AND $this->dbprefix != '')
+ if ($prefix_limit !== FALSE && $this->dbprefix !== '')
{
- //$sql .= " LIKE '".$this->escape_like_str($this->dbprefix)."%' ".sprintf($this->_like_escape_str, $this->_like_escape_chr);
- return FALSE; // not currently supported
+ return $sql." AND table_name LIKE '".$this->escape_like_str($this->dbprefix)."%' "
+ .sprintf($this->_like_escape_str, $this->_like_escape_chr);
}
return $sql;
@@ -302,12 +288,12 @@ class CI_DB_odbc_driver extends CI_DB {
*
* Generates a platform-specific query string so that the column names can be fetched
*
- * @param string the table name
+ * @param string $table
* @return string
*/
protected function _list_columns($table = '')
{
- return "SHOW COLUMNS FROM ".$table;
+ return 'SHOW COLUMNS FROM '.$table;
}
// --------------------------------------------------------------------
@@ -317,12 +303,12 @@ class CI_DB_odbc_driver extends CI_DB {
*
* Generates a platform-specific query so that the column data can be retrieved
*
- * @param string the table name
+ * @param string $table
* @return string
*/
protected function _field_data($table)
{
- return "SELECT TOP 1 FROM ".$table;
+ return 'SELECT TOP 1 FROM '.$table;
}
// --------------------------------------------------------------------
@@ -343,22 +329,19 @@ class CI_DB_odbc_driver extends CI_DB {
// --------------------------------------------------------------------
/**
- * From Tables
+ * Update statement
*
- * This function implicitly groups FROM tables so there is no confusion
- * about operator precedence in harmony with SQL standards
+ * Generates a platform-specific update string from the supplied data
*
- * @param array
+ * @param string $table
+ * @param array $values
* @return string
*/
- protected function _from_tables($tables)
+ protected function _update($table, $values)
{
- if ( ! is_array($tables))
- {
- $tables = array($tables);
- }
-
- return '('.implode(', ', $tables).')';
+ $this->qb_limit = FALSE;
+ $this->qb_orderby = array();
+ return parent::_update($table, $values);
}
// --------------------------------------------------------------------
@@ -368,10 +351,10 @@ class CI_DB_odbc_driver extends CI_DB {
*
* Generates a platform-specific truncate string from the supplied data
*
- * If the database does not support the truncate() command,
+ * If the database does not support the TRUNCATE statement,
* then this method maps to 'DELETE FROM table'
*
- * @param string the table name
+ * @param string $table
* @return string
*/
protected function _truncate($table)
@@ -382,19 +365,17 @@ class CI_DB_odbc_driver extends CI_DB {
// --------------------------------------------------------------------
/**
- * Limit string
+ * Delete statement
*
- * Generates a platform-specific LIMIT clause
+ * Generates a platform-specific delete string from the supplied data
*
- * @param string the sql query string
- * @param int the number of rows to limit the query to
- * @param int the offset value
+ * @param string $table
* @return string
*/
- protected function _limit($sql, $limit, $offset)
+ protected function _delete($table)
{
- // Does ODBC doesn't use the LIMIT clause?
- return $sql;
+ $this->qb_limit = FALSE;
+ return parent::_delete($table);
}
// --------------------------------------------------------------------
@@ -402,12 +383,11 @@ class CI_DB_odbc_driver extends CI_DB {
/**
* Close DB Connection
*
- * @param resource
* @return void
*/
- protected function _close($conn_id)
+ protected function _close()
{
- @odbc_close($conn_id);
+ @odbc_close($this->conn_id);
}
}
diff --git a/system/database/drivers/odbc/odbc_forge.php b/system/database/drivers/odbc/odbc_forge.php
index d59b8a911..fb16ca5cf 100644
--- a/system/database/drivers/odbc/odbc_forge.php
+++ b/system/database/drivers/odbc/odbc_forge.php
@@ -1,4 +1,4 @@
-<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');
+<?php
/**
* CodeIgniter
*
@@ -24,6 +24,7 @@
* @since Version 1.0
* @filesource
*/
+defined('BASEPATH') OR exit('No direct script access allowed');
/**
* ODBC Forge Class
@@ -34,163 +35,39 @@
*/
class CI_DB_odbc_forge extends CI_DB_forge {
- protected $_drop_database = 'DROP DATABASE %s';
- protected $_drop_table = 'DROP TABLE %s';
-
/**
- * Create Table
+ * CREATE TABLE IF statement
*
- * @param string the table name
- * @param array the fields
- * @param mixed primary key(s)
- * @param mixed key(s)
- * @param bool should 'IF NOT EXISTS' be added to the SQL
- * @return bool
+ * @var string
*/
- protected function _create_table($table, $fields, $primary_keys, $keys, $if_not_exists)
- {
- $sql = 'CREATE TABLE ';
-
- if ($if_not_exists === TRUE)
- {
- $sql .= 'IF NOT EXISTS ';
- }
-
- $sql .= $this->db->escape_identifiers($table).' (';
- $current_field_count = 0;
-
- foreach ($fields as $field => $attributes)
- {
- // Numeric field names aren't allowed in databases, so if the key is
- // numeric, we know it was assigned by PHP and the developer manually
- // entered the field information, so we'll simply add it to the list
- if (is_numeric($field))
- {
- $sql .= "\n\t$attributes";
- }
- else
- {
- $attributes = array_change_key_case($attributes, CASE_UPPER);
-
- $sql .= "\n\t".$this->db->protect_identifiers($field);
-
- $sql .= ' '.$attributes['TYPE'];
-
- if (array_key_exists('CONSTRAINT', $attributes))
- {
- $sql .= '('.$attributes['CONSTRAINT'].')';
- }
-
- if (array_key_exists('UNSIGNED', $attributes) && $attributes['UNSIGNED'] === TRUE)
- {
- $sql .= ' UNSIGNED';
- }
-
- if (array_key_exists('DEFAULT', $attributes))
- {
- $sql .= ' DEFAULT \''.$attributes['DEFAULT'].'\'';
- }
-
- if (array_key_exists('NULL', $attributes) && $attributes['NULL'] === TRUE)
- {
- $sql .= ' NULL';
- }
- else
- {
- $sql .= ' NOT NULL';
- }
-
- if (array_key_exists('AUTO_INCREMENT', $attributes) && $attributes['AUTO_INCREMENT'] === TRUE)
- {
- $sql .= ' AUTO_INCREMENT';
- }
- }
-
- // don't add a comma on the end of the last field
- if (++$current_field_count < count($fields))
- {
- $sql .= ',';
- }
- }
-
- if (count($primary_keys) > 0)
- {
- $primary_keys = $this->db->protect_identifiers($primary_keys);
- $sql .= ",\n\tPRIMARY KEY (" . implode(', ', $primary_keys) . ")";
- }
-
- if (is_array($keys) && count($keys) > 0)
- {
- foreach ($keys as $key)
- {
- if (is_array($key))
- {
- $key = $this->db->protect_identifiers($key);
- }
- else
- {
- $key = array($this->db->protect_identifiers($key));
- }
-
- $sql .= ",\n\tFOREIGN KEY (" . implode(', ', $key) . ")";
- }
- }
+ protected $_create_table_if = FALSE;
- $sql .= "\n)";
+ /**
+ * DROP TABLE IF statement
+ *
+ * @var string
+ */
+ protected $_drop_table_if = FALSE;
- return $sql;
- }
+ /**
+ * UNSIGNED support
+ *
+ * @var bool|array
+ */
+ protected $_unsigned = FALSE;
// --------------------------------------------------------------------
/**
- * Alter table query
- *
- * Generates a platform-specific query so that a table can be altered
- * Called by add_column(), drop_column(), and column_alter(),
+ * Field attribute AUTO_INCREMENT
*
- * @param string the ALTER type (ADD, DROP, CHANGE)
- * @param string the column name
- * @param string the table name
- * @param string the column definition
- * @param string the default value
- * @param bool should 'NOT NULL' be added
- * @param string the field after which we should add the new field
- * @return string
+ * @param array &$attributes
+ * @param array &$field
+ * @return void
*/
- protected function _alter_table($alter_type, $table, $column_name, $column_definition = '', $default_value = '', $null = '', $after_field = '')
+ protected function _attr_auto_increment(&$attributes, &$field)
{
- $sql = 'ALTER TABLE '.$this->db->protect_identifiers($table).' '.$alter_type.' '.$this->db->protect_identifiers($column_name);
-
- // DROP has everything it needs now.
- if ($alter_type == 'DROP')
- {
- return $sql;
- }
-
- $sql .= " $column_definition";
-
- if ($default_value != '')
- {
- $sql .= " DEFAULT \"$default_value\"";
- }
-
- if ($null === NULL)
- {
- $sql .= ' NULL';
- }
- else
- {
- $sql .= ' NOT NULL';
- }
-
- if ($after_field != '')
- {
- return $sql.' AFTER '.$this->db->protect_identifiers($after_field);
- }
-
- return $sql;
-
+ // Not supported (in most databases at least)
}
}
diff --git a/system/database/drivers/odbc/odbc_result.php b/system/database/drivers/odbc/odbc_result.php
index ecba5977e..2c50c255b 100644
--- a/system/database/drivers/odbc/odbc_result.php
+++ b/system/database/drivers/odbc/odbc_result.php
@@ -1,4 +1,4 @@
-<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');
+<?php
/**
* CodeIgniter
*
@@ -24,6 +24,7 @@
* @since Version 1.0
* @filesource
*/
+defined('BASEPATH') OR exit('No direct script access allowed');
/**
* ODBC Result Class
@@ -33,11 +34,10 @@
* @category Database
* @author EllisLab Dev Team
* @link http://codeigniter.com/user_guide/database/
+ * @since 1.3
*/
class CI_DB_odbc_result extends CI_DB_result {
- public $num_rows;
-
/**
* Number of rows in the result set
*
@@ -49,14 +49,22 @@ class CI_DB_odbc_result extends CI_DB_result {
{
return $this->num_rows;
}
+ elseif (($this->num_rows = @odbc_num_rows($this->result_id)) !== -1)
+ {
+ return $this->num_rows;
+ }
// Work-around for ODBC subdrivers that don't support num_rows()
- if (($this->num_rows = @odbc_num_rows($this->result_id)) === -1)
+ if (count($this->result_array) > 0)
{
- $this->num_rows = count($this->result_array());
+ return $this->num_rows = count($this->result_array);
+ }
+ elseif (count($this->result_object) > 0)
+ {
+ return $this->num_rows = count($this->result_object);
}
- return $this->num_rows;
+ return $this->num_rows = count($this->result_array());
}
// --------------------------------------------------------------------
@@ -148,14 +156,7 @@ class CI_DB_odbc_result extends CI_DB_result {
*/
protected function _fetch_assoc()
{
- if (function_exists('odbc_fetch_array'))
- {
- return odbc_fetch_array($this->result_id);
- }
- else
- {
- return $this->_odbc_fetch_array($this->result_id);
- }
+ return odbc_fetch_array($this->result_id);
}
// --------------------------------------------------------------------
@@ -165,141 +166,93 @@ class CI_DB_odbc_result extends CI_DB_result {
*
* Returns the result set as an object
*
+ * @param string $class_name
* @return object
*/
- protected function _fetch_object()
+ protected function _fetch_object($class_name = 'stdClass')
{
- if (function_exists('odbc_fetch_object'))
- {
- return odbc_fetch_object($this->result_id);
- }
- else
+ $row = odbc_fetch_object($this->result_id);
+
+ if ($class_name === 'stdClass' OR ! $row)
{
- return $this->_odbc_fetch_object($this->result_id);
+ return $row;
}
- }
-
- // --------------------------------------------------------------------
- /**
- * Result - object
- *
- * subsititutes the odbc_fetch_object function when
- * not available (odbc_fetch_object requires unixODBC)
- *
- * @return object
- */
- protected function _odbc_fetch_object(& $odbc_result)
- {
- $rs = array();
- $rs_obj = FALSE;
- if (odbc_fetch_into($odbc_result, $rs))
+ $class_name = new $class_name();
+ foreach ($row as $key => $value)
{
- foreach ($rs as $k => $v)
- {
- $field_name = odbc_field_name($odbc_result, $k+1);
- $rs_obj->$field_name = $v;
- }
+ $class_name->$key = $value;
}
- return $rs_obj;
+
+ return $class_name;
}
- // --------------------------------------------------------------------
+}
+
+// --------------------------------------------------------------------
+if ( ! function_exists('odbc_fetch_array'))
+{
/**
- * Result - array
+ * ODBC Fetch array
*
- * subsititutes the odbc_fetch_array function when
- * not available (odbc_fetch_array requires unixODBC)
+ * Emulates the native odbc_fetch_array() function when
+ * it is not available (odbc_fetch_array() requires unixODBC)
*
+ * @param resource &$result
+ * @param int $rownumber
* @return array
*/
- protected function _odbc_fetch_array(& $odbc_result)
+ function odbc_fetch_array(&$result, $rownumber = 1)
{
$rs = array();
- $rs_assoc = FALSE;
- if (odbc_fetch_into($odbc_result, $rs))
+ if ( ! odbc_fetch_into($result, $rs, $rownumber))
{
- $rs_assoc = array();
- foreach ($rs as $k => $v)
- {
- $field_name = odbc_field_name($odbc_result, $k+1);
- $rs_assoc[$field_name] = $v;
- }
+ return FALSE;
}
- return $rs_assoc;
- }
- // --------------------------------------------------------------------
-
- /**
- * Query result. Array version.
- *
- * @return array
- */
- public function result_array()
- {
- if (count($this->result_array) > 0)
- {
- return $this->result_array;
- }
- elseif (($c = count($this->result_object)) > 0)
- {
- for ($i = 0; $i < $c; $i++)
- {
- $this->result_array[$i] = (array) $this->result_object[$i];
- }
- }
- elseif ($this->result_id === FALSE)
+ $rs_assoc = array();
+ foreach ($rs as $k => $v)
{
- return array();
- }
- else
- {
- while ($row = $this->_fetch_assoc())
- {
- $this->result_array[] = $row;
- }
+ $field_name = odbc_field_name($result, $k+1);
+ $rs_assoc[$field_name] = $v;
}
- return $this->result_array;
+ return $rs_assoc;
}
+}
- // --------------------------------------------------------------------
+// --------------------------------------------------------------------
+if ( ! function_exists('odbc_fetch_object'))
+{
/**
- * Query result. Object version.
+ * ODBC Fetch object
*
- * @return array
+ * Emulates the native odbc_fetch_object() function when
+ * it is not available.
+ *
+ * @param resource &$result
+ * @param int $rownumber
+ * @return object
*/
- public function result_object()
+ function odbc_fetch_object(&$result, $rownumber = 1)
{
- if (count($this->result_object) > 0)
- {
- return $this->result_object;
- }
- elseif (($c = count($this->result_array)) > 0)
- {
- for ($i = 0; $i < $c; $i++)
- {
- $this->result_object[$i] = (object) $this->result_array[$i];
- }
- }
- elseif ($this->result_id === FALSE)
+ $rs = array();
+ if ( ! odbc_fetch_into($result, $rs, $rownumber))
{
- return array();
+ return FALSE;
}
- else
+
+ $rs_object = new stdClass();
+ foreach ($rs as $k => $v)
{
- while ($row = $this->_fetch_object())
- {
- $this->result_object[] = $row;
- }
+ $field_name = odbc_field_name($result, $k+1);
+ $rs_object->$field_name = $v;
}
- return $this->result_object;
+ return $rs_object;
}
-
}
/* End of file odbc_result.php */
diff --git a/system/database/drivers/odbc/odbc_utility.php b/system/database/drivers/odbc/odbc_utility.php
index 224d48d2b..908674a9d 100644
--- a/system/database/drivers/odbc/odbc_utility.php
+++ b/system/database/drivers/odbc/odbc_utility.php
@@ -1,4 +1,4 @@
-<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');
+<?php
/**
* CodeIgniter
*
@@ -24,6 +24,7 @@
* @since Version 1.0
* @filesource
*/
+defined('BASEPATH') OR exit('No direct script access allowed');
/**
* ODBC Utility Class
@@ -34,18 +35,16 @@
*/
class CI_DB_odbc_utility extends CI_DB_utility {
- protected $_list_databases = FALSE;
-
/**
- * ODBC Export
+ * Export
*
- * @param array Preferences
+ * @param array $params Preferences
* @return mixed
*/
protected function _backup($params = array())
{
// Currently unsupported
- return $this->db->display_error('db_unsuported_feature');
+ return $this->db->display_error('db_unsupported_feature');
}
}
diff --git a/system/database/drivers/pdo/pdo_driver.php b/system/database/drivers/pdo/pdo_driver.php
index 60151b900..d2dfa8bf0 100644
--- a/system/database/drivers/pdo/pdo_driver.php
+++ b/system/database/drivers/pdo/pdo_driver.php
@@ -1,4 +1,4 @@
-<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');
+<?php
/**
* CodeIgniter
*
@@ -24,12 +24,13 @@
* @since Version 2.1.0
* @filesource
*/
+defined('BASEPATH') OR exit('No direct script access allowed');
/**
* PDO Database Adapter Class
*
* Note: _DB is an extender class that the app controller
- * creates dynamically based on whether the active record
+ * creates dynamically based on whether the query builder
* class is being used or not.
*
* @package CodeIgniter
@@ -40,159 +41,103 @@
*/
class CI_DB_pdo_driver extends CI_DB {
+ /**
+ * Database driver
+ *
+ * @var string
+ */
public $dbdriver = 'pdo';
- // the character used to excape - not necessary for PDO
- protected $_escape_char = '';
-
- // clause and character used for LIKE escape sequences
- protected $_like_escape_str = " ESCAPE '%s' ";
- protected $_like_escape_chr = '!';
-
/**
- * The syntax to count rows is slightly different across different
- * database engines, so this string appears in each driver and is
- * used for the count_all() and count_all_results() functions.
+ * Transaction enabled flag
+ *
+ * @var bool
*/
- protected $_count_string = 'SELECT COUNT(*) AS ';
- protected $_random_keyword;
+ public $trans_enabled = FALSE;
- // need to track the pdo driver and options
- public $pdodriver;
+ /**
+ * PDO Options
+ *
+ * @var array
+ */
public $options = array();
+ // --------------------------------------------------------------------
+
+ /**
+ * Class constructor
+ *
+ * Validates the DSN string and/or detects the subdriver.
+ *
+ * @param array $params
+ * @return void
+ */
public function __construct($params)
{
parent::__construct($params);
- if (preg_match('/([^;]+):/', $this->dsn, $match) && count($match) == 2)
+ if (preg_match('/([^;]+):/', $this->dsn, $match) && count($match) === 2)
{
// If there is a minimum valid dsn string pattern found, we're done
// This is for general PDO users, who tend to have a full DSN string.
- $this->pdodriver = end($match);
+ $this->subdriver = $match[1];
+ return;
}
- else
+ // Legacy support for DSN specified in the hostname field
+ elseif (preg_match('/([^;]+):/', $this->hostname, $match) && count($match) === 2)
{
- // Try to build a complete DSN string from params
- $this->_connect_string($params);
+ $this->dsn = $this->hostname;
+ $this->hostname = NULL;
+ $this->subdriver = $match[1];
+ return;
}
-
- // clause and character used for LIKE escape sequences
- // this one depends on the driver being used
- if ($this->pdodriver == 'mysql')
+ elseif (in_array($this->subdriver, array('mssql', 'sybase'), TRUE))
{
- $this->_escape_char = '`';
- $this->_like_escape_str = '';
- $this->_like_escape_chr = '';
+ $this->subdriver = 'dblib';
}
- elseif ($this->pdodriver == 'odbc')
+ elseif ($this->subdriver === '4D')
{
- $this->_like_escape_str = " {escape '%s'} ";
+ $this->subdriver = '4d';
}
- elseif ( ! in_array($this->pdodriver, array('sqlsrv', 'mssql', 'dblib', 'sybase')))
+ elseif ( ! in_array($this->subdriver, array('4d', 'cubrid', 'dblib', 'firebird', 'ibm', 'informix', 'mysql', 'oci', 'odbc', 'sqlite', 'sqlsrv'), TRUE))
{
- $this->_escape_char = '"';
+ log_message('error', 'PDO: Invalid or non-existent subdriver');
+
+ if ($this->db_debug)
+ {
+ show_error('Invalid or non-existent PDO subdriver');
+ }
}
- $this->trans_enabled = FALSE;
- $this->_random_keyword = ' RND('.time().')'; // database specific random keyword
+ $this->dsn = NULL;
}
+ // --------------------------------------------------------------------
+
/**
- * Connection String
+ * Database connection
*
- * @param array
- * @return void
+ * @param bool $persistent
+ * @return object
*/
- protected function _connect_string($params)
+ public function db_connect($persistent = FALSE)
{
- if (strpos($this->hostname, ':'))
+ $this->options[PDO::ATTR_PERSISTENT] = $persistent;
+
+ // Connecting...
+ try
{
- // hostname generally would have this prototype
- // $db['hostname'] = 'pdodriver:host(/Server(/DSN))=hostname(/DSN);';
- // We need to get the prefix (pdodriver used by PDO).
- $dsnarray = explode(':', $this->hostname);
- $this->pdodriver = $dsnarray[0];
-
- // End dsn with a semicolon for extra backward compability
- // if database property was not empty.
- if ( ! empty($this->database))
- {
- $this->dsn .= rtrim($this->hostname, ';').';';
- }
+ return @new PDO($this->dsn, $this->username, $this->password, $this->options);
}
- else
+ catch (PDOException $e)
{
- // Invalid DSN, display an error
- if ( ! array_key_exists('pdodriver', $params))
- {
- show_error('Invalid DB Connection String for PDO');
- }
-
- // Assuming that the following DSN string format is used:
- // $dsn = 'pdo://username:password@hostname:port/database?pdodriver=pgsql';
- $this->dsn = $this->pdodriver.':';
-
- // Add hostname to the DSN for databases that need it
- if ( ! empty($this->hostname)
- && strpos($this->hostname, ':') === FALSE
- && in_array($this->pdodriver, array('informix', 'mysql', 'pgsql', 'sybase', 'mssql', 'dblib', 'cubrid')))
+ if ($this->db_debug && empty($this->failover))
{
- $this->dsn .= 'host='.$this->hostname.';';
+ $this->display_error($e->getMessage(), '', TRUE);
}
- // Add a port to the DSN for databases that can use it
- if ( ! empty($this->port) && in_array($this->pdodriver, array('informix', 'mysql', 'pgsql', 'ibm', 'cubrid')))
- {
- $this->dsn .= 'port='.$this->port.';';
- }
+ return FALSE;
}
-
- // Add the database name to the DSN, if needed
- if (stripos($this->dsn, 'dbname') === FALSE
- && in_array($this->pdodriver, array('4D', 'pgsql', 'mysql', 'firebird', 'sybase', 'mssql', 'dblib', 'cubrid')))
- {
- $this->dsn .= 'dbname='.$this->database.';';
- }
- elseif (stripos($this->dsn, 'database') === FALSE && in_array($this->pdodriver, array('ibm', 'sqlsrv')))
- {
- if (stripos($this->dsn, 'dsn') === FALSE)
- {
- $this->dsn .= 'database='.$this->database.';';
- }
- }
- elseif ($this->pdodriver === 'sqlite' && $this->dsn === 'sqlite:')
- {
- if ($this->database !== ':memory')
- {
- if ( ! file_exists($this->database))
- {
- show_error('Invalid DB Connection string for PDO SQLite');
- }
-
- $this->dsn .= (strpos($this->database, DIRECTORY_SEPARATOR) !== 0) ? DIRECTORY_SEPARATOR : '';
- }
-
- $this->dsn .= $this->database;
- }
-
- // Add charset to the DSN, if needed
- if ( ! empty($this->char_set) && in_array($this->pdodriver, array('4D', 'mysql', 'sybase', 'mssql', 'dblib', 'oci')))
- {
- $this->dsn .= 'charset='.$this->char_set.';';
- }
- }
-
- // --------------------------------------------------------------------
-
- /**
- * Non-persistent database connection
- *
- * @return object
- */
- public function db_connect()
- {
- return $this->_pdo_connect();
}
// --------------------------------------------------------------------
@@ -204,69 +149,44 @@ class CI_DB_pdo_driver extends CI_DB {
*/
public function db_pconnect()
{
- return $this->_pdo_connect(TRUE);
+ return $this->db_connect(TRUE);
}
// --------------------------------------------------------------------
/**
- * PDO connection
+ * Database version number
*
- * @param bool
- * @return object
+ * @return string
*/
- protected function _pdo_connect($persistent = FALSE)
+ public function version()
{
- $this->options[PDO::ATTR_ERRMODE] = PDO::ERRMODE_SILENT;
- $persistent === FALSE OR $this->options[PDO::ATTR_PERSISTENT] = TRUE;
-
- /* Prior to PHP 5.3.6, even if the charset was supplied in the DSN
- * on connect - it was ignored. This is a work-around for the issue.
- *
- * Reference: http://www.php.net/manual/en/ref.pdo-mysql.connection.php
- */
- if ($this->subdriver === 'mysql' && ! is_php('5.3.6') && ! empty($this->char_set))
+ if (isset($this->data_cache['version']))
+ {
+ return $this->data_cache['version'];
+ }
+ elseif ( ! $this->conn_id)
{
- $this->options[PDO::MYSQL_ATTR_INIT_COMMAND] = 'SET NAMES '.$this->char_set
- .( ! empty($this->db_collat) ? " COLLATE '".$this->dbcollat."'" : '');
+ $this->initialize();
}
- // Connecting...
+ // Not all subdrivers support the getAttribute() method
try
{
- return new PDO($this->dsn, $this->username, $this->password, $this->options);
+ return $this->data_cache['version'] = $this->conn_id->getAttribute(PDO::ATTR_SERVER_VERSION);
}
catch (PDOException $e)
{
- if ($this->db_debug && empty($this->failover))
- {
- $this->display_error($e->getMessage(), '', TRUE);
- }
-
- return FALSE;
+ return parent::version();
}
}
// --------------------------------------------------------------------
/**
- * Database version number
- *
- * @return string
- */
- public function version()
- {
- return isset($this->data_cache['version'])
- ? $this->data_cache['version']
- : $this->data_cache['version'] = $this->conn_id->getAttribute(PDO::ATTR_SERVER_VERSION);
- }
-
- // --------------------------------------------------------------------
-
- /**
* Execute the query
*
- * @param string an SQL query
+ * @param string $sql SQL query
* @return mixed
*/
protected function _execute($sql)
@@ -279,6 +199,7 @@ class CI_DB_pdo_driver extends CI_DB {
/**
* Begin Transaction
*
+ * @param bool $test_mode
* @return bool
*/
public function trans_begin($test_mode = FALSE)
@@ -338,8 +259,8 @@ class CI_DB_pdo_driver extends CI_DB {
/**
* Escape String
*
- * @param string
- * @param bool whether or not the string will be used in a LIKE condition
+ * @param string $str
+ * @param bool $like Whether or not the string will be used in a LIKE condition
* @return string
*/
public function escape_str($str, $like = FALSE)
@@ -358,7 +279,7 @@ class CI_DB_pdo_driver extends CI_DB {
$str = $this->conn_id->quote($str);
// If there are duplicated quotes, trim them away
- if (strpos($str, "'") === 0)
+ if ($str[0] === "'")
{
$str = substr($str, 1, -1);
}
@@ -391,132 +312,27 @@ class CI_DB_pdo_driver extends CI_DB {
/**
* Insert ID
*
- * @param string
+ * @param string $name
* @return int
*/
public function insert_id($name = NULL)
{
- if ($this->pdodriver === 'pgsql' && $name === NULL && $this->version() >= '8.1')
- {
- $query = $this->query('SELECT LASTVAL() AS ins_id');
- $query = $query->row();
- return $query->ins_id;
- }
-
return $this->conn_id->lastInsertId($name);
}
// --------------------------------------------------------------------
/**
- * "Count All" query
- *
- * Generates a platform-specific query string that counts all records in
- * the specified database
- *
- * @param string
- * @return string
- */
- public function count_all($table = '')
- {
- if ($table == '')
- {
- return 0;
- }
-
- $sql = $this->_count_string.$this->protect_identifiers('numrows').' FROM '.$this->protect_identifiers($table, TRUE, NULL, FALSE);
- $query = $this->query($sql);
-
- if ($query->num_rows() == 0)
- {
- return 0;
- }
-
- $row = $query->row();
- $this->_reset_select();
-
- return (int) $row->numrows;
- }
-
- // --------------------------------------------------------------------
-
- /**
- * Show table query
- *
- * Generates a platform-specific query string so that the table names can be fetched
- *
- * @param bool
- * @return string
- */
- protected function _list_tables($prefix_limit = FALSE)
- {
- if ($this->pdodriver == 'pgsql')
- {
- // Analog function to show all tables in postgre
- $sql = "SELECT * FROM information_schema.tables WHERE table_schema = 'public'";
- }
- elseif ($this->pdodriver == 'sqlite')
- {
- // Analog function to show all tables in sqlite
- $sql = "SELECT name FROM sqlite_master WHERE type='table' AND name NOT LIKE 'sqlite_%'";
- }
- else
- {
- $sql = 'SHOW TABLES FROM '.$this->escape_identifiers($this->database);
- }
-
- if ($prefix_limit !== FALSE AND $this->dbprefix != '')
- {
- return FALSE;
- }
-
- return $sql;
- }
-
- // --------------------------------------------------------------------
-
- /**
- * Show column query
- *
- * Generates a platform-specific query string so that the column names can be fetched
- *
- * @param string the table name
- * @return string
- */
- protected function _list_columns($table = '')
- {
- return 'SHOW COLUMNS FROM '.$this->escape_identifiers($table);
- }
-
- // --------------------------------------------------------------------
-
- /**
* Field data query
*
* Generates a platform-specific query so that the column data can be retrieved
*
- * @param string the table name
+ * @param string $table
* @return string
*/
protected function _field_data($table)
{
- if ($this->pdodriver == 'mysql' or $this->pdodriver == 'pgsql')
- {
- // Analog function for mysql and postgre
- return 'SELECT * FROM '.$this->escape_identifiers($table).' LIMIT 1';
- }
- elseif ($this->pdodriver == 'oci')
- {
- // Analog function for oci
- return 'SELECT * FROM '.$this->escape_identifiers($table).' WHERE ROWNUM <= 1';
- }
- elseif ($this->pdodriver == 'sqlite')
- {
- // Analog function for sqlite
- return 'PRAGMA table_info('.$this->escape_identifiers($table).')';
- }
-
- return 'SELECT TOP 1 FROM '.$this->escape_identifiers($table);
+ return 'SELECT TOP 1 * FROM '.$this->protect_identifiers($table);
}
// --------------------------------------------------------------------
@@ -551,57 +367,32 @@ class CI_DB_pdo_driver extends CI_DB {
// --------------------------------------------------------------------
/**
- * From Tables
- *
- * This function implicitly groups FROM tables so there is no confusion
- * about operator precedence in harmony with SQL standards
- *
- * @param array
- * @return string
- */
- protected function _from_tables($tables)
- {
- if ( ! is_array($tables))
- {
- $tables = array($tables);
- }
-
- return (count($tables) === 1) ? $tables[0] : '('.implode(', ', $tables).')';
- }
-
- // --------------------------------------------------------------------
-
- /**
* Update_Batch statement
*
* Generates a platform-specific batch update string from the supplied data
*
- * @param string the table name
- * @param array the update data
- * @param array the where clause
+ * @param string $table Table name
+ * @param array $values Update data
+ * @param string $index WHERE key
* @return string
*/
- protected function _update_batch($table, $values, $index, $where = NULL)
+ protected function _update_batch($table, $values, $index)
{
- $ids = array();
- $where = ($where != '' && count($where) >=1) ? implode(" ", $where).' AND ' : '';
-
+ $ids = array();
foreach ($values as $key => $val)
{
$ids[] = $val[$index];
foreach (array_keys($val) as $field)
{
- if ($field != $index)
+ if ($field !== $index)
{
- $final[$field][] = 'WHEN '.$index.' = '.$val[$index].' THEN '.$val[$field];
+ $final[$field][] = 'WHEN '.$index.' = '.$val[$index].' THEN '.$val[$field];
}
}
}
- $sql = 'UPDATE '.$table.' SET ';
$cases = '';
-
foreach ($final as $k => $v)
{
$cases .= $k.' = CASE '."\n";
@@ -614,10 +405,9 @@ class CI_DB_pdo_driver extends CI_DB {
$cases .= 'ELSE '.$k.' END, ';
}
- $sql .= substr($cases, 0, -2);
- $sql .= ' WHERE '.$where.$index.' IN ('.implode(',', $ids).')';
+ $this->where($index.' IN('.implode(',', $ids).')', NULL, FALSE);
- return $sql;
+ return 'UPDATE '.$table.' SET '.substr($cases, 0, -2).$this->_compile_wh('qb_where');
}
// --------------------------------------------------------------------
@@ -627,57 +417,15 @@ class CI_DB_pdo_driver extends CI_DB {
*
* Generates a platform-specific truncate string from the supplied data
*
- * If the database does not support the truncate() command,
+ * If the database does not support the TRUNCATE statement,
* then this method maps to 'DELETE FROM table'
*
- * @param string the table name
+ * @param string $table
* @return string
*/
protected function _truncate($table)
{
- return 'DELETE FROM '.$table;
- }
-
- // --------------------------------------------------------------------
-
- /**
- * Limit string
- *
- * Generates a platform-specific LIMIT clause
- *
- * @param string the sql query string
- * @param int the number of rows to limit the query to
- * @param int the offset value
- * @return string
- */
- protected function _limit($sql, $limit, $offset)
- {
- if ($this->pdodriver == 'cubrid' OR $this->pdodriver == 'sqlite')
- {
- $offset = ($offset == 0) ? '' : $offset.', ';
-
- return $sql.'LIMIT '.$offset.$limit;
- }
- else
- {
- $sql .= 'LIMIT '.$limit;
- $sql .= ($offset > 0) ? ' OFFSET '.$offset : '';
-
- return $sql;
- }
- }
-
- // --------------------------------------------------------------------
-
- /**
- * Close DB Connection
- *
- * @param object
- * @return void
- */
- protected function _close($conn_id)
- {
- $this->conn_id = NULL;
+ return 'TRUNCATE TABLE '.$table;
}
}
diff --git a/system/database/drivers/pdo/pdo_forge.php b/system/database/drivers/pdo/pdo_forge.php
index ca8657a0f..130d3667e 100644
--- a/system/database/drivers/pdo/pdo_forge.php
+++ b/system/database/drivers/pdo/pdo_forge.php
@@ -1,4 +1,4 @@
-<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');
+<?php
/**
* CodeIgniter
*
@@ -24,6 +24,7 @@
* @since Version 2.1.0
* @filesource
*/
+defined('BASEPATH') OR exit('No direct script access allowed');
/**
* PDO Forge Class
@@ -34,169 +35,19 @@
*/
class CI_DB_pdo_forge extends CI_DB_forge {
- protected $_drop_database = 'DROP DATABASE %s';
- protected $_drop_table = 'DROP TABLE %s';
-
/**
- * Create Table
+ * CREATE TABLE IF statement
*
- * @param string the table name
- * @param array the fields
- * @param mixed primary key(s)
- * @param mixed key(s)
- * @param bool should 'IF NOT EXISTS' be added to the SQL
- * @return bool
+ * @var string
*/
- protected function _create_table($table, $fields, $primary_keys, $keys, $if_not_exists)
- {
- $sql = 'CREATE TABLE ';
-
- if ($if_not_exists === TRUE)
- {
- $sql .= 'IF NOT EXISTS ';
- }
-
- $sql .= $this->db->escape_identifiers($table).' (';
- $current_field_count = 0;
-
- foreach ($fields as $field => $attributes)
- {
- // Numeric field names aren't allowed in databases, so if the key is
- // numeric, we know it was assigned by PHP and the developer manually
- // entered the field information, so we'll simply add it to the list
- if (is_numeric($field))
- {
- $sql .= "\n\t$attributes";
- }
- else
- {
- $attributes = array_change_key_case($attributes, CASE_UPPER);
- $numeric = array('SERIAL', 'INTEGER');
-
- $sql .= "\n\t".$this->db->protect_identifiers($field);
-
- $sql .= ' '.$attributes['TYPE'];
-
- if (array_key_exists('CONSTRAINT', $attributes))
- {
- // Exception for Postgre numeric which not too happy with constraint within those type
- if ( ! ($this->db->pdodriver == 'pgsql' && in_array($attributes['TYPE'], $numeric)))
- {
- $sql .= '('.$attributes['CONSTRAINT'].')';
- }
- }
-
- if (array_key_exists('UNSIGNED', $attributes) && $attributes['UNSIGNED'] === TRUE)
- {
- $sql .= ' UNSIGNED';
- }
-
- if (array_key_exists('DEFAULT', $attributes))
- {
- $sql .= ' DEFAULT \''.$attributes['DEFAULT'].'\'';
- }
-
- if (array_key_exists('NULL', $attributes) && $attributes['NULL'] === TRUE)
- {
- $sql .= ' NULL';
- }
- else
- {
- $sql .= ' NOT NULL';
- }
-
- if (array_key_exists('AUTO_INCREMENT', $attributes) && $attributes['AUTO_INCREMENT'] === TRUE)
- {
- $sql .= ' AUTO_INCREMENT';
- }
- }
-
- // don't add a comma on the end of the last field
- if (++$current_field_count < count($fields))
- {
- $sql .= ',';
- }
- }
-
- if (count($primary_keys) > 0)
- {
- $primary_keys = $this->db->protect_identifiers($primary_keys);
- $sql .= ",\n\tPRIMARY KEY (" . implode(', ', $primary_keys) . ")";
- }
-
- if (is_array($keys) && count($keys) > 0)
- {
- foreach ($keys as $key)
- {
- if (is_array($key))
- {
- $key = $this->db->protect_identifiers($key);
- }
- else
- {
- $key = array($this->db->protect_identifiers($key));
- }
-
- $sql .= ",\n\tFOREIGN KEY (" . implode(', ', $key) . ")";
- }
- }
-
- $sql .= "\n)";
-
- return $sql;
- }
-
- // --------------------------------------------------------------------
+ protected $_create_table_if = FALSE;
/**
- * Alter table query
- *
- * Generates a platform-specific query so that a table can be altered
- * Called by add_column(), drop_column(), and column_alter(),
+ * DROP TABLE IF statement
*
- * @param string the ALTER type (ADD, DROP, CHANGE)
- * @param string the column name
- * @param string the table name
- * @param string the column definition
- * @param string the default value
- * @param bool should 'NOT NULL' be added
- * @param string the field after which we should add the new field
- * @return string
+ * @var string
*/
- protected function _alter_table($alter_type, $table, $column_name, $column_definition = '', $default_value = '', $null = '', $after_field = '')
- {
- $sql = 'ALTER TABLE `'.$this->db->protect_identifiers($table).'` '.$alter_type.' '.$this->db->protect_identifiers($column_name);
-
- // DROP has everything it needs now.
- if ($alter_type == 'DROP')
- {
- return $sql;
- }
-
- $sql .= " $column_definition";
-
- if ($default_value != '')
- {
- $sql .= " DEFAULT \"$default_value\"";
- }
-
- if ($null === NULL)
- {
- $sql .= ' NULL';
- }
- else
- {
- $sql .= ' NOT NULL';
- }
-
- if ($after_field != '')
- {
- return $sql.' AFTER '.$this->db->protect_identifiers($after_field);
- }
-
- return $sql;
-
- }
+ protected $_drop_table_if = FALSE;
}
diff --git a/system/database/drivers/pdo/pdo_result.php b/system/database/drivers/pdo/pdo_result.php
index 19aee1dfc..25cf87be8 100644
--- a/system/database/drivers/pdo/pdo_result.php
+++ b/system/database/drivers/pdo/pdo_result.php
@@ -1,4 +1,4 @@
-<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');
+<?php
/**
* CodeIgniter
*
@@ -21,9 +21,10 @@
* @copyright Copyright (c) 2008 - 2012, EllisLab, Inc. (http://ellislab.com/)
* @license http://opensource.org/licenses/OSL-3.0 Open Software License (OSL 3.0)
* @link http://codeigniter.com
- * @since Version 2.1.0
+ * @since Version 1.0
* @filesource
*/
+defined('BASEPATH') OR exit('No direct script access allowed');
/**
* PDO Result Class
@@ -33,77 +34,35 @@
* @category Database
* @author EllisLab Dev Team
* @link http://codeigniter.com/user_guide/database/
+ * @since 2.1
*/
class CI_DB_pdo_result extends CI_DB_result {
/**
- * @var bool Hold the flag whether a result handler already fetched before
- */
- protected $is_fetched = FALSE;
-
- /**
- * @var mixed Hold the fetched assoc array of a result handler
- */
- protected $result_assoc;
-
- /**
* Number of rows in the result set
*
* @return int
*/
public function num_rows()
{
- if (empty($this->result_id) OR ! is_object($this->result_id))
+ if (is_int($this->num_rows))
{
- // invalid result handler
- return 0;
+ return $this->num_rows;
}
- elseif (($num_rows = $this->result_id->rowCount()) && $num_rows > 0)
+ elseif (count($this->result_array) > 0)
{
- // If rowCount return something, we're done.
- return $num_rows;
+ return $this->num_rows = count($this->result_array);
}
-
- // Fetch the result, instead perform another extra query
- return ($this->is_fetched && is_array($this->result_assoc)) ? count($this->result_assoc) : count($this->result_assoc());
- }
-
- /**
- * Fetch the result handler
- *
- * @return mixed
- */
- public function result_assoc()
- {
- // If the result already fetched before, use that one
- if (count($this->result_array) > 0 OR $this->is_fetched)
+ elseif (count($this->result_object) > 0)
{
- return $this->result_array();
+ return $this->num_rows = count($this->result_object);
}
-
- // Define the output
- $output = array('assoc', 'object');
-
- // Fetch the result
- foreach ($output as $type)
+ elseif (($num_rows = $this->result_id->rowCount()) > 0)
{
- // Define the method and handler
- $res_method = '_fetch_'.$type;
- $res_handler = 'result_'.$type;
-
- $this->$res_handler = array();
-
- while ($row = $this->$res_method())
- {
- $this->{$res_handler}[] = $row;
- }
+ return $this->num_rows = $num_rows;
}
- // Save this as buffer and marked the fetch flag
- $this->result_array = $this->result_assoc;
- $this->is_fetched = TRUE;
-
- return $this->result_assoc;
+ return $this->num_rows = count($this->result_array());
}
// --------------------------------------------------------------------
@@ -129,12 +88,14 @@ class CI_DB_pdo_result extends CI_DB_result {
*/
public function list_fields()
{
- if ($this->db->db_debug)
+ $field_names = array();
+ for ($i = 0, $c = $this->num_fields(); $i < $c; $i++)
{
- return $this->db->display_error('db_unsuported_feature');
+ $field_names[$i] = @$this->result_id->getColumnMeta();
+ $field_names[$i] = $field_names[$i]['name'];
}
- return FALSE;
+ return $field_names;
}
// --------------------------------------------------------------------
@@ -148,61 +109,28 @@ class CI_DB_pdo_result extends CI_DB_result {
*/
public function field_data()
{
- $data = array();
-
try
{
- if (strpos($this->result_id->queryString, 'PRAGMA') !== FALSE)
- {
- foreach ($this->result_array() as $field)
- {
- preg_match('/([a-zA-Z]+)(\(\d+\))?/', $field['type'], $matches);
-
- $F = new stdClass();
- $F->name = $field['name'];
- $F->type = ( ! empty($matches[1])) ? $matches[1] : NULL;
- $F->default = NULL;
- $F->max_length = ( ! empty($matches[2])) ? preg_replace('/[^\d]/', '', $matches[2]) : NULL;
- $F->primary_key = (int) $field['pk'];
- $F->pdo_type = NULL;
+ $retval = array();
- $data[] = $F;
- }
- }
- else
+ for ($i = 0, $c = $this->num_fields(); $i < $c; $i++)
{
- for($i = 0, $max = $this->num_fields(); $i < $max; $i++)
- {
- $field = $this->result_id->getColumnMeta($i);
-
- $F = new stdClass();
- $F->name = $field['name'];
- $F->type = $field['native_type'];
- $F->default = NULL;
- $F->pdo_type = $field['pdo_type'];
-
- if ($field['precision'] < 0)
- {
- $F->max_length = NULL;
- $F->primary_key = 0;
- }
- else
- {
- $F->max_length = ($field['len'] > 255) ? 0 : $field['len'];
- $F->primary_key = (int) ( ! empty($field['flags']) && in_array('primary_key', $field['flags']));
- }
+ $field = $this->result_id->getColumnMeta($i);
- $data[] = $F;
- }
+ $retval[$i] = new stdClass();
+ $retval[$i]->name = $field['name'];
+ $retval[$i]->type = $field['native_type'];
+ $retval[$i]->max_length = ($field['len'] > 0) ? $field['len'] : NULL;
+ $retval[$i]->primary_key = (int) ( ! empty($field['flags']) && in_array('primary_key', $field['flags'], TRUE));
}
- return $data;
+ return $retval;
}
catch (Exception $e)
{
if ($this->db->db_debug)
{
- return $this->db->display_error('db_unsuported_feature');
+ return $this->db->display_error('db_unsupported_feature');
}
return FALSE;
@@ -245,11 +173,12 @@ class CI_DB_pdo_result extends CI_DB_result {
*
* Returns the result set as an object
*
+ * @param string $class_name
* @return object
*/
- protected function _fetch_object()
+ protected function _fetch_object($class_name = 'stdClass')
{
- return $this->result_id->fetchObject();
+ return $this->result_id->fetchObject($class_name);
}
}
diff --git a/system/database/drivers/pdo/pdo_utility.php b/system/database/drivers/pdo/pdo_utility.php
index 930842118..86f2b120a 100644
--- a/system/database/drivers/pdo/pdo_utility.php
+++ b/system/database/drivers/pdo/pdo_utility.php
@@ -1,4 +1,4 @@
-<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');
+<?php
/**
* CodeIgniter
*
@@ -24,6 +24,7 @@
* @since Version 2.1.0
* @filesource
*/
+defined('BASEPATH') OR exit('No direct script access allowed');
/**
* PDO Utility Class
@@ -34,18 +35,16 @@
*/
class CI_DB_pdo_utility extends CI_DB_utility {
- protected $_list_databases = FALSE;
-
/**
- * PDO Export
+ * Export
*
- * @param array Preferences
+ * @param array $params Preferences
* @return mixed
*/
protected function _backup($params = array())
{
// Currently unsupported
- return $this->db->display_error('db_unsuported_feature');
+ return $this->db->display_error('db_unsupported_feature');
}
}
diff --git a/system/database/drivers/pdo/subdrivers/index.html b/system/database/drivers/pdo/subdrivers/index.html
new file mode 100644
index 000000000..c942a79ce
--- /dev/null
+++ b/system/database/drivers/pdo/subdrivers/index.html
@@ -0,0 +1,10 @@
+<html>
+<head>
+ <title>403 Forbidden</title>
+</head>
+<body>
+
+<p>Directory access is forbidden.</p>
+
+</body>
+</html> \ No newline at end of file
diff --git a/system/database/drivers/pdo/subdrivers/pdo_4d_driver.php b/system/database/drivers/pdo/subdrivers/pdo_4d_driver.php
new file mode 100644
index 000000000..6ebd92a9b
--- /dev/null
+++ b/system/database/drivers/pdo/subdrivers/pdo_4d_driver.php
@@ -0,0 +1,192 @@
+<?php
+/**
+ * CodeIgniter
+ *
+ * An open source application development framework for PHP 5.2.4 or newer
+ *
+ * NOTICE OF LICENSE
+ *
+ * Licensed under the Open Software License version 3.0
+ *
+ * This source file is subject to the Open Software License (OSL 3.0) that is
+ * bundled with this package in the files license.txt / license.rst. It is
+ * also available through the world wide web at this URL:
+ * http://opensource.org/licenses/OSL-3.0
+ * If you did not receive a copy of the license and are unable to obtain it
+ * through the world wide web, please send an email to
+ * licensing@ellislab.com so we can send you a copy immediately.
+ *
+ * @package CodeIgniter
+ * @author EllisLab Dev Team
+ * @copyright Copyright (c) 2008 - 2012, EllisLab, Inc. (http://ellislab.com/)
+ * @license http://opensource.org/licenses/OSL-3.0 Open Software License (OSL 3.0)
+ * @link http://codeigniter.com
+ * @since Version 3.0.0
+ * @filesource
+ */
+defined('BASEPATH') OR exit('No direct script access allowed');
+
+/**
+ * PDO 4D Database Adapter Class
+ *
+ * Note: _DB is an extender class that the app controller
+ * creates dynamically based on whether the query builder
+ * class is being used or not.
+ *
+ * @package CodeIgniter
+ * @subpackage Drivers
+ * @category Database
+ * @author EllisLab Dev Team
+ * @link http://codeigniter.com/user_guide/database/
+ */
+class CI_DB_pdo_4d_driver extends CI_DB_pdo_driver {
+
+ /**
+ * Sub-driver
+ *
+ * @var string
+ */
+ public $subdriver = '4d';
+
+ /**
+ * Identifier escape character
+ *
+ * @var string[]
+ */
+ protected $_escape_char = array('[', ']');
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Class constructor
+ *
+ * Builds the DSN if not already set.
+ *
+ * @param array $params
+ * @return void
+ */
+ public function __construct($params)
+ {
+ parent::__construct($params);
+
+ if (empty($this->dsn))
+ {
+ $this->dsn = '4D:host='.(empty($this->hostname) ? '127.0.0.1' : $this->hostname);
+
+ empty($this->port) OR $this->dsn .= ';port='.$this->port;
+ empty($this->database) OR $this->dsn .= ';dbname='.$this->database;
+ empty($this->char_set) OR $this->dsn .= ';charset='.$this->char_set;
+ }
+ elseif ( ! empty($this->char_set) && strpos($this->dsn, 'charset=', 3) === FALSE)
+ {
+ $this->dsn .= ';charset='.$this->char_set;
+ }
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Show table query
+ *
+ * Generates a platform-specific query string so that the table names can be fetched
+ *
+ * @param bool $prefix_limit
+ * @return string
+ */
+ protected function _list_tables($prefix_limit = FALSE)
+ {
+ $sql = 'SELECT '.$this->escape_identifiers('TABLE_NAME').' FROM '.$this->escape_identifiers('_USER_TABLES');
+
+ if ($prefix_limit === TRUE && $this->dbprefix !== '')
+ {
+ $sql .= ' WHERE '.$this->escape_identifiers('TABLE_NAME')." LIKE '".$this->escape_like_str($this->dbprefix)."%' "
+ .sprintf($this->_like_escape_str, $this->_like_escape_chr);
+ }
+
+ return $sql;
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Show column query
+ *
+ * Generates a platform-specific query string so that the column names can be fetched
+ *
+ * @param string $table
+ * @return string
+ */
+ protected function _list_columns($table = '')
+ {
+ return 'SELECT '.$this->escape_identifiers('COLUMN_NAME').' FROM '.$this->escape_identifiers('_USER_COLUMNS')
+ .' WHERE '.$this->escape_identifiers('TABLE_NAME').' = '.$this->escape($table);
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Field data query
+ *
+ * Generates a platform-specific query so that the column data can be retrieved
+ *
+ * @param string $table
+ * @return string
+ */
+ protected function _field_data($table)
+ {
+ return 'SELECT * FROM '.$this->protect_identifiers($table, TRUE, NULL, FALSE).' LIMIT 1';
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Update statement
+ *
+ * Generates a platform-specific update string from the supplied data
+ *
+ * @param string $table
+ * @param array $values
+ * @return string
+ */
+ protected function _update($table, $values)
+ {
+ $this->qb_limit = FALSE;
+ $this->qb_orderby = array();
+ return parent::_update($table, $values);
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Delete statement
+ *
+ * Generates a platform-specific delete string from the supplied data
+ *
+ * @param string $table
+ * @return string
+ */
+ protected function _delete($table)
+ {
+ $this->qb_limit = FALSE;
+ return parent::_delete($table);
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * LIMIT
+ *
+ * Generates a platform-specific LIMIT clause
+ *
+ * @param string $sql SQL Query
+ * @return string
+ */
+ protected function _limit($sql)
+ {
+ return $sql.' LIMIT '.$this->qb_limit.($this->qb_offset ? ' OFFSET '.$this->qb_offset : '');
+ }
+
+}
+
+/* End of file pdo_4d_driver.php */
+/* Location: ./system/database/drivers/pdo/subdrivers/pdo_4d_driver.php */ \ No newline at end of file
diff --git a/system/database/drivers/pdo/subdrivers/pdo_4d_forge.php b/system/database/drivers/pdo/subdrivers/pdo_4d_forge.php
new file mode 100644
index 000000000..231ad53a4
--- /dev/null
+++ b/system/database/drivers/pdo/subdrivers/pdo_4d_forge.php
@@ -0,0 +1,209 @@
+<?php
+/**
+ * CodeIgniter
+ *
+ * An open source application development framework for PHP 5.2.4 or newer
+ *
+ * NOTICE OF LICENSE
+ *
+ * Licensed under the Open Software License version 3.0
+ *
+ * This source file is subject to the Open Software License (OSL 3.0) that is
+ * bundled with this package in the files license.txt / license.rst. It is
+ * also available through the world wide web at this URL:
+ * http://opensource.org/licenses/OSL-3.0
+ * If you did not receive a copy of the license and are unable to obtain it
+ * through the world wide web, please send an email to
+ * licensing@ellislab.com so we can send you a copy immediately.
+ *
+ * @package CodeIgniter
+ * @author EllisLab Dev Team
+ * @copyright Copyright (c) 2008 - 2012, EllisLab, Inc. (http://ellislab.com/)
+ * @license http://opensource.org/licenses/OSL-3.0 Open Software License (OSL 3.0)
+ * @link http://codeigniter.com
+ * @since Version 2.1.0
+ * @filesource
+ */
+defined('BASEPATH') OR exit('No direct script access allowed');
+
+/**
+ * PDO 4D Forge Class
+ *
+ * @category Database
+ * @author EllisLab Dev Team
+ * @link http://codeigniter.com/user_guide/database/
+ */
+class CI_DB_pdo_4d_forge extends CI_DB_4d_forge {
+
+ /**
+ * CREATE DATABASE statement
+ *
+ * @var string
+ */
+ protected $_create_database = 'CREATE SCHEMA %s';
+
+ /**
+ * DROP DATABASE statement
+ *
+ * @var string
+ */
+ protected $_drop_database = 'DROP SCHEMA %s';
+
+ /**
+ * CREATE TABLE IF statement
+ *
+ * @var string
+ */
+ protected $_create_table_if = 'CREATE TABLE IF NOT EXISTS';
+
+ /**
+ * RENAME TABLE statement
+ *
+ * @var string
+ */
+ protected $_rename_table = FALSE;
+
+ /**
+ * DROP TABLE IF statement
+ *
+ * @var string
+ */
+ protected $_drop_table_if = 'DROP TABLE IF EXISTS';
+
+ /**
+ * UNSIGNED support
+ *
+ * @var array
+ */
+ protected $_unsigned = array(
+ 'INT16' => 'INT',
+ 'SMALLINT' => 'INT',
+ 'INT' => 'INT64',
+ 'INT32' => 'INT64'
+ );
+
+ /**
+ * DEFAULT value representation in CREATE/ALTER TABLE statements
+ *
+ * @var string
+ */
+ protected $_default = FALSE;
+
+ // --------------------------------------------------------------------
+
+ /**
+ * ALTER TABLE
+ *
+ * @param string $alter_type ALTER type
+ * @param string $table Table name
+ * @param mixed $field Column definition
+ * @return string|string[]
+ */
+ protected function _alter_table($alter_type, $table, $field)
+ {
+ if (in_array($alter_type, array('ADD', 'DROP'), TRUE))
+ {
+ return parent::_alter_table($alter_table, $table, $field);
+ }
+
+ // No method of modifying columns is supported
+ return FALSE;
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Process column
+ *
+ * @param array $field
+ * @return string
+ */
+ protected function _process_column($field)
+ {
+ return $this->db->escape_identifiers($field['name'])
+ .' '.$field['type'].$field['length']
+ .$field['null']
+ .$field['unique']
+ .$field['auto_increment'];
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Field attribute TYPE
+ *
+ * Performs a data type mapping between different databases.
+ *
+ * @param array &$attributes
+ * @return void
+ */
+ protected function _attr_type(&$attributes)
+ {
+ switch (strtoupper($attributes['TYPE']))
+ {
+ case 'TINYINT':
+ $attributes['TYPE'] = 'SMALLINT';
+ $attributes['UNSIGNED'] = FALSE;
+ return;
+ case 'MEDIUMINT':
+ $attributes['TYPE'] = 'INTEGER';
+ $attributes['UNSIGNED'] = FALSE;
+ return;
+ case 'INTEGER':
+ $attributes['TYPE'] = 'INT';
+ return;
+ case 'BIGINT':
+ $attribites['TYPE'] = 'INT64';
+ return;
+ default: return;
+ }
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Field attribute UNIQUE
+ *
+ * @param array &$attributes
+ * @param array &$field
+ * @return void
+ */
+ protected function _attr_unique(&$attributes, &$field)
+ {
+ if ( ! empty($attributes['UNIQUE']) && $attributes['UNIQUE'] === TRUE)
+ {
+ $field['unique'] = ' UNIQUE';
+
+ // UNIQUE must be used with NOT NULL
+ $field['null'] = ' NOT NULL';
+ }
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Field attribute AUTO_INCREMENT
+ *
+ * @param array &$attributes
+ * @param array &$field
+ * @return void
+ */
+ protected function _attr_auto_increment(&$attributes, &$field)
+ {
+ if ( ! empty($attributes['AUTO_INCREMENT']) && $attributes['AUTO_INCREMENT'] === TRUE)
+ {
+ if (stripos($field['type'], 'int') !== FALSE)
+ {
+ $field['auto_increment'] = ' AUTO_INCREMENT';
+ }
+ elseif (strcasecmp($field['type'], 'UUID') === 0)
+ {
+ $field['auto_increment'] = ' AUTO_GENERATE';
+ }
+ }
+ }
+
+}
+
+/* End of file pdo_4d_forge.php */
+/* Location: ./system/database/drivers/pdo/subdrivers/pdo_4d_forge.php */ \ No newline at end of file
diff --git a/system/database/drivers/pdo/subdrivers/pdo_cubrid_driver.php b/system/database/drivers/pdo/subdrivers/pdo_cubrid_driver.php
new file mode 100644
index 000000000..7e703e7b5
--- /dev/null
+++ b/system/database/drivers/pdo/subdrivers/pdo_cubrid_driver.php
@@ -0,0 +1,247 @@
+<?php
+/**
+ * CodeIgniter
+ *
+ * An open source application development framework for PHP 5.2.4 or newer
+ *
+ * NOTICE OF LICENSE
+ *
+ * Licensed under the Open Software License version 3.0
+ *
+ * This source file is subject to the Open Software License (OSL 3.0) that is
+ * bundled with this package in the files license.txt / license.rst. It is
+ * also available through the world wide web at this URL:
+ * http://opensource.org/licenses/OSL-3.0
+ * If you did not receive a copy of the license and are unable to obtain it
+ * through the world wide web, please send an email to
+ * licensing@ellislab.com so we can send you a copy immediately.
+ *
+ * @package CodeIgniter
+ * @author EllisLab Dev Team
+ * @copyright Copyright (c) 2008 - 2012, EllisLab, Inc. (http://ellislab.com/)
+ * @license http://opensource.org/licenses/OSL-3.0 Open Software License (OSL 3.0)
+ * @link http://codeigniter.com
+ * @since Version 3.0.0
+ * @filesource
+ */
+defined('BASEPATH') OR exit('No direct script access allowed');
+
+/**
+ * PDO CUBRID Database Adapter Class
+ *
+ * Note: _DB is an extender class that the app controller
+ * creates dynamically based on whether the query builder
+ * class is being used or not.
+ *
+ * @package CodeIgniter
+ * @subpackage Drivers
+ * @category Database
+ * @author EllisLab Dev Team
+ * @link http://codeigniter.com/user_guide/database/
+ */
+class CI_DB_pdo_cubrid_driver extends CI_DB_pdo_driver {
+
+ /**
+ * Sub-driver
+ *
+ * @var string
+ */
+ public $subdriver = 'cubrid';
+
+ /**
+ * Identifier escape character
+ *
+ * @var string
+ */
+ protected $_escape_char = '`';
+
+ /**
+ * ORDER BY random keyword
+ *
+ * @var array
+ */
+ protected $_random_keyword = array('RANDOM()', 'RANDOM(%d)');
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Class constructor
+ *
+ * Builds the DSN if not already set.
+ *
+ * @param array $params
+ * @return void
+ */
+ public function __construct($params)
+ {
+ parent::__construct($params);
+
+ if (empty($this->dsn))
+ {
+ $this->dsn = 'cubrid:host='.(empty($this->hostname) ? '127.0.0.1' : $this->hostname);
+
+ empty($this->port) OR $this->dsn .= ';port='.$this->port;
+ empty($this->database) OR $this->dsn .= ';dbname='.$this->database;
+ empty($this->char_set) OR $this->dsn .= ';charset='.$this->char_set;
+ }
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Show table query
+ *
+ * Generates a platform-specific query string so that the table names can be fetched
+ *
+ * @param bool $prefix_limit
+ * @return string
+ */
+ protected function _list_tables($prefix_limit = FALSE)
+ {
+ $sql = 'SHOW TABLES';
+
+ if ($prefix_limit === TRUE && $this->dbprefix !== '')
+ {
+ return $sql." LIKE '".$this->escape_like_str($this->dbprefix)."%'";
+ }
+
+ return $sql;
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Show column query
+ *
+ * Generates a platform-specific query string so that the column names can be fetched
+ *
+ * @param string $table
+ * @return string
+ */
+ protected function _list_columns($table = '')
+ {
+ return 'SHOW COLUMNS FROM '.$this->protect_identifiers($table, TRUE, NULL, FALSE);
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Returns an object with field data
+ *
+ * @param string $table
+ * @return array
+ */
+ public function field_data($table = '')
+ {
+ if ($table === '')
+ {
+ return ($this->db_debug) ? $this->display_error('db_field_param_missing') : FALSE;
+ }
+
+ if (($query = $this->query('SHOW COLUMNS FROM '.$this->protect_identifiers($table, TRUE, NULL, FALSE))) === FALSE)
+ {
+ return FALSE;
+ }
+ $query = $query->result_object();
+
+ $retval = array();
+ for ($i = 0, $c = count($query); $i < $c; $i++)
+ {
+ $retval[$i] = new stdClass();
+ $retval[$i]->name = $query[$i]->Field;
+
+ sscanf($query[$i]->Type, '%[a-z](%d)',
+ $retval[$i]->type,
+ $retval[$i]->max_length
+ );
+
+ $retval[$i]->default = $query[$i]->Default;
+ $retval[$i]->primary_key = (int) ($query[$i]->Key === 'PRI');
+ }
+
+ return $retval;
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Update_Batch statement
+ *
+ * Generates a platform-specific batch update string from the supplied data
+ *
+ * @param string $table Table name
+ * @param array $values Update data
+ * @param string $index WHERE key
+ * @return string
+ */
+ protected function _update_batch($table, $values, $index)
+ {
+ $ids = array();
+ foreach ($values as $key => $val)
+ {
+ $ids[] = $val[$index];
+
+ foreach (array_keys($val) as $field)
+ {
+ if ($field !== $index)
+ {
+ $final[$field][] = 'WHEN '.$index.' = '.$val[$index].' THEN '.$val[$field];
+ }
+ }
+ }
+
+ $cases = '';
+ foreach ($final as $k => $v)
+ {
+ $cases .= $k." = CASE \n"
+ .implode("\n", $v)."\n"
+ .'ELSE '.$k.' END), ';
+ }
+
+ $this->where($index.' IN('.implode(',', $ids).')', NULL, FALSE);
+
+ return 'UPDATE '.$table.' SET '.substr($cases, 0, -2).$this->_compile_wh('qb_where');
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Truncate statement
+ *
+ * Generates a platform-specific truncate string from the supplied data
+ *
+ * If the database does not support the TRUNCATE statement,
+ * then this method maps to 'DELETE FROM table'
+ *
+ * @param string $table
+ * @return string
+ */
+ protected function _truncate($table)
+ {
+ return 'TRUNCATE '.$table;
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * FROM tables
+ *
+ * Groups tables in FROM clauses if needed, so there is no confusion
+ * about operator precedence.
+ *
+ * @return string
+ */
+ protected function _from_tables()
+ {
+ if ( ! empty($this->qb_join) && count($this->qb_from) > 1)
+ {
+ return '('.implode(', ', $this->qb_from).')';
+ }
+
+ return implode(', ', $this->qb_from);
+ }
+
+}
+
+/* End of file pdo_cubrid_driver.php */
+/* Location: ./system/database/drivers/pdo/subdrivers/pdo_cubrid_driver.php */ \ No newline at end of file
diff --git a/system/database/drivers/pdo/subdrivers/pdo_cubrid_forge.php b/system/database/drivers/pdo/subdrivers/pdo_cubrid_forge.php
new file mode 100644
index 000000000..ebf4b15d6
--- /dev/null
+++ b/system/database/drivers/pdo/subdrivers/pdo_cubrid_forge.php
@@ -0,0 +1,219 @@
+<?php
+/**
+ * CodeIgniter
+ *
+ * An open source application development framework for PHP 5.2.4 or newer
+ *
+ * NOTICE OF LICENSE
+ *
+ * Licensed under the Open Software License version 3.0
+ *
+ * This source file is subject to the Open Software License (OSL 3.0) that is
+ * bundled with this package in the files license.txt / license.rst. It is
+ * also available through the world wide web at this URL:
+ * http://opensource.org/licenses/OSL-3.0
+ * If you did not receive a copy of the license and are unable to obtain it
+ * through the world wide web, please send an email to
+ * licensing@ellislab.com so we can send you a copy immediately.
+ *
+ * @package CodeIgniter
+ * @author EllisLab Dev Team
+ * @copyright Copyright (c) 2008 - 2012, EllisLab, Inc. (http://ellislab.com/)
+ * @license http://opensource.org/licenses/OSL-3.0 Open Software License (OSL 3.0)
+ * @link http://codeigniter.com
+ * @since Version 2.1.0
+ * @filesource
+ */
+defined('BASEPATH') OR exit('No direct script access allowed');
+
+/**
+ * PDO CUBRID Forge Class
+ *
+ * @category Database
+ * @author EllisLab Dev Team
+ * @link http://codeigniter.com/user_guide/database/
+ */
+class CI_DB_pdo_cubrid_forge extends CI_DB_pdo_forge {
+
+ /**
+ * CREATE DATABASE statement
+ *
+ * @var string
+ */
+ protected $_create_database = FALSE;
+
+ /**
+ * DROP DATABASE statement
+ *
+ * @var string
+ */
+ protected $_drop_database = FALSE;
+
+ /**
+ * CREATE TABLE keys flag
+ *
+ * Whether table keys are created from within the
+ * CREATE TABLE statement.
+ *
+ * @var bool
+ */
+ protected $_create_table_keys = TRUE;
+
+ /**
+ * DROP TABLE IF statement
+ *
+ * @var string
+ */
+ protected $_drop_table_if = 'DROP TABLE IF EXISTS';
+
+ /**
+ * UNSIGNED support
+ *
+ * @var array
+ */
+ protected $_unsigned = array(
+ 'SHORT' => 'INTEGER',
+ 'SMALLINT' => 'INTEGER',
+ 'INT' => 'BIGINT',
+ 'INTEGER' => 'BIGINT',
+ 'BIGINT' => 'NUMERIC',
+ 'FLOAT' => 'DOUBLE',
+ 'REAL' => 'DOUBLE'
+ );
+
+ // --------------------------------------------------------------------
+
+ /**
+ * ALTER TABLE
+ *
+ * @param string $alter_type ALTER type
+ * @param string $table Table name
+ * @param mixed $field Column definition
+ * @return string|string[]
+ */
+ protected function _alter_table($alter_type, $table, $field)
+ {
+ if (in_array($alter_type, array('DROP', 'ADD'), TRUE))
+ {
+ return parent::_alter_table($alter_type, $table, $field);
+ }
+
+ $sql = 'ALTER TABLE '.$this->db->escape_identifiers($table);
+ $sqls = array();
+ for ($i = 0, $c = count($field); $i < $c; $i++)
+ {
+ if ($field[$i]['_literal'] !== FALSE)
+ {
+ $sqls[] = $sql.' CHANGE '.$field[$i]['_literal'];
+ }
+ else
+ {
+ $alter_type = empty($field[$i]['new_name']) ? ' MODIFY ' : ' CHANGE ';
+ $sqls[] = $sql.$alter_type.$this->_process_column($field[$i]);
+ }
+ }
+
+ return $sqls;
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Process column
+ *
+ * @param array $field
+ * @return string
+ */
+ protected function _process_column($field)
+ {
+ $extra_clause = isset($field['after'])
+ ? ' AFTER '.$this->db->escape_identifiers($field['after']) : '';
+
+ if (empty($extra_clause) && isset($field['first']) && $field['first'] === TRUE)
+ {
+ $extra_clause = ' FIRST';
+ }
+
+ return $this->db->escape_identifiers($field['name'])
+ .(empty($field['new_name']) ? '' : ' '.$this->db->escape_identifiers($field['new_name']))
+ .' '.$field['type'].$field['length']
+ .$field['unsigned']
+ .$field['null']
+ .$field['default']
+ .$field['auto_increment']
+ .$field['unique']
+ .$extra_clause;
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Field attribute TYPE
+ *
+ * Performs a data type mapping between different databases.
+ *
+ * @param array &$attributes
+ * @return void
+ */
+ protected function _attr_type(&$attributes)
+ {
+ switch (strtoupper($attributes['TYPE']))
+ {
+ case 'TINYINT':
+ $attributes['TYPE'] = 'SMALLINT';
+ $attributes['UNSIGNED'] = FALSE;
+ return;
+ case 'MEDIUMINT':
+ $attributes['TYPE'] = 'INTEGER';
+ $attributes['UNSIGNED'] = FALSE;
+ return;
+ default: return;
+ }
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Process indexes
+ *
+ * @param string $table (ignored)
+ * @return string
+ */
+ protected function _process_indexes($table)
+ {
+ $sql = '';
+
+ for ($i = 0, $c = count($this->keys); $i < $c; $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;
+ }
+
+ is_array($this->keys[$i]) OR $this->keys[$i] = array($this->keys[$i]);
+
+ $sql .= ",\n\tKEY ".$this->db->escape_identifiers(implode('_', $this->keys[$i]))
+ .' ('.implode(', ', $this->db->escape_identifiers($this->keys[$i])).')';
+ }
+
+ $this->keys = array();
+
+ return $sql;
+ }
+
+}
+
+/* End of file pdo_cubrid_forge.php */
+/* Location: ./system/database/drivers/pdo/subdrivers/pdo_cubrid_forge.php */ \ No newline at end of file
diff --git a/system/database/drivers/pdo/subdrivers/pdo_dblib_driver.php b/system/database/drivers/pdo/subdrivers/pdo_dblib_driver.php
new file mode 100644
index 000000000..cf049b61d
--- /dev/null
+++ b/system/database/drivers/pdo/subdrivers/pdo_dblib_driver.php
@@ -0,0 +1,329 @@
+<?php
+/**
+ * CodeIgniter
+ *
+ * An open source application development framework for PHP 5.2.4 or newer
+ *
+ * NOTICE OF LICENSE
+ *
+ * Licensed under the Open Software License version 3.0
+ *
+ * This source file is subject to the Open Software License (OSL 3.0) that is
+ * bundled with this package in the files license.txt / license.rst. It is
+ * also available through the world wide web at this URL:
+ * http://opensource.org/licenses/OSL-3.0
+ * If you did not receive a copy of the license and are unable to obtain it
+ * through the world wide web, please send an email to
+ * licensing@ellislab.com so we can send you a copy immediately.
+ *
+ * @package CodeIgniter
+ * @author EllisLab Dev Team
+ * @copyright Copyright (c) 2008 - 2012, EllisLab, Inc. (http://ellislab.com/)
+ * @license http://opensource.org/licenses/OSL-3.0 Open Software License (OSL 3.0)
+ * @link http://codeigniter.com
+ * @since Version 3.0.0
+ * @filesource
+ */
+defined('BASEPATH') OR exit('No direct script access allowed');
+
+/**
+ * PDO DBLIB Database Adapter Class
+ *
+ * Note: _DB is an extender class that the app controller
+ * creates dynamically based on whether the query builder
+ * class is being used or not.
+ *
+ * @package CodeIgniter
+ * @subpackage Drivers
+ * @category Database
+ * @author EllisLab Dev Team
+ * @link http://codeigniter.com/user_guide/database/
+ */
+class CI_DB_pdo_dblib_driver extends CI_DB_pdo_driver {
+
+ /**
+ * Sub-driver
+ *
+ * @var string
+ */
+ public $subdriver = 'dblib';
+
+ // --------------------------------------------------------------------
+
+ /**
+ * ORDER BY random keyword
+ *
+ * @var array
+ */
+ protected $_random_keyword = array('NEWID()', 'RAND(%d)');
+
+ /**
+ * Quoted identifier flag
+ *
+ * Whether to use SQL-92 standard quoted identifier
+ * (double quotes) or brackets for identifier escaping.
+ *
+ * @var bool
+ */
+ protected $_quoted_identifier;
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Class constructor
+ *
+ * Builds the DSN if not already set.
+ *
+ * @param array $params
+ * @return void
+ */
+ public function __construct($params)
+ {
+ parent::__construct($params);
+
+ if (empty($this->dsn))
+ {
+ $this->dsn = $params['subdriver'].':host='.(empty($this->hostname) ? '127.0.0.1' : $this->hostname);
+
+ if ( ! empty($this->port))
+ {
+ $this->dsn .= (DIRECTORY_SEPARATOR === '\\' ? ',' : ':').$this->port;
+ }
+
+ empty($this->database) OR $this->dsn .= ';dbname='.$this->database;
+ empty($this->char_set) OR $this->dsn .= ';charset='.$this->char_set;
+ empty($this->appname) OR $this->dsn .= ';appname='.$this->appname;
+ }
+ else
+ {
+ if ( ! empty($this->char_set) && strpos($this->dsn, 'charset=', 6) === FALSE)
+ {
+ $this->dsn .= ';charset='.$this->char_set;
+ }
+
+ $this->subdriver = 'dblib';
+ }
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Database connection
+ *
+ * @param bool $persistent
+ * @return object
+ */
+ public function db_connect($persistent = FALSE)
+ {
+ $this->conn_id = parent::db_connect($persistent);
+
+ if ( ! is_object($this->conn_id))
+ {
+ return $this->conn_id;
+ }
+
+ // Determine how identifiers are escaped
+ $query = $this->query('SELECT CASE WHEN (@@OPTIONS | 256) = @@OPTIONS THEN 1 ELSE 0 END AS qi');
+ $query = $query->row_array();
+ $this->_quoted_identifier = empty($query) ? FALSE : (bool) $query['qi'];
+ $this->_escape_char = ($this->_quoted_identifier) ? '"' : array('[', ']');
+
+ return $this->conn_id;
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Show table query
+ *
+ * Generates a platform-specific query string so that the table names can be fetched
+ *
+ * @param bool $prefix_limit
+ * @return string
+ */
+ protected function _list_tables($prefix_limit = FALSE)
+ {
+ return 'SELECT '.$this->escape_identifiers('name')
+ .' FROM '.$this->escape_identifiers('sysobjects')
+ .' WHERE '.$this->escape_identifiers('type')." = 'U'";
+
+ if ($prefix_limit === TRUE && $this->dbprefix !== '')
+ {
+ $sql .= ' AND '.$this->escape_identifiers('name')." LIKE '".$this->escape_like_str($this->dbprefix)."%' "
+ .sprintf($this->_like_escape_str, $this->_like_escape_chr);
+ }
+
+ return $sql.' ORDER BY '.$this->escape_identifiers('name');
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Show column query
+ *
+ * Generates a platform-specific query string so that the column names can be fetched
+ *
+ * @param string $table
+ * @return string
+ */
+ protected function _list_columns($table = '')
+ {
+ return 'SELECT COLUMN_NAME
+ FROM INFORMATION_SCHEMA.Columns
+ WHERE UPPER(TABLE_NAME) = '.$this->escape(strtoupper($table));
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Returns an object with field data
+ *
+ * @param string $table
+ * @return array
+ */
+ public function field_data($table = '')
+ {
+ if ($table === '')
+ {
+ return ($this->db_debug) ? $this->display_error('db_field_param_missing') : FALSE;
+ }
+
+ $sql = 'SELECT COLUMN_NAME, DATA_TYPE, CHARACTER_MAXIMUM_LENGTH, NUMERIC_PRECISION, COLUMN_DEFAULT
+ FROM INFORMATION_SCHEMA.Columns
+ WHERE UPPER(TABLE_NAME) = '.$this->escape(strtoupper($table));
+
+ if (($query = $this->query($sql)) === FALSE)
+ {
+ return FALSE;
+ }
+ $query = $query->result_object();
+
+ $retval = array();
+ for ($i = 0, $c = count($query); $i < $c; $i++)
+ {
+ $retval[$i] = new stdClass();
+ $retval[$i]->name = $query[$i]->COLUMN_NAME;
+ $retval[$i]->type = $query[$i]->DATA_TYPE;
+ $retval[$i]->max_length = ($query[$i]->CHARACTER_MAXIMUM_LENGTH > 0) ? $query[$i]->CHARACTER_MAXIMUM_LENGTH : $query[$i]->NUMERIC_PRECISION;
+ $retval[$i]->default = $query[$i]->COLUMN_DEFAULT;
+ }
+
+ return $retval;
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Update statement
+ *
+ * Generates a platform-specific update string from the supplied data
+ *
+ * @param string $table
+ * @param array $values
+ * @return string
+ */
+ protected function _update($table, $values)
+ {
+ $this->qb_limit = FALSE;
+ $this->qb_orderby = array();
+ return parent::_update($table, $values);
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Delete statement
+ *
+ * Generates a platform-specific delete string from the supplied data
+ *
+ * @param string $table
+ * @return string
+ */
+ protected function _delete($table)
+ {
+ if ($this->qb_limit)
+ {
+ return 'WITH ci_delete AS (SELECT TOP '.$this->qb_limit.' * FROM '.$table.$this->_compile_wh('qb_where').') DELETE FROM ci_delete';
+ }
+
+ return parent::_delete($table);
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * LIMIT
+ *
+ * Generates a platform-specific LIMIT clause
+ *
+ * @param string $sql SQL Query
+ * @return string
+ */
+ protected function _limit($sql)
+ {
+ $limit = $this->qb_offset + $this->qb_limit;
+
+ // As of SQL Server 2005 (9.0.*) ROW_NUMBER() is supported,
+ // however an ORDER BY clause is required for it to work
+ if (version_compare($this->version(), '9', '>=') && $this->qb_offset && ! empty($this->qb_orderby))
+ {
+ $orderby = $this->_compile_order_by();
+
+ // We have to strip the ORDER BY clause
+ $sql = trim(substr($sql, 0, strrpos($sql, $orderby)));
+
+ // Get the fields to select from our subquery, so that we can avoid CI_rownum appearing in the actual results
+ if (count($this->qb_select) === 0)
+ {
+ $select = '*'; // Inevitable
+ }
+ else
+ {
+ // Use only field names and their aliases, everything else is out of our scope.
+ $select = array();
+ $field_regexp = ($this->_quoted_identifier)
+ ? '("[^\"]+")' : '(\[[^\]]+\])';
+ for ($i = 0, $c = count($this->qb_select); $i < $c; $i++)
+ {
+ $select[] = preg_match('/(?:\s|\.)'.$field_regexp.'$/i', $this->qb_select[$i], $m)
+ ? $m[1] : $this->qb_select[$i];
+ }
+ $select = implode(', ', $select);
+ }
+
+ return 'SELECT '.$select." FROM (\n\n"
+ .preg_replace('/^(SELECT( DISTINCT)?)/i', '\\1 ROW_NUMBER() OVER('.trim($orderby).') AS '.$this->escape_identifiers('CI_rownum').', ', $sql)
+ ."\n\n) ".$this->escape_identifiers('CI_subquery')
+ ."\nWHERE ".$this->escape_identifiers('CI_rownum').' BETWEEN '.($this->qb_offset + 1).' AND '.$limit;
+ }
+
+ return preg_replace('/(^\SELECT (DISTINCT)?)/i','\\1 TOP '.$limit.' ', $sql);
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Insert batch statement
+ *
+ * Generates a platform-specific insert string from the supplied data.
+ *
+ * @param string $table Table name
+ * @param array $keys INSERT keys
+ * @param array $values INSERT values
+ * @return string|bool
+ */
+ protected function _insert_batch($table, $keys, $values)
+ {
+ // Multiple-value inserts are only supported as of SQL Server 2008
+ if (version_compare($this->version(), '10', '>='))
+ {
+ return parent::_insert_batch($table, $keys, $values);
+ }
+
+ return ($this->db->db_debug) ? $this->db->display_error('db_unsupported_feature') : FALSE;
+ }
+
+}
+
+/* End of file pdo_dblib_driver.php */
+/* Location: ./system/database/drivers/pdo/subdrivers/pdo_dblib_driver.php */ \ No newline at end of file
diff --git a/system/database/drivers/pdo/subdrivers/pdo_dblib_forge.php b/system/database/drivers/pdo/subdrivers/pdo_dblib_forge.php
new file mode 100644
index 000000000..236e1cce2
--- /dev/null
+++ b/system/database/drivers/pdo/subdrivers/pdo_dblib_forge.php
@@ -0,0 +1,136 @@
+<?php
+/**
+ * CodeIgniter
+ *
+ * An open source application development framework for PHP 5.2.4 or newer
+ *
+ * NOTICE OF LICENSE
+ *
+ * Licensed under the Open Software License version 3.0
+ *
+ * This source file is subject to the Open Software License (OSL 3.0) that is
+ * bundled with this package in the files license.txt / license.rst. It is
+ * also available through the world wide web at this URL:
+ * http://opensource.org/licenses/OSL-3.0
+ * If you did not receive a copy of the license and are unable to obtain it
+ * through the world wide web, please send an email to
+ * licensing@ellislab.com so we can send you a copy immediately.
+ *
+ * @package CodeIgniter
+ * @author EllisLab Dev Team
+ * @copyright Copyright (c) 2008 - 2012, EllisLab, Inc. (http://ellislab.com/)
+ * @license http://opensource.org/licenses/OSL-3.0 Open Software License (OSL 3.0)
+ * @link http://codeigniter.com
+ * @since Version 2.1.0
+ * @filesource
+ */
+defined('BASEPATH') OR exit('No direct script access allowed');
+
+/**
+ * PDO DBLIB Forge Class
+ *
+ * @category Database
+ * @author EllisLab Dev Team
+ * @link http://codeigniter.com/user_guide/database/
+ */
+class CI_DB_pdo_dblib_forge extends CI_DB_pdo_forge {
+
+ /**
+ * CREATE TABLE IF statement
+ *
+ * @var string
+ */
+ protected $_create_table_if = "IF NOT EXISTS (SELECT * FROM sysobjects WHERE ID = object_id(N'%s') AND OBJECTPROPERTY(id, N'IsUserTable') = 1)\nCREATE TABLE";
+
+ /**
+ * DROP TABLE IF statement
+ *
+ * @var string
+ */
+ protected $_drop_table_if = "IF EXISTS (SELECT * FROM sysobjects WHERE ID = object_id(N'%s') AND OBJECTPROPERTY(id, N'IsUserTable') = 1)\nDROP TABLE";
+
+ /**
+ * UNSIGNED support
+ *
+ * @var array
+ */
+ protected $_unsigned = array(
+ 'TINYINT' => 'SMALLINT',
+ 'SMALLINT' => 'INT',
+ 'INT' => 'BIGINT',
+ 'REAL' => 'FLOAT'
+ );
+
+ // --------------------------------------------------------------------
+
+ /**
+ * ALTER TABLE
+ *
+ * @param string $alter_type ALTER type
+ * @param string $table Table name
+ * @param mixed $field Column definition
+ * @return string|string[]
+ */
+ protected function _alter_table($alter_type, $table, $field)
+ {
+ if (in_array($alter_type, array('ADD', 'DROP'), TRUE))
+ {
+ return parent::_alter_table($alter_type, $table, $field);
+ }
+
+ $sql = 'ALTER TABLE '.$this->db->escape_identifiers($table).' ALTER COLUMN ';
+ $sqls = array();
+ for ($i = 0, $c = count($field); $i < $c; $i++)
+ {
+ $sqls[] = $sql.$this->_process_column($field[$i]);
+ }
+
+ return $sqls;
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Field attribute TYPE
+ *
+ * Performs a data type mapping between different databases.
+ *
+ * @param array &$attributes
+ * @return void
+ */
+ protected function _attr_type(&$attributes)
+ {
+ switch (strtoupper($attributes['TYPE']))
+ {
+ case 'MEDIUMINT':
+ $attributes['TYPE'] = 'INTEGER';
+ $attributes['UNSIGNED'] = FALSE;
+ return;
+ case 'INTEGER':
+ $attributes['TYPE'] = 'INT';
+ return;
+ default: return;
+ }
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Field attribute AUTO_INCREMENT
+ *
+ * @param array &$attributes
+ * @param array &$field
+ * @return void
+ */
+ protected function _attr_auto_increment(&$attributes, &$field)
+ {
+ if ( ! empty($attributes['AUTO_INCREMENT']) && $attributes['AUTO_INCREMENT'] === TRUE && stripos($field['type'], 'int') !== FALSE)
+ {
+ $field['auto_increment'] = ' IDENTITY(1,1)';
+ }
+ }
+
+}
+
+/* End of file pdo_dblib_forge.php */
+/* Location: ./system/database/drivers/pdo/subdrivers/pdo_dblib_forge.php */ \ No newline at end of file
diff --git a/system/database/drivers/pdo/subdrivers/pdo_firebird_driver.php b/system/database/drivers/pdo/subdrivers/pdo_firebird_driver.php
new file mode 100644
index 000000000..adac03880
--- /dev/null
+++ b/system/database/drivers/pdo/subdrivers/pdo_firebird_driver.php
@@ -0,0 +1,260 @@
+<?php
+/**
+ * CodeIgniter
+ *
+ * An open source application development framework for PHP 5.2.4 or newer
+ *
+ * NOTICE OF LICENSE
+ *
+ * Licensed under the Open Software License version 3.0
+ *
+ * This source file is subject to the Open Software License (OSL 3.0) that is
+ * bundled with this package in the files license.txt / license.rst. It is
+ * also available through the world wide web at this URL:
+ * http://opensource.org/licenses/OSL-3.0
+ * If you did not receive a copy of the license and are unable to obtain it
+ * through the world wide web, please send an email to
+ * licensing@ellislab.com so we can send you a copy immediately.
+ *
+ * @package CodeIgniter
+ * @author EllisLab Dev Team
+ * @copyright Copyright (c) 2008 - 2012, EllisLab, Inc. (http://ellislab.com/)
+ * @license http://opensource.org/licenses/OSL-3.0 Open Software License (OSL 3.0)
+ * @link http://codeigniter.com
+ * @since Version 3.0.0
+ * @filesource
+ */
+defined('BASEPATH') OR exit('No direct script access allowed');
+
+/**
+ * PDO Firebird Database Adapter Class
+ *
+ * Note: _DB is an extender class that the app controller
+ * creates dynamically based on whether the query builder
+ * class is being used or not.
+ *
+ * @package CodeIgniter
+ * @subpackage Drivers
+ * @category Database
+ * @author EllisLab Dev Team
+ * @link http://codeigniter.com/user_guide/database/
+ */
+class CI_DB_pdo_firebird_driver extends CI_DB_pdo_driver {
+
+ /**
+ * Sub-driver
+ *
+ * @var string
+ */
+ public $subdriver = 'firebird';
+
+ // --------------------------------------------------------------------
+
+ /**
+ * ORDER BY random keyword
+ *
+ * @var array
+ */
+ protected $_random_keyword = array('RAND()', 'RAND()');
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Class constructor
+ *
+ * Builds the DSN if not already set.
+ *
+ * @param array $params
+ * @return void
+ */
+ public function __construct($params)
+ {
+ parent::__construct($params);
+
+ if (empty($this->dsn))
+ {
+ $this->dsn = 'firebird:';
+
+ if ( ! empty($this->database))
+ {
+ $this->dsn .= 'dbname='.$this->database;
+ }
+ elseif ( ! empty($this->hostname))
+ {
+ $this->dsn .= 'dbname='.$this->hostname;
+ }
+
+ empty($this->char_set) OR $this->dsn .= ';charset='.$this->char_set;
+ empty($this->role) OR $this->dsn .= ';role='.$this->role;
+ }
+ elseif ( ! empty($this->char_set) && strpos($this->dsn, 'charset=', 9) === FALSE)
+ {
+ $this->dsn .= ';charset='.$this->char_set;
+ }
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Show table query
+ *
+ * Generates a platform-specific query string so that the table names can be fetched
+ *
+ * @param bool $prefix_limit
+ * @return string
+ */
+ protected function _list_tables($prefix_limit = FALSE)
+ {
+ $sql = 'SELECT "RDB$RELATION_NAME" FROM "RDB$RELATIONS" WHERE "RDB$RELATION_NAME" NOT LIKE \'RDB$%\' AND "RDB$RELATION_NAME" NOT LIKE \'MON$%\'';
+
+ if ($prefix_limit === TRUE && $this->dbprefix !== '')
+ {
+ return $sql.' AND "RDB$RELATION_NAME" LIKE \''.$this->escape_like_str($this->dbprefix)."%' "
+ .sprintf($this->_like_escape_str, $this->_like_escape_chr);
+ }
+
+ return $sql;
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Show column query
+ *
+ * Generates a platform-specific query string so that the column names can be fetched
+ *
+ * @param string $table
+ * @return string
+ */
+ protected function _list_columns($table = '')
+ {
+ return 'SELECT "RDB$FIELD_NAME" FROM "RDB$RELATION_FIELDS" WHERE "RDB$RELATION_NAME" = '.$this->escape($table);
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Returns an object with field data
+ *
+ * @param string $table
+ * @return array
+ */
+ public function field_data($table = '')
+ {
+ if ($table === '')
+ {
+ return ($this->db_debug) ? $this->display_error('db_field_param_missing') : FALSE;
+ }
+
+ $sql = 'SELECT "rfields"."RDB$FIELD_NAME" AS "name",
+ CASE "fields"."RDB$FIELD_TYPE"
+ WHEN 7 THEN \'SMALLINT\'
+ WHEN 8 THEN \'INTEGER\'
+ WHEN 9 THEN \'QUAD\'
+ WHEN 10 THEN \'FLOAT\'
+ WHEN 11 THEN \'DFLOAT\'
+ WHEN 12 THEN \'DATE\'
+ WHEN 13 THEN \'TIME\'
+ WHEN 14 THEN \'CHAR\'
+ WHEN 16 THEN \'INT64\'
+ WHEN 27 THEN \'DOUBLE\'
+ WHEN 35 THEN \'TIMESTAMP\'
+ WHEN 37 THEN \'VARCHAR\'
+ WHEN 40 THEN \'CSTRING\'
+ WHEN 261 THEN \'BLOB\'
+ ELSE NULL
+ END AS "type",
+ "fields"."RDB$FIELD_LENGTH" AS "max_length",
+ "rfields"."RDB$DEFAULT_VALUE" AS "default"
+ FROM "RDB$RELATION_FIELDS" "rfields"
+ JOIN "RDB$FIELDS" "fields" ON "rfields"."RDB$FIELD_SOURCE" = "fields"."RDB$FIELD_NAME"
+ WHERE "rfields"."RDB$RELATION_NAME" = '.$this->escape($table).'
+ ORDER BY "rfields"."RDB$FIELD_POSITION"';
+
+ return (($query = $this->query($sql)) !== FALSE)
+ ? $query->result_object()
+ : FALSE;
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Update statement
+ *
+ * Generates a platform-specific update string from the supplied data
+ *
+ * @param string $table
+ * @param array $values
+ * @return string
+ */
+ protected function _update($table, $values)
+ {
+ $this->qb_limit = FALSE;
+ return parent::_update($table, $values);
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Truncate statement
+ *
+ * Generates a platform-specific truncate string from the supplied data
+ *
+ * If the database does not support the TRUNCATE statement,
+ * then this method maps to 'DELETE FROM table'
+ *
+ * @param string $table
+ * @return string
+ */
+ protected function _truncate($table)
+ {
+ return 'DELETE FROM '.$table;
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Delete statement
+ *
+ * Generates a platform-specific delete string from the supplied data
+ *
+ * @param string $table
+ * @return string
+ */
+ protected function _delete($table)
+ {
+ $this->qb_limit = FALSE;
+ return parent::_delete($table);
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * LIMIT
+ *
+ * Generates a platform-specific LIMIT clause
+ *
+ * @param string $sql SQL Query
+ * @return string
+ */
+ protected function _limit($sql)
+ {
+ // Limit clause depends on if Interbase or Firebird
+ if (stripos($this->version(), 'firebird') !== FALSE)
+ {
+ $select = 'FIRST '.$this->qb_limit
+ .($this->qb_offset > 0 ? ' SKIP '.$this->qb_offset : '');
+ }
+ else
+ {
+ $select = 'ROWS '
+ .($this->qb_offset > 0 ? $this->qb_offset.' TO '.($this->qb_limit + $this->qb_offset) : $this->qb_limit);
+ }
+
+ return preg_replace('`SELECT`i', 'SELECT '.$select, $sql);
+ }
+
+}
+
+/* End of file pdo_firebird_driver.php */
+/* Location: ./system/database/drivers/pdo/subdrivers/pdo_firebird_driver.php */ \ No newline at end of file
diff --git a/system/database/drivers/pdo/subdrivers/pdo_firebird_forge.php b/system/database/drivers/pdo/subdrivers/pdo_firebird_forge.php
new file mode 100644
index 000000000..7b86de97f
--- /dev/null
+++ b/system/database/drivers/pdo/subdrivers/pdo_firebird_forge.php
@@ -0,0 +1,229 @@
+<?php
+/**
+ * CodeIgniter
+ *
+ * An open source application development framework for PHP 5.2.4 or newer
+ *
+ * NOTICE OF LICENSE
+ *
+ * Licensed under the Open Software License version 3.0
+ *
+ * This source file is subject to the Open Software License (OSL 3.0) that is
+ * bundled with this package in the files license.txt / license.rst. It is
+ * also available through the world wide web at this URL:
+ * http://opensource.org/licenses/OSL-3.0
+ * If you did not receive a copy of the license and are unable to obtain it
+ * through the world wide web, please send an email to
+ * licensing@ellislab.com so we can send you a copy immediately.
+ *
+ * @package CodeIgniter
+ * @author EllisLab Dev Team
+ * @copyright Copyright (c) 2008 - 2012, EllisLab, Inc. (http://ellislab.com/)
+ * @license http://opensource.org/licenses/OSL-3.0 Open Software License (OSL 3.0)
+ * @link http://codeigniter.com
+ * @since Version 2.1.0
+ * @filesource
+ */
+defined('BASEPATH') OR exit('No direct script access allowed');
+
+/**
+ * PDO Firebird Forge Class
+ *
+ * @category Database
+ * @author EllisLab Dev Team
+ * @link http://codeigniter.com/user_guide/database/
+ */
+class CI_DB_pdo_firebird_forge extends CI_DB_pdo_forge {
+
+ /**
+ * RENAME TABLE statement
+ *
+ * @var string
+ */
+ protected $_rename_table = FALSE;
+
+ /**
+ * UNSIGNED support
+ *
+ * @var array
+ */
+ protected $_unsigned = array(
+ 'SMALLINT' => 'INTEGER',
+ 'INTEGER' => 'INT64',
+ 'FLOAT' => 'DOUBLE PRECISION'
+ );
+
+ /**
+ * NULL value representation in CREATE/ALTER TABLE statements
+ *
+ * @var string
+ */
+ protected $_null = 'NULL';
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Create database
+ *
+ * @param string $db_name
+ * @return string
+ */
+ public function create_database($db_name)
+ {
+ // Firebird databases are flat files, so a path is required
+
+ // Hostname is needed for remote access
+ empty($this->db->hostname) OR $db_name = $this->hostname.':'.$db_name;
+
+ return parent::create_database('"'.$db_name.'"');
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Drop database
+ *
+ * @param string $db_name (ignored)
+ * @return bool
+ */
+ public function drop_database($db_name = '')
+ {
+ if ( ! ibase_drop_db($this->conn_id))
+ {
+ return ($this->db->db_debug) ? $this->db->display_error('db_unable_to_drop') : FALSE;
+ }
+ elseif ( ! empty($this->db->data_cache['db_names']))
+ {
+ $key = array_search(strtolower($this->db->database), array_map('strtolower', $this->db->data_cache['db_names']), TRUE);
+ if ($key !== FALSE)
+ {
+ unset($this->db->data_cache['db_names'][$key]);
+ }
+ }
+
+ return TRUE;
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * ALTER TABLE
+ *
+ * @param string $alter_type ALTER type
+ * @param string $table Table name
+ * @param mixed $field Column definition
+ * @return string|string[]
+ */
+ protected function _alter_table($alter_type, $table, $field)
+ {
+ if (in_array($alter_type, array('DROP', 'ADD'), TRUE))
+ {
+ return parent::_alter_table($alter_type, $table, $field);
+ }
+
+ $sql = 'ALTER TABLE '.$this->db->escape_identifiers($table);
+ $sqls = array();
+ for ($i = 0, $c = count($field); $i < $c; $i++)
+ {
+ if ($field[$i]['_literal'] !== FALSE)
+ {
+ return FALSE;
+ }
+
+ if (isset($field[$i]['type']))
+ {
+ $sqls[] = $sql.' ALTER COLUMN '.$this->db->escape_identifiers($field[$i]['name'])
+ .' TYPE '.$field[$i]['type'].$field[$i]['length'];
+ }
+
+ if ( ! empty($field[$i]['default']))
+ {
+ $sqls[] = $sql.' ALTER COLUMN '.$this->db->escape_identifiers($field[$i]['name'])
+ .' SET DEFAULT '.$field[$i]['default'];
+ }
+
+ if (isset($field[$i]['null']))
+ {
+ $sqls[] = 'UPDATE "RDB$RELATION_FIELDS" SET "RDB$NULL_FLAG" = '
+ .($field[$i]['null'] === TRUE ? 'NULL' : '1')
+ .' WHERE "RDB$FIELD_NAME" = '.$this->db->escape($field[$i]['name'])
+ .' AND "RDB$RELATION_NAME" = '.$this->db->escape($table);
+ }
+
+ if ( ! empty($field[$i]['new_name']))
+ {
+ $sqls[] = $sql.' ALTER COLUMN '.$this->db->escape_identifiers($field[$i]['name'])
+ .' TO '.$this->db->escape_identifiers($field[$i]['new_name']);
+ }
+ }
+
+ return $sqls;
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Process column
+ *
+ * @param array $field
+ * @return string
+ */
+ protected function _process_column($field)
+ {
+ return $this->db->escape_identifiers($field['name'])
+ .' '.$field['type'].$field['length']
+ .$field['null']
+ .$field['unique']
+ .$field['default'];
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Field attribute TYPE
+ *
+ * Performs a data type mapping between different databases.
+ *
+ * @param array &$attributes
+ * @return void
+ */
+ protected function _attr_type(&$attributes)
+ {
+ switch (strtoupper($attributes['TYPE']))
+ {
+ case 'TINYINT':
+ $attributes['TYPE'] = 'SMALLINT';
+ $attributes['UNSIGNED'] = FALSE;
+ return;
+ case 'MEDIUMINT':
+ $attributes['TYPE'] = 'INTEGER';
+ $attributes['UNSIGNED'] = FALSE;
+ return;
+ case 'INT':
+ $attributes['TYPE'] = 'INTEGER';
+ return;
+ case 'BIGINT':
+ $attributes['TYPE'] = 'INT64';
+ return;
+ default: return;
+ }
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Field attribute AUTO_INCREMENT
+ *
+ * @param array &$attributes
+ * @param array &$field
+ * @return void
+ */
+ protected function _attr_auto_increment(&$attributes, &$field)
+ {
+ // Not supported
+ }
+
+}
+
+/* End of file pdo_firebird_forge.php */
+/* Location: ./system/database/drivers/pdo/subdrivers/pdo_firebird_forge.php */ \ No newline at end of file
diff --git a/system/database/drivers/pdo/subdrivers/pdo_ibm_driver.php b/system/database/drivers/pdo/subdrivers/pdo_ibm_driver.php
new file mode 100644
index 000000000..2ef97cd6e
--- /dev/null
+++ b/system/database/drivers/pdo/subdrivers/pdo_ibm_driver.php
@@ -0,0 +1,236 @@
+<?php
+/**
+ * CodeIgniter
+ *
+ * An open source application development framework for PHP 5.2.4 or newer
+ *
+ * NOTICE OF LICENSE
+ *
+ * Licensed under the Open Software License version 3.0
+ *
+ * This source file is subject to the Open Software License (OSL 3.0) that is
+ * bundled with this package in the files license.txt / license.rst. It is
+ * also available through the world wide web at this URL:
+ * http://opensource.org/licenses/OSL-3.0
+ * If you did not receive a copy of the license and are unable to obtain it
+ * through the world wide web, please send an email to
+ * licensing@ellislab.com so we can send you a copy immediately.
+ *
+ * @package CodeIgniter
+ * @author EllisLab Dev Team
+ * @copyright Copyright (c) 2008 - 2012, EllisLab, Inc. (http://ellislab.com/)
+ * @license http://opensource.org/licenses/OSL-3.0 Open Software License (OSL 3.0)
+ * @link http://codeigniter.com
+ * @since Version 3.0.0
+ * @filesource
+ */
+defined('BASEPATH') OR exit('No direct script access allowed');
+
+/**
+ * PDO IBM DB2 Database Adapter Class
+ *
+ * Note: _DB is an extender class that the app controller
+ * creates dynamically based on whether the query builder
+ * class is being used or not.
+ *
+ * @package CodeIgniter
+ * @subpackage Drivers
+ * @category Database
+ * @author EllisLab Dev Team
+ * @link http://codeigniter.com/user_guide/database/
+ */
+class CI_DB_pdo_ibm_driver extends CI_DB_pdo_driver {
+
+ /**
+ * Sub-driver
+ *
+ * @var string
+ */
+ public $subdriver = 'ibm';
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Class constructor
+ *
+ * Builds the DSN if not already set.
+ *
+ * @param array $params
+ * @return void
+ */
+ public function __construct($params)
+ {
+ parent::__construct($params);
+
+ if (empty($this->dsn))
+ {
+ $this->dsn = 'ibm:';
+
+ // Pre-defined DSN
+ if (empty($this->hostname) && empty($this->HOSTNAME) && empty($this->port) && empty($this->PORT))
+ {
+ if (isset($this->DSN))
+ {
+ $this->dsn .= 'DSN='.$this->DSN;
+ }
+ elseif ( ! empty($this->database))
+ {
+ $this->dsn .= 'DSN='.$this->database;
+ }
+
+ return;
+ }
+
+ $this->dsn .= 'DRIVER='.(isset($this->DRIVER) ? '{'.$this->DRIVER.'}' : '{IBM DB2 ODBC DRIVER}').';';
+
+ if (isset($this->DATABASE))
+ {
+ $this->dsn .= 'DATABASE='.$this->DATABASE.';';
+ }
+ elseif ( ! empty($this->database))
+ {
+ $this->dsn .= 'DATABASE='.$this->database.';';
+ }
+
+ if (isset($this->HOSTNAME))
+ {
+ $this->dsn .= 'HOSTNAME='.$this->HOSTNAME.';';
+ }
+ else
+ {
+ $this->dsn .= 'HOSTNAME='.(empty($this->hostname) ? '127.0.0.1;' : $this->hostname.';');
+ }
+
+ if (isset($this->PORT))
+ {
+ $this->dsn .= 'PORT='.$this->port.';';
+ }
+ elseif ( ! empty($this->port))
+ {
+ $this->dsn .= ';PORT='.$this->port.';';
+ }
+
+ $this->dsn .= 'PROTOCOL='.(isset($this->PROTOCOL) ? $this->PROTOCOL.';' : 'TCPIP;');
+ }
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Show table query
+ *
+ * Generates a platform-specific query string so that the table names can be fetched
+ *
+ * @param bool $prefix_limit
+ * @return string
+ */
+ protected function _list_tables($prefix_limit = FALSE)
+ {
+ $sql = 'SELECT "tabname" FROM "syscat"."tables"
+ WHERE "type" = \'T\' AND LOWER("tabschema") = '.$this->escape(strtolower($this->database));
+
+ if ($prefix_limit === TRUE && $this->dbprefix !== '')
+ {
+ $sql .= ' AND "tabname" LIKE \''.$this->escape_like_str($this->dbprefix)."%' "
+ .sprintf($this->_like_escape_str, $this->_like_escape_chr);
+ }
+
+ return $sql;
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Show column query
+ *
+ * Generates a platform-specific query string so that the column names can be fetched
+ *
+ * @param string $table
+ * @return array
+ */
+ protected function _list_columns($table = '')
+ {
+ return 'SELECT "colname" FROM "syscat"."columns"
+ WHERE LOWER("tabschema") = '.$this->escape(strtolower($this->database)).'
+ AND LOWER("tabname") = '.$this->escape(strtolower($table));
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Returns an object with field data
+ *
+ * @param string $table
+ * @return array
+ */
+ public function field_data($table = '')
+ {
+ $sql = 'SELECT "colname" AS "name", "typename" AS "type", "default" AS "default", "length" AS "max_length",
+ CASE "keyseq" WHEN NULL THEN 0 ELSE 1 END AS "primary_key"
+ FROM "syscat"."columns"
+ WHERE LOWER("tabschema") = '.$this->escape(strtolower($this->database)).'
+ AND LOWER("tabname") = '.$this->escape(strtolower($table)).'
+ ORDER BY "colno"';
+
+ return (($query = $this->query($sql)) !== FALSE)
+ ? $query->result_object()
+ : FALSE;
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Update statement
+ *
+ * Generates a platform-specific update string from the supplied data
+ *
+ * @param string $table
+ * @param array $values
+ * @return string
+ */
+ protected function _update($table, $values)
+ {
+ $this->qb_limit = FALSE;
+ $this->qb_orderby = array();
+ return parent::_update($table, $values);
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Delete statement
+ *
+ * Generates a platform-specific delete string from the supplied data
+ *
+ * @param string $table
+ * @return string
+ */
+ protected function _delete($table)
+ {
+ $this->qb_limit = FALSE;
+ return parent::_delete($table);
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * LIMIT
+ *
+ * Generates a platform-specific LIMIT clause
+ *
+ * @param string $sql SQL Query
+ * @return string
+ */
+ protected function _limit($sql)
+ {
+ $sql .= ' FETCH FIRST '.($this->qb_limit + $this->qb_offset).' ROWS ONLY';
+
+ return ($this->qb_offset)
+ ? 'SELECT * FROM ('.$sql.') WHERE rownum > '.$this->qb_offset
+ : $sql;
+ }
+
+}
+
+/* End of file pdo_ibm_driver.php */
+/* Location: ./system/database/drivers/pdo/subdrivers/pdo_ibm_driver.php */ \ No newline at end of file
diff --git a/system/database/drivers/pdo/subdrivers/pdo_ibm_forge.php b/system/database/drivers/pdo/subdrivers/pdo_ibm_forge.php
new file mode 100644
index 000000000..f095c717a
--- /dev/null
+++ b/system/database/drivers/pdo/subdrivers/pdo_ibm_forge.php
@@ -0,0 +1,146 @@
+<?php
+/**
+ * CodeIgniter
+ *
+ * An open source application development framework for PHP 5.2.4 or newer
+ *
+ * NOTICE OF LICENSE
+ *
+ * Licensed under the Open Software License version 3.0
+ *
+ * This source file is subject to the Open Software License (OSL 3.0) that is
+ * bundled with this package in the files license.txt / license.rst. It is
+ * also available through the world wide web at this URL:
+ * http://opensource.org/licenses/OSL-3.0
+ * If you did not receive a copy of the license and are unable to obtain it
+ * through the world wide web, please send an email to
+ * licensing@ellislab.com so we can send you a copy immediately.
+ *
+ * @package CodeIgniter
+ * @author EllisLab Dev Team
+ * @copyright Copyright (c) 2008 - 2012, EllisLab, Inc. (http://ellislab.com/)
+ * @license http://opensource.org/licenses/OSL-3.0 Open Software License (OSL 3.0)
+ * @link http://codeigniter.com
+ * @since Version 2.1.0
+ * @filesource
+ */
+defined('BASEPATH') OR exit('No direct script access allowed');
+
+/**
+ * PDO IBM DB2 Forge Class
+ *
+ * @category Database
+ * @author EllisLab Dev Team
+ * @link http://codeigniter.com/user_guide/database/
+ */
+class CI_DB_pdo_ibm_forge extends CI_DB_pdo_forge {
+
+ /**
+ * RENAME TABLE IF statement
+ *
+ * @var string
+ */
+ protected $_rename_table = 'RENAME TABLE %s TO %s';
+
+ /**
+ * UNSIGNED support
+ *
+ * @var array
+ */
+ protected $_unsigned = array(
+ 'SMALLINT' => 'INTEGER',
+ 'INT' => 'BIGINT',
+ 'INTEGER' => 'BIGINT'
+ );
+
+ /**
+ * DEFAULT value representation in CREATE/ALTER TABLE statements
+ *
+ * @var string
+ */
+ protected $_default = FALSE;
+
+ // --------------------------------------------------------------------
+
+ /**
+ * ALTER TABLE
+ *
+ * @param string $alter_type ALTER type
+ * @param string $table Table name
+ * @param mixed $field Column definition
+ * @return string|string[]
+ */
+ protected function _alter_table($alter_type, $table, $field)
+ {
+ if ($alter_type === 'CHANGE')
+ {
+ $alter_type = 'MODIFY';
+ }
+
+ return parent::_alter_table($alter_type, $table, $field);
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Field attribute TYPE
+ *
+ * Performs a data type mapping between different databases.
+ *
+ * @param array &$attributes
+ * @return void
+ */
+ protected function _attr_type(&$attributes)
+ {
+ switch (strtoupper($attributes['TYPE']))
+ {
+ case 'TINYINT':
+ $attributes['TYPE'] = 'SMALLINT';
+ $attributes['UNSIGNED'] = FALSE;
+ return;
+ case 'MEDIUMINT':
+ $attributes['TYPE'] = 'INTEGER';
+ $attributes['UNSIGNED'] = FALSE;
+ return;
+ default: return;
+ }
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Field attribute UNIQUE
+ *
+ * @param array &$attributes
+ * @param array &$field
+ * @return void
+ */
+ protected function _attr_unique(&$attributes, &$field)
+ {
+ if ( ! empty($attributes['UNIQUE']) && $attributes['UNIQUE'] === TRUE)
+ {
+ $field['unique'] = ' UNIQUE';
+
+ // UNIQUE must be used with NOT NULL
+ $field['null'] = ' NOT NULL';
+ }
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Field attribute AUTO_INCREMENT
+ *
+ * @param array &$attributes
+ * @param array &$field
+ * @return void
+ */
+ protected function _attr_auto_increment(&$attributes, &$field)
+ {
+ // Not supported
+ }
+
+}
+
+/* End of file pdo_ibm_forge.php */
+/* Location: ./system/database/drivers/pdo/subdrivers/pdo_ibm_forge.php */ \ No newline at end of file
diff --git a/system/database/drivers/pdo/subdrivers/pdo_informix_driver.php b/system/database/drivers/pdo/subdrivers/pdo_informix_driver.php
new file mode 100644
index 000000000..cfb474eec
--- /dev/null
+++ b/system/database/drivers/pdo/subdrivers/pdo_informix_driver.php
@@ -0,0 +1,301 @@
+<?php
+/**
+ * CodeIgniter
+ *
+ * An open source application development framework for PHP 5.2.4 or newer
+ *
+ * NOTICE OF LICENSE
+ *
+ * Licensed under the Open Software License version 3.0
+ *
+ * This source file is subject to the Open Software License (OSL 3.0) that is
+ * bundled with this package in the files license.txt / license.rst. It is
+ * also available through the world wide web at this URL:
+ * http://opensource.org/licenses/OSL-3.0
+ * If you did not receive a copy of the license and are unable to obtain it
+ * through the world wide web, please send an email to
+ * licensing@ellislab.com so we can send you a copy immediately.
+ *
+ * @package CodeIgniter
+ * @author EllisLab Dev Team
+ * @copyright Copyright (c) 2008 - 2012, EllisLab, Inc. (http://ellislab.com/)
+ * @license http://opensource.org/licenses/OSL-3.0 Open Software License (OSL 3.0)
+ * @link http://codeigniter.com
+ * @since Version 3.0.0
+ * @filesource
+ */
+defined('BASEPATH') OR exit('No direct script access allowed');
+
+/**
+ * PDO Informix Database Adapter Class
+ *
+ * Note: _DB is an extender class that the app controller
+ * creates dynamically based on whether the query builder
+ * class is being used or not.
+ *
+ * @package CodeIgniter
+ * @subpackage Drivers
+ * @category Database
+ * @author EllisLab Dev Team
+ * @link http://codeigniter.com/user_guide/database/
+ */
+class CI_DB_pdo_informix_driver extends CI_DB_pdo_driver {
+
+ /**
+ * Sub-driver
+ *
+ * @var string
+ */
+ public $subdriver = 'informix';
+
+ // --------------------------------------------------------------------
+
+ /**
+ * ORDER BY random keyword
+ *
+ * @var array
+ */
+ protected $_random_keyword = array('ASC', 'ASC'); // Currently not supported
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Class constructor
+ *
+ * Builds the DSN if not already set.
+ *
+ * @param array $params
+ * @return void
+ */
+ public function __construct($params)
+ {
+ parent::__construct($params);
+
+ if (empty($this->dsn))
+ {
+ $this->dsn = 'informix:';
+
+ // Pre-defined DSN
+ if (empty($this->hostname) && empty($this->host) && empty($this->port) && empty($this->service))
+ {
+ if (isset($this->DSN))
+ {
+ $this->dsn .= 'DSN='.$this->DSN;
+ }
+ elseif ( ! empty($this->database))
+ {
+ $this->dsn .= 'DSN='.$this->database;
+ }
+
+ return;
+ }
+
+ if (isset($this->host))
+ {
+ $this->dsn .= 'host='.$this->host;
+ }
+ else
+ {
+ $this->dsn .= 'host='.(empty($this->hostname) ? '127.0.0.1' : $this->hostname);
+ }
+
+ if (isset($this->service))
+ {
+ $this->dsn .= '; service='.$this->service;
+ }
+ elseif ( ! empty($this->port))
+ {
+ $this->dsn .= '; service='.$this->port;
+ }
+
+ empty($this->database) OR $this->dsn .= '; database='.$this->database;
+ empty($this->server) OR $this->dsn .= '; server='.$this->server;
+
+ $this->dsn .= '; protocol='.(isset($this->protocol) ? $this->protocol : 'onsoctcp')
+ .'; EnableScrollableCursors=1';
+ }
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Show table query
+ *
+ * Generates a platform-specific query string so that the table names can be fetched
+ *
+ * @param bool $prefix_limit
+ * @return string
+ */
+ protected function _list_tables($prefix_limit = FALSE)
+ {
+ $sql = 'SELECT "tabname" FROM "systables"
+ WHERE "tabid" > 99 AND "tabtype" = \'T\' AND LOWER("owner") = '.$this->escape(strtolower($this->username));
+
+ if ($prefix_limit === TRUE && $this->dbprefix !== '')
+ {
+ $sql .= ' AND "tabname" LIKE \''.$this->escape_like_str($this->dbprefix)."%' "
+ .sprintf($this->_like_escape_str, $this->_like_escape_chr);
+ }
+
+ return $sql;
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Show column query
+ *
+ * Generates a platform-specific query string so that the column names can be fetched
+ *
+ * @param string $table
+ * @return string
+ */
+ protected function _list_columns($table = '')
+ {
+ if (strpos($table, '.') !== FALSE)
+ {
+ sscanf($table, '%[^.].%s', $owner, $table);
+ }
+ else
+ {
+ $owner = $this->username;
+ }
+
+ return 'SELECT "colname" FROM "systables", "syscolumns"
+ WHERE "systables"."tabid" = "syscolumns"."tabid"
+ AND "systables"."tabtype" = \'T\'
+ AND LOWER("systables"."owner") = '.$this->escape(strtolower($owner)).'
+ AND LOWER("systables"."tabname") = '.$this->escape(strtolower($table));
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Returns an object with field data
+ *
+ * @param string $table
+ * @return array
+ */
+ public function field_data($table = '')
+ {
+ $sql = 'SELECT "syscolumns"."colname" AS "name",
+ CASE "syscolumns"."coltype"
+ WHEN 0 THEN \'CHAR\'
+ WHEN 1 THEN \'SMALLINT\'
+ WHEN 2 THEN \'INTEGER\'
+ WHEN 3 THEN \'FLOAT\'
+ WHEN 4 THEN \'SMALLFLOAT\'
+ WHEN 5 THEN \'DECIMAL\'
+ WHEN 6 THEN \'SERIAL\'
+ WHEN 7 THEN \'DATE\'
+ WHEN 8 THEN \'MONEY\'
+ WHEN 9 THEN \'NULL\'
+ WHEN 10 THEN \'DATETIME\'
+ WHEN 11 THEN \'BYTE\'
+ WHEN 12 THEN \'TEXT\'
+ WHEN 13 THEN \'VARCHAR\'
+ WHEN 14 THEN \'INTERVAL\'
+ WHEN 15 THEN \'NCHAR\'
+ WHEN 16 THEN \'NVARCHAR\'
+ WHEN 17 THEN \'INT8\'
+ WHEN 18 THEN \'SERIAL8\'
+ WHEN 19 THEN \'SET\'
+ WHEN 20 THEN \'MULTISET\'
+ WHEN 21 THEN \'LIST\'
+ WHEN 22 THEN \'Unnamed ROW\'
+ WHEN 40 THEN \'LVARCHAR\'
+ WHEN 41 THEN \'BLOB/CLOB/BOOLEAN\'
+ WHEN 4118 THEN \'Named ROW\'
+ ELSE "syscolumns"."coltype"
+ END AS "type",
+ "syscolumns"."collength" as "max_length",
+ CASE "sysdefaults"."type"
+ WHEN \'L\' THEN "sysdefaults"."default"
+ ELSE NULL
+ END AS "default"
+ FROM "syscolumns", "systables", "sysdefaults"
+ WHERE "syscolumns"."tabid" = "systables"."tabid"
+ AND "systables"."tabid" = "sysdefaults"."tabid"
+ AND "syscolumns"."colno" = "sysdefaults"."colno"
+ AND "systables"."tabtype" = \'T\'
+ AND LOWER("systables"."owner") = '.$this->escape(strtolower($this->username)).'
+ AND LOWER("systables"."tabname") = '.$this->escape(strtolower($table)).'
+ ORDER BY "syscolumns"."colno"';
+
+ return (($query = $this->query($sql)) !== FALSE)
+ ? $query->result_object()
+ : FALSE;
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Update statement
+ *
+ * Generates a platform-specific update string from the supplied data
+ *
+ * @param string $table
+ * @param array $values
+ * @return string
+ */
+ protected function _update($table, $values)
+ {
+ $this->qb_limit = FALSE;
+ $this->qb_orderby = array();
+ return parent::_update($table, $values);
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Truncate statement
+ *
+ * Generates a platform-specific truncate string from the supplied data
+ *
+ * If the database does not support the TRUNCATE statement,
+ * then this method maps to 'DELETE FROM table'
+ *
+ * @param string $table
+ * @return string
+ */
+ protected function _truncate($table)
+ {
+ return 'TRUNCATE TABLE ONLY '.$table;
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Delete statement
+ *
+ * Generates a platform-specific delete string from the supplied data
+ *
+ * @param string $table
+ * @return string
+ */
+ protected function _delete($table)
+ {
+ $this->qb_limit = FALSE;
+ return parent::_delete($table);
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * LIMIT
+ *
+ * Generates a platform-specific LIMIT clause
+ *
+ * @param string $sql $SQL Query
+ * @return string
+ */
+ protected function _limit($sql)
+ {
+ $select = 'SELECT '.($this->qb_offset ? 'SKIP '.$this->qb_offset : '').'FIRST '.$this->qb_limit.' ';
+ return preg_replace('/^(SELECT\s)/i', $select, $sql, 1);
+ }
+
+}
+
+/* End of file pdo_informix_driver.php */
+/* Location: ./system/database/drivers/pdo/subdrivers/pdo_informix_driver.php */ \ No newline at end of file
diff --git a/system/database/drivers/pdo/subdrivers/pdo_informix_forge.php b/system/database/drivers/pdo/subdrivers/pdo_informix_forge.php
new file mode 100644
index 000000000..8722dd200
--- /dev/null
+++ b/system/database/drivers/pdo/subdrivers/pdo_informix_forge.php
@@ -0,0 +1,155 @@
+<?php
+/**
+ * CodeIgniter
+ *
+ * An open source application development framework for PHP 5.2.4 or newer
+ *
+ * NOTICE OF LICENSE
+ *
+ * Licensed under the Open Software License version 3.0
+ *
+ * This source file is subject to the Open Software License (OSL 3.0) that is
+ * bundled with this package in the files license.txt / license.rst. It is
+ * also available through the world wide web at this URL:
+ * http://opensource.org/licenses/OSL-3.0
+ * If you did not receive a copy of the license and are unable to obtain it
+ * through the world wide web, please send an email to
+ * licensing@ellislab.com so we can send you a copy immediately.
+ *
+ * @package CodeIgniter
+ * @author EllisLab Dev Team
+ * @copyright Copyright (c) 2008 - 2012, EllisLab, Inc. (http://ellislab.com/)
+ * @license http://opensource.org/licenses/OSL-3.0 Open Software License (OSL 3.0)
+ * @link http://codeigniter.com
+ * @since Version 2.1.0
+ * @filesource
+ */
+defined('BASEPATH') OR exit('No direct script access allowed');
+
+/**
+ * PDO Informix Forge Class
+ *
+ * @category Database
+ * @author EllisLab Dev Team
+ * @link http://codeigniter.com/user_guide/database/
+ */
+class CI_DB_pdo_informix_forge extends CI_DB_pdo_forge {
+
+ /**
+ * RENAME TABLE statement
+ *
+ * @var string
+ */
+ protected $_rename_table = 'RENAME TABLE %s TO %s';
+
+ /**
+ * UNSIGNED support
+ *
+ * @var array
+ */
+ protected $_unsigned = array(
+ 'SMALLINT' => 'INTEGER',
+ 'INT' => 'BIGINT',
+ 'INTEGER' => 'BIGINT',
+ 'REAL' => 'DOUBLE PRECISION',
+ 'SMALLFLOAT' => 'DOUBLE PRECISION'
+ );
+
+ /**
+ * DEFAULT value representation in CREATE/ALTER TABLE statements
+ *
+ * @var string
+ */
+ protected $_default = ', ';
+
+ // --------------------------------------------------------------------
+
+ /**
+ * ALTER TABLE
+ *
+ * @param string $alter_type ALTER type
+ * @param string $table Table name
+ * @param mixed $field Column definition
+ * @return string|string[]
+ */
+ protected function _alter_table($alter_type, $table, $field)
+ {
+ if ($alter_type === 'CHANGE')
+ {
+ $alter_type = 'MODIFY';
+ }
+
+ return parent::_alter_table($alter_type, $table, $field);
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Field attribute TYPE
+ *
+ * Performs a data type mapping between different databases.
+ *
+ * @param array &$attributes
+ * @return void
+ */
+ protected function _attr_type(&$attributes)
+ {
+ switch (strtoupper($attributes['TYPE']))
+ {
+ case 'TINYINT':
+ $attributes['TYPE'] = 'SMALLINT';
+ $attributes['UNSIGNED'] = FALSE;
+ return;
+ case 'MEDIUMINT':
+ $attributes['TYPE'] = 'INTEGER';
+ $attributes['UNSIGNED'] = FALSE;
+ return;
+ case 'BYTE':
+ case 'TEXT':
+ case 'BLOB':
+ case 'CLOB':
+ $attributes['UNIQUE'] = FALSE;
+ if (isset($attributes['DEFAULT']))
+ {
+ unset($attributes['DEFAULT']);
+ }
+ return;
+ default: return;
+ }
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Field attribute UNIQUE
+ *
+ * @param array &$attributes
+ * @param array &$field
+ * @return void
+ */
+ protected function _attr_unique(&$attributes, &$field)
+ {
+ if ( ! empty($attributes['UNIQUE']) && $attributes['UNIQUE'] === TRUE)
+ {
+ $field['unique'] = ' UNIQUE CONSTRAINT '.$this->db->escape_identifiers($field['name']);
+ }
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Field attribute AUTO_INCREMENT
+ *
+ * @param array &$attributes
+ * @param array &$field
+ * @return void
+ */
+ protected function _attr_auto_increment(&$attributes, &$field)
+ {
+ // Not supported
+ }
+
+}
+
+/* End of file pdo_informix_forge.php */
+/* Location: ./system/database/drivers/pdo/subdrivers/pdo_informix_forge.php */ \ No newline at end of file
diff --git a/system/database/drivers/pdo/subdrivers/pdo_mysql_driver.php b/system/database/drivers/pdo/subdrivers/pdo_mysql_driver.php
new file mode 100644
index 000000000..a29397205
--- /dev/null
+++ b/system/database/drivers/pdo/subdrivers/pdo_mysql_driver.php
@@ -0,0 +1,283 @@
+<?php
+/**
+ * CodeIgniter
+ *
+ * An open source application development framework for PHP 5.2.4 or newer
+ *
+ * NOTICE OF LICENSE
+ *
+ * Licensed under the Open Software License version 3.0
+ *
+ * This source file is subject to the Open Software License (OSL 3.0) that is
+ * bundled with this package in the files license.txt / license.rst. It is
+ * also available through the world wide web at this URL:
+ * http://opensource.org/licenses/OSL-3.0
+ * If you did not receive a copy of the license and are unable to obtain it
+ * through the world wide web, please send an email to
+ * licensing@ellislab.com so we can send you a copy immediately.
+ *
+ * @package CodeIgniter
+ * @author EllisLab Dev Team
+ * @copyright Copyright (c) 2008 - 2012, EllisLab, Inc. (http://ellislab.com/)
+ * @license http://opensource.org/licenses/OSL-3.0 Open Software License (OSL 3.0)
+ * @link http://codeigniter.com
+ * @since Version 3.0.0
+ * @filesource
+ */
+defined('BASEPATH') OR exit('No direct script access allowed');
+
+/**
+ * PDO MySQL Database Adapter Class
+ *
+ * Note: _DB is an extender class that the app controller
+ * creates dynamically based on whether the query builder
+ * class is being used or not.
+ *
+ * @package CodeIgniter
+ * @subpackage Drivers
+ * @category Database
+ * @author EllisLab Dev Team
+ * @link http://codeigniter.com/user_guide/database/
+ */
+class CI_DB_pdo_mysql_driver extends CI_DB_pdo_driver {
+
+ /**
+ * Sub-driver
+ *
+ * @var string
+ */
+ public $subdriver = 'mysql';
+
+ /**
+ * Compression flag
+ *
+ * @var bool
+ */
+ public $compress = FALSE;
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Identifier escape character
+ *
+ * @var string
+ */
+ protected $_escape_char = '`';
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Class constructor
+ *
+ * Builds the DSN if not already set.
+ *
+ * @param array $params
+ * @return void
+ */
+ public function __construct($params)
+ {
+ parent::__construct($params);
+
+ if (empty($this->dsn))
+ {
+ $this->dsn = 'mysql:host='.(empty($this->hostname) ? '127.0.0.1' : $this->hostname);
+
+ empty($this->port) OR $this->dsn .= ';port='.$this->port;
+ empty($this->database) OR $this->dsn .= ';dbname='.$this->database;
+ empty($this->char_set) OR $this->dsn .= ';charset='.$this->char_set;
+ }
+ elseif ( ! empty($this->char_set) && strpos($this->dsn, 'charset=', 6) === FALSE && is_php('5.3.6'))
+ {
+ $this->dsn .= ';charset='.$this->char_set;
+ }
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Database connection
+ *
+ * @param bool $persistent
+ * @return object
+ * @todo SSL support
+ */
+ public function db_connect($persistent = FALSE)
+ {
+ /* Prior to PHP 5.3.6, even if the charset was supplied in the DSN
+ * on connect - it was ignored. This is a work-around for the issue.
+ *
+ * Reference: http://www.php.net/manual/en/ref.pdo-mysql.connection.php
+ */
+ if ( ! is_php('5.3.6') && ! empty($this->char_set))
+ {
+ $this->options[PDO::MYSQL_ATTR_INIT_COMMAND] = 'SET NAMES '.$this->char_set
+ .(empty($this->dbcollat) ? '' : ' COLLATE '.$this->dbcollat);
+ }
+
+ if ($this->compress === TRUE)
+ {
+ $this->options[PDO::MYSQL_ATTR_COMPRESS] = TRUE;
+ }
+
+ return parent::db_connect($persistent);
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Show table query
+ *
+ * Generates a platform-specific query string so that the table names can be fetched
+ *
+ * @param bool $prefix_limit
+ * @return string
+ */
+ protected function _list_tables($prefix_limit = FALSE)
+ {
+ $sql = 'SHOW TABLES';
+
+ if ($prefix_limit === TRUE && $this->dbprefix !== '')
+ {
+ return $sql." LIKE '".$this->escape_like_str($this->dbprefix)."%'";
+ }
+
+ return $sql;
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Show column query
+ *
+ * Generates a platform-specific query string so that the column names can be fetched
+ *
+ * @param string $table
+ * @return string
+ */
+ protected function _list_columns($table = '')
+ {
+ return 'SHOW COLUMNS FROM '.$this->protect_identifiers($table, TRUE, NULL, FALSE);
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Returns an object with field data
+ *
+ * @param string $table
+ * @return array
+ */
+ public function field_data($table = '')
+ {
+ if ($table === '')
+ {
+ return ($this->db_debug) ? $this->display_error('db_field_param_missing') : FALSE;
+ }
+
+ if (($query = $this->query('SHOW COLUMNS FROM '.$this->protect_identifiers($table, TRUE, NULL, FALSE))) === FALSE)
+ {
+ return FALSE;
+ }
+ $query = $query->result_object();
+
+ $retval = array();
+ for ($i = 0, $c = count($query); $i < $c; $i++)
+ {
+ $retval[$i] = new stdClass();
+ $retval[$i]->name = $query[$i]->Field;
+
+ sscanf($query[$i]->Type, '%[a-z](%d)',
+ $retval[$i]->type,
+ $retval[$i]->max_length
+ );
+
+ $retval[$i]->default = $query[$i]->Default;
+ $retval[$i]->primary_key = (int) ($query[$i]->Key === 'PRI');
+ }
+
+ return $retval;
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Update_Batch statement
+ *
+ * Generates a platform-specific batch update string from the supplied data
+ *
+ * @param string $table Table name
+ * @param array $values Update data
+ * @param string $index UPDATE key
+ * @return string
+ */
+ protected function _update_batch($table, $values, $index)
+ {
+ $ids = array();
+ foreach ($values as $key => $val)
+ {
+ $ids[] = $val[$index];
+
+ foreach (array_keys($val) as $field)
+ {
+ if ($field !== $index)
+ {
+ $final[$field][] = 'WHEN '.$index.' = '.$val[$index].' THEN '.$val[$field];
+ }
+ }
+ }
+
+ $cases = '';
+ foreach ($final as $k => $v)
+ {
+ $cases .= $k." = CASE \n"
+ .implode("\n", $v)."\n"
+ .'ELSE '.$k.' END), ';
+ }
+
+ $this->where($index.' IN('.implode(',', $ids).')', NULL, FALSE);
+
+ return 'UPDATE '.$table.' SET '.substr($cases, 0, -2).$this->_compile_wh('qb_where');
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Truncate statement
+ *
+ * Generates a platform-specific truncate string from the supplied data
+ *
+ * If the database does not support the TRUNCATE statement,
+ * then this method maps to 'DELETE FROM table'
+ *
+ * @param string $table
+ * @return string
+ */
+ protected function _truncate($table)
+ {
+ return 'TRUNCATE '.$table;
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * FROM tables
+ *
+ * Groups tables in FROM clauses if needed, so there is no confusion
+ * about operator precedence.
+ *
+ * @return string
+ */
+ protected function _from_tables()
+ {
+ if ( ! empty($this->qb_join) && count($this->qb_from) > 1)
+ {
+ return '('.implode(', ', $this->qb_from).')';
+ }
+
+ return implode(', ', $this->qb_from);
+ }
+
+}
+
+/* End of file pdo_mysql_driver.php */
+/* Location: ./system/database/drivers/pdo/subdrivers/pdo_mysql_driver.php */ \ No newline at end of file
diff --git a/system/database/drivers/pdo/subdrivers/pdo_mysql_forge.php b/system/database/drivers/pdo/subdrivers/pdo_mysql_forge.php
new file mode 100644
index 000000000..5a6de6b2d
--- /dev/null
+++ b/system/database/drivers/pdo/subdrivers/pdo_mysql_forge.php
@@ -0,0 +1,229 @@
+<?php
+/**
+ * CodeIgniter
+ *
+ * An open source application development framework for PHP 5.2.4 or newer
+ *
+ * NOTICE OF LICENSE
+ *
+ * Licensed under the Open Software License version 3.0
+ *
+ * This source file is subject to the Open Software License (OSL 3.0) that is
+ * bundled with this package in the files license.txt / license.rst. It is
+ * also available through the world wide web at this URL:
+ * http://opensource.org/licenses/OSL-3.0
+ * If you did not receive a copy of the license and are unable to obtain it
+ * through the world wide web, please send an email to
+ * licensing@ellislab.com so we can send you a copy immediately.
+ *
+ * @package CodeIgniter
+ * @author EllisLab Dev Team
+ * @copyright Copyright (c) 2008 - 2012, EllisLab, Inc. (http://ellislab.com/)
+ * @license http://opensource.org/licenses/OSL-3.0 Open Software License (OSL 3.0)
+ * @link http://codeigniter.com
+ * @since Version 2.1.0
+ * @filesource
+ */
+defined('BASEPATH') OR exit('No direct script access allowed');
+
+/**
+ * PDO MySQL Forge Class
+ *
+ * @category Database
+ * @author EllisLab Dev Team
+ * @link http://codeigniter.com/user_guide/database/
+ */
+class CI_DB_pdo_mysql_forge extends CI_DB_pdo_forge {
+
+ /**
+ * CREATE DATABASE statement
+ *
+ * @var string
+ */
+ protected $_create_database = 'CREATE DATABASE %s CHARACTER SET %s COLLATE %s';
+
+ /**
+ * CREATE TABLE IF statement
+ *
+ * @var string
+ */
+ protected $_create_table_if = 'CREATE TABLE IF NOT EXISTS';
+
+ /**
+ * CREATE TABLE keys flag
+ *
+ * Whether table keys are created from within the
+ * CREATE TABLE statement.
+ *
+ * @var bool
+ */
+ protected $_create_table_keys = TRUE;
+
+ /**
+ * DROP TABLE IF statement
+ *
+ * @var string
+ */
+ protected $_drop_table_if = 'DROP TABLE IF EXISTS';
+
+ /**
+ * UNSIGNED support
+ *
+ * @var array
+ */
+ protected $_unsigned = array(
+ 'TINYINT',
+ 'SMALLINT',
+ 'MEDIUMINT',
+ 'INT',
+ 'INTEGER',
+ 'BIGINT',
+ 'REAL',
+ 'DOUBLE',
+ 'DOUBLE PRECISION',
+ 'FLOAT',
+ 'DECIMAL',
+ 'NUMERIC'
+ );
+
+ /**
+ * NULL value representation in CREATE/ALTER TABLE statements
+ *
+ * @var string
+ */
+ protected $_null = 'NULL';
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Class constructor
+ *
+ * @param object &$db Database object
+ * @return void
+ */
+ public function __construct(&$db)
+ {
+ parent::__construct($db);
+
+ $this->_create_table .= ' DEFAULT CHARSET '.$this->db->char_set.' COLLATE '.$this->db->dbcollat;
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * ALTER TABLE
+ *
+ * @param string $alter_type ALTER type
+ * @param string $table Table name
+ * @param mixed $field Column definition
+ * @return string|string[]
+ */
+ protected function _alter_table($alter_type, $table, $field)
+ {
+ if ($alter_type === 'DROP')
+ {
+ return parent::_alter_table($alter_type, $table, $field);
+ }
+
+ $sql = 'ALTER TABLE '.$this->db->escape_identifiers($table);
+ for ($i = 0, $c = count($field); $i < $c; $i++)
+ {
+ if ($field[$i]['_literal'] !== FALSE)
+ {
+ $field[$i] = ($alter_type === 'ADD')
+ ? "\n\tADD ".$field[$i]['_literal']
+ : "\n\tMODIFY ".$field[$i]['_literal'];
+ }
+ else
+ {
+ if ($alter_type === 'ADD')
+ {
+ $field[$i]['_literal'] = "\n\tADD ";
+ }
+ else
+ {
+ $field[$i]['_literal'] = empty($field[$i]['new_name']) ? "\n\tMODIFY " : "\n\tCHANGE ";
+ }
+
+ $field[$i] = $field[$i]['_literal'].$this->_process_column($field[$i]);
+ }
+ }
+
+ return array($sql.implode(',', $field));
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Process column
+ *
+ * @param array $field
+ * @return string
+ */
+ protected function _process_column($field)
+ {
+ $extra_clause = isset($field['after'])
+ ? ' AFTER '.$this->db->escape_identifiers($field['after']) : '';
+
+ if (empty($extra_clause) && isset($field['first']) && $field['first'] === TRUE)
+ {
+ $extra_clause = ' FIRST';
+ }
+
+ return $this->db->escape_identifiers($field['name'])
+ .(empty($field['new_name']) ? '' : ' '.$this->db->escape_identifiers($field['new_name']))
+ .' '.$field['type'].$field['length']
+ .$field['unsigned']
+ .$field['null']
+ .$field['default']
+ .$field['auto_increment']
+ .$field['unique']
+ .$extra_clause;
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Process indexes
+ *
+ * @param string $table (ignored)
+ * @return string
+ */
+ protected function _process_indexes($table)
+ {
+ $sql = '';
+
+ for ($i = 0, $c = count($this->keys); $i < $c; $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;
+ }
+
+ is_array($this->keys[$i]) OR $this->keys[$i] = array($this->keys[$i]);
+
+ $sql .= ",\n\tKEY ".$this->db->escape_identifiers(implode('_', $this->keys[$i]))
+ .' ('.implode(', ', $this->db->escape_identifiers($this->keys[$i])).')';
+ }
+
+ $this->keys = array();
+
+ return $sql;
+ }
+
+}
+
+/* End of file pdo_mysql_forge.php */
+/* Location: ./system/database/drivers/pdo/subdrivers/pdo_mysql_forge.php */ \ No newline at end of file
diff --git a/system/database/drivers/pdo/subdrivers/pdo_oci_driver.php b/system/database/drivers/pdo/subdrivers/pdo_oci_driver.php
new file mode 100644
index 000000000..57df558ad
--- /dev/null
+++ b/system/database/drivers/pdo/subdrivers/pdo_oci_driver.php
@@ -0,0 +1,291 @@
+<?php
+/**
+ * CodeIgniter
+ *
+ * An open source application development framework for PHP 5.2.4 or newer
+ *
+ * NOTICE OF LICENSE
+ *
+ * Licensed under the Open Software License version 3.0
+ *
+ * This source file is subject to the Open Software License (OSL 3.0) that is
+ * bundled with this package in the files license.txt / license.rst. It is
+ * also available through the world wide web at this URL:
+ * http://opensource.org/licenses/OSL-3.0
+ * If you did not receive a copy of the license and are unable to obtain it
+ * through the world wide web, please send an email to
+ * licensing@ellislab.com so we can send you a copy immediately.
+ *
+ * @package CodeIgniter
+ * @author EllisLab Dev Team
+ * @copyright Copyright (c) 2008 - 2012, EllisLab, Inc. (http://ellislab.com/)
+ * @license http://opensource.org/licenses/OSL-3.0 Open Software License (OSL 3.0)
+ * @link http://codeigniter.com
+ * @since Version 3.0.0
+ * @filesource
+ */
+defined('BASEPATH') OR exit('No direct script access allowed');
+
+/**
+ * PDO Oracle Database Adapter Class
+ *
+ * Note: _DB is an extender class that the app controller
+ * creates dynamically based on whether the query builder
+ * class is being used or not.
+ *
+ * @package CodeIgniter
+ * @subpackage Drivers
+ * @category Database
+ * @author EllisLab Dev Team
+ * @link http://codeigniter.com/user_guide/database/
+ */
+class CI_DB_pdo_oci_driver extends CI_DB_pdo_driver {
+
+ /**
+ * Sub-driver
+ *
+ * @var string
+ */
+ public $subdriver = 'oci';
+
+ // --------------------------------------------------------------------
+
+ /**
+ * List of reserved identifiers
+ *
+ * Identifiers that must NOT be escaped.
+ *
+ * @var string[]
+ */
+ protected $_reserved_identifiers = array('*', 'rownum');
+
+ /**
+ * ORDER BY random keyword
+ *
+ * @var array
+ */
+ protected $_random_keyword = array('ASC', 'ASC'); // Currently not supported
+
+ /**
+ * COUNT string
+ *
+ * @used-by CI_DB_driver::count_all()
+ * @used-by CI_DB_query_builder::count_all_results()
+ *
+ * @var string
+ */
+ protected $_count_string = 'SELECT COUNT(1) AS ';
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Class constructor
+ *
+ * Builds the DSN if not already set.
+ *
+ * @param array $params
+ * @return void
+ */
+ public function __construct($params)
+ {
+ parent::__construct($params);
+
+ if (empty($this->dsn))
+ {
+ $this->dsn = 'oci:dbname=';
+
+ // Oracle has a slightly different PDO DSN format (Easy Connect),
+ // which also supports pre-defined DSNs.
+ if (empty($this->hostname) && empty($this->port))
+ {
+ $this->dsn .= $this->database;
+ }
+ else
+ {
+ $this->dsn .= '//'.(empty($this->hostname) ? '127.0.0.1' : $this->hostname)
+ .(empty($this->port) ? '' : ':'.$this->port).'/';
+
+ empty($this->database) OR $this->dsn .= $this->database;
+ }
+
+ empty($this->char_set) OR $this->dsn .= ';charset='.$this->char_set;
+ }
+ elseif ( ! empty($this->char_set) && strpos($this->dsn, 'charset=', 4) === FALSE)
+ {
+ $this->dsn .= ';charset='.$this->char_set;
+ }
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Show table query
+ *
+ * Generates a platform-specific query string so that the table names can be fetched
+ *
+ * @param bool $prefix_limit
+ * @return string
+ */
+ protected function _list_tables($prefix_limit = FALSE)
+ {
+ $sql = 'SELECT "TABLE_NAME" FROM "ALL_TABLES"';
+
+ if ($prefix_limit === TRUE && $this->dbprefix !== '')
+ {
+ return $sql.' WHERE "TABLE_NAME" LIKE \''.$this->escape_like_str($this->dbprefix)."%' "
+ .sprintf($this->_like_escape_str, $this->_like_escape_chr);
+ }
+
+ return $sql;
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Show column query
+ *
+ * Generates a platform-specific query string so that the column names can be fetched
+ *
+ * @param string $table
+ * @return string
+ */
+ protected function _list_columns($table = '')
+ {
+ if (strpos($table, '.') !== FALSE)
+ {
+ sscanf($table, '%[^.].%s', $owner, $table);
+ }
+ else
+ {
+ $owner = $this->username;
+ }
+
+ return 'SELECT COLUMN_NAME FROM ALL_TAB_COLUMNS
+ WHERE UPPER(OWNER) = '.$this->escape(strtoupper($owner)).'
+ AND UPPER(TABLE_NAME) = '.$this->escape(strtoupper($table));
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Returns an object with field data
+ *
+ * @param string $table
+ * @return array
+ */
+ public function field_data($table = '')
+ {
+ if ($table === '')
+ {
+ return ($this->db_debug) ? $this->display_error('db_field_param_missing') : FALSE;
+ }
+ elseif (strpos($table, '.') !== FALSE)
+ {
+ sscanf($table, '%[^.].%s', $owner, $table);
+ }
+ else
+ {
+ $owner = $this->username;
+ }
+
+ $sql = 'SELECT COLUMN_NAME, DATA_TYPE, CHAR_LENGTH, DATA_PRECISION, DATA_LENGTH, DATA_DEFAULT, NULLABLE
+ FROM ALL_TAB_COLUMNS
+ WHERE UPPER(OWNER) = '.$this->escape(strtoupper($owner)).'
+ AND UPPER(TABLE_NAME) = '.$this->escape(strtoupper($table));
+
+ if (($query = $this->query($sql)) === FALSE)
+ {
+ return FALSE;
+ }
+ $query = $query->result_object();
+
+ $retval = array();
+ for ($i = 0, $c = count($query); $i < $c; $i++)
+ {
+ $retval[$i] = new stdClass();
+ $retval[$i]->name = $query[$i]->COLUMN_NAME;
+ $retval[$i]->type = $query[$i]->DATA_TYPE;
+
+ $length = ($query[$i]->CHAR_LENGTH > 0)
+ ? $query[$i]->CHAR_LENGTH : $query[$i]->DATA_PRECISION;
+ if ($length === NULL)
+ {
+ $length = $query[$i]->DATA_LENGTH;
+ }
+ $retval[$i]->max_length = $length;
+
+ $default = $query[$i]->DATA_DEFAULT;
+ if ($default === NULL && $query[$i]->NULLABLE === 'N')
+ {
+ $default = '';
+ }
+ $retval[$i]->default = $query[$i]->COLUMN_DEFAULT;
+ }
+
+ return $retval;
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Insert batch statement
+ *
+ * @param string $table Table name
+ * @param array $keys INSERT keys
+ * @param array $values INSERT values
+ * @return string
+ */
+ protected function _insert_batch($table, $keys, $values)
+ {
+ $keys = implode(', ', $keys);
+ $sql = "INSERT ALL\n";
+
+ for ($i = 0, $c = count($values); $i < $c; $i++)
+ {
+ $sql .= ' INTO '.$table.' ('.$keys.') VALUES '.$values[$i]."\n";
+ }
+
+ return $sql.'SELECT * FROM dual';
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Delete statement
+ *
+ * Generates a platform-specific delete string from the supplied data
+ *
+ * @param string $table
+ * @return string
+ */
+ protected function _delete($table)
+ {
+ if ($this->qb_limit)
+ {
+ $this->where('rownum <= ',$this->qb_limit, FALSE);
+ $this->qb_limit = FALSE;
+ }
+
+ return parent::_delete($table);
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * LIMIT
+ *
+ * Generates a platform-specific LIMIT clause
+ *
+ * @param string $sql SQL Query
+ * @return string
+ */
+ protected function _limit($sql)
+ {
+ return 'SELECT * FROM (SELECT inner_query.*, rownum rnum FROM ('.$sql.') inner_query WHERE rownum < '.($this->qb_offset + $this->qb_limit + 1).')'
+ .($this->qb_offset ? ' WHERE rnum >= '.($this->qb_offset + 1): '');
+ }
+
+}
+
+/* End of file pdo_oci_driver.php */
+/* Location: ./system/database/drivers/pdo/subdrivers/pdo_oci_driver.php */ \ No newline at end of file
diff --git a/system/database/drivers/pdo/subdrivers/pdo_oci_forge.php b/system/database/drivers/pdo/subdrivers/pdo_oci_forge.php
new file mode 100644
index 000000000..6d51a14b1
--- /dev/null
+++ b/system/database/drivers/pdo/subdrivers/pdo_oci_forge.php
@@ -0,0 +1,133 @@
+<?php
+/**
+ * CodeIgniter
+ *
+ * An open source application development framework for PHP 5.2.4 or newer
+ *
+ * NOTICE OF LICENSE
+ *
+ * Licensed under the Open Software License version 3.0
+ *
+ * This source file is subject to the Open Software License (OSL 3.0) that is
+ * bundled with this package in the files license.txt / license.rst. It is
+ * also available through the world wide web at this URL:
+ * http://opensource.org/licenses/OSL-3.0
+ * If you did not receive a copy of the license and are unable to obtain it
+ * through the world wide web, please send an email to
+ * licensing@ellislab.com so we can send you a copy immediately.
+ *
+ * @package CodeIgniter
+ * @author EllisLab Dev Team
+ * @copyright Copyright (c) 2008 - 2012, EllisLab, Inc. (http://ellislab.com/)
+ * @license http://opensource.org/licenses/OSL-3.0 Open Software License (OSL 3.0)
+ * @link http://codeigniter.com
+ * @since Version 2.1.0
+ * @filesource
+ */
+defined('BASEPATH') OR exit('No direct script access allowed');
+
+/**
+ * PDO Oracle Forge Class
+ *
+ * @category Database
+ * @author EllisLab Dev Team
+ * @link http://codeigniter.com/user_guide/database/
+ */
+class CI_DB_pdo_oci_forge extends CI_DB_pdo_forge {
+
+ /**
+ * CREATE DATABASE statement
+ *
+ * @var string
+ */
+ protected $_create_database = FALSE;
+
+ /**
+ * DROP DATABASE statement
+ *
+ * @var string
+ */
+ protected $_drop_database = FALSE;
+
+ /**
+ * CREATE TABLE IF statement
+ *
+ * @var string
+ */
+ protected $_create_table_if = 'CREATE TABLE IF NOT EXISTS';
+
+ /**
+ * UNSIGNED support
+ *
+ * @var bool|array
+ */
+ protected $_unsigned = FALSE;
+
+ // --------------------------------------------------------------------
+
+ /**
+ * ALTER TABLE
+ *
+ * @param string $alter_type ALTER type
+ * @param string $table Table name
+ * @param mixed $field Column definition
+ * @return string|string[]
+ */
+ protected function _alter_table($alter_type, $table, $field)
+ {
+ if ($alter_type === 'DROP')
+ {
+ return parent::_alter_table($alter_type, $table, $field);
+ }
+ elseif ($alter_type === 'CHANGE')
+ {
+ $alter_type = 'MODIFY';
+ }
+
+ $sql = 'ALTER TABLE '.$this->db->escape_identifiers($table);
+ $sqls = array();
+ for ($i = 0, $c = count($field); $i < $c; $i++)
+ {
+ if ($field[$i]['_literal'] !== FALSE)
+ {
+ $field[$i] = "\n\t".$field[$i]['_literal'];
+ }
+ else
+ {
+ $field[$i]['_literal'] = "\n\t".$this->_process_column($field[$i]);
+ if ($alter_type === 'MODIFY' && ! empty($field[$i]['new_name']))
+ {
+ $sqls[] = $sql.' RENAME COLUMN '.$this->db->escape_identifiers($field[$i]['name'])
+ .' '.$this->db->escape_identifiers($field[$i]['new_name']);
+ }
+ }
+ }
+
+ $sql .= ' '.$alter_type.' ';
+ $sql .= (count($field) === 1)
+ ? $field[0]
+ : '('.implode(',', $field).')';
+
+ // RENAME COLUMN must be executed after MODIFY
+ array_unshift($sqls, $sql);
+ return $sql;
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Field attribute AUTO_INCREMENT
+ *
+ * @param array &$attributes
+ * @param array &$field
+ * @return void
+ */
+ protected function _attr_auto_increment(&$attributes, &$field)
+ {
+ // Not supported - sequences and triggers must be used instead
+ }
+
+}
+
+/* End of file pdo_oci_forge.php */
+/* Location: ./system/database/drivers/pdo/subdrivers/pdo_oci_forge.php */ \ No newline at end of file
diff --git a/system/database/drivers/pdo/subdrivers/pdo_odbc_driver.php b/system/database/drivers/pdo/subdrivers/pdo_odbc_driver.php
new file mode 100644
index 000000000..c940a7b1f
--- /dev/null
+++ b/system/database/drivers/pdo/subdrivers/pdo_odbc_driver.php
@@ -0,0 +1,258 @@
+<?php
+/**
+ * CodeIgniter
+ *
+ * An open source application development framework for PHP 5.2.4 or newer
+ *
+ * NOTICE OF LICENSE
+ *
+ * Licensed under the Open Software License version 3.0
+ *
+ * This source file is subject to the Open Software License (OSL 3.0) that is
+ * bundled with this package in the files license.txt / license.rst. It is
+ * also available through the world wide web at this URL:
+ * http://opensource.org/licenses/OSL-3.0
+ * If you did not receive a copy of the license and are unable to obtain it
+ * through the world wide web, please send an email to
+ * licensing@ellislab.com so we can send you a copy immediately.
+ *
+ * @package CodeIgniter
+ * @author EllisLab Dev Team
+ * @copyright Copyright (c) 2008 - 2012, EllisLab, Inc. (http://ellislab.com/)
+ * @license http://opensource.org/licenses/OSL-3.0 Open Software License (OSL 3.0)
+ * @link http://codeigniter.com
+ * @since Version 3.0.0
+ * @filesource
+ */
+defined('BASEPATH') OR exit('No direct script access allowed');
+
+/**
+ * PDO ODBC Database Adapter Class
+ *
+ * Note: _DB is an extender class that the app controller
+ * creates dynamically based on whether the query builder
+ * class is being used or not.
+ *
+ * @package CodeIgniter
+ * @subpackage Drivers
+ * @category Database
+ * @author EllisLab Dev Team
+ * @link http://codeigniter.com/user_guide/database/
+ */
+class CI_DB_pdo_odbc_driver extends CI_DB_pdo_driver {
+
+ /**
+ * Sub-driver
+ *
+ * @var string
+ */
+ public $subdriver = 'odbc';
+
+ /**
+ * Database schema
+ *
+ * @var string
+ */
+ public $schema = 'public';
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Identifier escape character
+ *
+ * Must be empty for ODBC.
+ *
+ * @var string
+ */
+ protected $_escape_char = '';
+
+ /**
+ * ESCAPE statement string
+ *
+ * @var string
+ */
+ protected $_like_escape_str = " {escape '%s'} ";
+
+ /**
+ * ORDER BY random keyword
+ *
+ * @var array
+ */
+ protected $_random_keyword = array('RND()', 'RND(%d)');
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Class constructor
+ *
+ * Builds the DSN if not already set.
+ *
+ * @param array $params
+ * @return void
+ */
+ public function __construct($params)
+ {
+ parent::__construct($params);
+
+ if (empty($this->dsn))
+ {
+ $this->dsn = 'odbc:';
+
+ // Pre-defined DSN
+ if (empty($this->hostname) && empty($this->HOSTNAME) && empty($this->port) && empty($this->PORT))
+ {
+ if (isset($this->DSN))
+ {
+ $this->dsn .= 'DSN='.$this->DSN;
+ }
+ elseif ( ! empty($this->database))
+ {
+ $this->dsn .= 'DSN='.$this->database;
+ }
+
+ return;
+ }
+
+ // If the DSN is not pre-configured - try to build an IBM DB2 connection string
+ $this->dsn .= 'DRIVER='.(isset($this->DRIVER) ? '{'.$this->DRIVER.'}' : '{IBM DB2 ODBC DRIVER}').';';
+
+ if (isset($this->DATABASE))
+ {
+ $this->dsn .= 'DATABASE='.$this->DATABASE.';';
+ }
+ elseif ( ! empty($this->database))
+ {
+ $this->dsn .= 'DATABASE='.$this->database.';';
+ }
+
+ if (isset($this->HOSTNAME))
+ {
+ $this->dsn .= 'HOSTNAME='.$this->HOSTNAME.';';
+ }
+ else
+ {
+ $this->dsn .= 'HOSTNAME='.(empty($this->hostname) ? '127.0.0.1;' : $this->hostname.';');
+ }
+
+ if (isset($this->PORT))
+ {
+ $this->dsn .= 'PORT='.$this->port.';';
+ }
+ elseif ( ! empty($this->port))
+ {
+ $this->dsn .= ';PORT='.$this->port.';';
+ }
+
+ $this->dsn .= 'PROTOCOL='.(isset($this->PROTOCOL) ? $this->PROTOCOL.';' : 'TCPIP;');
+ }
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Show table query
+ *
+ * Generates a platform-specific query string so that the table names can be fetched
+ *
+ * @param bool $prefix_limit
+ * @return string
+ */
+ protected function _list_tables($prefix_limit = FALSE)
+ {
+ $sql = "SELECT table_name FROM information_schema.tables WHERE table_schema = '".$this->schema."'";
+
+ if ($prefix_limit !== FALSE && $this->dbprefix !== '')
+ {
+ return $sql." AND table_name LIKE '".$this->escape_like_str($this->dbprefix)."%' "
+ .sprintf($this->_like_escape_str, $this->_like_escape_chr);
+ }
+
+ return $sql;
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Show column query
+ *
+ * Generates a platform-specific query string so that the column names can be fetched
+ *
+ * @param string $table
+ * @return string
+ */
+ protected function _list_columns($table = '')
+ {
+ return 'SELECT column_name FROM information_schema.columns WHERE table_name = '.$this->escape($table);
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Update statement
+ *
+ * Generates a platform-specific update string from the supplied data
+ *
+ * @param string $table
+ * @param array $values
+ * @return string
+ */
+ protected function _update($table, $values)
+ {
+ $this->qb_limit = FALSE;
+ $this->qb_orderby = array();
+ return parent::_update($table, $values);
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Truncate statement
+ *
+ * Generates a platform-specific truncate string from the supplied data
+ *
+ * If the database does not support the TRUNCATE statement,
+ * then this method maps to 'DELETE FROM table'
+ *
+ * @param string $table
+ * @return string
+ */
+ protected function _truncate($table)
+ {
+ return 'DELETE FROM '.$table;
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Delete statement
+ *
+ * Generates a platform-specific delete string from the supplied data
+ *
+ * @param string the table name
+ * @return string
+ */
+ protected function _delete($table)
+ {
+ $this->qb_limit = FALSE;
+ return parent::_delete($table);
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * LIMIT
+ *
+ * Generates a platform-specific LIMIT clause
+ *
+ * @param string $sql SQL Query
+ * @return string
+ */
+ protected function _limit($sql)
+ {
+ return preg_replace('/(^\SELECT (DISTINCT)?)/i','\\1 TOP '.$this->qb_limit.' ', $sql);
+ }
+
+}
+
+/* End of file pdo_odbc_driver.php */
+/* Location: ./system/database/drivers/pdo/subdrivers/pdo_odbc_driver.php */ \ No newline at end of file
diff --git a/system/database/drivers/pdo/subdrivers/pdo_odbc_forge.php b/system/database/drivers/pdo/subdrivers/pdo_odbc_forge.php
new file mode 100644
index 000000000..ab4d2bf84
--- /dev/null
+++ b/system/database/drivers/pdo/subdrivers/pdo_odbc_forge.php
@@ -0,0 +1,62 @@
+<?php
+/**
+ * CodeIgniter
+ *
+ * An open source application development framework for PHP 5.2.4 or newer
+ *
+ * NOTICE OF LICENSE
+ *
+ * Licensed under the Open Software License version 3.0
+ *
+ * This source file is subject to the Open Software License (OSL 3.0) that is
+ * bundled with this package in the files license.txt / license.rst. It is
+ * also available through the world wide web at this URL:
+ * http://opensource.org/licenses/OSL-3.0
+ * If you did not receive a copy of the license and are unable to obtain it
+ * through the world wide web, please send an email to
+ * licensing@ellislab.com so we can send you a copy immediately.
+ *
+ * @package CodeIgniter
+ * @author EllisLab Dev Team
+ * @copyright Copyright (c) 2008 - 2012, EllisLab, Inc. (http://ellislab.com/)
+ * @license http://opensource.org/licenses/OSL-3.0 Open Software License (OSL 3.0)
+ * @link http://codeigniter.com
+ * @since Version 2.1.0
+ * @filesource
+ */
+defined('BASEPATH') OR exit('No direct script access allowed');
+
+/**
+ * PDO ODBC Forge Class
+ *
+ * @category Database
+ * @author EllisLab Dev Team
+ * @link http://codeigniter.com/database/
+ */
+class CI_DB_pdo_odbc_forge extends CI_DB_pdo_forge {
+
+ /**
+ * UNSIGNED support
+ *
+ * @var bool|array
+ */
+ protected $_unsigned = FALSE;
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Field attribute AUTO_INCREMENT
+ *
+ * @param array &$attributes
+ * @param array &$field
+ * @return void
+ */
+ protected function _attr_auto_increment(&$attributes, &$field)
+ {
+ // Not supported (in most databases at least)
+ }
+
+}
+
+/* End of file pdo_odbc_forge.php */
+/* Location: ./system/database/drivers/pdo/subdrivers/pdo_odbc_forge.php */ \ No newline at end of file
diff --git a/system/database/drivers/pdo/subdrivers/pdo_pgsql_driver.php b/system/database/drivers/pdo/subdrivers/pdo_pgsql_driver.php
new file mode 100644
index 000000000..2eb0606b3
--- /dev/null
+++ b/system/database/drivers/pdo/subdrivers/pdo_pgsql_driver.php
@@ -0,0 +1,357 @@
+<?php
+/**
+ * CodeIgniter
+ *
+ * An open source application development framework for PHP 5.2.4 or newer
+ *
+ * NOTICE OF LICENSE
+ *
+ * Licensed under the Open Software License version 3.0
+ *
+ * This source file is subject to the Open Software License (OSL 3.0) that is
+ * bundled with this package in the files license.txt / license.rst. It is
+ * also available through the world wide web at this URL:
+ * http://opensource.org/licenses/OSL-3.0
+ * If you did not receive a copy of the license and are unable to obtain it
+ * through the world wide web, please send an email to
+ * licensing@ellislab.com so we can send you a copy immediately.
+ *
+ * @package CodeIgniter
+ * @author EllisLab Dev Team
+ * @copyright Copyright (c) 2008 - 2012, EllisLab, Inc. (http://ellislab.com/)
+ * @license http://opensource.org/licenses/OSL-3.0 Open Software License (OSL 3.0)
+ * @link http://codeigniter.com
+ * @since Version 3.0.0
+ * @filesource
+ */
+defined('BASEPATH') OR exit('No direct script access allowed');
+
+/**
+ * PDO PostgreSQL Database Adapter Class
+ *
+ * Note: _DB is an extender class that the app controller
+ * creates dynamically based on whether the query builder
+ * class is being used or not.
+ *
+ * @package CodeIgniter
+ * @subpackage Drivers
+ * @category Database
+ * @author EllisLab Dev Team
+ * @link http://codeigniter.com/user_guide/database/
+ */
+class CI_DB_pdo_pgsql_driver extends CI_DB_pdo_driver {
+
+ /**
+ * Sub-driver
+ *
+ * @var string
+ */
+ public $subdriver = 'pgsql';
+
+ /**
+ * Database schema
+ *
+ * @var string
+ */
+ public $schema = 'public';
+
+ // --------------------------------------------------------------------
+
+ /**
+ * ORDER BY random keyword
+ *
+ * @var array
+ */
+ protected $_random_keyword = array('RANDOM()', 'RANDOM()');
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Class constructor
+ *
+ * Builds the DSN if not already set.
+ *
+ * @param array $params
+ * @return void
+ */
+ public function __construct($params)
+ {
+ parent::__construct($params);
+
+ if (empty($this->dsn))
+ {
+ $this->dsn = 'pgsql:host='.(empty($this->hostname) ? '127.0.0.1' : $this->hostname);
+
+ empty($this->port) OR $this->dsn .= ';port='.$this->port;
+ empty($this->database) OR $this->dsn .= ';dbname='.$this->database;
+ }
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Database connection
+ *
+ * @param bool $persistent
+ * @return object
+ */
+ public function db_connect($persistent = FALSE)
+ {
+ $this->conn_id = parent::db_connect($persistent);
+
+ if (is_object($this->conn_id) && ! empty($this->schema))
+ {
+ $this->simple_query('SET search_path TO '.$this->schema.',public');
+ }
+
+ return $this->conn_id;
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Insert ID
+ *
+ * @param string $name
+ * @return int
+ */
+ public function insert_id($name = NULL)
+ {
+ if ($name === NULL && version_compare($this->version(), '8.1', '>='))
+ {
+ $query = $this->query('SELECT LASTVAL() AS ins_id');
+ $query = $query->row();
+ return $query->ins_id;
+ }
+
+ return $this->conn_id->lastInsertId($name);
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * "Smart" Escape String
+ *
+ * Escapes data based on type
+ *
+ * @param string $str
+ * @return mixed
+ */
+ public function escape($str)
+ {
+ if (is_bool($str))
+ {
+ return ($str) ? 'TRUE' : 'FALSE';
+ }
+
+ return parent::escape($str);
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * ORDER BY
+ *
+ * @param string $orderby
+ * @param string $direction ASC or DESC
+ * @param bool $escape
+ * @return object
+ */
+ public function order_by($orderby, $direction = '', $escape = NULL)
+ {
+ $direction = strtoupper(trim($direction));
+ if ($direction === 'RANDOM')
+ {
+ if ( ! is_float($orderby) && ctype_digit((string) $orderby))
+ {
+ $orderby = ($orderby > 1)
+ ? (float) '0.'.$orderby
+ : (float) $orderby;
+ }
+
+ if (is_float($orderby))
+ {
+ $this->simple_query('SET SEED '.$orderby);
+ }
+
+ $orderby = $this->_random_keyword[0];
+ $direction = '';
+ $escape = FALSE;
+ }
+
+ return parent::order_by($orderby, $direction, $escape);
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Show table query
+ *
+ * Generates a platform-specific query string so that the table names can be fetched
+ *
+ * @param bool $prefix_limit
+ * @return string
+ */
+ protected function _list_tables($prefix_limit = FALSE)
+ {
+ $sql = 'SELECT "table_name" FROM "information_schema"."tables" WHERE "table_schema" = \''.$this->schema."'";
+
+ if ($prefix_limit === TRUE && $this->dbprefix !== '')
+ {
+ return $sql.' AND "table_name" LIKE \''
+ .$this->escape_like_str($this->dbprefix)."%' "
+ .sprintf($this->_like_escape_str, $this->_like_escape_chr);
+ }
+
+ return $sql;
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * List column query
+ *
+ * Generates a platform-specific query string so that the column names can be fetched
+ *
+ * @param string $table
+ * @return string
+ */
+ protected function _list_columns($table = '')
+ {
+ return 'SELECT "column_name"
+ FROM "information_schema"."columns"
+ WHERE LOWER("table_name") = '.$this->escape(strtolower($table));
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Returns an object with field data
+ *
+ * @param string $table
+ * @return array
+ */
+ public function field_data($table = '')
+ {
+ if ($table === '')
+ {
+ return ($this->db_debug) ? $this->display_error('db_field_param_missing') : FALSE;
+ }
+
+ $sql = 'SELECT "column_name", "data_type", "character_maximum_length", "numeric_precision", "column_default"
+ FROM "information_schema"."columns"
+ WHERE LOWER("table_name") = '.$this->escape(strtolower($table));
+
+ if (($query = $this->query($sql)) === FALSE)
+ {
+ return FALSE;
+ }
+ $query = $query->result_object();
+
+ $retval = array();
+ for ($i = 0, $c = count($query); $i < $c; $i++)
+ {
+ $retval[$i] = new stdClass();
+ $retval[$i]->name = $query[$i]->column_name;
+ $retval[$i]->type = $query[$i]->data_type;
+ $retval[$i]->max_length = ($query[$i]->character_maximum_length > 0) ? $query[$i]->character_maximum_length : $query[$i]->numeric_precision;
+ $retval[$i]->default = $query[$i]->column_default;
+ }
+
+ return $retval;
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Update statement
+ *
+ * Generates a platform-specific update string from the supplied data
+ *
+ * @param string $table
+ * @param array $values
+ * @return string
+ */
+ protected function _update($table, $values)
+ {
+ $this->qb_limit = FALSE;
+ $this->qb_orderby = array();
+ return parent::_update($table, $values);
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Update_Batch statement
+ *
+ * Generates a platform-specific batch update string from the supplied data
+ *
+ * @param string $table Table name
+ * @param array $values Update data
+ * @param string $index WHERE key
+ * @return string
+ */
+ protected function _update_batch($table, $values, $index)
+ {
+ $ids = array();
+ foreach ($values as $key => $val)
+ {
+ $ids[] = $val[$index];
+
+ foreach (array_keys($val) as $field)
+ {
+ if ($field !== $index)
+ {
+ $final[$field][] = 'WHEN '.$val[$index].' THEN '.$val[$field];
+ }
+ }
+ }
+
+ $cases = '';
+ foreach ($final as $k => $v)
+ {
+ $cases .= $k.' = (CASE '.$index."\n"
+ .implode("\n", $v)."\n"
+ .'ELSE '.$k.' END), ';
+ }
+
+ $this->where($index.' IN('.implode(',', $ids).')', NULL, FALSE);
+
+ return 'UPDATE '.$table.' SET '.substr($cases, 0, -2).$this->_compile_wh('qb_where');
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Delete statement
+ *
+ * Generates a platform-specific delete string from the supplied data
+ *
+ * @param string $table
+ * @return string
+ */
+ protected function _delete($table)
+ {
+ $this->qb_limit = FALSE;
+ return parent::_delete($table);
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * LIMIT
+ *
+ * Generates a platform-specific LIMIT clause
+ *
+ * @param string $sql SQL Query
+ * @return string
+ */
+ protected function _limit($sql)
+ {
+ return $sql.' LIMIT '.$this->qb_limit.($this->qb_offset ? ' OFFSET '.$this->qb_offset : '');
+ }
+
+}
+
+/* End of file pdo_pgsql_driver.php */
+/* Location: ./system/database/drivers/pdo/subdrivers/pdo_pgsql_driver.php */ \ No newline at end of file
diff --git a/system/database/drivers/pdo/subdrivers/pdo_pgsql_forge.php b/system/database/drivers/pdo/subdrivers/pdo_pgsql_forge.php
new file mode 100644
index 000000000..a24c898af
--- /dev/null
+++ b/system/database/drivers/pdo/subdrivers/pdo_pgsql_forge.php
@@ -0,0 +1,195 @@
+<?php
+/**
+ * CodeIgniter
+ *
+ * An open source application development framework for PHP 5.2.4 or newer
+ *
+ * NOTICE OF LICENSE
+ *
+ * Licensed under the Open Software License version 3.0
+ *
+ * This source file is subject to the Open Software License (OSL 3.0) that is
+ * bundled with this package in the files license.txt / license.rst. It is
+ * also available through the world wide web at this URL:
+ * http://opensource.org/licenses/OSL-3.0
+ * If you did not receive a copy of the license and are unable to obtain it
+ * through the world wide web, please send an email to
+ * licensing@ellislab.com so we can send you a copy immediately.
+ *
+ * @package CodeIgniter
+ * @author EllisLab Dev Team
+ * @copyright Copyright (c) 2008 - 2012, EllisLab, Inc. (http://ellislab.com/)
+ * @license http://opensource.org/licenses/OSL-3.0 Open Software License (OSL 3.0)
+ * @link http://codeigniter.com
+ * @since Version 2.1.0
+ * @filesource
+ */
+defined('BASEPATH') OR exit('No direct script access allowed');
+
+/**
+ * PDO PostgreSQL Forge Class
+ *
+ * @category Database
+ * @author EllisLab Dev Team
+ * @link http://codeigniter.com/user_guide/database/
+ */
+class CI_DB_pdo_pgsql_forge extends CI_DB_pdo_forge {
+
+ /**
+ * DROP TABLE IF statement
+ *
+ * @var string
+ */
+ protected $_drop_table_if = 'DROP TABLE IF EXISTS';
+
+ /**
+ * UNSIGNED support
+ *
+ * @var array
+ */
+ protected $_unsigned = array(
+ 'INT2' => 'INTEGER',
+ 'SMALLINT' => 'INTEGER',
+ 'INT' => 'BIGINT',
+ 'INT4' => 'BIGINT',
+ 'INTEGER' => 'BIGINT',
+ 'INT8' => 'NUMERIC',
+ 'BIGINT' => 'NUMERIC',
+ 'REAL' => 'DOUBLE PRECISION',
+ 'FLOAT' => 'DOUBLE PRECISION'
+ );
+
+ /**
+ * NULL value representation in CREATE/ALTER TABLE statements
+ *
+ * @var string
+ */
+ protected $_null = 'NULL';
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Class constructor
+ *
+ * @param object &$db Database object
+ * @return void
+ */
+ public function __construct(&$db)
+ {
+ parent::__construct($db);
+
+ if (version_compare($this->db->version(), '9.0', '>'))
+ {
+ $this->create_table_if = 'CREATE TABLE IF NOT EXISTS';
+ }
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * ALTER TABLE
+ *
+ * @param string $alter_type ALTER type
+ * @param string $table Table name
+ * @param mixed $field Column definition
+ * @return string|string[]
+ */
+ protected function _alter_table($alter_type, $table, $field)
+ {
+ if (in_array($alter_type, array('DROP', 'ADD'), TRUE))
+ {
+ return parent::_alter_table($alter_type, $table, $field);
+ }
+
+ $sql = 'ALTER TABLE '.$this->db->escape_identifiers($table);
+ $sqls = array();
+ for ($i = 0, $c = count($field); $i < $c; $i++)
+ {
+ if ($field[$i]['_literal'] !== FALSE)
+ {
+ return FALSE;
+ }
+
+ if (version_compare($this->db->version(), '8', '>=') && isset($field[$i]['type']))
+ {
+ $sqls[] = $sql.' ALTER COLUMN '.$this->db->escape_identifiers($field[$i]['name'])
+ .' TYPE '.$field[$i]['type'].$field[$i]['length'];
+ }
+
+ if ( ! empty($field[$i]['default']))
+ {
+ $sqls[] = $sql.' ALTER COLUMN '.$this->db->escape_identifiers($field[$i]['name'])
+ .' SET DEFAULT '.$field[$i]['default'];
+ }
+
+ if (isset($field[$i]['null']))
+ {
+ $sqls[] = $sql.' ALTER COLUMN '.$this->db->escape_identifiers($field[$i]['name'])
+ .($field[$i]['null'] === TRUE ? ' DROP NOT NULL' : ' SET NOT NULL');
+ }
+
+ if ( ! empty($field[$i]['new_name']))
+ {
+ $sqls[] = $sql.' RENAME COLUMN '.$this->db->escape_identifiers($field[$i]['name'])
+ .' TO '.$this->db->escape_identifiers($field[$i]['new_name']);
+ }
+ }
+
+ return $sqls;
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Field attribute TYPE
+ *
+ * Performs a data type mapping between different databases.
+ *
+ * @param array &$attributes
+ * @return void
+ */
+ protected function _attr_type(&$attributes)
+ {
+ // Reset field lenghts for data types that don't support it
+ if (isset($attributes['CONSTRAINT']) && stripos($attributes['TYPE'], 'int') !== FALSE)
+ {
+ $attributes['CONSTRAINT'] = NULL;
+ }
+
+ switch (strtoupper($attributes['TYPE']))
+ {
+ case 'TINYINT':
+ $attributes['TYPE'] = 'SMALLINT';
+ $attributes['UNSIGNED'] = FALSE;
+ return;
+ case 'MEDIUMINT':
+ $attributes['TYPE'] = 'INTEGER';
+ $attributes['UNSIGNED'] = FALSE;
+ return;
+ default: return;
+ }
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Field attribute AUTO_INCREMENT
+ *
+ * @param array &$attributes
+ * @param array &$field
+ * @return void
+ */
+ protected function _attr_auto_increment(&$attributes, &$field)
+ {
+ if ( ! empty($attributes['AUTO_INCREMENT']) && $attributes['AUTO_INCREMENT'] === TRUE)
+ {
+ $field['type'] = ($field['type'] === 'NUMERIC')
+ ? 'BIGSERIAL'
+ : 'SERIAL';
+ }
+ }
+
+}
+
+/* End of file pdo_pgsql_forge.php */
+/* Location: ./system/database/drivers/pdo/subdrivers/pdo_pgsql_forge.php */ \ No newline at end of file
diff --git a/system/database/drivers/pdo/subdrivers/pdo_sqlite_driver.php b/system/database/drivers/pdo/subdrivers/pdo_sqlite_driver.php
new file mode 100644
index 000000000..568044e2d
--- /dev/null
+++ b/system/database/drivers/pdo/subdrivers/pdo_sqlite_driver.php
@@ -0,0 +1,202 @@
+<?php
+/**
+ * CodeIgniter
+ *
+ * An open source application development framework for PHP 5.2.4 or newer
+ *
+ * NOTICE OF LICENSE
+ *
+ * Licensed under the Open Software License version 3.0
+ *
+ * This source file is subject to the Open Software License (OSL 3.0) that is
+ * bundled with this package in the files license.txt / license.rst. It is
+ * also available through the world wide web at this URL:
+ * http://opensource.org/licenses/OSL-3.0
+ * If you did not receive a copy of the license and are unable to obtain it
+ * through the world wide web, please send an email to
+ * licensing@ellislab.com so we can send you a copy immediately.
+ *
+ * @package CodeIgniter
+ * @author EllisLab Dev Team
+ * @copyright Copyright (c) 2008 - 2012, EllisLab, Inc. (http://ellislab.com/)
+ * @license http://opensource.org/licenses/OSL-3.0 Open Software License (OSL 3.0)
+ * @link http://codeigniter.com
+ * @since Version 3.0.0
+ * @filesource
+ */
+defined('BASEPATH') OR exit('No direct script access allowed');
+
+/**
+ * PDO SQLite Database Adapter Class
+ *
+ * Note: _DB is an extender class that the app controller
+ * creates dynamically based on whether the query builder
+ * class is being used or not.
+ *
+ * @package CodeIgniter
+ * @subpackage Drivers
+ * @category Database
+ * @author EllisLab Dev Team
+ * @link http://codeigniter.com/user_guide/database/
+ */
+class CI_DB_pdo_sqlite_driver extends CI_DB_pdo_driver {
+
+ /**
+ * Sub-driver
+ *
+ * @var string
+ */
+ public $subdriver = 'sqlite';
+
+ // --------------------------------------------------------------------
+
+ /**
+ * ORDER BY random keyword
+ *
+ * @var array
+ */
+ protected $_random_keyword = ' RANDOM()';
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Class constructor
+ *
+ * Builds the DSN if not already set.
+ *
+ * @param array $params
+ * @return void
+ */
+ public function __construct($params)
+ {
+ parent::__construct($params);
+
+ if (empty($this->dsn))
+ {
+ $this->dsn = 'sqlite:';
+
+ if (empty($this->database) && empty($this->hostname))
+ {
+ $this->database = ':memory:';
+ }
+
+ $this->database = empty($this->database) ? $this->hostname : $this->database;
+ }
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Show table query
+ *
+ * Generates a platform-specific query string so that the table names can be fetched
+ *
+ * @param bool $prefix_limit
+ * @return string
+ */
+ protected function _list_tables($prefix_limit = FALSE)
+ {
+ $sql = 'SELECT "NAME" FROM "SQLITE_MASTER" WHERE "TYPE" = \'table\'';
+
+ if ($prefix_limit === TRUE && $this->dbprefix !== '')
+ {
+ return $sql.' AND "NAME" LIKE \''.$this->escape_like_str($this->dbprefix)."%' "
+ .sprintf($this->_like_escape_str, $this->_like_escape_chr);
+ }
+
+ return $sql;
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Show column query
+ *
+ * Generates a platform-specific query string so that the column names can be fetched
+ *
+ * @param string $table
+ * @return string
+ */
+ protected function _list_columns($table = '')
+ {
+ // Not supported
+ return FALSE;
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Returns an object with field data
+ *
+ * @param string $table
+ * @return array
+ */
+ public function field_data($table = '')
+ {
+ if ($table === '')
+ {
+ return ($this->db_debug) ? $this->display_error('db_field_param_missing') : FALSE;
+ }
+
+ if (($query = $this->query('PRAGMA TABLE_INFO('.$this->protect_identifiers($table, TRUE, NULL, FALSE).')')) === FALSE)
+ {
+ return FALSE;
+ }
+
+ $query = $query->result_array();
+ if (empty($query))
+ {
+ return FALSE;
+ }
+
+ $retval = array();
+ for ($i = 0, $c = count($query); $i < $c; $i++)
+ {
+ $retval[$i] = new stdClass();
+ $retval[$i]->name = $query[$i]['name'];
+ $retval[$i]->type = $query[$i]['type'];
+ $retval[$i]->max_length = NULL;
+ $retval[$i]->default = $query[$i]['dflt_value'];
+ $retval[$i]->primary_key = isset($query[$i]['pk']) ? (int) $query[$i]['pk'] : 0;
+ }
+
+ return $retval;
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Replace statement
+ *
+ * @param string $table Table name
+ * @param array $keys INSERT keys
+ * @param array $values INSERT values
+ * @return string
+ */
+ protected function _replace($table, $keys, $values)
+ {
+ return 'INSERT OR '.parent::_replace($table, $keys, $values);
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Truncate statement
+ *
+ * Generates a platform-specific truncate string from the supplied data
+ *
+ * If the database does not support the TRUNCATE statement,
+ * then this method maps to 'DELETE FROM table'
+ *
+ * @param string $table
+ * @return string
+ */
+ protected function _truncate($table)
+ {
+ return 'DELETE FROM '.$table;
+ }
+
+}
+
+/* End of file pdo_sqlite_driver.php */
+/* Location: ./system/database/drivers/pdo/subdrivers/pdo_sqlite_driver.php */ \ No newline at end of file
diff --git a/system/database/drivers/pdo/subdrivers/pdo_sqlite_forge.php b/system/database/drivers/pdo/subdrivers/pdo_sqlite_forge.php
new file mode 100644
index 000000000..da098df31
--- /dev/null
+++ b/system/database/drivers/pdo/subdrivers/pdo_sqlite_forge.php
@@ -0,0 +1,229 @@
+<?php
+/**
+ * CodeIgniter
+ *
+ * An open source application development framework for PHP 5.1.6 or newer
+ *
+ * NOTICE OF LICENSE
+ *
+ * Licensed under the Open Software License version 3.0
+ *
+ * This source file is subject to the Open Software License (OSL 3.0) that is
+ * bundled with this package in the files license.txt / license.rst. It is
+ * also available through the world wide web at this URL:
+ * http://opensource.org/licenses/OSL-3.0
+ * If you did not receive a copy of the license and are unable to obtain it
+ * through the world wide web, please send an email to
+ * licensing@ellislab.com so we can send you a copy immediately.
+ *
+ * @package CodeIgniter
+ * @author EllisLab Dev Team
+ * @copyright Copyright (c) 2008 - 2012, EllisLab, Inc. (http://ellislab.com/)
+ * @license http://opensource.org/licenses/OSL-3.0 Open Software License (OSL 3.0)
+ * @link http://codeigniter.com
+ * @since Version 2.1.0
+ * @filesource
+ */
+defined('BASEPATH') OR exit('No direct script access allowed');
+
+/**
+ * PDO SQLite Forge Class
+ *
+ * @category Database
+ * @author EllisLab Dev Team
+ * @link http://codeigniter.com/user_guide/database/
+ */
+class CI_DB_pdo_sqlite_forge extends CI_DB_pdo_forge {
+
+ /**
+ * CREATE TABLE IF statement
+ *
+ * @var string
+ */
+ protected $_create_table_if = 'CREATE TABLE IF NOT EXISTS';
+
+ /**
+ * DROP TABLE IF statement
+ *
+ * @var string
+ */
+ protected $_drop_table_if = 'DROP TABLE IF EXISTS';
+
+ /**
+ * UNSIGNED support
+ *
+ * @var bool|array
+ */
+ protected $_unsigned = FALSE;
+
+ /**
+ * NULL value representation in CREATE/ALTER TABLE statements
+ *
+ * @var string
+ */
+ protected $_null = 'NULL';
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Class constructor
+ *
+ * @param object &$db Database object
+ * @return void
+ */
+ public function __construct(&$db)
+ {
+ parent::__construct($db);
+
+ if (version_compare($this->db->version(), '3.3', '<'))
+ {
+ $this->_create_table_if = FALSE;
+ }
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Create database
+ *
+ * @param string $db_name (ignored)
+ * @return bool
+ */
+ public function create_database($db_name = '')
+ {
+ // In SQLite, a database is created when you connect to the database.
+ // We'll return TRUE so that an error isn't generated
+ return TRUE;
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Drop database
+ *
+ * @param string $db_name (ignored)
+ * @return bool
+ */
+ public function drop_database($db_name = '')
+ {
+ // In SQLite, a database is dropped when we delete a file
+ if (@file_exists($this->db->database))
+ {
+ // We need to close the pseudo-connection first
+ $this->db->close();
+ if ( ! @unlink($this->db->database))
+ {
+ return $this->db->db_debug ? $this->db->display_error('db_unable_to_drop') : FALSE;
+ }
+ elseif ( ! empty($this->db->data_cache['db_names']))
+ {
+ $key = array_search(strtolower($this->db->database), array_map('strtolower', $this->db->data_cache['db_names']), TRUE);
+ if ($key !== FALSE)
+ {
+ unset($this->db->data_cache['db_names'][$key]);
+ }
+ }
+
+ return TRUE;
+ }
+
+ return $this->db->db_debug ? $this->db->display_error('db_unable_to_drop') : FALSE;
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * ALTER TABLE
+ *
+ * @param string $alter_type ALTER type
+ * @param string $table Table name
+ * @param mixed $field Column definition
+ * @return string|string[]
+ */
+ protected function _alter_table($alter_type, $table, $field)
+ {
+ if ($alter_type === 'DROP' OR $alter_type === 'CHANGE')
+ {
+ // drop_column():
+ // BEGIN TRANSACTION;
+ // CREATE TEMPORARY TABLE t1_backup(a,b);
+ // INSERT INTO t1_backup SELECT a,b FROM t1;
+ // DROP TABLE t1;
+ // CREATE TABLE t1(a,b);
+ // INSERT INTO t1 SELECT a,b FROM t1_backup;
+ // DROP TABLE t1_backup;
+ // COMMIT;
+
+ return FALSE;
+ }
+
+ return parent::_alter_table($alter_type, $table, $field);
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Process column
+ *
+ * @param array $field
+ * @return string
+ */
+ protected function _process_column($field)
+ {
+ return $this->db->escape_identifiers($field['name'])
+ .' '.$field['type']
+ .$field['auto_increment']
+ .$field['null']
+ .$field['unique']
+ .$field['default'];
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Field attribute TYPE
+ *
+ * Performs a data type mapping between different databases.
+ *
+ * @param array &$attributes
+ * @return void
+ */
+ protected function _attr_type(&$attributes)
+ {
+ switch (strtoupper($attributes['TYPE']))
+ {
+ case 'ENUM':
+ case 'SET':
+ $attributes['TYPE'] = 'TEXT';
+ return;
+ default: return;
+ }
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Field attribute AUTO_INCREMENT
+ *
+ * @param array &$attributes
+ * @param array &$field
+ * @return void
+ */
+ protected function _attr_auto_increment(&$attributes, &$field)
+ {
+ if ( ! empty($attributes['AUTO_INCREMENT']) && $attributes['AUTO_INCREMENT'] === TRUE && stripos($field['type'], 'int') !== FALSE)
+ {
+ $field['type'] = 'INTEGER PRIMARY KEY';
+ $field['default'] = '';
+ $field['null'] = '';
+ $field['unique'] = '';
+ $field['auto_increment'] = ' AUTOINCREMENT';
+
+ $this->primary_keys = array();
+ }
+ }
+
+}
+
+/* End of file pdo_sqlite_forge.php */
+/* Location: ./system/database/drivers/pdo/subdrivers/pdo_sqlite_forge.php */ \ No newline at end of file
diff --git a/system/database/drivers/pdo/subdrivers/pdo_sqlsrv_driver.php b/system/database/drivers/pdo/subdrivers/pdo_sqlsrv_driver.php
new file mode 100644
index 000000000..ec0252613
--- /dev/null
+++ b/system/database/drivers/pdo/subdrivers/pdo_sqlsrv_driver.php
@@ -0,0 +1,363 @@
+<?php
+/**
+ * CodeIgniter
+ *
+ * An open source application development framework for PHP 5.2.4 or newer
+ *
+ * NOTICE OF LICENSE
+ *
+ * Licensed under the Open Software License version 3.0
+ *
+ * This source file is subject to the Open Software License (OSL 3.0) that is
+ * bundled with this package in the files license.txt / license.rst. It is
+ * also available through the world wide web at this URL:
+ * http://opensource.org/licenses/OSL-3.0
+ * If you did not receive a copy of the license and are unable to obtain it
+ * through the world wide web, please send an email to
+ * licensing@ellislab.com so we can send you a copy immediately.
+ *
+ * @package CodeIgniter
+ * @author EllisLab Dev Team
+ * @copyright Copyright (c) 2008 - 2012, EllisLab, Inc. (http://ellislab.com/)
+ * @license http://opensource.org/licenses/OSL-3.0 Open Software License (OSL 3.0)
+ * @link http://codeigniter.com
+ * @since Version 3.0.0
+ * @filesource
+ */
+defined('BASEPATH') OR exit('No direct script access allowed');
+
+/**
+ * PDO SQLSRV Database Adapter Class
+ *
+ * Note: _DB is an extender class that the app controller
+ * creates dynamically based on whether the query builder
+ * class is being used or not.
+ *
+ * @package CodeIgniter
+ * @subpackage Drivers
+ * @category Database
+ * @author EllisLab Dev Team
+ * @link http://codeigniter.com/user_guide/database/
+ */
+class CI_DB_pdo_sqlsrv_driver extends CI_DB_pdo_driver {
+
+ /**
+ * Sub-driver
+ *
+ * @var string
+ */
+ public $subdriver = 'sqlsrv';
+
+ // --------------------------------------------------------------------
+
+ /**
+ * ORDER BY random keyword
+ *
+ * @var array
+ */
+ protected $_random_keyword = array('NEWID()', 'RAND(%d)');
+
+ /**
+ * Quoted identifier flag
+ *
+ * Whether to use SQL-92 standard quoted identifier
+ * (double quotes) or brackets for identifier escaping.
+ *
+ * @var bool
+ */
+ protected $_quoted_identifier;
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Class constructor
+ *
+ * Builds the DSN if not already set.
+ *
+ * @param array $params
+ * @return void
+ */
+ public function __construct($params)
+ {
+ parent::__construct($params);
+
+ if (empty($this->dsn))
+ {
+ $this->dsn = 'sqlsrv:Server='.(empty($this->hostname) ? '127.0.0.1' : $this->hostname);
+
+ empty($this->port) OR $this->dsn .= ','.$this->port;
+ empty($this->database) OR $this->dsn .= ';Database='.$this->database;
+
+ // Some custom options
+
+ if (isset($this->QuotedId))
+ {
+ $this->dsn .= ';QuotedId='.$this->QuotedId;
+ $this->_quoted_identifier = (bool) $this->QuotedId;
+ }
+
+ if (isset($this->ConnectionPooling))
+ {
+ $this->dsn .= ';ConnectionPooling='.$this->ConnectionPooling;
+ }
+
+ if ($this->encrypt === TRUE)
+ {
+ $this->dsn .= ';Encrypt=1';
+ }
+
+ if (isset($this->TraceOn))
+ {
+ $this->dsn .= ';TraceOn='.$this->TraceOn;
+ }
+
+ if (isset($this->TrustServerCertificate))
+ {
+ $this->dsn .= ';TrustServerCertificate='.$this->TrustServerCertificate;
+ }
+
+ empty($this->APP) OR $this->dsn .= ';APP='.$this->APP;
+ empty($this->Failover_Partner) OR $this->dsn .= ';Failover_Partner='.$this->Failover_Partner;
+ empty($this->LoginTimeout) OR $this->dsn .= ';LoginTimeout='.$this->LoginTimeout;
+ empty($this->MultipleActiveResultSets) OR $this->dsn .= ';MultipleActiveResultSets='.$this->MultipleActiveResultSets;
+ empty($this->TraceFile) OR $this->dsn .= ';TraceFile='.$this->TraceFile;
+ empty($this->WSID) OR $this->dsn .= ';WSID='.$this->WSID;
+ }
+ elseif (preg_match('/QuotedId=(0|1)/', $this->dsn, $match))
+ {
+ $this->_quoted_identifier = (bool) $match[1];
+ }
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Database connection
+ *
+ * @param bool $persistent
+ * @return object
+ */
+ public function db_connect($persistent = FALSE)
+ {
+ if ( ! empty($this->char_set) && preg_match('/utf[^8]*8/i', $this->char_set))
+ {
+ $this->options[PDO::SQLSRV_ENCODING_UTF8] = 1;
+ }
+
+ $this->conn_id = parent::db_connect($persistent);
+
+ if ( ! is_object($this->conn_id) OR is_bool($this->_quoted_identifier))
+ {
+ return $this->conn_id;
+ }
+
+ // Determine how identifiers are escaped
+ $query = $this->query('SELECT CASE WHEN (@@OPTIONS | 256) = @@OPTIONS THEN 1 ELSE 0 END AS qi');
+ $query = $query->row_array();
+ $this->_quoted_identifier = empty($query) ? FALSE : (bool) $query['qi'];
+ $this->_escape_char = ($this->_quoted_identifier) ? '"' : array('[', ']');
+
+ return $this->conn_id;
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Show table query
+ *
+ * Generates a platform-specific query string so that the table names can be fetched
+ *
+ * @param bool $prefix_limit
+ * @return string
+ */
+ protected function _list_tables($prefix_limit = FALSE)
+ {
+ return 'SELECT '.$this->escape_identifiers('name')
+ .' FROM '.$this->escape_identifiers('sysobjects')
+ .' WHERE '.$this->escape_identifiers('type')." = 'U'";
+
+ if ($prefix_limit === TRUE && $this->dbprefix !== '')
+ {
+ $sql .= ' AND '.$this->escape_identifiers('name')." LIKE '".$this->escape_like_str($this->dbprefix)."%' "
+ .sprintf($this->_like_escape_str, $this->_like_escape_chr);
+ }
+
+ return $sql.' ORDER BY '.$this->escape_identifiers('name');
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Show column query
+ *
+ * Generates a platform-specific query string so that the column names can be fetched
+ *
+ * @param string $table
+ * @return string
+ */
+ protected function _list_columns($table = '')
+ {
+ return 'SELECT COLUMN_NAME
+ FROM INFORMATION_SCHEMA.Columns
+ WHERE UPPER(TABLE_NAME) = '.$this->escape(strtoupper($table));
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Returns an object with field data
+ *
+ * @param string $table
+ * @return array
+ */
+ public function field_data($table = '')
+ {
+ if ($table === '')
+ {
+ return ($this->db_debug) ? $this->display_error('db_field_param_missing') : FALSE;
+ }
+
+ $sql = 'SELECT COLUMN_NAME, DATA_TYPE, CHARACTER_MAXIMUM_LENGTH, NUMERIC_PRECISION, COLUMN_DEFAULT
+ FROM INFORMATION_SCHEMA.Columns
+ WHERE UPPER(TABLE_NAME) = '.$this->escape(strtoupper($table));
+
+ if (($query = $this->query($sql)) === FALSE)
+ {
+ return FALSE;
+ }
+ $query = $query->result_object();
+
+ $retval = array();
+ for ($i = 0, $c = count($query); $i < $c; $i++)
+ {
+ $retval[$i] = new stdClass();
+ $retval[$i]->name = $query[$i]->COLUMN_NAME;
+ $retval[$i]->type = $query[$i]->DATA_TYPE;
+ $retval[$i]->max_length = ($query[$i]->CHARACTER_MAXIMUM_LENGTH > 0) ? $query[$i]->CHARACTER_MAXIMUM_LENGTH : $query[$i]->NUMERIC_PRECISION;
+ $retval[$i]->default = $query[$i]->COLUMN_DEFAULT;
+ }
+
+ return $retval;
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Update statement
+ *
+ * Generates a platform-specific update string from the supplied data
+ *
+ * @param string $table
+ * @param array $values
+ * @return string
+ */
+ protected function _update($table, $values)
+ {
+ $this->qb_limit = FALSE;
+ $this->qb_orderby = array();
+ return parent::_update($table, $values);
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Delete statement
+ *
+ * Generates a platform-specific delete string from the supplied data
+ *
+ * @param string $table
+ * @return string
+ */
+ protected function _delete($table)
+ {
+ if ($this->qb_limit)
+ {
+ return 'WITH ci_delete AS (SELECT TOP '.$this->qb_limit.' * FROM '.$table.$this->_compile_wh('qb_where').') DELETE FROM ci_delete';
+ }
+
+ return parent::_delete($table);
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * LIMIT
+ *
+ * Generates a platform-specific LIMIT clause
+ *
+ * @param string $sql SQL Query
+ * @return string
+ */
+ protected function _limit($sql)
+ {
+ // As of SQL Server 2012 (11.0.*) OFFSET is supported
+ if (version_compare($this->version(), '11', '>='))
+ {
+ return $sql.' OFFSET '.(int) $this->qb_offset.' ROWS FETCH NEXT '.$this->qb_limit.' ROWS ONLY';
+ }
+
+ $limit = $this->qb_offset + $this->qb_limit;
+
+ // An ORDER BY clause is required for ROW_NUMBER() to work
+ if ($this->qb_offset && ! empty($this->qb_orderby))
+ {
+ $orderby = $this->_compile_order_by();
+
+ // We have to strip the ORDER BY clause
+ $sql = trim(substr($sql, 0, strrpos($sql, $orderby)));
+
+ // Get the fields to select from our subquery, so that we can avoid CI_rownum appearing in the actual results
+ if (count($this->qb_select) === 0)
+ {
+ $select = '*'; // Inevitable
+ }
+ else
+ {
+ // Use only field names and their aliases, everything else is out of our scope.
+ $select = array();
+ $field_regexp = ($this->_quoted_identifier)
+ ? '("[^\"]+")' : '(\[[^\]]+\])';
+ for ($i = 0, $c = count($this->qb_select); $i < $c; $i++)
+ {
+ $select[] = preg_match('/(?:\s|\.)'.$field_regexp.'$/i', $this->qb_select[$i], $m)
+ ? $m[1] : $this->qb_select[$i];
+ }
+ $select = implode(', ', $select);
+ }
+
+ return 'SELECT '.$select." FROM (\n\n"
+ .preg_replace('/^(SELECT( DISTINCT)?)/i', '\\1 ROW_NUMBER() OVER('.trim($orderby).') AS '.$this->escape_identifiers('CI_rownum').', ', $sql)
+ ."\n\n) ".$this->escape_identifiers('CI_subquery')
+ ."\nWHERE ".$this->escape_identifiers('CI_rownum').' BETWEEN '.($this->qb_offset + 1).' AND '.$limit;
+ }
+
+ return preg_replace('/(^\SELECT (DISTINCT)?)/i','\\1 TOP '.$limit.' ', $sql);
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Insert batch statement
+ *
+ * Generates a platform-specific insert string from the supplied data.
+ *
+ * @param string $table Table name
+ * @param array $keys INSERT keys
+ * @param array $values INSERT values
+ * @return string|bool
+ */
+ protected function _insert_batch($table, $keys, $values)
+ {
+ // Multiple-value inserts are only supported as of SQL Server 2008
+ if (version_compare($this->version(), '10', '>='))
+ {
+ return parent::_insert_batch($table, $keys, $values);
+ }
+
+ return ($this->db->db_debug) ? $this->db->display_error('db_unsupported_feature') : FALSE;
+ }
+
+}
+
+/* End of file pdo_sqlsrv_driver.php */
+/* Location: ./system/database/drivers/pdo/subdrivers/pdo_sqlsrv_driver.php */ \ No newline at end of file
diff --git a/system/database/drivers/pdo/subdrivers/pdo_sqlsrv_forge.php b/system/database/drivers/pdo/subdrivers/pdo_sqlsrv_forge.php
new file mode 100644
index 000000000..e4b669f6e
--- /dev/null
+++ b/system/database/drivers/pdo/subdrivers/pdo_sqlsrv_forge.php
@@ -0,0 +1,136 @@
+<?php
+/**
+ * CodeIgniter
+ *
+ * An open source application development framework for PHP 5.2.4 or newer
+ *
+ * NOTICE OF LICENSE
+ *
+ * Licensed under the Open Software License version 3.0
+ *
+ * This source file is subject to the Open Software License (OSL 3.0) that is
+ * bundled with this package in the files license.txt / license.rst. It is
+ * also available through the world wide web at this URL:
+ * http://opensource.org/licenses/OSL-3.0
+ * If you did not receive a copy of the license and are unable to obtain it
+ * through the world wide web, please send an email to
+ * licensing@ellislab.com so we can send you a copy immediately.
+ *
+ * @package CodeIgniter
+ * @author EllisLab Dev Team
+ * @copyright Copyright (c) 2008 - 2012, EllisLab, Inc. (http://ellislab.com/)
+ * @license http://opensource.org/licenses/OSL-3.0 Open Software License (OSL 3.0)
+ * @link http://codeigniter.com
+ * @since Version 2.1.0
+ * @filesource
+ */
+defined('BASEPATH') OR exit('No direct script access allowed');
+
+/**
+ * PDO SQLSRV Forge Class
+ *
+ * @category Database
+ * @author EllisLab Dev Team
+ * @link http://codeigniter.com/user_guide/database/
+ */
+class CI_DB_pdo_sqlsrv_forge extends CI_DB_pdo_forge {
+
+ /**
+ * CREATE TABLE IF statement
+ *
+ * @var string
+ */
+ protected $_create_table_if = "IF NOT EXISTS (SELECT * FROM sysobjects WHERE ID = object_id(N'%s') AND OBJECTPROPERTY(id, N'IsUserTable') = 1)\nCREATE TABLE";
+
+ /**
+ * DROP TABLE IF statement
+ *
+ * @var string
+ */
+ protected $_drop_table_if = "IF EXISTS (SELECT * FROM sysobjects WHERE ID = object_id(N'%s') AND OBJECTPROPERTY(id, N'IsUserTable') = 1)\nDROP TABLE";
+
+ /**
+ * UNSIGNED support
+ *
+ * @var array
+ */
+ protected $_unsigned = array(
+ 'TINYINT' => 'SMALLINT',
+ 'SMALLINT' => 'INT',
+ 'INT' => 'BIGINT',
+ 'REAL' => 'FLOAT'
+ );
+
+ // --------------------------------------------------------------------
+
+ /**
+ * ALTER TABLE
+ *
+ * @param string $alter_type ALTER type
+ * @param string $table Table name
+ * @param mixed $field Column definition
+ * @return string|string[]
+ */
+ protected function _alter_table($alter_type, $table, $field)
+ {
+ if (in_array($alter_type, array('ADD', 'DROP'), TRUE))
+ {
+ return parent::_alter_table($alter_type, $table, $field);
+ }
+
+ $sql = 'ALTER TABLE '.$this->db->escape_identifiers($table).' ALTER COLUMN ';
+ $sqls = array();
+ for ($i = 0, $c = count($field); $i < $c; $i++)
+ {
+ $sqls[] = $sql.$this->_process_column($field[$i]);
+ }
+
+ return $sqls;
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Field attribute TYPE
+ *
+ * Performs a data type mapping between different databases.
+ *
+ * @param array &$attributes
+ * @return void
+ */
+ protected function _attr_type(&$attributes)
+ {
+ switch (strtoupper($attributes['TYPE']))
+ {
+ case 'MEDIUMINT':
+ $attributes['TYPE'] = 'INTEGER';
+ $attributes['UNSIGNED'] = FALSE;
+ return;
+ case 'INTEGER':
+ $attributes['TYPE'] = 'INT';
+ return;
+ default: return;
+ }
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Field attribute AUTO_INCREMENT
+ *
+ * @param array &$attributes
+ * @param array &$field
+ * @return void
+ */
+ protected function _attr_auto_increment(&$attributes, &$field)
+ {
+ if ( ! empty($attributes['AUTO_INCREMENT']) && $attributes['AUTO_INCREMENT'] === TRUE && stripos($field['type'], 'int') !== FALSE)
+ {
+ $field['auto_increment'] = ' IDENTITY(1,1)';
+ }
+ }
+
+}
+
+/* End of file pdo_sqlsrv_forge.php */
+/* Location: ./system/database/drivers/pdo/subdrivers/pdo_sqlsrv_forge.php */ \ No newline at end of file
diff --git a/system/database/drivers/postgre/postgre_driver.php b/system/database/drivers/postgre/postgre_driver.php
index 14259be52..44cd0ce9b 100644
--- a/system/database/drivers/postgre/postgre_driver.php
+++ b/system/database/drivers/postgre/postgre_driver.php
@@ -1,4 +1,4 @@
-<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');
+<?php
/**
* CodeIgniter
*
@@ -24,12 +24,13 @@
* @since Version 1.0
* @filesource
*/
+defined('BASEPATH') OR exit('No direct script access allowed');
/**
* Postgre Database Adapter Class
*
* Note: _DB is an extender class that the app controller
- * creates dynamically based on whether the active record
+ * creates dynamically based on whether the query builder
* class is being used or not.
*
* @package CodeIgniter
@@ -40,27 +41,37 @@
*/
class CI_DB_postgre_driver extends CI_DB {
+ /**
+ * Database driver
+ *
+ * @var string
+ */
public $dbdriver = 'postgre';
- protected $_escape_char = '"';
+ /**
+ * Database schema
+ *
+ * @var string
+ */
+ public $schema = 'public';
- // clause and character used for LIKE escape sequences
- protected $_like_escape_str = " ESCAPE '%s' ";
- protected $_like_escape_chr = '!';
+ // --------------------------------------------------------------------
/**
- * The syntax to count rows is slightly different across different
- * database engines, so this string appears in each driver and is
- * used for the count_all() and count_all_results() functions.
+ * ORDER BY random keyword
+ *
+ * @var array
*/
- protected $_count_string = 'SELECT COUNT(*) AS ';
- protected $_random_keyword = ' RANDOM()'; // database specific random keyword
+ protected $_random_keyword = array('RANDOM()', 'RANDOM()');
+
+ // --------------------------------------------------------------------
/**
- * Constructor
+ * Class constructor
*
* Creates a DSN string to be used for db_connect() and db_pconnect()
*
+ * @param array $params
* @return void
*/
public function __construct($params)
@@ -120,13 +131,32 @@ class CI_DB_postgre_driver extends CI_DB {
// --------------------------------------------------------------------
/**
- * Non-persistent database connection
+ * Database connection
*
+ * @param bool $persistent
* @return resource
*/
- public function db_connect()
+ public function db_connect($persistent = FALSE)
{
- return @pg_connect($this->dsn);
+ if ($persistent === TRUE
+ && ($this->conn_id = @pg_pconnect($this->dsn))
+ && pg_connection_status($this->conn_id) === PGSQL_CONNECTION_BAD
+ && pg_ping($this->conn_id) === FALSE
+ )
+ {
+ return FALSE;
+ }
+ else
+ {
+ $this->conn_id = @pg_connect($this->dsn);
+ }
+
+ if ($this->conn_id && ! empty($this->schema))
+ {
+ $this->simple_query('SET search_path TO '.$this->schema.',public');
+ }
+
+ return $this->conn_id;
}
// --------------------------------------------------------------------
@@ -138,7 +168,7 @@ class CI_DB_postgre_driver extends CI_DB {
*/
public function db_pconnect()
{
- return @pg_pconnect($this->dsn);
+ return $this->db_connect(TRUE);
}
// --------------------------------------------------------------------
@@ -164,8 +194,8 @@ class CI_DB_postgre_driver extends CI_DB {
/**
* Set client character set
*
- * @param string
- * @return bool
+ * @param string $charset
+ * @return bool
*/
protected function _db_set_charset($charset)
{
@@ -185,8 +215,12 @@ class CI_DB_postgre_driver extends CI_DB {
{
return $this->data_cache['version'];
}
+ elseif ( ! $this->conn_id)
+ {
+ $this->initialize();
+ }
- if (($pg_version = pg_version($this->conn_id)) === FALSE)
+ if ( ! $this->conn_id OR ($pg_version = pg_version($this->conn_id)) === FALSE)
{
return FALSE;
}
@@ -206,7 +240,7 @@ class CI_DB_postgre_driver extends CI_DB {
/**
* Execute the query
*
- * @param string an SQL query
+ * @param string $sql an SQL query
* @return resource
*/
protected function _execute($sql)
@@ -219,6 +253,7 @@ class CI_DB_postgre_driver extends CI_DB {
/**
* Begin Transaction
*
+ * @param bool $test_mode
* @return bool
*/
public function trans_begin($test_mode = FALSE)
@@ -234,7 +269,7 @@ class CI_DB_postgre_driver extends CI_DB {
// even if the queries produce a successful result.
$this->_trans_failure = ($test_mode === TRUE);
- return @pg_query($this->conn_id, 'BEGIN');
+ return (bool) @pg_query($this->conn_id, 'BEGIN');
}
// --------------------------------------------------------------------
@@ -252,7 +287,7 @@ class CI_DB_postgre_driver extends CI_DB {
return TRUE;
}
- return @pg_query($this->conn_id, 'COMMIT');
+ return (bool) @pg_query($this->conn_id, 'COMMIT');
}
// --------------------------------------------------------------------
@@ -270,7 +305,7 @@ class CI_DB_postgre_driver extends CI_DB {
return TRUE;
}
- return @pg_query($this->conn_id, 'ROLLBACK');
+ return (bool) @pg_query($this->conn_id, 'ROLLBACK');
}
// --------------------------------------------------------------------
@@ -278,8 +313,8 @@ class CI_DB_postgre_driver extends CI_DB {
/**
* Escape String
*
- * @param string
- * @param bool whether or not the string will be used in a LIKE condition
+ * @param string $str
+ * @param bool $like Whether or not the string will be used in a LIKE condition
* @return string
*/
public function escape_str($str, $like = FALSE)
@@ -310,6 +345,26 @@ class CI_DB_postgre_driver extends CI_DB {
// --------------------------------------------------------------------
/**
+ * "Smart" Escape String
+ *
+ * Escapes data based on type
+ *
+ * @param string $str
+ * @return mixed
+ */
+ public function escape($str)
+ {
+ if (is_bool($str))
+ {
+ return ($str) ? 'TRUE' : 'FALSE';
+ }
+
+ return parent::escape($str);
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
* Affected Rows
*
* @return int
@@ -328,63 +383,41 @@ class CI_DB_postgre_driver extends CI_DB {
*/
public function insert_id()
{
- $v = $this->version();
+ $v = pg_version($this->conn_id);
+ $v = isset($v['server']) ? $v['server'] : 0; // 'server' key is only available since PosgreSQL 7.4
- $table = func_num_args() > 0 ? func_get_arg(0) : NULL;
- $column = func_num_args() > 1 ? func_get_arg(1) : NULL;
+ $table = (func_num_args() > 0) ? func_get_arg(0) : NULL;
+ $column = (func_num_args() > 1) ? func_get_arg(1) : NULL;
- if ($table == NULL && $v >= '8.1')
- {
- $sql='SELECT LASTVAL() as ins_id';
- }
- elseif ($table != NULL && $column != NULL && $v >= '8.0')
+ if ($table === NULL && $v >= '8.1')
{
- $sql = sprintf("SELECT pg_get_serial_sequence('%s','%s') as seq", $table, $column);
- $query = $this->query($sql);
- $row = $query->row();
- $sql = sprintf("SELECT CURRVAL('%s') as ins_id", $row->seq);
+ $sql = 'SELECT LASTVAL() AS ins_id';
}
- elseif ($table != NULL)
+ elseif ($table !== NULL)
{
- // seq_name passed in table parameter
- $sql = sprintf("SELECT CURRVAL('%s') as ins_id", $table);
+ if ($column !== NULL && $v >= '8.0')
+ {
+ $sql = 'SELECT pg_get_serial_sequence(\''.$table."', '".$column."') AS seq";
+ $query = $this->query($sql);
+ $query = $query->row();
+ $seq = $query->seq;
+ }
+ else
+ {
+ // seq_name passed in table parameter
+ $seq = $table;
+ }
+
+ $sql = 'SELECT CURRVAL(\''.$seq."') AS ins_id";
}
else
{
return pg_last_oid($this->result_id);
}
- $query = $this->query($sql);
- $row = $query->row();
- return $row->ins_id;
- }
- // --------------------------------------------------------------------
-
- /**
- * "Count All" query
- *
- * Generates a platform-specific query string that counts all records in
- * the specified database
- *
- * @param string
- * @return string
- */
- public function count_all($table = '')
- {
- if ($table == '')
- {
- return 0;
- }
-
- $query = $this->query($this->_count_string.$this->protect_identifiers('numrows').' FROM '.$this->protect_identifiers($table, TRUE, NULL, FALSE));
- if ($query->num_rows() == 0)
- {
- return 0;
- }
-
- $row = $query->row();
- $this->_reset_select();
- return (int) $row->numrows;
+ $query = $this->query($sql);
+ $query = $query->row();
+ return (int) $query->ins_id;
}
// --------------------------------------------------------------------
@@ -394,16 +427,18 @@ class CI_DB_postgre_driver extends CI_DB {
*
* Generates a platform-specific query string so that the table names can be fetched
*
- * @param bool
+ * @param bool $prefix_limit
* @return string
*/
protected function _list_tables($prefix_limit = FALSE)
{
- $sql = "SELECT table_name FROM information_schema.tables WHERE table_schema = 'public'";
+ $sql = 'SELECT "table_name" FROM "information_schema"."tables" WHERE "table_schema" = \''.$this->schema."'";
- if ($prefix_limit !== FALSE AND $this->dbprefix != '')
+ if ($prefix_limit !== FALSE && $this->dbprefix !== '')
{
- $sql .= " AND table_name LIKE '".$this->escape_like_str($this->dbprefix)."%' ".sprintf($this->_like_escape_str, $this->_like_escape_chr);
+ return $sql.' AND "table_name" LIKE \''
+ .$this->escape_like_str($this->dbprefix)."%' "
+ .sprintf($this->_like_escape_str, $this->_like_escape_chr);
}
return $sql;
@@ -412,31 +447,56 @@ class CI_DB_postgre_driver extends CI_DB {
// --------------------------------------------------------------------
/**
- * Show column query
+ * List column query
*
* Generates a platform-specific query string so that the column names can be fetched
*
- * @param string the table name
+ * @param string $table
* @return string
*/
protected function _list_columns($table = '')
{
- return "SELECT column_name FROM information_schema.columns WHERE table_name ='".$table."'";
+ return 'SELECT "column_name"
+ FROM "information_schema"."columns"
+ WHERE LOWER("table_name") = '.$this->escape(strtolower($table));
}
// --------------------------------------------------------------------
/**
- * Field data query
- *
- * Generates a platform-specific query so that the column data can be retrieved
+ * Returns an object with field data
*
- * @param string the table name
- * @return object
+ * @param string $table
+ * @return array
*/
- protected function _field_data($table)
+ public function field_data($table = '')
{
- return "SELECT * FROM ".$table." LIMIT 1";
+ if ($table === '')
+ {
+ return ($this->db_debug) ? $this->display_error('db_field_param_missing') : FALSE;
+ }
+
+ $sql = 'SELECT "column_name", "data_type", "character_maximum_length", "numeric_precision", "column_default"
+ FROM "information_schema"."columns"
+ WHERE LOWER("table_name") = '.$this->escape(strtolower($table));
+
+ if (($query = $this->query($sql)) === FALSE)
+ {
+ return FALSE;
+ }
+ $query = $query->result_object();
+
+ $retval = array();
+ for ($i = 0, $c = count($query); $i < $c; $i++)
+ {
+ $retval[$i] = new stdClass();
+ $retval[$i]->name = $query[$i]->column_name;
+ $retval[$i]->type = $query[$i]->data_type;
+ $retval[$i]->max_length = ($query[$i]->character_maximum_length > 0) ? $query[$i]->character_maximum_length : $query[$i]->numeric_precision;
+ $retval[$i]->default = $query[$i]->column_default;
+ }
+
+ return $retval;
}
// --------------------------------------------------------------------
@@ -457,22 +517,36 @@ class CI_DB_postgre_driver extends CI_DB {
// --------------------------------------------------------------------
/**
- * From Tables
+ * ORDER BY
*
- * This function implicitly groups FROM tables so there is no confusion
- * about operator precedence in harmony with SQL standards
- *
- * @param array
- * @return string
+ * @param string $orderby
+ * @param string $direction ASC or DESC
+ * @param bool $escape
+ * @return object
*/
- protected function _from_tables($tables)
+ public function order_by($orderby, $direction = '', $escape = NULL)
{
- if ( ! is_array($tables))
+ $direction = strtoupper(trim($direction));
+ if ($direction === 'RANDOM')
{
- $tables = array($tables);
+ if ( ! is_float($orderby) && ctype_digit((string) $orderby))
+ {
+ $orderby = ($orderby > 1)
+ ? (float) '0.'.$orderby
+ : (float) $orderby;
+ }
+
+ if (is_float($orderby))
+ {
+ $this->simple_query('SET SEED '.$orderby);
+ }
+
+ $orderby = $this->_random_keyword[0];
+ $direction = '';
+ $escape = FALSE;
}
- return implode(', ', $tables);
+ return parent::order_by($orderby, $direction, $escape);
}
// --------------------------------------------------------------------
@@ -482,29 +556,56 @@ class CI_DB_postgre_driver extends CI_DB {
*
* Generates a platform-specific update string from the supplied data
*
- * @param string the table name
- * @param array the update data
- * @param array the where clause
- * @param array the orderby clause (ignored)
- * @param array the limit clause (ignored)
- * @param array the like clause
+ * @param string $table
+ * @param array $values
+ * @return string
+ */
+ protected function _update($table, $values)
+ {
+ $this->qb_limit = FALSE;
+ $this->qb_orderby = array();
+ return parent::_update($table, $values);
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Update_Batch statement
+ *
+ * Generates a platform-specific batch update string from the supplied data
+ *
+ * @param string $table Table name
+ * @param array $values Update data
+ * @param string $index WHERE key
* @return string
*/
- protected function _update($table, $values, $where, $orderby = array(), $limit = FALSE, $like = array())
+ protected function _update_batch($table, $values, $index)
{
+ $ids = array();
foreach ($values as $key => $val)
{
- $valstr[] = $key.' = '.$val;
- }
+ $ids[] = $val[$index];
- $where = empty($where) ? '' : ' WHERE '.implode(' ', $where);
+ foreach (array_keys($val) as $field)
+ {
+ if ($field !== $index)
+ {
+ $final[$field][] = 'WHEN '.$val[$index].' THEN '.$val[$field];
+ }
+ }
+ }
- if ( ! empty($like))
+ $cases = '';
+ foreach ($final as $k => $v)
{
- $where .= ($where === '' ? ' WHERE ' : ' AND ').implode(' ', $like);
+ $cases .= $k.' = (CASE '.$index."\n"
+ .implode("\n", $v)."\n"
+ .'ELSE '.$k.' END), ';
}
- return 'UPDATE '.$table.' SET '.implode(', ', $valstr).$where;
+ $this->where($index.' IN('.implode(',', $ids).')', NULL, FALSE);
+
+ return 'UPDATE '.$table.' SET '.substr($cases, 0, -2).$this->_compile_wh('qb_where');
}
// --------------------------------------------------------------------
@@ -514,43 +615,28 @@ class CI_DB_postgre_driver extends CI_DB {
*
* Generates a platform-specific delete string from the supplied data
*
- * @param string the table name
- * @param array the where clause
- * @param array the like clause
- * @param string the limit clause (ignored)
+ * @param string $table
* @return string
*/
- protected function _delete($table, $where = array(), $like = array(), $limit = FALSE)
+ protected function _delete($table)
{
- $conditions = array();
-
- empty($where) OR $conditions[] = implode(' ', $where);
- empty($like) OR $conditions[] = implode(' ', $like);
-
- return 'DELETE FROM '.$table.(count($conditions) > 0 ? ' WHERE '.implode(' AND ', $conditions) : '');
+ $this->qb_limit = FALSE;
+ return parent::_delete($table);
}
// --------------------------------------------------------------------
+
/**
- * Limit string
+ * LIMIT
*
* Generates a platform-specific LIMIT clause
*
- * @param string the sql query string
- * @param int the number of rows to limit the query to
- * @param int the offset value
+ * @param string $sql SQL Query
* @return string
*/
- protected function _limit($sql, $limit, $offset)
+ protected function _limit($sql)
{
- $sql .= "LIMIT ".$limit;
-
- if ($offset > 0)
- {
- $sql .= " OFFSET ".$offset;
- }
-
- return $sql;
+ return $sql.' LIMIT '.$this->qb_limit.($this->qb_offset ? ' OFFSET '.$this->qb_offset : '');
}
// --------------------------------------------------------------------
@@ -558,12 +644,11 @@ class CI_DB_postgre_driver extends CI_DB {
/**
* Close DB Connection
*
- * @param resource
* @return void
*/
- protected function _close($conn_id)
+ protected function _close()
{
- @pg_close($conn_id);
+ @pg_close($this->conn_id);
}
}
diff --git a/system/database/drivers/postgre/postgre_forge.php b/system/database/drivers/postgre/postgre_forge.php
index 8b214ebe6..5e378385c 100644
--- a/system/database/drivers/postgre/postgre_forge.php
+++ b/system/database/drivers/postgre/postgre_forge.php
@@ -1,4 +1,4 @@
-<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');
+<?php
/**
* CodeIgniter
*
@@ -24,6 +24,7 @@
* @since Version 1.0
* @filesource
*/
+defined('BASEPATH') OR exit('No direct script access allowed');
/**
* Postgre Forge Class
@@ -34,215 +35,152 @@
*/
class CI_DB_postgre_forge extends CI_DB_forge {
- protected $_drop_table = 'DROP TABLE IF EXISTS %s CASCADE';
+ /**
+ * UNSIGNED support
+ *
+ * @var array
+ */
+ protected $_unsigned = array(
+ 'INT2' => 'INTEGER',
+ 'SMALLINT' => 'INTEGER',
+ 'INT' => 'BIGINT',
+ 'INT4' => 'BIGINT',
+ 'INTEGER' => 'BIGINT',
+ 'INT8' => 'NUMERIC',
+ 'BIGINT' => 'NUMERIC',
+ 'REAL' => 'DOUBLE PRECISION',
+ 'FLOAT' => 'DOUBLE PRECISION'
+ );
/**
- * Process Fields
+ * NULL value representation in CREATE/ALTER TABLE statements
*
- * @param mixed the fields
- * @return string
+ * @var string
*/
- protected function _process_fields($fields, $primary_keys=array())
+ protected $_null = 'NULL';
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Class constructor
+ *
+ * @param object &$db Database object
+ * @return void
+ */
+ public function __construct(&$db)
{
- $sql = '';
- $current_field_count = 0;
+ parent::__construct($db);
- foreach ($fields as $field => $attributes)
+ if (version_compare($this->db->version(), '9.0', '>'))
{
- // Numeric field names aren't allowed in databases, so if the key is
- // numeric, we know it was assigned by PHP and the developer manually
- // entered the field information, so we'll simply add it to the list
- if (is_numeric($field))
- {
- $sql .= "\n\t$attributes";
- }
- else
- {
- $attributes = array_change_key_case($attributes, CASE_UPPER);
-
- $sql .= "\n\t".$this->db->protect_identifiers($field);
-
- $is_unsigned = (array_key_exists('UNSIGNED', $attributes) && $attributes['UNSIGNED'] === TRUE);
-
- // Convert datatypes to be PostgreSQL-compatible
- switch (strtoupper($attributes['TYPE']))
- {
- case 'TINYINT':
- $attributes['TYPE'] = 'SMALLINT';
- break;
- case 'SMALLINT':
- $attributes['TYPE'] = ($is_unsigned) ? 'INTEGER' : 'SMALLINT';
- break;
- case 'MEDIUMINT':
- $attributes['TYPE'] = 'INTEGER';
- break;
- case 'INT':
- $attributes['TYPE'] = ($is_unsigned) ? 'BIGINT' : 'INTEGER';
- break;
- case 'BIGINT':
- $attributes['TYPE'] = ($is_unsigned) ? 'NUMERIC' : 'BIGINT';
- break;
- case 'DOUBLE':
- $attributes['TYPE'] = 'DOUBLE PRECISION';
- break;
- case 'DATETIME':
- $attributes['TYPE'] = 'TIMESTAMP';
- break;
- case 'LONGTEXT':
- $attributes['TYPE'] = 'TEXT';
- break;
- case 'BLOB':
- $attributes['TYPE'] = 'BYTEA';
- break;
- }
-
- // If this is an auto-incrementing primary key, use the serial data type instead
- if (in_array($field, $primary_keys) && array_key_exists('AUTO_INCREMENT', $attributes)
- && $attributes['AUTO_INCREMENT'] === TRUE)
- {
- $sql .= ' SERIAL';
- }
- else
- {
- $sql .= ' '.$attributes['TYPE'];
- }
-
- // Modified to prevent constraints with integer data types
- if (array_key_exists('CONSTRAINT', $attributes) && strpos($attributes['TYPE'], 'INT') === false)
- {
- $sql .= '('.$attributes['CONSTRAINT'].')';
- }
-
- if (array_key_exists('DEFAULT', $attributes))
- {
- $sql .= ' DEFAULT \''.$attributes['DEFAULT'].'\'';
- }
-
- if (array_key_exists('NULL', $attributes) && $attributes['NULL'] === TRUE)
- {
- $sql .= ' NULL';
- }
- else
- {
- $sql .= ' NOT NULL';
- }
-
- // Added new attribute to create unqite fields. Also works with MySQL
- if (array_key_exists('UNIQUE', $attributes) && $attributes['UNIQUE'] === TRUE)
- {
- $sql .= ' UNIQUE';
- }
- }
-
- // don't add a comma on the end of the last field
- if (++$current_field_count < count($fields))
- {
- $sql .= ',';
- }
+ $this->create_table_if = 'CREATE TABLE IF NOT EXISTS';
}
-
- return $sql;
}
// --------------------------------------------------------------------
/**
- * Create Table
+ * ALTER TABLE
*
- * @param string the table name
- * @param array the fields
- * @param mixed primary key(s)
- * @param mixed key(s)
- * @param bool should 'IF NOT EXISTS' be added to the SQL
- * @return bool
+ * @param string $alter_type ALTER type
+ * @param string $table Table name
+ * @param mixed $field Column definition
+ * @return string|string[]
*/
- protected function _create_table($table, $fields, $primary_keys, $keys, $if_not_exists)
- {
- $sql = 'CREATE TABLE ';
+ protected function _alter_table($alter_type, $table, $field)
+ {
+ if (in_array($alter_type, array('DROP', 'ADD'), TRUE))
+ {
+ return parent::_alter_table($alter_type, $table, $field);
+ }
- if ($if_not_exists === TRUE)
+ $sql = 'ALTER TABLE '.$this->db->escape_identifiers($table);
+ $sqls = array();
+ for ($i = 0, $c = count($field); $i < $c; $i++)
{
- // PostgreSQL doesn't support IF NOT EXISTS syntax so we check if table exists manually
- if ($this->db->table_exists($table))
+ if ($field[$i]['_literal'] !== FALSE)
{
- return TRUE;
+ return FALSE;
}
- }
- $sql .= $this->db->escape_identifiers($table).' ('.$this->_process_fields($fields, $primary_keys);
-
- if (count($primary_keys) > 0)
- {
- // Something seems to break when passing an array to protect_identifiers()
- foreach ($primary_keys as $index => $key)
+ if (version_compare($this->db->version(), '8', '>=') && isset($field[$i]['type']))
{
- $primary_keys[$index] = $this->db->protect_identifiers($key);
+ $sqls[] = $sql.' ALTER COLUMN '.$this->db->escape_identifiers($field[$i]['name'])
+ .' TYPE '.$field[$i]['type'].$field[$i]['length'];
}
- $sql .= ",\n\tPRIMARY KEY (" . implode(', ', $primary_keys) . ")";
- }
+ if ( ! empty($field[$i]['default']))
+ {
+ $sqls[] = $sql.' ALTER COLUMN '.$this->db->escape_identifiers($field[$i]['name'])
+ .' SET DEFAULT '.$field[$i]['default'];
+ }
- $sql .= "\n);";
+ if (isset($field[$i]['null']))
+ {
+ $sqls[] = $sql.' ALTER COLUMN '.$this->db->escape_identifiers($field[$i]['name'])
+ .($field[$i]['null'] === TRUE ? ' DROP NOT NULL' : ' SET NOT NULL');
+ }
- if (is_array($keys) && count($keys) > 0)
- {
- foreach ($keys as $key)
+ if ( ! empty($field[$i]['new_name']))
{
- if (is_array($key))
- {
- $key = $this->db->protect_identifiers($key);
- }
- else
- {
- $key = array($this->db->protect_identifiers($key));
- }
-
- foreach ($key as $field)
- {
- $sql .= "CREATE INDEX " . $table . "_" . str_replace(array('"', "'"), '', $field) . "_index ON $table ($field); ";
- }
+ $sqls[] = $sql.' RENAME COLUMN '.$this->db->escape_identifiers($field[$i]['name'])
+ .' TO '.$this->db->escape_identifiers($field[$i]['new_name']);
}
}
- return $sql;
- }
+ return $sqls;
+ }
// --------------------------------------------------------------------
/**
- * Alter table query
+ * Field attribute TYPE
*
- * Generates a platform-specific query so that a table can be altered
- * Called by add_column(), drop_column(), and column_alter(),
+ * Performs a data type mapping between different databases.
*
- * @param string the ALTER type (ADD, DROP, CHANGE)
- * @param string the column name
- * @param string the table name
- * @param string the column definition
- * @param string the default value
- * @param boolean should 'NOT NULL' be added
- * @param string the field after which we should add the new field
- * @return string
+ * @param array &$attributes
+ * @return void
*/
- protected function _alter_table($alter_type, $table, $fields, $after_field = '')
- {
- $sql = 'ALTER TABLE '.$this->db->protect_identifiers($table).' '.$alter_type.' ';
-
- // DROP has everything it needs now.
- if ($alter_type == 'DROP')
- {
- return $sql.$this->db->protect_identifiers($fields);
- }
+ protected function _attr_type(&$attributes)
+ {
+ // Reset field lenghts for data types that don't support it
+ if (isset($attributes['CONSTRAINT']) && stripos($attributes['TYPE'], 'int') !== FALSE)
+ {
+ $attributes['CONSTRAINT'] = NULL;
+ }
- $sql .= $this->_process_fields($fields);
+ switch (strtoupper($attributes['TYPE']))
+ {
+ case 'TINYINT':
+ $attributes['TYPE'] = 'SMALLINT';
+ $attributes['UNSIGNED'] = FALSE;
+ return;
+ case 'MEDIUMINT':
+ $attributes['TYPE'] = 'INTEGER';
+ $attributes['UNSIGNED'] = FALSE;
+ return;
+ default: return;
+ }
+ }
- if ($after_field != '')
- {
- return $sql.' AFTER '.$this->db->protect_identifiers($after_field);
- }
+ // --------------------------------------------------------------------
- return $sql;
- }
+ /**
+ * Field attribute AUTO_INCREMENT
+ *
+ * @param array &$attributes
+ * @param array &$field
+ * @return void
+ */
+ protected function _attr_auto_increment(&$attributes, &$field)
+ {
+ if ( ! empty($attributes['AUTO_INCREMENT']) && $attributes['AUTO_INCREMENT'] === TRUE)
+ {
+ $field['type'] = ($field['type'] === 'NUMERIC')
+ ? 'BIGSERIAL'
+ : 'SERIAL';
+ }
+ }
}
diff --git a/system/database/drivers/postgre/postgre_result.php b/system/database/drivers/postgre/postgre_result.php
index f913bc9eb..fdaeaef70 100644
--- a/system/database/drivers/postgre/postgre_result.php
+++ b/system/database/drivers/postgre/postgre_result.php
@@ -1,4 +1,4 @@
-<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');
+<?php
/**
* CodeIgniter
*
@@ -24,6 +24,7 @@
* @since Version 1.0
* @filesource
*/
+defined('BASEPATH') OR exit('No direct script access allowed');
/**
* Postgres Result Class
@@ -33,6 +34,7 @@
* @category Database
* @author EllisLab Dev Team
* @link http://codeigniter.com/user_guide/database/
+ * @since 1.3
*/
class CI_DB_postgre_result extends CI_DB_result {
@@ -43,7 +45,9 @@ class CI_DB_postgre_result extends CI_DB_result {
*/
public function num_rows()
{
- return @pg_num_rows($this->result_id);
+ return is_int($this->num_rows)
+ ? $this->num_rows
+ : $this->num_rows = @pg_num_rows($this->result_id);
}
// --------------------------------------------------------------------
@@ -96,8 +100,6 @@ class CI_DB_postgre_result extends CI_DB_result {
$retval[$i]->name = pg_field_name($this->result_id, $i);
$retval[$i]->type = pg_field_type($this->result_id, $i);
$retval[$i]->max_length = pg_field_size($this->result_id, $i);
- $retval[$i]->primary_key = 0;
- $retval[$i]->default = '';
}
return $retval;
@@ -126,11 +128,12 @@ class CI_DB_postgre_result extends CI_DB_result {
*
* Moves the internal pointer to the desired offset. We call
* this internally before fetching results to make sure the
- * result set starts at zero
+ * result set starts at zero.
*
+ * @param int $n
* @return bool
*/
- protected function _data_seek($n = 0)
+ public function data_seek($n = 0)
{
return pg_result_seek($this->result_id, $n);
}
@@ -156,11 +159,12 @@ class CI_DB_postgre_result extends CI_DB_result {
*
* Returns the result set as an object
*
+ * @param string $class_name
* @return object
*/
- protected function _fetch_object()
+ protected function _fetch_object($class_name = 'stdClass')
{
- return pg_fetch_object($this->result_id);
+ return pg_fetch_object($this->result_id, NULL, $class_name);
}
}
diff --git a/system/database/drivers/postgre/postgre_utility.php b/system/database/drivers/postgre/postgre_utility.php
index c95e6df0c..d3b2b9cdc 100644
--- a/system/database/drivers/postgre/postgre_utility.php
+++ b/system/database/drivers/postgre/postgre_utility.php
@@ -1,4 +1,4 @@
-<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');
+<?php
/**
* CodeIgniter
*
@@ -24,6 +24,7 @@
* @since Version 1.0
* @filesource
*/
+defined('BASEPATH') OR exit('No direct script access allowed');
/**
* Postgre Utility Class
@@ -34,19 +35,32 @@
*/
class CI_DB_postgre_utility extends CI_DB_utility {
+ /**
+ * List databases statement
+ *
+ * @var string
+ */
protected $_list_databases = 'SELECT datname FROM pg_database';
+
+ /**
+ * OPTIMIZE TABLE statement
+ *
+ * @var string
+ */
protected $_optimize_table = 'REINDEX TABLE %s';
+ // --------------------------------------------------------------------
+
/**
- * Postgre Export
+ * Export
*
- * @param array Preferences
+ * @param array $params Preferences
* @return mixed
*/
protected function _backup($params = array())
{
// Currently unsupported
- return $this->db->display_error('db_unsuported_feature');
+ return $this->db->display_error('db_unsupported_feature');
}
}
diff --git a/system/database/drivers/sqlite/sqlite_driver.php b/system/database/drivers/sqlite/sqlite_driver.php
index 5021deb63..8c706c242 100644
--- a/system/database/drivers/sqlite/sqlite_driver.php
+++ b/system/database/drivers/sqlite/sqlite_driver.php
@@ -1,4 +1,4 @@
-<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');
+<?php
/**
* CodeIgniter
*
@@ -24,12 +24,13 @@
* @since Version 1.0
* @filesource
*/
+defined('BASEPATH') OR exit('No direct script access allowed');
/**
* SQLite Database Adapter Class
*
* Note: _DB is an extender class that the app controller
- * creates dynamically based on whether the active record
+ * creates dynamically based on whether the query builder
* class is being used or not.
*
* @package CodeIgniter
@@ -40,22 +41,23 @@
*/
class CI_DB_sqlite_driver extends CI_DB {
+ /**
+ * Database driver
+ *
+ * @var string
+ */
public $dbdriver = 'sqlite';
- // The character used to escape with - not needed for SQLite
- protected $_escape_char = '';
-
- // clause and character used for LIKE escape sequences
- protected $_like_escape_str = " ESCAPE '%s' ";
- protected $_like_escape_chr = '!';
+ // --------------------------------------------------------------------
/**
- * The syntax to count rows is slightly different across different
- * database engines, so this string appears in each driver and is
- * used for the count_all() and count_all_results() functions.
+ * ORDER BY random keyword
+ *
+ * @var array
*/
- protected $_count_string = 'SELECT COUNT(*) AS ';
- protected $_random_keyword = ' Random()'; // database specific random keyword
+ protected $_random_keyword = array('RANDOM()', 'RANDOM()');
+
+ // --------------------------------------------------------------------
/**
* Non-persistent database connection
@@ -122,12 +124,14 @@ class CI_DB_sqlite_driver extends CI_DB {
/**
* Execute the query
*
- * @param string an SQL query
+ * @param string $sql an SQL query
* @return resource
*/
protected function _execute($sql)
{
- return @sqlite_query($this->conn_id, $sql);
+ return $this->is_write_type($sql)
+ ? @sqlite_exec($this->conn_id, $sql)
+ : @sqlite_query($this->conn_id, $sql);
}
// --------------------------------------------------------------------
@@ -135,17 +139,13 @@ class CI_DB_sqlite_driver extends CI_DB {
/**
* Begin Transaction
*
+ * @param bool $test_mode
* @return bool
*/
public function trans_begin($test_mode = FALSE)
{
- if ( ! $this->trans_enabled)
- {
- return TRUE;
- }
-
// When transactions are nested we only begin/commit/rollback the outermost ones
- if ($this->_trans_depth > 0)
+ if ( ! $this->trans_enabled OR $this->_trans_depth > 0)
{
return TRUE;
}
@@ -153,7 +153,7 @@ class CI_DB_sqlite_driver extends CI_DB {
// Reset the transaction failure flag.
// If the $test_mode flag is set to TRUE transactions will be rolled back
// even if the queries produce a successful result.
- $this->_trans_failure = ($test_mode === TRUE) ? TRUE : FALSE;
+ $this->_trans_failure = ($test_mode === TRUE);
$this->simple_query('BEGIN TRANSACTION');
return TRUE;
@@ -168,13 +168,8 @@ class CI_DB_sqlite_driver extends CI_DB {
*/
public function trans_commit()
{
- if ( ! $this->trans_enabled)
- {
- return TRUE;
- }
-
// When transactions are nested we only begin/commit/rollback the outermost ones
- if ($this->_trans_depth > 0)
+ if ( ! $this->trans_enabled OR $this->_trans_depth > 0)
{
return TRUE;
}
@@ -192,13 +187,8 @@ class CI_DB_sqlite_driver extends CI_DB {
*/
public function trans_rollback()
{
- if ( ! $this->trans_enabled)
- {
- return TRUE;
- }
-
// When transactions are nested we only begin/commit/rollback the outermost ones
- if ($this->_trans_depth > 0)
+ if ( ! $this->trans_enabled OR $this->_trans_depth > 0)
{
return TRUE;
}
@@ -212,8 +202,8 @@ class CI_DB_sqlite_driver extends CI_DB {
/**
* Escape String
*
- * @param string
- * @param bool whether or not the string will be used in a LIKE condition
+ * @param string $str
+ * @param bool $like Whether or not the string will be used in a LIKE condition
* @return string
*/
public function escape_str($str, $like = FALSE)
@@ -268,50 +258,22 @@ class CI_DB_sqlite_driver extends CI_DB {
// --------------------------------------------------------------------
/**
- * "Count All" query
- *
- * Generates a platform-specific query string that counts all records in
- * the specified database
- *
- * @param string
- * @return string
- */
- public function count_all($table = '')
- {
- if ($table == '')
- {
- return 0;
- }
-
- $query = $this->query($this->_count_string.$this->protect_identifiers('numrows').' FROM '.$this->protect_identifiers($table, TRUE, NULL, FALSE));
- if ($query->num_rows() == 0)
- {
- return 0;
- }
-
- $row = $query->row();
- $this->_reset_select();
- return (int) $row->numrows;
- }
-
- // --------------------------------------------------------------------
-
- /**
* List table query
*
* Generates a platform-specific query string so that the table names can be fetched
*
- * @param bool
+ * @param bool $prefix_limit
* @return string
*/
protected function _list_tables($prefix_limit = FALSE)
{
- $sql = "SELECT name from sqlite_master WHERE type='table'";
+ $sql = "SELECT name FROM sqlite_master WHERE type='table'";
- if ($prefix_limit !== FALSE AND $this->dbprefix != '')
+ if ($prefix_limit !== FALSE && $this->dbprefix != '')
{
- $sql .= " AND 'name' LIKE '".$this->escape_like_str($this->dbprefix)."%' ".sprintf($this->_like_escape_str, $this->_like_escape_chr);
+ return $sql." AND 'name' LIKE '".$this->escape_like_str($this->dbprefix)."%' ".sprintf($this->_like_escape_str, $this->_like_escape_chr);
}
+
return $sql;
}
@@ -322,7 +284,7 @@ class CI_DB_sqlite_driver extends CI_DB {
*
* Generates a platform-specific query string so that the column names can be fetched
*
- * @param string the table name
+ * @param string $table
* @return bool
*/
protected function _list_columns($table = '')
@@ -334,16 +296,41 @@ class CI_DB_sqlite_driver extends CI_DB {
// --------------------------------------------------------------------
/**
- * Field data query
- *
- * Generates a platform-specific query so that the column data can be retrieved
+ * Returns an object with field data
*
- * @param string the table name
- * @return string
+ * @param string $table
+ * @return array
*/
- protected function _field_data($table)
+ public function field_data($table = '')
{
- return "SELECT * FROM ".$table." LIMIT 1";
+ if ($table === '')
+ {
+ return ($this->db_debug) ? $this->display_error('db_field_param_missing') : FALSE;
+ }
+
+ if (($query = $this->query('PRAGMA TABLE_INFO('.$this->protect_identifiers($table, TRUE, NULL, FALSE).')')) === FALSE)
+ {
+ return FALSE;
+ }
+
+ $query = $query->result_array();
+ if (empty($query))
+ {
+ return FALSE;
+ }
+
+ $retval = array();
+ for ($i = 0, $c = count($query); $i < $c; $i++)
+ {
+ $retval[$i] = new stdClass();
+ $retval[$i]->name = $query[$i]['name'];
+ $retval[$i]->type = $query[$i]['type'];
+ $retval[$i]->max_length = NULL;
+ $retval[$i]->default = $query[$i]['dflt_value'];
+ $retval[$i]->primary_key = isset($query[$i]['pk']) ? (int) $query[$i]['pk'] : 0;
+ }
+
+ return $retval;
}
// --------------------------------------------------------------------
@@ -366,34 +353,13 @@ class CI_DB_sqlite_driver extends CI_DB {
// --------------------------------------------------------------------
/**
- * From Tables
- *
- * This function implicitly groups FROM tables so there is no confusion
- * about operator precedence in harmony with SQL standards
- *
- * @param array
- * @return string
- */
- protected function _from_tables($tables)
- {
- if ( ! is_array($tables))
- {
- $tables = array($tables);
- }
-
- return '('.implode(', ', $tables).')';
- }
-
- // --------------------------------------------------------------------
-
- /**
* Replace statement
*
* Generates a platform-specific replace string from the supplied data
*
- * @param string the table name
- * @param array the insert keys
- * @param array the insert values
+ * @param string $table Table name
+ * @param array $keys INSERT keys
+ * @param array $values INSERT values
* @return string
*/
protected function _replace($table, $keys, $values)
@@ -408,10 +374,10 @@ class CI_DB_sqlite_driver extends CI_DB {
*
* Generates a platform-specific truncate string from the supplied data
*
- * If the database does not support the truncate() command,
+ * If the database does not support the TRUNCATE statement,
* then this function maps to 'DELETE FROM table'
*
- * @param string the table name
+ * @param string $table
* @return string
*/
protected function _truncate($table)
@@ -422,40 +388,13 @@ class CI_DB_sqlite_driver extends CI_DB {
// --------------------------------------------------------------------
/**
- * Limit string
- *
- * Generates a platform-specific LIMIT clause
- *
- * @param string the sql query string
- * @param int the number of rows to limit the query to
- * @param int the offset value
- * @return string
- */
- protected function _limit($sql, $limit, $offset)
- {
- if ($offset == 0)
- {
- $offset = '';
- }
- else
- {
- $offset .= ", ";
- }
-
- return $sql."LIMIT ".$offset.$limit;
- }
-
- // --------------------------------------------------------------------
-
- /**
* Close DB Connection
*
- * @param resource
* @return void
*/
- protected function _close($conn_id)
+ protected function _close()
{
- @sqlite_close($conn_id);
+ @sqlite_close($this->conn_id);
}
}
diff --git a/system/database/drivers/sqlite/sqlite_forge.php b/system/database/drivers/sqlite/sqlite_forge.php
index dd6f0f78d..6ad583560 100644
--- a/system/database/drivers/sqlite/sqlite_forge.php
+++ b/system/database/drivers/sqlite/sqlite_forge.php
@@ -1,4 +1,4 @@
-<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');
+<?php
/**
* CodeIgniter
*
@@ -24,6 +24,7 @@
* @since Version 1.0
* @filesource
*/
+defined('BASEPATH') OR exit('No direct script access allowed');
/**
* SQLite Forge Class
@@ -35,9 +36,32 @@
class CI_DB_sqlite_forge extends CI_DB_forge {
/**
+ * CREATE TABLE IF statement
+ *
+ * @var string
+ */
+ protected $_create_table_if = FALSE;
+
+ /**
+ * UNSIGNED support
+ *
+ * @var bool|array
+ */
+ protected $_unsigned = FALSE;
+
+ /**
+ * NULL value representation in CREATE/ALTER TABLE statements
+ *
+ * @var string
+ */
+ protected $_null = 'NULL';
+
+ // --------------------------------------------------------------------
+
+ /**
* Create database
*
- * @param string the database name
+ * @param string $db_name (ignored)
* @return bool
*/
public function create_database($db_name = '')
@@ -52,7 +76,7 @@ class CI_DB_sqlite_forge extends CI_DB_forge {
/**
* Drop database
*
- * @param string the database name (ignored)
+ * @param string $db_name (ignored)
* @return bool
*/
public function drop_database($db_name = '')
@@ -61,6 +85,14 @@ class CI_DB_sqlite_forge extends CI_DB_forge {
{
return ($this->db->db_debug) ? $this->db->display_error('db_unable_to_drop') : FALSE;
}
+ elseif ( ! empty($this->db->data_cache['db_names']))
+ {
+ $key = array_search(strtolower($this->db->database), array_map('strtolower', $this->db->data_cache['db_names']), TRUE);
+ if ($key !== FALSE)
+ {
+ unset($this->db->data_cache['db_names'][$key]);
+ }
+ }
return TRUE;
}
@@ -68,163 +100,95 @@ class CI_DB_sqlite_forge extends CI_DB_forge {
// --------------------------------------------------------------------
/**
- * Create Table
+ * ALTER TABLE
*
- * @param string the table name
- * @param array the fields
- * @param mixed primary key(s)
- * @param mixed key(s)
- * @param bool should 'IF NOT EXISTS' be added to the SQL
- * @return bool
+ * @todo implement drop_column(), modify_column()
+ * @param string $alter_type ALTER type
+ * @param string $table Table name
+ * @param mixed $field Column definition
+ * @return string|string[]
*/
- protected function _create_table($table, $fields, $primary_keys, $keys, $if_not_exists)
+ protected function _alter_table($alter_type, $table, $field)
{
- $sql = 'CREATE TABLE ';
-
- // IF NOT EXISTS added to SQLite in 3.3.0
- if ($if_not_exists === TRUE && version_compare($this->db->version(), '3.3.0', '>=') === TRUE)
- {
- $sql .= 'IF NOT EXISTS ';
- }
-
- $sql .= $this->db->escape_identifiers($table).' (';
- $current_field_count = 0;
-
- foreach ($fields as $field => $attributes)
+ if ($alter_type === 'DROP' OR $alter_type === 'CHANGE')
{
- // Numeric field names aren't allowed in databases, so if the key is
- // numeric, we know it was assigned by PHP and the developer manually
- // entered the field information, so we'll simply add it to the list
- if (is_numeric($field))
- {
- $sql .= "\n\t$attributes";
- }
- else
- {
- $attributes = array_change_key_case($attributes, CASE_UPPER);
-
- $sql .= "\n\t".$this->db->protect_identifiers($field);
-
- $sql .= ' '.$attributes['TYPE'];
-
- if (array_key_exists('CONSTRAINT', $attributes))
- {
- $sql .= '('.$attributes['CONSTRAINT'].')';
- }
-
- if (array_key_exists('UNSIGNED', $attributes) && $attributes['UNSIGNED'] === TRUE)
- {
- $sql .= ' UNSIGNED';
- }
-
- if (array_key_exists('DEFAULT', $attributes))
- {
- $sql .= ' DEFAULT \''.$attributes['DEFAULT'].'\'';
- }
-
- if (array_key_exists('NULL', $attributes) && $attributes['NULL'] === TRUE)
- {
- $sql .= ' NULL';
- }
- else
- {
- $sql .= ' NOT NULL';
- }
-
- if (array_key_exists('AUTO_INCREMENT', $attributes) && $attributes['AUTO_INCREMENT'] === TRUE)
- {
- $sql .= ' AUTO_INCREMENT';
- }
- }
-
- // don't add a comma on the end of the last field
- if (++$current_field_count < count($fields))
- {
- $sql .= ',';
- }
- }
+ // drop_column():
+ // BEGIN TRANSACTION;
+ // CREATE TEMPORARY TABLE t1_backup(a,b);
+ // INSERT INTO t1_backup SELECT a,b FROM t1;
+ // DROP TABLE t1;
+ // CREATE TABLE t1(a,b);
+ // INSERT INTO t1 SELECT a,b FROM t1_backup;
+ // DROP TABLE t1_backup;
+ // COMMIT;
- if (count($primary_keys) > 0)
- {
- $primary_keys = $this->db->protect_identifiers($primary_keys);
- $sql .= ",\n\tPRIMARY KEY (" . implode(', ', $primary_keys) . ")";
+ return FALSE;
}
- if (is_array($keys) && count($keys) > 0)
- {
- foreach ($keys as $key)
- {
- if (is_array($key))
- {
- $key = $this->db->protect_identifiers($key);
- }
- else
- {
- $key = array($this->db->protect_identifiers($key));
- }
-
- $sql .= ",\n\tUNIQUE (" . implode(', ', $key) . ")";
- }
- }
+ return parent::_alter_table($alter_type, $table, $field);
+ }
- $sql .= "\n)";
+ // --------------------------------------------------------------------
- return $sql;
+ /**
+ * Process column
+ *
+ * @param array $field
+ * @return string
+ */
+ protected function _process_column($field)
+ {
+ return $this->db->escape_identifiers($field['name'])
+ .' '.$field['type']
+ .$field['auto_increment']
+ .$field['null']
+ .$field['unique']
+ .$field['default'];
}
// --------------------------------------------------------------------
/**
- * Alter table query
+ * Field attribute TYPE
*
- * Generates a platform-specific query so that a table can be altered
- * Called by add_column(), drop_column(), and column_alter(),
+ * Performs a data type mapping between different databases.
*
- * @param string the ALTER type (ADD, DROP, CHANGE)
- * @param string the column name
- * @param string the table name
- * @param string the column definition
- * @param string the default value
- * @param bool should 'NOT NULL' be added
- * @param string the field after which we should add the new field
- * @return string
+ * @param array &$attributes
+ * @return void
*/
- protected function _alter_table($alter_type, $table, $column_name, $column_definition = '', $default_value = '', $null = '', $after_field = '')
+ protected function _attr_type(&$attributes)
{
- $sql = 'ALTER TABLE '.$this->db->protect_identifiers($table).' '.$alter_type.' '.$this->db->protect_identifiers($column_name);
-
- // DROP has everything it needs now.
- if ($alter_type == 'DROP')
+ switch (strtoupper($attributes['TYPE']))
{
- // SQLite does not support dropping columns
- // http://www.sqlite.org/omitted.html
- // http://www.sqlite.org/faq.html#q11
- return FALSE;
+ case 'ENUM':
+ case 'SET':
+ $attributes['TYPE'] = 'TEXT';
+ return;
+ default: return;
}
+ }
- $sql .= " $column_definition";
-
- if ($default_value != '')
- {
- $sql .= " DEFAULT \"$default_value\"";
- }
+ // --------------------------------------------------------------------
- if ($null === NULL)
- {
- $sql .= ' NULL';
- }
- else
+ /**
+ * Field attribute AUTO_INCREMENT
+ *
+ * @param array &$attributes
+ * @param array &$field
+ * @return void
+ */
+ protected function _attr_auto_increment(&$attributes, &$field)
+ {
+ if ( ! empty($attributes['AUTO_INCREMENT']) && $attributes['AUTO_INCREMENT'] === TRUE && stripos($field['type'], 'int') !== FALSE)
{
- $sql .= ' NOT NULL';
- }
+ $field['type'] = 'INTEGER PRIMARY KEY';
+ $field['default'] = '';
+ $field['null'] = '';
+ $field['unique'] = '';
+ $field['auto_increment'] = ' AUTOINCREMENT';
- if ($after_field != '')
- {
- return $sql.' AFTER '.$this->db->protect_identifiers($after_field);
+ $this->primary_keys = array();
}
-
- return $sql;
-
}
}
diff --git a/system/database/drivers/sqlite/sqlite_result.php b/system/database/drivers/sqlite/sqlite_result.php
index 741dc9d8d..889757dea 100644
--- a/system/database/drivers/sqlite/sqlite_result.php
+++ b/system/database/drivers/sqlite/sqlite_result.php
@@ -1,4 +1,4 @@
-<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');
+<?php
/**
* CodeIgniter
*
@@ -24,6 +24,7 @@
* @since Version 1.0
* @filesource
*/
+defined('BASEPATH') OR exit('No direct script access allowed');
/**
* SQLite Result Class
@@ -33,6 +34,7 @@
* @category Database
* @author EllisLab Dev Team
* @link http://codeigniter.com/user_guide/database/
+ * @since 1.3
*/
class CI_DB_sqlite_result extends CI_DB_result {
@@ -43,7 +45,9 @@ class CI_DB_sqlite_result extends CI_DB_result {
*/
public function num_rows()
{
- return @sqlite_num_rows($this->result_id);
+ return is_int($this->num_rows)
+ ? $this->num_rows
+ : $this->num_rows = @sqlite_num_rows($this->result_id);
}
// --------------------------------------------------------------------
@@ -94,10 +98,8 @@ class CI_DB_sqlite_result extends CI_DB_result {
{
$retval[$i] = new stdClass();
$retval[$i]->name = sqlite_field_name($this->result_id, $i);
- $retval[$i]->type = 'varchar';
- $retval[$i]->max_length = 0;
- $retval[$i]->primary_key = 0;
- $retval[$i]->default = '';
+ $retval[$i]->type = NULL;
+ $retval[$i]->max_length = NULL;
}
return $retval;
@@ -110,11 +112,12 @@ class CI_DB_sqlite_result extends CI_DB_result {
*
* Moves the internal pointer to the desired offset. We call
* this internally before fetching results to make sure the
- * result set starts at zero
+ * result set starts at zero.
*
+ * @param int $n
* @return bool
*/
- protected function _data_seek($n = 0)
+ public function data_seek($n = 0)
{
return sqlite_seek($this->result_id, $n);
}
@@ -140,17 +143,12 @@ class CI_DB_sqlite_result extends CI_DB_result {
*
* Returns the result set as an object
*
+ * @param string $class_name
* @return object
*/
- protected function _fetch_object()
+ protected function _fetch_object($class_name = 'stdClass')
{
- if (function_exists('sqlite_fetch_object'))
- {
- return sqlite_fetch_object($this->result_id);
- }
-
- $arr = sqlite_fetch_array($this->result_id, SQLITE_ASSOC);
- return is_array($arr) ? (object) $arr : FALSE;
+ return sqlite_fetch_object($this->result_id, $class_name);
}
}
diff --git a/system/database/drivers/sqlite/sqlite_utility.php b/system/database/drivers/sqlite/sqlite_utility.php
index 1bcb42d9f..222d02712 100644
--- a/system/database/drivers/sqlite/sqlite_utility.php
+++ b/system/database/drivers/sqlite/sqlite_utility.php
@@ -1,4 +1,4 @@
-<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');
+<?php
/**
* CodeIgniter
*
@@ -24,6 +24,7 @@
* @since Version 1.0
* @filesource
*/
+defined('BASEPATH') OR exit('No direct script access allowed');
/**
* SQLite Utility Class
@@ -34,18 +35,16 @@
*/
class CI_DB_sqlite_utility extends CI_DB_utility {
- protected $_list_databases = FALSE;
-
/**
- * SQLite Export
+ * Export
*
- * @param array Preferences
+ * @param array $params Preferences
* @return mixed
*/
protected function _backup($params = array())
{
// Currently unsupported
- return $this->db->display_error('db_unsuported_feature');
+ return $this->db->display_error('db_unsupported_feature');
}
}
diff --git a/system/database/drivers/sqlite3/sqlite3_driver.php b/system/database/drivers/sqlite3/sqlite3_driver.php
index fb45bee9c..e37268aca 100644
--- a/system/database/drivers/sqlite3/sqlite3_driver.php
+++ b/system/database/drivers/sqlite3/sqlite3_driver.php
@@ -1,4 +1,4 @@
-<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');
+<?php
/**
* CodeIgniter
*
@@ -24,12 +24,13 @@
* @since Version 1.0
* @filesource
*/
+defined('BASEPATH') OR exit('No direct script access allowed');
/**
* SQLite3 Database Adapter Class
*
* Note: _DB is an extender class that the app controller
- * creates dynamically based on whether the active record
+ * creates dynamically based on whether the query builder
* class is being used or not.
*
* @package CodeIgniter
@@ -41,22 +42,23 @@
*/
class CI_DB_sqlite3_driver extends CI_DB {
+ /**
+ * Database driver
+ *
+ * @var string
+ */
public $dbdriver = 'sqlite3';
- // The character used for escaping
- protected $_escape_char = '"';
-
- // clause and character used for LIKE escape sequences
- protected $_like_escape_str = ' ESCAPE \'%s\' ';
- protected $_like_escape_chr = '!';
+ // --------------------------------------------------------------------
/**
- * The syntax to count rows is slightly different across different
- * database engines, so this string appears in each driver and is
- * used for the count_all() and count_all_results() functions.
+ * ORDER BY random keyword
+ *
+ * @var array
*/
- protected $_count_string = 'SELECT COUNT(*) AS ';
- protected $_random_keyword = ' RANDOM()';
+ protected $_random_keyword = array('RANDOM()', 'RANDOM()');
+
+ // --------------------------------------------------------------------
/**
* Non-persistent database connection
@@ -87,7 +89,7 @@ class CI_DB_sqlite3_driver extends CI_DB {
public function db_pconnect()
{
log_message('debug', 'SQLite3 doesn\'t support persistent connections');
- return $this->db_pconnect();
+ return $this->db_connect();
}
// --------------------------------------------------------------------
@@ -104,7 +106,7 @@ class CI_DB_sqlite3_driver extends CI_DB {
return $this->data_cache['version'];
}
- $version = $this->conn_id->version();
+ $version = SQLite3::version();
return $this->data_cache['version'] = $version['versionString'];
}
@@ -113,13 +115,12 @@ class CI_DB_sqlite3_driver extends CI_DB {
/**
* Execute the query
*
- * @param string an SQL query
+ * @todo Implement use of SQLite3::querySingle(), if needed
+ * @param string $sql
* @return mixed SQLite3Result object or bool
*/
protected function _execute($sql)
{
- // TODO: Implement use of SQLite3::querySingle(), if needed
-
return $this->is_write_type($sql)
? $this->conn_id->exec($sql)
: $this->conn_id->query($sql);
@@ -130,6 +131,7 @@ class CI_DB_sqlite3_driver extends CI_DB {
/**
* Begin Transaction
*
+ * @param bool $test_mode
* @return bool
*/
public function trans_begin($test_mode = FALSE)
@@ -189,8 +191,8 @@ class CI_DB_sqlite3_driver extends CI_DB {
/**
* Escape String
*
- * @param string
- * @param bool whether or not the string will be used in a LIKE condition
+ * @param string $str
+ * @param bool $like Whether or not the string will be used in a LIKE condition
* @return string
*/
public function escape_str($str, $like = FALSE)
@@ -245,35 +247,11 @@ class CI_DB_sqlite3_driver extends CI_DB {
// --------------------------------------------------------------------
/**
- * "Count All" query
- *
- * Generates a platform-specific query string that counts all records in
- * the specified database
- *
- * @param string
- * @return int
- */
- public function count_all($table = '')
- {
- if ($table == '')
- {
- return 0;
- }
-
- $result = $this->conn_id->querySingle($this->_count_string.$this->protect_identifiers('numrows')
- .' FROM '.$this->protect_identifiers($table, TRUE, NULL, FALSE));
-
- return empty($result) ? 0 : (int) $result;
- }
-
- // --------------------------------------------------------------------
-
- /**
* Show table query
*
* Generates a platform-specific query string so that the table names can be fetched
*
- * @param bool
+ * @param bool $prefix_limit
* @return string
*/
protected function _list_tables($prefix_limit = FALSE)
@@ -291,7 +269,7 @@ class CI_DB_sqlite3_driver extends CI_DB {
*
* Generates a platform-specific query string so that the column names can be fetched
*
- * @param string the table name
+ * @param string $table
* @return string
*/
protected function _list_columns($table = '')
@@ -303,61 +281,56 @@ class CI_DB_sqlite3_driver extends CI_DB {
// --------------------------------------------------------------------
/**
- * Field data query
- *
- * Generates a platform-specific query so that the column data can be retrieved
+ * Returns an object with field data
*
- * @param string the table name
- * @return string
+ * @param string $table
+ * @return array
*/
- protected function _field_data($table)
+ public function field_data($table = '')
{
- return 'SELECT * FROM '.$table.' LIMIT 0,1';
- }
+ if ($table === '')
+ {
+ return ($this->db_debug) ? $this->display_error('db_field_param_missing') : FALSE;
+ }
- // --------------------------------------------------------------------
+ if (($query = $this->query('PRAGMA TABLE_INFO('.$this->protect_identifiers($table, TRUE, NULL, FALSE).')')) === FALSE)
+ {
+ return FALSE;
+ }
- /**
- * The error message string
- *
- * @return string
- */
- protected function _error_message()
- {
- return $this->conn_id->lastErrorMsg();
- }
+ $query = $query->result_array();
+ if (empty($query))
+ {
+ return FALSE;
+ }
- // --------------------------------------------------------------------
+ $retval = array();
+ for ($i = 0, $c = count($query); $i < $c; $i++)
+ {
+ $retval[$i] = new stdClass();
+ $retval[$i]->name = $query[$i]['name'];
+ $retval[$i]->type = $query[$i]['type'];
+ $retval[$i]->max_length = NULL;
+ $retval[$i]->default = $query[$i]['dflt_value'];
+ $retval[$i]->primary_key = isset($query[$i]['pk']) ? (int) $query[$i]['pk'] : 0;
+ }
- /**
- * The error message number
- *
- * @return int
- */
- protected function _error_number()
- {
- return $this->conn_id->lastErrorCode();
+ return $retval;
}
// --------------------------------------------------------------------
/**
- * From Tables
+ * Error
*
- * This function implicitly groups FROM tables so there is no confusion
- * about operator precedence in harmony with SQL standards
+ * Returns an array containing code and message of the last
+ * database error that has occured.
*
- * @param string
- * @return string
+ * @return array
*/
- protected function _from_tables($tables)
+ public function error()
{
- if ( ! is_array($tables))
- {
- $tables = array($tables);
- }
-
- return '('.implode(', ', $tables).')';
+ return array('code' => $this->conn_id->lastErrorCode(), 'message' => $this->conn_id->lastErrorMsg());
}
// --------------------------------------------------------------------
@@ -367,9 +340,9 @@ class CI_DB_sqlite3_driver extends CI_DB {
*
* Generates a platform-specific replace string from the supplied data
*
- * @param string the table name
- * @param array the insert keys
- * @param array the insert values
+ * @param string $table Table name
+ * @param array $keys INSERT keys
+ * @param array $values INSERT values
* @return string
*/
protected function _replace($table, $keys, $values)
@@ -384,10 +357,10 @@ class CI_DB_sqlite3_driver extends CI_DB {
*
* Generates a platform-specific truncate string from the supplied data
*
- * If the database does not support the truncate() command, then,
+ * If the database does not support the TRUNCATE statement,
* then this method maps to 'DELETE FROM table'
*
- * @param string the table name
+ * @param string $table
* @return string
*/
protected function _truncate($table)
@@ -398,29 +371,11 @@ class CI_DB_sqlite3_driver extends CI_DB {
// --------------------------------------------------------------------
/**
- * Limit string
- *
- * Generates a platform-specific LIMIT clause
- *
- * @param string the sql query string
- * @param int the number of rows to limit the query to
- * @param int the offset value
- * @return string
- */
- protected function _limit($sql, $limit, $offset)
- {
- return $sql.' LIMIT '.($offset ? $offset.',' : '').$limit;
- }
-
- // --------------------------------------------------------------------
-
- /**
* Close DB Connection
*
- * @param object (ignored)
* @return void
*/
- protected function _close($conn_id)
+ protected function _close()
{
$this->conn_id->close();
}
diff --git a/system/database/drivers/sqlite3/sqlite3_forge.php b/system/database/drivers/sqlite3/sqlite3_forge.php
index 20f1e6f63..e9b91e972 100644
--- a/system/database/drivers/sqlite3/sqlite3_forge.php
+++ b/system/database/drivers/sqlite3/sqlite3_forge.php
@@ -1,8 +1,8 @@
-<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');
+<?php
/**
* CodeIgniter
*
- * An open source application development framework for PHP 5.1.6 or newer
+ * An open source application development framework for PHP 5.2.4 or newer
*
* NOTICE OF LICENSE
*
@@ -24,6 +24,7 @@
* @since Version 1.0
* @filesource
*/
+defined('BASEPATH') OR exit('No direct script access allowed');
/**
* SQLite3 Forge Class
@@ -35,9 +36,43 @@
class CI_DB_sqlite3_forge extends CI_DB_forge {
/**
+ * UNSIGNED support
+ *
+ * @var bool|array
+ */
+ protected $_unsigned = FALSE;
+
+ /**
+ * NULL value representation in CREATE/ALTER TABLE statements
+ *
+ * @var string
+ */
+ protected $_null = 'NULL';
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Class constructor
+ *
+ * @param object &$db Database object
+ * @return void
+ */
+ public function __construct(&$db)
+ {
+ parent::__construct($db);
+
+ if (version_compare($this->db->version(), '3.3', '<'))
+ {
+ $this->create_table_if = FALSE;
+ }
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
* Create database
*
- * @param string the database name
+ * @param string $db_name
* @return bool
*/
public function create_database($db_name = '')
@@ -52,7 +87,7 @@ class CI_DB_sqlite3_forge extends CI_DB_forge {
/**
* Drop database
*
- * @param string the database name (ignored)
+ * @param string $db_name (ignored)
* @return bool
*/
public function drop_database($db_name = '')
@@ -66,6 +101,14 @@ class CI_DB_sqlite3_forge extends CI_DB_forge {
{
return $this->db->db_debug ? $this->db->display_error('db_unable_to_drop') : FALSE;
}
+ elseif ( ! empty($this->db->data_cache['db_names']))
+ {
+ $key = array_search(strtolower($this->db->database), array_map('strtolower', $this->db->data_cache['db_names']), TRUE);
+ if ($key !== FALSE)
+ {
+ unset($this->db->data_cache['db_names'][$key]);
+ }
+ }
return TRUE;
}
@@ -76,117 +119,95 @@ class CI_DB_sqlite3_forge extends CI_DB_forge {
// --------------------------------------------------------------------
/**
- * Create Table
+ * ALTER TABLE
*
- * @param string the table name
- * @param array the fields
- * @param mixed primary key(s)
- * @param mixed key(s)
- * @param bool should 'IF NOT EXISTS' be added to the SQL
- * @return bool
+ * @todo implement drop_column(), modify_column()
+ * @param string $alter_type ALTER type
+ * @param string $table Table name
+ * @param mixed $field Column definition
+ * @return string|string[]
*/
- protected function _create_table($table, $fields, $primary_keys, $keys, $if_not_exists)
+ protected function _alter_table($alter_type, $table, $field)
{
- $sql = 'CREATE TABLE ';
-
- // IF NOT EXISTS added to SQLite in 3.3.0
- if ($if_not_exists === TRUE && version_compare($this->db->version(), '3.3.0', '>=') === TRUE)
+ if ($alter_type === 'DROP' OR $alter_type === 'CHANGE')
{
- $sql .= 'IF NOT EXISTS ';
+ // drop_column():
+ // BEGIN TRANSACTION;
+ // CREATE TEMPORARY TABLE t1_backup(a,b);
+ // INSERT INTO t1_backup SELECT a,b FROM t1;
+ // DROP TABLE t1;
+ // CREATE TABLE t1(a,b);
+ // INSERT INTO t1 SELECT a,b FROM t1_backup;
+ // DROP TABLE t1_backup;
+ // COMMIT;
+
+ return FALSE;
}
- $sql .= $this->db->escape_identifiers($table).' (';
- $current_field_count = 0;
+ return parent::_alter_table($alter_type, $table, $field);
+ }
- foreach ($fields as $field => $attributes)
- {
- // Numeric field names aren't allowed in databases, so if the key is
- // numeric, we know it was assigned by PHP and the developer manually
- // entered the field information, so we'll simply add it to the list
- if (is_numeric($field))
- {
- $sql .= "\n\t".$attributes;
- }
- else
- {
- $attributes = array_change_key_case($attributes, CASE_UPPER);
-
- $sql .= "\n\t".$this->db->protect_identifiers($field)
- .' '.$attributes['TYPE']
- .( ! empty($attributes['CONSTRAINT']) ? '('.$attributes['CONSTRAINT'].')' : '')
- .(( ! empty($attributes['UNSIGNED']) && $attributes['UNSIGNED'] === TRUE) ? ' UNSIGNED' : '')
- .(isset($attributes['DEFAULT']) ? ' DEFAULT \''.$attributes['DEFAULT'].'\'' : '')
- .(( ! empty($attributes['NULL']) && $attributes['NULL'] === TRUE) ? ' NULL' : ' NOT NULL')
- .(( ! empty($attributes['AUTO_INCREMENT']) && $attributes['AUTO_INCREMENT'] === TRUE) ? ' AUTO_INCREMENT' : '');
- }
+ // --------------------------------------------------------------------
- // don't add a comma on the end of the last field
- if (++$current_field_count < count($fields))
- {
- $sql .= ',';
- }
- }
+ /**
+ * Process column
+ *
+ * @param array $field
+ * @return string
+ */
+ protected function _process_column($field)
+ {
+ return $this->db->escape_identifiers($field['name'])
+ .' '.$field['type']
+ .$field['auto_increment']
+ .$field['null']
+ .$field['unique']
+ .$field['default'];
+ }
- if (count($primary_keys) > 0)
- {
- $primary_keys = $this->db->protect_identifiers($primary_keys);
- $sql .= ",\n\tPRIMARY KEY (".implode(', ', $primary_keys).')';
- }
+ // --------------------------------------------------------------------
- if (is_array($keys) && count($keys) > 0)
+ /**
+ * Field attribute TYPE
+ *
+ * Performs a data type mapping between different databases.
+ *
+ * @param array &$attributes
+ * @return void
+ */
+ protected function _attr_type(&$attributes)
+ {
+ switch (strtoupper($attributes['TYPE']))
{
- foreach ($keys as $key)
- {
- if (is_array($key))
- {
- $key = $this->db->protect_identifiers($key);
- }
- else
- {
- $key = array($this->db->protect_identifiers($key));
- }
-
- $sql .= ",\n\tUNIQUE (".implode(', ', $key).')';
- }
+ case 'ENUM':
+ case 'SET':
+ $attributes['TYPE'] = 'TEXT';
+ return;
+ default: return;
}
-
- return $sql."\n)";
}
// --------------------------------------------------------------------
/**
- * Alter table query
- *
- * Generates a platform-specific query so that a table can be altered
- * Called by add_column(), drop_column(), and column_alter(),
+ * Field attribute AUTO_INCREMENT
*
- * @param string the ALTER type (ADD, DROP, CHANGE)
- * @param string the column name
- * @param string the table name
- * @param string the column definition
- * @param string the default value
- * @param bool should 'NOT NULL' be added
- * @param string the field after which we should add the new field
- * @return string
+ * @param array &$attributes
+ * @param array &$field
+ * @return void
*/
- protected function _alter_table($alter_type, $table, $column_name, $column_definition = '', $default_value = '', $null = '', $after_field = '')
+ protected function _attr_auto_increment(&$attributes, &$field)
{
- /* SQLite only supports adding new columns and it does
- * NOT support the AFTER statement. Each new column will
- * be added as the last one in the table.
- */
- if ($alter_type !== 'ADD COLUMN')
+ if ( ! empty($attributes['AUTO_INCREMENT']) && $attributes['AUTO_INCREMENT'] === TRUE && stripos($field['type'], 'int') !== FALSE)
{
- // Not supported
- return FALSE;
- }
+ $field['type'] = 'INTEGER PRIMARY KEY';
+ $field['default'] = '';
+ $field['null'] = '';
+ $field['unique'] = '';
+ $field['auto_increment'] = ' AUTOINCREMENT';
- return 'ALTER TABLE '.$this->db->protect_identifiers($table).' '.$alter_type.' '.$this->db->protect_identifiers($column_name)
- .' '.$column_definition
- .($default_value != '' ? ' DEFAULT '.$default_value : '')
- // If NOT NULL is specified, the field must have a DEFAULT value other than NULL
- .(($null !== NULL && $default_value !== 'NULL') ? ' NOT NULL' : ' NULL');
+ $this->primary_keys = array();
+ }
}
}
diff --git a/system/database/drivers/sqlite3/sqlite3_result.php b/system/database/drivers/sqlite3/sqlite3_result.php
index d83d6b2cd..69c42002c 100644
--- a/system/database/drivers/sqlite3/sqlite3_result.php
+++ b/system/database/drivers/sqlite3/sqlite3_result.php
@@ -1,8 +1,8 @@
-<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');
+<?php
/**
* CodeIgniter
*
- * An open source application development framework for PHP 5.1.6 or newer
+ * An open source application development framework for PHP 5.2.4 or newer
*
* NOTICE OF LICENSE
*
@@ -24,41 +24,20 @@
* @since Version 1.0
* @filesource
*/
+defined('BASEPATH') OR exit('No direct script access allowed');
/**
- * SQLite Result Class
+ * SQLite3 Result Class
*
* This class extends the parent result class: CI_DB_result
*
* @category Database
- * @author Andrey Andreev
- * @link http://codeigniter.com/user_guide/database/
+ * @author Andrey Andreev
+ * @link http://codeigniter.com/user_guide/database/
+ * @since 3.0
*/
class CI_DB_sqlite3_result extends CI_DB_result {
- // Overwriting the parent here, so we have a way to know if it's already set
- public $num_rows;
-
- // num_fields() might be called multiple times, so we'll use this one to cache it's result
- protected $_num_fields;
-
- /**
- * Number of rows in the result set
- *
- * @return int
- */
- public function num_rows()
- {
- /* The SQLite3 driver doesn't have a graceful way to do this,
- * so we'll have to do it on our own.
- */
- return is_int($this->num_rows)
- ? $this->num_rows
- : $this->num_rows = count($this->result_array());
- }
-
- // --------------------------------------------------------------------
-
/**
* Number of fields in the result set
*
@@ -66,9 +45,7 @@ class CI_DB_sqlite3_result extends CI_DB_result {
*/
public function num_fields()
{
- return ( ! is_int($this->_num_fields))
- ? $this->_num_fields = $this->result_id->numColumns()
- : $this->_num_fields;
+ return $this->result_id->numColumns();
}
// --------------------------------------------------------------------
@@ -102,15 +79,24 @@ class CI_DB_sqlite3_result extends CI_DB_result {
*/
public function field_data()
{
+ static $data_types = array(
+ SQLITE3_INTEGER => 'integer',
+ SQLITE3_FLOAT => 'float',
+ SQLITE3_TEXT => 'text',
+ SQLITE3_BLOB => 'blob',
+ SQLITE3_NULL => 'null'
+ );
+
$retval = array();
for ($i = 0, $c = $this->num_fields(); $i < $this->num_fields(); $i++)
{
$retval[$i] = new stdClass();
$retval[$i]->name = $this->result_id->columnName($i);
- $retval[$i]->type = 'varchar';
- $retval[$i]->max_length = 0;
- $retval[$i]->primary_key = 0;
- $retval[$i]->default = '';
+
+ $type = $this->result_id->columnType($i);
+ $retval[$i]->type = isset($data_types[$type]) ? $data_types[$type] : $type;
+
+ $retval[$i]->max_length = NULL;
}
return $retval;
@@ -153,443 +139,28 @@ class CI_DB_sqlite3_result extends CI_DB_result {
*
* Returns the result set as an object
*
+ * @param string $class_name
* @return object
*/
- protected function _fetch_object()
- {
- // No native support for fetching as an object
- $row = $this->_fetch_assoc();
- return ($row !== FALSE) ? (object) $row : FALSE;
- }
-
- // --------------------------------------------------------------------
-
- /**
- * Query result. "array" version.
- *
- * return array
- */
- public function result_array()
- {
- if (count($this->result_array) > 0)
- {
- return $this->result_array;
- }
- elseif (is_array($this->row_data))
- {
- if (count($this->row_data) === 0)
- {
- return $this->result_array;
- }
- else
- {
- $row_index = count($this->row_data);
- }
- }
- else
- {
- $row_index = 0;
- $this->row_data = array();
- }
-
- $row = NULL;
- while ($row = $this->_fetch_assoc())
- {
- $this->row_data[$row_index++] = $row;
- }
-
- return $this->result_array = $this->row_data;
- }
-
- // --------------------------------------------------------------------
-
- /**
- * Query result. "object" version.
- *
- * @return array
- */
- public function result_object()
- {
- if (count($this->result_object) > 0)
- {
- return $this->result_object;
- }
- elseif (count($this->result_array) > 0)
- {
- for ($i = 0, $c = count($this->result_array); $i < $c; $i++)
- {
- $this->result_object[] = (object) $this->result_array[$i];
- }
-
- return $this->result_object;
- }
- elseif (is_array($this->row_data))
- {
- if (count($this->row_data) === 0)
- {
- return $this->result_object;
- }
- else
- {
- $row_index = count($this->row_data);
- for ($i = 0; $i < $row_index; $i++)
- {
- $this->result_object[$i] = (object) $this->row_data[$i];
- }
- }
- }
- else
- {
- $row_index = 0;
- $this->row_data = array();
- }
-
- $row = NULL;
- while ($row = $this->_fetch_assoc())
- {
- $this->row_data[$row_index] = $row;
- $this->result_object[$row_index++] = (object) $row;
- }
-
- $this->result_array = $this->row_data;
-
- /* As described for the num_rows() method - there's no easy
- * way to get the number of rows selected. Our work-around
- * solution (as in here as well) first checks if result_array
- * exists and returns its count. It doesn't however check for
- * custom_object_result, so - do it here.
- */
- if ( ! is_int($this->num_rows))
- {
- $this->num_rows = count($this->result_object);
- }
-
- return $this->result_object;
- }
-
- // --------------------------------------------------------------------
-
- /**
- * Query result. Custom object version.
- *
- * @param string class name used to instantiate rows to
- * @return array
- */
- public function custom_result_object($class_name)
- {
- if (array_key_exists($class_name, $this->custom_result_object))
- {
- return $this->custom_result_object[$class_name];
- }
-
- if ( ! class_exists($class_name) OR ! is_object($this->result_id) OR $this->num_rows() === 0)
- {
- return array();
- }
-
- /* Even if result_array hasn't been set prior to custom_result_object being called,
- * num_rows() has done it.
- */
- $data = &$this->result_array;
-
- $result_object = array();
- for ($i = 0, $c = count($data); $i < $c; $i++)
- {
- $result_object[$i] = new $class_name();
- foreach ($data[$i] as $key => $value)
- {
- $result_object[$i]->$key = $value;
- }
- }
-
- /* As described for the num_rows() method - there's no easy
- * way to get the number of rows selected. Our work-around
- * solution (as in here as well) first checks if result_array
- * exists and returns its count. It doesn't however check for
- * custom_object_result, so - do it here.
- */
- if ( ! is_int($this->num_rows))
- {
- $this->num_rows = count($result_object);
- }
-
- // Cache and return the array
- return $this->custom_result_object[$class_name] = $result_object;
- }
-
- // --------------------------------------------------------------------
-
- /* Single row result.
- *
- * Acts as a wrapper for row_object(), row_array()
- * and custom_row_object(). Also used by first_row(), next_row()
- * and previous_row().
- *
- * @param int row index
- * @param string ('object', 'array' or a custom class name)
- * @return mixed whatever was passed to the second parameter
- */
- public function row($n = 0, $type = 'object')
- {
- if ($type === 'object')
- {
- return $this->row_object($n);
- }
- elseif ($type === 'array')
- {
- return $this->row_array($n);
- }
-
- return $this->custom_row_object($n, $type);
- }
-
- // --------------------------------------------------------------------
-
- /* Single row result. Array version.
- *
- * @param int row index
- * @return array
- */
- public function row_array($n = 0)
+ protected function _fetch_object($class_name = 'stdClass')
{
- // Make sure $n is not a string
- if ( ! is_int($n))
+ // No native support for fetching rows as objects
+ if (($row = $this->result_id->fetchArray(SQLITE3_ASSOC)) === FALSE)
{
- $n = (int) $n;
+ return FALSE;
}
-
- /* If row_data is initialized, it means that we've already tried
- * (at least) to fetch some data, so ... check if we already have
- * this row.
- */
- if (is_array($this->row_data))
+ elseif ($class_name === 'stdClass')
{
- /* If we already have row_data[$n] - return it.
- *
- * If we enter the elseif, there's a number of reasons to
- * return an empty array:
- *
- * - count($this->row_data) === 0 means there are no results
- * - num_rows being set or result_array having count() > 0 means
- * that we've already fetched all data and $n is greater than
- * our highest row index available
- * - $n < $this->current_row means that if such row existed,
- * we would've already returned it, therefore $n is an
- * invalid index
- */
- if (isset($this->row_data[$n])) // We already have this row
- {
- $this->current_row = $n;
- return $this->row_data[$n];
- }
- elseif (count($this->row_data) === 0 OR is_int($this->num_rows)
- OR count($this->result_array) > 0 OR $n < $this->current_row)
- {
- // No such row exists
- return array();
- }
-
- // Get the next row index that would actually need to be fetched
- $current_row = ($this->current_row < count($this->row_data)) ? count($this->row_data) : $this->current_row + 1;
- }
- else
- {
- $current_row = $this->current_row = 0;
- $this->row_data = array();
- }
-
- /* Fetch more data, if available
- *
- * NOTE: Operator precedence is important here, if you change
- * 'AND' with '&&' - it WILL BREAK the results, as
- * $row will be assigned the scalar value of both
- * expressions!
- */
- while ($row = $this->_fetch_assoc() AND $current_row <= $n)
- {
- $this->row_data[$current_row++] = $row;
- }
-
- // This would mean that there's no (more) data to fetch
- if ( ! is_array($this->row_data) OR ! isset($this->row_data[$n]))
- {
- // Cache what we already have
- if (is_array($this->row_data))
- {
- $this->num_rows = count($this->row_data);
- /* Usually, row_data could have less elements than result_array,
- * but at this point - they should be exactly the same.
- */
- $this->result_array = $this->row_data;
- }
- else
- {
- $this->num_rows = 0;
- }
-
- return array();
- }
-
- $this->current_row = $n;
- return $this->row_data[$n];
- }
-
- // --------------------------------------------------------------------
-
- /* Single row result. Object version.
- *
- * @param int row index
- * @return mixed object if row found; empty array if not
- */
- public function row_object($n = 0)
- {
- // Make sure $n is not a string
- if ( ! is_int($n))
- {
- $n = (int) $n;
- }
-
- /* Logic here is exactly the same as in row_array,
- * except we have to cast row_data[$n] to an object.
- *
- * If we already have result_object though - we can
- * directly return from it.
- */
- if (isset($this->result_object[$n]))
- {
- $this->current_row = $n;
- return $this->result_object[$n];
- }
-
- $row = $this->row_array($n);
- // Cast only if the row exists
- if (count($row) > 0)
- {
- $this->current_row = $n;
return (object) $row;
}
- return array();
- }
-
- // --------------------------------------------------------------------
-
- /* Single row result. Custom object version.
- *
- * @param int row index
- * @param string custom class name
- * @return mixed custom object if row found; empty array otherwise
- */
- public function custom_row_object($n = 0, $class_name)
- {
- // Make sure $n is not a string
- if ( ! is_int($n))
- {
- $n = (int) $n;
- }
-
- if (array_key_exists($class_name, $this->custom_result_object))
- {
- /* We already have a the whole result set with this class_name,
- * return the specified row if it exists, and an empty array if
- * it doesn't.
- */
- if (isset($this->custom_result_object[$class_name][$n]))
- {
- $this->current_row = $n;
- return $this->custom_result_object[$class_name][$n];
- }
- else
- {
- return array();
- }
- }
- elseif ( ! class_exists($class_name)) // No such class exists
- {
- return array();
- }
-
- $row = $this->row_array($n);
- // An array would mean that the row doesn't exist
- if (is_array($row))
- {
- return $row;
- }
-
- // Convert to the desired class and return
- $row_object = new $class_name();
- foreach ($row as $key => $value)
+ $class_name = new $class_name();
+ foreach (array_keys($row) as $key)
{
- $row_object->$key = $value;
+ $class_name->$key = $row[$key];
}
- $this->current_row = $n;
- return $row_object;
- }
-
- // --------------------------------------------------------------------
-
- /* First row result.
- *
- * @param string ('object', 'array' or a custom class name)
- * @return mixed whatever was passed to the second parameter
- */
- public function first_row($type = 'object')
- {
- return $this->row(0, $type);
- }
-
- // --------------------------------------------------------------------
-
- /* Last row result.
- *
- * @param string ('object', 'array' or a custom class name)
- * @return mixed whatever was passed to the second parameter
- */
- public function last_row($type = 'object')
- {
- $result = &$this->result($type);
- if ( ! isset($this->num_rows))
- {
- $this->num_rows = count($result);
- }
- $this->current_row = $this->num_rows - 1;
- return $result[$this->current_row];
- }
-
- // --------------------------------------------------------------------
-
- /* Next row result.
- *
- * @param string ('object', 'array' or a custom class name)
- * @return mixed whatever was passed to the second parameter
- */
- public function next_row($type = 'object')
- {
- if (is_array($this->row_data))
- {
- $count = count($this->row_data);
- $n = ($this->current_row > $count OR ($this->current_row === 0 && $count === 0)) ? $count : $this->current_row + 1;
- }
- else
- {
- $n = 0;
- }
-
- return $this->row($n, $type);
- }
-
- // --------------------------------------------------------------------
-
- /* Previous row result.
- *
- * @param string ('object', 'array' or a custom class name)
- * @return mixed whatever was passed to the second parameter
- */
- public function previous_row($type = 'object')
- {
- $n = ($this->current_row !== 0) ? $this->current_row - 1 : 0;
- return $this->row($n, $type);
+ return $class_name;
}
// --------------------------------------------------------------------
@@ -599,14 +170,15 @@ class CI_DB_sqlite3_result extends CI_DB_result {
*
* Moves the internal pointer to the desired offset. We call
* this internally before fetching results to make sure the
- * result set starts at zero
+ * result set starts at zero.
*
+ * @param int $n (ignored)
* @return array
*/
- protected function _data_seek($n = 0)
+ public function data_seek($n = 0)
{
// Only resetting to the start of the result set is supported
- return $this->result_id->reset();
+ return ($n > 0) ? FALSE : $this->result_id->reset();
}
}
diff --git a/system/database/drivers/sqlite3/sqlite3_utility.php b/system/database/drivers/sqlite3/sqlite3_utility.php
index 965c838e5..c7736cc6d 100644
--- a/system/database/drivers/sqlite3/sqlite3_utility.php
+++ b/system/database/drivers/sqlite3/sqlite3_utility.php
@@ -1,8 +1,8 @@
-<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');
+<?php
/**
* CodeIgniter
*
- * An open source application development framework for PHP 5.1.6 or newer
+ * An open source application development framework for PHP 5.2.4 or newer
*
* NOTICE OF LICENSE
*
@@ -24,6 +24,7 @@
* @since Version 1.0
* @filesource
*/
+defined('BASEPATH') OR exit('No direct script access allowed');
/**
* SQLite3 Utility Class
@@ -34,18 +35,16 @@
*/
class CI_DB_sqlite3_utility extends CI_DB_utility {
- protected $_list_databases = FALSE;
-
/**
- * SQLite Export
+ * Export
*
- * @param array Preferences
+ * @param array $params Preferences
* @return mixed
*/
protected function _backup($params = array())
{
// Not supported
- return $this->db->display_error('db_unsuported_feature');
+ return $this->db->display_error('db_unsupported_feature');
}
}
diff --git a/system/database/drivers/sqlsrv/sqlsrv_driver.php b/system/database/drivers/sqlsrv/sqlsrv_driver.php
index 951567033..ee9823ed1 100644
--- a/system/database/drivers/sqlsrv/sqlsrv_driver.php
+++ b/system/database/drivers/sqlsrv/sqlsrv_driver.php
@@ -1,4 +1,4 @@
-<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');
+<?php
/**
* CodeIgniter
*
@@ -21,15 +21,16 @@
* @copyright Copyright (c) 2008 - 2012, EllisLab, Inc. (http://ellislab.com/)
* @license http://opensource.org/licenses/OSL-3.0 Open Software License (OSL 3.0)
* @link http://codeigniter.com
- * @since Version 1.0
+ * @since Version 2.0.3
* @filesource
*/
+defined('BASEPATH') OR exit('No direct script access allowed');
/**
* SQLSRV Database Adapter Class
*
* Note: _DB is an extender class that the app controller
- * creates dynamically based on whether the active record
+ * creates dynamically based on whether the query builder
* class is being used or not.
*
* @package CodeIgniter
@@ -40,39 +41,52 @@
*/
class CI_DB_sqlsrv_driver extends CI_DB {
+ /**
+ * Database driver
+ *
+ * @var string
+ */
public $dbdriver = 'sqlsrv';
- // The character used for escaping
- protected $_escape_char = '';
+ // --------------------------------------------------------------------
- // clause and character used for LIKE escape sequences
- protected $_like_escape_str = " ESCAPE '%s' ";
- protected $_like_escape_chr = '!';
+ /**
+ * ORDER BY random keyword
+ *
+ * @var array
+ */
+ protected $_random_keyword = array('NEWID()', 'RAND(%d)');
/**
- * The syntax to count rows is slightly different across different
- * database engines, so this string appears in each driver and is
- * used for the count_all() and count_all_results() functions.
+ * Quoted identifier flag
+ *
+ * Whether to use SQL-92 standard quoted identifier
+ * (double quotes) or brackets for identifier escaping.
+ *
+ * @var bool
*/
- protected $_count_string = 'SELECT COUNT(*) AS ';
- protected $_random_keyword = ' NEWID()'; // not currently supported
+ protected $_quoted_identifier = TRUE;
+
+ // --------------------------------------------------------------------
/**
- * Non-persistent database connection
+ * Database connection
*
+ * @param bool $pooling
* @return resource
*/
public function db_connect($pooling = FALSE)
{
- // Check for a UTF-8 charset being passed as CI's default 'utf8'.
- $character_set = (0 === strcasecmp('utf8', $this->char_set)) ? 'UTF-8' : $this->char_set;
+ $charset = in_array(strtolower($this->char_set), array('utf-8', 'utf8'), TRUE)
+ ? 'UTF-8' : SQLSRV_ENC_CHAR;
$connection = array(
'UID' => empty($this->username) ? '' : $this->username,
'PWD' => empty($this->password) ? '' : $this->password,
'Database' => $this->database,
- 'ConnectionPooling' => $pooling ? 1 : 0,
- 'CharacterSet' => $character_set,
+ 'ConnectionPooling' => ($pooling === TRUE) ? 1 : 0,
+ 'CharacterSet' => $charset,
+ 'Encrypt' => ($this->encrypt === TRUE) ? 1 : 0,
'ReturnDatesAsStrings' => 1
);
@@ -83,7 +97,15 @@ class CI_DB_sqlsrv_driver extends CI_DB {
unset($connection['UID'], $connection['PWD']);
}
- return sqlsrv_connect($this->hostname, $connection);
+ $this->conn_id = sqlsrv_connect($this->hostname, $connection);
+
+ // Determine how identifiers are escaped
+ $query = $this->query('SELECT CASE WHEN (@@OPTIONS | 256) = @@OPTIONS THEN 1 ELSE 0 END AS qi');
+ $query = $query->row_array();
+ $this->_quoted_identifier = empty($query) ? FALSE : (bool) $query['qi'];
+ $this->_escape_char = ($this->_quoted_identifier) ? '"' : array('[', ']');
+
+ return $this->conn_id;
}
// --------------------------------------------------------------------
@@ -103,7 +125,7 @@ class CI_DB_sqlsrv_driver extends CI_DB {
/**
* Select the database
*
- * @param string database name
+ * @param string $database
* @return bool
*/
public function db_select($database = '')
@@ -113,7 +135,7 @@ class CI_DB_sqlsrv_driver extends CI_DB {
$database = $this->database;
}
- if ($this->_execute('USE '.$database))
+ if ($this->_execute('USE '.$this->escape_identifiers($database)))
{
$this->database = $database;
return TRUE;
@@ -127,16 +149,14 @@ class CI_DB_sqlsrv_driver extends CI_DB {
/**
* Execute the query
*
- * @param string an SQL query
+ * @param string $sql an SQL query
* @return resource
*/
protected function _execute($sql)
{
- return sqlsrv_query($this->conn_id,
- $sql,
- NULL,
- array('Scrollable'=> SQLSRV_CURSOR_STATIC, 'SendStreamParamsAtExec' => TRUE)
- );
+ return ($this->is_write_type($sql) && stripos($sql, 'INSERT') === FALSE)
+ ? sqlsrv_query($this->conn_id, $sql)
+ : sqlsrv_query($this->conn_id, $sql, NULL, array('Scrollable' => SQLSRV_CURSOR_STATIC));
}
// --------------------------------------------------------------------
@@ -144,17 +164,13 @@ class CI_DB_sqlsrv_driver extends CI_DB {
/**
* Begin Transaction
*
+ * @param bool $test_mode
* @return bool
*/
public function trans_begin($test_mode = FALSE)
{
- if ( ! $this->trans_enabled)
- {
- return TRUE;
- }
-
// When transactions are nested we only begin/commit/rollback the outermost ones
- if ($this->_trans_depth > 0)
+ if ( ! $this->trans_enabled OR $this->_trans_depth > 0)
{
return TRUE;
}
@@ -162,7 +178,7 @@ class CI_DB_sqlsrv_driver extends CI_DB {
// Reset the transaction failure flag.
// If the $test_mode flag is set to TRUE transactions will be rolled back
// even if the queries produce a successful result.
- $this->_trans_failure = ($test_mode === TRUE) ? TRUE : FALSE;
+ $this->_trans_failure = ($test_mode === TRUE);
return sqlsrv_begin_transaction($this->conn_id);
}
@@ -176,13 +192,8 @@ class CI_DB_sqlsrv_driver extends CI_DB {
*/
public function trans_commit()
{
- if ( ! $this->trans_enabled)
- {
- return TRUE;
- }
-
// When transactions are nested we only begin/commit/rollback the outermost ones
- if ($this->_trans_depth > 0)
+ if ( ! $this->trans_enabled OR $this->_trans_depth > 0)
{
return TRUE;
}
@@ -199,13 +210,8 @@ class CI_DB_sqlsrv_driver extends CI_DB {
*/
public function trans_rollback()
{
- if ( ! $this->trans_enabled)
- {
- return TRUE;
- }
-
// When transactions are nested we only begin/commit/rollback the outermost ones
- if ($this->_trans_depth > 0)
+ if ( ! $this->trans_enabled OR $this->_trans_depth > 0)
{
return TRUE;
}
@@ -218,8 +224,8 @@ class CI_DB_sqlsrv_driver extends CI_DB {
/**
* Escape String
*
- * @param string
- * @param bool whether or not the string will be used in a LIKE condition
+ * @param string $str
+ * @param bool $like Whether or not the string will be used in a LIKE condition
* @return string
*/
public function escape_str($str, $like = FALSE)
@@ -237,7 +243,7 @@ class CI_DB_sqlsrv_driver extends CI_DB {
*/
public function affected_rows()
{
- return @sqlrv_rows_affected($this->conn_id);
+ return sqlsrv_rows_affected($this->result_id);
}
// --------------------------------------------------------------------
@@ -269,42 +275,17 @@ class CI_DB_sqlsrv_driver extends CI_DB {
{
return $this->data_cache['version'];
}
-
- if (($info = sqlsrv_server_info($this->conn_id)) === FALSE)
+ elseif ( ! $this->conn_id)
{
- return FALSE;
+ $this->initialize();
}
- return $this->data_cache['version'] = $info['SQLServerVersion'];
- }
-
- // --------------------------------------------------------------------
-
- /**
- * "Count All" query
- *
- * Generates a platform-specific query string that counts all records in
- * the specified database
- *
- * @param string
- * @return int
- */
- public function count_all($table = '')
- {
- if ($table == '')
- {
- return 0;
- }
-
- $query = $this->query("SELECT COUNT(*) AS numrows FROM " . $this->dbprefix . $table);
- if ($query->num_rows() == 0)
+ if ( ! $this->conn_id OR ($info = sqlsrv_server_info($this->conn_id)) === FALSE)
{
- return 0;
+ return FALSE;
}
- $row = $query->row();
- $this->_reset_select();
- return (int) $row->numrows;
+ return $this->data_cache['version'] = $info['SQLServerVersion'];
}
// --------------------------------------------------------------------
@@ -315,11 +296,21 @@ class CI_DB_sqlsrv_driver extends CI_DB {
* Generates a platform-specific query string so that the table names can be fetched
*
* @param bool
- * @return string
+ * @return string $prefix_limit
*/
protected function _list_tables($prefix_limit = FALSE)
{
- return "SELECT name FROM sysobjects WHERE type = 'U' ORDER BY name";
+ $sql = 'SELECT '.$this->escape_identifiers('name')
+ .' FROM '.$this->escape_identifiers('sysobjects')
+ .' WHERE '.$this->escape_identifiers('type')." = 'U'";
+
+ if ($prefix_limit === TRUE && $this->dbprefix !== '')
+ {
+ $sql .= ' AND '.$this->escape_identifiers('name')." LIKE '".$this->escape_like_str($this->dbprefix)."%' "
+ .sprintf($this->_escape_like_str, $this->_escape_like_chr);
+ }
+
+ return $sql.' ORDER BY '.$this->escape_identifiers('name');
}
// --------------------------------------------------------------------
@@ -329,27 +320,52 @@ class CI_DB_sqlsrv_driver extends CI_DB {
*
* Generates a platform-specific query string so that the column names can be fetched
*
- * @param string the table name
+ * @param string $table
* @return string
*/
protected function _list_columns($table = '')
{
- return "SELECT * FROM INFORMATION_SCHEMA.Columns WHERE TABLE_NAME = '".$table."'";
+ return 'SELECT COLUMN_NAME
+ FROM INFORMATION_SCHEMA.Columns
+ WHERE UPPER(TABLE_NAME) = '.$this->escape(strtoupper($table));
}
// --------------------------------------------------------------------
/**
- * Field data query
- *
- * Generates a platform-specific query so that the column data can be retrieved
+ * Returns an object with field data
*
- * @param string the table name
- * @return string
+ * @param string $table
+ * @return array
*/
- protected function _field_data($table)
+ public function field_data($table = '')
{
- return 'SELECT TOP 1 * FROM '.$table;
+ if ($table === '')
+ {
+ return ($this->db_debug) ? $this->display_error('db_field_param_missing') : FALSE;
+ }
+
+ $sql = 'SELECT COLUMN_NAME, DATA_TYPE, CHARACTER_MAXIMUM_LENGTH, NUMERIC_PRECISION, COLUMN_DEFAULT
+ FROM INFORMATION_SCHEMA.Columns
+ WHERE UPPER(TABLE_NAME) = '.$this->escape(strtoupper($table));
+
+ if (($query = $this->query($sql)) === FALSE)
+ {
+ return FALSE;
+ }
+ $query = $query->result_object();
+
+ $retval = array();
+ for ($i = 0, $c = count($query); $i < $c; $i++)
+ {
+ $retval[$i] = new stdClass();
+ $retval[$i]->name = $query[$i]->COLUMN_NAME;
+ $retval[$i]->type = $query[$i]->DATA_TYPE;
+ $retval[$i]->max_length = ($query[$i]->CHARACTER_MAXIMUM_LENGTH > 0) ? $query[$i]->CHARACTER_MAXIMUM_LENGTH : $query[$i]->NUMERIC_PRECISION;
+ $retval[$i]->default = $query[$i]->COLUMN_DEFAULT;
+ }
+
+ return $retval;
}
// --------------------------------------------------------------------
@@ -393,54 +409,19 @@ class CI_DB_sqlsrv_driver extends CI_DB {
// --------------------------------------------------------------------
/**
- * From Tables
- *
- * This function implicitly groups FROM tables so there is no confusion
- * about operator precedence in harmony with SQL standards
- *
- * @param array
- * @return string
- */
- protected function _from_tables($tables)
- {
- if ( ! is_array($tables))
- {
- $tables = array($tables);
- }
-
- return implode(', ', $tables);
- }
-
- // --------------------------------------------------------------------
-
- /**
* Update statement
*
* Generates a platform-specific update string from the supplied data
*
- * @param string the table name
- * @param array the update data
- * @param array the where clause
- * @param array the orderby clause (ignored)
- * @param array the limit clause (ignored)
- * @param array the like clause
+ * @param string $table
+ * @param array $values
* @return string
*/
- protected function _update($table, $values, $where, $orderby = array(), $limit = FALSE, $like = array())
+ protected function _update($table, $values)
{
- foreach($values as $key => $val)
- {
- $valstr[] = $key.' = '.$val;
- }
-
- $where = empty($where) ? '' : ' WHERE '.implode(' ', $where);
-
- if ( ! empty($like))
- {
- $where .= ($where === '' ? ' WHERE ' : ' AND ').implode(' ', $like);
- }
-
- return 'UPDATE '.$table.' SET '.implode(', ', $valstr).' WHERE '.$where;
+ $this->qb_limit = FALSE;
+ $this->qb_orderby = array();
+ return parent::_update($table, $values);
}
// --------------------------------------------------------------------
@@ -450,10 +431,10 @@ class CI_DB_sqlsrv_driver extends CI_DB {
*
* Generates a platform-specific truncate string from the supplied data
*
- * If the database does not support the truncate() command,
+ * If the database does not support the TRUNCATE statement,
* then this method maps to 'DELETE FROM table'
*
- * @param string the table name
+ * @param string $table
* @return string
*/
protected function _truncate($table)
@@ -468,41 +449,96 @@ class CI_DB_sqlsrv_driver extends CI_DB {
*
* Generates a platform-specific delete string from the supplied data
*
- * @param string the table name
- * @param array the where clause
- * @param array the like clause
- * @param string the limit clause
+ * @param string $table
* @return string
*/
- protected function _delete($table, $where = array(), $like = array(), $limit = FALSE)
+ protected function _delete($table)
{
- $conditions = array();
-
- empty($where) OR $conditions[] = implode(' ', $where);
- empty($like) OR $conditions[] = implode(' ', $like);
-
- $conditions = (count($conditions) > 0) ? ' WHERE '.implode(' AND ', $conditions) : '';
+ if ($this->qb_limit)
+ {
+ return 'WITH ci_delete AS (SELECT TOP '.$this->qb_limit.' * FROM '.$table.$this->_compile_wh('qb_where').') DELETE FROM ci_delete';
+ }
- return ($limit)
- ? 'WITH ci_delete AS (SELECT TOP '.$limit.' * FROM '.$table.$conditions.') DELETE FROM ci_delete'
- : 'DELETE FROM '.$table.$conditions;
+ return parent::_delete($table);
}
// --------------------------------------------------------------------
/**
- * Limit string
+ * LIMIT
*
* Generates a platform-specific LIMIT clause
*
- * @param string the sql query string
- * @param int the number of rows to limit the query to
- * @param int the offset value
+ * @param string $sql SQL Query
* @return string
*/
- protected function _limit($sql, $limit, $offset)
+ protected function _limit($sql)
+ {
+ // As of SQL Server 2012 (11.0.*) OFFSET is supported
+ if (version_compare($this->version(), '11', '>='))
+ {
+ return $sql.' OFFSET '.(int) $this->qb_offset.' ROWS FETCH NEXT '.$this->qb_limit.' ROWS ONLY';
+ }
+
+ $limit = $this->qb_offset + $this->qb_limit;
+
+ // An ORDER BY clause is required for ROW_NUMBER() to work
+ if ($this->qb_offset && ! empty($this->qb_orderby))
+ {
+ $orderby = $this->_compile_order_by();
+
+ // We have to strip the ORDER BY clause
+ $sql = trim(substr($sql, 0, strrpos($sql, $orderby)));
+
+ // Get the fields to select from our subquery, so that we can avoid CI_rownum appearing in the actual results
+ if (count($this->qb_select) === 0)
+ {
+ $select = '*'; // Inevitable
+ }
+ else
+ {
+ // Use only field names and their aliases, everything else is out of our scope.
+ $select = array();
+ $field_regexp = ($this->_quoted_identifier)
+ ? '("[^\"]+")' : '(\[[^\]]+\])';
+ for ($i = 0, $c = count($this->qb_select); $i < $c; $i++)
+ {
+ $select[] = preg_match('/(?:\s|\.)'.$field_regexp.'$/i', $this->qb_select[$i], $m)
+ ? $m[1] : $this->qb_select[$i];
+ }
+ $select = implode(', ', $select);
+ }
+
+ return 'SELECT '.$select." FROM (\n\n"
+ .preg_replace('/^(SELECT( DISTINCT)?)/i', '\\1 ROW_NUMBER() OVER('.trim($orderby).') AS '.$this->escape_identifiers('CI_rownum').', ', $sql)
+ ."\n\n) ".$this->escape_identifiers('CI_subquery')
+ ."\nWHERE ".$this->escape_identifiers('CI_rownum').' BETWEEN '.($this->qb_offset + 1).' AND '.$limit;
+ }
+
+ return preg_replace('/(^\SELECT (DISTINCT)?)/i','\\1 TOP '.$limit.' ', $sql);
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Insert batch statement
+ *
+ * Generates a platform-specific insert string from the supplied data.
+ *
+ * @param string $table Table name
+ * @param array $keys INSERT keys
+ * @param array $values INSERT values
+ * @return string|bool
+ */
+ protected function _insert_batch($table, $keys, $values)
{
- return preg_replace('/(^\SELECT (DISTINCT)?)/i','\\1 TOP '.($limit + $offset).' ', $sql);
+ // Multiple-value inserts are only supported as of SQL Server 2008
+ if (version_compare($this->version(), '10', '>='))
+ {
+ return parent::_insert_batch($table, $keys, $values);
+ }
+
+ return ($this->db->db_debug) ? $this->db->display_error('db_unsupported_feature') : FALSE;
}
// --------------------------------------------------------------------
@@ -510,12 +546,11 @@ class CI_DB_sqlsrv_driver extends CI_DB {
/**
* Close DB Connection
*
- * @param resource
* @return void
*/
- protected function _close($conn_id)
+ protected function _close()
{
- @sqlsrv_close($conn_id);
+ @sqlsrv_close($this->conn_id);
}
}
diff --git a/system/database/drivers/sqlsrv/sqlsrv_forge.php b/system/database/drivers/sqlsrv/sqlsrv_forge.php
index e9143b269..da8f68c56 100644
--- a/system/database/drivers/sqlsrv/sqlsrv_forge.php
+++ b/system/database/drivers/sqlsrv/sqlsrv_forge.php
@@ -1,4 +1,4 @@
-<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');
+<?php
/**
* CodeIgniter
*
@@ -21,9 +21,10 @@
* @copyright Copyright (c) 2008 - 2012, EllisLab, Inc. (http://ellislab.com/)
* @license http://opensource.org/licenses/OSL-3.0 Open Software License (OSL 3.0)
* @link http://codeigniter.com
- * @since Version 1.0
+ * @since Version 2.0.3
* @filesource
*/
+defined('BASEPATH') OR exit('No direct script access allowed');
/**
* SQLSRV Forge Class
@@ -34,162 +35,99 @@
*/
class CI_DB_sqlsrv_forge extends CI_DB_forge {
- protected $_drop_table = 'DROP TABLE %s';
-
/**
- * Create Table
+ * CREATE TABLE IF statement
*
- * @param string the table name
- * @param array the fields
- * @param mixed primary key(s)
- * @param mixed key(s)
- * @param bool should 'IF NOT EXISTS' be added to the SQL
- * @return bool
+ * @var string
*/
- protected function _create_table($table, $fields, $primary_keys, $keys, $if_not_exists)
- {
- $sql = 'CREATE TABLE ';
-
- if ($if_not_exists === TRUE)
- {
- $sql .= 'IF NOT EXISTS ';
- }
-
- $sql .= $this->db->escape_identifiers($table).' (';
- $current_field_count = 0;
-
- foreach ($fields as $field => $attributes)
- {
- // Numeric field names aren't allowed in databases, so if the key is
- // numeric, we know it was assigned by PHP and the developer manually
- // entered the field information, so we'll simply add it to the list
- if (is_numeric($field))
- {
- $sql .= "\n\t$attributes";
- }
- else
- {
- $attributes = array_change_key_case($attributes, CASE_UPPER);
-
- $sql .= "\n\t".$this->db->protect_identifiers($field);
-
- $sql .= ' '.$attributes['TYPE'];
-
- if (array_key_exists('CONSTRAINT', $attributes))
- {
- $sql .= '('.$attributes['CONSTRAINT'].')';
- }
+ protected $_create_table_if = "IF NOT EXISTS (SELECT * FROM sysobjects WHERE ID = object_id(N'%s') AND OBJECTPROPERTY(id, N'IsUserTable') = 1)\nCREATE TABLE";
- if (array_key_exists('UNSIGNED', $attributes) && $attributes['UNSIGNED'] === TRUE)
- {
- $sql .= ' UNSIGNED';
- }
-
- if (array_key_exists('DEFAULT', $attributes))
- {
- $sql .= ' DEFAULT \''.$attributes['DEFAULT'].'\'';
- }
-
- if (array_key_exists('NULL', $attributes) && $attributes['NULL'] === TRUE)
- {
- $sql .= ' NULL';
- }
- else
- {
- $sql .= ' NOT NULL';
- }
+ /**
+ * DROP TABLE IF statement
+ *
+ * @var string
+ */
+ protected $_drop_table_if = "IF EXISTS (SELECT * FROM sysobjects WHERE ID = object_id(N'%s') AND OBJECTPROPERTY(id, N'IsUserTable') = 1)\nDROP TABLE";
- if (array_key_exists('AUTO_INCREMENT', $attributes) && $attributes['AUTO_INCREMENT'] === TRUE)
- {
- $sql .= ' AUTO_INCREMENT';
- }
- }
+ /**
+ * UNSIGNED support
+ *
+ * @var array
+ */
+ protected $_unsigned = array(
+ 'TINYINT' => 'SMALLINT',
+ 'SMALLINT' => 'INT',
+ 'INT' => 'BIGINT',
+ 'REAL' => 'FLOAT'
+ );
- // don't add a comma on the end of the last field
- if (++$current_field_count < count($fields))
- {
- $sql .= ',';
- }
- }
+ // --------------------------------------------------------------------
- if (count($primary_keys) > 0)
+ /**
+ * ALTER TABLE
+ *
+ * @param string $alter_type ALTER type
+ * @param string $table Table name
+ * @param mixed $field Column definition
+ * @return string|string[]
+ */
+ protected function _alter_table($alter_type, $table, $field)
+ {
+ if (in_array($alter_type, array('ADD', 'DROP'), TRUE))
{
- $primary_keys = $this->db->protect_identifiers($primary_keys);
- $sql .= ",\n\tPRIMARY KEY (" . implode(', ', $primary_keys) . ")";
+ return parent::_alter_table($alter_type, $table, $field);
}
- if (is_array($keys) && count($keys) > 0)
+ $sql = 'ALTER TABLE '.$this->db->escape_identifiers($table).' ALTER COLUMN ';
+ $sqls = array();
+ for ($i = 0, $c = count($field); $i < $c; $i++)
{
- foreach ($keys as $key)
- {
- if (is_array($key))
- {
- $key = $this->db->protect_identifiers($key);
- }
- else
- {
- $key = array($this->db->protect_identifiers($key));
- }
-
- $sql .= ",\n\tFOREIGN KEY (" . implode(', ', $key) . ")";
- }
+ $sqls[] = $sql.$this->_process_column($field[$i]);
}
- $sql .= "\n)";
-
- return $sql;
+ return $sqls;
}
// --------------------------------------------------------------------
/**
- * Alter table query
+ * Field attribute TYPE
*
- * Generates a platform-specific query so that a table can be altered
- * Called by add_column(), drop_column(), and column_alter(),
+ * Performs a data type mapping between different databases.
*
- * @param string the ALTER type (ADD, DROP, CHANGE)
- * @param string the column name
- * @param string the table name
- * @param string the column definition
- * @param string the default value
- * @param bool should 'NOT NULL' be added
- * @param string the field after which we should add the new field
- * @return string
+ * @param array &$attributes
+ * @return void
*/
- protected function _alter_table($alter_type, $table, $column_name, $column_definition = '', $default_value = '', $null = '', $after_field = '')
+ protected function _attr_type(&$attributes)
{
- $sql = 'ALTER TABLE '.$this->db->protect_identifiers($table).' '.$alter_type.' '.$this->db->protect_identifiers($column_name);
-
- // DROP has everything it needs now.
- if ($alter_type == 'DROP')
+ switch (strtoupper($attributes['TYPE']))
{
- return $sql;
- }
-
- $sql .= " $column_definition";
-
- if ($default_value != '')
- {
- $sql .= " DEFAULT \"$default_value\"";
+ case 'MEDIUMINT':
+ $attributes['TYPE'] = 'INTEGER';
+ $attributes['UNSIGNED'] = FALSE;
+ return;
+ case 'INTEGER':
+ $attributes['TYPE'] = 'INT';
+ return;
+ default: return;
}
+ }
- if ($null === NULL)
- {
- $sql .= ' NULL';
- }
- else
- {
- $sql .= ' NOT NULL';
- }
+ // --------------------------------------------------------------------
- if ($after_field != '')
+ /**
+ * Field attribute AUTO_INCREMENT
+ *
+ * @param array &$attributes
+ * @param array &$field
+ * @return void
+ */
+ protected function _attr_auto_increment(&$attributes, &$field)
+ {
+ if ( ! empty($attributes['AUTO_INCREMENT']) && $attributes['AUTO_INCREMENT'] === TRUE && stripos($field['type'], 'int') !== FALSE)
{
- return $sql.' AFTER '.$this->db->protect_identifiers($after_field);
+ $field['auto_increment'] = ' IDENTITY(1,1)';
}
-
- return $sql;
-
}
}
diff --git a/system/database/drivers/sqlsrv/sqlsrv_result.php b/system/database/drivers/sqlsrv/sqlsrv_result.php
index 0802677fc..b084b84cd 100644
--- a/system/database/drivers/sqlsrv/sqlsrv_result.php
+++ b/system/database/drivers/sqlsrv/sqlsrv_result.php
@@ -1,4 +1,4 @@
-<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');
+<?php
/**
* CodeIgniter
*
@@ -24,6 +24,7 @@
* @since Version 1.0
* @filesource
*/
+defined('BASEPATH') OR exit('No direct script access allowed');
/**
* SQLSRV Result Class
@@ -33,6 +34,7 @@
* @category Database
* @author EllisLab Dev Team
* @link http://codeigniter.com/user_guide/database/
+ * @since 2.0.3
*/
class CI_DB_sqlsrv_result extends CI_DB_result {
@@ -43,7 +45,9 @@ class CI_DB_sqlsrv_result extends CI_DB_result {
*/
public function num_rows()
{
- return @sqlsrv_num_rows($this->result_id);
+ return is_int($this->num_rows)
+ ? $this->num_rows
+ : $this->num_rows = @sqlsrv_num_rows($this->result_id);
}
// --------------------------------------------------------------------
@@ -90,16 +94,12 @@ class CI_DB_sqlsrv_result extends CI_DB_result {
public function field_data()
{
$retval = array();
- foreach (sqlsrv_field_metadata($this->result_id) as $offset => $field)
+ foreach (sqlsrv_field_metadata($this->result_id) as $i => $field)
{
- $F = new stdClass();
- $F->name = $field['Name'];
- $F->type = $field['Type'];
- $F->max_length = $field['Size'];
- $F->primary_key = 0;
- $F->default = '';
-
- $retval[] = $F;
+ $retval[$i] = new stdClass();
+ $retval[$i]->name = $field['Name'];
+ $retval[$i]->type = $field['Type'];
+ $retval[$i]->max_length = $field['Size'];
}
return $retval;
@@ -142,11 +142,12 @@ class CI_DB_sqlsrv_result extends CI_DB_result {
*
* Returns the result set as an object
*
+ * @param string $class_name
* @return object
*/
- protected function _fetch_object()
+ protected function _fetch_object($class_name = 'stdClass')
{
- return sqlsrv_fetch_object($this->result_id);
+ return sqlsrv_fetch_object($this->result_id, $class_name);
}
}
diff --git a/system/database/drivers/sqlsrv/sqlsrv_utility.php b/system/database/drivers/sqlsrv/sqlsrv_utility.php
index 394964b6a..2bc7f9e03 100644
--- a/system/database/drivers/sqlsrv/sqlsrv_utility.php
+++ b/system/database/drivers/sqlsrv/sqlsrv_utility.php
@@ -1,4 +1,4 @@
-<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');
+<?php
/**
* CodeIgniter
*
@@ -21,9 +21,10 @@
* @copyright Copyright (c) 2008 - 2012, EllisLab, Inc. (http://ellislab.com/)
* @license http://opensource.org/licenses/OSL-3.0 Open Software License (OSL 3.0)
* @link http://codeigniter.com
- * @since Version 1.0
+ * @since Version 2.0.3
* @filesource
*/
+defined('BASEPATH') OR exit('No direct script access allowed');
/**
* SQLSRV Utility Class
@@ -34,19 +35,32 @@
*/
class CI_DB_sqlsrv_utility extends CI_DB_utility {
+ /**
+ * List databases statement
+ *
+ * @var string
+ */
protected $_list_databases = 'EXEC sp_helpdb'; // Can also be: EXEC sp_databases
+
+ /**
+ * OPTIMIZE TABLE statement
+ *
+ * @var string
+ */
protected $_optimize_table = 'ALTER INDEX all ON %s REORGANIZE';
+ // --------------------------------------------------------------------
+
/**
- * SQLSRV Export
+ * Export
*
- * @param array Preferences
- * @return mixed
+ * @param array $params Preferences
+ * @return bool
*/
protected function _backup($params = array())
{
// Currently unsupported
- return $this->db->display_error('db_unsuported_feature');
+ return $this->db->display_error('db_unsupported_feature');
}
}
diff --git a/system/helpers/array_helper.php b/system/helpers/array_helper.php
index 6f56d9db9..0e66e4b77 100644
--- a/system/helpers/array_helper.php
+++ b/system/helpers/array_helper.php
@@ -1,4 +1,4 @@
-<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');
+<?php
/**
* CodeIgniter
*
@@ -24,6 +24,7 @@
* @since Version 1.0
* @filesource
*/
+defined('BASEPATH') OR exit('No direct script access allowed');
/**
* CodeIgniter Array Helpers
@@ -37,35 +38,35 @@
// ------------------------------------------------------------------------
-/**
- * Element
- *
- * Lets you determine whether an array index is set and whether it has a value.
- * If the element is empty it returns FALSE (or whatever you specify as the default value.)
- *
- * @param string
- * @param array
- * @param mixed
- * @return mixed depends on what the array contains
- */
if ( ! function_exists('element'))
{
- function element($item, $array, $default = FALSE)
+ /**
+ * Element
+ *
+ * Lets you determine whether an array index is set and whether it has a value.
+ * If the element is empty it returns NULL (or whatever you specify as the default value.)
+ *
+ * @param string
+ * @param array
+ * @param mixed
+ * @return mixed depends on what the array contains
+ */
+ function element($item, $array, $default = NULL)
{
- return empty($array[$item]) ? $default : $array[$item];
+ return array_key_exists($item, $array) ? $array[$item] : $default;
}
}
// ------------------------------------------------------------------------
-/**
- * Random Element - Takes an array as input and returns a random element
- *
- * @param array
- * @return mixed depends on what the array contains
- */
if ( ! function_exists('random_element'))
{
+ /**
+ * Random Element - Takes an array as input and returns a random element
+ *
+ * @param array
+ * @return mixed depends on what the array contains
+ */
function random_element($array)
{
return is_array($array) ? $array[array_rand($array)] : $array;
@@ -74,20 +75,20 @@ if ( ! function_exists('random_element'))
// --------------------------------------------------------------------
-/**
- * Elements
- *
- * Returns only the array items specified. Will return a default value if
- * it is not set.
- *
- * @param array
- * @param array
- * @param mixed
- * @return mixed depends on what the array contains
- */
if ( ! function_exists('elements'))
{
- function elements($items, $array, $default = FALSE)
+ /**
+ * Elements
+ *
+ * Returns only the array items specified. Will return a default value if
+ * it is not set.
+ *
+ * @param array
+ * @param array
+ * @param mixed
+ * @return mixed depends on what the array contains
+ */
+ function elements($items, $array, $default = NULL)
{
$return = array();
@@ -95,7 +96,7 @@ if ( ! function_exists('elements'))
foreach ($items as $item)
{
- $return[$item] = isset($array[$item]) ? $array[$item] : $default;
+ $return[$item] = array_key_exists($item, $array) ? $array[$item] : $default;
}
return $return;
diff --git a/system/helpers/captcha_helper.php b/system/helpers/captcha_helper.php
index bdbc62097..e9b167fa9 100644
--- a/system/helpers/captcha_helper.php
+++ b/system/helpers/captcha_helper.php
@@ -1,4 +1,4 @@
-<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');
+<?php
/**
* CodeIgniter
*
@@ -24,6 +24,7 @@
* @since Version 1.0
* @filesource
*/
+defined('BASEPATH') OR exit('No direct script access allowed');
/**
* CodeIgniter CAPTCHA Helper
@@ -32,22 +33,22 @@
* @subpackage Helpers
* @category Helpers
* @author EllisLab Dev Team
- * @link http://codeigniter.com/user_guide/helpers/xml_helper.html
+ * @link http://codeigniter.com/user_guide/helpers/captcha_helper.html
*/
// ------------------------------------------------------------------------
-/**
- * Create CAPTCHA
- *
- * @param array array of data for the CAPTCHA
- * @param string path to create the image in
- * @param string URL to the CAPTCHA image folder
- * @param string server path to font
- * @return string
- */
if ( ! function_exists('create_captcha'))
{
+ /**
+ * Create CAPTCHA
+ *
+ * @param array array of data for the CAPTCHA
+ * @param string path to create the image in
+ * @param string URL to the CAPTCHA image folder
+ * @param string server path to font
+ * @return string
+ */
function create_captcha($data = '', $img_path = '', $img_url = '', $font_path = '')
{
$defaults = array('word' => '', 'img_path' => '', 'img_url' => '', 'img_width' => '150', 'img_height' => '30', 'font_path' => '', 'expiration' => 7200);
@@ -64,7 +65,7 @@ if ( ! function_exists('create_captcha'))
}
}
- if ($img_path == '' OR $img_url == ''
+ if ($img_path === '' OR $img_url === ''
OR ! @is_dir($img_path) OR ! is_writeable($img_path)
OR ! extension_loaded('gd'))
{
@@ -80,8 +81,7 @@ if ( ! function_exists('create_captcha'))
$current_dir = @opendir($img_path);
while ($filename = @readdir($current_dir))
{
- if ($filename !== '.' && $filename !== '..' && $filename !== 'index.html'
- && (str_replace('.jpg', '', $filename) + $expiration) < $now)
+ if (substr($filename, -4) === '.jpg' && (str_replace('.jpg', '', $filename) + $expiration) < $now)
{
@unlink($img_path.$filename);
}
@@ -93,7 +93,7 @@ if ( ! function_exists('create_captcha'))
// Do we have a "word" yet?
// -----------------------------------
- if ($word == '')
+ if ($word === '')
{
$pool = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
$word = '';
@@ -156,7 +156,7 @@ if ( ! function_exists('create_captcha'))
// Write the text
// -----------------------------------
- $use_font = ($font_path != '' && file_exists($font_path) && function_exists('imagettftext'));
+ $use_font = ($font_path !== '' && file_exists($font_path) && function_exists('imagettftext'));
if ($use_font === FALSE)
{
$font_size = 5;
@@ -186,7 +186,6 @@ if ( ! function_exists('create_captcha'))
}
}
-
// Create the border
imagerectangle($im, 0, 0, $img_width - 1, $img_height - 1, $border_color);
diff --git a/system/helpers/cookie_helper.php b/system/helpers/cookie_helper.php
index 06560e723..02841409d 100644
--- a/system/helpers/cookie_helper.php
+++ b/system/helpers/cookie_helper.php
@@ -1,4 +1,4 @@
-<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');
+<?php
/**
* CodeIgniter
*
@@ -24,6 +24,7 @@
* @since Version 1.0
* @filesource
*/
+defined('BASEPATH') OR exit('No direct script access allowed');
/**
* CodeIgniter Cookie Helpers
@@ -37,24 +38,24 @@
// ------------------------------------------------------------------------
-/**
- * Set cookie
- *
- * Accepts seven parameters, or you can submit an associative
- * array in the first parameter containing all the values.
- *
- * @param mixed
- * @param string the value of the cookie
- * @param string the number of seconds until expiration
- * @param string the cookie domain. Usually: .yourdomain.com
- * @param string the cookie path
- * @param string the cookie prefix
- * @param bool true makes the cookie secure
- * @param bool true makes the cookie accessible via http(s) only (no javascript)
- * @return void
- */
if ( ! function_exists('set_cookie'))
{
+ /**
+ * Set cookie
+ *
+ * Accepts seven parameters, or you can submit an associative
+ * array in the first parameter containing all the values.
+ *
+ * @param mixed
+ * @param string the value of the cookie
+ * @param string the number of seconds until expiration
+ * @param string the cookie domain. Usually: .yourdomain.com
+ * @param string the cookie path
+ * @param string the cookie prefix
+ * @param bool true makes the cookie secure
+ * @param bool true makes the cookie accessible via http(s) only (no javascript)
+ * @return void
+ */
function set_cookie($name = '', $value = '', $expire = '', $domain = '', $path = '/', $prefix = '', $secure = FALSE, $httponly = FALSE)
{
// Set the config file options
@@ -65,15 +66,15 @@ if ( ! function_exists('set_cookie'))
// --------------------------------------------------------------------
-/**
- * Fetch an item from the COOKIE array
- *
- * @param string
- * @param bool
- * @return mixed
- */
if ( ! function_exists('get_cookie'))
{
+ /**
+ * Fetch an item from the COOKIE array
+ *
+ * @param string
+ * @param bool
+ * @return mixed
+ */
function get_cookie($index = '', $xss_clean = FALSE)
{
$CI =& get_instance();
@@ -84,17 +85,17 @@ if ( ! function_exists('get_cookie'))
// --------------------------------------------------------------------
-/**
- * Delete a COOKIE
- *
- * @param mixed
- * @param string the cookie domain. Usually: .yourdomain.com
- * @param string the cookie path
- * @param string the cookie prefix
- * @return void
- */
if ( ! function_exists('delete_cookie'))
{
+ /**
+ * Delete a COOKIE
+ *
+ * @param mixed
+ * @param string the cookie domain. Usually: .yourdomain.com
+ * @param string the cookie path
+ * @param string the cookie prefix
+ * @return void
+ */
function delete_cookie($name = '', $domain = '', $path = '/', $prefix = '')
{
set_cookie($name, '', '', $domain, $path, $prefix);
diff --git a/system/helpers/date_helper.php b/system/helpers/date_helper.php
index f1ba364f5..d54e01968 100644
--- a/system/helpers/date_helper.php
+++ b/system/helpers/date_helper.php
@@ -1,4 +1,4 @@
-<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');
+<?php
/**
* CodeIgniter
*
@@ -24,6 +24,7 @@
* @since Version 1.0
* @filesource
*/
+defined('BASEPATH') OR exit('No direct script access allowed');
/**
* CodeIgniter Date Helpers
@@ -37,70 +38,71 @@
// ------------------------------------------------------------------------
-/**
- * Get "now" time
- *
- * Returns time() or its GMT equivalent based on the config file preference
- *
- * @return int
- */
if ( ! function_exists('now'))
{
- function now()
+ /**
+ * Get "now" time
+ *
+ * Returns time() based on the timezone parameter or on the
+ * "time_reference" setting
+ *
+ * @param string
+ * @return int
+ */
+ function now($timezone = NULL)
{
- $CI =& get_instance();
-
- if (strtolower($CI->config->item('time_reference')) == 'gmt')
+ if (empty($timezone))
{
- $now = time();
- $system_time = mktime(gmdate("H", $now), gmdate("i", $now), gmdate("s", $now), gmdate("m", $now), gmdate("d", $now), gmdate("Y", $now));
-
- if (strlen($system_time) < 10)
- {
- $system_time = time();
- log_message('error', 'The Date class could not set a proper GMT timestamp so the local time() value was used.');
- }
+ $timezone = config_item('time_reference');
+ }
- return $system_time;
+ if ($timezone === 'local' OR $timezone === date_default_timezone_get())
+ {
+ return time();
}
- return time();
+ $datetime = new DateTime('now', new DateTimeZone($timezone));
+ sscanf($datetime->format('j-n-Y G:i:s'), '%d-%d-%d %d:%d:%d', $day, $month, $year, $hour, $minute, $second);
+
+ return mktime($hour, $minute, $second, $month, $day, $year);
}
}
// ------------------------------------------------------------------------
-/**
- * Convert MySQL Style Datecodes
- *
- * This function is identical to PHPs date() function,
- * except that it allows date codes to be formatted using
- * the MySQL style, where each code letter is preceded
- * with a percent sign: %Y %m %d etc...
- *
- * The benefit of doing dates this way is that you don't
- * have to worry about escaping your text letters that
- * match the date codes.
- *
- * @param string
- * @param int
- * @return int
- */
if ( ! function_exists('mdate'))
{
+ /**
+ * Convert MySQL Style Datecodes
+ *
+ * This function is identical to PHPs date() function,
+ * except that it allows date codes to be formatted using
+ * the MySQL style, where each code letter is preceded
+ * with a percent sign: %Y %m %d etc...
+ *
+ * The benefit of doing dates this way is that you don't
+ * have to worry about escaping your text letters that
+ * match the date codes.
+ *
+ * @param string
+ * @param int
+ * @return int
+ */
function mdate($datestr = '', $time = '')
{
- if ($datestr == '')
+ if ($datestr === '')
{
return '';
}
-
- $time = ($time == '') ? now() : $time;
+ elseif (empty($time))
+ {
+ $time = now();
+ }
$datestr = str_replace(
'%\\',
'',
- preg_replace("/([a-z]+?){1}/i", "\\\\\\1", $datestr)
+ preg_replace('/([a-z]+?){1}/i', '\\\\\\1', $datestr)
);
return date($datestr, $time);
@@ -109,75 +111,67 @@ if ( ! function_exists('mdate'))
// ------------------------------------------------------------------------
-/**
- * Standard Date
- *
- * Returns a date formatted according to the submitted standard.
- *
- * @param string the chosen format
- * @param int Unix timestamp
- * @return string
- */
if ( ! function_exists('standard_date'))
{
- function standard_date($fmt = 'DATE_RFC822', $time = '')
+ /**
+ * Standard Date
+ *
+ * Returns a date formatted according to the submitted standard.
+ *
+ * As of PHP 5.2, the DateTime extension provides constants that
+ * serve for the exact same purpose and are used with date().
+ *
+ * @todo Remove in version 3.1+.
+ * @deprecated 3.0.0 Use PHP's native date() instead.
+ * @link http://www.php.net/manual/en/class.datetime.php#datetime.constants.types
+ *
+ * @example date(DATE_RFC822, now()); // default
+ * @example date(DATE_W3C, $time); // a different format and time
+ *
+ * @param string $fmt = 'DATE_RFC822' the chosen format
+ * @param int $time = NULL Unix timestamp
+ * @return string
+ */
+ function standard_date($fmt = 'DATE_RFC822', $time = NULL)
{
- $formats = array(
- 'DATE_ATOM' => '%Y-%m-%dT%H:%i:%s%O',
- 'DATE_COOKIE' => '%l, %d-%M-%y %H:%i:%s UTC',
- 'DATE_ISO8601' => '%Y-%m-%dT%H:%i:%s%O',
- 'DATE_RFC822' => '%D, %d %M %y %H:%i:%s %O',
- 'DATE_RFC850' => '%l, %d-%M-%y %H:%i:%s UTC',
- 'DATE_RFC1036' => '%D, %d %M %y %H:%i:%s %O',
- 'DATE_RFC1123' => '%D, %d %M %Y %H:%i:%s %O',
- 'DATE_RFC2822' => '%D, %d %M %Y %H:%i:%s %O',
- 'DATE_RSS' => '%D, %d %M %Y %H:%i:%s %O',
- 'DATE_W3C' => '%Y-%m-%dT%H:%i:%s%O'
- );
-
- if ( ! isset($formats[$fmt]))
+ if (empty($time))
+ {
+ $time = now();
+ }
+
+ // Procedural style pre-defined constants from the DateTime extension
+ if (strpos($fmt, 'DATE_') !== 0 OR defined($fmt) === FALSE)
{
return FALSE;
}
- return mdate($formats[$fmt], $time);
+ return date(constant($fmt), $time);
}
}
// ------------------------------------------------------------------------
-/**
- * Timespan
- *
- * Returns a span of seconds in this format:
- * 10 days 14 hours 36 minutes 47 seconds
- *
- * @param int a number of seconds
- * @param int Unix timestamp
- * @param int a number of display units
- * @return string
- */
if ( ! function_exists('timespan'))
{
+ /**
+ * Timespan
+ *
+ * Returns a span of seconds in this format:
+ * 10 days 14 hours 36 minutes 47 seconds
+ *
+ * @param int a number of seconds
+ * @param int Unix timestamp
+ * @param int a number of display units
+ * @return string
+ */
function timespan($seconds = 1, $time = '', $units = 7)
{
$CI =& get_instance();
$CI->lang->load('date');
- if ( ! is_numeric($seconds))
- {
- $seconds = 1;
- }
-
- if ( ! is_numeric($time))
- {
- $time = time();
- }
-
- if ( ! is_numeric($units))
- {
- $units = 7;
- }
+ is_numeric($seconds) OR $seconds = 1;
+ is_numeric($time) OR $time = time();
+ is_numeric($units) OR $units = 7;
$seconds = ($time <= $seconds) ? 1 : $time - $seconds;
@@ -186,7 +180,7 @@ if ( ! function_exists('timespan'))
if ($years > 0)
{
- $str[] = $years.' '.$CI->lang->line((($years > 1) ? 'date_years' : 'date_year'));
+ $str[] = $years.' '.$CI->lang->line($years > 1 ? 'date_years' : 'date_year');
}
$seconds -= $years * 31557600;
@@ -196,7 +190,7 @@ if ( ! function_exists('timespan'))
{
if ($months > 0)
{
- $str[] = $months.' '.$CI->lang->line((($months > 1) ? 'date_months' : 'date_month'));
+ $str[] = $months.' '.$CI->lang->line($months > 1 ? 'date_months' : 'date_month');
}
$seconds -= $months * 2629743;
@@ -208,7 +202,7 @@ if ( ! function_exists('timespan'))
{
if ($weeks > 0)
{
- $str[] = $weeks.' '.$CI->lang->line((($weeks > 1) ? 'date_weeks' : 'date_week'));
+ $str[] = $weeks.' '.$CI->lang->line($weeks > 1 ? 'date_weeks' : 'date_week');
}
$seconds -= $weeks * 604800;
@@ -220,7 +214,7 @@ if ( ! function_exists('timespan'))
{
if ($days > 0)
{
- $str[] = $days.' '.$CI->lang->line((($days > 1) ? 'date_days' : 'date_day'));
+ $str[] = $days.' '.$CI->lang->line($days > 1 ? 'date_days' : 'date_day');
}
$seconds -= $days * 86400;
@@ -232,7 +226,7 @@ if ( ! function_exists('timespan'))
{
if ($hours > 0)
{
- $str[] = $hours.' '.$CI->lang->line((($hours > 1) ? 'date_hours' : 'date_hour'));
+ $str[] = $hours.' '.$CI->lang->line($hours > 1 ? 'date_hours' : 'date_hour');
}
$seconds -= $hours * 3600;
@@ -244,7 +238,7 @@ if ( ! function_exists('timespan'))
{
if ($minutes > 0)
{
- $str[] = $minutes.' '.$CI->lang->line((($minutes > 1) ? 'date_minutes' : 'date_minute'));
+ $str[] = $minutes.' '.$CI->lang->line($minutes > 1 ? 'date_minutes' : 'date_minute');
}
$seconds -= $minutes * 60;
@@ -252,7 +246,7 @@ if ( ! function_exists('timespan'))
if (count($str) === 0)
{
- $str[] = $seconds.' '.$CI->lang->line((($seconds > 1) ? 'date_seconds' : 'date_second'));
+ $str[] = $seconds.' '.$CI->lang->line($seconds > 1 ? 'date_seconds' : 'date_second');
}
return implode(', ', $str);
@@ -261,33 +255,37 @@ if ( ! function_exists('timespan'))
// ------------------------------------------------------------------------
-/**
- * Number of days in a month
- *
- * Takes a month/year as input and returns the number of days
- * for the given month/year. Takes leap years into consideration.
- *
- * @param int a numeric month
- * @param int a numeric year
- * @return int
- */
if ( ! function_exists('days_in_month'))
{
+ /**
+ * Number of days in a month
+ *
+ * Takes a month/year as input and returns the number of days
+ * for the given month/year. Takes leap years into consideration.
+ *
+ * @param int a numeric month
+ * @param int a numeric year
+ * @return int
+ */
function days_in_month($month = 0, $year = '')
{
if ($month < 1 OR $month > 12)
{
return 0;
}
-
- if ( ! is_numeric($year) OR strlen($year) != 4)
+ elseif ( ! is_numeric($year) OR strlen($year) !== 4)
{
$year = date('Y');
}
+ if ($year >= 1970)
+ {
+ return (int) date('t', mktime(12, 0, 0, $month, 1, $year));
+ }
+
if ($month == 2)
{
- if ($year % 400 == 0 OR ($year % 4 == 0 && $year % 100 != 0))
+ if ($year % 400 === 0 OR ($year % 4 === 0 && $year % 100 !== 0))
{
return 29;
}
@@ -300,85 +298,78 @@ if ( ! function_exists('days_in_month'))
// ------------------------------------------------------------------------
-/**
- * Converts a local Unix timestamp to GMT
- *
- * @param int Unix timestamp
- * @return int
- */
if ( ! function_exists('local_to_gmt'))
{
+ /**
+ * Converts a local Unix timestamp to GMT
+ *
+ * @param int Unix timestamp
+ * @return int
+ */
function local_to_gmt($time = '')
{
- if ($time == '')
+ if ($time === '')
{
$time = time();
}
return mktime(
- gmdate("H", $time),
- gmdate("i", $time),
- gmdate("s", $time),
- gmdate("m", $time),
- gmdate("d", $time),
- gmdate("Y", $time)
+ gmdate('G', $time),
+ gmdate('i', $time),
+ gmdate('s', $time),
+ gmdate('n', $time),
+ gmdate('j', $time),
+ gmdate('Y', $time)
);
}
}
// ------------------------------------------------------------------------
-/**
- * Converts GMT time to a localized value
- *
- * Takes a Unix timestamp (in GMT) as input, and returns
- * at the local value based on the timezone and DST setting
- * submitted
- *
- * @param int Unix timestamp
- * @param string timezone
- * @param bool whether DST is active
- * @return int
- */
if ( ! function_exists('gmt_to_local'))
{
+ /**
+ * Converts GMT time to a localized value
+ *
+ * Takes a Unix timestamp (in GMT) as input, and returns
+ * at the local value based on the timezone and DST setting
+ * submitted
+ *
+ * @param int Unix timestamp
+ * @param string timezone
+ * @param bool whether DST is active
+ * @return int
+ */
function gmt_to_local($time = '', $timezone = 'UTC', $dst = FALSE)
{
- if ($time == '')
+ if ($time === '')
{
return now();
}
$time += timezones($timezone) * 3600;
- if ($dst == TRUE)
- {
- $time += 3600;
- }
-
- return $time;
+ return ($dst === TRUE) ? $time + 3600 : $time;
}
}
// ------------------------------------------------------------------------
-/**
- * Converts a MySQL Timestamp to Unix
- *
- * @param int Unix timestamp
- * @return int
- */
if ( ! function_exists('mysql_to_unix'))
{
+ /**
+ * Converts a MySQL Timestamp to Unix
+ *
+ * @param int MySQL timestamp YYYY-MM-DD HH:MM:SS
+ * @return int Unix timstamp
+ */
function mysql_to_unix($time = '')
{
// We'll remove certain characters for backward compatibility
// since the formatting changed with MySQL 4.1
// YYYY-MM-DD HH:MM:SS
- $time = str_replace('-', '', $time);
- $time = str_replace(':', '', $time);
- $time = str_replace(' ', '', $time);
+ $time = str_replace(array('-', ':', ' '), '', $time);
// YYYYMMDDHHMMSS
return mktime(
@@ -394,23 +385,23 @@ if ( ! function_exists('mysql_to_unix'))
// ------------------------------------------------------------------------
-/**
- * Unix to "Human"
- *
- * Formats Unix timestamp to the following prototype: 2006-08-21 11:35 PM
- *
- * @param int Unix timestamp
- * @param bool whether to show seconds
- * @param string format: us or euro
- * @return string
- */
if ( ! function_exists('unix_to_human'))
{
+ /**
+ * Unix to "Human"
+ *
+ * Formats Unix timestamp to the following prototype: 2006-08-21 11:35 PM
+ *
+ * @param int Unix timestamp
+ * @param bool whether to show seconds
+ * @param string format: us or euro
+ * @return string
+ */
function unix_to_human($time = '', $seconds = FALSE, $fmt = 'us')
{
- $r = date('Y', $time).'-'.date('m', $time).'-'.date('d', $time).' ';
+ $r = date('Y', $time).'-'.date('m', $time).'-'.date('d', $time).' ';
- if ($fmt == 'us')
+ if ($fmt === 'us')
{
$r .= date('h', $time).':'.date('i', $time);
}
@@ -424,9 +415,9 @@ if ( ! function_exists('unix_to_human'))
$r .= ':'.date('s', $time);
}
- if ($fmt == 'us')
+ if ($fmt === 'us')
{
- $r .= ' '.date('A', $time);
+ return $r.' '.date('A', $time);
}
return $r;
@@ -435,71 +426,45 @@ if ( ! function_exists('unix_to_human'))
// ------------------------------------------------------------------------
-/**
- * Convert "human" date to GMT
- *
- * Reverses the above process
- *
- * @param string format: us or euro
- * @return int
- */
if ( ! function_exists('human_to_unix'))
{
+ /**
+ * Convert "human" date to GMT
+ *
+ * Reverses the above process
+ *
+ * @param string format: us or euro
+ * @return int
+ */
function human_to_unix($datestr = '')
{
- if ($datestr == '')
+ if ($datestr === '')
{
return FALSE;
}
- $datestr = trim($datestr);
- $datestr = preg_replace("/\040+/", ' ', $datestr);
+ $datestr = preg_replace('/\040+/', ' ', trim($datestr));
- if ( ! preg_match('/^[0-9]{2,4}\-[0-9]{1,2}\-[0-9]{1,2}\s[0-9]{1,2}:[0-9]{1,2}(?::[0-9]{1,2})?(?:\s[AP]M)?$/i', $datestr))
+ if ( ! preg_match('/^(\d{2}|\d{4})\-[0-9]{1,2}\-[0-9]{1,2}\s[0-9]{1,2}:[0-9]{1,2}(?::[0-9]{1,2})?(?:\s[AP]M)?$/i', $datestr))
{
return FALSE;
}
- $split = explode(' ', $datestr);
-
- $ex = explode("-", $split['0']);
-
- $year = (strlen($ex['0']) == 2) ? '20'.$ex['0'] : $ex['0'];
- $month = (strlen($ex['1']) == 1) ? '0'.$ex['1'] : $ex['1'];
- $day = (strlen($ex['2']) == 1) ? '0'.$ex['2'] : $ex['2'];
-
- $ex = explode(":", $split['1']);
+ sscanf($datestr, '%d-%d-%d %s %s', $year, $month, $day, $time, $ampm);
+ sscanf($time, '%d:%d:%d', $hour, $min, $sec);
+ isset($sec) OR $sec = 0;
- $hour = (strlen($ex['0']) == 1) ? '0'.$ex['0'] : $ex['0'];
- $min = (strlen($ex['1']) == 1) ? '0'.$ex['1'] : $ex['1'];
-
- if (isset($ex['2']) && preg_match('/[0-9]{1,2}/', $ex['2']))
- {
- $sec = (strlen($ex['2']) == 1) ? '0'.$ex['2'] : $ex['2'];
- }
- else
+ if (isset($ampm))
{
- // Unless specified, seconds get set to zero.
- $sec = '00';
- }
-
- if (isset($split['2']))
- {
- $ampm = strtolower($split['2']);
-
- if (substr($ampm, 0, 1) === 'p' && $hour < 12)
- {
- $hour = $hour + 12;
- }
+ $ampm = strtolower($ampm);
- if (substr($ampm, 0, 1) === 'a' && $hour == 12)
+ if ($ampm[0] === 'p' && $hour < 12)
{
- $hour = '00';
+ $hour += 12;
}
-
- if (strlen($hour) == 1)
+ elseif ($ampm[0] === 'a' && $hour === 12)
{
- $hour = '0'.$hour;
+ $hour = 0;
}
}
@@ -509,27 +474,31 @@ if ( ! function_exists('human_to_unix'))
// ------------------------------------------------------------------------
-/**
- * Turns many "reasonably-date-like" strings into something
- * that is actually useful. This only works for dates after unix epoch.
- *
- * @param string The terribly formatted date-like string
- * @param string Date format to return (same as php date function)
- * @return string
- */
if ( ! function_exists('nice_date'))
{
+ /**
+ * Turns many "reasonably-date-like" strings into something
+ * that is actually useful. This only works for dates after unix epoch.
+ *
+ * @param string The terribly formatted date-like string
+ * @param string Date format to return (same as php date function)
+ * @return string
+ */
function nice_date($bad_date = '', $format = FALSE)
{
if (empty($bad_date))
{
return 'Unknown';
}
+ elseif (empty($format))
+ {
+ $format = 'U';
+ }
// Date like: YYYYMM
- if (preg_match('/^\d{6}$/', $bad_date))
+ if (preg_match('/^\d{6}$/i', $bad_date))
{
- if (in_array(substr($bad_date, 0, 2),array('19', '20')))
+ if (in_array(substr($bad_date, 0, 2), array('19', '20')))
{
$year = substr($bad_date, 0, 4);
$month = substr($bad_date, 4, 2);
@@ -540,32 +509,27 @@ if ( ! function_exists('nice_date'))
$year = substr($bad_date, 2, 4);
}
- return date($format, strtotime($year . '-' . $month . '-01'));
+ return date($format, strtotime($year.'-'.$month.'-01'));
}
// Date Like: YYYYMMDD
- if (preg_match('/^\d{8}$/',$bad_date))
+ if (preg_match('/^(\d{2})\d{2}(\d{4})$/i', $bad_date, $matches))
{
- $month = substr($bad_date, 0, 2);
- $day = substr($bad_date, 2, 2);
- $year = substr($bad_date, 4, 4);
-
- return date($format, strtotime($month . '/01/' . $year));
+ return date($format, strtotime($matches[1].'/01/'.$matches[2]));
}
// Date Like: MM-DD-YYYY __or__ M-D-YYYY (or anything in between)
- if (preg_match('/^\d{1,2}-\d{1,2}-\d{4}$/',$bad_date))
+ if (preg_match('/^(\d{1,2})-(\d{1,2})-(\d{4})$/i', $bad_date, $matches))
{
- list($m, $d, $y) = explode('-', $bad_date);
- return date($format, strtotime("{$y}-{$m}-{$d}"));
+ return date($format, strtotime($matches[3].'-'.$matches[1].'-'.$matches[2]));
}
// Any other kind of string, when converted into UNIX time,
// produces "0 seconds after epoc..." is probably bad...
// return "Invalid Date".
- if (date('U', strtotime($bad_date)) == '0')
+ if (date('U', strtotime($bad_date)) === '0')
{
- return "Invalid Date";
+ return 'Invalid Date';
}
// It's probably a valid-ish date format already
@@ -575,59 +539,58 @@ if ( ! function_exists('nice_date'))
// ------------------------------------------------------------------------
-/**
- * Timezone Menu
- *
- * Generates a drop-down menu of timezones.
- *
- * @param string timezone
- * @param string classname
- * @param string menu name
- * @return string
- */
if ( ! function_exists('timezone_menu'))
{
- function timezone_menu($default = 'UTC', $class = "", $name = 'timezones')
+ /**
+ * Timezone Menu
+ *
+ * Generates a drop-down menu of timezones.
+ *
+ * @param string timezone
+ * @param string classname
+ * @param string menu name
+ * @param mixed attributes
+ * @return string
+ */
+ function timezone_menu($default = 'UTC', $class = '', $name = 'timezones', $attributes = '')
{
$CI =& get_instance();
$CI->lang->load('date');
- $default = ($default == 'GMT') ? 'UTC' : $default;
+ $default = ($default === 'GMT') ? 'UTC' : $default;
$menu = '<select name="'.$name.'"';
- if ($class != '')
+ if ($class !== '')
{
$menu .= ' class="'.$class.'"';
}
- $menu .= ">\n";
+ $menu .= _stringify_attributes($attributes).">\n";
foreach (timezones() as $key => $val)
{
- $selected = ($default == $key) ? " selected='selected'" : '';
- $menu .= "<option value='{$key}'{$selected}>".$CI->lang->line($key)."</option>\n";
+ $selected = ($default === $key) ? ' selected="selected"' : '';
+ $menu .= '<option value="'.$key.'"'.$selected.'>'.$CI->lang->line($key)."</option>\n";
}
- $menu .= "</select>";
-
- return $menu;
+ return $menu.'</select>';
}
}
// ------------------------------------------------------------------------
-/**
- * Timezones
- *
- * Returns an array of timezones. This is a helper function
- * for various other ones in this library
- *
- * @param string timezone
- * @return string
- */
if ( ! function_exists('timezones'))
{
+ /**
+ * Timezones
+ *
+ * Returns an array of timezones. This is a helper function
+ * for various other ones in this library
+ *
+ * @param string timezone
+ * @return string
+ */
function timezones($tz = '')
{
// Note: Don't change the order of these even though
@@ -676,16 +639,145 @@ if ( ! function_exists('timezones'))
'UP14' => +14
);
- if ($tz == '')
+ if ($tz === '')
{
return $zones;
}
- $tz = ($tz == 'GMT') ? 'UTC' : $tz;
-
return isset($zones[$tz]) ? $zones[$tz] : 0;
}
}
+// ------------------------------------------------------------------------
+
+if ( ! function_exists('date_range'))
+{
+ /**
+ * Date range
+ *
+ * Returns a list of dates within a specified period.
+ *
+ * @param int unix_start UNIX timestamp of period start date
+ * @param int unix_end|days UNIX timestamp of period end date
+ * or interval in days.
+ * @param mixed is_unix Specifies whether the second parameter
+ * is a UNIX timestamp or a day interval
+ * - TRUE or 'unix' for a timestamp
+ * - FALSE or 'days' for an interval
+ * @param string date_format Output date format, same as in date()
+ * @return array
+ */
+ function date_range($unix_start = '', $mixed = '', $is_unix = TRUE, $format = 'Y-m-d')
+ {
+ if ($unix_start == '' OR $mixed == '' OR $format == '')
+ {
+ return FALSE;
+ }
+
+ $is_unix = ! ( ! $is_unix OR $is_unix === 'days');
+
+ // Validate input and try strtotime() on invalid timestamps/intervals, just in case
+ if ( ( ! ctype_digit((string) $unix_start) && ($unix_start = @strtotime($unix_time)) === FALSE)
+ OR ( ! ctype_digit((string) $mixed) && ($is_unix === FALSE OR ($mixed = @strtotime($mixed)) === FALSE))
+ OR ($is_unix === TRUE && $mixed < $unix_start))
+ {
+ return FALSE;
+ }
+
+ if ($is_unix && ($unix_start == $mixed OR date($format, $unix_start) === date($format, $mixed)))
+ {
+ return array($start_date);
+ }
+
+ $range = array();
+
+ /* NOTE: Even though the DateTime object has many useful features, it appears that
+ * it doesn't always handle properly timezones, when timestamps are passed
+ * directly to its constructor. Neither of the following gave proper results:
+ *
+ * new DateTime('<timestamp>')
+ * new DateTime('<timestamp>', '<timezone>')
+ *
+ * --- available in PHP 5.3:
+ *
+ * DateTime::createFromFormat('<format>', '<timestamp>')
+ * DateTime::createFromFormat('<format>', '<timestamp>', '<timezone')
+ *
+ * ... so we'll have to set the timestamp after the object is instantiated.
+ * Furthermore, in PHP 5.3 we can use DateTime::setTimestamp() to do that and
+ * given that we have UNIX timestamps - we should use it.
+ */
+ $from = new DateTime();
+
+ if (is_php('5.3'))
+ {
+ $from->setTimestamp($unix_start);
+ if ($is_unix)
+ {
+ $arg = new DateTime();
+ $arg->setTimestamp($mixed);
+ }
+ else
+ {
+ $arg = (int) $mixed;
+ }
+
+ $period = new DatePeriod($from, new DateInterval('P1D'), $arg);
+ foreach ($period as $date)
+ {
+ $range[] = $date->format($format);
+ }
+
+ /* If a period end date was passed to the DatePeriod constructor, it might not
+ * be in our results. Not sure if this is a bug or it's just possible because
+ * the end date might actually be less than 24 hours away from the previously
+ * generated DateTime object, but either way - we have to append it manually.
+ */
+ if ( ! is_int($arg) && $range[count($range) - 1] !== $arg->format($format))
+ {
+ $range[] = $arg->format($format);
+ }
+
+ return $range;
+ }
+
+ $from->setDate(date('Y', $unix_start), date('n', $unix_start), date('j', $unix_start));
+ $from->setTime(date('G', $unix_start), date('i', $unix_start), date('s', $unix_start));
+ if ($is_unix)
+ {
+ $arg = new DateTime();
+ $arg->setDate(date('Y', $mixed), date('n', $mixed), date('j', $mixed));
+ $arg->setTime(date('G', $mixed), date('i', $mixed), date('s', $mixed));
+ }
+ else
+ {
+ $arg = (int) $mixed;
+ }
+ $range[] = $from->format($format);
+
+ if (is_int($arg)) // Day intervals
+ {
+ do
+ {
+ $from->modify('+1 day');
+ $range[] = $from->format($format);
+ }
+ while (--$arg > 0);
+ }
+ else // end date UNIX timestamp
+ {
+ for ($from->modify('+1 day'), $end_check = $arg->format('Ymd'); $from->format('Ymd') < $end_check; $from->modify('+1 day'))
+ {
+ $range[] = $from->format($format);
+ }
+
+ // Our loop only appended dates prior to our end date
+ $range[] = $arg->format($format);
+ }
+
+ return $range;
+ }
+}
+
/* End of file date_helper.php */
/* Location: ./system/helpers/date_helper.php */ \ No newline at end of file
diff --git a/system/helpers/directory_helper.php b/system/helpers/directory_helper.php
index 4044ace11..49dcfc8a9 100644
--- a/system/helpers/directory_helper.php
+++ b/system/helpers/directory_helper.php
@@ -1,4 +1,4 @@
-<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');
+<?php
/**
* CodeIgniter
*
@@ -24,6 +24,7 @@
* @since Version 1.0
* @filesource
*/
+defined('BASEPATH') OR exit('No direct script access allowed');
/**
* CodeIgniter Directory Helpers
@@ -37,19 +38,21 @@
// ------------------------------------------------------------------------
-/**
- * Create a Directory Map
- *
- * Reads the specified directory and builds an array
- * representation of it. Sub-folders contained with the
- * directory will be mapped as well.
- *
- * @param string path to source
- * @param int depth of directories to traverse (0 = fully recursive, 1 = current dir, etc)
- * @return array
- */
if ( ! function_exists('directory_map'))
{
+ /**
+ * Create a Directory Map
+ *
+ * Reads the specified directory and builds an array
+ * representation of it. Sub-folders contained with the
+ * directory will be mapped as well.
+ *
+ * @param string $source_dir Path to source
+ * @param int $directory_depth Depth of directories to traverse
+ * (0 = fully recursive, 1 = current dir, etc)
+ * @param bool $hidden Whether to show hidden files
+ * @return array
+ */
function directory_map($source_dir, $directory_depth = 0, $hidden = FALSE)
{
if ($fp = @opendir($source_dir))
@@ -61,14 +64,16 @@ if ( ! function_exists('directory_map'))
while (FALSE !== ($file = readdir($fp)))
{
// Remove '.', '..', and hidden files [optional]
- if ( ! trim($file, '.') OR ($hidden == FALSE && $file[0] === '.'))
+ if ($file === '.' OR $file === '..' OR ($hidden === FALSE && $file[0] === '.'))
{
continue;
}
+ @is_dir($source_dir.$file) AND $file .= DIRECTORY_SEPARATOR;
+
if (($directory_depth < 1 OR $new_depth > 0) && @is_dir($source_dir.$file))
{
- $filedata[$file] = directory_map($source_dir.$file.DIRECTORY_SEPARATOR, $new_depth, $hidden);
+ $filedata[$file] = directory_map($source_dir.$file, $new_depth, $hidden);
}
else
{
diff --git a/system/helpers/download_helper.php b/system/helpers/download_helper.php
index 19192a147..31652d53e 100644
--- a/system/helpers/download_helper.php
+++ b/system/helpers/download_helper.php
@@ -1,4 +1,4 @@
-<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');
+<?php
/**
* CodeIgniter
*
@@ -24,6 +24,7 @@
* @since Version 1.0
* @filesource
*/
+defined('BASEPATH') OR exit('No direct script access allowed');
/**
* CodeIgniter Download Helpers
@@ -37,24 +38,41 @@
// ------------------------------------------------------------------------
-/**
- * Force Download
- *
- * Generates headers that force a download to happen
- *
- * @param string filename
- * @param mixed the data to be downloaded
- * @param bool wether to try and send the actual file MIME type
- * @return void
- */
if ( ! function_exists('force_download'))
{
+ /**
+ * Force Download
+ *
+ * Generates headers that force a download to happen
+ *
+ * @param string filename
+ * @param mixed the data to be downloaded
+ * @param bool whether to try and send the actual file MIME type
+ * @return void
+ */
function force_download($filename = '', $data = '', $set_mime = FALSE)
{
- if ($filename == '' OR $data == '')
+ if ($filename === '' OR $data === '')
{
return FALSE;
}
+ elseif ($data === NULL)
+ {
+ if (@is_file($filename) && @file_exists($filename) && ($filesize = @filesize($filename)) !== FALSE)
+ {
+ $filepath = $filename;
+ $filename = explode('/', str_replace(DIRECTORY_SEPARATOR, '/', $filename));
+ $filename = end($filename);
+ }
+ else
+ {
+ return FALSE;
+ }
+ }
+ else
+ {
+ $filesize = strlen($data);
+ }
// Set the default MIME type to send
$mime = 'application/octet-stream';
@@ -73,14 +91,7 @@ if ( ! function_exists('force_download'))
}
// Load the mime types
- if (defined('ENVIRONMENT') && is_file(APPPATH.'config/'.ENVIRONMENT.'/mimes.php'))
- {
- include(APPPATH.'config/'.ENVIRONMENT.'/mimes.php');
- }
- elseif (is_file(APPPATH.'config/mimes.php'))
- {
- include(APPPATH.'config/mimes.php');
- }
+ $mimes =& get_mimes();
// Only change the default MIME if we can find one
if (isset($mimes[$extension]))
@@ -101,25 +112,46 @@ if ( ! function_exists('force_download'))
$filename = implode('.', $x);
}
+ if ($data === NULL && ($fp = @fopen($filepath, 'rb')) === FALSE)
+ {
+ return FALSE;
+ }
+
+ // Clean output buffer
+ if (ob_get_level() !== 0 && @ob_end_clean() === FALSE)
+ {
+ ob_clean();
+ }
+
// Generate the server headers
header('Content-Type: '.$mime);
header('Content-Disposition: attachment; filename="'.$filename.'"');
header('Expires: 0');
header('Content-Transfer-Encoding: binary');
- header('Content-Length: '.strlen($data));
+ header('Content-Length: '.$filesize);
// Internet Explorer-specific headers
if (isset($_SERVER['HTTP_USER_AGENT']) && strpos($_SERVER['HTTP_USER_AGENT'], 'MSIE') !== FALSE)
{
- header('Cache-Control: must-revalidate, post-check=0, pre-check=0');
- header('Pragma: public');
+ header('Cache-Control: no-cache, no-store, must-revalidate');
}
- else
+
+ header('Pragma: no-cache');
+
+ // If we have raw data - just dump it
+ if ($data !== NULL)
+ {
+ exit($data);
+ }
+
+ // Flush 1MB chunks of data
+ while ( ! feof($fp) && ($data = fread($fp, 1048576)) !== FALSE)
{
- header('Pragma: no-cache');
+ echo $data;
}
- exit($data);
+ fclose($fp);
+ exit;
}
}
diff --git a/system/helpers/email_helper.php b/system/helpers/email_helper.php
index 497625c10..dfb166a5a 100644
--- a/system/helpers/email_helper.php
+++ b/system/helpers/email_helper.php
@@ -1,4 +1,4 @@
-<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');
+<?php
/**
* CodeIgniter
*
@@ -24,6 +24,7 @@
* @since Version 1.0
* @filesource
*/
+defined('BASEPATH') OR exit('No direct script access allowed');
/**
* CodeIgniter Email Helpers
@@ -37,33 +38,35 @@
// ------------------------------------------------------------------------
-/**
- * Validate email address
- *
- * @param string
- * @return bool
- */
if ( ! function_exists('valid_email'))
{
- function valid_email($address)
+ /**
+ * Validate email address
+ *
+ * @deprecated 3.0.0 Use PHP's filter_var() instead
+ * @param string $email
+ * @return bool
+ */
+ function valid_email($email)
{
- return (bool) preg_match('/^([a-z0-9\+_\-]+)(\.[a-z0-9\+_\-]+)*@([a-z0-9\-]+\.)+[a-z]{2,6}$/ix', $address);
+ return (bool) filter_var($email, FILTER_VALIDATE_EMAIL);
}
}
// ------------------------------------------------------------------------
-/**
- * Send an email
- *
- * @param string
- * @param string
- * @param string
- * @return bool
- */
if ( ! function_exists('send_email'))
{
- function send_email($recipient, $subject = 'Test email', $message = 'Hello World')
+ /**
+ * Send an email
+ *
+ * @deprecated 3.0.0 Use PHP's mail() instead
+ * @param string $recipient
+ * @param string $subject
+ * @param string $message
+ * @return bool
+ */
+ function send_email($recipient, $subject, $message)
{
return mail($recipient, $subject, $message);
}
diff --git a/system/helpers/file_helper.php b/system/helpers/file_helper.php
index 3a373efd3..aebb6e47a 100644
--- a/system/helpers/file_helper.php
+++ b/system/helpers/file_helper.php
@@ -1,4 +1,4 @@
-<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');
+<?php
/**
* CodeIgniter
*
@@ -24,6 +24,7 @@
* @since Version 1.0
* @filesource
*/
+defined('BASEPATH') OR exit('No direct script access allowed');
/**
* CodeIgniter File Helpers
@@ -32,68 +33,45 @@
* @subpackage Helpers
* @category Helpers
* @author EllisLab Dev Team
- * @link http://codeigniter.com/user_guide/helpers/file_helpers.html
+ * @link http://codeigniter.com/user_guide/helpers/file_helper.html
*/
// ------------------------------------------------------------------------
-/**
- * Read File
- *
- * Opens the file specfied in the path and returns it as a string.
- *
- * @param string path to file
- * @return string
- */
if ( ! function_exists('read_file'))
{
+ /**
+ * Read File
+ *
+ * Opens the file specfied in the path and returns it as a string.
+ *
+ * @todo Remove in version 3.1+.
+ * @deprecated 3.0.0 It is now just an alias for PHP's native file_get_contents().
+ * @param string $file Path to file
+ * @return string File contents
+ */
function read_file($file)
{
- if ( ! file_exists($file))
- {
- return FALSE;
- }
-
- if (function_exists('file_get_contents'))
- {
- return file_get_contents($file);
- }
-
- if ( ! $fp = @fopen($file, FOPEN_READ))
- {
- return FALSE;
- }
-
- flock($fp, LOCK_SH);
-
- $data = '';
- if (filesize($file) > 0)
- {
- $data =& fread($fp, filesize($file));
- }
-
- flock($fp, LOCK_UN);
- fclose($fp);
-
- return $data;
+ return @file_get_contents($file);
}
}
// ------------------------------------------------------------------------
-/**
- * Write File
- *
- * Writes data to the file specified in the path.
- * Creates a new file if non-existent.
- *
- * @param string path to file
- * @param string file data
- * @return bool
- */
if ( ! function_exists('write_file'))
{
- function write_file($path, $data, $mode = FOPEN_WRITE_CREATE_DESTRUCTIVE)
+ /**
+ * Write File
+ *
+ * Writes data to the file specified in the path.
+ * Creates a new file if non-existent.
+ *
+ * @param string $path File path
+ * @param string $data Data to write
+ * @param string $mode fopen() mode (default: 'wb')
+ * @return bool
+ */
+ function write_file($path, $data, $mode = 'wb')
{
if ( ! $fp = @fopen($path, $mode))
{
@@ -111,26 +89,26 @@ if ( ! function_exists('write_file'))
// ------------------------------------------------------------------------
-/**
- * Delete Files
- *
- * Deletes all files contained in the supplied directory path.
- * Files must be writable or owned by the system in order to be deleted.
- * If the second parameter is set to TRUE, any directories contained
- * within the supplied base directory will be nuked as well.
- *
- * @param string path to file
- * @param bool whether to delete any directories found in the path
- * @param int
- * @param bool whether to skip deleting .htaccess and index page files
- * @return bool
- */
if ( ! function_exists('delete_files'))
{
- function delete_files($path, $del_dir = FALSE, $level = 0, $htdocs = FALSE)
+ /**
+ * Delete Files
+ *
+ * Deletes all files contained in the supplied directory path.
+ * Files must be writable or owned by the system in order to be deleted.
+ * If the second parameter is set to TRUE, any directories contained
+ * within the supplied base directory will be nuked as well.
+ *
+ * @param string $path File path
+ * @param bool $del_dir Whether to delete any directories found in the path
+ * @param bool $htdocs Whether to skip deleting .htaccess and index page files
+ * @param int $_level Current directory depth level (default: 0; internal use only)
+ * @return bool
+ */
+ function delete_files($path, $del_dir = FALSE, $htdocs = FALSE, $_level = 0)
{
// Trim the trailing slash
- $path = rtrim($path, DIRECTORY_SEPARATOR);
+ $path = rtrim($path, '/\\');
if ( ! $current_dir = @opendir($path))
{
@@ -143,9 +121,9 @@ if ( ! function_exists('delete_files'))
{
if (is_dir($path.DIRECTORY_SEPARATOR.$filename) && $filename[0] !== '.')
{
- delete_files($path.DIRECTORY_SEPARATOR.$filename, $del_dir, $level + 1, $htdocs);
+ delete_files($path.DIRECTORY_SEPARATOR.$filename, $del_dir, $htdocs, $_level + 1);
}
- elseif ($htdocs === TRUE && ! preg_match('/^(\.htaccess|index\.(html|htm|php))$/', $filename))
+ elseif ($htdocs !== TRUE OR ! preg_match('/^(\.htaccess|index\.(html|htm|php)|web\.config)$/i', $filename))
{
@unlink($path.DIRECTORY_SEPARATOR.$filename);
}
@@ -153,7 +131,7 @@ if ( ! function_exists('delete_files'))
}
@closedir($current_dir);
- if ($del_dir == TRUE && $level > 0)
+ if ($del_dir === TRUE && $_level > 0)
{
return @rmdir($path);
}
@@ -164,19 +142,19 @@ if ( ! function_exists('delete_files'))
// ------------------------------------------------------------------------
-/**
- * Get Filenames
- *
- * Reads the specified directory and builds an array containing the filenames.
- * Any sub-folders contained within the specified path are read as well.
- *
- * @param string path to source
- * @param bool whether to include the path as part of the filename
- * @param bool internal variable to determine recursion status - do not use in calls
- * @return array
- */
if ( ! function_exists('get_filenames'))
{
+ /**
+ * Get Filenames
+ *
+ * Reads the specified directory and builds an array containing the filenames.
+ * Any sub-folders contained within the specified path are read as well.
+ *
+ * @param string path to source
+ * @param bool whether to include the path as part of the filename
+ * @param bool internal variable to determine recursion status - do not use in calls
+ * @return array
+ */
function get_filenames($source_dir, $include_path = FALSE, $_recursion = FALSE)
{
static $_filedata = array();
@@ -198,7 +176,7 @@ if ( ! function_exists('get_filenames'))
}
elseif ($file[0] !== '.')
{
- $_filedata[] = ($include_path == TRUE) ? $source_dir.$file : $file;
+ $_filedata[] = ($include_path === TRUE) ? $source_dir.$file : $file;
}
}
closedir($fp);
@@ -212,21 +190,21 @@ if ( ! function_exists('get_filenames'))
// --------------------------------------------------------------------
-/**
- * Get Directory File Information
- *
- * Reads the specified directory and builds an array containing the filenames,
- * filesize, dates, and permissions
- *
- * Any sub-folders contained within the specified path are read as well.
- *
- * @param string path to source
- * @param bool Look only at the top level directory specified?
- * @param bool internal variable to determine recursion status - do not use in calls
- * @return array
- */
if ( ! function_exists('get_dir_file_info'))
{
+ /**
+ * Get Directory File Information
+ *
+ * Reads the specified directory and builds an array containing the filenames,
+ * filesize, dates, and permissions
+ *
+ * Any sub-folders contained within the specified path are read as well.
+ *
+ * @param string path to source
+ * @param bool Look only at the top level directory specified?
+ * @param bool internal variable to determine recursion status - do not use in calls
+ * @return array
+ */
function get_dir_file_info($source_dir, $top_level_only = TRUE, $_recursion = FALSE)
{
static $_filedata = array();
@@ -265,20 +243,20 @@ if ( ! function_exists('get_dir_file_info'))
// --------------------------------------------------------------------
-/**
-* Get File Info
-*
-* Given a file and path, returns the name, path, size, date modified
-* Second parameter allows you to explicitly declare what information you want returned
-* Options are: name, server_path, size, date, readable, writable, executable, fileperms
-* Returns FALSE if the file cannot be found.
-*
-* @param string path to file
-* @param mixed array or comma separated string of information returned
-* @return array
-*/
if ( ! function_exists('get_file_info'))
{
+ /**
+ * Get File Info
+ *
+ * Given a file and path, returns the name, path, size, date modified
+ * Second parameter allows you to explicitly declare what information you want returned
+ * Options are: name, server_path, size, date, readable, writable, executable, fileperms
+ * Returns FALSE if the file cannot be found.
+ *
+ * @param string path to file
+ * @param mixed array or comma separated string of information returned
+ * @return array
+ */
function get_file_info($file, $returned_values = array('name', 'server_path', 'size', 'date'))
{
@@ -330,54 +308,41 @@ if ( ! function_exists('get_file_info'))
// --------------------------------------------------------------------
-/**
- * Get Mime by Extension
- *
- * Translates a file extension into a mime type based on config/mimes.php.
- * Returns FALSE if it can't determine the type, or open the mime config file
- *
- * Note: this is NOT an accurate way of determining file mime types, and is here strictly as a convenience
- * It should NOT be trusted, and should certainly NOT be used for security
- *
- * @param string path to file
- * @return mixed
- */
if ( ! function_exists('get_mime_by_extension'))
{
- function get_mime_by_extension($file)
+ /**
+ * Get Mime by Extension
+ *
+ * Translates a file extension into a mime type based on config/mimes.php.
+ * Returns FALSE if it can't determine the type, or open the mime config file
+ *
+ * Note: this is NOT an accurate way of determining file mime types, and is here strictly as a convenience
+ * It should NOT be trusted, and should certainly NOT be used for security
+ *
+ * @param string $filename File name
+ * @return string
+ */
+ function get_mime_by_extension($filename)
{
- $extension = strtolower(substr(strrchr($file, '.'), 1));
+ $extension = strtolower(substr(strrchr($filename, '.'), 1));
- global $mimes;
+ static $mimes;
if ( ! is_array($mimes))
{
- if (defined('ENVIRONMENT') && is_file(APPPATH.'config/'.ENVIRONMENT.'/mimes.php'))
- {
- include(APPPATH.'config/'.ENVIRONMENT.'/mimes.php');
- }
- elseif (is_file(APPPATH.'config/mimes.php'))
- {
- include(APPPATH.'config/mimes.php');
- }
+ $mimes =& get_mimes();
- if ( ! is_array($mimes))
+ if (empty($mimes))
{
return FALSE;
}
}
- if (array_key_exists($extension, $mimes))
+ if (isset($mimes[$extension]))
{
- if (is_array($mimes[$extension]))
- {
- // Multiple mime types, just give the first one
- return current($mimes[$extension]);
- }
- else
- {
- return $mimes[$extension];
- }
+ return is_array($mimes[$extension])
+ ? current($mimes[$extension]) // Multiple mime types, just give the first one
+ : $mimes[$extension];
}
return FALSE;
@@ -386,17 +351,17 @@ if ( ! function_exists('get_mime_by_extension'))
// --------------------------------------------------------------------
-/**
- * Symbolic Permissions
- *
- * Takes a numeric value representing a file's permissions and returns
- * standard symbolic notation representing that value
- *
- * @param int
- * @return string
- */
if ( ! function_exists('symbolic_permissions'))
{
+ /**
+ * Symbolic Permissions
+ *
+ * Takes a numeric value representing a file's permissions and returns
+ * standard symbolic notation representing that value
+ *
+ * @param int $perms Permissions
+ * @return string
+ */
function symbolic_permissions($perms)
{
if (($perms & 0xC000) === 0xC000)
@@ -453,17 +418,17 @@ if ( ! function_exists('symbolic_permissions'))
// --------------------------------------------------------------------
-/**
- * Octal Permissions
- *
- * Takes a numeric value representing a file's permissions and returns
- * a three character string representing the file's octal permissions
- *
- * @param int
- * @return string
- */
if ( ! function_exists('octal_permissions'))
{
+ /**
+ * Octal Permissions
+ *
+ * Takes a numeric value representing a file's permissions and returns
+ * a three character string representing the file's octal permissions
+ *
+ * @param int $perms Permissions
+ * @return string
+ */
function octal_permissions($perms)
{
return substr(sprintf('%o', $perms), -3);
diff --git a/system/helpers/form_helper.php b/system/helpers/form_helper.php
index e5b487608..c7e6d4933 100644
--- a/system/helpers/form_helper.php
+++ b/system/helpers/form_helper.php
@@ -1,4 +1,4 @@
-<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');
+<?php
/**
* CodeIgniter
*
@@ -22,7 +22,9 @@
* @license http://opensource.org/licenses/OSL-3.0 Open Software License (OSL 3.0)
* @link http://codeigniter.com
* @since Version 1.0
+ * @filesource
*/
+defined('BASEPATH') OR exit('No direct script access allowed');
/**
* CodeIgniter Form Helpers
@@ -36,23 +38,23 @@
// ------------------------------------------------------------------------
-/**
- * Form Declaration
- *
- * Creates the opening portion of the form.
- *
- * @param string the URI segments of the form destination
- * @param array a key/value pair of attributes
- * @param array a key/value pair hidden data
- * @return string
- */
if ( ! function_exists('form_open'))
{
+ /**
+ * Form Declaration
+ *
+ * Creates the opening portion of the form.
+ *
+ * @param string the URI segments of the form destination
+ * @param array a key/value pair of attributes
+ * @param array a key/value pair hidden data
+ * @return string
+ */
function form_open($action = '', $attributes = '', $hidden = array())
{
$CI =& get_instance();
- if ($attributes == '')
+ if ($attributes === '')
{
$attributes = 'method="post"';
}
@@ -62,9 +64,11 @@ if ( ! function_exists('form_open'))
{
$action = $CI->config->site_url($action);
}
-
- // If no action is provided then set to the current url
- $action OR $action = $CI->config->site_url($CI->uri->uri_string());
+ elseif ( ! $action)
+ {
+ // If no action is provided then set to the current url
+ $action = $CI->config->site_url($CI->uri->uri_string());
+ }
$form = '<form action="'.$action.'"'._attributes_to_string($attributes, TRUE).">\n";
@@ -76,7 +80,7 @@ if ( ! function_exists('form_open'))
if (is_array($hidden) && count($hidden) > 0)
{
- $form .= sprintf('<div style="display:none;">%s</div>', form_hidden($hidden));
+ $form .= '<div style="display:none;">'.form_hidden($hidden).'</div>';
}
return $form;
@@ -85,18 +89,18 @@ if ( ! function_exists('form_open'))
// ------------------------------------------------------------------------
-/**
- * Form Declaration - Multipart type
- *
- * Creates the opening portion of the form, but with "multipart/form-data".
- *
- * @param string the URI segments of the form destination
- * @param array a key/value pair of attributes
- * @param array a key/value pair hidden data
- * @return string
- */
if ( ! function_exists('form_open_multipart'))
{
+ /**
+ * Form Declaration - Multipart type
+ *
+ * Creates the opening portion of the form, but with "multipart/form-data".
+ *
+ * @param string the URI segments of the form destination
+ * @param array a key/value pair of attributes
+ * @param array a key/value pair hidden data
+ * @return string
+ */
function form_open_multipart($action = '', $attributes = array(), $hidden = array())
{
if (is_string($attributes))
@@ -114,18 +118,19 @@ if ( ! function_exists('form_open_multipart'))
// ------------------------------------------------------------------------
-/**
- * Hidden Input Field
- *
- * Generates hidden fields. You can pass a simple key/value string or
- * an associative array with multiple values.
- *
- * @param mixed
- * @param string
- * @return string
- */
if ( ! function_exists('form_hidden'))
{
+ /**
+ * Hidden Input Field
+ *
+ * Generates hidden fields. You can pass a simple key/value string or
+ * an associative array with multiple values.
+ *
+ * @param mixed $name Field name
+ * @param string $value Field value
+ * @param bool $recursing
+ * @return string
+ */
function form_hidden($name, $value = '', $recursing = FALSE)
{
static $form;
@@ -146,7 +151,7 @@ if ( ! function_exists('form_hidden'))
if ( ! is_array($value))
{
- $form .= '<input type="hidden" name="'.$name.'" value="'.form_prep($value, $name)."\" />\n";
+ $form .= '<input type="hidden" name="'.$name.'" value="'.form_prep($value)."\" />\n";
}
else
{
@@ -163,16 +168,16 @@ if ( ! function_exists('form_hidden'))
// ------------------------------------------------------------------------
-/**
- * Text Input Field
- *
- * @param mixed
- * @param string
- * @param string
- * @return string
- */
if ( ! function_exists('form_input'))
{
+ /**
+ * Text Input Field
+ *
+ * @param mixed
+ * @param string
+ * @param string
+ * @return string
+ */
function form_input($data = '', $value = '', $extra = '')
{
$defaults = array('type' => 'text', 'name' => ( ! is_array($data) ? $data : ''), 'value' => $value);
@@ -183,18 +188,18 @@ if ( ! function_exists('form_input'))
// ------------------------------------------------------------------------
-/**
- * Password Field
- *
- * Identical to the input function but adds the "password" type
- *
- * @param mixed
- * @param string
- * @param string
- * @return string
- */
if ( ! function_exists('form_password'))
{
+ /**
+ * Password Field
+ *
+ * Identical to the input function but adds the "password" type
+ *
+ * @param mixed
+ * @param string
+ * @param string
+ * @return string
+ */
function form_password($data = '', $value = '', $extra = '')
{
if ( ! is_array($data))
@@ -209,18 +214,18 @@ if ( ! function_exists('form_password'))
// ------------------------------------------------------------------------
-/**
- * Upload Field
- *
- * Identical to the input function but adds the "file" type
- *
- * @param mixed
- * @param string
- * @param string
- * @return string
- */
if ( ! function_exists('form_upload'))
{
+ /**
+ * Upload Field
+ *
+ * Identical to the input function but adds the "file" type
+ *
+ * @param mixed
+ * @param string
+ * @param string
+ * @return string
+ */
function form_upload($data = '', $value = '', $extra = '')
{
if ( ! is_array($data))
@@ -235,16 +240,16 @@ if ( ! function_exists('form_upload'))
// ------------------------------------------------------------------------
-/**
- * Textarea field
- *
- * @param mixed
- * @param string
- * @param string
- * @return string
- */
if ( ! function_exists('form_textarea'))
{
+ /**
+ * Textarea field
+ *
+ * @param mixed $data
+ * @param string $value
+ * @param string $extra
+ * @return string
+ */
function form_textarea($data = '', $value = '', $extra = '')
{
$defaults = array('name' => ( ! is_array($data) ? $data : ''), 'cols' => '40', 'rows' => '10');
@@ -260,23 +265,23 @@ if ( ! function_exists('form_textarea'))
}
$name = is_array($data) ? $data['name'] : $data;
- return '<textarea '._parse_form_attributes($data, $defaults).$extra.'>'.form_prep($val, $name)."</textarea>\n";
+ return '<textarea '._parse_form_attributes($data, $defaults).$extra.'>'.form_prep($val, TRUE)."</textarea>\n";
}
}
// ------------------------------------------------------------------------
-/**
- * Multi-select menu
- *
- * @param string
- * @param array
- * @param mixed
- * @param string
- * @return string
- */
if ( ! function_exists('form_multiselect'))
{
+ /**
+ * Multi-select menu
+ *
+ * @param string
+ * @param array
+ * @param mixed
+ * @param string
+ * @return string
+ */
function form_multiselect($name = '', $options = array(), $selected = array(), $extra = '')
{
if ( ! strpos($extra, 'multiple'))
@@ -290,17 +295,17 @@ if ( ! function_exists('form_multiselect'))
// --------------------------------------------------------------------
-/**
- * Drop-down Menu
- *
- * @param string
- * @param array
- * @param string
- * @param string
- * @return string
- */
if ( ! function_exists('form_dropdown'))
{
+ /**
+ * Drop-down Menu
+ *
+ * @param mixed $name
+ * @param mixed $options
+ * @param mixed $selected
+ * @param mixed $extra
+ * @return string
+ */
function form_dropdown($name = '', $options = array(), $selected = array(), $extra = '')
{
// If name is really an array then we'll call the function again using the array
@@ -313,10 +318,7 @@ if ( ! function_exists('form_dropdown'))
return form_dropdown($name['name'], $name['options'], $name['selected'], $name['extra']);
}
- if ( ! is_array($selected))
- {
- $selected = array($selected);
- }
+ is_array($selected) OR $selected = array($selected);
// If no selected state was submitted we will attempt to set it automatically
if (count($selected) === 0 && isset($_POST[$name]))
@@ -324,7 +326,10 @@ if ( ! function_exists('form_dropdown'))
$selected = array($_POST[$name]);
}
- if ($extra != '') $extra = ' '.$extra;
+ if ($extra != '')
+ {
+ $extra = ' '.$extra;
+ }
$multiple = (count($selected) > 1 && strpos($extra, 'multiple') === FALSE) ? ' multiple="multiple"' : '';
@@ -334,21 +339,29 @@ if ( ! function_exists('form_dropdown'))
{
$key = (string) $key;
- if (is_array($val) && ! empty($val))
+ if (is_array($val))
{
+ if (empty($val))
+ {
+ continue;
+ }
+
$form .= '<optgroup label="'.$key."\">\n";
foreach ($val as $optgroup_key => $optgroup_val)
{
$sel = in_array($optgroup_key, $selected) ? ' selected="selected"' : '';
- $form .= '<option value="'.$optgroup_key.'"'.$sel.'>'.(string) $optgroup_val."</option>\n";
+ $form .= '<option value="'.form_prep($optgroup_key).'"'.$sel.'>'
+ .(string) $optgroup_val."</option>\n";
}
$form .= "</optgroup>\n";
}
else
{
- $form .= '<option value="'.$key.'"'.(in_array($key, $selected) ? ' selected="selected"' : '').'>'.(string) $val."</option>\n";
+ $form .= '<option value="'.form_prep($key).'"'
+ .(in_array($key, $selected) ? ' selected="selected"' : '').'>'
+ .(string) $val."</option>\n";
}
}
@@ -358,17 +371,17 @@ if ( ! function_exists('form_dropdown'))
// ------------------------------------------------------------------------
-/**
- * Checkbox Field
- *
- * @param mixed
- * @param string
- * @param bool
- * @param string
- * @return string
- */
if ( ! function_exists('form_checkbox'))
{
+ /**
+ * Checkbox Field
+ *
+ * @param mixed
+ * @param string
+ * @param bool
+ * @param string
+ * @return string
+ */
function form_checkbox($data = '', $value = '', $checked = FALSE, $extra = '')
{
$defaults = array('type' => 'checkbox', 'name' => ( ! is_array($data) ? $data : ''), 'value' => $value);
@@ -402,17 +415,17 @@ if ( ! function_exists('form_checkbox'))
// ------------------------------------------------------------------------
-/**
- * Radio Button
- *
- * @param mixed
- * @param string
- * @param bool
- * @param string
- * @return string
- */
if ( ! function_exists('form_radio'))
{
+ /**
+ * Radio Button
+ *
+ * @param mixed
+ * @param string
+ * @param bool
+ * @param string
+ * @return string
+ */
function form_radio($data = '', $value = '', $checked = FALSE, $extra = '')
{
if ( ! is_array($data))
@@ -427,16 +440,16 @@ if ( ! function_exists('form_radio'))
// ------------------------------------------------------------------------
-/**
- * Submit Button
- *
- * @param mixed
- * @param string
- * @param string
- * @return string
- */
if ( ! function_exists('form_submit'))
{
+ /**
+ * Submit Button
+ *
+ * @param mixed
+ * @param string
+ * @param string
+ * @return string
+ */
function form_submit($data = '', $value = '', $extra = '')
{
$defaults = array('type' => 'submit', 'name' => ( ! is_array($data) ? $data : ''), 'value' => $value);
@@ -446,16 +459,16 @@ if ( ! function_exists('form_submit'))
// ------------------------------------------------------------------------
-/**
- * Reset Button
- *
- * @param mixed
- * @param string
- * @param string
- * @return string
- */
if ( ! function_exists('form_reset'))
{
+ /**
+ * Reset Button
+ *
+ * @param mixed
+ * @param string
+ * @param string
+ * @return string
+ */
function form_reset($data = '', $value = '', $extra = '')
{
$defaults = array('type' => 'reset', 'name' => ( ! is_array($data) ? $data : ''), 'value' => $value);
@@ -465,16 +478,16 @@ if ( ! function_exists('form_reset'))
// ------------------------------------------------------------------------
-/**
- * Form Button
- *
- * @param mixed
- * @param string
- * @param string
- * @return string
- */
if ( ! function_exists('form_button'))
{
+ /**
+ * Form Button
+ *
+ * @param mixed
+ * @param string
+ * @param string
+ * @return string
+ */
function form_button($data = '', $content = '', $extra = '')
{
$defaults = array('name' => ( ! is_array($data) ? $data : ''), 'type' => 'button');
@@ -490,22 +503,22 @@ if ( ! function_exists('form_button'))
// ------------------------------------------------------------------------
-/**
- * Form Label Tag
- *
- * @param string The text to appear onscreen
- * @param string The id the label applies to
- * @param string Additional attributes
- * @return string
- */
if ( ! function_exists('form_label'))
{
+ /**
+ * Form Label Tag
+ *
+ * @param string The text to appear onscreen
+ * @param string The id the label applies to
+ * @param string Additional attributes
+ * @return string
+ */
function form_label($label_text = '', $id = '', $attributes = array())
{
$label = '<label';
- if ($id != '')
+ if ($id !== '')
{
$label .= ' for="'.$id.'"';
}
@@ -523,22 +536,23 @@ if ( ! function_exists('form_label'))
}
// ------------------------------------------------------------------------
-/**
- * Fieldset Tag
- *
- * Used to produce <fieldset><legend>text</legend>. To close fieldset
- * use form_fieldset_close()
- *
- * @param string The legend text
- * @param string Additional attributes
- * @return string
- */
+
if ( ! function_exists('form_fieldset'))
{
+ /**
+ * Fieldset Tag
+ *
+ * Used to produce <fieldset><legend>text</legend>. To close fieldset
+ * use form_fieldset_close()
+ *
+ * @param string The legend text
+ * @param string Additional attributes
+ * @return string
+ */
function form_fieldset($legend_text = '', $attributes = array())
{
$fieldset = '<fieldset'._attributes_to_string($attributes, FALSE).">\n";
- if ($legend_text != '')
+ if ($legend_text !== '')
{
return $fieldset.'<legend>'.$legend_text."</legend>\n";
}
@@ -549,14 +563,14 @@ if ( ! function_exists('form_fieldset'))
// ------------------------------------------------------------------------
-/**
- * Fieldset Close Tag
- *
- * @param string
- * @return string
- */
if ( ! function_exists('form_fieldset_close'))
{
+ /**
+ * Fieldset Close Tag
+ *
+ * @param string
+ * @return string
+ */
function form_fieldset_close($extra = '')
{
return '</fieldset>'.$extra;
@@ -565,14 +579,14 @@ if ( ! function_exists('form_fieldset_close'))
// ------------------------------------------------------------------------
-/**
- * Form Close Tag
- *
- * @param string
- * @return string
- */
if ( ! function_exists('form_close'))
{
+ /**
+ * Form Close Tag
+ *
+ * @param string
+ * @return string
+ */
function form_close($extra = '')
{
return '</form>'.$extra;
@@ -581,99 +595,82 @@ if ( ! function_exists('form_close'))
// ------------------------------------------------------------------------
-/**
- * Form Prep
- *
- * Formats text so that it can be safely placed in a form field in the event it has HTML tags.
- *
- * @param string
- * @return string
- */
if ( ! function_exists('form_prep'))
{
- function form_prep($str = '', $field_name = '')
+ /**
+ * Form Prep
+ *
+ * Formats text so that it can be safely placed in a form field in the event it has HTML tags.
+ *
+ * @param string|string[] $str Value to escape
+ * @param bool $is_textarea Whether we're escaping for a textarea element
+ * @return string|string[] Escaped values
+ */
+ function form_prep($str = '', $is_textarea = FALSE)
{
- static $prepped_fields = array();
-
- // if the field name is an array we do this recursively
if (is_array($str))
{
- foreach ($str as $key => $val)
+ foreach (array_keys($str) as $key)
{
- $str[$key] = form_prep($val);
+ $str[$key] = form_prep($str[$key], $is_textarea);
}
return $str;
}
- if ($str === '')
- {
- return '';
- }
-
- // we've already prepped a field with this name
- // @todo need to figure out a way to namespace this so
- // that we know the *exact* field and not just one with
- // the same name
- if (isset($prepped_fields[$field_name]))
- {
- return $str;
- }
-
- if ($field_name != '')
+ if ($is_textarea === TRUE)
{
- $prepped_fields[$field_name] = $field_name;
+ return str_replace(array('<', '>'), array('&lt;', '&gt;'), stripslashes($str));
}
- return html_escape($str);
+ return str_replace(array("'", '"'), array('&#39;', '&quot;'), stripslashes($str));
}
}
// ------------------------------------------------------------------------
-/**
- * Form Value
- *
- * Grabs a value from the POST array for the specified field so you can
- * re-populate an input field or textarea. If Form Validation
- * is active it retrieves the info from the validation class
- *
- * @param string
- * @return mixed
- */
if ( ! function_exists('set_value'))
{
- function set_value($field = '', $default = '')
+ /**
+ * Form Value
+ *
+ * Grabs a value from the POST array for the specified field so you can
+ * re-populate an input field or textarea. If Form Validation
+ * is active it retrieves the info from the validation class
+ *
+ * @param string $field Field name
+ * @param string $default Default value
+ * @param bool $is_textarea Whether the field is a textarea element
+ * @return string
+ */
+ function set_value($field = '', $default = '', $is_textarea = FALSE)
{
if (FALSE === ($OBJ =& _get_validation_object()))
{
- if ( ! isset($_POST[$field]))
- {
- return $default;
- }
-
- return form_prep($_POST[$field], $field);
+ return isset($_POST[$field])
+ ? form_prep($_POST[$field], $is_textarea)
+ : form_prep($default, $is_textarea);
}
- return form_prep($OBJ->set_value($field, $default), $field);
+ return form_prep($OBJ->set_value($field, $default), $is_textarea);
}
}
// ------------------------------------------------------------------------
-/**
- * Set Select
- *
- * Let's you set the selected value of a <select> menu via data in the POST array.
- * If Form Validation is active it retrieves the info from the validation class
- *
- * @param string
- * @param string
- * @param bool
- * @return string
- */
if ( ! function_exists('set_select'))
{
+ /**
+ * Set Select
+ *
+ * Let's you set the selected value of a <select> menu via data in the POST array.
+ * If Form Validation is active it retrieves the info from the validation class
+ *
+ * @param string
+ * @param string
+ * @param bool
+ * @return string
+ */
function set_select($field = '', $value = '', $default = FALSE)
{
$OBJ =& _get_validation_object();
@@ -682,7 +679,7 @@ if ( ! function_exists('set_select'))
{
if ( ! isset($_POST[$field]))
{
- if (count($_POST) === 0 && $default == TRUE)
+ if (count($_POST) === 0 && $default === TRUE)
{
return ' selected="selected"';
}
@@ -698,7 +695,7 @@ if ( ! function_exists('set_select'))
return '';
}
}
- elseif (($field == '' OR $value == '') OR ($field != $value))
+ elseif (($field == '' OR $value == '') OR $field !== $value)
{
return '';
}
@@ -712,19 +709,19 @@ if ( ! function_exists('set_select'))
// ------------------------------------------------------------------------
-/**
- * Set Checkbox
- *
- * Let's you set the selected value of a checkbox via the value in the POST array.
- * If Form Validation is active it retrieves the info from the validation class
- *
- * @param string
- * @param string
- * @param bool
- * @return string
- */
if ( ! function_exists('set_checkbox'))
{
+ /**
+ * Set Checkbox
+ *
+ * Let's you set the selected value of a checkbox via the value in the POST array.
+ * If Form Validation is active it retrieves the info from the validation class
+ *
+ * @param string
+ * @param string
+ * @param bool
+ * @return string
+ */
function set_checkbox($field = '', $value = '', $default = FALSE)
{
$OBJ =& _get_validation_object();
@@ -733,7 +730,7 @@ if ( ! function_exists('set_checkbox'))
{
if ( ! isset($_POST[$field]))
{
- if (count($_POST) === 0 && $default == TRUE)
+ if (count($_POST) === 0 && $default === TRUE)
{
return ' checked="checked"';
}
@@ -749,7 +746,7 @@ if ( ! function_exists('set_checkbox'))
return '';
}
}
- elseif (($field == '' OR $value == '') OR ($field != $value))
+ elseif (($field == '' OR $value == '') OR $field !== $value)
{
return '';
}
@@ -763,19 +760,19 @@ if ( ! function_exists('set_checkbox'))
// ------------------------------------------------------------------------
-/**
- * Set Radio
- *
- * Let's you set the selected value of a radio field via info in the POST array.
- * If Form Validation is active it retrieves the info from the validation class
- *
- * @param string
- * @param string
- * @param bool
- * @return string
- */
if ( ! function_exists('set_radio'))
{
+ /**
+ * Set Radio
+ *
+ * Let's you set the selected value of a radio field via info in the POST array.
+ * If Form Validation is active it retrieves the info from the validation class
+ *
+ * @param string
+ * @param string
+ * @param bool
+ * @return string
+ */
function set_radio($field = '', $value = '', $default = FALSE)
{
$OBJ =& _get_validation_object();
@@ -784,7 +781,7 @@ if ( ! function_exists('set_radio'))
{
if ( ! isset($_POST[$field]))
{
- if (count($_POST) === 0 && $default == TRUE)
+ if (count($_POST) === 0 && $default === TRUE)
{
return ' checked="checked"';
}
@@ -802,7 +799,7 @@ if ( ! function_exists('set_radio'))
}
else
{
- if (($field == '' OR $value == '') OR ($field != $value))
+ if (($field == '' OR $value == '') OR $field !== $value)
{
return '';
}
@@ -817,19 +814,19 @@ if ( ! function_exists('set_radio'))
// ------------------------------------------------------------------------
-/**
- * Form Error
- *
- * Returns the error for a specific form field. This is a helper for the
- * form validation class.
- *
- * @param string
- * @param string
- * @param string
- * @return string
- */
if ( ! function_exists('form_error'))
{
+ /**
+ * Form Error
+ *
+ * Returns the error for a specific form field. This is a helper for the
+ * form validation class.
+ *
+ * @param string
+ * @param string
+ * @param string
+ * @return string
+ */
function form_error($field = '', $prefix = '', $suffix = '')
{
if (FALSE === ($OBJ =& _get_validation_object()))
@@ -843,18 +840,18 @@ if ( ! function_exists('form_error'))
// ------------------------------------------------------------------------
-/**
- * Validation Error String
- *
- * Returns all the errors associated with a form submission. This is a helper
- * function for the form validation class.
- *
- * @param string
- * @param string
- * @return string
- */
if ( ! function_exists('validation_errors'))
{
+ /**
+ * Validation Error String
+ *
+ * Returns all the errors associated with a form submission. This is a helper
+ * function for the form validation class.
+ *
+ * @param string
+ * @param string
+ * @return string
+ */
function validation_errors($prefix = '', $suffix = '')
{
if (FALSE === ($OBJ =& _get_validation_object()))
@@ -868,17 +865,17 @@ if ( ! function_exists('validation_errors'))
// ------------------------------------------------------------------------
-/**
- * Parse the form attributes
- *
- * Helper function used by some of the form helpers
- *
- * @param array
- * @param array
- * @return string
- */
if ( ! function_exists('_parse_form_attributes'))
{
+ /**
+ * Parse the form attributes
+ *
+ * Helper function used by some of the form helpers
+ *
+ * @param array $attributes List of attributes
+ * @param array $default Default values
+ * @return string
+ */
function _parse_form_attributes($attributes, $default)
{
if (is_array($attributes))
@@ -902,9 +899,13 @@ if ( ! function_exists('_parse_form_attributes'))
foreach ($default as $key => $val)
{
- if ($key == 'value')
+ if ($key === 'value')
+ {
+ $val = form_prep($val);
+ }
+ elseif ($key === 'name' && ! strlen($default['name']))
{
- $val = form_prep($val, $default['name']);
+ continue;
}
$att .= $key.'="'.$val.'" ';
@@ -916,27 +917,27 @@ if ( ! function_exists('_parse_form_attributes'))
// ------------------------------------------------------------------------
-/**
- * Attributes To String
- *
- * Helper function used by some of the form helpers
- *
- * @param mixed
- * @param bool
- * @return string
- */
if ( ! function_exists('_attributes_to_string'))
{
+ /**
+ * Attributes To String
+ *
+ * Helper function used by some of the form helpers
+ *
+ * @param mixed
+ * @param bool
+ * @return string
+ */
function _attributes_to_string($attributes, $formtag = FALSE)
{
if (is_string($attributes) && strlen($attributes) > 0)
{
- if ($formtag == TRUE && strpos($attributes, 'method=') === FALSE)
+ if ($formtag === TRUE && strpos($attributes, 'method=') === FALSE)
{
$attributes .= ' method="post"';
}
- if ($formtag == TRUE && strpos($attributes, 'accept-charset=') === FALSE)
+ if ($formtag === TRUE && strpos($attributes, 'accept-charset=') === FALSE)
{
$attributes .= ' accept-charset="'.strtolower(config_item('charset')).'"';
}
@@ -975,16 +976,16 @@ if ( ! function_exists('_attributes_to_string'))
// ------------------------------------------------------------------------
-/**
- * Validation Object
- *
- * Determines what the form validation class was instantiated as, fetches
- * the object and returns it.
- *
- * @return mixed
- */
if ( ! function_exists('_get_validation_object'))
{
+ /**
+ * Validation Object
+ *
+ * Determines what the form validation class was instantiated as, fetches
+ * the object and returns it.
+ *
+ * @return mixed
+ */
function &_get_validation_object()
{
$CI =& get_instance();
diff --git a/system/helpers/html_helper.php b/system/helpers/html_helper.php
index 0417bd253..fa49f7d75 100644
--- a/system/helpers/html_helper.php
+++ b/system/helpers/html_helper.php
@@ -1,4 +1,4 @@
-<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');
+<?php
/**
* CodeIgniter
*
@@ -24,6 +24,7 @@
* @since Version 1.0
* @filesource
*/
+defined('BASEPATH') OR exit('No direct script access allowed');
/**
* CodeIgniter HTML Helpers
@@ -37,36 +38,37 @@
// ------------------------------------------------------------------------
-/**
- * Heading
- *
- * Generates an HTML heading tag.
- *
- * @param string content
- * @param int heading level
- * @return string
- */
if ( ! function_exists('heading'))
{
+ /**
+ * Heading
+ *
+ * Generates an HTML heading tag.
+ *
+ * @param string content
+ * @param int heading level
+ * @param string
+ * @return string
+ */
function heading($data = '', $h = '1', $attributes = '')
{
- return '<h'.$h.($attributes != '' ? ' ' : '').$attributes.'>'.$data.'</h'.$h.'>';
+ return '<h'.$h._stringify_attributes($attributes).'>'.$data.'</h'.$h.'>';
}
}
// ------------------------------------------------------------------------
-/**
- * Unordered List
- *
- * Generates an HTML unordered list from an single or multi-dimensional array.
- *
- * @param array
- * @param mixed
- * @return string
- */
if ( ! function_exists('ul'))
{
+ /**
+ * Unordered List
+ *
+ * Generates an HTML unordered list from an single or multi-dimensional array.
+ *
+ * @param array
+ * @param mixed
+ * @return string
+ */
function ul($list, $attributes = '')
{
return _list('ul', $list, $attributes);
@@ -75,17 +77,17 @@ if ( ! function_exists('ul'))
// ------------------------------------------------------------------------
-/**
- * Ordered List
- *
- * Generates an HTML ordered list from an single or multi-dimensional array.
- *
- * @param array
- * @param mixed
- * @return string
- */
if ( ! function_exists('ol'))
{
+ /**
+ * Ordered List
+ *
+ * Generates an HTML ordered list from an single or multi-dimensional array.
+ *
+ * @param array
+ * @param mixed
+ * @return string
+ */
function ol($list, $attributes = '')
{
return _list('ol', $list, $attributes);
@@ -94,19 +96,19 @@ if ( ! function_exists('ol'))
// ------------------------------------------------------------------------
-/**
- * Generates the list
- *
- * Generates an HTML ordered list from an single or multi-dimensional array.
- *
- * @param string
- * @param mixed
- * @param mixed
- * @param int
- * @return string
- */
if ( ! function_exists('_list'))
{
+ /**
+ * Generates the list
+ *
+ * Generates an HTML ordered list from an single or multi-dimensional array.
+ *
+ * @param string
+ * @param mixed
+ * @param mixed
+ * @param int
+ * @return string
+ */
function _list($type = 'ul', $list, $attributes = '', $depth = 0)
{
// If an array wasn't submitted there's nothing to do...
@@ -118,23 +120,8 @@ if ( ! function_exists('_list'))
// Set the indentation based on the depth
$out = str_repeat(' ', $depth);
- // Were any attributes submitted? If so generate a string
- if (is_array($attributes))
- {
- $atts = '';
- foreach ($attributes as $key => $val)
- {
- $atts .= ' '.$key.'="'.$val.'"';
- }
- $attributes = $atts;
- }
- elseif (is_string($attributes) && strlen($attributes) > 0)
- {
- $attributes = ' '.$attributes;
- }
-
// Write the opening list tag
- $out .= '<'.$type.$attributes.">\n";
+ $out .= '<'.$type._stringify_attributes($attributes).">\n";
// Cycle through the list elements. If an array is
// encountered we will recursively call _list()
@@ -165,34 +152,35 @@ if ( ! function_exists('_list'))
// ------------------------------------------------------------------------
-/**
- * Generates HTML BR tags based on number supplied
- *
- * @param int
- * @return string
- */
if ( ! function_exists('br'))
{
- function br($num = 1)
+ /**
+ * Generates HTML BR tags based on number supplied
+ *
+ * @param int $count Number of times to repeat the tag
+ * @return string
+ */
+ function br($count = 1)
{
- return str_repeat('<br />', $num);
+ return str_repeat('<br />', $count);
}
}
// ------------------------------------------------------------------------
-/**
- * Image
- *
- * Generates an <img /> element
- *
- * @param mixed
- * @param bool
- * @return string
- */
if ( ! function_exists('img'))
{
- function img($src = '', $index_page = FALSE)
+ /**
+ * Image
+ *
+ * Generates an <img /> element
+ *
+ * @param mixed
+ * @param bool
+ * @param mixed
+ * @return string
+ */
+ function img($src = '', $index_page = FALSE, $attributes = '')
{
if ( ! is_array($src) )
{
@@ -228,26 +216,26 @@ if ( ! function_exists('img'))
}
}
- return $img.'/>';
+ return $img._stringify_attributes($attributes).' />';
}
}
// ------------------------------------------------------------------------
-/**
- * Doctype
- *
- * Generates a page document type declaration
- *
- * Valid options are xhtml-11, xhtml-strict, xhtml-trans, xhtml-frame,
- * html4-strict, html4-trans, and html4-frame. Values are saved in the
- * doctypes config file.
- *
- * @param string type The doctype to be generated
- * @return string
- */
if ( ! function_exists('doctype'))
{
+ /**
+ * Doctype
+ *
+ * Generates a page document type declaration
+ *
+ * Examples of valid options: html5, xhtml-11, xhtml-strict, xhtml-trans,
+ * xhtml-frame, html4-strict, html4-trans, and html4-frame.
+ * All values are saved in the doctypes config file.
+ *
+ * @param string type The doctype to be generated
+ * @return string
+ */
function doctype($type = 'xhtml1-strict')
{
global $_doctypes;
@@ -275,21 +263,21 @@ if ( ! function_exists('doctype'))
// ------------------------------------------------------------------------
-/**
- * Link
- *
- * Generates link to a CSS file
- *
- * @param mixed stylesheet hrefs or an array
- * @param string rel
- * @param string type
- * @param string title
- * @param string media
- * @param bool should index_page be added to the css path
- * @return string
- */
if ( ! function_exists('link_tag'))
{
+ /**
+ * Link
+ *
+ * Generates link to a CSS file
+ *
+ * @param mixed stylesheet hrefs or an array
+ * @param string rel
+ * @param string type
+ * @param string title
+ * @param string media
+ * @param bool should index_page be added to the css path
+ * @return string
+ */
function link_tag($href = '', $rel = 'stylesheet', $type = 'text/css', $title = '', $media = '', $index_page = FALSE)
{
$CI =& get_instance();
@@ -333,12 +321,12 @@ if ( ! function_exists('link_tag'))
$link .= 'rel="'.$rel.'" type="'.$type.'" ';
- if ($media != '')
+ if ($media !== '')
{
$link .= 'media="'.$media.'" ';
}
- if ($title != '')
+ if ($title !== '')
{
$link .= 'title="'.$title.'" ';
}
@@ -350,17 +338,17 @@ if ( ! function_exists('link_tag'))
// ------------------------------------------------------------------------
-/**
- * Generates meta tags from an array of key/values
- *
- * @param array
- * @param string
- * @param string
- * @param string
- * @return string
- */
if ( ! function_exists('meta'))
{
+ /**
+ * Generates meta tags from an array of key/values
+ *
+ * @param array
+ * @param string
+ * @param string
+ * @param string
+ * @return string
+ */
function meta($name = '', $content = '', $type = 'name', $newline = "\n")
{
// Since we allow the data to be passes as a string, a simple array
@@ -378,10 +366,10 @@ if ( ! function_exists('meta'))
$str = '';
foreach ($name as $meta)
{
- $type = ( ! isset($meta['type']) OR $meta['type'] == 'name') ? 'name' : 'http-equiv';
- $name = ( ! isset($meta['name'])) ? '' : $meta['name'];
- $content = ( ! isset($meta['content'])) ? '' : $meta['content'];
- $newline = ( ! isset($meta['newline'])) ? "\n" : $meta['newline'];
+ $type = ( ! isset($meta['type']) OR $meta['type'] === 'name') ? 'name' : 'http-equiv';
+ $name = isset($meta['name']) ? $meta['name'] : '';
+ $content = isset($meta['content']) ? $meta['content'] : '';
+ $newline = isset($meta['newline']) ? $meta['newline'] : "\n";
$str .= '<meta '.$type.'="'.$name.'" content="'.$content.'" />'.$newline;
}
@@ -392,14 +380,14 @@ if ( ! function_exists('meta'))
// ------------------------------------------------------------------------
-/**
- * Generates non-breaking space entities based on number supplied
- *
- * @param int
- * @return string
- */
if ( ! function_exists('nbs'))
{
+ /**
+ * Generates non-breaking space entities based on number supplied
+ *
+ * @param int
+ * @return string
+ */
function nbs($num = 1)
{
return str_repeat('&nbsp;', $num);
diff --git a/system/helpers/inflector_helper.php b/system/helpers/inflector_helper.php
index feeaf57d7..68af820c5 100644
--- a/system/helpers/inflector_helper.php
+++ b/system/helpers/inflector_helper.php
@@ -1,4 +1,4 @@
-<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');
+<?php
/**
* CodeIgniter
*
@@ -24,6 +24,7 @@
* @since Version 1.0
* @filesource
*/
+defined('BASEPATH') OR exit('No direct script access allowed');
/**
* CodeIgniter Inflector Helpers
@@ -37,16 +38,16 @@
// --------------------------------------------------------------------
-/**
- * Singular
- *
- * Takes a plural word and makes it singular
- *
- * @param string
- * @return str
- */
if ( ! function_exists('singular'))
{
+ /**
+ * Singular
+ *
+ * Takes a plural word and makes it singular
+ *
+ * @param string $str Input string
+ * @return string
+ */
function singular($str)
{
$result = strval($str);
@@ -57,33 +58,33 @@ if ( ! function_exists('singular'))
}
$singular_rules = array(
- '/(matr)ices$/' => '\1ix',
- '/(vert|ind)ices$/' => '\1ex',
- '/^(ox)en/' => '\1',
- '/(alias)es$/' => '\1',
- '/([octop|vir])i$/' => '\1us',
- '/(cris|ax|test)es$/' => '\1is',
- '/(shoe)s$/' => '\1',
- '/(o)es$/' => '\1',
- '/(bus|campus)es$/' => '\1',
- '/([m|l])ice$/' => '\1ouse',
- '/(x|ch|ss|sh)es$/' => '\1',
- '/(m)ovies$/' => '\1\2ovie',
- '/(s)eries$/' => '\1\2eries',
- '/([^aeiouy]|qu)ies$/' => '\1y',
- '/([lr])ves$/' => '\1f',
- '/(tive)s$/' => '\1',
- '/(hive)s$/' => '\1',
- '/([^f])ves$/' => '\1fe',
- '/(^analy)ses$/' => '\1sis',
+ '/(matr)ices$/' => '\1ix',
+ '/(vert|ind)ices$/' => '\1ex',
+ '/^(ox)en/' => '\1',
+ '/(alias)es$/' => '\1',
+ '/([octop|vir])i$/' => '\1us',
+ '/(cris|ax|test)es$/' => '\1is',
+ '/(shoe)s$/' => '\1',
+ '/(o)es$/' => '\1',
+ '/(bus|campus)es$/' => '\1',
+ '/([m|l])ice$/' => '\1ouse',
+ '/(x|ch|ss|sh)es$/' => '\1',
+ '/(m)ovies$/' => '\1\2ovie',
+ '/(s)eries$/' => '\1\2eries',
+ '/([^aeiouy]|qu)ies$/' => '\1y',
+ '/([lr])ves$/' => '\1f',
+ '/(tive)s$/' => '\1',
+ '/(hive)s$/' => '\1',
+ '/([^f])ves$/' => '\1fe',
+ '/(^analy)ses$/' => '\1sis',
'/((a)naly|(b)a|(d)iagno|(p)arenthe|(p)rogno|(s)ynop|(t)he)ses$/' => '\1\2sis',
- '/([ti])a$/' => '\1um',
- '/(p)eople$/' => '\1\2erson',
- '/(m)en$/' => '\1an',
- '/(s)tatuses$/' => '\1\2tatus',
- '/(c)hildren$/' => '\1\2hild',
- '/(n)ews$/' => '\1\2ews',
- '/([^us])s$/' => '\1',
+ '/([ti])a$/' => '\1um',
+ '/(p)eople$/' => '\1\2erson',
+ '/(m)en$/' => '\1an',
+ '/(s)tatuses$/' => '\1\2tatus',
+ '/(c)hildren$/' => '\1\2hild',
+ '/(n)ews$/' => '\1\2ews',
+ '/([^us])s$/' => '\1'
);
foreach ($singular_rules as $rule => $replacement)
@@ -101,18 +102,17 @@ if ( ! function_exists('singular'))
// --------------------------------------------------------------------
-/**
- * Plural
- *
- * Takes a singular word and makes it plural
- *
- * @param string
- * @param bool
- * @return str
- */
if ( ! function_exists('plural'))
{
- function plural($str, $force = FALSE)
+ /**
+ * Plural
+ *
+ * Takes a singular word and makes it plural
+ *
+ * @param string $str Input string
+ * @return string
+ */
+ function plural($str)
{
$result = strval($str);
@@ -158,16 +158,16 @@ if ( ! function_exists('plural'))
// --------------------------------------------------------------------
-/**
- * Camelize
- *
- * Takes multiple words separated by spaces or underscores and camelizes them
- *
- * @param string
- * @return str
- */
if ( ! function_exists('camelize'))
{
+ /**
+ * Camelize
+ *
+ * Takes multiple words separated by spaces or underscores and camelizes them
+ *
+ * @param string $str Input string
+ * @return string
+ */
function camelize($str)
{
return strtolower($str[0]).substr(str_replace(' ', '', ucwords(preg_replace('/[\s_]+/', ' ', $str))), 1);
@@ -176,16 +176,16 @@ if ( ! function_exists('camelize'))
// --------------------------------------------------------------------
-/**
- * Underscore
- *
- * Takes multiple words separated by spaces and underscores them
- *
- * @param string
- * @return str
- */
if ( ! function_exists('underscore'))
{
+ /**
+ * Underscore
+ *
+ * Takes multiple words separated by spaces and underscores them
+ *
+ * @param string $str Input string
+ * @return string
+ */
function underscore($str)
{
return preg_replace('/[\s]+/', '_', strtolower(trim($str)));
@@ -194,34 +194,36 @@ if ( ! function_exists('underscore'))
// --------------------------------------------------------------------
-/**
- * Humanize
- *
- * Takes multiple words separated by the separator and changes them to spaces
- *
- * @param string $str
- * @param string $separator
- * @return str
- */
if ( ! function_exists('humanize'))
{
+ /**
+ * Humanize
+ *
+ * Takes multiple words separated by the separator and changes them to spaces
+ *
+ * @param string $str Input string
+ * @param string $separator Input separator
+ * @return string
+ */
function humanize($str, $separator = '_')
{
return ucwords(preg_replace('/['.$separator.']+/', ' ', strtolower(trim($str))));
}
}
-/**
- * Checks if the given word has a plural version.
- *
- * @param string the word to check
- * @return bool if the word is countable
- */
+// --------------------------------------------------------------------
+
if ( ! function_exists('is_countable'))
{
+ /**
+ * Checks if the given word has a plural version.
+ *
+ * @param string $word Word to check
+ * @return bool
+ */
function is_countable($word)
{
- return ! in_array(strtolower(strval($word)),
+ return ! in_array(strtolower($word),
array(
'equipment', 'information', 'rice', 'money',
'species', 'series', 'fish', 'meta'
diff --git a/system/helpers/language_helper.php b/system/helpers/language_helper.php
index b31c97107..6d24a9ca6 100644
--- a/system/helpers/language_helper.php
+++ b/system/helpers/language_helper.php
@@ -1,4 +1,4 @@
-<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');
+<?php
/**
* CodeIgniter
*
@@ -24,6 +24,7 @@
* @since Version 1.0
* @filesource
*/
+defined('BASEPATH') OR exit('No direct script access allowed');
/**
* CodeIgniter Language Helpers
@@ -37,25 +38,26 @@
// ------------------------------------------------------------------------
-/**
- * Lang
- *
- * Fetches a language variable and optionally outputs a form label
- *
- * @param string the language line
- * @param string the id of the form element
- * @return string
- */
if ( ! function_exists('lang'))
{
- function lang($line, $id = '')
+ /**
+ * Lang
+ *
+ * Fetches a language variable and optionally outputs a form label
+ *
+ * @param string $line The language line
+ * @param string $for The "for" value (id of the form element)
+ * @param array $attributes Any additional HTML attributes
+ * @return string
+ */
+ function lang($line, $for = '', $attributes = array())
{
$CI =& get_instance();
$line = $CI->lang->line($line);
- if ($id != '')
+ if ($for !== '')
{
- $line = '<label for="'.$id.'">'.$line.'</label>';
+ $line = '<label for="'.$for.'"'._stringify_attributes($attributes).'>'.$line.'</label>';
}
return $line;
diff --git a/system/helpers/number_helper.php b/system/helpers/number_helper.php
index 40da6e7bf..b93096543 100644
--- a/system/helpers/number_helper.php
+++ b/system/helpers/number_helper.php
@@ -1,4 +1,4 @@
-<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');
+<?php
/**
* CodeIgniter
*
@@ -24,6 +24,7 @@
* @since Version 1.0
* @filesource
*/
+defined('BASEPATH') OR exit('No direct script access allowed');
/**
* CodeIgniter Number Helpers
@@ -37,14 +38,15 @@
// ------------------------------------------------------------------------
-/**
- * Formats a numbers as bytes, based on size, and adds the appropriate suffix
- *
- * @param mixed // will be cast as int
- * @return string
- */
if ( ! function_exists('byte_format'))
{
+ /**
+ * Formats a numbers as bytes, based on size, and adds the appropriate suffix
+ *
+ * @param mixed will be cast as int
+ * @param int
+ * @return string
+ */
function byte_format($num, $precision = 1)
{
$CI =& get_instance();
diff --git a/system/helpers/path_helper.php b/system/helpers/path_helper.php
index 6ee99072c..5a798b118 100644
--- a/system/helpers/path_helper.php
+++ b/system/helpers/path_helper.php
@@ -1,4 +1,4 @@
-<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');
+<?php
/**
* CodeIgniter
*
@@ -24,6 +24,7 @@
* @since Version 1.0
* @filesource
*/
+defined('BASEPATH') OR exit('No direct script access allowed');
/**
* CodeIgniter Path Helpers
@@ -32,20 +33,20 @@
* @subpackage Helpers
* @category Helpers
* @author EllisLab Dev Team
- * @link http://codeigniter.com/user_guide/helpers/xml_helper.html
+ * @link http://codeigniter.com/user_guide/helpers/path_helper.html
*/
// ------------------------------------------------------------------------
-/**
- * Set Realpath
- *
- * @param string
- * @param bool checks to see if the path exists
- * @return string
- */
if ( ! function_exists('set_realpath'))
{
+ /**
+ * Set Realpath
+ *
+ * @param string
+ * @param bool checks to see if the path exists
+ * @return string
+ */
function set_realpath($path, $check_existance = FALSE)
{
// Security check to make sure the path is NOT a URL. No remote file inclusion!
@@ -55,7 +56,7 @@ if ( ! function_exists('set_realpath'))
}
// Resolve the path
- if (function_exists('realpath') && @realpath($path) !== FALSE)
+ if (@realpath($path) !== FALSE)
{
$path = realpath($path);
}
diff --git a/system/helpers/security_helper.php b/system/helpers/security_helper.php
index d6f134c9f..898a49c80 100644
--- a/system/helpers/security_helper.php
+++ b/system/helpers/security_helper.php
@@ -1,4 +1,4 @@
-<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');
+<?php
/**
* CodeIgniter
*
@@ -24,6 +24,7 @@
* @since Version 1.0
* @filesource
*/
+defined('BASEPATH') OR exit('No direct script access allowed');
/**
* CodeIgniter Security Helpers
@@ -37,15 +38,15 @@
// ------------------------------------------------------------------------
-/**
- * XSS Filtering
- *
- * @param string
- * @param bool whether or not the content is an image file
- * @return string
- */
if ( ! function_exists('xss_clean'))
{
+ /**
+ * XSS Filtering
+ *
+ * @param string
+ * @param bool whether or not the content is an image file
+ * @return string
+ */
function xss_clean($str, $is_image = FALSE)
{
$CI =& get_instance();
@@ -55,14 +56,14 @@ if ( ! function_exists('xss_clean'))
// ------------------------------------------------------------------------
-/**
- * Sanitize Filename
- *
- * @param string
- * @return string
- */
if ( ! function_exists('sanitize_filename'))
{
+ /**
+ * Sanitize Filename
+ *
+ * @param string
+ * @return string
+ */
function sanitize_filename($filename)
{
$CI =& get_instance();
@@ -72,14 +73,17 @@ if ( ! function_exists('sanitize_filename'))
// --------------------------------------------------------------------
-/**
- * Hash encode a string
- *
- * @param string
- * @return string
- */
if ( ! function_exists('do_hash'))
{
+ /**
+ * Hash encode a string
+ *
+ * @todo Remove in version 3.1+.
+ * @deprecated 3.0.0 Use PHP's native hash() instead.
+ * @param string $str
+ * @param string $type = 'sha1'
+ * @return string
+ */
function do_hash($str, $type = 'sha1')
{
if ( ! in_array(strtolower($type), hash_algos()))
@@ -93,33 +97,34 @@ if ( ! function_exists('do_hash'))
// ------------------------------------------------------------------------
-/**
- * Strip Image Tags
- *
- * @param string
- * @return string
- */
if ( ! function_exists('strip_image_tags'))
{
+ /**
+ * Strip Image Tags
+ *
+ * @param string
+ * @return string
+ */
function strip_image_tags($str)
{
- return preg_replace(array('#<img\s+.*?src\s*=\s*["\'](.+?)["\'].*?\>#', '#<img\s+.*?src\s*=\s*(.+?).*?\>#'), '\\1', $str);
+ $CI =& get_instance();
+ return $CI->security->strip_image_tags($str);
}
}
// ------------------------------------------------------------------------
-/**
- * Convert PHP tags to entities
- *
- * @param string
- * @return string
- */
if ( ! function_exists('encode_php_tags'))
{
+ /**
+ * Convert PHP tags to entities
+ *
+ * @param string
+ * @return string
+ */
function encode_php_tags($str)
{
- return str_replace(array('<?php', '<?PHP', '<?', '?>'), array('&lt;?php', '&lt;?PHP', '&lt;?', '?&gt;'), $str);
+ return str_replace(array('<?', '?>'), array('&lt;?', '?&gt;'), $str);
}
}
diff --git a/system/helpers/smiley_helper.php b/system/helpers/smiley_helper.php
index 8dba74e73..7293999fe 100644
--- a/system/helpers/smiley_helper.php
+++ b/system/helpers/smiley_helper.php
@@ -1,4 +1,4 @@
-<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');
+<?php
/**
* CodeIgniter
*
@@ -24,6 +24,7 @@
* @since Version 1.0
* @filesource
*/
+defined('BASEPATH') OR exit('No direct script access allowed');
/**
* CodeIgniter Smiley Helpers
@@ -37,125 +38,110 @@
// ------------------------------------------------------------------------
-/**
- * Smiley Javascript
- *
- * Returns the javascript required for the smiley insertion. Optionally takes
- * an array of aliases to loosely couple the smiley array to the view.
- *
- * @param mixed alias name or array of alias->field_id pairs
- * @param string field_id if alias name was passed in
- * @return array
- */
if ( ! function_exists('smiley_js'))
{
+ /**
+ * Smiley Javascript
+ *
+ * Returns the javascript required for the smiley insertion. Optionally takes
+ * an array of aliases to loosely couple the smiley array to the view.
+ *
+ * @param mixed alias name or array of alias->field_id pairs
+ * @param string field_id if alias name was passed in
+ * @param bool
+ * @return array
+ */
function smiley_js($alias = '', $field_id = '', $inline = TRUE)
{
static $do_setup = TRUE;
-
$r = '';
- if ($alias != '' && ! is_array($alias))
+ if ($alias !== '' && ! is_array($alias))
{
$alias = array($alias => $field_id);
}
if ($do_setup === TRUE)
{
- $do_setup = FALSE;
-
- $m = array();
+ $do_setup = FALSE;
+ $m = array();
- if (is_array($alias))
+ if (is_array($alias))
+ {
+ foreach ($alias as $name => $id)
{
- foreach ($alias as $name => $id)
- {
- $m[] = '"'.$name.'" : "'.$id.'"';
- }
+ $m[] = '"'.$name.'" : "'.$id.'"';
}
+ }
- $m = '{'.implode(',', $m).'}';
+ $m = '{'.implode(',', $m).'}';
- $r .= <<<EOF
- var smiley_map = {$m};
+ $r .= <<<EOF
+ var smiley_map = {$m};
- function insert_smiley(smiley, field_id) {
- var el = document.getElementById(field_id), newStart;
+ function insert_smiley(smiley, field_id) {
+ var el = document.getElementById(field_id), newStart;
- if ( ! el && smiley_map[field_id]) {
- el = document.getElementById(smiley_map[field_id]);
+ if ( ! el && smiley_map[field_id]) {
+ el = document.getElementById(smiley_map[field_id]);
- if ( ! el)
- return false;
- }
+ if ( ! el)
+ return false;
+ }
- el.focus();
- smiley = " " + smiley;
+ el.focus();
+ smiley = " " + smiley;
- if ('selectionStart' in el) {
- newStart = el.selectionStart + smiley.length;
+ if ('selectionStart' in el) {
+ newStart = el.selectionStart + smiley.length;
- el.value = el.value.substr(0, el.selectionStart) +
- smiley +
- el.value.substr(el.selectionEnd, el.value.length);
- el.setSelectionRange(newStart, newStart);
- }
- else if (document.selection) {
- document.selection.createRange().text = smiley;
- }
+ el.value = el.value.substr(0, el.selectionStart) +
+ smiley +
+ el.value.substr(el.selectionEnd, el.value.length);
+ el.setSelectionRange(newStart, newStart);
+ }
+ else if (document.selection) {
+ document.selection.createRange().text = smiley;
}
+ }
EOF;
}
- else
+ elseif (is_array($alias))
{
- if (is_array($alias))
+ foreach ($alias as $name => $id)
{
- foreach ($alias as $name => $id)
- {
- $r .= 'smiley_map["'.$name.'"] = "'.$id.'";'."\n";
- }
+ $r .= 'smiley_map["'.$name.'"] = "'.$id."\";\n";
}
}
- if ($inline)
- {
- return '<script type="text/javascript" charset="utf-8">/*<![CDATA[ */'.$r.'// ]]></script>';
- }
- else
- {
- return $r;
- }
+ return ($inline) ? '<script type="text/javascript" charset="utf-8">/*<![CDATA[ */'.$r.'// ]]></script>' : $r;
}
}
// ------------------------------------------------------------------------
-/**
- * Get Clickable Smileys
- *
- * Returns an array of image tag links that can be clicked to be inserted
- * into a form field.
- *
- * @param string the URL to the folder containing the smiley images
- * @return array
- */
if ( ! function_exists('get_clickable_smileys'))
{
- function get_clickable_smileys($image_url, $alias = '', $smileys = NULL)
+ /**
+ * Get Clickable Smileys
+ *
+ * Returns an array of image tag links that can be clicked to be inserted
+ * into a form field.
+ *
+ * @param string the URL to the folder containing the smiley images
+ * @param array
+ * @return array
+ */
+ function get_clickable_smileys($image_url, $alias = '')
{
// For backward compatibility with js_insert_smiley
-
if (is_array($alias))
{
$smileys = $alias;
}
-
- if ( ! is_array($smileys))
+ elseif (FALSE === ($smileys = _get_smiley_array()))
{
- if (FALSE === ($smileys = _get_smiley_array()))
- {
- return $smileys;
- }
+ return FALSE;
}
// Add a trailing slash to the file path if needed
@@ -165,7 +151,7 @@ if ( ! function_exists('get_clickable_smileys'))
foreach ($smileys as $key => $val)
{
// Keep duplicates from being used, which can happen if the
- // mapping array contains multiple identical replacements. For example:
+ // mapping array contains multiple identical replacements. For example:
// :-) and :) might be replaced with the same image so both smileys
// will be in the array.
if (isset($used[$smileys[$key][0]]))
@@ -173,8 +159,7 @@ if ( ! function_exists('get_clickable_smileys'))
continue;
}
- $link[] = "<a href=\"javascript:void(0);\" onclick=\"insert_smiley('".$key."', '".$alias."')\"><img src=\"".$image_url.$smileys[$key][0]."\" width=\"".$smileys[$key][1]."\" height=\"".$smileys[$key][2]."\" alt=\"".$smileys[$key][3]."\" style=\"border:0;\" /></a>";
-
+ $link[] = '<a href="javascript:void(0);" onclick="insert_smiley(\''.$key.'\', \''.$alias.'\')"><img src="'.$image_url.$smileys[$key][0].'" alt="'.$smileys[$key][3].'" style="width: '.$smileys[$key][1].'; height: '.$smileys[$key][2].'; border: 0;" /></a>';
$used[$smileys[$key][0]] = TRUE;
}
@@ -184,38 +169,31 @@ if ( ! function_exists('get_clickable_smileys'))
// ------------------------------------------------------------------------
-/**
- * Parse Smileys
- *
- * Takes a string as input and swaps any contained smileys for the actual image
- *
- * @param string the text to be parsed
- * @param string the URL to the folder containing the smiley images
- * @return string
- */
if ( ! function_exists('parse_smileys'))
{
+ /**
+ * Parse Smileys
+ *
+ * Takes a string as input and swaps any contained smileys for the actual image
+ *
+ * @param string the text to be parsed
+ * @param string the URL to the folder containing the smiley images
+ * @param array
+ * @return string
+ */
function parse_smileys($str = '', $image_url = '', $smileys = NULL)
{
- if ($image_url == '')
+ if ($image_url === '' OR ( ! is_array($smileys) && FALSE === ($smileys = _get_smiley_array())))
{
return $str;
}
- if ( ! is_array($smileys))
- {
- if (FALSE === ($smileys = _get_smiley_array()))
- {
- return $str;
- }
- }
-
// Add a trailing slash to the file path if needed
- $image_url = preg_replace("/(.+?)\/*$/", "\\1/", $image_url);
+ $image_url = rtrim($image_url, '/').'/';
foreach ($smileys as $key => $val)
{
- $str = str_replace($key, "<img src=\"".$image_url.$smileys[$key][0]."\" width=\"".$smileys[$key][1]."\" height=\"".$smileys[$key][2]."\" alt=\"".$smileys[$key][3]."\" style=\"border:0;\" />", $str);
+ $str = str_replace($key, '<img src="'.$image_url.$smileys[$key][0].'" alt="'.$smileys[$key][3].'" style="width: '.$smileys[$key][1].'; height: '.$smileys[$key][2].'; border: 0;" />', $str);
}
return $str;
@@ -224,15 +202,15 @@ if ( ! function_exists('parse_smileys'))
// ------------------------------------------------------------------------
-/**
- * Get Smiley Array
- *
- * Fetches the config/smiley.php file
- *
- * @return mixed
- */
if ( ! function_exists('_get_smiley_array'))
{
+ /**
+ * Get Smiley Array
+ *
+ * Fetches the config/smiley.php file
+ *
+ * @return mixed
+ */
function _get_smiley_array()
{
if (defined('ENVIRONMENT') && file_exists(APPPATH.'config/'.ENVIRONMENT.'/smileys.php'))
@@ -244,40 +222,7 @@ if ( ! function_exists('_get_smiley_array'))
include(APPPATH.'config/smileys.php');
}
- if (isset($smileys) && is_array($smileys))
- {
- return $smileys;
- }
-
- return FALSE;
- }
-}
-
-// ------------------------------------------------------------------------
-
-/**
- * JS Insert Smiley
- *
- * Generates the javascript function needed to insert smileys into a form field
- *
- * DEPRECATED as of version 1.7.2, use smiley_js instead
- *
- * @param string form name
- * @param string field name
- * @return string
- */
-if ( ! function_exists('js_insert_smiley'))
-{
- function js_insert_smiley($form_name = '', $form_field = '')
- {
- return <<<EOF
-<script type="text/javascript">
- function insert_smiley(smiley)
- {
- document.{$form_name}.{$form_field}.value += " " + smiley;
- }
-</script>
-EOF;
+ return (isset($smileys) && is_array($smileys)) ? $smileys : FALSE;
}
}
diff --git a/system/helpers/string_helper.php b/system/helpers/string_helper.php
index aed35c157..9fc24559a 100644
--- a/system/helpers/string_helper.php
+++ b/system/helpers/string_helper.php
@@ -1,4 +1,4 @@
-<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');
+<?php
/**
* CodeIgniter
*
@@ -24,6 +24,7 @@
* @since Version 1.0
* @filesource
*/
+defined('BASEPATH') OR exit('No direct script access allowed');
/**
* CodeIgniter String Helpers
@@ -37,22 +38,25 @@
// ------------------------------------------------------------------------
-/**
- * Trim Slashes
- *
- * Removes any leading/trailing slashes from a string:
- *
- * /this/that/theother/
- *
- * becomes:
- *
- * this/that/theother
- *
- * @param string
- * @return string
- */
if ( ! function_exists('trim_slashes'))
{
+ /**
+ * Trim Slashes
+ *
+ * Removes any leading/trailing slashes from a string:
+ *
+ * /this/that/theother/
+ *
+ * becomes:
+ *
+ * this/that/theother
+ *
+ * @todo Remove in version 3.1+.
+ * @deprecated 3.0.0 This is just an alias for PHP's native trim()
+ *
+ * @param string
+ * @return string
+ */
function trim_slashes($str)
{
return trim($str, '/');
@@ -61,28 +65,26 @@ if ( ! function_exists('trim_slashes'))
// ------------------------------------------------------------------------
-/**
- * Strip Slashes
- *
- * Removes slashes contained in a string or in an array
- *
- * @param mixed string or array
- * @return mixed string or array
- */
if ( ! function_exists('strip_slashes'))
{
+ /**
+ * Strip Slashes
+ *
+ * Removes slashes contained in a string or in an array
+ *
+ * @param mixed string or array
+ * @return mixed string or array
+ */
function strip_slashes($str)
{
- if (is_array($str))
+ if ( ! is_array($str))
{
- foreach ($str as $key => $val)
- {
- $str[$key] = strip_slashes($val);
- }
+ return stripslashes($str);
}
- else
+
+ foreach ($str as $key => $val)
{
- $str = stripslashes($str);
+ $str[$key] = strip_slashes($val);
}
return $str;
@@ -91,16 +93,16 @@ if ( ! function_exists('strip_slashes'))
// ------------------------------------------------------------------------
-/**
- * Strip Quotes
- *
- * Removes single and double quotes from a string
- *
- * @param string
- * @return string
- */
if ( ! function_exists('strip_quotes'))
{
+ /**
+ * Strip Quotes
+ *
+ * Removes single and double quotes from a string
+ *
+ * @param string
+ * @return string
+ */
function strip_quotes($str)
{
return str_replace(array('"', "'"), '', $str);
@@ -109,16 +111,16 @@ if ( ! function_exists('strip_quotes'))
// ------------------------------------------------------------------------
-/**
- * Quotes to Entities
- *
- * Converts single and double quotes to entities
- *
- * @param string
- * @return string
- */
if ( ! function_exists('quotes_to_entities'))
{
+ /**
+ * Quotes to Entities
+ *
+ * Converts single and double quotes to entities
+ *
+ * @param string
+ * @return string
+ */
function quotes_to_entities($str)
{
return str_replace(array("\'","\"","'",'"'), array("&#39;","&quot;","&#39;","&quot;"), $str);
@@ -127,23 +129,23 @@ if ( ! function_exists('quotes_to_entities'))
// ------------------------------------------------------------------------
-/**
- * Reduce Double Slashes
- *
- * Converts double slashes in a string to a single slash,
- * except those found in http://
- *
- * http://www.some-site.com//index.php
- *
- * becomes:
- *
- * http://www.some-site.com/index.php
- *
- * @param string
- * @return string
- */
if ( ! function_exists('reduce_double_slashes'))
{
+ /**
+ * Reduce Double Slashes
+ *
+ * Converts double slashes in a string to a single slash,
+ * except those found in http://
+ *
+ * http://www.some-site.com//index.php
+ *
+ * becomes:
+ *
+ * http://www.some-site.com/index.php
+ *
+ * @param string
+ * @return string
+ */
function reduce_double_slashes($str)
{
return preg_replace('#(^|[^:])//+#', '\\1/', $str);
@@ -152,131 +154,116 @@ if ( ! function_exists('reduce_double_slashes'))
// ------------------------------------------------------------------------
-/**
- * Reduce Multiples
- *
- * Reduces multiple instances of a particular character. Example:
- *
- * Fred, Bill,, Joe, Jimmy
- *
- * becomes:
- *
- * Fred, Bill, Joe, Jimmy
- *
- * @param string
- * @param string the character you wish to reduce
- * @param bool TRUE/FALSE - whether to trim the character from the beginning/end
- * @return string
- */
if ( ! function_exists('reduce_multiples'))
{
+ /**
+ * Reduce Multiples
+ *
+ * Reduces multiple instances of a particular character. Example:
+ *
+ * Fred, Bill,, Joe, Jimmy
+ *
+ * becomes:
+ *
+ * Fred, Bill, Joe, Jimmy
+ *
+ * @param string
+ * @param string the character you wish to reduce
+ * @param bool TRUE/FALSE - whether to trim the character from the beginning/end
+ * @return string
+ */
function reduce_multiples($str, $character = ',', $trim = FALSE)
{
$str = preg_replace('#'.preg_quote($character, '#').'{2,}#', $character, $str);
-
- if ($trim === TRUE)
- {
- return trim($str, $character);
- }
-
- return $str;
+ return ($trim === TRUE) ? trim($str, $character) : $str;
}
}
// ------------------------------------------------------------------------
-/**
- * Create a Random String
- *
- * Useful for generating passwords or hashes.
- *
- * @param string type of random string. basic, alpha, alunum, numeric, nozero, unique, md5, encrypt and sha1
- * @param int number of characters
- * @return string
- */
if ( ! function_exists('random_string'))
{
+ /**
+ * Create a Random String
+ *
+ * Useful for generating passwords or hashes.
+ *
+ * @param string type of random string. basic, alpha, alunum, numeric, nozero, unique, md5, encrypt and sha1
+ * @param int number of characters
+ * @return string
+ */
function random_string($type = 'alnum', $len = 8)
{
- switch($type)
+ switch ($type)
{
- case 'basic' : return mt_rand();
- break;
- case 'alnum' :
- case 'numeric' :
- case 'nozero' :
- case 'alpha' :
-
- switch ($type)
- {
- case 'alpha' : $pool = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
- break;
- case 'alnum' : $pool = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
- break;
- case 'numeric' : $pool = '0123456789';
- break;
- case 'nozero' : $pool = '123456789';
- break;
- }
-
- $str = substr(str_shuffle(str_repeat($pool, ceil($len/strlen($pool)))),0,$len);
-
- return $str;
- break;
- case 'unique' :
- case 'md5' :
-
- return md5(uniqid(mt_rand()));
- break;
- case 'encrypt' :
- case 'sha1' :
-
- $CI =& get_instance();
- $CI->load->helper('security');
-
- return do_hash(uniqid(mt_rand(), TRUE), 'sha1');
- break;
+ case 'basic':
+ return mt_rand();
+ case 'alnum':
+ case 'numeric':
+ case 'nozero':
+ case 'alpha':
+ switch ($type)
+ {
+ case 'alpha':
+ $pool = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
+ break;
+ case 'alnum':
+ $pool = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
+ break;
+ case 'numeric':
+ $pool = '0123456789';
+ break;
+ case 'nozero':
+ $pool = '123456789';
+ break;
+ }
+ return substr(str_shuffle(str_repeat($pool, ceil($len / strlen($pool)))), 0, $len);
+ case 'unique': // todo: remove in 3.1+
+ case 'md5':
+ return md5(uniqid(mt_rand()));
+ case 'encrypt': // todo: remove in 3.1+
+ case 'sha1':
+ return sha1(uniqid(mt_rand(), TRUE));
}
}
}
// ------------------------------------------------------------------------
-/**
- * Add's _1 to a string or increment the ending number to allow _2, _3, etc
- *
- * @param string required
- * @param string What should the duplicate number be appended with
- * @param string Which number should be used for the first dupe increment
- * @return string
- */
if ( ! function_exists('increment_string'))
{
+ /**
+ * Add's _1 to a string or increment the ending number to allow _2, _3, etc
+ *
+ * @param string required
+ * @param string What should the duplicate number be appended with
+ * @param string Which number should be used for the first dupe increment
+ * @return string
+ */
function increment_string($str, $separator = '_', $first = 1)
{
preg_match('/(.+)'.$separator.'([0-9]+)$/', $str, $match);
-
return isset($match[2]) ? $match[1].$separator.($match[2] + 1) : $str.$separator.$first;
}
}
// ------------------------------------------------------------------------
-/**
- * Alternator
- *
- * Allows strings to be alternated. See docs...
- *
- * @param string (as many parameters as needed)
- * @return string
- */
if ( ! function_exists('alternator'))
{
- function alternator()
+ /**
+ * Alternator
+ *
+ * Allows strings to be alternated. See docs...
+ *
+ * @param string (as many parameters as needed)
+ * @return string
+ */
+ function alternator($args)
{
static $i;
- if (func_num_args() == 0)
+ if (func_num_args() === 0)
{
$i = 0;
return '';
@@ -288,15 +275,18 @@ if ( ! function_exists('alternator'))
// ------------------------------------------------------------------------
-/**
- * Repeater function
- *
- * @param string
- * @param int number of repeats
- * @return string
- */
if ( ! function_exists('repeater'))
{
+ /**
+ * Repeater function
+ *
+ * @todo Remove in version 3.1+.
+ * @deprecated 3.0.0 This is just an alias for PHP's native str_repeat()
+ *
+ * @param string $data String to repeat
+ * @param int $num Number of repeats
+ * @return string
+ */
function repeater($data, $num = 1)
{
return ($num > 0) ? str_repeat($data, $num) : '';
diff --git a/system/helpers/text_helper.php b/system/helpers/text_helper.php
index cc501c334..705238704 100644
--- a/system/helpers/text_helper.php
+++ b/system/helpers/text_helper.php
@@ -1,4 +1,4 @@
-<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');
+<?php
/**
* CodeIgniter
*
@@ -24,6 +24,7 @@
* @since Version 1.0
* @filesource
*/
+defined('BASEPATH') OR exit('No direct script access allowed');
/**
* CodeIgniter Text Helpers
@@ -37,28 +38,28 @@
// ------------------------------------------------------------------------
-/**
- * Word Limiter
- *
- * Limits a string to X number of words.
- *
- * @param string
- * @param int
- * @param string the end character. Usually an ellipsis
- * @return string
- */
if ( ! function_exists('word_limiter'))
{
+ /**
+ * Word Limiter
+ *
+ * Limits a string to X number of words.
+ *
+ * @param string
+ * @param int
+ * @param string the end character. Usually an ellipsis
+ * @return string
+ */
function word_limiter($str, $limit = 100, $end_char = '&#8230;')
{
- if (trim($str) == '')
+ if (trim($str) === '')
{
return $str;
}
preg_match('/^\s*+(?:\S++\s*+){1,'.(int) $limit.'}/', $str, $matches);
- if (strlen($str) == strlen($matches[0]))
+ if (strlen($str) === strlen($matches[0]))
{
$end_char = '';
}
@@ -69,19 +70,19 @@ if ( ! function_exists('word_limiter'))
// ------------------------------------------------------------------------
-/**
- * Character Limiter
- *
- * Limits the string based on the character count. Preserves complete words
- * so the character count may not be exactly as specified.
- *
- * @param string
- * @param int
- * @param string the end character. Usually an ellipsis
- * @return string
- */
if ( ! function_exists('character_limiter'))
{
+ /**
+ * Character Limiter
+ *
+ * Limits the string based on the character count. Preserves complete words
+ * so the character count may not be exactly as specified.
+ *
+ * @param string
+ * @param int
+ * @param string the end character. Usually an ellipsis
+ * @return string
+ */
function character_limiter($str, $n = 500, $end_char = '&#8230;')
{
if (strlen($str) < $n)
@@ -89,14 +90,15 @@ if ( ! function_exists('character_limiter'))
return $str;
}
- $str = preg_replace("/\s+/", ' ', str_replace(array("\r\n", "\r", "\n"), ' ', $str));
+ // a bit complicated, but faster than preg_replace with \s+
+ $str = preg_replace('/ {2,}/', ' ', str_replace(array("\r", "\n", "\t", "\x0B", "\x0C"), ' ', $str));
if (strlen($str) <= $n)
{
return $str;
}
- $out = "";
+ $out = '';
foreach (explode(' ', trim($str)) as $val)
{
$out .= $val.' ';
@@ -104,7 +106,7 @@ if ( ! function_exists('character_limiter'))
if (strlen($out) >= $n)
{
$out = trim($out);
- return (strlen($out) == strlen($str)) ? $out : $out.$end_char;
+ return (strlen($out) === strlen($str)) ? $out : $out.$end_char;
}
}
}
@@ -112,23 +114,20 @@ if ( ! function_exists('character_limiter'))
// ------------------------------------------------------------------------
-/**
- * High ASCII to Entities
- *
- * Converts High ascii text and MS Word special characters to character entities
- *
- * @param string
- * @return string
- */
if ( ! function_exists('ascii_to_entities'))
{
+ /**
+ * High ASCII to Entities
+ *
+ * Converts high ASCII text and MS Word special characters to character entities
+ *
+ * @param string $str
+ * @return string
+ */
function ascii_to_entities($str)
{
- $count = 1;
- $out = '';
- $temp = array();
-
- for ($i = 0, $s = strlen($str); $i < $s; $i++)
+ $out = '';
+ for ($i = 0, $s = strlen($str), $count = 1, $temp = array(); $i < $s; $i++)
{
$ordinal = ord($str[$i]);
@@ -138,9 +137,9 @@ if ( ! function_exists('ascii_to_entities'))
If the $temp array has a value but we have moved on, then it seems only
fair that we output that entity and restart $temp before continuing. -Paul
*/
- if (count($temp) == 1)
+ if (count($temp) === 1)
{
- $out .= '&#'.array_shift($temp).';';
+ $out .= '&#'.array_shift($temp).';';
$count = 1;
}
@@ -148,16 +147,18 @@ if ( ! function_exists('ascii_to_entities'))
}
else
{
- if (count($temp) == 0)
+ if (count($temp) === 0)
{
$count = ($ordinal < 224) ? 2 : 3;
}
$temp[] = $ordinal;
- if (count($temp) == $count)
+ if (count($temp) === $count)
{
- $number = ($count == 3) ? (($temp['0'] % 16) * 4096) + (($temp['1'] % 64) * 64) + ($temp['2'] % 64) : (($temp['0'] % 32) * 64) + ($temp['1'] % 64);
+ $number = ($count === 3)
+ ? (($temp[0] % 16) * 4096) + (($temp[1] % 64) * 64) + ($temp[2] % 64)
+ : (($temp[0] % 32) * 64) + ($temp[1] % 64);
$out .= '&#'.$number.';';
$count = 1;
@@ -172,25 +173,24 @@ if ( ! function_exists('ascii_to_entities'))
// ------------------------------------------------------------------------
-/**
- * Entities to ASCII
- *
- * Converts character entities back to ASCII
- *
- * @param string
- * @param bool
- * @return string
- */
if ( ! function_exists('entities_to_ascii'))
{
+ /**
+ * Entities to ASCII
+ *
+ * Converts character entities back to ASCII
+ *
+ * @param string
+ * @param bool
+ * @return string
+ */
function entities_to_ascii($str, $all = TRUE)
{
if (preg_match_all('/\&#(\d+)\;/', $str, $matches))
{
- for ($i = 0, $s = count($matches['0']); $i < $s; $i++)
+ for ($i = 0, $s = count($matches[0]); $i < $s; $i++)
{
- $digits = $matches['1'][$i];
-
+ $digits = $matches[1][$i];
$out = '';
if ($digits < 128)
@@ -200,25 +200,24 @@ if ( ! function_exists('entities_to_ascii'))
}
elseif ($digits < 2048)
{
- $out .= chr(192 + (($digits - ($digits % 64)) / 64));
- $out .= chr(128 + ($digits % 64));
+ $out .= chr(192 + (($digits - ($digits % 64)) / 64)).chr(128 + ($digits % 64));
}
else
{
- $out .= chr(224 + (($digits - ($digits % 4096)) / 4096));
- $out .= chr(128 + ((($digits % 4096) - ($digits % 64)) / 64));
- $out .= chr(128 + ($digits % 64));
+ $out .= chr(224 + (($digits - ($digits % 4096)) / 4096))
+ .chr(128 + ((($digits % 4096) - ($digits % 64)) / 64))
+ .chr(128 + ($digits % 64));
}
- $str = str_replace($matches['0'][$i], $out, $str);
+ $str = str_replace($matches[0][$i], $out, $str);
}
}
if ($all)
{
- $str = str_replace(array("&amp;", "&lt;", "&gt;", "&quot;", "&apos;", "&#45;"),
- array("&","<",">","\"", "'", "-"),
- $str);
+ return str_replace(array('&amp;', '&lt;', '&gt;', '&quot;', '&apos;', '&#45;'),
+ array('&', '<', '>', '"', "'", '-'),
+ $str);
}
return $str;
@@ -227,20 +226,20 @@ if ( ! function_exists('entities_to_ascii'))
// ------------------------------------------------------------------------
-/**
- * Word Censoring Function
- *
- * Supply a string and an array of disallowed words and any
- * matched words will be converted to #### or to the replacement
- * word you've submitted.
- *
- * @param string the text string
- * @param string the array of censoered words
- * @param string the optional replacement value
- * @return string
- */
if ( ! function_exists('word_censor'))
{
+ /**
+ * Word Censoring Function
+ *
+ * Supply a string and an array of disallowed words and any
+ * matched words will be converted to #### or to the replacement
+ * word you've submitted.
+ *
+ * @param string the text string
+ * @param string the array of censoered words
+ * @param string the optional replacement value
+ * @return string
+ */
function word_censor($str, $censored, $replacement = '')
{
if ( ! is_array($censored))
@@ -258,7 +257,7 @@ if ( ! function_exists('word_censor'))
foreach ($censored as $badword)
{
- if ($replacement != '')
+ if ($replacement !== '')
{
$str = preg_replace("/({$delim})(".str_replace('\*', '\w*?', preg_quote($badword, '/')).")({$delim})/i", "\\1{$replacement}\\3", $str);
}
@@ -274,39 +273,45 @@ if ( ! function_exists('word_censor'))
// ------------------------------------------------------------------------
-/**
- * Code Highlighter
- *
- * Colorizes code strings
- *
- * @param string the text string
- * @return string
- */
if ( ! function_exists('highlight_code'))
{
+ /**
+ * Code Highlighter
+ *
+ * Colorizes code strings
+ *
+ * @param string the text string
+ * @return string
+ */
function highlight_code($str)
{
- // The highlight string function encodes and highlights
- // brackets so we need them to start raw
- $str = str_replace(array('&lt;', '&gt;'), array('<', '>'), $str);
-
- // Replace any existing PHP tags to temporary markers so they don't accidentally
- // break the string out of PHP, and thus, thwart the highlighting.
- $str = str_replace(array('<?', '?>', '<%', '%>', '\\', '</script>'),
- array('phptagopen', 'phptagclose', 'asptagopen', 'asptagclose', 'backslashtmp', 'scriptclose'),
+ /* The highlight string function encodes and highlights
+ * brackets so we need them to start raw.
+ *
+ * Also replace any existing PHP tags to temporary markers
+ * so they don't accidentally break the string out of PHP,
+ * and thus, thwart the highlighting.
+ */
+ $str = str_replace(array('&lt;', '&gt;', '<?', '?>', '<%', '%>', '\\', '</script>'),
+ array('<', '>', 'phptagopen', 'phptagclose', 'asptagopen', 'asptagclose', 'backslashtmp', 'scriptclose'),
$str);
// The highlight_string function requires that the text be surrounded
// by PHP tags, which we will remove later
- $str = '<?php '.$str.' ?>'; // <?
-
- // All the magic happens here, baby!
- $str = highlight_string($str, TRUE);
+ $str = highlight_string('<?php '.$str.' ?>', TRUE);
// Remove our artificially added PHP, and the syntax highlighting that came with it
- $str = preg_replace('/<span style="color: #([A-Z0-9]+)">&lt;\?php(&nbsp;| )/i', '<span style="color: #$1">', $str);
- $str = preg_replace('/(<span style="color: #[A-Z0-9]+">.*?)\?&gt;<\/span>\n<\/span>\n<\/code>/is', "$1</span>\n</span>\n</code>", $str);
- $str = preg_replace('/<span style="color: #[A-Z0-9]+"\><\/span>/i', '', $str);
+ $str = preg_replace(array(
+ '/<span style="color: #([A-Z0-9]+)">&lt;\?php(&nbsp;| )/i',
+ '/(<span style="color: #[A-Z0-9]+">.*?)\?&gt;<\/span>\n<\/span>\n<\/code>/is',
+ '/<span style="color: #[A-Z0-9]+"\><\/span>/i'
+ ),
+ array(
+ '<span style="color: #$1">',
+ "$1</span>\n</span>\n</code>",
+ ''
+ ),
+ $str);
// Replace our markers back to PHP tags.
return str_replace(array('phptagopen', 'phptagclose', 'asptagopen', 'asptagclose', 'backslashtmp', 'scriptclose'),
@@ -317,29 +322,29 @@ if ( ! function_exists('highlight_code'))
// ------------------------------------------------------------------------
-/**
- * Phrase Highlighter
- *
- * Highlights a phrase within a text string
- *
- * @param string the text string
- * @param string the phrase you'd like to highlight
- * @param string the openging tag to precede the phrase with
- * @param string the closing tag to end the phrase with
- * @return string
- */
if ( ! function_exists('highlight_phrase'))
{
+ /**
+ * Phrase Highlighter
+ *
+ * Highlights a phrase within a text string
+ *
+ * @param string the text string
+ * @param string the phrase you'd like to highlight
+ * @param string the openging tag to precede the phrase with
+ * @param string the closing tag to end the phrase with
+ * @return string
+ */
function highlight_phrase($str, $phrase, $tag_open = '<strong>', $tag_close = '</strong>')
{
- if ($str == '')
+ if ($str === '')
{
return '';
}
- if ($phrase != '')
+ if ($phrase !== '')
{
- return preg_replace('/('.preg_quote($phrase, '/').')/i', $tag_open."\\1".$tag_close, $str);
+ return preg_replace('/('.preg_quote($phrase, '/').')/i', $tag_open.'\\1'.$tag_close, $str);
}
return $str;
@@ -348,28 +353,33 @@ if ( ! function_exists('highlight_phrase'))
// ------------------------------------------------------------------------
-/**
- * Convert Accented Foreign Characters to ASCII
- *
- * @param string the text string
- * @return string
- */
if ( ! function_exists('convert_accented_characters'))
{
+ /**
+ * Convert Accented Foreign Characters to ASCII
+ *
+ * @param string the text string
+ * @return string
+ */
function convert_accented_characters($str)
{
- if (defined('ENVIRONMENT') && is_file(APPPATH.'config/'.ENVIRONMENT.'/foreign_chars.php'))
- {
- include(APPPATH.'config/'.ENVIRONMENT.'/foreign_chars.php');
- }
- elseif (is_file(APPPATH.'config/foreign_chars.php'))
- {
- include(APPPATH.'config/foreign_chars.php');
- }
+ global $foreign_characters;
- if ( ! isset($foreign_characters))
+ if ( ! isset($foreign_characters) OR ! is_array($foreign_characters))
{
- return $str;
+ if (defined('ENVIRONMENT') && is_file(APPPATH.'config/'.ENVIRONMENT.'/foreign_chars.php'))
+ {
+ include(APPPATH.'config/'.ENVIRONMENT.'/foreign_chars.php');
+ }
+ elseif (is_file(APPPATH.'config/foreign_chars.php'))
+ {
+ include(APPPATH.'config/foreign_chars.php');
+ }
+
+ if ( ! isset($foreign_characters) OR ! is_array($foreign_characters))
+ {
+ return $str;
+ }
}
return preg_replace(array_keys($foreign_characters), array_values($foreign_characters), $str);
@@ -378,27 +388,29 @@ if ( ! function_exists('convert_accented_characters'))
// ------------------------------------------------------------------------
-/**
- * Word Wrap
- *
- * Wraps text at the specified character. Maintains the integrity of words.
- * Anything placed between {unwrap}{/unwrap} will not be word wrapped, nor
- * will URLs.
- *
- * @param string the text string
- * @param int the number of characters to wrap at
- * @return string
- */
if ( ! function_exists('word_wrap'))
{
- function word_wrap($str, $charlim = '76')
+ /**
+ * Word Wrap
+ *
+ * Wraps text at the specified character. Maintains the integrity of words.
+ * Anything placed between {unwrap}{/unwrap} will not be word wrapped, nor
+ * will URLs.
+ *
+ * @param string $str the text string
+ * @param int $charlim = 76 the number of characters to wrap at
+ * @return string
+ */
+ function word_wrap($str, $charlim = 76)
{
- // Se the character limit
+ // Set the character limit
if ( ! is_numeric($charlim))
+ {
$charlim = 76;
+ }
// Reduce multiple spaces
- $str = preg_replace("| +|", " ", $str);
+ $str = preg_replace('| +|', ' ', $str);
// Standardize newlines
if (strpos($str, "\r") !== FALSE)
@@ -409,22 +421,22 @@ if ( ! function_exists('word_wrap'))
// If the current word is surrounded by {unwrap} tags we'll
// strip the entire chunk and replace it with a marker.
$unwrap = array();
- if (preg_match_all("|(\{unwrap\}.+?\{/unwrap\})|s", $str, $matches))
+ if (preg_match_all('|(\{unwrap\}.+?\{/unwrap\})|s', $str, $matches))
{
- for ($i = 0; $i < count($matches['0']); $i++)
+ for ($i = 0, $c = count($matches[0]); $i < $c; $i++)
{
- $unwrap[] = $matches['1'][$i];
- $str = str_replace($matches['1'][$i], "{{unwrapped".$i."}}", $str);
+ $unwrap[] = $matches[1][$i];
+ $str = str_replace($matches[1][$i], '{{unwrapped'.$i.'}}', $str);
}
}
// Use PHP's native function to do the initial wordwrap.
// We set the cut flag to FALSE so that any individual words that are
- // too long get left alone. In the next step we'll deal with them.
+ // too long get left alone. In the next step we'll deal with them.
$str = wordwrap($str, $charlim, "\n", FALSE);
// Split the string into individual lines of text and cycle through them
- $output = "";
+ $output = '';
foreach (explode("\n", $str) as $line)
{
// Is the line within the allowed character count?
@@ -439,28 +451,26 @@ if ( ! function_exists('word_wrap'))
while ((strlen($line)) > $charlim)
{
// If the over-length word is a URL we won't wrap it
- if (preg_match("!\[url.+\]|://|wwww.!", $line))
+ if (preg_match('!\[url.+\]|://|wwww.!', $line))
{
break;
}
// Trim the word down
- $temp .= substr($line, 0, $charlim-1);
- $line = substr($line, $charlim-1);
+ $temp .= substr($line, 0, $charlim - 1);
+ $line = substr($line, $charlim - 1);
}
// If $temp contains data it means we had to split up an over-length
// word into smaller chunks so we'll add it back to our current line
- if ($temp != '')
+ if ($temp !== '')
{
- $output .= $temp."\n".$line;
+ $output .= $temp."\n".$line."\n";
}
else
{
- $output .= $line;
+ $output .= $line."\n";
}
-
- $output .= "\n";
}
// Put our markers back
@@ -468,32 +478,30 @@ if ( ! function_exists('word_wrap'))
{
foreach ($unwrap as $key => $val)
{
- $output = str_replace("{{unwrapped".$key."}}", $val, $output);
+ $output = str_replace('{{unwrapped'.$key.'}}', $val, $output);
}
}
- // Remove the unwrap tags
- $output = str_replace(array('{unwrap}', '{/unwrap}'), '', $output);
-
- return $output;
+ // Remove the unwrap tags and return
+ return str_replace(array('{unwrap}', '{/unwrap}'), '', $output);
}
}
// ------------------------------------------------------------------------
-/**
- * Ellipsize String
- *
- * This function will strip tags from a string, split it at its max_length and ellipsize
- *
- * @param string string to ellipsize
- * @param int max length of string
- * @param mixed int (1|0) or float, .5, .2, etc for position to split
- * @param string ellipsis ; Default '...'
- * @return string ellipsized string
- */
if ( ! function_exists('ellipsize'))
{
+ /**
+ * Ellipsize String
+ *
+ * This function will strip tags from a string, split it at its max_length and ellipsize
+ *
+ * @param string string to ellipsize
+ * @param int max length of string
+ * @param mixed int (1|0) or float, .5, .2, etc for position to split
+ * @param string ellipsis ; Default '...'
+ * @return string ellipsized string
+ */
function ellipsize($str, $max_length, $position = 1, $ellipsis = '&hellip;')
{
// Strip tags
@@ -506,7 +514,6 @@ if ( ! function_exists('ellipsize'))
}
$beg = substr($str, 0, floor($max_length * $position));
-
$position = ($position > 1) ? 1 : $position;
if ($position === 1)
diff --git a/system/helpers/typography_helper.php b/system/helpers/typography_helper.php
index 7a3db5d6b..48f1f1147 100644
--- a/system/helpers/typography_helper.php
+++ b/system/helpers/typography_helper.php
@@ -1,4 +1,4 @@
-<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');
+<?php
/**
* CodeIgniter
*
@@ -24,6 +24,7 @@
* @since Version 1.0
* @filesource
*/
+defined('BASEPATH') OR exit('No direct script access allowed');
/**
* CodeIgniter Typography Helpers
@@ -37,14 +38,14 @@
// ------------------------------------------------------------------------
-/**
- * Convert newlines to HTML line breaks except within PRE tags
- *
- * @param string
- * @return string
- */
if ( ! function_exists('nl2br_except_pre'))
{
+ /**
+ * Convert newlines to HTML line breaks except within PRE tags
+ *
+ * @param string
+ * @return string
+ */
function nl2br_except_pre($str)
{
$CI =& get_instance();
@@ -55,38 +56,36 @@ if ( ! function_exists('nl2br_except_pre'))
// ------------------------------------------------------------------------
-/**
- * Auto Typography Wrapper Function
- *
- * @param string
- * @param bool whether to allow javascript event handlers
- * @param bool whether to reduce multiple instances of double newlines to two
- * @return string
- */
if ( ! function_exists('auto_typography'))
{
- function auto_typography($str, $strip_js_event_handlers = TRUE, $reduce_linebreaks = FALSE)
+ /**
+ * Auto Typography Wrapper Function
+ *
+ * @param string $str
+ * @param bool $reduce_linebreaks = FALSE whether to reduce multiple instances of double newlines to two
+ * @return string
+ */
+ function auto_typography($str, $reduce_linebreaks = FALSE)
{
$CI =& get_instance();
$CI->load->library('typography');
- return $CI->typography->auto_typography($str, $strip_js_event_handlers, $reduce_linebreaks);
+ return $CI->typography->auto_typography($str, $reduce_linebreaks);
}
}
-
// --------------------------------------------------------------------
-/**
- * HTML Entities Decode
- *
- * This function is a replacement for html_entity_decode()
- *
- * @param string
- * @param string
- * @return string
- */
if ( ! function_exists('entity_decode'))
{
+ /**
+ * HTML Entities Decode
+ *
+ * This function is a replacement for html_entity_decode()
+ *
+ * @param string
+ * @param string
+ * @return string
+ */
function entity_decode($str, $charset = NULL)
{
global $SEC;
diff --git a/system/helpers/url_helper.php b/system/helpers/url_helper.php
index 5576c2748..36ff0ff2c 100644
--- a/system/helpers/url_helper.php
+++ b/system/helpers/url_helper.php
@@ -1,4 +1,4 @@
-<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');
+<?php
/**
* CodeIgniter
*
@@ -24,6 +24,7 @@
* @since Version 1.0
* @filesource
*/
+defined('BASEPATH') OR exit('No direct script access allowed');
/**
* CodeIgniter URL Helpers
@@ -37,17 +38,17 @@
// ------------------------------------------------------------------------
-/**
- * Site URL
- *
- * Create a local URL based on your basepath. Segments can be passed via the
- * first parameter either as a string or an array.
- *
- * @param string
- * @return string
- */
if ( ! function_exists('site_url'))
{
+ /**
+ * Site URL
+ *
+ * Create a local URL based on your basepath. Segments can be passed via the
+ * first parameter either as a string or an array.
+ *
+ * @param string
+ * @return string
+ */
function site_url($uri = '')
{
$CI =& get_instance();
@@ -57,18 +58,18 @@ if ( ! function_exists('site_url'))
// ------------------------------------------------------------------------
-/**
- * Base URL
- *
- * Create a local URL based on your basepath.
- * Segments can be passed in as a string or an array, same as site_url
- * or a URL to a file can be passed in, e.g. to an image file.
- *
- * @param string
- * @return string
- */
if ( ! function_exists('base_url'))
{
+ /**
+ * Base URL
+ *
+ * Create a local URL based on your basepath.
+ * Segments can be passed in as a string or an array, same as site_url
+ * or a URL to a file can be passed in, e.g. to an image file.
+ *
+ * @param string
+ * @return string
+ */
function base_url($uri = '')
{
$CI =& get_instance();
@@ -78,16 +79,16 @@ if ( ! function_exists('base_url'))
// ------------------------------------------------------------------------
-/**
- * Current URL
- *
- * Returns the full URL (including segments) of the page where this
- * function is placed
- *
- * @return string
- */
if ( ! function_exists('current_url'))
{
+ /**
+ * Current URL
+ *
+ * Returns the full URL (including segments) of the page where this
+ * function is placed
+ *
+ * @return string
+ */
function current_url()
{
$CI =& get_instance();
@@ -96,15 +97,16 @@ if ( ! function_exists('current_url'))
}
// ------------------------------------------------------------------------
-/**
- * URL String
- *
- * Returns the URI segments.
- *
- * @return string
- */
+
if ( ! function_exists('uri_string'))
{
+ /**
+ * URL String
+ *
+ * Returns the URI segments.
+ *
+ * @return string
+ */
function uri_string()
{
$CI =& get_instance();
@@ -114,15 +116,15 @@ if ( ! function_exists('uri_string'))
// ------------------------------------------------------------------------
-/**
- * Index page
- *
- * Returns the "index_page" from your config file
- *
- * @return string
- */
if ( ! function_exists('index_page'))
{
+ /**
+ * Index page
+ *
+ * Returns the "index_page" from your config file
+ *
+ * @return string
+ */
function index_page()
{
$CI =& get_instance();
@@ -132,39 +134,39 @@ if ( ! function_exists('index_page'))
// ------------------------------------------------------------------------
-/**
- * Anchor Link
- *
- * Creates an anchor based on the local URL.
- *
- * @param string the URL
- * @param string the link title
- * @param mixed any attributes
- * @return string
- */
if ( ! function_exists('anchor'))
{
+ /**
+ * Anchor Link
+ *
+ * Creates an anchor based on the local URL.
+ *
+ * @param string the URL
+ * @param string the link title
+ * @param mixed any attributes
+ * @return string
+ */
function anchor($uri = '', $title = '', $attributes = '')
{
$title = (string) $title;
if ( ! is_array($uri))
{
- $site_url = preg_match('!^\w+://! i', $uri) ? $uri : site_url($uri);
+ $site_url = preg_match('#^(\w+:)?//#i', $uri) ? $uri : site_url($uri);
}
else
{
$site_url = site_url($uri);
}
- if ($title == '')
+ if ($title === '')
{
$title = $site_url;
}
- if ($attributes != '')
+ if ($attributes !== '')
{
- $attributes = _parse_attributes($attributes);
+ $attributes = _stringify_attributes($attributes);
}
return '<a href="'.$site_url.'"'.$attributes.'>'.$title.'</a>';
@@ -173,98 +175,105 @@ if ( ! function_exists('anchor'))
// ------------------------------------------------------------------------
-/**
- * Anchor Link - Pop-up version
- *
- * Creates an anchor based on the local URL. The link
- * opens a new window based on the attributes specified.
- *
- * @param string the URL
- * @param string the link title
- * @param mixed any attributes
- * @return string
- */
if ( ! function_exists('anchor_popup'))
{
+ /**
+ * Anchor Link - Pop-up version
+ *
+ * Creates an anchor based on the local URL. The link
+ * opens a new window based on the attributes specified.
+ *
+ * @param string the URL
+ * @param string the link title
+ * @param mixed any attributes
+ * @return string
+ */
function anchor_popup($uri = '', $title = '', $attributes = FALSE)
{
$title = (string) $title;
- $site_url = preg_match('!^\w+://! i', $uri) ? $uri : site_url($uri);
+ $site_url = preg_match('#^(\w+:)?//#i', $uri) ? $uri : site_url($uri);
- if ($title == '')
+ if ($title === '')
{
$title = $site_url;
}
if ($attributes === FALSE)
{
- return "<a href='javascript:void(0);' onclick=\"window.open('".$site_url."', '_blank');\">".$title.'</a>';
+ return '<a href="'.$site_url.'" onclick="window.open(\''.$site_url."', '_blank'); return false;\">".$title.'</a>';
}
if ( ! is_array($attributes))
{
- $attributes = array();
+ $attributes = array($attributes);
+
+ // Ref: http://www.w3schools.com/jsref/met_win_open.asp
+ $window_name = '_blank';
+ }
+ elseif ( ! empty($attributes['window_name']))
+ {
+ $window_name = $attributes['window_name'];
+ unset($attributes['window_name']);
}
- foreach (array('width' => '800', 'height' => '600', 'scrollbars' => 'yes', 'status' => 'yes', 'resizable' => 'yes', 'screenx' => '0', 'screeny' => '0', ) as $key => $val)
+ foreach (array('width' => '800', 'height' => '600', 'scrollbars' => 'yes', 'status' => 'yes', 'resizable' => 'yes', 'screenx' => '0', 'screeny' => '0') as $key => $val)
{
$atts[$key] = isset($attributes[$key]) ? $attributes[$key] : $val;
unset($attributes[$key]);
}
- if ($attributes != '')
- {
- $attributes = _parse_attributes($attributes);
- }
+ $attributes = _stringify_attributes($attributes);
- return "<a href='javascript:void(0);' onclick=\"window.open('".$site_url."', '_blank', '"._parse_attributes($atts, TRUE)."');\"".$attributes.'>'.$title.'</a>';
+ return '<a href="'.$site_url
+ .'" onclick="window.open(\''.$site_url."', '".$window_name."', '"._stringify_attributes($atts, TRUE)."'); return false;\""
+ .$attributes.'>'.$title.'</a>';
}
}
// ------------------------------------------------------------------------
-/**
- * Mailto Link
- *
- * @param string the email address
- * @param string the link title
- * @param mixed any attributes
- * @return string
- */
if ( ! function_exists('mailto'))
{
+ /**
+ * Mailto Link
+ *
+ * @param string the email address
+ * @param string the link title
+ * @param mixed any attributes
+ * @return string
+ */
function mailto($email, $title = '', $attributes = '')
{
$title = (string) $title;
- if ($title == '')
+ if ($title === '')
{
$title = $email;
}
- return '<a href="mailto:'.$email.'"'._parse_attributes($attributes).'>'.$title.'</a>';
+ return '<a href="mailto:'.$email.'"'._stringify_attributes($attributes).'>'.$title.'</a>';
}
}
// ------------------------------------------------------------------------
-/**
- * Encoded Mailto Link
- *
- * Create a spam-protected mailto link written in Javascript
- *
- * @param string the email address
- * @param string the link title
- * @param mixed any attributes
- * @return string
- */
if ( ! function_exists('safe_mailto'))
{
+ /**
+ * Encoded Mailto Link
+ *
+ * Create a spam-protected mailto link written in Javascript
+ *
+ * @param string the email address
+ * @param string the link title
+ * @param mixed any attributes
+ * @return string
+ */
function safe_mailto($email, $title = '', $attributes = '')
{
$title = (string) $title;
- if ($title == '')
+ if ($title === '')
{
$title = $email;
}
@@ -278,13 +287,13 @@ if ( ! function_exists('safe_mailto'))
$x[] = '"';
- if ($attributes != '')
+ if ($attributes !== '')
{
if (is_array($attributes))
{
foreach ($attributes as $key => $val)
{
- $x[] = ' '.$key.'="';
+ $x[] = ' '.$key.'="';
for ($i = 0, $l = strlen($val); $i < $l; $i++)
{
$x[] = '|'.ord($val[$i]);
@@ -344,7 +353,7 @@ if ( ! function_exists('safe_mailto'))
for ($i = 0, $c = count($x); $i < $c; $i++) { ?>l[<?php echo $i; ?>]='<?php echo $x[$i]; ?>';<?php } ?>
for (var i = l.length-1; i >= 0; i=i-1){
- if (l[i].substring(0, 1) == '|') document.write("&#"+unescape(l[i].substring(1))+";");
+ if (l[i].substring(0, 1) === '|') document.write("&#"+unescape(l[i].substring(1))+";");
else document.write(unescape(l[i]));}
//]]>
</script><?php
@@ -357,21 +366,21 @@ if ( ! function_exists('safe_mailto'))
// ------------------------------------------------------------------------
-/**
- * Auto-linker
- *
- * Automatically links URL and Email addresses.
- * Note: There's a bit of extra code here to deal with
- * URLs or emails that end in a period. We'll strip these
- * off and add them after the link.
- *
- * @param string the string
- * @param string the type: email, url, or both
- * @param bool whether to create pop-up links
- * @return string
- */
if ( ! function_exists('auto_link'))
{
+ /**
+ * Auto-linker
+ *
+ * Automatically links URL and Email addresses.
+ * Note: There's a bit of extra code here to deal with
+ * URLs or emails that end in a period. We'll strip these
+ * off and add them after the link.
+ *
+ * @param string the string
+ * @param string the type: email, url, or both
+ * @param bool whether to create pop-up links
+ * @return string
+ */
function auto_link($str, $type = 'both', $popup = FALSE)
{
if ($type !== 'email' && preg_match_all('#(^|\s|\(|\b)((http(s?)://)|(www\.))(\w+[^\s\)\<]+)#i', $str, $matches))
@@ -380,40 +389,43 @@ if ( ! function_exists('auto_link'))
for ($i = 0, $c = count($matches[0]); $i < $c; $i++)
{
- if (preg_match('|\.$|', $matches[6][$i]))
+ if (preg_match('/(\.|\,)$/i', $matches[6][$i], $m))
{
- $period = '.';
+ $punct = $m[1];
$matches[6][$i] = substr($matches[6][$i], 0, -1);
}
else
{
- $period = '';
+ $punct = '';
}
$str = str_replace($matches[0][$i],
$matches[1][$i].'<a href="http'.$matches[4][$i].'://'
.$matches[5][$i].$matches[6][$i].'"'.$pop.'>http'
.$matches[4][$i].'://'.$matches[5][$i]
- .$matches[6][$i].'</a>'.$period,
+ .$matches[6][$i].'</a>'.$punct,
$str);
}
}
- if ($type !== 'url' && preg_match_all('/([a-zA-Z0-9_\.\-\+]+)@([a-zA-Z0-9\-]+)\.([a-zA-Z0-9\-\.]*)/i', $str, $matches))
+ if ($type !== 'url' && preg_match_all('/([a-zA-Z0-9_\.\-\+]+)@([a-zA-Z0-9\-]+)\.([a-zA-Z0-9\-\.]+)/i', $str, $matches))
{
for ($i = 0, $c = count($matches); $i < $c; $i++)
{
- if (preg_match('|\.$|', $matches[3][$i]))
+ if (preg_match('/(\.|\,)$/i', $matches[3][$i], $m))
{
- $period = '.';
+ $punct = $m[1];
$matches[3][$i] = substr($matches[3][$i], 0, -1);
}
else
{
- $period = '';
+ $punct = '';
}
- $str = str_replace($matches[0][$i], safe_mailto($matches[1][$i].'@'.$matches[2][$i].'.'.$matches[3][$i]).$period, $str);
+ if (filter_var(($m = $matches[1][$i].'@'.$matches[2][$i].'.'.$matches[3][$i]), FILTER_VALIDATE_EMAIL) !== FALSE)
+ {
+ $str = str_replace($matches[0][$i], safe_mailto($m).$punct, $str);
+ }
}
}
@@ -423,19 +435,19 @@ if ( ! function_exists('auto_link'))
// ------------------------------------------------------------------------
-/**
- * Prep URL
- *
- * Simply adds the http:// part if no scheme is included
- *
- * @param string the URL
- * @return string
- */
if ( ! function_exists('prep_url'))
{
+ /**
+ * Prep URL
+ *
+ * Simply adds the http:// part if no scheme is included
+ *
+ * @param string the URL
+ * @return string
+ */
function prep_url($str = '')
{
- if ($str === 'http://' OR $str == '')
+ if ($str === 'http://' OR $str === '')
{
return '';
}
@@ -453,20 +465,22 @@ if ( ! function_exists('prep_url'))
// ------------------------------------------------------------------------
-/**
- * Create URL Title
- *
- * Takes a "title" string as input and creates a
- * human-friendly URL string with a "separator" string
- * as the word separator.
- *
- * @param string the string
- * @param string the separator
- * @param bool
- * @return string
- */
if ( ! function_exists('url_title'))
{
+ /**
+ * Create URL Title
+ *
+ * Takes a "title" string as input and creates a
+ * human-friendly URL string with a "separator" string
+ * as the word separator.
+ *
+ * @todo Remove old 'dash' and 'underscore' usage in 3.1+.
+ * @param string $str Input string
+ * @param string $separator Word separator
+ * (usually '-' or '_')
+ * @param bool $lowercase Wether to transform the output string to lowercase
+ * @return string
+ */
function url_title($str, $separator = '-', $lowercase = FALSE)
{
if ($separator === 'dash')
@@ -478,7 +492,7 @@ if ( ! function_exists('url_title'))
$separator = '_';
}
- $q_separator = preg_quote($separator);
+ $q_separator = preg_quote($separator, '#');
$trans = array(
'&.+?;' => '',
@@ -504,86 +518,54 @@ if ( ! function_exists('url_title'))
// ------------------------------------------------------------------------
-/**
- * Header Redirect
- *
- * Header redirect in two flavors
- * For very fine grained control over headers, you could use the Output
- * Library's set_header() function.
- *
- * @param string the URL
- * @param string the method: location or refresh
- * @return string
- */
if ( ! function_exists('redirect'))
{
- function redirect($uri = '', $method = 'auto', $http_response_code = 302)
+ /**
+ * Header Redirect
+ *
+ * Header redirect in two flavors
+ * For very fine grained control over headers, you could use the Output
+ * Library's set_header() function.
+ *
+ * @param string $uri URL
+ * @param string $method Redirect method
+ * 'auto', 'location' or 'refresh'
+ * @param int $code HTTP Response status code
+ * @return void
+ */
+ function redirect($uri = '', $method = 'auto', $code = NULL)
{
- if ( ! preg_match('#^https?://#i', $uri))
+ if ( ! preg_match('#^(\w+:)?//#i', $uri))
{
$uri = site_url($uri);
}
// IIS environment likely? Use 'refresh' for better compatibility
- if (DIRECTORY_SEPARATOR !== '/' && $method === 'auto')
+ if ($method === 'auto' && isset($_SERVER['SERVER_SOFTWARE']) && strpos($_SERVER['SERVER_SOFTWARE'], 'Microsoft-IIS') !== FALSE)
{
$method = 'refresh';
}
+ elseif ($method !== 'refresh' && (empty($code) OR ! is_numeric($code)))
+ {
+ // Reference: http://en.wikipedia.org/wiki/Post/Redirect/Get
+ $code = (isset($_SERVER['REQUEST_METHOD'], $_SERVER['SERVER_PROTOCOL'])
+ && $_SERVER['REQUEST_METHOD'] === 'POST'
+ && $_SERVER['SERVER_PROTOCOL'] === 'HTTP/1.1')
+ ? 303 : 302;
+ }
- switch($method)
+ switch ($method)
{
case 'refresh':
header('Refresh:0;url='.$uri);
break;
default:
- header('Location: '.$uri, TRUE, $http_response_code);
+ header('Location: '.$uri, TRUE, $code);
break;
}
exit;
}
}
-// ------------------------------------------------------------------------
-
-/**
- * Parse out the attributes
- *
- * Some of the functions use this
- *
- * @param array
- * @param bool
- * @return string
- */
-if ( ! function_exists('_parse_attributes'))
-{
- function _parse_attributes($attributes, $javascript = FALSE)
- {
- if (is_string($attributes))
- {
- return ($attributes != '') ? ' '.$attributes : '';
- }
-
- $att = '';
- foreach ($attributes as $key => $val)
- {
- if ($javascript == TRUE)
- {
- $att .= $key.'='.$val.',';
- }
- else
- {
- $att .= ' '.$key.'="'.$val.'"';
- }
- }
-
- if ($javascript == TRUE && $att != '')
- {
- return substr($att, 0, -1);
- }
-
- return $att;
- }
-}
-
/* End of file url_helper.php */
/* Location: ./system/helpers/url_helper.php */ \ No newline at end of file
diff --git a/system/helpers/xml_helper.php b/system/helpers/xml_helper.php
index 67fd34b97..c3dfdcddb 100644
--- a/system/helpers/xml_helper.php
+++ b/system/helpers/xml_helper.php
@@ -1,4 +1,4 @@
-<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');
+<?php
/**
* CodeIgniter
*
@@ -24,6 +24,7 @@
* @since Version 1.0
* @filesource
*/
+defined('BASEPATH') OR exit('No direct script access allowed');
/**
* CodeIgniter XML Helpers
@@ -37,15 +38,15 @@
// ------------------------------------------------------------------------
-/**
- * Convert Reserved XML characters to Entities
- *
- * @param string
- * @param bool
- * @return string
- */
if ( ! function_exists('xml_convert'))
{
+ /**
+ * Convert Reserved XML characters to Entities
+ *
+ * @param string
+ * @param bool
+ * @return string
+ */
function xml_convert($str, $protect_all = FALSE)
{
$temp = '__TEMP_AMPERSANDS__';
@@ -54,7 +55,7 @@ if ( ! function_exists('xml_convert'))
// ampersands won't get messed up
$str = preg_replace('/&#(\d+);/', $temp.'\\1;', $str);
- if ($protect_all == TRUE)
+ if ($protect_all === TRUE)
{
$str = preg_replace('/&(\w+);/', $temp.'\\1;', $str);
}
@@ -66,7 +67,7 @@ if ( ! function_exists('xml_convert'))
// Decode the temp markers back to entities
$str = preg_replace('/'.$temp.'(\d+);/', '&#\\1;', $str);
- if ($protect_all == TRUE)
+ if ($protect_all === TRUE)
{
return preg_replace('/'.$temp.'(\w+);/', '&\\1;', $str);
}
diff --git a/system/language/english/calendar_lang.php b/system/language/english/calendar_lang.php
index 2d477e6c8..288eb91d8 100644
--- a/system/language/english/calendar_lang.php
+++ b/system/language/english/calendar_lang.php
@@ -5,9 +5,9 @@
* An open source application development framework for PHP 5.2.4 or newer
*
* NOTICE OF LICENSE
- *
+ *
* Licensed under the Open Software License version 3.0
- *
+ *
* This source file is subject to the Open Software License (OSL 3.0) that is
* bundled with this package in the files license.txt / license.rst. It is
* also available through the world wide web at this URL:
@@ -24,53 +24,53 @@
* @since Version 1.0
* @filesource
*/
+defined('BASEPATH') OR exit('No direct script access allowed');
-$lang['cal_su'] = "Su";
-$lang['cal_mo'] = "Mo";
-$lang['cal_tu'] = "Tu";
-$lang['cal_we'] = "We";
-$lang['cal_th'] = "Th";
-$lang['cal_fr'] = "Fr";
-$lang['cal_sa'] = "Sa";
-$lang['cal_sun'] = "Sun";
-$lang['cal_mon'] = "Mon";
-$lang['cal_tue'] = "Tue";
-$lang['cal_wed'] = "Wed";
-$lang['cal_thu'] = "Thu";
-$lang['cal_fri'] = "Fri";
-$lang['cal_sat'] = "Sat";
-$lang['cal_sunday'] = "Sunday";
-$lang['cal_monday'] = "Monday";
-$lang['cal_tuesday'] = "Tuesday";
-$lang['cal_wednesday'] = "Wednesday";
-$lang['cal_thursday'] = "Thursday";
-$lang['cal_friday'] = "Friday";
-$lang['cal_saturday'] = "Saturday";
-$lang['cal_jan'] = "Jan";
-$lang['cal_feb'] = "Feb";
-$lang['cal_mar'] = "Mar";
-$lang['cal_apr'] = "Apr";
-$lang['cal_may'] = "May";
-$lang['cal_jun'] = "Jun";
-$lang['cal_jul'] = "Jul";
-$lang['cal_aug'] = "Aug";
-$lang['cal_sep'] = "Sep";
-$lang['cal_oct'] = "Oct";
-$lang['cal_nov'] = "Nov";
-$lang['cal_dec'] = "Dec";
-$lang['cal_january'] = "January";
-$lang['cal_february'] = "February";
-$lang['cal_march'] = "March";
-$lang['cal_april'] = "April";
-$lang['cal_mayl'] = "May";
-$lang['cal_june'] = "June";
-$lang['cal_july'] = "July";
-$lang['cal_august'] = "August";
-$lang['cal_september'] = "September";
-$lang['cal_october'] = "October";
-$lang['cal_november'] = "November";
-$lang['cal_december'] = "December";
-
+$lang['cal_su'] = 'Su';
+$lang['cal_mo'] = 'Mo';
+$lang['cal_tu'] = 'Tu';
+$lang['cal_we'] = 'We';
+$lang['cal_th'] = 'Th';
+$lang['cal_fr'] = 'Fr';
+$lang['cal_sa'] = 'Sa';
+$lang['cal_sun'] = 'Sun';
+$lang['cal_mon'] = 'Mon';
+$lang['cal_tue'] = 'Tue';
+$lang['cal_wed'] = 'Wed';
+$lang['cal_thu'] = 'Thu';
+$lang['cal_fri'] = 'Fri';
+$lang['cal_sat'] = 'Sat';
+$lang['cal_sunday'] = 'Sunday';
+$lang['cal_monday'] = 'Monday';
+$lang['cal_tuesday'] = 'Tuesday';
+$lang['cal_wednesday'] = 'Wednesday';
+$lang['cal_thursday'] = 'Thursday';
+$lang['cal_friday'] = 'Friday';
+$lang['cal_saturday'] = 'Saturday';
+$lang['cal_jan'] = 'Jan';
+$lang['cal_feb'] = 'Feb';
+$lang['cal_mar'] = 'Mar';
+$lang['cal_apr'] = 'Apr';
+$lang['cal_may'] = 'May';
+$lang['cal_jun'] = 'Jun';
+$lang['cal_jul'] = 'Jul';
+$lang['cal_aug'] = 'Aug';
+$lang['cal_sep'] = 'Sep';
+$lang['cal_oct'] = 'Oct';
+$lang['cal_nov'] = 'Nov';
+$lang['cal_dec'] = 'Dec';
+$lang['cal_january'] = 'January';
+$lang['cal_february'] = 'February';
+$lang['cal_march'] = 'March';
+$lang['cal_april'] = 'April';
+$lang['cal_mayl'] = 'May';
+$lang['cal_june'] = 'June';
+$lang['cal_july'] = 'July';
+$lang['cal_august'] = 'August';
+$lang['cal_september'] = 'September';
+$lang['cal_october'] = 'October';
+$lang['cal_november'] = 'November';
+$lang['cal_december'] = 'December';
/* End of file calendar_lang.php */
/* Location: ./system/language/english/calendar_lang.php */ \ No newline at end of file
diff --git a/system/language/english/date_lang.php b/system/language/english/date_lang.php
index 533563700..db1e9e0ff 100644
--- a/system/language/english/date_lang.php
+++ b/system/language/english/date_lang.php
@@ -5,9 +5,9 @@
* An open source application development framework for PHP 5.2.4 or newer
*
* NOTICE OF LICENSE
- *
+ *
* Licensed under the Open Software License version 3.0
- *
+ *
* This source file is subject to the Open Software License (OSL 3.0) that is
* bundled with this package in the files license.txt / license.rst. It is
* also available through the world wide web at this URL:
@@ -24,21 +24,22 @@
* @since Version 1.0
* @filesource
*/
+defined('BASEPATH') OR exit('No direct script access allowed');
-$lang['date_year'] = "Year";
-$lang['date_years'] = "Years";
-$lang['date_month'] = "Month";
-$lang['date_months'] = "Months";
-$lang['date_week'] = "Week";
-$lang['date_weeks'] = "Weeks";
-$lang['date_day'] = "Day";
-$lang['date_days'] = "Days";
-$lang['date_hour'] = "Hour";
-$lang['date_hours'] = "Hours";
-$lang['date_minute'] = "Minute";
-$lang['date_minutes'] = "Minutes";
-$lang['date_second'] = "Second";
-$lang['date_seconds'] = "Seconds";
+$lang['date_year'] = 'Year';
+$lang['date_years'] = 'Years';
+$lang['date_month'] = 'Month';
+$lang['date_months'] = 'Months';
+$lang['date_week'] = 'Week';
+$lang['date_weeks'] = 'Weeks';
+$lang['date_day'] = 'Day';
+$lang['date_days'] = 'Days';
+$lang['date_hour'] = 'Hour';
+$lang['date_hours'] = 'Hours';
+$lang['date_minute'] = 'Minute';
+$lang['date_minutes'] = 'Minutes';
+$lang['date_second'] = 'Second';
+$lang['date_seconds'] = 'Seconds';
$lang['UM12'] = '(UTC -12:00) Baker/Howland Island';
$lang['UM11'] = '(UTC -11:00) Niue';
@@ -81,6 +82,5 @@ $lang['UP1275'] = '(UTC +12:45) Chatham Islands Standard Time';
$lang['UP13'] = '(UTC +13:00) Samoa Time Zone, Phoenix Islands Time, Tonga';
$lang['UP14'] = '(UTC +14:00) Line Islands';
-
/* End of file date_lang.php */
/* Location: ./system/language/english/date_lang.php */ \ No newline at end of file
diff --git a/system/language/english/db_lang.php b/system/language/english/db_lang.php
index a135d1aac..50ce6bbd6 100644
--- a/system/language/english/db_lang.php
+++ b/system/language/english/db_lang.php
@@ -5,9 +5,9 @@
* An open source application development framework for PHP 5.2.4 or newer
*
* NOTICE OF LICENSE
- *
+ *
* Licensed under the Open Software License version 3.0
- *
+ *
* This source file is subject to the Open Software License (OSL 3.0) that is
* bundled with this package in the files license.txt / license.rst. It is
* also available through the world wide web at this URL:
@@ -24,6 +24,7 @@
* @since Version 1.0
* @filesource
*/
+defined('BASEPATH') OR exit('No direct script access allowed');
$lang['db_invalid_connection_str'] = 'Unable to determine the database settings based on the connection string you submitted.';
$lang['db_unable_to_connect'] = 'Unable to connect to your database server using the provided settings.';
@@ -40,8 +41,8 @@ $lang['db_field_param_missing'] = 'To fetch fields requires the name of the tabl
$lang['db_unsupported_function'] = 'This feature is not available for the database you are using.';
$lang['db_transaction_failure'] = 'Transaction failure: Rollback performed.';
$lang['db_unable_to_drop'] = 'Unable to drop the specified database.';
-$lang['db_unsuported_feature'] = 'Unsupported feature of the database platform you are using.';
-$lang['db_unsuported_compression'] = 'The file compression format you chose is not supported by your server.';
+$lang['db_unsupported_feature'] = 'Unsupported feature of the database platform you are using.';
+$lang['db_unsupported_compression'] = 'The file compression format you chose is not supported by your server.';
$lang['db_filepath_error'] = 'Unable to write data to the file path you have submitted.';
$lang['db_invalid_cache_path'] = 'The cache path you submitted is not valid or writable.';
$lang['db_table_name_required'] = 'A table name is required for that operation.';
diff --git a/system/language/english/email_lang.php b/system/language/english/email_lang.php
index 23296a244..646a49647 100644
--- a/system/language/english/email_lang.php
+++ b/system/language/english/email_lang.php
@@ -5,9 +5,9 @@
* An open source application development framework for PHP 5.2.4 or newer
*
* NOTICE OF LICENSE
- *
+ *
* Licensed under the Open Software License version 3.0
- *
+ *
* This source file is subject to the Open Software License (OSL 3.0) that is
* bundled with this package in the files license.txt / license.rst. It is
* also available through the world wide web at this URL:
@@ -24,26 +24,26 @@
* @since Version 1.0
* @filesource
*/
+defined('BASEPATH') OR exit('No direct script access allowed');
-$lang['email_must_be_array'] = "The email validation method must be passed an array.";
-$lang['email_invalid_address'] = "Invalid email address: %s";
-$lang['email_attachment_missing'] = "Unable to locate the following email attachment: %s";
-$lang['email_attachment_unreadable'] = "Unable to open this attachment: %s";
-$lang['email_no_recipients'] = "You must include recipients: To, Cc, or Bcc";
-$lang['email_send_failure_phpmail'] = "Unable to send email using PHP mail(). Your server might not be configured to send mail using this method.";
-$lang['email_send_failure_sendmail'] = "Unable to send email using PHP Sendmail. Your server might not be configured to send mail using this method.";
-$lang['email_send_failure_smtp'] = "Unable to send email using PHP SMTP. Your server might not be configured to send mail using this method.";
-$lang['email_sent'] = "Your message has been successfully sent using the following protocol: %s";
-$lang['email_no_socket'] = "Unable to open a socket to Sendmail. Please check settings.";
-$lang['email_no_hostname'] = "You did not specify a SMTP hostname.";
-$lang['email_smtp_error'] = "The following SMTP error was encountered: %s";
-$lang['email_no_smtp_unpw'] = "Error: You must assign a SMTP username and password.";
-$lang['email_failed_smtp_login'] = "Failed to send AUTH LOGIN command. Error: %s";
-$lang['email_smtp_auth_un'] = "Failed to authenticate username. Error: %s";
-$lang['email_smtp_auth_pw'] = "Failed to authenticate password. Error: %s";
-$lang['email_smtp_data_failure'] = "Unable to send data: %s";
-$lang['email_exit_status'] = "Exit status code: %s";
-
+$lang['email_must_be_array'] = 'The email validation method must be passed an array.';
+$lang['email_invalid_address'] = 'Invalid email address: %s';
+$lang['email_attachment_missing'] = 'Unable to locate the following email attachment: %s';
+$lang['email_attachment_unreadable'] = 'Unable to open this attachment: %s';
+$lang['email_no_recipients'] = 'You must include recipients: To, Cc, or Bcc';
+$lang['email_send_failure_phpmail'] = 'Unable to send email using PHP mail(). Your server might not be configured to send mail using this method.';
+$lang['email_send_failure_sendmail'] = 'Unable to send email using PHP Sendmail. Your server might not be configured to send mail using this method.';
+$lang['email_send_failure_smtp'] = 'Unable to send email using PHP SMTP. Your server might not be configured to send mail using this method.';
+$lang['email_sent'] = 'Your message has been successfully sent using the following protocol: %s';
+$lang['email_no_socket'] = 'Unable to open a socket to Sendmail. Please check settings.';
+$lang['email_no_hostname'] = 'You did not specify a SMTP hostname.';
+$lang['email_smtp_error'] = 'The following SMTP error was encountered: %s';
+$lang['email_no_smtp_unpw'] = 'Error: You must assign a SMTP username and password.';
+$lang['email_failed_smtp_login'] = 'Failed to send AUTH LOGIN command. Error: %s';
+$lang['email_smtp_auth_un'] = 'Failed to authenticate username. Error: %s';
+$lang['email_smtp_auth_pw'] = 'Failed to authenticate password. Error: %s';
+$lang['email_smtp_data_failure'] = 'Unable to send data: %s';
+$lang['email_exit_status'] = 'Exit status code: %s';
/* End of file email_lang.php */
/* Location: ./system/language/english/email_lang.php */ \ No newline at end of file
diff --git a/system/language/english/form_validation_lang.php b/system/language/english/form_validation_lang.php
index 3d77e5eda..47c6bbd76 100644
--- a/system/language/english/form_validation_lang.php
+++ b/system/language/english/form_validation_lang.php
@@ -5,9 +5,9 @@
* An open source application development framework for PHP 5.2.4 or newer
*
* NOTICE OF LICENSE
- *
+ *
* Licensed under the Open Software License version 3.0
- *
+ *
* This source file is subject to the Open Software License (OSL 3.0) that is
* bundled with this package in the files license.txt / license.rst. It is
* also available through the world wide web at this URL:
@@ -24,31 +24,34 @@
* @since Version 1.0
* @filesource
*/
+defined('BASEPATH') OR exit('No direct script access allowed');
-$lang['required'] = 'The {field} field is required.';
-$lang['isset'] = 'The {field} field must have a value.';
-$lang['valid_email'] = 'The {field} field must contain a valid email address.';
-$lang['valid_emails'] = 'The {field} field must contain all valid email addresses.';
-$lang['valid_url'] = 'The {field} field must contain a valid URL.';
-$lang['valid_ip'] = 'The {field} field must contain a valid IP.';
-$lang['min_length'] = 'The {field} field must be at least {param} characters in length.';
-$lang['max_length'] = 'The {field} field cannot exceed {param} characters in length.';
-$lang['exact_length'] = 'The {field} field must be exactly {param} characters in length.';
-$lang['alpha'] = 'The {field} field may only contain alphabetical characters.';
-$lang['alpha_numeric'] = 'The {field} field may only contain alpha-numeric characters.';
-$lang['alpha_dash'] = 'The {field} field may only contain alpha-numeric characters, underscores, and dashes.';
-$lang['numeric'] = 'The {field} field must contain only numbers.';
-$lang['is_numeric'] = 'The {field} field must contain only numeric characters.';
-$lang['integer'] = 'The {field} field must contain an integer.';
-$lang['regex_match'] = 'The {field} field is not in the correct format.';
-$lang['matches'] = 'The {field} field does not match the {param} field.';
-$lang['is_unique'] = 'The {field} field must contain a unique value.';
-$lang['is_natural'] = 'The {field} field must contain an ordinary number greater or equal to zero.';
-$lang['is_natural_no_zero'] = 'The {field} field must contain an ordinary number greater than zero.';
-$lang['decimal'] = 'The {field} field must contain a decimal number.';
-$lang['less_than'] = 'The {field} field must contain a number less than {param}.';
-$lang['greater_than'] = 'The {field} field must contain a number greater than {param}.';
-
+$lang['required'] = 'The {field} field is required.';
+$lang['isset'] = 'The {field} field must have a value.';
+$lang['valid_email'] = 'The {field} field must contain a valid email address.';
+$lang['valid_emails'] = 'The {field} field must contain all valid email addresses.';
+$lang['valid_url'] = 'The {field} field must contain a valid URL.';
+$lang['valid_ip'] = 'The {field} field must contain a valid IP.';
+$lang['min_length'] = 'The {field} field must be at least {param} characters in length.';
+$lang['max_length'] = 'The {field} field cannot exceed {param} characters in length.';
+$lang['exact_length'] = 'The {field} field must be exactly {param} characters in length.';
+$lang['alpha'] = 'The {field} field may only contain alphabetical characters.';
+$lang['alpha_numeric'] = 'The {field} field may only contain alpha-numeric characters.';
+$lang['alpha_dash'] = 'The {field} field may only contain alpha-numeric characters, underscores, and dashes.';
+$lang['numeric'] = 'The {field} field must contain only numbers.';
+$lang['is_numeric'] = 'The {field} field must contain only numeric characters.';
+$lang['integer'] = 'The {field} field must contain an integer.';
+$lang['regex_match'] = 'The {field} field is not in the correct format.';
+$lang['matches'] = 'The {field} field does not match The {field} field.';
+$lang['differs'] = 'The {field} field must differ from The {field} field.';
+$lang['is_unique'] = 'The {field} field must contain a unique value.';
+$lang['is_natural'] = 'The {field} field must only contain digits.';
+$lang['is_natural_no_zero'] = 'The {field} field must only contain digits and must be greater than zero.';
+$lang['decimal'] = 'The {field} field must contain a decimal number.';
+$lang['less_than'] = 'The {field} field must contain a number less than {param}.';
+$lang['less_than_equal_to'] = 'The {field} field must contain a number less than or equal to {param}.';
+$lang['greater_than'] = 'The {field} field must contain a number greater than {param}.';
+$lang['greater_than_equal_to'] = 'The {field} field must contain a number greater than or equal to {param}.';
/* End of file form_validation_lang.php */
-/* Location: ./system/language/english/form_validation_lang.php */
+/* Location: ./system/language/english/form_validation_lang.php */ \ No newline at end of file
diff --git a/system/language/english/ftp_lang.php b/system/language/english/ftp_lang.php
index 4e39e43bf..090a88c28 100644
--- a/system/language/english/ftp_lang.php
+++ b/system/language/english/ftp_lang.php
@@ -5,9 +5,9 @@
* An open source application development framework for PHP 5.2.4 or newer
*
* NOTICE OF LICENSE
- *
+ *
* Licensed under the Open Software License version 3.0
- *
+ *
* This source file is subject to the Open Software License (OSL 3.0) that is
* bundled with this package in the files license.txt / license.rst. It is
* also available through the world wide web at this URL:
@@ -24,20 +24,20 @@
* @since Version 1.0
* @filesource
*/
+defined('BASEPATH') OR exit('No direct script access allowed');
-$lang['ftp_no_connection'] = "Unable to locate a valid connection ID. Please make sure you are connected before peforming any file routines.";
-$lang['ftp_unable_to_connect'] = "Unable to connect to your FTP server using the supplied hostname.";
-$lang['ftp_unable_to_login'] = "Unable to login to your FTP server. Please check your username and password.";
-$lang['ftp_unable_to_makdir'] = "Unable to create the directory you have specified.";
-$lang['ftp_unable_to_changedir'] = "Unable to change directories.";
-$lang['ftp_unable_to_chmod'] = "Unable to set file permissions. Please check your path. Note: This feature is only available in PHP 5 or higher.";
-$lang['ftp_unable_to_upload'] = "Unable to upload the specified file. Please check your path.";
-$lang['ftp_unable_to_download'] = "Unable to download the specified file. Please check your path.";
-$lang['ftp_no_source_file'] = "Unable to locate the source file. Please check your path.";
-$lang['ftp_unable_to_rename'] = "Unable to rename the file.";
-$lang['ftp_unable_to_delete'] = "Unable to delete the file.";
-$lang['ftp_unable_to_move'] = "Unable to move the file. Please make sure the destination directory exists.";
-
+$lang['ftp_no_connection'] = 'Unable to locate a valid connection ID. Please make sure you are connected before peforming any file routines.';
+$lang['ftp_unable_to_connect'] = 'Unable to connect to your FTP server using the supplied hostname.';
+$lang['ftp_unable_to_login'] = 'Unable to login to your FTP server. Please check your username and password.';
+$lang['ftp_unable_to_makdir'] = 'Unable to create the directory you have specified.';
+$lang['ftp_unable_to_changedir'] = 'Unable to change directories.';
+$lang['ftp_unable_to_chmod'] = 'Unable to set file permissions. Please check your path. Note: This feature is only available in PHP 5 or higher.';
+$lang['ftp_unable_to_upload'] = 'Unable to upload the specified file. Please check your path.';
+$lang['ftp_unable_to_download'] = 'Unable to download the specified file. Please check your path.';
+$lang['ftp_no_source_file'] = 'Unable to locate the source file. Please check your path.';
+$lang['ftp_unable_to_rename'] = 'Unable to rename the file.';
+$lang['ftp_unable_to_delete'] = 'Unable to delete the file.';
+$lang['ftp_unable_to_move'] = 'Unable to move the file. Please make sure the destination directory exists.';
/* End of file ftp_lang.php */
/* Location: ./system/language/english/ftp_lang.php */ \ No newline at end of file
diff --git a/system/language/english/imglib_lang.php b/system/language/english/imglib_lang.php
index 67ca94277..296c4af68 100644
--- a/system/language/english/imglib_lang.php
+++ b/system/language/english/imglib_lang.php
@@ -5,9 +5,9 @@
* An open source application development framework for PHP 5.2.4 or newer
*
* NOTICE OF LICENSE
- *
+ *
* Licensed under the Open Software License version 3.0
- *
+ *
* This source file is subject to the Open Software License (OSL 3.0) that is
* bundled with this package in the files license.txt / license.rst. It is
* also available through the world wide web at this URL:
@@ -24,26 +24,26 @@
* @since Version 1.0
* @filesource
*/
+defined('BASEPATH') OR exit('No direct script access allowed');
-$lang['imglib_source_image_required'] = "You must specify a source image in your preferences.";
-$lang['imglib_gd_required'] = "The GD image library is required for this feature.";
-$lang['imglib_gd_required_for_props'] = "Your server must support the GD image library in order to determine the image properties.";
-$lang['imglib_unsupported_imagecreate'] = "Your server does not support the GD function required to process this type of image.";
-$lang['imglib_gif_not_supported'] = "GIF images are often not supported due to licensing restrictions. You may have to use JPG or PNG images instead.";
-$lang['imglib_jpg_not_supported'] = "JPG images are not supported.";
-$lang['imglib_png_not_supported'] = "PNG images are not supported.";
-$lang['imglib_jpg_or_png_required'] = "The image resize protocol specified in your preferences only works with JPEG or PNG image types.";
-$lang['imglib_copy_error'] = "An error was encountered while attempting to replace the file. Please make sure your file directory is writable.";
-$lang['imglib_rotate_unsupported'] = "Image rotation does not appear to be supported by your server.";
-$lang['imglib_libpath_invalid'] = "The path to your image library is not correct. Please set the correct path in your image preferences.";
-$lang['imglib_image_process_failed'] = "Image processing failed. Please verify that your server supports the chosen protocol and that the path to your image library is correct.";
-$lang['imglib_rotation_angle_required'] = "An angle of rotation is required to rotate the image.";
-$lang['imglib_writing_failed_gif'] = "GIF image.";
-$lang['imglib_invalid_path'] = "The path to the image is not correct.";
-$lang['imglib_copy_failed'] = "The image copy routine failed.";
-$lang['imglib_missing_font'] = "Unable to find a font to use.";
-$lang['imglib_save_failed'] = "Unable to save the image. Please make sure the image and file directory are writable.";
-
+$lang['imglib_source_image_required'] = 'You must specify a source image in your preferences.';
+$lang['imglib_gd_required'] = 'The GD image library is required for this feature.';
+$lang['imglib_gd_required_for_props'] = 'Your server must support the GD image library in order to determine the image properties.';
+$lang['imglib_unsupported_imagecreate'] = 'Your server does not support the GD function required to process this type of image.';
+$lang['imglib_gif_not_supported'] = 'GIF images are often not supported due to licensing restrictions. You may have to use JPG or PNG images instead.';
+$lang['imglib_jpg_not_supported'] = 'JPG images are not supported.';
+$lang['imglib_png_not_supported'] = 'PNG images are not supported.';
+$lang['imglib_jpg_or_png_required'] = 'The image resize protocol specified in your preferences only works with JPEG or PNG image types.';
+$lang['imglib_copy_error'] = 'An error was encountered while attempting to replace the file. Please make sure your file directory is writable.';
+$lang['imglib_rotate_unsupported'] = 'Image rotation does not appear to be supported by your server.';
+$lang['imglib_libpath_invalid'] = 'The path to your image library is not correct. Please set the correct path in your image preferences.';
+$lang['imglib_image_process_failed'] = 'Image processing failed. Please verify that your server supports the chosen protocol and that the path to your image library is correct.';
+$lang['imglib_rotation_angle_required'] = 'An angle of rotation is required to rotate the image.';
+$lang['imglib_writing_failed_gif'] = 'GIF image.';
+$lang['imglib_invalid_path'] = 'The path to the image is not correct.';
+$lang['imglib_copy_failed'] = 'The image copy routine failed.';
+$lang['imglib_missing_font'] = 'Unable to find a font to use.';
+$lang['imglib_save_failed'] = 'Unable to save the image. Please make sure the image and file directory are writable.';
/* End of file imglib_lang.php */
/* Location: ./system/language/english/imglib_lang.php */ \ No newline at end of file
diff --git a/system/language/english/migration_lang.php b/system/language/english/migration_lang.php
index 2085cee2a..33bd02620 100644
--- a/system/language/english/migration_lang.php
+++ b/system/language/english/migration_lang.php
@@ -5,9 +5,9 @@
* An open source application development framework for PHP 5.2.4 or newer
*
* NOTICE OF LICENSE
- *
+ *
* Licensed under the Open Software License version 3.0
- *
+ *
* This source file is subject to the Open Software License (OSL 3.0) that is
* bundled with this package in the files license.txt / license.rst. It is
* also available through the world wide web at this URL:
@@ -24,15 +24,16 @@
* @since Version 3.0
* @filesource
*/
+defined('BASEPATH') OR exit('No direct script access allowed');
-$lang['migration_none_found'] = "No migrations were found.";
-$lang['migration_not_found'] = "This migration could not be found.";
-$lang['migration_multiple_version'] = "This are multiple migrations with the same version number: %d.";
-$lang['migration_class_doesnt_exist'] = "The migration class \"%s\" could not be found.";
-$lang['migration_missing_up_method'] = "The migration class \"%s\" is missing an 'up' method.";
-$lang['migration_missing_down_method'] = "The migration class \"%s\" is missing a 'down' method.";
-$lang['migration_invalid_filename'] = "Migration \"%s\" has an invalid filename.";
-
+$lang['migration_none_found'] = 'No migrations were found.';
+$lang['migration_not_found'] = 'No migration could be found with the version number: %d.';
+$lang['migration_sequence_gap'] = 'There is a gap in the migration sequence near version number: %d.';
+$lang['migration_multiple_version'] = 'There are multiple migrations with the same version number: %d.';
+$lang['migration_class_doesnt_exist'] = 'The migration class "%s" could not be found.';
+$lang['migration_missing_up_method'] = 'The migration class "%s" is missing an "up" method.';
+$lang['migration_missing_down_method'] = 'The migration class "%s" is missing a "down" method.';
+$lang['migration_invalid_filename'] = 'Migration "%s" has an invalid filename.';
/* End of file migration_lang.php */
/* Location: ./system/language/english/migration_lang.php */ \ No newline at end of file
diff --git a/system/language/english/number_lang.php b/system/language/english/number_lang.php
index 0c19ec614..019013a49 100644
--- a/system/language/english/number_lang.php
+++ b/system/language/english/number_lang.php
@@ -5,9 +5,9 @@
* An open source application development framework for PHP 5.2.4 or newer
*
* NOTICE OF LICENSE
- *
+ *
* Licensed under the Open Software License version 3.0
- *
+ *
* This source file is subject to the Open Software License (OSL 3.0) that is
* bundled with this package in the files license.txt / license.rst. It is
* also available through the world wide web at this URL:
@@ -24,12 +24,13 @@
* @since Version 1.0
* @filesource
*/
+defined('BASEPATH') OR exit('No direct script access allowed');
-$lang['terabyte_abbr'] = "TB";
-$lang['gigabyte_abbr'] = "GB";
-$lang['megabyte_abbr'] = "MB";
-$lang['kilobyte_abbr'] = "KB";
-$lang['bytes'] = "Bytes";
+$lang['terabyte_abbr'] = 'TB';
+$lang['gigabyte_abbr'] = 'GB';
+$lang['megabyte_abbr'] = 'MB';
+$lang['kilobyte_abbr'] = 'KB';
+$lang['bytes'] = 'Bytes';
/* End of file number_lang.php */
/* Location: ./system/language/english/number_lang.php */ \ No newline at end of file
diff --git a/system/language/english/profiler_lang.php b/system/language/english/profiler_lang.php
index 11d791272..6ffcd9349 100644
--- a/system/language/english/profiler_lang.php
+++ b/system/language/english/profiler_lang.php
@@ -5,9 +5,9 @@
* An open source application development framework for PHP 5.2.4 or newer
*
* NOTICE OF LICENSE
- *
+ *
* Licensed under the Open Software License version 3.0
- *
+ *
* This source file is subject to the Open Software License (OSL 3.0) that is
* bundled with this package in the files license.txt / license.rst. It is
* also available through the world wide web at this URL:
@@ -24,6 +24,7 @@
* @since Version 1.0
* @filesource
*/
+defined('BASEPATH') OR exit('No direct script access allowed');
$lang['profiler_database'] = 'DATABASE';
$lang['profiler_controller_info'] = 'CLASS/METHOD';
diff --git a/system/language/english/unit_test_lang.php b/system/language/english/unit_test_lang.php
index 3a8e14403..ed452615f 100644
--- a/system/language/english/unit_test_lang.php
+++ b/system/language/english/unit_test_lang.php
@@ -5,9 +5,9 @@
* An open source application development framework for PHP 5.2.4 or newer
*
* NOTICE OF LICENSE
- *
+ *
* Licensed under the Open Software License version 3.0
- *
+ *
* This source file is subject to the Open Software License (OSL 3.0) that is
* bundled with this package in the files license.txt / license.rst. It is
* also available through the world wide web at this URL:
@@ -24,6 +24,7 @@
* @since Version 1.0
* @filesource
*/
+defined('BASEPATH') OR exit('No direct script access allowed');
$lang['ut_test_name'] = 'Test Name';
$lang['ut_test_datatype'] = 'Test Datatype';
@@ -45,6 +46,5 @@ $lang['ut_resource'] = 'Resource';
$lang['ut_null'] = 'Null';
$lang['ut_notes'] = 'Notes';
-
/* End of file unit_test_lang.php */
/* Location: ./system/language/english/unit_test_lang.php */ \ No newline at end of file
diff --git a/system/language/english/upload_lang.php b/system/language/english/upload_lang.php
index 4fa8394ec..26a5c545c 100644
--- a/system/language/english/upload_lang.php
+++ b/system/language/english/upload_lang.php
@@ -5,9 +5,9 @@
* An open source application development framework for PHP 5.2.4 or newer
*
* NOTICE OF LICENSE
- *
+ *
* Licensed under the Open Software License version 3.0
- *
+ *
* This source file is subject to the Open Software License (OSL 3.0) that is
* bundled with this package in the files license.txt / license.rst. It is
* also available through the world wide web at this URL:
@@ -24,24 +24,24 @@
* @since Version 1.0
* @filesource
*/
+defined('BASEPATH') OR exit('No direct script access allowed');
-$lang['upload_userfile_not_set'] = "Unable to find a post variable called userfile.";
-$lang['upload_file_exceeds_limit'] = "The uploaded file exceeds the maximum allowed size in your PHP configuration file.";
-$lang['upload_file_exceeds_form_limit'] = "The uploaded file exceeds the maximum size allowed by the submission form.";
-$lang['upload_file_partial'] = "The file was only partially uploaded.";
-$lang['upload_no_temp_directory'] = "The temporary folder is missing.";
-$lang['upload_unable_to_write_file'] = "The file could not be written to disk.";
-$lang['upload_stopped_by_extension'] = "The file upload was stopped by extension.";
-$lang['upload_no_file_selected'] = "You did not select a file to upload.";
-$lang['upload_invalid_filetype'] = "The filetype you are attempting to upload is not allowed.";
-$lang['upload_invalid_filesize'] = "The file you are attempting to upload is larger than the permitted size.";
-$lang['upload_invalid_dimensions'] = "The image you are attempting to upload exceeds the maximum height or width.";
-$lang['upload_destination_error'] = "A problem was encountered while attempting to move the uploaded file to the final destination.";
-$lang['upload_no_filepath'] = "The upload path does not appear to be valid.";
-$lang['upload_no_file_types'] = "You have not specified any allowed file types.";
-$lang['upload_bad_filename'] = "The file name you submitted already exists on the server.";
-$lang['upload_not_writable'] = "The upload destination folder does not appear to be writable.";
-
+$lang['upload_userfile_not_set'] = 'Unable to find a post variable called userfile.';
+$lang['upload_file_exceeds_limit'] = 'The uploaded file exceeds the maximum allowed size in your PHP configuration file.';
+$lang['upload_file_exceeds_form_limit'] = 'The uploaded file exceeds the maximum size allowed by the submission form.';
+$lang['upload_file_partial'] = 'The file was only partially uploaded.';
+$lang['upload_no_temp_directory'] = 'The temporary folder is missing.';
+$lang['upload_unable_to_write_file'] = 'The file could not be written to disk.';
+$lang['upload_stopped_by_extension'] = 'The file upload was stopped by extension.';
+$lang['upload_no_file_selected'] = 'You did not select a file to upload.';
+$lang['upload_invalid_filetype'] = 'The filetype you are attempting to upload is not allowed.';
+$lang['upload_invalid_filesize'] = 'The file you are attempting to upload is larger than the permitted size.';
+$lang['upload_invalid_dimensions'] = 'The image you are attempting to upload doesn\'t fit into the allowed dimensions.';
+$lang['upload_destination_error'] = 'A problem was encountered while attempting to move the uploaded file to the final destination.';
+$lang['upload_no_filepath'] = 'The upload path does not appear to be valid.';
+$lang['upload_no_file_types'] = 'You have not specified any allowed file types.';
+$lang['upload_bad_filename'] = 'The file name you submitted already exists on the server.';
+$lang['upload_not_writable'] = 'The upload destination folder does not appear to be writable.';
/* End of file upload_lang.php */
/* Location: ./system/language/english/upload_lang.php */ \ No newline at end of file
diff --git a/system/libraries/Cache/Cache.php b/system/libraries/Cache/Cache.php
index f98241617..48bd9581a 100644
--- a/system/libraries/Cache/Cache.php
+++ b/system/libraries/Cache/Cache.php
@@ -1,4 +1,4 @@
-<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');
+<?php
/**
* CodeIgniter
*
@@ -18,12 +18,13 @@
*
* @package CodeIgniter
* @author EllisLab Dev Team
- * @copyright Copyright (c) 2006 - 2012 EllisLab, Inc.
+ * @copyright Copyright (c) 2008 - 2012, EllisLab, Inc. (http://ellislab.com/)
* @license http://opensource.org/licenses/OSL-3.0 Open Software License (OSL 3.0)
* @link http://codeigniter.com
* @since Version 2.0
* @filesource
*/
+defined('BASEPATH') OR exit('No direct script access allowed');
/**
* CodeIgniter Caching Class
@@ -36,32 +37,62 @@
*/
class CI_Cache extends CI_Driver_Library {
- protected $valid_drivers = array(
- 'cache_apc',
- 'cache_file',
- 'cache_memcached',
- 'cache_dummy',
- 'cache_wincache'
- );
+ /**
+ * Valid cache drivers
+ *
+ * @var array
+ */
+ protected $valid_drivers = array(
+ 'apc',
+ 'dummy',
+ 'file',
+ 'memcached',
+ 'redis',
+ 'wincache'
+ );
+
+ /**
+ * Path of cache files (if file-based cache)
+ *
+ * @var string
+ */
+ protected $_cache_path = NULL;
+
+ /**
+ * Reference to the driver
+ *
+ * @var mixed
+ */
+ protected $_adapter = 'dummy';
- protected $_cache_path = NULL; // Path of cache files (if file-based cache)
- protected $_adapter = 'dummy';
- protected $_backup_driver;
+ /**
+ * Fallback driver
+ *
+ * @var string
+ */
+ protected $_backup_driver = 'dummy';
+
+ /**
+ * Cache key prefix
+ *
+ * @var string
+ */
+ public $key_prefix = '';
/**
* Constructor
*
* Initialize class properties based on the configuration array.
*
- * @param array
+ * @param array $config = array()
* @return void
*/
public function __construct($config = array())
{
$default_config = array(
- 'adapter',
- 'memcached'
- );
+ 'adapter',
+ 'memcached'
+ );
foreach ($default_config as $key)
{
@@ -73,11 +104,26 @@ class CI_Cache extends CI_Driver_Library {
}
}
- if (isset($config['backup']))
+ isset($config['key_prefix']) && $this->key_prefix = $config['key_prefix'];
+
+ if (isset($config['backup']) && in_array('cache_'.$config['backup'], $this->valid_drivers))
{
- if (in_array('cache_'.$config['backup'], $this->valid_drivers))
+ $this->_backup_driver = $config['backup'];
+ }
+
+ // If the specified adapter isn't available, check the backup.
+ if ( ! $this->is_supported($this->_adapter))
+ {
+ if ( ! $this->is_supported($this->_backup_driver))
{
- $this->_backup_driver = $config['backup'];
+ // Backup isn't supported either. Default to 'Dummy' driver.
+ log_message('error', 'Cache adapter "'.$this->_adapter.'" and backup "'.$this->_backup_driver.'" are both unavailable. Cache is now using "Dummy" adapter.');
+ $this->_adapter = 'dummy';
+ }
+ else
+ {
+ // Backup is supported. Set it to primary.
+ $this->_adapter = $this->_backup_driver;
}
}
}
@@ -90,12 +136,12 @@ class CI_Cache extends CI_Driver_Library {
* Look for a value in the cache. If it exists, return the data
* if not, return FALSE
*
- * @param string
- * @return mixed value that is stored/FALSE on failure
+ * @param string $id
+ * @return mixed value matching $id or FALSE on failure
*/
public function get($id)
{
- return $this->{$this->_adapter}->get($id);
+ return $this->{$this->_adapter}->get($this->key_prefix.$id);
}
// ------------------------------------------------------------------------
@@ -103,14 +149,14 @@ class CI_Cache extends CI_Driver_Library {
/**
* Cache Save
*
- * @param string Unique Key
- * @param mixed Data to store
- * @param int Length of time (in seconds) to cache the data
- * @return bool true on success/false on failure
+ * @param string $id Cache ID
+ * @param mixed $data Data to store
+ * @param int $ttl = 60 Cache TTL (in seconds)
+ * @return bool TRUE on success, FALSE on failure
*/
public function save($id, $data, $ttl = 60)
{
- return $this->{$this->_adapter}->save($id, $data, $ttl);
+ return $this->{$this->_adapter}->save($this->key_prefix.$id, $data, $ttl);
}
// ------------------------------------------------------------------------
@@ -118,12 +164,12 @@ class CI_Cache extends CI_Driver_Library {
/**
* Delete from Cache
*
- * @param mixed unique identifier of the item in the cache
- * @return bool true on success/false on failure
+ * @param string $id Cache ID
+ * @return bool TRUE on success, FALSE on failure
*/
public function delete($id)
{
- return $this->{$this->_adapter}->delete($id);
+ return $this->{$this->_adapter}->delete($this->key_prefix.$id);
}
// ------------------------------------------------------------------------
@@ -131,7 +177,7 @@ class CI_Cache extends CI_Driver_Library {
/**
* Clean the cache
*
- * @return bool false on failure/true on success
+ * @return bool TRUE on success, FALSE on failure
*/
public function clean()
{
@@ -143,8 +189,8 @@ class CI_Cache extends CI_Driver_Library {
/**
* Cache Info
*
- * @param string user/filehits
- * @return mixed array on success, false on failure
+ * @param string $type = 'user' user/filehits
+ * @return mixed array containing cache info on success OR FALSE on failure
*/
public function cache_info($type = 'user')
{
@@ -156,12 +202,12 @@ class CI_Cache extends CI_Driver_Library {
/**
* Get Cache Metadata
*
- * @param mixed key to get cache metadata on
- * @return mixed return value from child method
+ * @param string $id key to get cache metadata on
+ * @return mixed cache item metadata
*/
public function get_metadata($id)
{
- return $this->{$this->_adapter}->get_metadata($id);
+ return $this->{$this->_adapter}->get_metadata($this->key_prefix.$id);
}
// ------------------------------------------------------------------------
@@ -169,7 +215,7 @@ class CI_Cache extends CI_Driver_Library {
/**
* Is the requested driver supported in this environment?
*
- * @param string The driver to test.
+ * @param string $driver The driver to test
* @return array
*/
public function is_supported($driver)
@@ -184,26 +230,6 @@ class CI_Cache extends CI_Driver_Library {
return $support[$driver];
}
- // ------------------------------------------------------------------------
-
- /**
- * __get()
- *
- * @param child
- * @return object
- */
- public function __get($child)
- {
- $obj = parent::__get($child);
-
- if ( ! $this->is_supported($child))
- {
- $this->_adapter = $this->_backup_driver;
- }
-
- return $obj;
- }
-
}
/* End of file Cache.php */
diff --git a/system/libraries/Cache/drivers/Cache_apc.php b/system/libraries/Cache/drivers/Cache_apc.php
index 59ab67533..a9ad6ed19 100644
--- a/system/libraries/Cache/drivers/Cache_apc.php
+++ b/system/libraries/Cache/drivers/Cache_apc.php
@@ -1,4 +1,4 @@
-<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');
+<?php
/**
* CodeIgniter
*
@@ -18,12 +18,13 @@
*
* @package CodeIgniter
* @author EllisLab Dev Team
- * @copyright Copyright (c) 2006 - 2012 EllisLab, Inc.
+ * @copyright Copyright (c) 2008 - 2012, EllisLab, Inc. (http://ellislab.com/)
* @license http://opensource.org/licenses/OSL-3.0 Open Software License (OSL 3.0)
* @link http://codeigniter.com
* @since Version 2.0
* @filesource
*/
+defined('BASEPATH') OR exit('No direct script access allowed');
/**
* CodeIgniter APC Caching Class
@@ -47,9 +48,11 @@ class CI_Cache_apc extends CI_Driver {
*/
public function get($id)
{
- $data = apc_fetch($id);
+ $success = FALSE;
+ $data = apc_fetch($id, $success);
- return is_array($data) ? $data[0] : FALSE;
+ return ($success === TRUE && is_array($data))
+ ? unserialize($data[0]) : FALSE;
}
// ------------------------------------------------------------------------
@@ -66,7 +69,7 @@ class CI_Cache_apc extends CI_Driver {
public function save($id, $data, $ttl = 60)
{
$ttl = (int) $ttl;
- return apc_store($id, array($data, time(), $ttl), $ttl);
+ return apc_store($id, array(serialize($data), time(), $ttl), $ttl);
}
// ------------------------------------------------------------------------
@@ -75,7 +78,7 @@ class CI_Cache_apc extends CI_Driver {
* Delete from Cache
*
* @param mixed unique identifier of the item in the cache
- * @param bool true on success/false on failure
+ * @return bool true on success/false on failure
*/
public function delete($id)
{
@@ -117,9 +120,10 @@ class CI_Cache_apc extends CI_Driver {
*/
public function get_metadata($id)
{
- $stored = apc_fetch($id);
+ $success = FALSE;
+ $stored = apc_fetch($id, $success);
- if (count($stored) !== 3)
+ if ($success === FALSE OR count($stored) !== 3)
{
return FALSE;
}
@@ -129,7 +133,7 @@ class CI_Cache_apc extends CI_Driver {
return array(
'expire' => $time + $ttl,
'mtime' => $time,
- 'data' => $data
+ 'data' => unserialize($data)
);
}
diff --git a/system/libraries/Cache/drivers/Cache_dummy.php b/system/libraries/Cache/drivers/Cache_dummy.php
index e8b791c5b..a3bdc3c80 100644
--- a/system/libraries/Cache/drivers/Cache_dummy.php
+++ b/system/libraries/Cache/drivers/Cache_dummy.php
@@ -1,4 +1,4 @@
-<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');
+<?php
/**
* CodeIgniter
*
@@ -18,12 +18,13 @@
*
* @package CodeIgniter
* @author EllisLab Dev Team
- * @copyright Copyright (c) 2006 - 2012 EllisLab, Inc.
+ * @copyright Copyright (c) 2008 - 2012, EllisLab, Inc. (http://ellislab.com/)
* @license http://opensource.org/licenses/OSL-3.0 Open Software License (OSL 3.0)
* @link http://codeigniter.com
* @since Version 2.0
* @filesource
*/
+defined('BASEPATH') OR exit('No direct script access allowed');
/**
* CodeIgniter Dummy Caching Class
@@ -70,7 +71,7 @@ class CI_Cache_dummy extends CI_Driver {
* Delete from Cache
*
* @param mixed unique identifier of the item in the cache
- * @param bool TRUE, simulating success
+ * @return bool TRUE, simulating success
*/
public function delete($id)
{
diff --git a/system/libraries/Cache/drivers/Cache_file.php b/system/libraries/Cache/drivers/Cache_file.php
index dd27aa90e..9fd053362 100644
--- a/system/libraries/Cache/drivers/Cache_file.php
+++ b/system/libraries/Cache/drivers/Cache_file.php
@@ -1,4 +1,4 @@
-<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');
+<?php
/**
* CodeIgniter
*
@@ -18,15 +18,16 @@
*
* @package CodeIgniter
* @author EllisLab Dev Team
- * @copyright Copyright (c) 2006 - 2012 EllisLab, Inc.
+ * @copyright Copyright (c) 2008 - 2012, EllisLab, Inc. (http://ellislab.com/)
* @license http://opensource.org/licenses/OSL-3.0 Open Software License (OSL 3.0)
* @link http://codeigniter.com
* @since Version 2.0
* @filesource
*/
+defined('BASEPATH') OR exit('No direct script access allowed');
/**
- * CodeIgniter Memcached Caching Class
+ * CodeIgniter File Caching Class
*
* @package CodeIgniter
* @subpackage Libraries
@@ -36,14 +37,24 @@
*/
class CI_Cache_file extends CI_Driver {
+ /**
+ * Directory in which to save cache files
+ *
+ * @var string
+ */
protected $_cache_path;
+ /**
+ * Initialize file-based cache
+ *
+ * @return void
+ */
public function __construct()
{
$CI =& get_instance();
$CI->load->helper('file');
$path = $CI->config->item('cache_path');
- $this->_cache_path = ($path == '') ? APPPATH.'cache/' : $path;
+ $this->_cache_path = ($path === '') ? APPPATH.'cache/' : $path;
}
// ------------------------------------------------------------------------
@@ -61,9 +72,9 @@ class CI_Cache_file extends CI_Driver {
return FALSE;
}
- $data = unserialize(read_file($this->_cache_path.$id));
+ $data = unserialize(file_get_contents($this->_cache_path.$id));
- if (time() > $data['time'] + $data['ttl'])
+ if ($data['ttl'] > 0 && time() > $data['time'] + $data['ttl'])
{
unlink($this->_cache_path.$id);
return FALSE;
@@ -86,10 +97,10 @@ class CI_Cache_file extends CI_Driver {
public function save($id, $data, $ttl = 60)
{
$contents = array(
- 'time' => time(),
- 'ttl' => $ttl,
- 'data' => $data
- );
+ 'time' => time(),
+ 'ttl' => $ttl,
+ 'data' => $data
+ );
if (write_file($this->_cache_path.$id, serialize($contents)))
{
@@ -155,19 +166,19 @@ class CI_Cache_file extends CI_Driver {
return FALSE;
}
- $data = unserialize(read_file($this->_cache_path.$id));
+ $data = unserialize(file_get_contents($this->_cache_path.$id));
if (is_array($data))
{
$mtime = filemtime($this->_cache_path.$id);
- if ( ! isset($data['data']['ttl']))
+ if ( ! isset($data['ttl']))
{
return FALSE;
}
return array(
- 'expire' => $mtime + $data['data']['ttl'],
+ 'expire' => $mtime + $data['ttl'],
'mtime' => $mtime
);
}
diff --git a/system/libraries/Cache/drivers/Cache_memcached.php b/system/libraries/Cache/drivers/Cache_memcached.php
index 4cd5f3d6f..fae002347 100644
--- a/system/libraries/Cache/drivers/Cache_memcached.php
+++ b/system/libraries/Cache/drivers/Cache_memcached.php
@@ -1,4 +1,4 @@
-<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');
+<?php
/**
* CodeIgniter
*
@@ -18,12 +18,13 @@
*
* @package CodeIgniter
* @author EllisLab Dev Team
- * @copyright Copyright (c) 2006 - 2012 EllisLab, Inc.
+ * @copyright Copyright (c) 2008 - 2012, EllisLab, Inc. (http://ellislab.com/)
* @license http://opensource.org/licenses/OSL-3.0 Open Software License (OSL 3.0)
* @link http://codeigniter.com
* @since Version 2.0
* @filesource
*/
+defined('BASEPATH') OR exit('No direct script access allowed');
/**
* CodeIgniter Memcached Caching Class
@@ -36,15 +37,25 @@
*/
class CI_Cache_memcached extends CI_Driver {
- protected $_memcached; // Holds the memcached object
+ /**
+ * Holds the memcached object
+ *
+ * @var object
+ */
+ protected $_memcached;
+ /**
+ * Memcached configuration
+ *
+ * @var array
+ */
protected $_memcache_conf = array(
- 'default' => array(
- 'default_host' => '127.0.0.1',
- 'default_port' => 11211,
- 'default_weight' => 1
- )
- );
+ 'default' => array(
+ 'default_host' => '127.0.0.1',
+ 'default_port' => 11211,
+ 'default_weight' => 1
+ )
+ );
/**
* Fetch from cache
@@ -67,7 +78,7 @@ class CI_Cache_memcached extends CI_Driver {
* @param string unique identifier
* @param mixed data being cached
* @param int time to live
- * @return bool true on success, false on failure
+ * @return bool true on success, false on failure
*/
public function save($id, $data, $ttl = 60)
{
@@ -89,7 +100,7 @@ class CI_Cache_memcached extends CI_Driver {
* Delete from Cache
*
* @param mixed key to be deleted.
- * @return bool true on success, false on failure
+ * @return bool true on success, false on failure
*/
public function delete($id)
{
@@ -202,7 +213,7 @@ class CI_Cache_memcached extends CI_Driver {
$cache_server['weight'] = $this->_memcache_conf['default']['default_weight'];
}
- if (get_class($this->_memcached) == 'Memcache')
+ if (get_class($this->_memcached) === 'Memcache')
{
// Third parameter is persistance and defaults to TRUE.
$this->_memcached->addServer(
diff --git a/system/libraries/Cache/drivers/Cache_redis.php b/system/libraries/Cache/drivers/Cache_redis.php
new file mode 100644
index 000000000..60033344b
--- /dev/null
+++ b/system/libraries/Cache/drivers/Cache_redis.php
@@ -0,0 +1,237 @@
+<?php
+/**
+ * CodeIgniter
+ *
+ * An open source application development framework for PHP 5.2.4 or newer
+ *
+ * NOTICE OF LICENSE
+ *
+ * Licensed under the Open Software License version 3.0
+ *
+ * This source file is subject to the Open Software License (OSL 3.0) that is
+ * bundled with this package in the files license.txt / license.rst. It is
+ * also available through the world wide web at this URL:
+ * http://opensource.org/licenses/OSL-3.0
+ * If you did not receive a copy of the license and are unable to obtain it
+ * through the world wide web, please send an email to
+ * licensing@ellislab.com so we can send you a copy immediately.
+ *
+ * @package CodeIgniter
+ * @author EllisLab Dev Team
+ * @copyright Copyright (c) 2008 - 2012, EllisLab, Inc. (http://ellislab.com/)
+ * @license http://opensource.org/licenses/OSL-3.0 Open Software License (OSL 3.0)
+ * @link http://codeigniter.com
+ * @since Version 3.0
+ * @filesource
+ */
+defined('BASEPATH') OR exit('No direct script access allowed');
+
+/**
+ * CodeIgniter Redis Caching Class
+ *
+ * @package CodeIgniter
+ * @subpackage Libraries
+ * @category Core
+ * @author Anton Lindqvist <anton@qvister.se>
+ * @link
+ */
+class CI_Cache_redis extends CI_Driver
+{
+ /**
+ * Default config
+ *
+ * @static
+ * @var array
+ */
+ protected static $_default_config = array(
+ 'host' => '127.0.0.1',
+ 'password' => NULL,
+ 'port' => 6379,
+ 'timeout' => 0
+ );
+
+ /**
+ * Redis connection
+ *
+ * @var Redis
+ */
+ protected $_redis;
+
+ // ------------------------------------------------------------------------
+
+ /**
+ * Get cache
+ *
+ * @param string Cache key identifier
+ * @return mixed
+ */
+ public function get($key)
+ {
+ return $this->_redis->get($key);
+ }
+
+ // ------------------------------------------------------------------------
+
+ /**
+ * Save cache
+ *
+ * @param string Cache key identifier
+ * @param mixed Data to save
+ * @param int Time to live
+ * @return bool
+ */
+ public function save($key, $value, $ttl = NULL)
+ {
+ return ($ttl)
+ ? $this->_redis->setex($key, $ttl, $value)
+ : $this->_redis->set($key, $value);
+ }
+
+ // ------------------------------------------------------------------------
+
+ /**
+ * Delete from cache
+ *
+ * @param string Cache key
+ * @return bool
+ */
+ public function delete($key)
+ {
+ return ($this->_redis->delete($key) === 1);
+ }
+
+ // ------------------------------------------------------------------------
+
+ /**
+ * Clean cache
+ *
+ * @return bool
+ * @see Redis::flushDB()
+ */
+ public function clean()
+ {
+ return $this->_redis->flushDB();
+ }
+
+ // ------------------------------------------------------------------------
+
+ /**
+ * Get cache driver info
+ *
+ * @param string Not supported in Redis.
+ * Only included in order to offer a
+ * consistent cache API.
+ * @return array
+ * @see Redis::info()
+ */
+ public function cache_info($type = NULL)
+ {
+ return $this->_redis->info();
+ }
+
+ // ------------------------------------------------------------------------
+
+ /**
+ * Get cache metadata
+ *
+ * @param string Cache key
+ * @return array
+ */
+ public function get_metadata($key)
+ {
+ $value = $this->get($key);
+
+ if ($value)
+ {
+ return array(
+ 'expire' => time() + $this->_redis->ttl($key),
+ 'data' => $value
+ );
+ }
+
+ return FALSE;
+ }
+
+ // ------------------------------------------------------------------------
+
+ /**
+ * Check if Redis driver is supported
+ *
+ * @return bool
+ */
+ public function is_supported()
+ {
+ if (extension_loaded('redis'))
+ {
+ $this->_setup_redis();
+ return TRUE;
+ }
+ else
+ {
+ log_message('error', 'The Redis extension must be loaded to use Redis cache.');
+ return FALSE;
+ }
+ }
+
+ // ------------------------------------------------------------------------
+
+ /**
+ * Setup Redis config and connection
+ *
+ * Loads Redis config file if present. Will halt execution
+ * if a Redis connection can't be established.
+ *
+ * @return bool
+ * @see Redis::connect()
+ */
+ protected function _setup_redis()
+ {
+ $config = array();
+ $CI =& get_instance();
+
+ if ($CI->config->load('redis', TRUE, TRUE))
+ {
+ $config += $CI->config->item('redis');
+ }
+
+ $config = array_merge(self::$_default_config, $config);
+
+ $this->_redis = new Redis();
+
+ try
+ {
+ $this->_redis->connect($config['host'], $config['port'], $config['timeout']);
+ }
+ catch (RedisException $e)
+ {
+ show_error('Redis connection refused. ' . $e->getMessage());
+ }
+
+ if (isset($config['password']))
+ {
+ $this->_redis->auth($config['password']);
+ }
+ }
+
+ // ------------------------------------------------------------------------
+
+ /**
+
+ * Class destructor
+ *
+ * Closes the connection to Redis if present.
+ *
+ * @return void
+ */
+ public function __destruct()
+ {
+ if ($this->_redis)
+ {
+ $this->_redis->close();
+ }
+ }
+
+}
+
+/* End of file Cache_redis.php */
+/* Location: ./system/libraries/Cache/drivers/Cache_redis.php */ \ No newline at end of file
diff --git a/system/libraries/Cache/drivers/Cache_wincache.php b/system/libraries/Cache/drivers/Cache_wincache.php
index b32e66a46..9154f3fce 100644
--- a/system/libraries/Cache/drivers/Cache_wincache.php
+++ b/system/libraries/Cache/drivers/Cache_wincache.php
@@ -1,8 +1,8 @@
-<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');
+<?php
/**
* CodeIgniter
*
- * An open source application development framework for PHP 5.1.6 or newer
+ * An open source application development framework for PHP 5.2.4 or newer
*
* NOTICE OF LICENSE
*
@@ -18,12 +18,13 @@
*
* @package CodeIgniter
* @author EllisLab Dev Team
- * @copyright Copyright (c) 2006 - 2012 EllisLab, Inc.
+ * @copyright Copyright (c) 2008 - 2012, EllisLab, Inc. (http://ellislab.com/)
* @license http://opensource.org/licenses/OSL-3.0 Open Software License (OSL 3.0)
* @link http://codeigniter.com
* @since Version 3.0
* @filesource
*/
+defined('BASEPATH') OR exit('No direct script access allowed');
/**
* CodeIgniter Wincache Caching Class
@@ -78,7 +79,7 @@ class CI_Cache_wincache extends CI_Driver {
* Delete from Cache
*
* @param mixed unique identifier of the item in the cache
- * @param bool true on success/false on failure
+ * @return bool true on success/false on failure
*/
public function delete($id)
{
@@ -126,10 +127,10 @@ class CI_Cache_wincache extends CI_Driver {
$hitcount = $stored['ucache_entries'][1]['hitcount'];
return array(
- 'expire' => $ttl - $age,
- 'hitcount' => $hitcount,
- 'age' => $age,
- 'ttl' => $ttl
+ 'expire' => $ttl - $age,
+ 'hitcount' => $hitcount,
+ 'age' => $age,
+ 'ttl' => $ttl
);
}
diff --git a/system/libraries/Cache/drivers/index.html b/system/libraries/Cache/drivers/index.html
new file mode 100644
index 000000000..c942a79ce
--- /dev/null
+++ b/system/libraries/Cache/drivers/index.html
@@ -0,0 +1,10 @@
+<html>
+<head>
+ <title>403 Forbidden</title>
+</head>
+<body>
+
+<p>Directory access is forbidden.</p>
+
+</body>
+</html> \ No newline at end of file
diff --git a/system/libraries/Cache/index.html b/system/libraries/Cache/index.html
new file mode 100644
index 000000000..c942a79ce
--- /dev/null
+++ b/system/libraries/Cache/index.html
@@ -0,0 +1,10 @@
+<html>
+<head>
+ <title>403 Forbidden</title>
+</head>
+<body>
+
+<p>Directory access is forbidden.</p>
+
+</body>
+</html> \ No newline at end of file
diff --git a/system/libraries/Calendar.php b/system/libraries/Calendar.php
index b6f145d95..ec2b7bcc1 100644
--- a/system/libraries/Calendar.php
+++ b/system/libraries/Calendar.php
@@ -1,4 +1,4 @@
-<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');
+<?php
/**
* CodeIgniter
*
@@ -24,6 +24,7 @@
* @since Version 1.0
* @filesource
*/
+defined('BASEPATH') OR exit('No direct script access allowed');
/**
* CodeIgniter Calendar Class
@@ -38,22 +39,70 @@
*/
class CI_Calendar {
+ /**
+ * Reference to CodeIgniter instance
+ *
+ * @var object
+ */
protected $CI;
- public $lang;
+
+ /**
+ * Current local time
+ *
+ * @var int
+ */
public $local_time;
+
+ /**
+ * Calendar layout template
+ *
+ * @var string
+ */
public $template = '';
+
+ /**
+ * Day of the week to start the calendar on
+ *
+ * @var string
+ */
public $start_day = 'sunday';
+
+ /**
+ * How to display months
+ *
+ * @var string
+ */
public $month_type = 'long';
+
+ /**
+ * How to display names of days
+ *
+ * @var string
+ */
public $day_type = 'abr';
- public $show_next_prev = FALSE;
- public $next_prev_url = '';
/**
- * Constructor
+ * Whether to show next/prev month links
+ *
+ * @var bool
+ */
+ public $show_next_prev = FALSE;
+
+ /**
+ * Url base to use for next/prev month links
+ *
+ * @var bool
+ */
+ public $next_prev_url = '';
+
+ /**
+ * Class constructor
*
- * Loads the calendar language file and sets the default time reference
+ * Loads the calendar language file and sets the default time reference.
*
- * @param array
+ * @uses CI_Lang::$is_loaded
+ *
+ * @param array $config Calendar options
* @return void
*/
public function __construct($config = array())
@@ -109,9 +158,9 @@ class CI_Calendar {
public function generate($year = '', $month = '', $data = array())
{
// Set and validate the supplied month/year
- if ($year == '')
+ if (empty($year))
{
- $year = date('Y', $this->local_time);
+ $year = date('Y', $this->local_time);
}
elseif (strlen($year) === 1)
{
@@ -122,7 +171,7 @@ class CI_Calendar {
$year = '20'.$year;
}
- if ($month == '')
+ if (empty($month))
{
$month = date('m', $this->local_time);
}
@@ -141,7 +190,7 @@ class CI_Calendar {
// Set the starting day of the week
$start_days = array('sunday' => 0, 'monday' => 1, 'tuesday' => 2, 'wednesday' => 3, 'thursday' => 4, 'friday' => 5, 'saturday' => 6);
- $start_day = ( ! isset($start_days[$this->start_day])) ? 0 : $start_days[$this->start_day];
+ $start_day = isset($start_days[$this->start_day]) ? $start_days[$this->start_day] : 0;
// Set the starting day number
$local_date = mktime(12, 0, 0, $month, 1, $year);
@@ -168,17 +217,17 @@ class CI_Calendar {
$out = $this->temp['table_open']."\n\n".$this->temp['heading_row_start']."\n";
// "previous" month link
- if ($this->show_next_prev == TRUE)
+ if ($this->show_next_prev === TRUE)
{
- // Add a trailing slash to the URL if needed
- $this->next_prev_url = preg_replace('/(.+?)\/*$/', '\\1/', $this->next_prev_url);
+ // Add a trailing slash to the URL if needed
+ $this->next_prev_url = preg_replace('/(.+?)\/*$/', '\\1/', $this->next_prev_url);
$adjusted_date = $this->adjust_date($month - 1, $year);
$out .= str_replace('{previous_url}', $this->next_prev_url.$adjusted_date['year'].'/'.$adjusted_date['month'], $this->temp['heading_previous_cell'])."\n";
}
// Heading containing the month/year
- $colspan = ($this->show_next_prev == TRUE) ? 5 : 7;
+ $colspan = ($this->show_next_prev === TRUE) ? 5 : 7;
$this->temp['heading_title_cell'] = str_replace('{colspan}', $colspan,
str_replace('{heading}', $this->get_month_name($month).'&nbsp;'.$year, $this->temp['heading_title_cell']));
@@ -186,7 +235,7 @@ class CI_Calendar {
$out .= $this->temp['heading_title_cell']."\n";
// "next" month link
- if ($this->show_next_prev == TRUE)
+ if ($this->show_next_prev === TRUE)
{
$adjusted_date = $this->adjust_date($month + 1, $year);
$out .= str_replace('{next_url}', $this->next_prev_url.$adjusted_date['year'].'/'.$adjusted_date['month'], $this->temp['heading_next_cell']);
@@ -244,9 +293,7 @@ class CI_Calendar {
$out .= "\n".$this->temp['cal_row_end']."\n";
}
- $out .= "\n".$this->temp['table_close'];
-
- return $out;
+ return $out .= "\n".$this->temp['table_close'];
}
// --------------------------------------------------------------------
@@ -262,7 +309,7 @@ class CI_Calendar {
*/
public function get_month_name($month)
{
- if ($this->month_type == 'short')
+ if ($this->month_type === 'short')
{
$month_names = array('01' => 'cal_jan', '02' => 'cal_feb', '03' => 'cal_mar', '04' => 'cal_apr', '05' => 'cal_may', '06' => 'cal_jun', '07' => 'cal_jul', '08' => 'cal_aug', '09' => 'cal_sep', '10' => 'cal_oct', '11' => 'cal_nov', '12' => 'cal_dec');
}
@@ -271,14 +318,9 @@ class CI_Calendar {
$month_names = array('01' => 'cal_january', '02' => 'cal_february', '03' => 'cal_march', '04' => 'cal_april', '05' => 'cal_mayl', '06' => 'cal_june', '07' => 'cal_july', '08' => 'cal_august', '09' => 'cal_september', '10' => 'cal_october', '11' => 'cal_november', '12' => 'cal_december');
}
- $month = $month_names[$month];
-
- if ($this->CI->lang->line($month) === FALSE)
- {
- return ucfirst(substr($month, 4));
- }
-
- return $this->CI->lang->line($month);
+ return ($this->CI->lang->line($month_names[$month]) === FALSE)
+ ? ucfirst(substr($month_names[$month], 4))
+ : $this->CI->lang->line($month_names[$month]);
}
// --------------------------------------------------------------------
@@ -294,16 +336,16 @@ class CI_Calendar {
*/
public function get_day_names($day_type = '')
{
- if ($day_type != '')
+ if ($day_type !== '')
{
$this->day_type = $day_type;
}
- if ($this->day_type == 'long')
+ if ($this->day_type === 'long')
{
$day_names = array('sunday', 'monday', 'tuesday', 'wednesday', 'thursday', 'friday', 'saturday');
}
- elseif ($this->day_type == 'short')
+ elseif ($this->day_type === 'short')
{
$day_names = array('sun', 'mon', 'tue', 'wed', 'thu', 'fri', 'sat');
}
@@ -382,7 +424,7 @@ class CI_Calendar {
// Is the year a leap year?
if ($month == 2)
{
- if ($year % 400 == 0 OR ($year % 4 == 0 && $year % 100 != 0))
+ if ($year % 400 === 0 OR ($year % 4 === 0 && $year % 100 !== 0))
{
return 29;
}
@@ -402,29 +444,29 @@ class CI_Calendar {
*/
public function default_template()
{
- return array (
- 'table_open' => '<table border="0" cellpadding="4" cellspacing="0">',
- 'heading_row_start' => '<tr>',
- 'heading_previous_cell' => '<th><a href="{previous_url}">&lt;&lt;</a></th>',
- 'heading_title_cell' => '<th colspan="{colspan}">{heading}</th>',
- 'heading_next_cell' => '<th><a href="{next_url}">&gt;&gt;</a></th>',
- 'heading_row_end' => '</tr>',
- 'week_row_start' => '<tr>',
- 'week_day_cell' => '<td>{week_day}</td>',
- 'week_row_end' => '</tr>',
- 'cal_row_start' => '<tr>',
- 'cal_cell_start' => '<td>',
- 'cal_cell_start_today' => '<td>',
- 'cal_cell_content' => '<a href="{content}">{day}</a>',
- 'cal_cell_content_today' => '<a href="{content}"><strong>{day}</strong></a>',
- 'cal_cell_no_content' => '{day}',
- 'cal_cell_no_content_today' => '<strong>{day}</strong>',
- 'cal_cell_blank' => '&nbsp;',
- 'cal_cell_end' => '</td>',
- 'cal_cell_end_today' => '</td>',
- 'cal_row_end' => '</tr>',
- 'table_close' => '</table>'
- );
+ return array(
+ 'table_open' => '<table border="0" cellpadding="4" cellspacing="0">',
+ 'heading_row_start' => '<tr>',
+ 'heading_previous_cell' => '<th><a href="{previous_url}">&lt;&lt;</a></th>',
+ 'heading_title_cell' => '<th colspan="{colspan}">{heading}</th>',
+ 'heading_next_cell' => '<th><a href="{next_url}">&gt;&gt;</a></th>',
+ 'heading_row_end' => '</tr>',
+ 'week_row_start' => '<tr>',
+ 'week_day_cell' => '<td>{week_day}</td>',
+ 'week_row_end' => '</tr>',
+ 'cal_row_start' => '<tr>',
+ 'cal_cell_start' => '<td>',
+ 'cal_cell_start_today' => '<td>',
+ 'cal_cell_content' => '<a href="{content}">{day}</a>',
+ 'cal_cell_content_today' => '<a href="{content}"><strong>{day}</strong></a>',
+ 'cal_cell_no_content' => '{day}',
+ 'cal_cell_no_content_today' => '<strong>{day}</strong>',
+ 'cal_cell_blank' => '&nbsp;',
+ 'cal_cell_end' => '</td>',
+ 'cal_cell_end_today' => '</td>',
+ 'cal_row_end' => '</tr>',
+ 'table_close' => '</table>'
+ );
}
// --------------------------------------------------------------------
@@ -441,14 +483,14 @@ class CI_Calendar {
{
$this->temp = $this->default_template();
- if ($this->template == '')
+ if ($this->template === '')
{
return;
}
$today = array('cal_cell_start_today', 'cal_cell_content_today', 'cal_cell_no_content_today', 'cal_cell_end_today');
- foreach (array('table_open', 'table_close', 'heading_row_start', 'heading_previous_cell', 'heading_title_cell', 'heading_next_cell', 'heading_row_end', 'week_row_start', 'week_day_cell', 'week_row_end', 'cal_row_start', 'cal_cell_start', 'cal_cell_content', 'cal_cell_no_content', 'cal_cell_blank', 'cal_cell_end', 'cal_row_end', 'cal_cell_start_today', 'cal_cell_content_today', 'cal_cell_no_content_today', 'cal_cell_end_today') as $val)
+ foreach (array('table_open', 'table_close', 'heading_row_start', 'heading_previous_cell', 'heading_title_cell', 'heading_next_cell', 'heading_row_end', 'week_row_start', 'week_day_cell', 'week_row_end', 'cal_row_start', 'cal_cell_start', 'cal_cell_content', 'cal_cell_no_content', 'cal_cell_blank', 'cal_cell_end', 'cal_row_end', 'cal_cell_start_today', 'cal_cell_content_today', 'cal_cell_no_content_today', 'cal_cell_end_today') as $val)
{
if (preg_match('/\{'.$val.'\}(.*?)\{\/'.$val.'\}/si', $this->template, $match))
{
diff --git a/system/libraries/Cart.php b/system/libraries/Cart.php
index ca7be555e..79c2b8cdc 100644
--- a/system/libraries/Cart.php
+++ b/system/libraries/Cart.php
@@ -1,4 +1,4 @@
-<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');
+<?php
/**
* CodeIgniter
*
@@ -24,6 +24,7 @@
* @since Version 1.0
* @filesource
*/
+defined('BASEPATH') OR exit('No direct script access allowed');
/**
* Shopping Cart Class
@@ -36,19 +37,54 @@
*/
class CI_Cart {
- // These are the regular expression rules that we use to validate the product ID and product name
- public $product_id_rules = '\.a-z0-9_-'; // alpha-numeric, dashes, underscores, or periods
- public $product_name_rules = '\.\:\-_ a-z0-9'; // alpha-numeric, dashes, underscores, colons or periods
- public $product_name_safe = TRUE; // only allow safe product names
+ /**
+ * These are the regular expression rules that we use to validate the product ID and product name
+ * alpha-numeric, dashes, underscores, or periods
+ *
+ * @var string
+ */
+ public $product_id_rules = '\.a-z0-9_-';
+
+ /**
+ * These are the regular expression rules that we use to validate the product ID and product name
+ * alpha-numeric, dashes, underscores, colons or periods
+ *
+ * @var string
+ */
+ public $product_name_rules = '\.\:\-_ a-z0-9';
+ /**
+ * only allow safe product names
+ *
+ * @var bool
+ */
+ public $product_name_safe = TRUE;
+
+ // --------------------------------------------------------------------------
// Protected variables. Do not change!
+ // --------------------------------------------------------------------------
+
+ /**
+ * Reference to CodeIgniter instance
+ *
+ * @var object
+ */
protected $CI;
+
+ /**
+ * Contents of the cart
+ *
+ * @var array
+ */
protected $_cart_contents = array();
/**
* Shopping Class Constructor
*
* The constructor loads the Session class, used to store the shopping cart contents.
+ *
+ * @param array
+ * @return void
*/
public function __construct($params = array())
{
@@ -63,7 +99,7 @@ class CI_Cart {
// Grab the shopping cart array from the session table
$this->_cart_contents = $this->CI->session->userdata('cart_contents');
- if ($this->_cart_contents === FALSE)
+ if ($this->_cart_contents === NULL)
{
// No cart exists so we'll set some base values
$this->_cart_contents = array('cart_total' => 0, 'total_items' => 0);
@@ -146,7 +182,7 @@ class CI_Cart {
// --------------------------------------------------------------------
// Does the $items array contain an id, quantity, price, and name? These are required
- if ( ! isset($items['id']) OR ! isset($items['qty']) OR ! isset($items['price']) OR ! isset($items['name']))
+ if ( ! isset($items['id'], $items['qty'], $items['price'], $items['name']))
{
log_message('error', 'The cart array must contain a product ID, quantity, price, and name.');
return FALSE;
@@ -158,7 +194,7 @@ class CI_Cart {
$items['qty'] = (float) $items['qty'];
// If the quantity is zero or blank there's nothing for us to do
- if ( ! is_numeric($items['qty']) OR $items['qty'] == 0)
+ if ($items['qty'] == 0)
{
return FALSE;
}
@@ -189,15 +225,6 @@ class CI_Cart {
// Prep the price. Remove leading zeros and anything that isn't a number or decimal point.
$items['price'] = (float) $items['price'];
- // Is the price a valid number?
- if ( ! is_numeric($items['price']))
- {
- log_message('error', 'An invalid price was submitted for product ID: '.$items['id']);
- return FALSE;
- }
-
- // --------------------------------------------------------------------
-
// We now need to create a unique identifier for the item being inserted into the cart.
// Every time something is added to the cart it is stored in the master cart array.
// Each row in the cart array, however, must have a unique index that identifies not only
@@ -210,7 +237,7 @@ class CI_Cart {
// This becomes the unique "row ID"
if (isset($items['options']) && count($items['options']) > 0)
{
- $rowid = md5($items['id'].implode('', $items['options']));
+ $rowid = md5($items['id'].serialize($items['options']));
}
else
{
@@ -245,7 +272,6 @@ class CI_Cart {
* product ID and quantity for each item.
*
* @param array
- * @param string
* @return bool
*/
public function update($items = array())
@@ -308,7 +334,7 @@ class CI_Cart {
protected function _update($items = array())
{
// Without these array indexes there is nothing we can do
- if ( ! isset($items['qty']) OR ! isset($items['rowid']) OR ! isset($this->_cart_contents[$items['rowid']]))
+ if ( ! isset($items['qty'], $items['rowid'], $this->_cart_contents[$items['rowid']]))
{
return FALSE;
}
@@ -316,12 +342,6 @@ class CI_Cart {
// Prep the quantity
$items['qty'] = (float) $items['qty'];
- // Is the quantity a number?
- if ( ! is_numeric($items['qty']))
- {
- return FALSE;
- }
-
// Is the quantity zero? If so we will remove the item from the cart.
// If the quantity is greater than zero we are updating
if ($items['qty'] == 0)
@@ -350,7 +370,7 @@ class CI_Cart {
foreach ($this->_cart_contents as $key => $val)
{
// We make sure the array contains the proper indexes
- if ( ! is_array($val) OR ! isset($val['price']) OR ! isset($val['qty']))
+ if ( ! is_array($val) OR ! isset($val['price'], $val['qty']))
{
continue;
}
@@ -360,7 +380,7 @@ class CI_Cart {
$this->_cart_contents[$key]['subtotal'] = ($this->_cart_contents[$key]['price'] * $this->_cart_contents[$key]['qty']);
}
- // Is our cart empty? If so we delete it from the session
+ // Is our cart empty? If so we delete it from the session
if (count($this->_cart_contents) <= 2)
{
$this->CI->session->unset_userdata('cart_contents');
@@ -396,6 +416,7 @@ class CI_Cart {
*
* Removes an item from the cart
*
+ * @param int
* @return bool
*/
public function remove($rowid)
@@ -427,6 +448,7 @@ class CI_Cart {
*
* Returns the entire cart array
*
+ * @param bool
* @return array
*/
public function contents($newest_first = FALSE)
@@ -444,16 +466,34 @@ class CI_Cart {
// --------------------------------------------------------------------
/**
+ * Get cart item
+ *
+ * Returns the details of a specific item in the cart
+ *
+ * @param string $row_id
+ * @return array
+ */
+ public function get_item($row_id)
+ {
+ return (in_array($row_id, array('total_items', 'cart_total'), TRUE) OR ! isset($this->_cart_contents[$row_id]))
+ ? FALSE
+ : $this->_cart_contents[$row_id];
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
* Has options
*
* Returns TRUE if the rowid passed to this function correlates to an item
* that has options associated with it.
*
+ * @param string $row_id = ''
* @return bool
*/
- public function has_options($rowid = '')
+ public function has_options($row_id = '')
{
- return (isset($this->_cart_contents[$rowid]['options']) && count($this->_cart_contents[$rowid]['options']) !== 0) ? TRUE : FALSE;
+ return (isset($this->_cart_contents[$row_id]['options']) && count($this->_cart_contents[$row_id]['options']) !== 0);
}
// --------------------------------------------------------------------
@@ -463,12 +503,12 @@ class CI_Cart {
*
* Returns the an array of options, for a particular product row ID
*
- * @param int
+ * @param string $row_id = ''
* @return array
*/
- public function product_options($rowid = '')
+ public function product_options($row_id = '')
{
- return isset($this->_cart_contents[$rowid]['options']) ? $this->_cart_contents[$rowid]['options'] : array();
+ return isset($this->_cart_contents[$row_id]['options']) ? $this->_cart_contents[$row_id]['options'] : array();
}
// --------------------------------------------------------------------
@@ -483,15 +523,7 @@ class CI_Cart {
*/
public function format_number($n = '')
{
- if ($n == '')
- {
- return '';
- }
-
- // Remove anything that isn't a number or decimal point.
- $n = (float) $n;
-
- return number_format($n, 2, '.', ',');
+ return ($n === '') ? '' : number_format( (float) $n, 2, '.', ',');
}
// --------------------------------------------------------------------
diff --git a/system/libraries/Driver.php b/system/libraries/Driver.php
index f409f47d4..8323e8f01 100644
--- a/system/libraries/Driver.php
+++ b/system/libraries/Driver.php
@@ -1,4 +1,4 @@
-<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');
+<?php
/**
* CodeIgniter
*
@@ -24,6 +24,7 @@
* @since Version 1.0
* @filesource
*/
+defined('BASEPATH') OR exit('No direct script access allowed');
/**
* CodeIgniter Driver Library Class
@@ -39,67 +40,149 @@
*/
class CI_Driver_Library {
- protected $valid_drivers = array();
- protected static $lib_name;
+ /**
+ * Array of drivers that are available to use with the driver class
+ *
+ * @var array
+ */
+ protected $valid_drivers = array();
+
+ /**
+ * Name of the current class - usually the driver class
+ *
+ * @var string
+ */
+ protected $lib_name;
- // The first time a child is used it won't exist, so we instantiate it
- // subsequents calls will go straight to the proper child.
+ /**
+ * Get magic method
+ *
+ * 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
+ */
public function __get($child)
{
+ // Try to load the driver
+ return $this->load_driver($child);
+ }
+
+ /**
+ * Load driver
+ *
+ * Separate load_driver call to support explicit driver load by library or user
+ *
+ * @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;
- // Remove the CI_ prefix and lowercase
- $lib_name = ucfirst(strtolower(str_replace('CI_', '', $this->lib_name)));
- $driver_name = strtolower(str_replace('CI_', '', $child_class));
+ // 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);
+ }
+
+ // 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))
+ {
+ if (class_exists($child_name))
+ {
+ $class_name = $child_name;
+ }
+ else
+ {
+ $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;
}
}
+// --------------------------------------------------------------------------
+
/**
* CodeIgniter Driver Class
*
@@ -114,11 +197,33 @@ class CI_Driver_Library {
*/
class CI_Driver {
+ /**
+ * Instance of the parent class
+ *
+ * @var object
+ */
protected $_parent;
+ /**
+ * List of methods in the parent class
+ *
+ * @var array
+ */
protected $_methods = array();
+
+ /**
+ * List of properties in the parent class
+ *
+ * @var array
+ */
protected $_properties = array();
+ /**
+ * Array of methods and properties for the parent class(es)
+ *
+ * @static
+ * @var array
+ */
protected static $_reflections = array();
/**
diff --git a/system/libraries/Email.php b/system/libraries/Email.php
index 48c3bf3ab..5d8fc8aea 100644
--- a/system/libraries/Email.php
+++ b/system/libraries/Email.php
@@ -1,4 +1,4 @@
-<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');
+<?php
/**
* CodeIgniter
*
@@ -24,6 +24,7 @@
* @since Version 1.0
* @filesource
*/
+defined('BASEPATH') OR exit('No direct script access allowed');
/**
* CodeIgniter Email Class
@@ -38,74 +39,364 @@
*/
class CI_Email {
+ /**
+ * Used as the User-Agent and X-Mailer headers' value.
+ *
+ * @var string
+ */
public $useragent = 'CodeIgniter';
+
+ /**
+ * Path to the Sendmail binary.
+ *
+ * @var string
+ */
public $mailpath = '/usr/sbin/sendmail'; // Sendmail path
+
+ /**
+ * Which method to use for sending e-mails.
+ *
+ * @var string 'mail', 'sendmail' or 'smtp'
+ */
public $protocol = 'mail'; // mail/sendmail/smtp
- public $smtp_host = ''; // SMTP Server. Example: mail.earthlink.net
- public $smtp_user = ''; // SMTP Username
- public $smtp_pass = ''; // SMTP Password
- public $smtp_port = 25; // SMTP Port
- public $smtp_timeout = 5; // SMTP Timeout in seconds
- public $smtp_crypto = ''; // SMTP Encryption. Can be null, tls or ssl.
- public $wordwrap = TRUE; // TRUE/FALSE Turns word-wrap on/off
- public $wrapchars = 76; // Number of characters to wrap at.
- public $mailtype = 'text'; // text/html Defines email formatting
- public $charset = 'utf-8'; // Default char set: iso-8859-1 or us-ascii
+
+ /**
+ * STMP Server host
+ *
+ * @var string
+ */
+ public $smtp_host = '';
+
+ /**
+ * SMTP Username
+ *
+ * @var string
+ */
+ public $smtp_user = '';
+
+ /**
+ * SMTP Password
+ *
+ * @var string
+ */
+ public $smtp_pass = '';
+
+ /**
+ * SMTP Server port
+ *
+ * @var int
+ */
+ public $smtp_port = 25;
+
+ /**
+ * SMTP connection timeout in seconds
+ *
+ * @var int
+ */
+ public $smtp_timeout = 5;
+
+ /**
+ * SMTP Encryption
+ *
+ * @var string NULL, 'tls' or 'ssl'
+ */
+ public $smtp_crypto = NULL;
+
+ /**
+ * Whether to apply word-wrapping to the message body.
+ *
+ * @var bool
+ */
+ public $wordwrap = TRUE;
+
+ /**
+ * Number of characters to wrap at.
+ *
+ * @see CI_Email::$wordwrap
+ * @var int
+ */
+ public $wrapchars = 76;
+
+ /**
+ * Message format.
+ *
+ * @var string 'text' or 'html'
+ */
+ public $mailtype = 'text';
+
+ /**
+ * Character set (default: utf-8)
+ *
+ * @var string
+ */
+ public $charset = 'utf-8';
+
+ /**
+ * Multipart message
+ *
+ * @var string 'mixed' (in the body) or 'related' (separate)
+ */
public $multipart = 'mixed'; // "mixed" (in the body) or "related" (separate)
- public $alt_message = ''; // Alternative message for HTML emails
- public $validate = FALSE; // TRUE/FALSE. Enables email validation
+
+ /**
+ * Alternative message (for HTML messages only)
+ *
+ * @var string
+ */
+ public $alt_message = '';
+
+ /**
+ * Whether to validate e-mail addresses.
+ *
+ * @var bool
+ */
+ public $validate = FALSE;
+
+ /**
+ * X-Priority header value.
+ *
+ * @var int 1-5
+ */
public $priority = 3; // Default priority (1 - 5)
+
+ /**
+ * Newline character sequence.
+ * Use "\r\n" to comply with RFC 822.
+ *
+ * @link http://www.ietf.org/rfc/rfc822.txt
+ * @var string "\r\n" or "\n"
+ */
public $newline = "\n"; // Default newline. "\r\n" or "\n" (Use "\r\n" to comply with RFC 822)
- public $crlf = "\n"; // The RFC 2045 compliant CRLF for quoted-printable is "\r\n". Apparently some servers,
- // even on the receiving end think they need to muck with CRLFs, so using "\n", while
- // distasteful, is the only thing that seems to work for all environments.
- public $dsn = FALSE; // Delivery Status Notification
- public $send_multipart = TRUE; // TRUE/FALSE - Yahoo does not like multipart alternative, so this is an override. Set to FALSE for Yahoo.
- public $bcc_batch_mode = FALSE; // TRUE/FALSE - Turns on/off Bcc batch feature
- public $bcc_batch_size = 200; // If bcc_batch_mode = TRUE, sets max number of Bccs in each batch
+ /**
+ * CRLF character sequence
+ *
+ * RFC 2045 specifies that for 'quoted-printable' encoding,
+ * "\r\n" must be used. However, it appears that some servers
+ * (even on the receiving end) don't handle it properly and
+ * switching to "\n", while improper, is the only solution
+ * that seems to work for all environments.
+ *
+ * @link http://www.ietf.org/rfc/rfc822.txt
+ * @var string
+ */
+ public $crlf = "\n";
+
+ /**
+ * Whether to use Delivery Status Notification.
+ *
+ * @var bool
+ */
+ public $dsn = FALSE;
+
+ /**
+ * Whether to send multipart alternatives.
+ * Yahoo! doesn't seem to like these.
+ *
+ * @var bool
+ */
+ public $send_multipart = TRUE;
+
+ /**
+ * Whether to send messages to BCC recipients in batches.
+ *
+ * @var bool
+ */
+ public $bcc_batch_mode = FALSE;
+
+ /**
+ * BCC Batch max number size.
+ *
+ * @see CI_Email::$bcc_batch_mode
+ * @var int
+ */
+ public $bcc_batch_size = 200;
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Whether PHP is running in safe mode. Initialized by the class constructor.
+ *
+ * @var bool
+ */
protected $_safe_mode = FALSE;
+
+ /**
+ * Subject header
+ *
+ * @var string
+ */
protected $_subject = '';
+
+ /**
+ * Message body
+ *
+ * @var string
+ */
protected $_body = '';
+
+ /**
+ * Final message body to be sent.
+ *
+ * @var string
+ */
protected $_finalbody = '';
+
+ /**
+ * multipart/alternative boundary
+ *
+ * @var string
+ */
protected $_alt_boundary = '';
+
+ /**
+ * Attachment boundary
+ *
+ * @var string
+ */
protected $_atc_boundary = '';
+
+ /**
+ * Final headers to send
+ *
+ * @var string
+ */
protected $_header_str = '';
+
+ /**
+ * SMTP Connection socket placeholder
+ *
+ * @var resource
+ */
protected $_smtp_connect = '';
+
+ /**
+ * Mail encoding
+ *
+ * @var string '8bit' or '7bit'
+ */
protected $_encoding = '8bit';
- protected $_IP = FALSE;
+
+ /**
+ * Whether to perform SMTP authentication
+ *
+ * @var bool
+ */
protected $_smtp_auth = FALSE;
+
+ /**
+ * Whether to send a Reply-To header
+ *
+ * @var bool
+ */
protected $_replyto_flag = FALSE;
+
+ /**
+ * Debug messages
+ *
+ * @see CI_Email::print_debugger()
+ * @var string
+ */
protected $_debug_msg = array();
+
+ /**
+ * Recipients
+ *
+ * @var string[]
+ */
protected $_recipients = array();
+
+ /**
+ * CC Recipients
+ *
+ * @var string[]
+ */
protected $_cc_array = array();
+
+ /**
+ * BCC Recipients
+ *
+ * @var string[]
+ */
protected $_bcc_array = array();
+
+ /**
+ * Message headers
+ *
+ * @var string[]
+ */
protected $_headers = array();
- protected $_attach_name = array();
- protected $_attach_type = array();
- protected $_attach_disp = array();
+
+ /**
+ * Attachment data
+ *
+ * @var array
+ */
+ protected $_attachments = array();
+
+ /**
+ * Valid $protocol values
+ *
+ * @see CI_Email::$protocol
+ * @var string[]
+ */
protected $_protocols = array('mail', 'sendmail', 'smtp');
- protected $_base_charsets = array('us-ascii', 'iso-2022-'); // 7-bit charsets (excluding language suffix)
+
+ /**
+ * Base charsets
+ *
+ * Character sets valid for 7-bit encoding,
+ * excluding language suffix.
+ *
+ * @var string[]
+ */
+ protected $_base_charsets = array('us-ascii', 'iso-2022-');
+
+ /**
+ * Bit depths
+ *
+ * Valid mail encodings
+ *
+ * @see CI_Email::$_encoding
+ * @var string[]
+ */
protected $_bit_depths = array('7bit', '8bit');
+
+ /**
+ * $priority translations
+ *
+ * Actual values to send with the X-Priority header
+ *
+ * @var string[]
+ */
protected $_priorities = array('1 (Highest)', '2 (High)', '3 (Normal)', '4 (Low)', '5 (Lowest)');
+ // --------------------------------------------------------------------
+
/**
* Constructor - Sets Email Preferences
*
* The constructor can be passed an array of config values
+ *
+ * @param array $config = array()
+ * @return void
*/
public function __construct($config = array())
{
+ $this->charset = config_item('charset');
+
if (count($config) > 0)
{
$this->initialize($config);
}
else
{
- $this->_smtp_auth = ! ($this->smtp_user == '' && $this->smtp_pass == '');
+ $this->_smtp_auth = ! ($this->smtp_user === '' && $this->smtp_pass === '');
$this->_safe_mode = (bool) @ini_get('safe_mode');
}
+ $this->charset = strtoupper($this->charset);
+
log_message('debug', 'Email Class Initialized');
}
@@ -137,7 +428,7 @@ class CI_Email {
}
$this->clear();
- $this->_smtp_auth = ! ($this->smtp_user == '' && $this->smtp_pass == '');
+ $this->_smtp_auth = ! ($this->smtp_user === '' && $this->smtp_pass === '');
$this->_safe_mode = (bool) @ini_get('safe_mode');
return $this;
@@ -164,14 +455,12 @@ class CI_Email {
$this->_headers = array();
$this->_debug_msg = array();
- $this->_set_header('User-Agent', $this->useragent);
- $this->_set_header('Date', $this->_set_date());
+ $this->set_header('User-Agent', $this->useragent);
+ $this->set_header('Date', $this->_set_date());
if ($clear_attachments !== FALSE)
{
- $this->_attach_name = array();
- $this->_attach_type = array();
- $this->_attach_disp = array();
+ $this->_attachments = array();
}
return $this;
@@ -182,11 +471,12 @@ class CI_Email {
/**
* Set FROM
*
- * @param string
- * @param string
+ * @param string $from
+ * @param string $name
+ * @param string $return_path = NULL Return-Path
* @return object
*/
- public function from($from, $name = '')
+ public function from($from, $name = '', $return_path = NULL)
{
if (preg_match('/\<(.*)\>/', $from, $match))
{
@@ -196,10 +486,14 @@ class CI_Email {
if ($this->validate)
{
$this->validate_email($this->_str_to_array($from));
+ if ($return_path)
+ {
+ $this->validate_email($this->_str_to_array($return_path));
+ }
}
// prepare the display name
- if ($name != '')
+ if ($name !== '')
{
// only use Q encoding if there are characters that would require it
if ( ! preg_match('/[\200-\377]/', $name))
@@ -209,12 +503,14 @@ class CI_Email {
}
else
{
- $name = $this->_prep_q_encoding($name, TRUE);
+ $name = $this->_prep_q_encoding($name);
}
}
- $this->_set_header('From', $name.' <'.$from.'>');
- $this->_set_header('Return-Path', '<'.$from.'>');
+ $this->set_header('From', $name.' <'.$from.'>');
+
+ isset($return_path) OR $return_path = $from;
+ $this->set_header('Return-Path', '<'.$return_path.'>');
return $this;
}
@@ -240,17 +536,17 @@ class CI_Email {
$this->validate_email($this->_str_to_array($replyto));
}
- if ($name == '')
+ if ($name === '')
{
$name = $replyto;
}
- if (strncmp($name, '"', 1) !== 0)
+ if (strpos($name, '"') !== 0)
{
$name = '"'.$name.'"';
}
- $this->_set_header('Reply-To', $name.' <'.$replyto.'>');
+ $this->set_header('Reply-To', $name.' <'.$replyto.'>');
$this->_replyto_flag = TRUE;
return $this;
@@ -276,19 +572,10 @@ class CI_Email {
if ($this->_get_protocol() !== 'mail')
{
- $this->_set_header('To', implode(', ', $to));
+ $this->set_header('To', implode(', ', $to));
}
- switch ($this->_get_protocol())
- {
- case 'smtp':
- $this->_recipients = $to;
- break;
- case 'sendmail':
- case 'mail':
- $this->_recipients = implode(', ', $to);
- break;
- }
+ $this->_recipients = $to;
return $this;
}
@@ -303,15 +590,14 @@ class CI_Email {
*/
public function cc($cc)
{
- $cc = $this->_str_to_array($cc);
- $cc = $this->clean_email($cc);
+ $cc = $this->clean_email($this->_str_to_array($cc));
if ($this->validate)
{
$this->validate_email($cc);
}
- $this->_set_header('Cc', implode(', ', $cc));
+ $this->set_header('Cc', implode(', ', $cc));
if ($this->_get_protocol() === 'smtp')
{
@@ -332,14 +618,13 @@ class CI_Email {
*/
public function bcc($bcc, $limit = '')
{
- if ($limit != '' && is_numeric($limit))
+ if ($limit !== '' && is_numeric($limit))
{
$this->bcc_batch_mode = TRUE;
$this->bcc_batch_size = $limit;
}
- $bcc = $this->_str_to_array($bcc);
- $bcc = $this->clean_email($bcc);
+ $bcc = $this->clean_email($this->_str_to_array($bcc));
if ($this->validate)
{
@@ -352,7 +637,7 @@ class CI_Email {
}
else
{
- $this->_set_header('Bcc', implode(', ', $bcc));
+ $this->set_header('Bcc', implode(', ', $bcc));
}
return $this;
@@ -369,7 +654,7 @@ class CI_Email {
public function subject($subject)
{
$subject = $this->_prep_q_encoding($subject);
- $this->_set_header('Subject', $subject);
+ $this->set_header('Subject', $subject);
return $this;
}
@@ -404,14 +689,20 @@ class CI_Email {
/**
* Assign file attachments
*
- * @param string
+ * @param string $filename
+ * @param string $disposition = 'attachment'
+ * @param string $newname = NULL
+ * @param string $mime = ''
* @return object
*/
public function attach($filename, $disposition = '', $newname = NULL, $mime = '')
{
- $this->_attach_name[] = array($filename, $newname);
- $this->_attach_disp[] = empty($disposition) ? 'attachment' : $disposition; // Can also be 'inline' Not sure if it matters
- $this->_attach_type[] = $mime;
+ $this->_attachments[] = array(
+ 'name' => array($filename, $newname),
+ 'disposition' => empty($disposition) ? 'attachment' : $disposition, // Can also be 'inline' Not sure if it matters
+ 'type' => $mime
+ );
+
return $this;
}
@@ -424,7 +715,7 @@ class CI_Email {
* @param string
* @return void
*/
- protected function _set_header($header, $value)
+ public function set_header($header, $value)
{
$this->_headers[$header] = $value;
}
@@ -441,15 +732,11 @@ class CI_Email {
{
if ( ! is_array($email))
{
- if (strpos($email, ',') !== FALSE)
- {
- $email = preg_split('/[\s,]/', $email, -1, PREG_SPLIT_NO_EMPTY);
- }
- else
- {
- $email = (array) trim($email);
- }
+ return (strpos($email, ',') !== FALSE)
+ ? preg_split('/[\s,]/', $email, -1, PREG_SPLIT_NO_EMPTY)
+ : (array) trim($email);
}
+
return $email;
}
@@ -477,7 +764,7 @@ class CI_Email {
*/
public function set_mailtype($type = 'text')
{
- $this->mailtype = ($type == 'html') ? 'html' : 'text';
+ $this->mailtype = ($type === 'html') ? 'html' : 'text';
return $this;
}
@@ -574,7 +861,7 @@ class CI_Email {
protected function _get_message_id()
{
$from = str_replace(array('>', '<'), '', $this->_headers['Return-Path']);
- return '<'.uniqid('').strstr($from, '@').'>';
+ return '<'.uniqid('').strstr($from, '@').'>';
}
// --------------------------------------------------------------------
@@ -590,7 +877,7 @@ class CI_Email {
$this->protocol = strtolower($this->protocol);
in_array($this->protocol, $this->_protocols, TRUE) OR $this->protocol = 'mail';
- if ($return == TRUE)
+ if ($return === TRUE)
{
return $this->protocol;
}
@@ -610,13 +897,13 @@ class CI_Email {
foreach ($this->_base_charsets as $charset)
{
- if (strncmp($charset, $this->charset, strlen($charset)) === 0)
+ if (strpos($charset, $this->charset) === 0)
{
$this->_encoding = '7bit';
}
}
- if ($return == TRUE)
+ if ($return === TRUE)
{
return $this->_encoding;
}
@@ -631,15 +918,11 @@ class CI_Email {
*/
protected function _get_content_type()
{
- if ($this->mailtype === 'html' && count($this->_attach_name) === 0)
- {
- return 'html';
- }
- elseif ($this->mailtype === 'html' && count($this->_attach_name) > 0)
+ if ($this->mailtype === 'html')
{
- return 'html-attach';
+ return (count($this->_attachments) === 0) ? 'html' : 'html-attach';
}
- elseif ($this->mailtype === 'text' && count($this->_attach_name) > 0)
+ elseif ($this->mailtype === 'text' && count($this->_attachments) > 0)
{
return 'plain-attach';
}
@@ -659,7 +942,7 @@ class CI_Email {
protected function _set_date()
{
$timezone = date('Z');
- $operator = (strncmp($timezone, '-', 1) === 0) ? '-' : '+';
+ $operator = ($timezone[0] === '-') ? '-' : '+';
$timezone = abs($timezone);
$timezone = floor($timezone/3600) * 100 + ($timezone % 3600) / 60;
@@ -714,9 +997,9 @@ class CI_Email {
* @param string
* @return bool
*/
- public function valid_email($address)
+ public function valid_email($email)
{
- return (bool) preg_match('/^([a-z0-9\+_\-]+)(\.[a-z0-9\+_\-]+)*@([a-z0-9\-]+\.)+[a-z]{2,6}$/ix', $address);
+ return (bool) filter_var($email, FILTER_VALIDATE_EMAIL);
}
// --------------------------------------------------------------------
@@ -731,7 +1014,7 @@ class CI_Email {
{
if ( ! is_array($email))
{
- return (preg_match('/\<(.*)\>/', $email, $match)) ? $match[1] : $email;
+ return preg_match('/\<(.*)\>/', $email, $match) ? $match[1] : $email;
}
$clean_email = array();
@@ -749,8 +1032,8 @@ class CI_Email {
/**
* Build alternative plain text message
*
- * This public function provides the raw message for use
- * in plain-text headers of HTML-formatted emails.
+ * Provides the raw message for use in plain-text headers of
+ * HTML-formatted emails.
* If the user hasn't specified his own alternative message
* it creates one by stripping the HTML
*
@@ -758,12 +1041,14 @@ class CI_Email {
*/
protected function _get_alt_message()
{
- if ($this->alt_message != '')
+ if ( ! empty($this->alt_message))
{
- return $this->word_wrap($this->alt_message, '76');
+ return ($this->wordwrap)
+ ? $this->word_wrap($this->alt_message, 76)
+ : $this->alt_message;
}
- $body = (preg_match('/\<body.*?\>(.*)\<\/body\>/si', $this->_body, $match)) ? $match[1] : $this->_body;
+ $body = preg_match('/\<body.*?\>(.*)\<\/body\>/si', $this->_body, $match) ? $match[1] : $this->_body;
$body = str_replace("\t", '', preg_replace('#<!--(.*)--\>#', '', trim(strip_tags($body))));
for ($i = 20; $i >= 3; $i--)
@@ -771,7 +1056,12 @@ class CI_Email {
$body = str_replace(str_repeat("\n", $i), "\n\n", $body);
}
- return $this->word_wrap($body, 76);
+ // Reduce multiple spaces
+ $body = preg_replace('| +|', ' ', $body);
+
+ return ($this->wordwrap)
+ ? $this->word_wrap($body, 76)
+ : $body;
}
// --------------------------------------------------------------------
@@ -780,45 +1070,45 @@ class CI_Email {
* Word Wrap
*
* @param string
- * @param int
+ * @param int line-length limit
* @return string
*/
- public function word_wrap($str, $charlim = '')
+ public function word_wrap($str, $charlim = NULL)
{
- // Se the character limit
- if ($charlim == '')
+ // Set the character limit, if not already present
+ if (empty($charlim))
{
- $charlim = ($this->wrapchars == "") ? 76 : $this->wrapchars;
+ $charlim = empty($this->wrapchars) ? 76 : $this->wrapchars;
}
- // Reduce multiple spaces
- $str = preg_replace("| +|", " ", $str);
-
// Standardize newlines
if (strpos($str, "\r") !== FALSE)
{
$str = str_replace(array("\r\n", "\r"), "\n", $str);
}
+ // Reduce multiple spaces at end of line
+ $str = preg_replace('| +\n|', "\n", $str);
+
// If the current word is surrounded by {unwrap} tags we'll
// strip the entire chunk and replace it with a marker.
$unwrap = array();
- if (preg_match_all("|(\{unwrap\}.+?\{/unwrap\})|s", $str, $matches))
+ if (preg_match_all('|(\{unwrap\}.+?\{/unwrap\})|s', $str, $matches))
{
for ($i = 0, $c = count($matches[0]); $i < $c; $i++)
{
$unwrap[] = $matches[1][$i];
- $str = str_replace($matches[1][$i], "{{unwrapped".$i."}}", $str);
+ $str = str_replace($matches[1][$i], '{{unwrapped'.$i.'}}', $str);
}
}
// Use PHP's native public function to do the initial wordwrap.
// We set the cut flag to FALSE so that any individual words that are
- // too long get left alone. In the next step we'll deal with them.
+ // too long get left alone. In the next step we'll deal with them.
$str = wordwrap($str, $charlim, "\n", FALSE);
// Split the string into individual lines of text and cycle through them
- $output = "";
+ $output = '';
foreach (explode("\n", $str) as $line)
{
// Is the line within the allowed character count?
@@ -833,7 +1123,7 @@ class CI_Email {
do
{
// If the over-length word is a URL we won't wrap it
- if (preg_match("!\[url.+\]|://|wwww.!", $line))
+ if (preg_match('!\[url.+\]|://|wwww.!', $line))
{
break;
}
@@ -846,7 +1136,7 @@ class CI_Email {
// If $temp contains data it means we had to split up an over-length
// word into smaller chunks so we'll add it back to our current line
- if ($temp != '')
+ if ($temp !== '')
{
$output .= $temp.$this->newline;
}
@@ -859,7 +1149,7 @@ class CI_Email {
{
foreach ($unwrap as $key => $val)
{
- $output = str_replace("{{unwrapped".$key."}}", $val, $output);
+ $output = str_replace('{{unwrapped'.$key.'}}', $val, $output);
}
}
@@ -875,11 +1165,11 @@ class CI_Email {
*/
protected function _build_headers()
{
- $this->_set_header('X-Sender', $this->clean_email($this->_headers['From']));
- $this->_set_header('X-Mailer', $this->useragent);
- $this->_set_header('X-Priority', $this->_priorities[$this->priority - 1]);
- $this->_set_header('Message-ID', $this->_get_message_id());
- $this->_set_header('Mime-Version', '1.0');
+ $this->set_header('X-Sender', $this->clean_email($this->_headers['From']));
+ $this->set_header('X-Mailer', $this->useragent);
+ $this->set_header('X-Priority', $this->_priorities[$this->priority - 1]);
+ $this->set_header('Message-ID', $this->_get_message_id());
+ $this->set_header('Mime-Version', '1.0');
}
// --------------------------------------------------------------------
@@ -898,15 +1188,15 @@ class CI_Email {
}
reset($this->_headers);
- $this->_header_str = "";
+ $this->_header_str = '';
foreach ($this->_headers as $key => $val)
{
$val = trim($val);
- if ($val != "")
+ if ($val !== '')
{
- $this->_header_str .= $key.": ".$val.$this->newline;
+ $this->_header_str .= $key.': '.$val.$this->newline;
}
}
@@ -940,8 +1230,8 @@ class CI_Email {
{
case 'plain' :
- $hdr .= "Content-Type: text/plain; charset=" . $this->charset . $this->newline
- . "Content-Transfer-Encoding: " . $this->_get_encoding();
+ $hdr .= 'Content-Type: text/plain; charset='.$this->charset.$this->newline
+ .'Content-Transfer-Encoding: '.$this->_get_encoding();
if ($this->_get_protocol() === 'mail')
{
@@ -959,26 +1249,25 @@ class CI_Email {
if ($this->send_multipart === FALSE)
{
- $hdr .= "Content-Type: text/html; charset=" . $this->charset . $this->newline
- . "Content-Transfer-Encoding: quoted-printable";
+ $hdr .= 'Content-Type: text/html; charset='.$this->charset.$this->newline
+ .'Content-Transfer-Encoding: quoted-printable';
}
else
{
- $hdr .= "Content-Type: multipart/alternative; boundary=\"" . $this->_alt_boundary . "\"" . $this->newline . $this->newline;
+ $hdr .= 'Content-Type: multipart/alternative; boundary="'.$this->_alt_boundary.'"'.$this->newline.$this->newline;
- $body .= $this->_get_mime_message() . $this->newline . $this->newline
- . "--" . $this->_alt_boundary . $this->newline
+ $body .= $this->_get_mime_message().$this->newline.$this->newline
+ .'--'.$this->_alt_boundary.$this->newline
- . "Content-Type: text/plain; charset=" . $this->charset . $this->newline
- . "Content-Transfer-Encoding: " . $this->_get_encoding() . $this->newline . $this->newline
- . $this->_get_alt_message() . $this->newline . $this->newline . "--" . $this->_alt_boundary . $this->newline
+ .'Content-Type: text/plain; charset='.$this->charset.$this->newline
+ .'Content-Transfer-Encoding: '.$this->_get_encoding().$this->newline.$this->newline
+ .$this->_get_alt_message().$this->newline.$this->newline.'--'.$this->_alt_boundary.$this->newline
- . "Content-Type: text/html; charset=" . $this->charset . $this->newline
- . "Content-Transfer-Encoding: quoted-printable" . $this->newline . $this->newline;
+ .'Content-Type: text/html; charset='.$this->charset.$this->newline
+ .'Content-Transfer-Encoding: quoted-printable'.$this->newline.$this->newline;
}
- $this->_finalbody = $body . $this->_prep_quoted_printable($this->_body) . $this->newline . $this->newline;
-
+ $this->_finalbody = $body.$this->_prep_quoted_printable($this->_body).$this->newline.$this->newline;
if ($this->_get_protocol() === 'mail')
{
@@ -986,72 +1275,72 @@ class CI_Email {
}
else
{
- $this->_finalbody = $hdr . $this->_finalbody;
+ $this->_finalbody = $hdr.$this->_finalbody;
}
-
if ($this->send_multipart !== FALSE)
{
- $this->_finalbody .= "--" . $this->_alt_boundary . "--";
+ $this->_finalbody .= '--'.$this->_alt_boundary.'--';
}
return;
case 'plain-attach' :
- $hdr .= "Content-Type: multipart/".$this->multipart."; boundary=\"" . $this->_atc_boundary."\"" . $this->newline . $this->newline;
+ $hdr .= 'Content-Type: multipart/'.$this->multipart.'; boundary="'.$this->_atc_boundary.'"'.$this->newline.$this->newline;
if ($this->_get_protocol() === 'mail')
{
$this->_header_str .= $hdr;
}
- $body .= $this->_get_mime_message() . $this->newline . $this->newline
- . "--" . $this->_atc_boundary . $this->newline
+ $body .= $this->_get_mime_message().$this->newline.$this->newline
+ .'--'.$this->_atc_boundary.$this->newline
- . "Content-Type: text/plain; charset=" . $this->charset . $this->newline
- . "Content-Transfer-Encoding: " . $this->_get_encoding() . $this->newline . $this->newline
+ .'Content-Type: text/plain; charset='.$this->charset.$this->newline
+ .'Content-Transfer-Encoding: '.$this->_get_encoding().$this->newline.$this->newline
- . $this->_body . $this->newline . $this->newline;
+ .$this->_body.$this->newline.$this->newline;
break;
case 'html-attach' :
- $hdr .= "Content-Type: multipart/".$this->multipart."; boundary=\"" . $this->_atc_boundary."\"" . $this->newline . $this->newline;
+ $hdr .= 'Content-Type: multipart/'.$this->multipart.'; boundary="'.$this->_atc_boundary.'"'.$this->newline.$this->newline;
if ($this->_get_protocol() === 'mail')
{
$this->_header_str .= $hdr;
}
- $body .= $this->_get_mime_message() . $this->newline . $this->newline
- . "--" . $this->_atc_boundary . $this->newline
+ $body .= $this->_get_mime_message().$this->newline.$this->newline
+ .'--'.$this->_atc_boundary.$this->newline
- . "Content-Type: multipart/alternative; boundary=\"" . $this->_alt_boundary . "\"" . $this->newline .$this->newline
- . "--" . $this->_alt_boundary . $this->newline
+ .'Content-Type: multipart/alternative; boundary="'.$this->_alt_boundary.'"'.$this->newline.$this->newline
+ .'--'.$this->_alt_boundary.$this->newline
- . "Content-Type: text/plain; charset=" . $this->charset . $this->newline
- . "Content-Transfer-Encoding: " . $this->_get_encoding() . $this->newline . $this->newline
- . $this->_get_alt_message() . $this->newline . $this->newline . "--" . $this->_alt_boundary . $this->newline
+ .'Content-Type: text/plain; charset='.$this->charset.$this->newline
+ .'Content-Transfer-Encoding: '.$this->_get_encoding().$this->newline.$this->newline
+ .$this->_get_alt_message().$this->newline.$this->newline.'--'.$this->_alt_boundary.$this->newline
- . "Content-Type: text/html; charset=" . $this->charset . $this->newline
- . "Content-Transfer-Encoding: quoted-printable" . $this->newline . $this->newline
+ .'Content-Type: text/html; charset='.$this->charset.$this->newline
+ .'Content-Transfer-Encoding: quoted-printable'.$this->newline.$this->newline
- . $this->_prep_quoted_printable($this->_body) . $this->newline . $this->newline
- . "--" . $this->_alt_boundary . "--" . $this->newline . $this->newline;
+ .$this->_prep_quoted_printable($this->_body).$this->newline.$this->newline
+ .'--'.$this->_alt_boundary.'--'.$this->newline.$this->newline;
break;
}
$attachment = array();
- for ($i = 0, $c = count($this->_attach_name), $z = 0; $i < $c; $i++)
+ for ($i = 0, $c = count($this->_attachments), $z = 0; $i < $c; $i++)
{
- $filename = $this->_attach_name[$i][0];
- $basename = (is_null($this->_attach_name[$i][1])) ? basename($filename) : $this->_attach_name[$i][1];
- $ctype = $this->_attach_type[$i];
+ $filename = $this->_attachments[$i]['name'][0];
+ $basename = is_null($this->_attachments[$i]['name'][1])
+ ? basename($filename) : $this->_attachments[$i]['name'][1];
+ $ctype = $this->_attachments[$i]['type'];
$file_content = '';
- if ($this->_attach_type[$i] == '')
+ if ($ctype === '')
{
if ( ! file_exists($filename))
{
@@ -1073,19 +1362,20 @@ class CI_Email {
}
else
{
- $file_content =& $this->_attach_content[$i];
+ $file_content =& $this->_attachments[$i]['name'][0];
}
- $attachment[$z++] = "--".$this->_atc_boundary.$this->newline
- . "Content-type: ".$ctype."; "
- . "name=\"".$basename."\"".$this->newline
- . "Content-Disposition: ".$this->_attach_disp[$i].";".$this->newline
- . "Content-Transfer-Encoding: base64".$this->newline;
+
+ $attachment[$z++] = '--'.$this->_atc_boundary.$this->newline
+ .'Content-type: '.$ctype.'; '
+ .'name="'.$basename.'"'.$this->newline
+ .'Content-Disposition: '.$this->_attachments[$i]['disposition'].';'.$this->newline
+ .'Content-Transfer-Encoding: base64'.$this->newline;
$attachment[$z++] = chunk_split(base64_encode($file_content));
}
- $body .= implode($this->newline, $attachment).$this->newline."--".$this->_atc_boundary."--";
- $this->_finalbody = ($this->_get_protocol() === 'mail') ? $body : $hdr . $body;
+ $body .= implode($this->newline, $attachment).$this->newline.'--'.$this->_atc_boundary.'--';
+ $this->_finalbody = ($this->_get_protocol() === 'mail') ? $body : $hdr.$body;
return;
}
@@ -1098,21 +1388,32 @@ class CI_Email {
* Refer to RFC 2045 http://www.ietf.org/rfc/rfc2045.txt
*
* @param string
- * @param int
* @return string
*/
- protected function _prep_quoted_printable($str, $charlim = '')
+ protected function _prep_quoted_printable($str)
{
- // Set the character limit
- // Don't allow over 76, as that will make servers and MUAs barf
- // all over quoted-printable data
- if ($charlim == '' OR $charlim > 76)
+ // We are intentionally wrapping so mail servers will encode characters
+ // properly and MUAs will behave, so {unwrap} must go!
+ $str = str_replace(array('{unwrap}', '{/unwrap}'), '', $str);
+
+ // RFC 2045 specifies CRLF as "\r\n".
+ // However, many developers choose to override that and violate
+ // the RFC rules due to (apparently) a bug in MS Exchange,
+ // which only works with "\n".
+ if ($this->crlf === "\r\n")
{
- $charlim = 76;
+ if (is_php('5.3'))
+ {
+ return quoted_printable_encode($str);
+ }
+ elseif (function_exists('imap_8bit'))
+ {
+ return imap_8bit($str);
+ }
}
// Reduce multiple spaces & remove nulls
- $str = preg_replace(array("| +|", '/\x00+/'), array(' ', ''), $str);
+ $str = preg_replace(array('| +|', '/\x00+/'), array(' ', ''), $str);
// Standardize newlines
if (strpos($str, "\r") !== FALSE)
@@ -1120,10 +1421,6 @@ class CI_Email {
$str = str_replace(array("\r\n", "\r"), "\n", $str);
}
- // We are intentionally wrapping so mail servers will encode characters
- // properly and MUAs will behave, so {unwrap} must go!
- $str = str_replace(array('{unwrap}', '{/unwrap}'), '', $str);
-
$escape = '=';
$output = '';
@@ -1153,7 +1450,7 @@ class CI_Email {
// If we're at the character limit, add the line to the output,
// reset our temp variable, and keep on chuggin'
- if ((strlen($temp) + strlen($char)) >= $charlim)
+ if ((strlen($temp) + strlen($char)) >= 76)
{
$output .= $temp.$escape.$this->crlf;
$temp = '';
@@ -1176,68 +1473,75 @@ class CI_Email {
/**
* Prep Q Encoding
*
- * Performs "Q Encoding" on a string for use in email headers. It's related
- * but not identical to quoted-printable, so it has its own method
+ * Performs "Q Encoding" on a string for use in email headers.
+ * It's related but not identical to quoted-printable, so it has its
+ * own method.
*
* @param string
- * @param bool set to TRUE for processing From: headers
* @return string
*/
- protected function _prep_q_encoding($str, $from = FALSE)
+ protected function _prep_q_encoding($str)
{
- $str = str_replace(array("\r", "\n"), array('', ''), $str);
+ $str = str_replace(array("\r", "\n"), '', $str);
- // Line length must not exceed 76 characters, so we adjust for
- // a space, 7 extra characters =??Q??=, and the charset that we will add to each line
- $limit = 75 - 7 - strlen($this->charset);
-
- // these special characters must be converted too
- $convert = array('_', '=', '?');
-
- if ($from === TRUE)
+ if ($this->charset === 'UTF-8')
{
- $convert[] = ',';
- $convert[] = ';';
+ if (MB_ENABLED === TRUE)
+ {
+ return mb_encode_mimeheader($str, $this->charset, 'Q', $this->crlf);
+ }
+ elseif (extension_loaded('iconv'))
+ {
+ $output = @iconv_mime_encode('', $str,
+ array(
+ 'scheme' => 'Q',
+ 'line-length' => 76,
+ 'input-charset' => $this->charset,
+ 'output-charset' => $this->charset,
+ 'line-break-chars' => $this->crlf
+ )
+ );
+
+ // There are reports that iconv_mime_encode() might fail and return FALSE
+ if ($output !== FALSE)
+ {
+ // iconv_mime_encode() will always put a header field name.
+ // We've passed it an empty one, but it still prepends our
+ // encoded string with ': ', so we need to strip it.
+ return substr($output, 2);
+ }
+
+ $chars = iconv_strlen($str, 'UTF-8');
+ }
}
- $output = '';
- $temp = '';
+ // We might already have this set for UTF-8
+ isset($chars) OR $chars = strlen($str);
- for ($i = 0, $length = strlen($str); $i < $length; $i++)
+ $output = '=?'.$this->charset.'?Q?';
+ for ($i = 0, $length = strlen($output), $iconv = extension_loaded('iconv'); $i < $chars; $i++)
{
- // Grab the next character
- $char = $str[$i];
- $ascii = ord($char);
+ $chr = ($this->charset === 'UTF-8' && $iconv === TRUE)
+ ? '='.implode('=', str_split(strtoupper(bin2hex(iconv_substr($str, $i, 1, $this->charset))), 2))
+ : '='.strtoupper(bin2hex($str[$i]));
- // convert ALL non-printable ASCII characters and our specials
- if ($ascii < 32 OR $ascii > 126 OR in_array($char, $convert))
+ // RFC 2045 sets a limit of 76 characters per line.
+ // We'll append ?= to the end of each line though.
+ if ($length + ($l = strlen($chr)) > 74)
{
- $char = '='.dechex($ascii);
+ $output .= '?='.$this->crlf // EOL
+ .' =?'.$this->charset.'?Q?'.$chr; // New line
+ $length = 6 + strlen($this->charset) + $l; // Reset the length for the new line
}
-
- // handle regular spaces a bit more compactly than =20
- if ($ascii === 32)
- {
- $char = '_';
- }
-
- // If we're at the character limit, add the line to the output,
- // reset our temp variable, and keep on chuggin'
- if ((strlen($temp) + strlen($char)) >= $limit)
+ else
{
- $output .= $temp.$this->crlf;
- $temp = '';
+ $output .= $chr;
+ $length += $l;
}
-
- // Add the character to our temporary line
- $temp .= $char;
}
- $str = $output.$temp;
-
- // wrap each line with the shebang, charset, and transfer encoding
- // the preceding space on successive lines is required for header "folding"
- return trim(preg_replace('/^(.*)$/m', ' =?'.$this->charset.'?Q?$1?=', $str));
+ // End the header
+ return $output.'?=';
}
// --------------------------------------------------------------------
@@ -1245,11 +1549,12 @@ class CI_Email {
/**
* Send Email
*
+ * @param bool $auto_clear = TRUE
* @return bool
*/
- public function send()
+ public function send($auto_clear = TRUE)
{
- if ($this->_replyto_flag == FALSE)
+ if ($this->_replyto_flag === FALSE)
{
$this->reply_to($this->_headers['From']);
}
@@ -1266,11 +1571,25 @@ class CI_Email {
if ($this->bcc_batch_mode && count($this->_bcc_array) > $this->bcc_batch_size)
{
- return $this->batch_bcc_send();
+ $result = $this->batch_bcc_send();
+
+ if ($result && $auto_clear)
+ {
+ $this->clear();
+ }
+
+ return $result;
}
$this->_build_message();
- return $this->_spool_email();
+ $result = $this->_spool_email();
+
+ if ($result && $auto_clear)
+ {
+ $this->clear();
+ }
+
+ return $result;
}
// --------------------------------------------------------------------
@@ -1293,7 +1612,7 @@ class CI_Email {
$set .= ', '.$this->_bcc_array[$i];
}
- if ($i == $float)
+ if ($i === $float)
{
$chunk[] = substr($set, 1);
$float += $this->bcc_batch_size;
@@ -1314,7 +1633,7 @@ class CI_Email {
if ($this->protocol !== 'smtp')
{
- $this->_set_header('Bcc', implode(', ', $bcc));
+ $this->set_header('Bcc', implode(', ', $bcc));
}
else
{
@@ -1335,7 +1654,7 @@ class CI_Email {
*/
protected function _unwrap_specials()
{
- $this->_finalbody = preg_replace_callback("/\{unwrap\}(.*?)\{\/unwrap\}/si", array($this, '_remove_nl_callback'), $this->_finalbody);
+ $this->_finalbody = preg_replace_callback('/\{unwrap\}(.*?)\{\/unwrap\}/si', array($this, '_remove_nl_callback'), $this->_finalbody);
}
// --------------------------------------------------------------------
@@ -1343,6 +1662,7 @@ class CI_Email {
/**
* Strip line-breaks via callback
*
+ * @param string $matches
* @return string
*/
protected function _remove_nl_callback($matches)
@@ -1366,10 +1686,10 @@ class CI_Email {
{
$this->_unwrap_specials();
- $method = '_send_with_' . $this->_get_protocol();
+ $method = '_send_with_'.$this->_get_protocol();
if ( ! $this->$method())
{
- $this->_set_error_message('lang:email_send_failure_' . ($this->_get_protocol() === 'mail' ? 'phpmail' : $this->_get_protocol()));
+ $this->_set_error_message('lang:email_send_failure_'.($this->_get_protocol() === 'mail' ? 'phpmail' : $this->_get_protocol()));
return FALSE;
}
@@ -1386,7 +1706,12 @@ class CI_Email {
*/
protected function _send_with_mail()
{
- if ($this->_safe_mode == TRUE)
+ if (is_array($this->_recipients))
+ {
+ $this->_recipients = implode(', ', $this->_recipients);
+ }
+
+ if ($this->_safe_mode === TRUE)
{
return mail($this->_recipients, $this->_subject, $this->_finalbody, $this->_header_str);
}
@@ -1394,7 +1719,7 @@ class CI_Email {
{
// most documentation of sendmail using the "-f" flag lacks a space after it, however
// we've encountered servers that seem to require it to be in place.
- return mail($this->_recipients, $this->_subject, $this->_finalbody, $this->_header_str, "-f ".$this->clean_email($this->_headers['From']));
+ return mail($this->_recipients, $this->_subject, $this->_finalbody, $this->_header_str, '-f '.$this->clean_email($this->_headers['Return-Path']));
}
}
@@ -1407,11 +1732,14 @@ class CI_Email {
*/
protected function _send_with_sendmail()
{
- $fp = @popen($this->mailpath . " -oi -f ".$this->clean_email($this->_headers['From'])." -t", 'w');
-
- if ($fp === FALSE OR $fp === NULL)
+ // is popen() enabled?
+ if ( ! function_usable('popen')
+ OR FALSE === ($fp = @popen(
+ $this->mailpath.' -oi -f '.$this->clean_email($this->_headers['From'])
+ .' -t -r '.$this->clean_email($this->_headers['Return-Path'])
+ , 'w'))
+ ) // server probably has popen disabled, so nothing we can do to get a verbose error.
{
- // server probably has popen disabled, so nothing we can do to get a verbose error.
return FALSE;
}
@@ -1439,7 +1767,7 @@ class CI_Email {
*/
protected function _send_with_smtp()
{
- if ($this->smtp_host == '')
+ if ($this->smtp_host === '')
{
$this->_set_error_message('lang:email_no_hostname');
return FALSE;
@@ -1461,7 +1789,7 @@ class CI_Email {
{
foreach ($this->_cc_array as $val)
{
- if ($val != "")
+ if ($val !== '')
{
$this->_send_command('to', $val);
}
@@ -1472,7 +1800,7 @@ class CI_Email {
{
foreach ($this->_bcc_array as $val)
{
- if ($val != "")
+ if ($val !== '')
{
$this->_send_command('to', $val);
}
@@ -1482,7 +1810,7 @@ class CI_Email {
$this->_send_command('data');
// perform dot transformation on any lines that begin with a dot
- $this->_send_data($this->_header_str . preg_replace('/^\./m', '..$1', $this->_finalbody));
+ $this->_send_data($this->_header_str.preg_replace('/^\./m', '..$1', $this->_finalbody));
$this->_send_data('.');
@@ -1490,7 +1818,7 @@ class CI_Email {
$this->_set_error_message($reply);
- if (strncmp($reply, '250', 3) !== 0)
+ if (strpos($reply, '250') !== 0)
{
$this->_set_error_message('lang:email_smtp_error', $reply);
return FALSE;
@@ -1505,28 +1833,27 @@ class CI_Email {
/**
* SMTP Connect
*
- * @param string
* @return string
*/
protected function _smtp_connect()
{
- $ssl = ($this->smtp_crypto == 'ssl') ? 'ssl://' : NULL;
+ $ssl = ($this->smtp_crypto === 'ssl') ? 'ssl://' : NULL;
$this->_smtp_connect = fsockopen($ssl.$this->smtp_host,
- $this->smtp_port,
- $errno,
- $errstr,
- $this->smtp_timeout);
+ $this->smtp_port,
+ $errno,
+ $errstr,
+ $this->smtp_timeout);
if ( ! is_resource($this->_smtp_connect))
{
- $this->_set_error_message('lang:email_smtp_error', $errno." ".$errstr);
+ $this->_set_error_message('lang:email_smtp_error', $errno.' '.$errstr);
return FALSE;
}
$this->_set_error_message($this->_get_smtp_data());
- if ($this->smtp_crypto == 'tls')
+ if ($this->smtp_crypto === 'tls')
{
$this->_send_command('hello');
$this->_send_command('starttls');
@@ -1558,27 +1885,29 @@ class CI_Email {
{
case 'hello' :
- if ($this->_smtp_auth OR $this->_get_encoding() == '8bit')
- $this->_send_data('EHLO '.$this->_get_hostname());
- else
- $this->_send_data('HELO '.$this->_get_hostname());
+ if ($this->_smtp_auth OR $this->_get_encoding() === '8bit')
+ {
+ $this->_send_data('EHLO '.$this->_get_hostname());
+ }
+ else
+ {
+ $this->_send_data('HELO '.$this->_get_hostname());
+ }
$resp = 250;
break;
case 'starttls' :
$this->_send_data('STARTTLS');
-
$resp = 220;
break;
case 'from' :
$this->_send_data('MAIL FROM:<'.$data.'>');
-
$resp = 250;
break;
- case 'to' :
-
+ case 'to' :
+
if ($this->dsn)
{
$this->_send_data('RCPT TO:<'.$data.'> NOTIFY=SUCCESS,DELAY,FAILURE ORCPT=rfc822;'.$data);
@@ -1587,33 +1916,32 @@ class CI_Email {
{
$this->_send_data('RCPT TO:<'.$data.'>');
}
+
$resp = 250;
break;
case 'data' :
$this->_send_data('DATA');
-
$resp = 354;
break;
case 'quit' :
$this->_send_data('QUIT');
-
$resp = 221;
break;
}
$reply = $this->_get_smtp_data();
- $this->_debug_msg[] = "<pre>".$cmd.": ".$reply."</pre>";
+ $this->_debug_msg[] = '<pre>'.$cmd.': '.$reply.'</pre>';
- if (substr($reply, 0, 3) != $resp)
+ if ((int) substr($reply, 0, 3) !== $resp)
{
$this->_set_error_message('lang:email_smtp_error', $reply);
return FALSE;
}
- if ($cmd == 'quit')
+ if ($cmd === 'quit')
{
fclose($this->_smtp_connect);
}
@@ -1624,7 +1952,7 @@ class CI_Email {
// --------------------------------------------------------------------
/**
- * SMTP Authenticate
+ * SMTP Authenticate
*
* @return bool
*/
@@ -1635,7 +1963,7 @@ class CI_Email {
return TRUE;
}
- if ($this->smtp_user == '' && $this->smtp_pass == '')
+ if ($this->smtp_user === '' && $this->smtp_pass === '')
{
$this->_set_error_message('lang:email_no_smtp_unpw');
return FALSE;
@@ -1645,7 +1973,7 @@ class CI_Email {
$reply = $this->_get_smtp_data();
- if (strncmp($reply, '334', 3) !== 0)
+ if (strpos($reply, '334') !== 0)
{
$this->_set_error_message('lang:email_failed_smtp_login', $reply);
return FALSE;
@@ -1655,7 +1983,7 @@ class CI_Email {
$reply = $this->_get_smtp_data();
- if (strncmp($reply, '334', 3) !== 0)
+ if (strpos($reply, '334') !== 0)
{
$this->_set_error_message('lang:email_smtp_auth_un', $reply);
return FALSE;
@@ -1665,7 +1993,7 @@ class CI_Email {
$reply = $this->_get_smtp_data();
- if (strncmp($reply, '235', 3) !== 0)
+ if (strpos($reply, '235') !== 0)
{
$this->_set_error_message('lang:email_smtp_auth_pw', $reply);
return FALSE;
@@ -1679,11 +2007,12 @@ class CI_Email {
/**
* Send SMTP data
*
+ * @param string $data
* @return bool
*/
protected function _send_data($data)
{
- if ( ! fwrite($this->_smtp_connect, $data . $this->newline))
+ if ( ! fwrite($this->_smtp_connect, $data.$this->newline))
{
$this->_set_error_message('lang:email_smtp_data_failure', $data);
return FALSE;
@@ -1701,13 +2030,13 @@ class CI_Email {
*/
protected function _get_smtp_data()
{
- $data = "";
+ $data = '';
while ($str = fgets($this->_smtp_connect, 512))
{
$data .= $str;
- if ($str[3] == " ")
+ if ($str[3] === ' ')
{
break;
}
@@ -1731,64 +2060,44 @@ class CI_Email {
// --------------------------------------------------------------------
/**
- * Get IP
+ * Get Debug Message
*
+ * @param array $include List of raw data chunks to include in the output
+ * Valid options are: 'headers', 'subject', 'body'
* @return string
*/
- protected function _get_ip()
+ public function print_debugger($include = array('headers', 'subject', 'body'))
{
- if ($this->_IP !== FALSE)
- {
- return $this->_IP;
- }
+ $msg = '';
- $cip = ( ! empty($_SERVER['HTTP_CLIENT_IP'])) ? $_SERVER['HTTP_CLIENT_IP'] : FALSE;
- $rip = ( ! empty($_SERVER['REMOTE_ADDR'])) ? $_SERVER['REMOTE_ADDR'] : FALSE;
- if ($cip) $this->_IP = $cip;
- elseif ($rip) $this->_IP = $rip;
- else
+ if (count($this->_debug_msg) > 0)
{
- $fip = ( ! empty($_SERVER['HTTP_X_FORWARDED_FOR'])) ? $_SERVER['HTTP_X_FORWARDED_FOR'] : FALSE;
- if ($fip)
+ foreach ($this->_debug_msg as $val)
{
- $this->_IP = $fip;
+ $msg .= $val;
}
}
- if (strpos($this->_IP, ',') !== FALSE)
+ // Determine which parts of our raw data needs to be printed
+ $raw_data = '';
+ is_array($include) OR $include = array($include);
+
+ if (in_array('headers', $include, TRUE))
{
- $x = explode(',', $this->_IP);
- $this->_IP = end($x);
+ $raw_data = $this->_header_str."\n";
}
- if ( ! preg_match('/^[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}$/', $this->_IP))
+ if (in_array('subject', $include, TRUE))
{
- $this->_IP = '0.0.0.0';
+ $raw_data .= htmlspecialchars($this->_subject)."\n";
}
- return $this->_IP;
- }
-
- // --------------------------------------------------------------------
-
- /**
- * Get Debug Message
- *
- * @return string
- */
- public function print_debugger()
- {
- $msg = '';
-
- if (count($this->_debug_msg) > 0)
+ if (in_array('body', $include, TRUE))
{
- foreach ($this->_debug_msg as $val)
- {
- $msg .= $val;
- }
+ $raw_data .= htmlspecialchars($this->_finalbody);
}
- return $msg.'<pre>'.$this->_header_str."\n".htmlspecialchars($this->_subject)."\n".htmlspecialchars($this->_finalbody).'</pre>';
+ return $msg.($raw_data === '' ? '' : '<pre>'.$raw_data.'</pre>');
}
// --------------------------------------------------------------------
@@ -1796,7 +2105,8 @@ class CI_Email {
/**
* Set Message
*
- * @param string
+ * @param string $msg
+ * @param string $val = ''
* @return void
*/
protected function _set_error_message($msg, $val = '')
@@ -1804,13 +2114,13 @@ class CI_Email {
$CI =& get_instance();
$CI->lang->load('email');
- if (substr($msg, 0, 5) !== 'lang:' OR FALSE === ($line = $CI->lang->line(substr($msg, 5))))
+ if (sscanf($msg, 'lang:%s', $line) !== 1 OR FALSE === ($line = $CI->lang->line($line)))
{
- $this->_debug_msg[] = str_replace('%s', $val, $msg)."<br />";
+ $this->_debug_msg[] = str_replace('%s', $val, $msg).'<br />';
}
else
{
- $this->_debug_msg[] = str_replace('%s', $val, $line)."<br />";
+ $this->_debug_msg[] = str_replace('%s', $val, $line).'<br />';
}
}
@@ -1824,100 +2134,26 @@ class CI_Email {
*/
protected function _mime_types($ext = '')
{
- $mimes = array(
- 'hqx' => 'application/mac-binhex40',
- 'cpt' => 'application/mac-compactpro',
- 'doc' => 'application/msword',
- 'bin' => 'application/macbinary',
- 'dms' => 'application/octet-stream',
- 'lha' => 'application/octet-stream',
- 'lzh' => 'application/octet-stream',
- 'exe' => 'application/octet-stream',
- 'class' => 'application/octet-stream',
- 'psd' => 'application/octet-stream',
- 'so' => 'application/octet-stream',
- 'sea' => 'application/octet-stream',
- 'dll' => 'application/octet-stream',
- 'oda' => 'application/oda',
- 'pdf' => 'application/pdf',
- 'ai' => 'application/postscript',
- 'eps' => 'application/postscript',
- 'ps' => 'application/postscript',
- 'smi' => 'application/smil',
- 'smil' => 'application/smil',
- 'mif' => 'application/vnd.mif',
- 'xls' => 'application/vnd.ms-excel',
- 'ppt' => 'application/vnd.ms-powerpoint',
- 'wbxml' => 'application/vnd.wap.wbxml',
- 'wmlc' => 'application/vnd.wap.wmlc',
- 'dcr' => 'application/x-director',
- 'dir' => 'application/x-director',
- 'dxr' => 'application/x-director',
- 'dvi' => 'application/x-dvi',
- 'gtar' => 'application/x-gtar',
- 'php' => 'application/x-httpd-php',
- 'php4' => 'application/x-httpd-php',
- 'php3' => 'application/x-httpd-php',
- 'phtml' => 'application/x-httpd-php',
- 'phps' => 'application/x-httpd-php-source',
- 'js' => 'application/x-javascript',
- 'swf' => 'application/x-shockwave-flash',
- 'sit' => 'application/x-stuffit',
- 'tar' => 'application/x-tar',
- 'tgz' => 'application/x-tar',
- 'xhtml' => 'application/xhtml+xml',
- 'xht' => 'application/xhtml+xml',
- 'zip' => 'application/zip',
- 'mid' => 'audio/midi',
- 'midi' => 'audio/midi',
- 'mpga' => 'audio/mpeg',
- 'mp2' => 'audio/mpeg',
- 'mp3' => 'audio/mpeg',
- 'aif' => 'audio/x-aiff',
- 'aiff' => 'audio/x-aiff',
- 'aifc' => 'audio/x-aiff',
- 'ram' => 'audio/x-pn-realaudio',
- 'rm' => 'audio/x-pn-realaudio',
- 'rpm' => 'audio/x-pn-realaudio-plugin',
- 'ra' => 'audio/x-realaudio',
- 'rv' => 'video/vnd.rn-realvideo',
- 'wav' => 'audio/x-wav',
- 'bmp' => 'image/bmp',
- 'gif' => 'image/gif',
- 'jpeg' => 'image/jpeg',
- 'jpg' => 'image/jpeg',
- 'jpe' => 'image/jpeg',
- 'png' => 'image/png',
- 'tiff' => 'image/tiff',
- 'tif' => 'image/tiff',
- 'css' => 'text/css',
- 'html' => 'text/html',
- 'htm' => 'text/html',
- 'shtml' => 'text/html',
- 'txt' => 'text/plain',
- 'text' => 'text/plain',
- 'log' => 'text/plain',
- 'rtx' => 'text/richtext',
- 'rtf' => 'text/rtf',
- 'xml' => 'text/xml',
- 'xsl' => 'text/xml',
- 'mpeg' => 'video/mpeg',
- 'mpg' => 'video/mpeg',
- 'mpe' => 'video/mpeg',
- 'qt' => 'video/quicktime',
- 'mov' => 'video/quicktime',
- 'avi' => 'video/x-msvideo',
- 'movie' => 'video/x-sgi-movie',
- 'doc' => 'application/msword',
- 'word' => 'application/msword',
- 'xl' => 'application/excel',
- 'eml' => 'message/rfc822'
- );
-
- return isset($mimes[strtolower($ext)]) ? $mimes[strtolower($ext)] : 'application/x-unknown-content-type';
+ static $mimes;
+
+ $ext = strtolower($ext);
+
+ if ( ! is_array($mimes))
+ {
+ $mimes =& get_mimes();
+ }
+
+ if (isset($mimes[$ext]))
+ {
+ return is_array($mimes[$ext])
+ ? current($mimes[$ext])
+ : $mimes[$ext];
+ }
+
+ return 'application/x-unknown-content-type';
}
}
/* End of file Email.php */
-/* Location: ./system/libraries/Email.php */
+/* Location: ./system/libraries/Email.php */ \ No newline at end of file
diff --git a/system/libraries/Encrypt.php b/system/libraries/Encrypt.php
index 54b5bf737..cdb0a6452 100644
--- a/system/libraries/Encrypt.php
+++ b/system/libraries/Encrypt.php
@@ -1,4 +1,4 @@
-<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');
+<?php
/**
* CodeIgniter
*
@@ -24,6 +24,7 @@
* @since Version 1.0
* @filesource
*/
+defined('BASEPATH') OR exit('No direct script access allowed');
/**
* CodeIgniter Encryption Class
@@ -38,12 +39,46 @@
*/
class CI_Encrypt {
+ /**
+ * Reference to the user's encryption key
+ *
+ * @var string
+ */
public $encryption_key = '';
+
+ /**
+ * Type of hash operation
+ *
+ * @var string
+ */
protected $_hash_type = 'sha1';
+
+ /**
+ * Flag for the existance of mcrypt
+ *
+ * @var bool
+ */
protected $_mcrypt_exists = FALSE;
+
+ /**
+ * Current cipher to be used with mcrypt
+ *
+ * @var string
+ */
protected $_mcrypt_cipher;
+
+ /**
+ * Method for encrypting/decrypting data
+ *
+ * @var int
+ */
protected $_mcrypt_mode;
+ /**
+ * Initialize Encryption class
+ *
+ * @return void
+ */
public function __construct()
{
$this->_mcrypt_exists = function_exists('mcrypt_encrypt');
@@ -63,15 +98,14 @@ class CI_Encrypt {
*/
public function get_key($key = '')
{
- if ($key == '')
+ if ($key === '')
{
- if ($this->encryption_key != '')
+ if ($this->encryption_key !== '')
{
return $this->encryption_key;
}
- $CI =& get_instance();
- $key = $CI->config->item('encryption_key');
+ $key = config_item('encryption_key');
if ($key === FALSE)
{
@@ -132,7 +166,7 @@ class CI_Encrypt {
*/
public function decode($string, $key = '')
{
- if (preg_match('/[^a-zA-Z0-9\/\+=]/', $string))
+ if (preg_match('/[^a-zA-Z0-9\/\+=]/', $string) OR base64_encode(base64_decode($string)) !== $string)
{
return FALSE;
}
@@ -180,6 +214,7 @@ class CI_Encrypt {
$dec = base64_decode($string);
if (($dec = $this->mcrypt_decode($dec, $key)) === FALSE)
{
+ $this->set_mode($current_mode);
return FALSE;
}
@@ -349,7 +384,8 @@ class CI_Encrypt {
*
* Function description
*
- * @param string
+ * @param string $data
+ * @param string $key
* @return string
*/
protected function _remove_cipher_noise($data, $key)
@@ -414,7 +450,7 @@ class CI_Encrypt {
*/
protected function _get_cipher()
{
- if ($this->_mcrypt_cipher == '')
+ if ($this->_mcrypt_cipher === NULL)
{
return $this->_mcrypt_cipher = MCRYPT_RIJNDAEL_256;
}
@@ -431,7 +467,7 @@ class CI_Encrypt {
*/
protected function _get_mode()
{
- if ($this->_mcrypt_mode == '')
+ if ($this->_mcrypt_mode === NULL)
{
return $this->_mcrypt_mode = MCRYPT_MODE_CBC;
}
@@ -449,7 +485,7 @@ class CI_Encrypt {
*/
public function set_hash($type = 'sha1')
{
- $this->_hash_type = ($type !== 'sha1' && $type !== 'md5') ? 'sha1' : $type;
+ $this->_hash_type = in_array($type, hash_algos()) ? $type : 'sha1';
}
// --------------------------------------------------------------------
@@ -462,7 +498,7 @@ class CI_Encrypt {
*/
public function hash($str)
{
- return ($this->_hash_type === 'sha1') ? sha1($str) : md5($str);
+ return hash($this->_hash_type, $str);
}
}
diff --git a/system/libraries/Form_validation.php b/system/libraries/Form_validation.php
index fc879ef10..19041bd95 100644
--- a/system/libraries/Form_validation.php
+++ b/system/libraries/Form_validation.php
@@ -1,4 +1,4 @@
-<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');
+<?php
/**
* CodeIgniter
*
@@ -24,6 +24,7 @@
* @since Version 1.0
* @filesource
*/
+defined('BASEPATH') OR exit('No direct script access allowed');
/**
* Form Validation Class
@@ -36,17 +37,82 @@
*/
class CI_Form_validation {
+ /**
+ * Reference to the CodeIgniter instance
+ *
+ * @var object
+ */
protected $CI;
+
+ /**
+ * Validation data for the current form submission
+ *
+ * @var array
+ */
protected $_field_data = array();
+
+ /**
+ * Validation rules for the current form
+ *
+ * @var array
+ */
protected $_config_rules = array();
+
+ /**
+ * Array of validation errors
+ *
+ * @var array
+ */
protected $_error_array = array();
+
+ /**
+ * Array of custom error messages
+ *
+ * @var array
+ */
protected $_error_messages = array();
+
+ /**
+ * Start tag for error wrapping
+ *
+ * @var string
+ */
protected $_error_prefix = '<p>';
+
+ /**
+ * End tag for error wrapping
+ *
+ * @var string
+ */
protected $_error_suffix = '</p>';
+
+ /**
+ * Custom error message
+ *
+ * @var string
+ */
protected $error_string = '';
+
+ /**
+ * Whether the form data has been validated as safe
+ *
+ * @var bool
+ */
protected $_safe_form_data = FALSE;
- protected $validation_data = array();
+ /**
+ * Custom data to validate
+ *
+ * @var array
+ */
+ public $validation_data = array();
+
+ /**
+ * Initialize Form_Validation class
+ *
+ * @param array $rules
+ * @return void
+ */
public function __construct($rules = array())
{
$this->CI =& get_instance();
@@ -69,12 +135,6 @@ class CI_Form_validation {
// Automatically load the form helper
$this->CI->load->helper('form');
- // Set the character encoding in MB.
- if (MB_ENABLED === TRUE)
- {
- mb_internal_encoding($this->CI->config->item('charset'));
- }
-
log_message('debug', 'Form Validation Class Initialized');
}
@@ -86,8 +146,9 @@ class CI_Form_validation {
* This function takes an array of field names and validation
* rules as input, validates the info, and stores it
*
- * @param mixed
- * @param string
+ * @param mixed $field
+ * @param string $label
+ * @param mixed $rules
* @return object
*/
public function set_rules($field, $label = '', $rules = '')
@@ -121,27 +182,31 @@ class CI_Form_validation {
return $this;
}
+ // Convert an array of rules to a string
+ if (is_array($rules))
+ {
+ $rules = implode('|', $rules);
+ }
+
// No fields? Nothing to do...
- if ( ! is_string($field) OR ! is_string($rules) OR $field == '')
+ if ( ! is_string($field) OR ! is_string($rules) OR $field === '')
{
return $this;
}
// If the field label wasn't passed we use the field name
- $label = ($label == '') ? $field : $label;
+ $label = ($label === '') ? $field : $label;
// Is the field name an array? If it is an array, we break it apart
// into its components so that we can fetch the corresponding POST data later
+ $indexes = array();
if (preg_match_all('/\[(.*?)\]/', $field, $matches))
{
- // Note: Due to a bug in current() that affects some versions
- // of PHP we can not pass function call directly into it
- $x = explode('[', $field);
- $indexes[] = current($x);
+ sscanf($field, '%[^[][', $indexes[0]);
for ($i = 0, $c = count($matches[0]); $i < $c; $i++)
{
- if ($matches[1][$i] != '')
+ if ($matches[1][$i] !== '')
{
$indexes[] = $matches[1][$i];
}
@@ -151,19 +216,18 @@ class CI_Form_validation {
}
else
{
- $indexes = array();
$is_array = FALSE;
}
// Build our master array
$this->_field_data[$field] = array(
- 'field' => $field,
- 'label' => $label,
- 'rules' => $rules,
- 'is_array' => $is_array,
- 'keys' => $indexes,
- 'postdata' => NULL,
- 'error' => ''
+ 'field' => $field,
+ 'label' => $label,
+ 'rules' => $rules,
+ 'is_array' => $is_array,
+ 'keys' => $indexes,
+ 'postdata' => NULL,
+ 'error' => ''
);
return $this;
@@ -241,6 +305,8 @@ class CI_Form_validation {
* Gets the error message associated with a particular field
*
* @param string the field name
+ * @param string the html start tag
+ * @param strign the html end tag
* @return string
*/
public function error($field = '', $prefix = '', $suffix = '')
@@ -250,12 +316,12 @@ class CI_Form_validation {
return '';
}
- if ($prefix == '')
+ if ($prefix === '')
{
$prefix = $this->_error_prefix;
}
- if ($suffix == '')
+ if ($suffix === '')
{
$suffix = $this->_error_suffix;
}
@@ -296,12 +362,12 @@ class CI_Form_validation {
return '';
}
- if ($prefix == '')
+ if ($prefix === '')
{
$prefix = $this->_error_prefix;
}
- if ($suffix == '')
+ if ($suffix === '')
{
$suffix = $this->_error_suffix;
}
@@ -310,7 +376,7 @@ class CI_Form_validation {
$str = '';
foreach ($this->_error_array as $val)
{
- if ($val != '')
+ if ($val !== '')
{
$str .= $prefix.$val.$suffix."\n";
}
@@ -326,6 +392,7 @@ class CI_Form_validation {
*
* This function does all the work.
*
+ * @param string $group
* @return bool
*/
public function run($group = '')
@@ -348,9 +415,9 @@ class CI_Form_validation {
}
// Is there a validation rule for the particular URI being accessed?
- $uri = ($group == '') ? trim($this->CI->uri->ruri_string(), '/') : $group;
+ $uri = ($group === '') ? trim($this->CI->uri->ruri_string(), '/') : $group;
- if ($uri != '' && isset($this->_config_rules[$uri]))
+ if ($uri !== '' && isset($this->_config_rules[$uri]))
{
$this->set_rules($this->_config_rules[$uri]);
}
@@ -370,20 +437,31 @@ class CI_Form_validation {
// Load the language file containing error messages
$this->CI->lang->load('form_validation');
- // Cycle through the rules for each field, match the
- // corresponding $_POST item and test for errors
+ // Cycle through the rules for each field and match the corresponding $validation_data item
foreach ($this->_field_data as $field => $row)
{
- // Fetch the data from the corresponding $_POST or validation array and cache it in the _field_data array.
+ // Fetch the data from the validation_data array item and cache it in the _field_data array.
// Depending on whether the field name is an array or a string will determine where we get it from.
if ($row['is_array'] === TRUE)
{
$this->_field_data[$field]['postdata'] = $this->_reduce_array($validation_array, $row['keys']);
}
- elseif ( ! empty($validation_array[$field]))
+ elseif (isset($validation_array[$field]) && $validation_array[$field] !== '')
{
$this->_field_data[$field]['postdata'] = $validation_array[$field];
}
+ }
+
+ // Execute validation rules
+ // Note: A second foreach (for now) is required in order to avoid false-positives
+ // for rules like 'matches', which correlate to other validation fields.
+ foreach ($this->_field_data as $field => $row)
+ {
+ // Don't try to validate if we have no rules set
+ if (empty($row['rules']))
+ {
+ continue;
+ }
$this->_execute($row, explode('|', $row['rules']), $this->_field_data[$field]['postdata']);
}
@@ -418,7 +496,8 @@ class CI_Form_validation {
return isset($array[$keys[$i]]) ? $this->_reduce_array($array[$keys[$i]], $keys, ($i+1)) : NULL;
}
- return $array;
+ // NULL must be returned for empty fields
+ return ($array === '') ? NULL : $array;
}
// --------------------------------------------------------------------
@@ -496,8 +575,7 @@ class CI_Form_validation {
{
foreach ($postdata as $key => $val)
{
- $this->_execute($row, $rules, $val, $cycles);
- $cycles++;
+ $this->_execute($row, $rules, $val, $key);
}
return;
@@ -527,16 +605,13 @@ class CI_Form_validation {
// Set the message type
$type = in_array('required', $rules) ? 'required' : 'isset';
- if ( ! isset($this->_error_messages[$type]))
+ if (isset($this->_error_messages[$type]))
{
- if (FALSE === ($line = $this->CI->lang->line($type)))
- {
- $line = 'The field was not set';
- }
+ $line = $this->_error_messages[$type];
}
- else
+ elseif (FALSE === ($line = $this->CI->lang->line($type)))
{
- $line = $this->_error_messages[$type];
+ $line = 'The field was not set';
}
// Build the error message
@@ -563,7 +638,7 @@ class CI_Form_validation {
// We set the $postdata variable with the current data in our master array so that
// each cycle of the loop is dealing with the processed data from the last cycle
- if ($row['is_array'] == TRUE && is_array($this->_field_data[$row['field']]['postdata']))
+ if ($row['is_array'] === TRUE && is_array($this->_field_data[$row['field']]['postdata']))
{
// We shouldn't need this safety, but just in case there isn't an array index
// associated with this cycle we'll bail out
@@ -577,7 +652,12 @@ class CI_Form_validation {
}
else
{
- $postdata = $this->_field_data[$row['field']]['postdata'];
+ // If we get an array field, but it's not expected - then it is most likely
+ // somebody messing with the form on the client side, so we'll just consider
+ // it an empty field
+ $postdata = is_array($this->_field_data[$row['field']]['postdata'])
+ ? NULL
+ : $this->_field_data[$row['field']]['postdata'];
}
// Is the rule a callback?
@@ -593,8 +673,8 @@ class CI_Form_validation {
$param = FALSE;
if (preg_match('/(.*?)\[(.*)\]/', $rule, $match))
{
- $rule = $match[1];
- $param = $match[2];
+ $rule = $match[1];
+ $param = $match[2];
}
// Call the function that corresponds to the rule
@@ -714,11 +794,8 @@ class CI_Form_validation {
{
// Do we need to translate the field name?
// We look for the prefix lang: to determine this
- if (strpos($fieldname, 'lang:') === 0)
+ if (sscanf($fieldname, 'lang:%s', $line) === 1)
{
- // Grab the variable
- $line = substr($fieldname, 5);
-
// Were we able to translate the field name? If not we use $line
if (FALSE === ($fieldname = $this->CI->lang->line($line)))
{
@@ -789,6 +866,7 @@ class CI_Form_validation {
*
* @param string
* @param string
+ * @param bool
* @return string
*/
public function set_select($field = '', $value = '', $default = FALSE)
@@ -806,7 +884,7 @@ class CI_Form_validation {
return '';
}
}
- elseif (($field == '' OR $value == '') OR ($field != $value))
+ elseif (($field === '' OR $value === '') OR ($field !== $value))
{
return '';
}
@@ -824,6 +902,7 @@ class CI_Form_validation {
*
* @param string
* @param string
+ * @param bool
* @return string
*/
public function set_radio($field = '', $value = '', $default = FALSE)
@@ -841,7 +920,7 @@ class CI_Form_validation {
return '';
}
}
- elseif (($field == '' OR $value == '') OR ($field != $value))
+ elseif (($field === '' OR $value === '') OR ($field !== $value))
{
return '';
}
@@ -859,6 +938,7 @@ class CI_Form_validation {
*
* @param string
* @param string
+ * @param bool
* @return string
*/
public function set_checkbox($field = '', $value = '', $default = FALSE)
@@ -899,19 +979,29 @@ class CI_Form_validation {
/**
* Match one field to another
*
- * @param string
- * @param string field
+ * @param string $str string to compare against
+ * @param string $field
* @return bool
*/
public function matches($str, $field)
{
- $validation_array = empty($this->validation_data) ? $_POST : $this->validation_data;
- if ( ! isset($validation_array[$field]))
- {
- return FALSE;
- }
+ return isset($this->_field_data[$field], $this->_field_data[$field]['postdata'])
+ ? ($str === $this->_field_data[$field]['postdata'])
+ : FALSE;
+ }
- return ($str === $validation_array[$field]);
+ // --------------------------------------------------------------------
+
+ /**
+ * Differs from another field
+ *
+ * @param string
+ * @param string field
+ * @return bool
+ */
+ public function differs($str, $field)
+ {
+ return ! (isset($this->_field_data[$field]) && $this->_field_data[$field]['postdata'] === $str);
}
// --------------------------------------------------------------------
@@ -928,7 +1018,7 @@ class CI_Form_validation {
*/
public function is_unique($str, $field)
{
- list($table, $field) = explode('.', $field);
+ sscanf($field, '%[^.].%[^.]', $table, $field);
if (isset($this->CI->db))
{
$query = $this->CI->db->limit(1)->get_where($table, array($field => $str));
@@ -943,19 +1033,23 @@ class CI_Form_validation {
* Minimum Length
*
* @param string
- * @param int
+ * @param string
* @return bool
*/
public function min_length($str, $val)
{
- if (preg_match('/[^0-9]/', $val))
+ if ( ! is_numeric($val))
{
return FALSE;
}
+ else
+ {
+ $val = (int) $val;
+ }
return (MB_ENABLED === TRUE)
? ($val <= mb_strlen($str))
- : ($val <= strlen(str));
+ : ($val <= strlen($str));
}
// --------------------------------------------------------------------
@@ -964,15 +1058,19 @@ class CI_Form_validation {
* Max Length
*
* @param string
- * @param int
+ * @param string
* @return bool
*/
public function max_length($str, $val)
{
- if (preg_match('/[^0-9]/', $val))
+ if ( ! is_numeric($val))
{
return FALSE;
}
+ else
+ {
+ $val = (int) $val;
+ }
return (MB_ENABLED === TRUE)
? ($val >= mb_strlen($str))
@@ -985,19 +1083,65 @@ class CI_Form_validation {
* Exact Length
*
* @param string
- * @param int
+ * @param string
* @return bool
*/
public function exact_length($str, $val)
{
- if (preg_match('/[^0-9]/', $val))
+ if ( ! is_numeric($val))
{
return FALSE;
}
+ else
+ {
+ $val = (int) $val;
+ }
return (MB_ENABLED === TRUE)
- ? (mb_strlen($str) == $val)
- : (strlen($str) == $val);
+ ? (mb_strlen($str) === $val)
+ : (strlen($str) === $val);
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Valid URL
+ *
+ * @param string $str
+ * @return bool
+ */
+ public function valid_url($str)
+ {
+ if (empty($str))
+ {
+ return FALSE;
+ }
+ elseif (preg_match('/^(?:([^:]*)\:)?\/\/(.+)$/', $str, $matches))
+ {
+ if (empty($matches[2]))
+ {
+ return FALSE;
+ }
+ elseif ( ! in_array($matches[1], array('http', 'https'), TRUE))
+ {
+ return FALSE;
+ }
+
+ $str = $matches[2];
+ }
+
+ $str = 'http://'.$str;
+
+ // There's a bug affecting PHP 5.2.13, 5.3.2 that considers the
+ // underscore to be a valid hostname character instead of a dash.
+ // Reference: https://bugs.php.net/bug.php?id=51192
+ if (version_compare(PHP_VERSION, '5.2.13', '==') === 0 OR version_compare(PHP_VERSION, '5.3.2', '==') === 0)
+ {
+ sscanf($str, 'http://%[^/]', $host);
+ $str = substr_replace($str, strtr($host, array('_' => '-', '-' => '_')), 7, strlen($host));
+ }
+
+ return (filter_var($str, FILTER_VALIDATE_URL) !== FALSE);
}
// --------------------------------------------------------------------
@@ -1010,7 +1154,7 @@ class CI_Form_validation {
*/
public function valid_email($str)
{
- return (bool) preg_match('/^([a-z0-9\+_\-]+)(\.[a-z0-9\+_\-]+)*@([a-z0-9\-]+\.)+[a-z]{2,6}$/ix', $str);
+ return (bool) filter_var($str, FILTER_VALIDATE_EMAIL);
}
// --------------------------------------------------------------------
@@ -1045,11 +1189,12 @@ class CI_Form_validation {
* Validate IP Address
*
* @param string
+ * @param string 'ipv4' or 'ipv6' to validate a specific IP format
* @return bool
*/
- public function valid_ip($ip)
+ public function valid_ip($ip, $which = '')
{
- return $this->CI->input->valid_ip($ip);
+ return $this->CI->input->valid_ip($ip, $which);
}
// --------------------------------------------------------------------
@@ -1062,7 +1207,7 @@ class CI_Form_validation {
*/
public function alpha($str)
{
- return (bool) preg_match('/^[a-z]+$/i', $str);
+ return ctype_alpha($str);
}
// --------------------------------------------------------------------
@@ -1075,7 +1220,7 @@ class CI_Form_validation {
*/
public function alpha_numeric($str)
{
- return (bool) preg_match('/^[a-z0-9]+$/i', $str);
+ return ctype_alnum((string) $str);
}
// --------------------------------------------------------------------
@@ -1137,6 +1282,7 @@ class CI_Form_validation {
* Greater than
*
* @param string
+ * @param int
* @return bool
*/
public function greater_than($str, $min)
@@ -1150,6 +1296,7 @@ class CI_Form_validation {
* Equal to or Greater than
*
* @param string
+ * @param int
* @return bool
*/
public function greater_than_equal_to($str, $min)
@@ -1163,6 +1310,7 @@ class CI_Form_validation {
* Less than
*
* @param string
+ * @param int
* @return bool
*/
public function less_than($str, $max)
@@ -1176,6 +1324,7 @@ class CI_Form_validation {
* Equal to or Less than
*
* @param string
+ * @param int
* @return bool
*/
public function less_than_equal_to($str, $max)
@@ -1193,7 +1342,7 @@ class CI_Form_validation {
*/
public function is_natural($str)
{
- return (bool) preg_match('/^[0-9]+$/', $str);
+ return ctype_digit((string) $str);
}
// --------------------------------------------------------------------
@@ -1206,7 +1355,7 @@ class CI_Form_validation {
*/
public function is_natural_no_zero($str)
{
- return ($str != 0 && preg_match('/^[0-9]+$/', $str));
+ return ($str != 0 && ctype_digit((string) $str));
}
// --------------------------------------------------------------------
@@ -1222,7 +1371,7 @@ class CI_Form_validation {
*/
public function valid_base64($str)
{
- return (bool) ! preg_match('/[^a-zA-Z0-9\/\+=]/', $str);
+ return ! preg_match('/[^a-zA-Z0-9\/\+=]/', $str);
}
// --------------------------------------------------------------------
@@ -1238,6 +1387,11 @@ class CI_Form_validation {
*/
public function prep_for_form($data = '')
{
+ if ($this->_safe_form_data === FALSE OR empty($data))
+ {
+ return $data;
+ }
+
if (is_array($data))
{
foreach ($data as $key => $val)
@@ -1248,11 +1402,6 @@ class CI_Form_validation {
return $data;
}
- if ($this->_safe_form_data == FALSE OR $data === '')
- {
- return $data;
- }
-
return str_replace(array("'", '"', '<', '>'), array('&#39;', '&quot;', '&lt;', '&gt;'), stripslashes($data));
}
@@ -1266,7 +1415,7 @@ class CI_Form_validation {
*/
public function prep_url($str = '')
{
- if ($str === 'http://' OR $str == '')
+ if ($str === 'http://' OR $str === '')
{
return '';
}
@@ -1289,7 +1438,7 @@ class CI_Form_validation {
*/
public function strip_image_tags($str)
{
- return $this->CI->input->strip_image_tags($str);
+ return $this->CI->security->strip_image_tags($str);
}
// --------------------------------------------------------------------
@@ -1315,7 +1464,7 @@ class CI_Form_validation {
*/
public function encode_php_tags($str)
{
- return str_replace(array('<?php', '<?PHP', '<?', '?>'), array('&lt;?php', '&lt;?PHP', '&lt;?', '?&gt;'), $str);
+ return str_replace(array('<?', '?>'), array('&lt;?', '?&gt;'), $str);
}
// --------------------------------------------------------------------
diff --git a/system/libraries/Ftp.php b/system/libraries/Ftp.php
index 8aa1650d2..7f58fee7b 100644
--- a/system/libraries/Ftp.php
+++ b/system/libraries/Ftp.php
@@ -1,4 +1,4 @@
-<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');
+<?php
/**
* CodeIgniter
*
@@ -24,6 +24,7 @@
* @since Version 1.0
* @filesource
*/
+defined('BASEPATH') OR exit('No direct script access allowed');
/**
* FTP Class
@@ -36,15 +37,65 @@
*/
class CI_FTP {
+ /**
+ * FTP Server hostname
+ *
+ * @var string
+ */
public $hostname = '';
+
+ /**
+ * FTP Username
+ *
+ * @var string
+ */
public $username = '';
+
+ /**
+ * FTP Password
+ *
+ * @var string
+ */
public $password = '';
+
+ /**
+ * FTP Server port
+ *
+ * @var int
+ */
public $port = 21;
+
+ /**
+ * Passive mode flag
+ *
+ * @var bool
+ */
public $passive = TRUE;
+
+ /**
+ * Debug flag
+ *
+ * Specifies whether to display error messages.
+ *
+ * @var bool
+ */
public $debug = FALSE;
+
+ /**
+ * Connection
+ *
+ * @var resource
+ */
public $conn_id = FALSE;
+ // --------------------------------------------------------------------
+ /**
+ * Constructor
+ *
+ * @param array $config
+ * @return void
+ */
public function __construct($config = array())
{
if (count($config) > 0)
@@ -60,7 +111,7 @@ class CI_FTP {
/**
* Initialize preferences
*
- * @param array
+ * @param array $config
* @return void
*/
public function initialize($config = array())
@@ -82,7 +133,7 @@ class CI_FTP {
/**
* FTP Connect
*
- * @param array the connection values
+ * @param array $config Connection values
* @return bool
*/
public function connect($config = array())
@@ -94,7 +145,7 @@ class CI_FTP {
if (FALSE === ($this->conn_id = @ftp_connect($this->hostname, $this->port)))
{
- if ($this->debug == TRUE)
+ if ($this->debug === TRUE)
{
$this->_error('ftp_unable_to_connect');
}
@@ -103,7 +154,7 @@ class CI_FTP {
if ( ! $this->_login())
{
- if ($this->debug == TRUE)
+ if ($this->debug === TRUE)
{
$this->_error('ftp_unable_to_login');
}
@@ -111,7 +162,7 @@ class CI_FTP {
}
// Set passive mode if needed
- if ($this->passive == TRUE)
+ if ($this->passive === TRUE)
{
ftp_pasv($this->conn_id, TRUE);
}
@@ -142,7 +193,7 @@ class CI_FTP {
{
if ( ! is_resource($this->conn_id))
{
- if ($this->debug == TRUE)
+ if ($this->debug === TRUE)
{
$this->_error('ftp_no_connection');
}
@@ -162,13 +213,13 @@ class CI_FTP {
* so we do it by trying to change to a particular directory.
* Internally, this parameter is only used by the "mirror" function below.
*
- * @param string
- * @param bool
+ * @param string $path
+ * @param bool $supress_debug
* @return bool
*/
public function changedir($path = '', $supress_debug = FALSE)
{
- if ($path == '' OR ! $this->_is_conn())
+ if ($path === '' OR ! $this->_is_conn())
{
return FALSE;
}
@@ -177,7 +228,7 @@ class CI_FTP {
if ($result === FALSE)
{
- if ($this->debug == TRUE && $supress_debug == FALSE)
+ if ($this->debug === TRUE && $supress_debug === FALSE)
{
$this->_error('ftp_unable_to_changedir');
}
@@ -192,13 +243,13 @@ class CI_FTP {
/**
* Create a directory
*
- * @param string
- * @param int
+ * @param string $path
+ * @param int $permissions
* @return bool
*/
public function mkdir($path = '', $permissions = NULL)
{
- if ($path == '' OR ! $this->_is_conn())
+ if ($path === '' OR ! $this->_is_conn())
{
return FALSE;
}
@@ -207,7 +258,7 @@ class CI_FTP {
if ($result === FALSE)
{
- if ($this->debug == TRUE)
+ if ($this->debug === TRUE)
{
$this->_error('ftp_unable_to_makdir');
}
@@ -228,10 +279,10 @@ class CI_FTP {
/**
* Upload a file to the server
*
- * @param string
- * @param string
- * @param string
- * @param int
+ * @param string $locpath
+ * @param string $rempath
+ * @param string $mode
+ * @param int $permissions
* @return bool
*/
public function upload($locpath, $rempath, $mode = 'auto', $permissions = NULL)
@@ -261,7 +312,7 @@ class CI_FTP {
if ($result === FALSE)
{
- if ($this->debug == TRUE)
+ if ($this->debug === TRUE)
{
$this->_error('ftp_unable_to_upload');
}
@@ -282,9 +333,9 @@ class CI_FTP {
/**
* Download a file from a remote server to the local server
*
- * @param string
- * @param string
- * @param string
+ * @param string $rempath
+ * @param string $locpath
+ * @param string $mode
* @return bool
*/
public function download($rempath, $locpath, $mode = 'auto')
@@ -308,7 +359,7 @@ class CI_FTP {
if ($result === FALSE)
{
- if ($this->debug == TRUE)
+ if ($this->debug === TRUE)
{
$this->_error('ftp_unable_to_download');
}
@@ -323,9 +374,9 @@ class CI_FTP {
/**
* Rename (or move) a file
*
- * @param string
- * @param string
- * @param bool
+ * @param string $old_file
+ * @param string $new_file
+ * @param bool $move
* @return bool
*/
public function rename($old_file, $new_file, $move = FALSE)
@@ -339,9 +390,9 @@ class CI_FTP {
if ($result === FALSE)
{
- if ($this->debug == TRUE)
+ if ($this->debug === TRUE)
{
- $this->_error('ftp_unable_to_' . ($move == FALSE ? 'rename' : 'move'));
+ $this->_error('ftp_unable_to_' . ($move === FALSE ? 'rename' : 'move'));
}
return FALSE;
}
@@ -354,8 +405,8 @@ class CI_FTP {
/**
* Move a file
*
- * @param string
- * @param string
+ * @param string $old_file
+ * @param string $new_file
* @return bool
*/
public function move($old_file, $new_file)
@@ -368,7 +419,7 @@ class CI_FTP {
/**
* Rename (or move) a file
*
- * @param string
+ * @param string $filepath
* @return bool
*/
public function delete_file($filepath)
@@ -382,7 +433,7 @@ class CI_FTP {
if ($result === FALSE)
{
- if ($this->debug == TRUE)
+ if ($this->debug === TRUE)
{
$this->_error('ftp_unable_to_delete');
}
@@ -398,7 +449,7 @@ class CI_FTP {
* Delete a folder and recursively delete everything (including sub-folders)
* containted within it.
*
- * @param string
+ * @param string $filepath
* @return bool
*/
public function delete_dir($filepath)
@@ -409,7 +460,7 @@ class CI_FTP {
}
// Add a trailing slash to the file path if needed
- $filepath = preg_replace('/(.+?)\/*$/', '\\1/', $filepath);
+ $filepath = preg_replace('/(.+?)\/*$/', '\\1/', $filepath);
$list = $this->list_files($filepath);
@@ -430,7 +481,7 @@ class CI_FTP {
if ($result === FALSE)
{
- if ($this->debug == TRUE)
+ if ($this->debug === TRUE)
{
$this->_error('ftp_unable_to_delete');
}
@@ -445,8 +496,8 @@ class CI_FTP {
/**
* Set file permissions
*
- * @param string the file path
- * @param string the permissions
+ * @param string $path File path
+ * @param int $perm Permissions
* @return bool
*/
public function chmod($path, $perm)
@@ -460,7 +511,7 @@ class CI_FTP {
if ($result === FALSE)
{
- if ($this->debug == TRUE)
+ if ($this->debug === TRUE)
{
$this->_error('ftp_unable_to_chmod');
}
@@ -475,6 +526,7 @@ class CI_FTP {
/**
* FTP List files in the specified directory
*
+ * @param string $path
* @return array
*/
public function list_files($path = '.')
@@ -497,8 +549,8 @@ class CI_FTP {
* Whatever the directory structure of the original file path will be
* recreated on the server.
*
- * @param string path to source with trailing slash
- * @param string path to destination - include the base folder with trailing slash
+ * @param string $locpath Path to source with trailing slash
+ * @param string $rempath Path to destination - include the base folder with trailing slash
* @return bool
*/
public function mirror($locpath, $rempath)
@@ -539,13 +591,12 @@ class CI_FTP {
return FALSE;
}
-
// --------------------------------------------------------------------
/**
* Extract the file extension
*
- * @param string
+ * @param string $filename
* @return string
*/
protected function _getext($filename)
@@ -564,7 +615,7 @@ class CI_FTP {
/**
* Set the upload type
*
- * @param string
+ * @param string $ext Filename extension
* @return string
*/
protected function _settype($ext)
@@ -585,7 +636,6 @@ class CI_FTP {
'xml'
);
-
return in_array($ext, $text_types) ? 'ascii' : 'binary';
}
@@ -611,7 +661,7 @@ class CI_FTP {
/**
* Display error message
*
- * @param string
+ * @param string $line
* @return void
*/
protected function _error($line)
diff --git a/system/libraries/Image_lib.php b/system/libraries/Image_lib.php
index 1ab8b23e0..46a9c120f 100644
--- a/system/libraries/Image_lib.php
+++ b/system/libraries/Image_lib.php
@@ -1,4 +1,4 @@
-<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');
+<?php
/**
* CodeIgniter
*
@@ -24,6 +24,7 @@
* @since Version 1.0
* @filesource
*/
+defined('BASEPATH') OR exit('No direct script access allowed');
/**
* Image Manipulation class
@@ -36,56 +37,336 @@
*/
class CI_Image_lib {
- public $image_library = 'gd2'; // Can be: imagemagick, netpbm, gd, gd2
+ /**
+ * PHP extension/library to use for image manipulation
+ * Can be: imagemagick, netpbm, gd, gd2
+ *
+ * @var string
+ */
+ public $image_library = 'gd2';
+
+ /**
+ * Path to the graphic library (if applicable)
+ *
+ * @var string
+ */
public $library_path = '';
- public $dynamic_output = FALSE; // Whether to send to browser or write to disk
+
+ /**
+ * Whether to send to browser or write to disk
+ *
+ * @var bool
+ */
+ public $dynamic_output = FALSE;
+
+ /**
+ * Path to original image
+ *
+ * @var string
+ */
public $source_image = '';
- public $new_image = '';
- public $width = '';
- public $height = '';
- public $quality = '90';
+
+ /**
+ * Path to the modified image
+ *
+ * @var string
+ */
+ public $new_image = '';
+
+ /**
+ * Image width
+ *
+ * @var int
+ */
+ public $width = '';
+
+ /**
+ * Image height
+ *
+ * @var int
+ */
+ public $height = '';
+
+ /**
+ * Quality percentage of new image
+ *
+ * @var int
+ */
+ public $quality = 90;
+
+ /**
+ * Whether to create a thumbnail
+ *
+ * @var bool
+ */
public $create_thumb = FALSE;
+
+ /**
+ * String to add to thumbnail version of image
+ *
+ * @var string
+ */
public $thumb_marker = '_thumb';
- public $maintain_ratio = TRUE; // Whether to maintain aspect ratio when resizing or use hard values
- public $master_dim = 'auto'; // auto, height, or width. Determines what to use as the master dimension
+
+ /**
+ * Whether to maintain aspect ratio when resizing or use hard values
+ *
+ * @var bool
+ */
+ public $maintain_ratio = TRUE;
+
+ /**
+ * auto, height, or width. Determines what to use as the master dimension
+ *
+ * @var string
+ */
+ public $master_dim = 'auto';
+
+ /**
+ * Angle at to rotate image
+ *
+ * @var string
+ */
public $rotation_angle = '';
- public $x_axis = '';
- public $y_axis = '';
+ /**
+ * X Coordinate for manipulation of the current image
+ *
+ * @var int
+ */
+ public $x_axis = '';
+
+ /**
+ * Y Coordinate for manipulation of the current image
+ *
+ * @var int
+ */
+ public $y_axis = '';
+
+ // --------------------------------------------------------------------------
// Watermark Vars
- public $wm_text = ''; // Watermark text if graphic is not used
- public $wm_type = 'text'; // Type of watermarking. Options: text/overlay
+ // --------------------------------------------------------------------------
+
+ /**
+ * Watermark text if graphic is not used
+ *
+ * @var string
+ */
+ public $wm_text = '';
+
+ /**
+ * Type of watermarking. Options: text/overlay
+ *
+ * @var string
+ */
+ public $wm_type = 'text';
+
+ /**
+ * Default transparency for watermark
+ *
+ * @var int
+ */
public $wm_x_transp = 4;
+
+ /**
+ * Default transparency for watermark
+ *
+ * @var int
+ */
public $wm_y_transp = 4;
- public $wm_overlay_path = ''; // Watermark image path
- public $wm_font_path = ''; // TT font
- public $wm_font_size = 17; // Font size (different versions of GD will either use points or pixels)
- public $wm_vrt_alignment = 'B'; // Vertical alignment: T M B
- public $wm_hor_alignment = 'C'; // Horizontal alignment: L R C
- public $wm_padding = 0; // Padding around text
- public $wm_hor_offset = 0; // Lets you push text to the right
- public $wm_vrt_offset = 0; // Lets you push text down
- protected $wm_font_color = '#ffffff'; // Text color
- protected $wm_shadow_color = ''; // Dropshadow color
- public $wm_shadow_distance = 2; // Dropshadow distance
- public $wm_opacity = 50; // Image opacity: 1 - 100 Only works with image
+ /**
+ * Watermark image path
+ *
+ * @var string
+ */
+ public $wm_overlay_path = '';
+
+ /**
+ * TT font
+ *
+ * @var string
+ */
+ public $wm_font_path = '';
+
+ /**
+ * Font size (different versions of GD will either use points or pixels)
+ *
+ * @var int
+ */
+ public $wm_font_size = 17;
+
+ /**
+ * Vertical alignment: T M B
+ *
+ * @var string
+ */
+ public $wm_vrt_alignment = 'B';
+
+ /**
+ * Horizontal alignment: L R C
+ *
+ * @var string
+ */
+ public $wm_hor_alignment = 'C';
+
+ /**
+ * Padding around text
+ *
+ * @var int
+ */
+ public $wm_padding = 0;
+
+ /**
+ * Lets you push text to the right
+ *
+ * @var int
+ */
+ public $wm_hor_offset = 0;
+
+ /**
+ * Lets you push text down
+ *
+ * @var int
+ */
+ public $wm_vrt_offset = 0;
+
+ /**
+ * Text color
+ *
+ * @var string
+ */
+ protected $wm_font_color = '#ffffff';
+
+ /**
+ * Dropshadow color
+ *
+ * @var string
+ */
+ protected $wm_shadow_color = '';
+
+ /**
+ * Dropshadow distance
+ *
+ * @var int
+ */
+ public $wm_shadow_distance = 2;
+
+ /**
+ * Image opacity: 1 - 100 Only works with image
+ *
+ * @var int
+ */
+ public $wm_opacity = 50;
+
+ // --------------------------------------------------------------------------
// Private Vars
+ // --------------------------------------------------------------------------
+
+ /**
+ * Source image folder
+ *
+ * @var string
+ */
public $source_folder = '';
+
+ /**
+ * Destination image folder
+ *
+ * @var string
+ */
public $dest_folder = '';
- public $mime_type = '';
- public $orig_width = '';
+
+ /**
+ * Image mime-type
+ *
+ * @var string
+ */
+ public $mime_type = '';
+
+ /**
+ * Original image width
+ *
+ * @var int
+ */
+ public $orig_width = '';
+
+ /**
+ * Original image height
+ *
+ * @var int
+ */
public $orig_height = '';
- public $image_type = '';
- public $size_str = '';
+
+ /**
+ * Image format
+ *
+ * @var string
+ */
+ public $image_type = '';
+
+ /**
+ * Size of current image
+ *
+ * @var string
+ */
+ public $size_str = '';
+
+ /**
+ * Full path to source image
+ *
+ * @var string
+ */
public $full_src_path = '';
+
+ /**
+ * Full path to destination image
+ *
+ * @var string
+ */
public $full_dst_path = '';
- public $create_fnc = 'imagecreatetruecolor';
- public $copy_fnc = 'imagecopyresampled';
- public $error_msg = array();
+
+ /**
+ * Name of function to create image
+ *
+ * @var string
+ */
+ public $create_fnc = 'imagecreatetruecolor';
+
+ /**
+ * Name of function to copy image
+ *
+ * @var string
+ */
+ public $copy_fnc = 'imagecopyresampled';
+
+ /**
+ * Error messages
+ *
+ * @var array
+ */
+ public $error_msg = array();
+
+ /**
+ * Whether to have a drop shadow on watermark
+ *
+ * @var bool
+ */
protected $wm_use_drop_shadow = FALSE;
+
+ /**
+ * Whether to use truetype fonts
+ *
+ * @var bool
+ */
public $wm_use_truetype = FALSE;
+ /**
+ * Initialize Image Library
+ *
+ * @param array $props
+ * @return void
+ */
public function __construct($props = array())
{
if (count($props) > 0)
@@ -116,7 +397,7 @@ class CI_Image_lib {
$this->image_library = 'gd2';
$this->dynamic_output = FALSE;
- $this->quality = '90';
+ $this->quality = 90;
$this->create_thumb = FALSE;
$this->thumb_marker = '_thumb';
$this->maintain_ratio = TRUE;
@@ -186,7 +467,7 @@ class CI_Image_lib {
}
// Is there a source image? If not, there's no reason to continue
- if ($this->source_image == '')
+ if ($this->source_image === '')
{
$this->set_error('imglib_source_image_required');
return FALSE;
@@ -239,7 +520,7 @@ class CI_Image_lib {
* it means we are altering the original. We'll
* set the destination filename and path accordingly.
*/
- if ($this->new_image == '')
+ if ($this->new_image === '')
{
$this->dest_image = $this->source_image;
$this->dest_folder = $this->source_folder;
@@ -282,7 +563,7 @@ class CI_Image_lib {
* We'll also split the destination image name
* so we can insert the thumbnail marker if needed.
*/
- if ($this->create_thumb === FALSE OR $this->thumb_marker == '')
+ if ($this->create_thumb === FALSE OR $this->thumb_marker === '')
{
$this->thumb_marker = '';
}
@@ -301,7 +582,7 @@ class CI_Image_lib {
* might not be in correct proportion with the source
* image's width/height. We'll recalculate it here.
*/
- if ($this->maintain_ratio === TRUE && ($this->width != 0 OR $this->height != 0))
+ if ($this->maintain_ratio === TRUE && ($this->width !== 0 OR $this->height !== 0))
{
$this->image_reproportion();
}
@@ -311,12 +592,12 @@ class CI_Image_lib {
* If the destination width/height was not submitted we
* will use the values from the actual file
*/
- if ($this->width == '')
+ if ($this->width === '')
{
$this->width = $this->orig_width;
}
- if ($this->height == '')
+ if ($this->height === '')
{
$this->height = $this->orig_height;
}
@@ -324,31 +605,31 @@ class CI_Image_lib {
// Set the quality
$this->quality = trim(str_replace('%', '', $this->quality));
- if ($this->quality == '' OR $this->quality == 0 OR ! preg_match('/^[0-9]+$/', $this->quality))
+ if ($this->quality === '' OR $this->quality === 0 OR ! ctype_digit($this->quality))
{
$this->quality = 90;
}
// Set the x/y coordinates
- $this->x_axis = ($this->x_axis == '' OR ! preg_match('/^[0-9]+$/', $this->x_axis)) ? 0 : $this->x_axis;
- $this->y_axis = ($this->y_axis == '' OR ! preg_match('/^[0-9]+$/', $this->y_axis)) ? 0 : $this->y_axis;
+ is_numeric($this->x_axis) OR $this->x_axis = 0;
+ is_numeric($this->y_axis) OR $this->y_axis = 0;
// Watermark-related Stuff...
- if ($this->wm_overlay_path != '')
+ if ($this->wm_overlay_path !== '')
{
$this->wm_overlay_path = str_replace('\\', '/', realpath($this->wm_overlay_path));
}
- if ($this->wm_shadow_color != '')
+ if ($this->wm_shadow_color !== '')
{
$this->wm_use_drop_shadow = TRUE;
}
- elseif ($this->wm_use_drop_shadow == TRUE && $this->wm_shadow_color == '')
+ elseif ($this->wm_use_drop_shadow === TRUE && $this->wm_shadow_color === '')
{
$this->wm_use_drop_shadow = FALSE;
}
- if ($this->wm_font_path != '')
+ if ($this->wm_font_path !== '')
{
$this->wm_use_truetype = TRUE;
}
@@ -403,14 +684,14 @@ class CI_Image_lib {
// Allowed rotation values
$degs = array(90, 180, 270, 'vrt', 'hor');
- if ($this->rotation_angle == '' OR ! in_array($this->rotation_angle, $degs))
+ if ($this->rotation_angle === '' OR ! in_array($this->rotation_angle, $degs))
{
$this->set_error('imglib_rotation_angle_required');
return FALSE;
}
// Reassign the width and height
- if ($this->rotation_angle == 90 OR $this->rotation_angle == 270)
+ if ($this->rotation_angle === 90 OR $this->rotation_angle === 270)
{
$this->width = $this->orig_height;
$this->height = $this->orig_width;
@@ -449,9 +730,9 @@ class CI_Image_lib {
// If the target width/height match the source, AND if the new file name is not equal to the old file name
// we'll simply make a copy of the original with the new name... assuming dynamic rendering is off.
- if ($this->dynamic_output === FALSE && $this->orig_width == $this->width && $this->orig_height == $this->height)
+ if ($this->dynamic_output === FALSE && $this->orig_width === $this->width && $this->orig_height === $this->height)
{
- if ($this->source_image != $this->new_image && @copy($this->full_src_path, $this->full_dst_path))
+ if ($this->source_image !== $this->new_image && @copy($this->full_src_path, $this->full_dst_path))
{
@chmod($this->full_dst_path, FILE_WRITE_MODE);
}
@@ -460,7 +741,7 @@ class CI_Image_lib {
}
// Let's set up our values based on the action
- if ($action == 'crop')
+ if ($action === 'crop')
{
// Reassign the source width/height if cropping
$this->orig_width = $this->width;
@@ -470,7 +751,7 @@ class CI_Image_lib {
if ($this->gd_version() !== FALSE)
{
$gd_version = str_replace('0', '', $this->gd_version());
- $v2_override = ($gd_version == 2) ? TRUE : FALSE;
+ $v2_override = ($gd_version === 2);
}
}
else
@@ -492,7 +773,7 @@ class CI_Image_lib {
* it appears that this is no longer the issue that it was in 2004, so we've removed it, retaining it in the comment
* below should that ever prove inaccurate.
*
- * if ($this->image_library === 'gd2' && function_exists('imagecreatetruecolor') && $v2_override == FALSE)
+ * if ($this->image_library === 'gd2' && function_exists('imagecreatetruecolor') && $v2_override === FALSE)
*/
if ($this->image_library === 'gd2' && function_exists('imagecreatetruecolor'))
{
@@ -507,7 +788,7 @@ class CI_Image_lib {
$dst_img = $create($this->width, $this->height);
- if ($this->image_type == 3) // png we can actually preserve transparency
+ if ($this->image_type === 3) // png we can actually preserve transparency
{
imagealphablending($dst_img, FALSE);
imagesavealpha($dst_img, TRUE);
@@ -516,7 +797,7 @@ class CI_Image_lib {
$copy($dst_img, $src_img, 0, 0, $this->x_axis, $this->y_axis, $this->width, $this->height, $this->orig_width, $this->orig_height);
// Show the image
- if ($this->dynamic_output == TRUE)
+ if ($this->dynamic_output === TRUE)
{
$this->image_display_gd($dst_img);
}
@@ -548,7 +829,7 @@ class CI_Image_lib {
public function image_process_imagemagick($action = 'resize')
{
// Do we have a vaild library path?
- if ($this->library_path == '')
+ if ($this->library_path === '')
{
$this->set_error('imglib_libpath_invalid');
return FALSE;
@@ -562,11 +843,11 @@ class CI_Image_lib {
// Execute the command
$cmd = $this->library_path.' -quality '.$this->quality;
- if ($action == 'crop')
+ if ($action === 'crop')
{
$cmd .= ' -crop '.$this->width.'x'.$this->height.'+'.$this->x_axis.'+'.$this->y_axis.' "'.$this->full_src_path.'" "'.$this->full_dst_path .'" 2>&1';
}
- elseif ($action == 'rotate')
+ elseif ($action === 'rotate')
{
$angle = ($this->rotation_angle === 'hor' OR $this->rotation_angle === 'vrt')
? '-flop' : '-rotate '.$this->rotation_angle;
@@ -575,11 +856,22 @@ class CI_Image_lib {
}
else // Resize
{
- $cmd .= ' -resize '.$this->width.'x'.$this->height.' "'.$this->full_src_path.'" "'.$this->full_dst_path.'" 2>&1';
+ if($this->maintain_ratio === TRUE)
+ {
+ $cmd .= ' -resize '.$this->width.'x'.$this->height.' "'.$this->full_src_path.'" "'.$this->full_dst_path.'" 2>&1';
+ }
+ else
+ {
+ $cmd .= ' -resize '.$this->width.'x'.$this->height.'\! "'.$this->full_src_path.'" "'.$this->full_dst_path.'" 2>&1';
+ }
}
$retval = 1;
- @exec($cmd, $output, $retval);
+ // exec() might be disabled
+ if (function_usable('exec'))
+ {
+ @exec($cmd, $output, $retval);
+ }
// Did it work?
if ($retval > 0)
@@ -606,7 +898,7 @@ class CI_Image_lib {
*/
public function image_process_netpbm($action = 'resize')
{
- if ($this->library_path == '')
+ if ($this->library_path === '')
{
$this->set_error('imglib_libpath_invalid');
return FALSE;
@@ -616,36 +908,36 @@ class CI_Image_lib {
switch ($this->image_type)
{
case 1 :
- $cmd_in = 'giftopnm';
- $cmd_out = 'ppmtogif';
+ $cmd_in = 'giftopnm';
+ $cmd_out = 'ppmtogif';
break;
case 2 :
- $cmd_in = 'jpegtopnm';
- $cmd_out = 'ppmtojpeg';
+ $cmd_in = 'jpegtopnm';
+ $cmd_out = 'ppmtojpeg';
break;
case 3 :
- $cmd_in = 'pngtopnm';
- $cmd_out = 'ppmtopng';
+ $cmd_in = 'pngtopnm';
+ $cmd_out = 'ppmtopng';
break;
}
- if ($action == 'crop')
+ if ($action === 'crop')
{
$cmd_inner = 'pnmcut -left '.$this->x_axis.' -top '.$this->y_axis.' -width '.$this->width.' -height '.$this->height;
}
- elseif ($action == 'rotate')
+ elseif ($action === 'rotate')
{
switch ($this->rotation_angle)
{
- case 90 : $angle = 'r270';
+ case 90: $angle = 'r270';
break;
- case 180 : $angle = 'r180';
+ case 180: $angle = 'r180';
break;
- case 270 : $angle = 'r90';
+ case 270: $angle = 'r90';
break;
- case 'vrt' : $angle = 'tb';
+ case 'vrt': $angle = 'tb';
break;
- case 'hor' : $angle = 'lr';
+ case 'hor': $angle = 'lr';
break;
}
@@ -659,7 +951,11 @@ class CI_Image_lib {
$cmd = $this->library_path.$cmd_in.' '.$this->full_src_path.' | '.$cmd_inner.' | '.$cmd_out.' > '.$this->dest_folder.'netpbm.tmp';
$retval = 1;
- @exec($cmd, $output, $retval);
+ // exec() might be disabled
+ if (function_usable('exec'))
+ {
+ @exec($cmd, $output, $retval);
+ }
// Did it work?
if ($retval > 0)
@@ -671,7 +967,7 @@ class CI_Image_lib {
// With NetPBM we have to create a temporary image.
// If you try manipulating the original it fails so
// we have to rename the temp file.
- copy ($this->dest_folder.'netpbm.tmp', $this->full_dst_path);
+ copy($this->dest_folder.'netpbm.tmp', $this->full_dst_path);
unlink($this->dest_folder.'netpbm.tmp');
@chmod($this->full_dst_path, FILE_WRITE_MODE);
@@ -704,7 +1000,7 @@ class CI_Image_lib {
$dst_img = imagerotate($src_img, $this->rotation_angle, $white);
// Show the image
- if ($this->dynamic_output == TRUE)
+ if ($this->dynamic_output === TRUE)
{
$this->image_display_gd($dst_img);
}
@@ -778,7 +1074,7 @@ class CI_Image_lib {
}
// Show the image
- if ($this->dynamic_output == TRUE)
+ if ($this->dynamic_output === TRUE)
{
$this->image_display_gd($src_img);
}
@@ -804,7 +1100,6 @@ class CI_Image_lib {
* This is a wrapper function that chooses the type
* of watermarking based on the specified preference.
*
- * @param string
* @return bool
*/
public function watermark()
@@ -850,10 +1145,10 @@ class CI_Image_lib {
$this->wm_vrt_alignment = strtoupper($this->wm_vrt_alignment[0]);
$this->wm_hor_alignment = strtoupper($this->wm_hor_alignment[0]);
- if ($this->wm_vrt_alignment == 'B')
+ if ($this->wm_vrt_alignment === 'B')
$this->wm_vrt_offset = $this->wm_vrt_offset * -1;
- if ($this->wm_hor_alignment == 'R')
+ if ($this->wm_hor_alignment === 'R')
$this->wm_hor_offset = $this->wm_hor_offset * -1;
// Set the base x and y axis values
@@ -881,7 +1176,7 @@ class CI_Image_lib {
}
// Build the finalized image
- if ($wm_img_type == 3 && function_exists('imagealphablending'))
+ if ($wm_img_type === 3 && function_exists('imagealphablending'))
{
@imagealphablending($src_img, TRUE);
}
@@ -904,7 +1199,7 @@ class CI_Image_lib {
}
// Output the image
- if ($this->dynamic_output == TRUE)
+ if ($this->dynamic_output === TRUE)
{
$this->image_display_gd($src_img);
}
@@ -933,7 +1228,7 @@ class CI_Image_lib {
return FALSE;
}
- if ($this->wm_use_truetype == TRUE && ! file_exists($this->wm_font_path))
+ if ($this->wm_use_truetype === TRUE && ! file_exists($this->wm_font_path))
{
$this->set_error('imglib_missing_font');
return FALSE;
@@ -949,18 +1244,18 @@ class CI_Image_lib {
// invert the offset. Note: The horizontal
// offset flips itself automatically
- if ($this->wm_vrt_alignment == 'B')
+ if ($this->wm_vrt_alignment === 'B')
$this->wm_vrt_offset = $this->wm_vrt_offset * -1;
- if ($this->wm_hor_alignment == 'R')
+ if ($this->wm_hor_alignment === 'R')
$this->wm_hor_offset = $this->wm_hor_offset * -1;
// Set font width and height
// These are calculated differently depending on
// whether we are using the true type font or not
- if ($this->wm_use_truetype == TRUE)
+ if ($this->wm_use_truetype === TRUE)
{
- if ($this->wm_font_size == '')
+ if ($this->wm_font_size === '')
{
$this->wm_font_size = 17;
}
@@ -979,11 +1274,11 @@ class CI_Image_lib {
$x_axis = $this->wm_hor_offset + $this->wm_padding;
$y_axis = $this->wm_vrt_offset + $this->wm_padding;
- if ($this->wm_use_drop_shadow == FALSE)
+ if ($this->wm_use_drop_shadow === FALSE)
$this->wm_shadow_distance = 0;
- $this->wm_vrt_alignment = strtoupper(substr($this->wm_vrt_alignment, 0, 1));
- $this->wm_hor_alignment = strtoupper(substr($this->wm_hor_alignment, 0, 1));
+ $this->wm_vrt_alignment = strtoupper($this->wm_vrt_alignment[0]);
+ $this->wm_hor_alignment = strtoupper($this->wm_hor_alignment[0]);
// Set verticle alignment
if ($this->wm_vrt_alignment === 'M')
@@ -1034,10 +1329,17 @@ class CI_Image_lib {
imagestring($src_img, $this->wm_font_size, $x_shad, $y_shad, $this->wm_text, $drp_color);
imagestring($src_img, $this->wm_font_size, $x_axis, $y_axis, $this->wm_text, $txt_color);
}
+
+ // We can preserve transparency for PNG images
+ if ($this->image_type === 3)
+ {
+ imagealphablending($src_img, FALSE);
+ imagesavealpha($src_img, TRUE);
+ }
}
// Output the final image
- if ($this->dynamic_output == TRUE)
+ if ($this->dynamic_output === TRUE)
{
$this->image_display_gd($src_img);
}
@@ -1060,17 +1362,17 @@ class CI_Image_lib {
* based on the type of image being processed
*
* @param string
+ * @param string
* @return resource
*/
public function image_create_gd($path = '', $image_type = '')
{
- if ($path == '')
+ if ($path === '')
$path = $this->full_src_path;
- if ($image_type == '')
+ if ($image_type === '')
$image_type = $this->image_type;
-
switch ($image_type)
{
case 1 :
@@ -1122,49 +1424,49 @@ class CI_Image_lib {
{
switch ($this->image_type)
{
- case 1 :
- if ( ! function_exists('imagegif'))
- {
- $this->set_error(array('imglib_unsupported_imagecreate', 'imglib_gif_not_supported'));
- return FALSE;
- }
+ case 1:
+ if ( ! function_exists('imagegif'))
+ {
+ $this->set_error(array('imglib_unsupported_imagecreate', 'imglib_gif_not_supported'));
+ return FALSE;
+ }
- if ( ! @imagegif($resource, $this->full_dst_path))
- {
- $this->set_error('imglib_save_failed');
- return FALSE;
- }
- break;
- case 2 :
- if ( ! function_exists('imagejpeg'))
- {
- $this->set_error(array('imglib_unsupported_imagecreate', 'imglib_jpg_not_supported'));
- return FALSE;
- }
+ if ( ! @imagegif($resource, $this->full_dst_path))
+ {
+ $this->set_error('imglib_save_failed');
+ return FALSE;
+ }
+ break;
+ case 2:
+ if ( ! function_exists('imagejpeg'))
+ {
+ $this->set_error(array('imglib_unsupported_imagecreate', 'imglib_jpg_not_supported'));
+ return FALSE;
+ }
- if ( ! @imagejpeg($resource, $this->full_dst_path, $this->quality))
- {
- $this->set_error('imglib_save_failed');
- return FALSE;
- }
- break;
- case 3 :
- if ( ! function_exists('imagepng'))
- {
- $this->set_error(array('imglib_unsupported_imagecreate', 'imglib_png_not_supported'));
- return FALSE;
- }
+ if ( ! @imagejpeg($resource, $this->full_dst_path, $this->quality))
+ {
+ $this->set_error('imglib_save_failed');
+ return FALSE;
+ }
+ break;
+ case 3:
+ if ( ! function_exists('imagepng'))
+ {
+ $this->set_error(array('imglib_unsupported_imagecreate', 'imglib_png_not_supported'));
+ return FALSE;
+ }
- if ( ! @imagepng($resource, $this->full_dst_path))
- {
- $this->set_error('imglib_save_failed');
- return FALSE;
- }
- break;
- default :
- $this->set_error(array('imglib_unsupported_imagecreate'));
- return FALSE;
- break;
+ if ( ! @imagepng($resource, $this->full_dst_path))
+ {
+ $this->set_error('imglib_save_failed');
+ return FALSE;
+ }
+ break;
+ default:
+ $this->set_error(array('imglib_unsupported_imagecreate'));
+ return FALSE;
+ break;
}
return TRUE;
@@ -1187,13 +1489,13 @@ class CI_Image_lib {
switch ($this->image_type)
{
- case 1 : imagegif($resource);
+ case 1 : imagegif($resource);
break;
- case 2 : imagejpeg($resource, '', $this->quality);
+ case 2 : imagejpeg($resource, '', $this->quality);
break;
- case 3 : imagepng($resource);
+ case 3 : imagepng($resource);
break;
- default : echo 'Unable to display the image';
+ default: echo 'Unable to display the image';
break;
}
}
@@ -1214,14 +1516,14 @@ class CI_Image_lib {
*/
public function image_reproportion()
{
- if (($this->width == 0 && $this->height == 0) OR $this->orig_width == 0 OR $this->orig_height == 0
- OR ( ! preg_match('/^[0-9]+$/', $this->width) && ! preg_match('/^[0-9]+$/', $this->height))
- OR ! preg_match('/^[0-9]+$/', $this->orig_width) OR ! preg_match('/^[0-9]+$/', $this->orig_height))
+ if (($this->width === 0 && $this->height === 0) OR $this->orig_width === 0 OR $this->orig_height === 0
+ OR ( ! ctype_digit((string) $this->width) && ! ctype_digit((string) $this->height))
+ OR ! ctype_digit((string) $this->orig_width) OR ! ctype_digit((string) $this->orig_height))
{
return;
}
- // Sanitize so we don't call preg_match() anymore
+ // Sanitize
$this->width = (int) $this->width;
$this->height = (int) $this->height;
@@ -1261,6 +1563,7 @@ class CI_Image_lib {
* A helper function that gets info about the file
*
* @param string
+ * @param bool
* @return mixed
*/
public function get_image_properties($path = '', $return = FALSE)
@@ -1268,7 +1571,7 @@ class CI_Image_lib {
// For now we require GD but we should
// find a way to determine this using IM or NetPBM
- if ($path == '')
+ if ($path === '')
{
$path = $this->full_src_path;
}
@@ -1283,7 +1586,7 @@ class CI_Image_lib {
$types = array(1 => 'gif', 2 => 'jpeg', 3 => 'png');
$mime = (isset($types[$vals[2]])) ? 'image/'.$types[$vals[2]] : 'image/jpg';
- if ($return == TRUE)
+ if ($return === TRUE)
{
return array(
'width' => $vals[0],
@@ -1333,20 +1636,22 @@ class CI_Image_lib {
foreach ($allowed as $item)
{
- if ( ! isset($vals[$item]) OR $vals[$item] == '')
+ if (empty($vals[$item]))
+ {
$vals[$item] = 0;
+ }
}
- if ($vals['width'] == 0 OR $vals['height'] == 0)
+ if ($vals['width'] === 0 OR $vals['height'] === 0)
{
return $vals;
}
- if ($vals['new_width'] == 0)
+ if ($vals['new_width'] === 0)
{
$vals['new_width'] = ceil($vals['width']*$vals['new_height']/$vals['height']);
}
- elseif ($vals['new_height'] == 0)
+ elseif ($vals['new_height'] === 0)
{
$vals['new_height'] = ceil($vals['new_width']*$vals['height']/$vals['width']);
}
@@ -1432,15 +1737,14 @@ class CI_Image_lib {
{
foreach ($msg as $val)
{
-
- $msg = ($CI->lang->line($val) == FALSE) ? $val : $CI->lang->line($val);
+ $msg = ($CI->lang->line($val) === FALSE) ? $val : $CI->lang->line($val);
$this->error_msg[] = $msg;
log_message('error', $msg);
}
}
else
{
- $msg = ($CI->lang->line($msg) == FALSE) ? $msg : $CI->lang->line($msg);
+ $msg = ($CI->lang->line($msg) === FALSE) ? $msg : $CI->lang->line($msg);
$this->error_msg[] = $msg;
log_message('error', $msg);
}
@@ -1452,6 +1756,7 @@ class CI_Image_lib {
* Show error messages
*
* @param string
+ * @param string
* @return string
*/
public function display_errors($open = '<p>', $close = '</p>')
diff --git a/system/libraries/Javascript.php b/system/libraries/Javascript.php
index 629a3adfe..420b623ee 100644
--- a/system/libraries/Javascript.php
+++ b/system/libraries/Javascript.php
@@ -1,4 +1,4 @@
-<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');
+<?php
/**
* CodeIgniter
*
@@ -24,6 +24,7 @@
* @since Version 1.0
* @filesource
*/
+defined('BASEPATH') OR exit('No direct script access allowed');
/**
* Javascript Class
@@ -36,8 +37,21 @@
*/
class CI_Javascript {
+ /**
+ * JavaScript location
+ *
+ * @var string
+ */
protected $_javascript_location = 'js';
+ // --------------------------------------------------------------------
+
+ /**
+ * Constructor
+ *
+ * @param array $params
+ * @return void
+ */
public function __construct($params = array())
{
$defaults = array('js_library_driver' => 'jquery', 'autoload' => TRUE);
@@ -312,8 +326,7 @@ class CI_Javascript {
*
* Outputs a javascript library mouseup event
*
- * @param string The element to attach the event to
- * @param string The code to execute
+ * @param string $js Code to execute
* @return string
*/
public function ready($js)
@@ -394,9 +407,10 @@ class CI_Javascript {
*
* Outputs a javascript library animate event
*
- * @param string - element
- * @param string - One of 'slow', 'normal', 'fast', or time in milliseconds
- * @param string - Javascript callback function
+ * @param string $element = 'this'
+ * @param array $params = array()
+ * @param mixed $speed 'slow', 'normal', 'fast', or time in milliseconds
+ * @param string $extra
* @return string
*/
public function animate($element = 'this', $params = array(), $speed = '', $extra = '')
@@ -546,10 +560,11 @@ class CI_Javascript {
*
* Outputs a javascript library toggle class event
*
- * @param string - element
+ * @param string $element = 'this'
+ * @param string $class = ''
* @return string
*/
- public function toggleClass($element = 'this', $class='')
+ public function toggleClass($element = 'this', $class = '')
{
return $this->js->_toggleClass($element, $class);
}
@@ -571,7 +586,6 @@ class CI_Javascript {
return $this->js->_show($element, $speed, $callback);
}
-
// --------------------------------------------------------------------
/**
@@ -579,7 +593,8 @@ class CI_Javascript {
*
* gather together all script needing to be output
*
- * @param string The element to attach the event to
+ * @param string $view_var
+ * @param bool $script_tags
* @return string
*/
public function compile($view_var = 'script_foot', $script_tags = TRUE)
@@ -587,6 +602,8 @@ class CI_Javascript {
$this->js->_compile($view_var, $script_tags);
}
+ // --------------------------------------------------------------------
+
/**
* Clear Compile
*
@@ -606,7 +623,8 @@ class CI_Javascript {
*
* Outputs a <script> tag with the source as an external js file
*
- * @param string The element to attach the event to
+ * @param string $external_file
+ * @param bool $relative
* @return string
*/
public function external($external_file = '', $relative = FALSE)
@@ -615,12 +633,12 @@ class CI_Javascript {
{
$this->_javascript_location = $external_file;
}
- elseif ($this->CI->config->item('javascript_location') != '')
+ elseif ($this->CI->config->item('javascript_location') !== '')
{
$this->_javascript_location = $this->CI->config->item('javascript_location');
}
- if ($relative === TRUE OR strncmp($external_file, 'http://', 7) === 0 OR strncmp($external_file, 'https://', 8) === 0)
+ if ($relative === TRUE OR strpos($external_file, 'http://') === 0 OR strpos($external_file, 'https://') === 0)
{
$str = $this->_open_script($external_file);
}
@@ -667,7 +685,7 @@ class CI_Javascript {
protected function _open_script($src = '')
{
return '<script type="text/javascript" charset="'.strtolower($this->CI->config->item('charset')).'"'
- .($src == '' ? '>' : ' src="'.$src.'">');
+ .($src === '' ? '>' : ' src="'.$src.'">');
}
// --------------------------------------------------------------------
@@ -723,7 +741,7 @@ class CI_Javascript {
{
if (is_object($result))
{
- $json_result = $result->result_array();
+ $json_result = is_callable(array($result, 'result_array')) ? $result->result_array() : (array) $result;
}
elseif (is_array($result))
{
@@ -799,7 +817,8 @@ class CI_Javascript {
*
* Ensures a standard json value and escapes values
*
- * @param mixed
+ * @param mixed $result
+ * @param bool $is_key = FALSE
* @return string
*/
protected function _prep_args($result, $is_key = FALSE)
diff --git a/system/libraries/Migration.php b/system/libraries/Migration.php
index a18fcb9f1..e591ab64a 100644
--- a/system/libraries/Migration.php
+++ b/system/libraries/Migration.php
@@ -1,4 +1,4 @@
-<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');
+<?php
/**
* CodeIgniter
*
@@ -24,6 +24,7 @@
* @since Version 3.0
* @filesource
*/
+defined('BASEPATH') OR exit('No direct script access allowed');
/**
* Migration Class
@@ -39,14 +40,68 @@
*/
class CI_Migration {
+ /**
+ * Whether the library is enabled
+ *
+ * @var bool
+ */
protected $_migration_enabled = FALSE;
+
+ /**
+ * Migration numbering type
+ *
+ * @var bool
+ */
+ protected $_migration_type = 'sequential';
+
+ /**
+ * Path to migration classes
+ *
+ * @var string
+ */
protected $_migration_path = NULL;
+
+ /**
+ * Current migration version
+ *
+ * @var mixed
+ */
protected $_migration_version = 0;
+
+ /**
+ * Database table with migration info
+ *
+ * @var string
+ */
protected $_migration_table = 'migrations';
+
+ /**
+ * Whether to automatically run migrations
+ *
+ * @var bool
+ */
protected $_migration_auto_latest = FALSE;
+ /**
+ * Migration basename regex
+ *
+ * @var bool
+ */
+ protected $_migration_regex = NULL;
+
+ /**
+ * Error message
+ *
+ * @var string
+ */
protected $_error_string = '';
+ /**
+ * Initialize Migration Class
+ *
+ * @param array $config
+ * @return void
+ */
public function __construct($config = array())
{
# Only run this constructor on main library load
@@ -57,7 +112,7 @@ class CI_Migration {
foreach ($config as $key => $val)
{
- $this->{'_' . $key} = $val;
+ $this->{'_'.$key} = $val;
}
log_message('debug', 'Migrations class initialized');
@@ -69,7 +124,7 @@ class CI_Migration {
}
// If not set, set it
- $this->_migration_path != '' OR $this->_migration_path = APPPATH.'migrations/';
+ $this->_migration_path !== '' OR $this->_migration_path = APPPATH.'migrations/';
// Add trailing slash if not set
$this->_migration_path = rtrim($this->_migration_path, '/').'/';
@@ -86,11 +141,22 @@ class CI_Migration {
show_error('Migrations configuration file (migration.php) must have "migration_table" set.');
}
+ // Migration basename regex
+ $this->_migration_regex = ($this->_migration_type === 'timestamp')
+ ? '/^\d{14}_(\w+)$/'
+ : '/^\d{3}_(\w+)$/';
+
+ // Make sure a valid migration numbering type was set.
+ if ( ! in_array($this->_migration_type, array('sequential', 'timestamp')))
+ {
+ show_error('An invalid migration numbering type was specified: '.$this->_migration_type);
+ }
+
// If the migrations table is missing, make it
if ( ! $this->db->table_exists($this->_migration_table))
{
$this->dbforge->add_field(array(
- 'version' => array('type' => 'INT', 'constraint' => 3),
+ 'version' => array('type' => 'BIGINT', 'constraint' => 20),
));
$this->dbforge->create_table($this->_migration_table, TRUE);
@@ -113,118 +179,88 @@ class CI_Migration {
* Calls each migration step required to get to the schema version of
* choice
*
- * @param int Target schema version
+ * @param int $target_version Target schema version
* @return mixed TRUE if already latest, FALSE if failed, int if upgraded
*/
public function version($target_version)
{
- $start = $current_version = $this->_get_version();
- $stop = $target_version;
+ $current_version = (int) $this->_get_version();
+ $target_version = (int) $target_version;
+
+ $migrations = $this->find_migrations();
+
+ if ($target_version > 0 && ! isset($migrations[$target_version]))
+ {
+ $this->_error_string = sprintf($this->lang->line('migration_not_found'), $target_version);
+ return FALSE;
+ }
if ($target_version > $current_version)
{
// Moving Up
- ++$start;
- ++$stop;
- $step = 1;
+ $method = 'up';
}
else
{
- // Moving Down
- $step = -1;
+ // Moving Down, apply in reverse order
+ $method = 'down';
+ krsort($migrations);
}
- $method = $step === 1 ? 'up' : 'down';
- $migrations = array();
-
- // We now prepare to actually DO the migrations
- // But first let's make sure that everything is the way it should be
- for ($i = $start; $i != $stop; $i += $step)
+ if (empty($migrations))
{
- $f = glob(sprintf($this->_migration_path.'%03d_*.php', $i));
+ return TRUE;
+ }
+
+ $previous = FALSE;
- // Only one migration per step is permitted
- if (count($f) > 1)
+ // Validate all available migrations, and run the ones within our target range
+ foreach ($migrations as $number => $file)
+ {
+ // Check for sequence gaps
+ if ($this->_migration_type === 'sequential' && $previous !== FALSE && abs($number - $previous) > 1)
{
- $this->_error_string = sprintf($this->lang->line('migration_multiple_version'), $i);
+ $this->_error_string = sprintf($this->lang->line('migration_sequence_gap'), $number);
return FALSE;
}
- // Migration step not found
- if (count($f) === 0)
- {
- // If trying to migrate up to a version greater than the last
- // existing one, migrate to the last one.
- if ($step === 1)
- {
- break;
- }
+ include $file;
+ $class = 'Migration_'.ucfirst(strtolower($this->_get_migration_name(basename($file, '.php'))));
- // If trying to migrate down but we're missing a step,
- // something must definitely be wrong.
- $this->_error_string = sprintf($this->lang->line('migration_not_found'), $i);
+ // Validate the migration file structure
+ if ( ! class_exists($class))
+ {
+ $this->_error_string = sprintf($this->lang->line('migration_class_doesnt_exist'), $class);
return FALSE;
}
- $file = basename($f[0]);
- $name = basename($f[0], '.php');
+ $previous = $number;
- // Filename validations
- if (preg_match('/^\d{3}_(\w+)$/', $name, $match))
+ // Run migrations that are inside the target range
+ if (
+ ($method === 'up' && $number > $current_version && $number <= $target_version) OR
+ ($method === 'down' && $number <= $current_version && $number > $target_version)
+ )
{
- $match[1] = strtolower($match[1]);
-
- // Cannot repeat a migration at different steps
- if (in_array($match[1], $migrations))
- {
- $this->_error_string = sprintf($this->lang->line('migration_multiple_version'), $match[1]);
- return FALSE;
- }
-
- include $f[0];
- $class = 'Migration_'.ucfirst($match[1]);
-
- if ( ! class_exists($class))
- {
- $this->_error_string = sprintf($this->lang->line('migration_class_doesnt_exist'), $class);
- return FALSE;
- }
-
- if ( ! is_callable(array($class, $method)))
+ $instance = new $class();
+ if ( ! is_callable(array($instance, $method)))
{
$this->_error_string = sprintf($this->lang->line('migration_missing_'.$method.'_method'), $class);
return FALSE;
}
- $migrations[] = $match[1];
+ log_message('debug', 'Migrating '.$method.' from version '.$current_version.' to version '.$number);
+ call_user_func(array($instance, $method));
+ $current_version = $number;
+ $this->_update_version($current_version);
}
- else
- {
- $this->_error_string = sprintf($this->lang->line('migration_invalid_filename'), $file);
- return FALSE;
- }
- }
-
- log_message('debug', 'Current migration: '.$current_version);
-
- $version = $i + ($step === 1 ? -1 : 0);
-
- // If there is nothing to do so quit
- if ($migrations === array())
- {
- return TRUE;
}
- log_message('debug', 'Migrating from '.$method.' to version '.$version);
-
- // Loop through the migrations
- foreach ($migrations AS $migration)
+ // This is necessary when moving down, since the the last migration applied
+ // will be the down() method for the next migration up from the target
+ if ($current_version <> $target_version)
{
- // Run the migration class
- $class = 'Migration_'.ucfirst(strtolower($migration));
- call_user_func(array(new $class, $method));
-
- $current_version += $step;
+ $current_version = $target_version;
$this->_update_version($current_version);
}
@@ -238,21 +274,23 @@ class CI_Migration {
/**
* Set's the schema to the latest migration
*
- * @return mixed true if already latest, false if failed, int if upgraded
+ * @return mixed TRUE if already latest, FALSE if failed, int if upgraded
*/
public function latest()
{
- if ( ! $migrations = $this->find_migrations())
+ $migrations = $this->find_migrations();
+
+ if (empty($migrations))
{
$this->_error_string = $this->lang->line('migration_none_found');
- return false;
+ return FALSE;
}
$last_migration = basename(end($migrations));
// Calculate the last migration step from existing migration
// filenames and procceed to the standard version migration
- return $this->version((int) substr($last_migration, 0, 3));
+ return $this->version($this->_get_migration_number($last_migration));
}
// --------------------------------------------------------------------
@@ -260,7 +298,7 @@ class CI_Migration {
/**
* Set's the schema to the migration version set in config
*
- * @return mixed true if already current, false if failed, int if upgraded
+ * @return mixed TRUE if already current, FALSE if failed, int if upgraded
*/
public function current()
{
@@ -282,27 +320,66 @@ class CI_Migration {
// --------------------------------------------------------------------
/**
- * Set's the schema to the latest migration
+ * Retrieves list of available migration scripts
*
- * @return mixed true if already latest, false if failed, int if upgraded
+ * @return array list of migration file paths sorted by version
*/
- protected function find_migrations()
+ public function find_migrations()
{
- // Load all *_*.php files in the migrations path
- $files = glob($this->_migration_path.'*_*.php');
+ $migrations = array();
- for ($i = 0, $c = count($files); $i < $c; $i++)
+ // Load all *_*.php files in the migrations path
+ foreach (glob($this->_migration_path.'*_*.php') as $file)
{
- // Mark wrongly formatted files as false for later filtering
- if ( ! preg_match('/^\d{3}_(\w+)$/', basename($files[$i], '.php')))
+ $name = basename($file, '.php');
+
+ // Filter out non-migration files
+ if (preg_match($this->_migration_regex, $name))
{
- $files[$i] = FALSE;
+ $number = $this->_get_migration_number($name);
+
+ // There cannot be duplicate migration numbers
+ if (isset($migrations[$number]))
+ {
+ $this->_error_string = sprintf($this->lang->line('migration_multiple_version'), $number);
+ show_error($this->_error_string);
+ }
+
+ $migrations[$number] = $file;
}
}
- sort($files);
+ ksort($migrations);
+ return $migrations;
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Extracts the migration number from a filename
+ *
+ * @param string $migration
+ * @return int Numeric portion of a migration filename
+ */
+ protected function _get_migration_number($migration)
+ {
+ return sscanf($migration, '%d', $number)
+ ? $number : 0;
+ }
+
+ // --------------------------------------------------------------------
- return $files;
+ /**
+ * Extracts the migration class name from a filename
+ *
+ * @param string $migration
+ * @return string text portion of a migration filename
+ */
+ protected function _get_migration_name($migration)
+ {
+ $parts = explode('_', $migration);
+ array_shift($parts);
+ return implode('_', $parts);
}
// --------------------------------------------------------------------
@@ -323,13 +400,13 @@ class CI_Migration {
/**
* Stores the current schema version
*
- * @param int Migration reached
+ * @param int $migration Migration reached
* @return void Outputs a report of the migration
*/
- protected function _update_version($migrations)
+ protected function _update_version($migration)
{
return $this->db->update($this->_migration_table, array(
- 'version' => $migrations
+ 'version' => $migration
));
}
@@ -338,13 +415,14 @@ class CI_Migration {
/**
* Enable the use of CI super-global
*
- * @param $var
+ * @param string $var
* @return mixed
*/
public function __get($var)
{
return get_instance()->$var;
}
+
}
/* End of file Migration.php */
diff --git a/system/libraries/Pagination.php b/system/libraries/Pagination.php
index 0fe73d69f..66b341760 100644
--- a/system/libraries/Pagination.php
+++ b/system/libraries/Pagination.php
@@ -1,4 +1,4 @@
-<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');
+<?php
/**
* CodeIgniter
*
@@ -24,6 +24,7 @@
* @since Version 1.0
* @filesource
*/
+defined('BASEPATH') OR exit('No direct script access allowed');
/**
* Pagination Class
@@ -36,43 +37,270 @@
*/
class CI_Pagination {
- protected $base_url = ''; // The page we are linking to
- protected $prefix = ''; // A custom prefix added to the path.
- protected $suffix = ''; // A custom suffix added to the path.
- protected $total_rows = 0; // Total number of items (database results)
- protected $per_page = 10; // Max number of items you want shown per page
- protected $num_links = 2; // Number of "digit" links to show before/after the currently viewed page
- protected $cur_page = 0; // The current page being viewed
- protected $use_page_numbers = FALSE; // Use page number for segment instead of offset
- protected $first_link = '&lsaquo; First';
- protected $next_link = '&gt;';
- protected $prev_link = '&lt;';
- protected $last_link = 'Last &rsaquo;';
- protected $uri_segment = 3;
- protected $full_tag_open = '';
- protected $full_tag_close = '';
- protected $first_tag_open = '';
- protected $first_tag_close = '&nbsp;';
- protected $last_tag_open = '&nbsp;';
- protected $last_tag_close = '';
- protected $first_url = ''; // Alternative URL for the First Page.
- protected $cur_tag_open = '&nbsp;<strong>';
- protected $cur_tag_close = '</strong>';
- protected $next_tag_open = '&nbsp;';
- protected $next_tag_close = '&nbsp;';
- protected $prev_tag_open = '&nbsp;';
- protected $prev_tag_close = '';
- protected $num_tag_open = '&nbsp;';
- protected $num_tag_close = '';
+ /**
+ * Base URL
+ *
+ * The page that we're linking to
+ *
+ * @var string
+ */
+ protected $base_url = '';
+
+ /**
+ * Prefix
+ *
+ * @var string
+ */
+ protected $prefix = '';
+
+ /**
+ * Suffix
+ *
+ * @var string
+ */
+ protected $suffix = '';
+
+ /**
+ * Total number of items
+ *
+ * @var int
+ */
+ protected $total_rows = 0;
+
+ /**
+ * Items per page
+ *
+ * @var int
+ */
+ protected $per_page = 10;
+
+ /**
+ * Number of links to show
+ *
+ * Relates to "digit" type links shown before/after
+ * the currently viewed page.
+ *
+ * @var int
+ */
+ protected $num_links = 2;
+
+ /**
+ * Current page
+ *
+ * @var int
+ */
+ protected $cur_page = 0;
+
+ /**
+ * Use page numbers flag
+ *
+ * Whether to use actual page numbers instead of an offset
+ *
+ * @var bool
+ */
+ protected $use_page_numbers = FALSE;
+
+ /**
+ * First link
+ *
+ * @var string
+ */
+ protected $first_link = '&lsaquo; First';
+
+ /**
+ * Next link
+ *
+ * @var string
+ */
+ protected $next_link = '&gt;';
+
+ /**
+ * Previous link
+ *
+ * @var string
+ */
+ protected $prev_link = '&lt;';
+
+ /**
+ * Last link
+ *
+ * @var string
+ */
+ protected $last_link = 'Last &rsaquo;';
+
+ /**
+ * URI Segment
+ *
+ * @var int
+ */
+ protected $uri_segment = 3;
+
+ /**
+ * Full tag open
+ *
+ * @var string
+ */
+ protected $full_tag_open = '';
+
+ /**
+ * Full tag close
+ *
+ * @var string
+ */
+ protected $full_tag_close = '';
+
+ /**
+ * First tag open
+ *
+ * @var string
+ */
+ protected $first_tag_open = '';
+
+ /**
+ * First tag close
+ *
+ * @var string
+ */
+ protected $first_tag_close = '';
+
+ /**
+ * Last tag open
+ *
+ * @var string
+ */
+ protected $last_tag_open = '';
+
+ /**
+ * Last tag close
+ *
+ * @var string
+ */
+ protected $last_tag_close = '';
+
+ /**
+ * First URL
+ *
+ * An alternative URL for the first page
+ *
+ * @var string
+ */
+ protected $first_url = '';
+
+ /**
+ * Current tag open
+ *
+ * @var string
+ */
+ protected $cur_tag_open = '<strong>';
+
+ /**
+ * Current tag close
+ *
+ * @var string
+ */
+ protected $cur_tag_close = '</strong>';
+
+ /**
+ * Next tag open
+ *
+ * @var string
+ */
+ protected $next_tag_open = '';
+
+ /**
+ * Next tag close
+ *
+ * @var string
+ */
+ protected $next_tag_close = '';
+
+ /**
+ * Previous tag open
+ *
+ * @var string
+ */
+ protected $prev_tag_open = '';
+
+ /**
+ * Previous tag close
+ *
+ * @var string
+ */
+ protected $prev_tag_close = '';
+
+ /**
+ * Number tag open
+ *
+ * @var string
+ */
+ protected $num_tag_open = '';
+
+ /**
+ * Number tag close
+ *
+ * @var string
+ */
+ protected $num_tag_close = '';
+
+ /**
+ * Page query string flag
+ *
+ * @var bool
+ */
protected $page_query_string = FALSE;
+
+ /**
+ * Query string segment
+ *
+ * @var string
+ */
protected $query_string_segment = 'per_page';
- protected $display_pages = TRUE;
- protected $anchor_class = '';
+
+ /**
+ * Display pages flag
+ *
+ * @var bool
+ */
+ protected $display_pages = TRUE;
+
+ /**
+ * Attributes
+ *
+ * @var string
+ */
+ protected $_attributes = '';
+
+ /**
+ * Link types
+ *
+ * "rel" attribute
+ *
+ * @see CI_Pagination::_attr_rel()
+ * @var array
+ */
+ protected $_link_types = array();
+
+ /**
+ * Reuse query string flag
+ *
+ * @var bool
+ */
+ protected $reuse_query_string = FALSE;
+
+ /**
+ * Data page attribute
+ *
+ * @var string
+ */
+ protected $data_page_attr = 'data-ci-pagination-page';
+
+ // --------------------------------------------------------------------
/**
* Constructor
*
- * @param array initialization parameters
+ * @param array $params Initialization parameters
+ * @return void
*/
public function __construct($params = array())
{
@@ -85,11 +313,29 @@ class CI_Pagination {
/**
* Initialize Preferences
*
- * @param array initialization parameters
+ * @param array $params Initialization parameters
* @return void
*/
public function initialize($params = array())
{
+ $attributes = array();
+
+ if (isset($params['attributes']) && is_array($params['attributes']))
+ {
+ $attributes = $params['attributes'];
+ unset($params['attributes']);
+ }
+
+ // Deprecated legacy support for the anchor_class option
+ // Should be removed in CI 3.1+
+ if (isset($params['anchor_class']))
+ {
+ empty($params['anchor_class']) OR $attributes['class'] = $params['anchor_class'];
+ unset($params['anchor_class']);
+ }
+
+ $this->_parse_attributes($attributes);
+
if (count($params) > 0)
{
foreach ($params as $key => $val)
@@ -100,11 +346,6 @@ class CI_Pagination {
}
}
}
-
- if ($this->anchor_class != '')
- {
- $this->anchor_class = 'class="'.$this->anchor_class.'" ';
- }
}
// --------------------------------------------------------------------
@@ -117,7 +358,7 @@ class CI_Pagination {
public function create_links()
{
// If our item count or per-page total is zero there is no need to continue.
- if ($this->total_rows == 0 OR $this->per_page == 0)
+ if ($this->total_rows === 0 OR $this->per_page === 0)
{
return '';
}
@@ -138,9 +379,9 @@ class CI_Pagination {
$CI =& get_instance();
// See if we are using a prefix or suffix on links
- if ($this->prefix != '' OR $this->suffix != '')
+ if ($this->prefix !== '' OR $this->suffix !== '')
{
- $this->cur_page = (int) str_replace(array($this->prefix, $this->suffix), '', $CI->uri->segment($this->uri_segment));
+ $this->cur_page = (int) str_replace(array($this->prefix, $this->suffix), '', $CI->uri->rsegment($this->uri_segment));
}
if ($CI->config->item('enable_query_strings') === TRUE OR $this->page_query_string === TRUE)
@@ -150,13 +391,13 @@ class CI_Pagination {
$this->cur_page = (int) $CI->input->get($this->query_string_segment);
}
}
- elseif ( ! $this->cur_page && $CI->uri->segment($this->uri_segment) != $base_page)
+ elseif ( ! $this->cur_page && $CI->uri->segment($this->uri_segment) !== $base_page)
{
- $this->cur_page = (int) $CI->uri->segment($this->uri_segment);
+ $this->cur_page = (int) $CI->uri->rsegment($this->uri_segment);
}
// Set current page to 1 if it's not valid or if using page numbers instead of offset
- if ( ! is_numeric($this->cur_page) OR ($this->use_page_numbers && $this->cur_page == 0))
+ if ( ! is_numeric($this->cur_page) OR ($this->use_page_numbers && $this->cur_page === 0))
{
$this->cur_page = $base_page;
}
@@ -186,7 +427,7 @@ class CI_Pagination {
if ( ! $this->use_page_numbers)
{
- $this->cur_page = floor(($this->cur_page/$this->per_page) + 1);
+ $this->cur_page = (int) floor(($this->cur_page/$this->per_page) + 1);
}
// Calculate the start and end numbers. These determine
@@ -198,7 +439,8 @@ class CI_Pagination {
// string. If post, add a trailing slash to the base URL if needed
if ($CI->config->item('enable_query_strings') === TRUE OR $this->page_query_string === TRUE)
{
- $this->base_url = rtrim($this->base_url).'&amp;'.$this->query_string_segment.'=';
+ $segment = (strpos($this->base_url, '?')) ? '&amp;' : '?';
+ $this->base_url = rtrim($this->base_url).$segment.$this->query_string_segment.'=';
}
else
{
@@ -207,27 +449,58 @@ class CI_Pagination {
// And here we go...
$output = '';
+ $query_string = '';
+
+ // Add anything in the query string back to the links
+ // Note: Nothing to do with query_string_segment or any other query string options
+ if ($this->reuse_query_string === TRUE)
+ {
+ $get = $CI->input->get();
+
+ // Unset the controll, method, old-school routing options
+ unset($get['c'], $get['m'], $get[$this->query_string_segment]);
+
+ if ( ! empty($get))
+ {
+ // Put everything else onto the end
+ $query_string = (strpos($this->base_url, '?') !== FALSE ? '&amp;' : '?')
+ .http_build_query($get, '', '&amp;');
+
+ // Add this after the suffix to put it into more links easily
+ $this->suffix .= $query_string;
+ }
+ }
// Render the "First" link
if ($this->first_link !== FALSE && $this->cur_page > ($this->num_links + 1))
{
- $first_url = ($this->first_url == '') ? $this->base_url : $this->first_url;
- $output .= $this->first_tag_open.'<a '.$this->anchor_class.'href="'.$first_url.'">'.$this->first_link.'</a>'.$this->first_tag_close;
+ $first_url = ($this->first_url === '') ? $this->base_url : $this->first_url;
+
+ // Take the general parameters, and squeeze this pagination-page attr in there for JS fw's
+ $attributes = sprintf('%s %s="%d"', $this->_attributes, $this->data_page_attr, 1);
+
+ $output .= $this->first_tag_open.'<a href="'.$first_url.'"'.$attributes.$this->_attr_rel('start').'>'
+ .$this->first_link.'</a>'.$this->first_tag_close;
}
// Render the "previous" link
- if ($this->prev_link !== FALSE && $this->cur_page != 1)
+ if ($this->prev_link !== FALSE && $this->cur_page !== 1)
{
$i = ($this->use_page_numbers) ? $uri_page_number - 1 : $uri_page_number - $this->per_page;
- if ($i == $base_page && $this->first_url != '')
+ // Take the general parameters, and squeeze this pagination-page attr in there for JS fw's
+ $attributes = sprintf('%s %s="%d"', $this->_attributes, $this->data_page_attr, (int) $i);
+
+ if ($i === $base_page && $this->first_url !== '')
{
- $output .= $this->prev_tag_open.'<a '.$this->anchor_class.'href="'.$this->first_url.'">'.$this->prev_link.'</a>'.$this->prev_tag_close;
+ $output .= $this->prev_tag_open.'<a href="'.$this->first_url.$query_string.'"'.$attributes.$this->_attr_rel('prev').'>'
+ .$this->prev_link.'</a>'.$this->prev_tag_close;
}
else
{
- $i = ($i == $base_page) ? '' : $this->prefix.$i.$this->suffix;
- $output .= $this->prev_tag_open.'<a '.$this->anchor_class.'href="'.$this->base_url.$i.'">'.$this->prev_link.'</a>'.$this->prev_tag_close;
+ $append = ($i === $base_page) ? $query_string : $this->prefix.$i.$this->suffix;
+ $output .= $this->prev_tag_open.'<a href="'.$this->base_url.$append.'"'.$attributes.$this->_attr_rel('prev').'>'
+ .$this->prev_link.'</a>'.$this->prev_tag_close;
}
}
@@ -240,25 +513,28 @@ class CI_Pagination {
{
$i = ($this->use_page_numbers) ? $loop : ($loop * $this->per_page) - $this->per_page;
+ // Take the general parameters, and squeeze this pagination-page attr in there for JS fw's
+ $attributes = sprintf('%s %s="%d"', $this->_attributes, $this->data_page_attr, (int) $i);
+
if ($i >= $base_page)
{
- if ($this->cur_page == $loop)
+ if ($this->cur_page === $loop)
{
$output .= $this->cur_tag_open.$loop.$this->cur_tag_close; // Current page
}
else
{
- $n = ($i == $base_page) ? '' : $i;
-
- if ($n == '' && $this->first_url != '')
+ $n = ($i === $base_page) ? '' : $i;
+ if ($n === '' && ! empty($this->first_url))
{
- $output .= $this->num_tag_open.'<a '.$this->anchor_class.'href="'.$this->first_url.'">'.$loop.'</a>'.$this->num_tag_close;
+ $output .= $this->num_tag_open.'<a href="'.$this->first_url.$query_string.'"'.$attributes.$this->_attr_rel('start').'>'
+ .$loop.'</a>'.$this->num_tag_close;
}
else
{
- $n = ($n == '') ? '' : $this->prefix.$n.$this->suffix;
-
- $output .= $this->num_tag_open.'<a '.$this->anchor_class.'href="'.$this->base_url.$n.'">'.$loop.'</a>'.$this->num_tag_close;
+ $append = ($n === '') ? $query_string : $this->prefix.$n.$this->suffix;
+ $output .= $this->num_tag_open.'<a href="'.$this->base_url.$append.'"'.$attributes.$this->_attr_rel('start').'>'
+ .$loop.'</a>'.$this->num_tag_close;
}
}
}
@@ -270,7 +546,11 @@ class CI_Pagination {
{
$i = ($this->use_page_numbers) ? $this->cur_page + 1 : $this->cur_page * $this->per_page;
- $output .= $this->next_tag_open.'<a '.$this->anchor_class.'href="'.$this->base_url.$this->prefix.$i.$this->suffix.'">'.$this->next_link.'</a>'.$this->next_tag_close;
+ // Take the general parameters, and squeeze this pagination-page attr in there for JS fw's
+ $attributes = sprintf('%s %s="%d"', $this->_attributes, $this->data_page_attr, (int) $i);
+
+ $output .= $this->next_tag_open.'<a href="'.$this->base_url.$this->prefix.$i.$this->suffix.'"'.$attributes
+ .$this->_attr_rel('next').'>'.$this->next_link.'</a>'.$this->next_tag_close;
}
// Render the "Last" link
@@ -278,7 +558,11 @@ class CI_Pagination {
{
$i = ($this->use_page_numbers) ? $num_pages : ($num_pages * $this->per_page) - $this->per_page;
- $output .= $this->last_tag_open.'<a '.$this->anchor_class.'href="'.$this->base_url.$this->prefix.$i.$this->suffix.'">'.$this->last_link.'</a>'.$this->last_tag_close;
+ // Take the general parameters, and squeeze this pagination-page attr in there for JS fw's
+ $attributes = sprintf('%s %s="%d"', $this->_attributes, $this->data_page_attr, (int) $i);
+
+ $output .= $this->last_tag_open.'<a href="'.$this->base_url.$this->prefix.$i.$this->suffix.'"'.$attributes.'>'
+ .$this->last_link.'</a>'.$this->last_tag_close;
}
// Kill double slashes. Note: Sometimes we can end up with a double slash
@@ -289,6 +573,49 @@ class CI_Pagination {
return $this->full_tag_open.$output.$this->full_tag_close;
}
+ // --------------------------------------------------------------------
+
+ /**
+ * Parse attributes
+ *
+ * @param array $attributes
+ * @return void
+ */
+ protected function _parse_attributes($attributes)
+ {
+ isset($attributes['rel']) OR $attributes['rel'] = TRUE;
+ $this->_link_types = ($attributes['rel'])
+ ? array('start' => 'start', 'prev' => 'prev', 'next' => 'next')
+ : array();
+ unset($attributes['rel']);
+
+ $this->_attributes = '';
+ foreach ($attributes as $key => $value)
+ {
+ $this->_attributes .= ' '.$key.'="'.$value.'"';
+ }
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Add "rel" attribute
+ *
+ * @link http://www.w3.org/TR/html5/links.html#linkTypes
+ * @param string $type
+ * @return string
+ */
+ protected function _attr_rel($type)
+ {
+ if (isset($this->_link_types[$type]))
+ {
+ unset($this->_link_types[$type]);
+ return ' rel="'.$type.'"';
+ }
+
+ return '';
+ }
+
}
/* End of file Pagination.php */
diff --git a/system/libraries/Parser.php b/system/libraries/Parser.php
index d1b5b764b..faa94b7c9 100644
--- a/system/libraries/Parser.php
+++ b/system/libraries/Parser.php
@@ -1,4 +1,4 @@
-<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');
+<?php
/**
* CodeIgniter
*
@@ -24,6 +24,7 @@
* @since Version 1.0
* @filesource
*/
+defined('BASEPATH') OR exit('No direct script access allowed');
/**
* Parser Class
@@ -36,11 +37,41 @@
*/
class CI_Parser {
+ /**
+ * Left delimeter character for psuedo vars
+ *
+ * @var string
+ */
public $l_delim = '{';
+
+ /**
+ * Right delimeter character for psuedo vars
+ *
+ * @var string
+ */
public $r_delim = '}';
- public $object;
+
+ /**
+ * Reference to CodeIgniter instance
+ *
+ * @var object
+ */
protected $CI;
+ // --------------------------------------------------------------------
+
+ /**
+ * Class constructor
+ *
+ * @return void
+ */
+ public function __construct()
+ {
+ $this->CI =& get_instance();
+ }
+
+ // --------------------------------------------------------------------
+
/**
* Parse a template
*
@@ -54,7 +85,6 @@ class CI_Parser {
*/
public function parse($template, $data, $return = FALSE)
{
- $this->CI =& get_instance();
$template = $this->CI->load->view($template, $data, TRUE);
return $this->_parse($template, $data, $return);
@@ -93,24 +123,19 @@ class CI_Parser {
*/
protected function _parse($template, $data, $return = FALSE)
{
- if ($template == '')
+ if ($template === '')
{
return FALSE;
}
foreach ($data as $key => $val)
{
- if (is_array($val))
- {
- $template = $this->_parse_pair($key, $val, $template);
- }
- else
- {
- $template = $this->_parse_single($key, (string)$val, $template);
- }
+ $template = is_array($val)
+ ? $this->_parse_pair($key, $val, $template)
+ : $template = $this->_parse_single($key, (string) $val, $template);
}
- if ($return == FALSE)
+ if ($return === FALSE)
{
$this->CI->output->append_output($template);
}
@@ -173,14 +198,9 @@ class CI_Parser {
$temp = $match[1];
foreach ($row as $key => $val)
{
- if ( ! is_array($val))
- {
- $temp = $this->_parse_single($key, $val, $temp);
- }
- else
- {
- $temp = $this->_parse_pair($key, $val, $temp);
- }
+ $temp = is_array($val)
+ ? $this->_parse_pair($key, $val, $temp)
+ : $this->_parse_single($key, $val, $temp);
}
$str .= $temp;
diff --git a/system/libraries/Profiler.php b/system/libraries/Profiler.php
index 6320ab50d..1c97e3481 100644
--- a/system/libraries/Profiler.php
+++ b/system/libraries/Profiler.php
@@ -1,4 +1,4 @@
-<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');
+<?php
/**
* CodeIgniter
*
@@ -24,6 +24,7 @@
* @since Version 1.0
* @filesource
*/
+defined('BASEPATH') OR exit('No direct script access allowed');
/**
* CodeIgniter Profiler Class
@@ -42,23 +43,47 @@
*/
class CI_Profiler {
+ /**
+ * List of profiler sections available to show
+ *
+ * @var array
+ */
protected $_available_sections = array(
- 'benchmarks',
- 'get',
- 'memory_usage',
- 'post',
- 'uri_string',
- 'controller_info',
- 'queries',
- 'http_headers',
- 'session_data',
- 'config'
- );
+ 'benchmarks',
+ 'get',
+ 'memory_usage',
+ 'post',
+ 'uri_string',
+ 'controller_info',
+ 'queries',
+ 'http_headers',
+ 'session_data',
+ 'config'
+ );
+ /**
+ * Number of queries to show before making the additional queries togglable
+ *
+ * @var int
+ */
protected $_query_toggle_count = 25;
+ /**
+ * Reference to the CodeIgniter singleton
+ *
+ * @var object
+ */
protected $CI;
+ // --------------------------------------------------------------------
+
+ /**
+ * Class constructor
+ *
+ * Initialize Profiler
+ *
+ * @param array $config Parameters
+ */
public function __construct($config = array())
{
$this->CI =& get_instance();
@@ -89,11 +114,17 @@ class CI_Profiler {
*
* Sets the private _compile_* properties to enable/disable Profiler sections
*
- * @param mixed
+ * @param mixed $config
* @return void
*/
public function set_sections($config)
{
+ if (isset($config['query_toggle_count']))
+ {
+ $this->_query_toggle_count = (int) $config['query_toggle_count'];
+ unset($config['query_toggle_count']);
+ }
+
foreach ($config as $method => $enable)
{
if (in_array($method, $this->_available_sections))
@@ -162,11 +193,24 @@ class CI_Profiler {
$dbs = array();
// Let's determine which databases are currently connected to
- foreach (get_object_vars($this->CI) as $CI_object)
+ foreach (get_object_vars($this->CI) as $name => $cobject)
{
- if (is_object($CI_object) && is_subclass_of(get_class($CI_object), 'CI_DB'))
+ if (is_object($cobject))
{
- $dbs[] = $CI_object;
+ if ($cobject instanceof CI_DB)
+ {
+ $dbs[get_class($this->CI).':$'.$name] = $cobject;
+ }
+ elseif ($cobject instanceof CI_Model)
+ {
+ foreach (get_object_vars($cobject) as $mname => $mobject)
+ {
+ if ($mobject instanceof CI_DB)
+ {
+ $dbs[get_class($cobject).':$'.$mname] = $mobject;
+ }
+ }
+ }
}
}
@@ -191,13 +235,13 @@ class CI_Profiler {
$output = "\n\n";
$count = 0;
- foreach ($dbs as $db)
+ foreach ($dbs as $name => $db)
{
$hide_queries = (count($db->queries) > $this->_query_toggle_count) ? ' display:none' : '';
$show_hide_js = '(<span style="cursor: pointer;" onclick="var s=document.getElementById(\'ci_profiler_queries_db_'.$count.'\').style;s.display=s.display==\'none\'?\'\':\'none\';this.innerHTML=this.innerHTML==\''.$this->CI->lang->line('profiler_section_hide').'\'?\''.$this->CI->lang->line('profiler_section_show').'\':\''.$this->CI->lang->line('profiler_section_hide').'\';">'.$this->CI->lang->line('profiler_section_hide').'</span>)';
- if ($hide_queries != '')
+ if ($hide_queries !== '')
{
$show_hide_js = '(<span style="cursor: pointer;" onclick="var s=document.getElementById(\'ci_profiler_queries_db_'.$count.'\').style;s.display=s.display==\'none\'?\'\':\'none\';this.innerHTML=this.innerHTML==\''.$this->CI->lang->line('profiler_section_show').'\'?\''.$this->CI->lang->line('profiler_section_hide').'\':\''.$this->CI->lang->line('profiler_section_show').'\';">'.$this->CI->lang->line('profiler_section_show').'</span>)';
}
@@ -205,7 +249,7 @@ class CI_Profiler {
$output .= '<fieldset style="border:1px solid #0000FF;padding:6px 10px 10px 10px;margin:20px 0 20px 0;background-color:#eee;">'
."\n"
.'<legend style="color:#0000FF;">&nbsp;&nbsp;'.$this->CI->lang->line('profiler_database')
- .':&nbsp; '.$db->database.'&nbsp;&nbsp;&nbsp;'.$this->CI->lang->line('profiler_queries')
+ .':&nbsp; '.$db->database.' ('.$name.')&nbsp;&nbsp;&nbsp;'.$this->CI->lang->line('profiler_queries')
.': '.count($db->queries).'&nbsp;&nbsp;'.$show_hide_js."</legend>\n\n\n"
.'<table style="width:100%;'.$hide_queries.'" id="ci_profiler_queries_db_'.$count."\">\n";
@@ -293,7 +337,7 @@ class CI_Profiler {
."\n"
.'<legend style="color:#009900;">&nbsp;&nbsp;'.$this->CI->lang->line('profiler_post_data')."&nbsp;&nbsp;</legend>\n";
- if (count($_POST) == 0)
+ if (count($_POST) === 0)
{
$output .= '<div style="color:#009900;font-weight:normal;padding:4px 0 4px 0;">'.$this->CI->lang->line('profiler_no_post').'</div>';
}
@@ -343,7 +387,7 @@ class CI_Profiler {
."\n"
.'<legend style="color:#000;">&nbsp;&nbsp;'.$this->CI->lang->line('profiler_uri_string')."&nbsp;&nbsp;</legend>\n"
.'<div style="color:#000;font-weight:normal;padding:4px 0 4px 0;">'
- .($this->CI->uri->uri_string == '' ? $this->CI->lang->line('profiler_no_uri') : $this->CI->uri->uri_string)
+ .($this->CI->uri->uri_string === '' ? $this->CI->lang->line('profiler_no_uri') : $this->CI->uri->uri_string)
.'</div></fieldset>';
}
@@ -380,7 +424,7 @@ class CI_Profiler {
."\n"
.'<legend style="color:#5a0099;">&nbsp;&nbsp;'.$this->CI->lang->line('profiler_memory_usage')."&nbsp;&nbsp;</legend>\n"
.'<div style="color:#5a0099;font-weight:normal;padding:4px 0 4px 0;">'
- .((function_exists('memory_get_usage') && ($usage = memory_get_usage()) != '') ? number_format($usage).' bytes' : $this->CI->lang->line('profiler_no_memory'))
+ .(($usage = memory_get_usage()) != '' ? number_format($usage).' bytes' : $this->CI->lang->line('profiler_no_memory'))
.'</div></fieldset>';
}
@@ -505,6 +549,7 @@ class CI_Profiler {
return $output.'</div>';
}
+
}
/* End of file Profiler.php */
diff --git a/system/libraries/Session.php b/system/libraries/Session.php
deleted file mode 100644
index 3515764ce..000000000
--- a/system/libraries/Session.php
+++ /dev/null
@@ -1,819 +0,0 @@
-<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');
-/**
- * CodeIgniter
- *
- * An open source application development framework for PHP 5.2.4 or newer
- *
- * NOTICE OF LICENSE
- *
- * Licensed under the Open Software License version 3.0
- *
- * This source file is subject to the Open Software License (OSL 3.0) that is
- * bundled with this package in the files license.txt / license.rst. It is
- * also available through the world wide web at this URL:
- * http://opensource.org/licenses/OSL-3.0
- * If you did not receive a copy of the license and are unable to obtain it
- * through the world wide web, please send an email to
- * licensing@ellislab.com so we can send you a copy immediately.
- *
- * @package CodeIgniter
- * @author EllisLab Dev Team
- * @copyright Copyright (c) 2008 - 2012, EllisLab, Inc. (http://ellislab.com/)
- * @license http://opensource.org/licenses/OSL-3.0 Open Software License (OSL 3.0)
- * @link http://codeigniter.com
- * @since Version 1.0
- * @filesource
- */
-
-/**
- * Session Class
- *
- * @package CodeIgniter
- * @subpackage Libraries
- * @category Sessions
- * @author EllisLab Dev Team
- * @link http://codeigniter.com/user_guide/libraries/sessions.html
- */
-class CI_Session {
-
- public $sess_encrypt_cookie = FALSE;
- public $sess_use_database = FALSE;
- public $sess_table_name = '';
- public $sess_expiration = 7200;
- public $sess_expire_on_close = FALSE;
- public $sess_match_ip = FALSE;
- public $sess_match_useragent = TRUE;
- public $sess_cookie_name = 'ci_session';
- public $cookie_prefix = '';
- public $cookie_path = '';
- public $cookie_domain = '';
- public $cookie_secure = FALSE;
- public $cookie_httponly = FALSE;
- public $sess_time_to_update = 300;
- public $encryption_key = '';
- public $flashdata_key = 'flash';
- public $time_reference = 'time';
- public $gc_probability = 5;
- public $userdata = array();
- public $CI;
- public $now;
-
- /**
- * Session Constructor
- *
- * The constructor runs the session routines automatically
- * whenever the class is instantiated.
- */
- public function __construct($params = array())
- {
- log_message('debug', 'Session Class Initialized');
-
- // Set the super object to a local variable for use throughout the class
- $this->CI =& get_instance();
-
- // Set all the session preferences, which can either be set
- // manually via the $params array above or via the config file
- foreach (array('sess_encrypt_cookie', 'sess_use_database', 'sess_table_name', 'sess_expiration', 'sess_expire_on_close', 'sess_match_ip', 'sess_match_useragent', 'sess_cookie_name', 'cookie_path', 'cookie_domain', 'cookie_secure', 'cookie_httponly', 'sess_time_to_update', 'time_reference', 'cookie_prefix', 'encryption_key') as $key)
- {
- $this->$key = (isset($params[$key])) ? $params[$key] : $this->CI->config->item($key);
- }
-
- if ($this->encryption_key == '')
- {
- show_error('In order to use the Session class you are required to set an encryption key in your config file.');
- }
-
- // Load the string helper so we can use the strip_slashes() function
- $this->CI->load->helper('string');
-
- // Do we need encryption? If so, load the encryption class
- if ($this->sess_encrypt_cookie == TRUE)
- {
- $this->CI->load->library('encrypt');
- }
-
- // Are we using a database? If so, load it
- if ($this->sess_use_database === TRUE && $this->sess_table_name != '')
- {
- $this->CI->load->database();
- }
-
- // Set the "now" time. Can either be GMT or server time, based on the
- // config prefs. We use this to set the "last activity" time
- $this->now = $this->_get_time();
-
- // Set the session length. If the session expiration is
- // set to zero we'll set the expiration two years from now.
- if ($this->sess_expiration == 0)
- {
- $this->sess_expiration = (60*60*24*365*2);
- }
-
- // Set the cookie name
- $this->sess_cookie_name = $this->cookie_prefix.$this->sess_cookie_name;
-
- // Run the Session routine. If a session doesn't exist we'll
- // create a new one. If it does, we'll update it.
- if ( ! $this->sess_read())
- {
- $this->sess_create();
- }
- else
- {
- $this->sess_update();
- }
-
- // Delete 'old' flashdata (from last request)
- $this->_flashdata_sweep();
-
- // Mark all new flashdata as old (data will be deleted before next request)
- $this->_flashdata_mark();
-
- // Delete expired sessions if necessary
- $this->_sess_gc();
-
- log_message('debug', 'Session routines successfully run');
- }
-
- // --------------------------------------------------------------------
-
- /**
- * Fetch the current session data if it exists
- *
- * @return bool
- */
- public function sess_read()
- {
- // Fetch the cookie
- $session = $this->CI->input->cookie($this->sess_cookie_name);
-
- // No cookie? Goodbye cruel world!...
- if ($session === FALSE)
- {
- log_message('debug', 'A session cookie was not found.');
- return FALSE;
- }
-
- // Decrypt the cookie data
- if ($this->sess_encrypt_cookie == TRUE)
- {
- $session = $this->CI->encrypt->decode($session);
- }
- else
- {
- // encryption was not used, so we need to check the md5 hash
- $hash = substr($session, strlen($session)-32); // get last 32 chars
- $session = substr($session, 0, strlen($session)-32);
-
- // Does the md5 hash match? This is to prevent manipulation of session data in userspace
- if ($hash !== md5($session.$this->encryption_key))
- {
- log_message('error', 'The session cookie data did not match what was expected. This could be a possible hacking attempt.');
- $this->sess_destroy();
- return FALSE;
- }
- }
-
- // Unserialize the session array
- $session = $this->_unserialize($session);
-
- // Is the session data we unserialized an array with the correct format?
- if ( ! is_array($session) OR ! isset($session['session_id'], $session['ip_address'], $session['user_agent'], $session['last_activity']))
- {
- $this->sess_destroy();
- return FALSE;
- }
-
- // Is the session current?
- if (($session['last_activity'] + $this->sess_expiration) < $this->now)
- {
- $this->sess_destroy();
- return FALSE;
- }
-
- // Does the IP match?
- if ($this->sess_match_ip == TRUE && $session['ip_address'] !== $this->CI->input->ip_address())
- {
- $this->sess_destroy();
- return FALSE;
- }
-
- // Does the User Agent Match?
- if ($this->sess_match_useragent == TRUE && trim($session['user_agent']) !== trim(substr($this->CI->input->user_agent(), 0, 120)))
- {
- $this->sess_destroy();
- return FALSE;
- }
-
- // Is there a corresponding session in the DB?
- if ($this->sess_use_database === TRUE)
- {
- $this->CI->db->where('session_id', $session['session_id']);
-
- if ($this->sess_match_ip == TRUE)
- {
- $this->CI->db->where('ip_address', $session['ip_address']);
- }
-
- if ($this->sess_match_useragent == TRUE)
- {
- $this->CI->db->where('user_agent', $session['user_agent']);
- }
-
- $query = $this->CI->db->limit(1)->get($this->sess_table_name);
-
- // No result? Kill it!
- if ($query->num_rows() === 0)
- {
- $this->sess_destroy();
- return FALSE;
- }
-
- // Is there custom data? If so, add it to the main session array
- $row = $query->row();
- if (isset($row->user_data) && $row->user_data != '')
- {
- $custom_data = $this->_unserialize($row->user_data);
-
- if (is_array($custom_data))
- {
- foreach ($custom_data as $key => $val)
- {
- $session[$key] = $val;
- }
- }
- }
- }
-
- // Session is valid!
- $this->userdata = $session;
- unset($session);
-
- return TRUE;
- }
-
- // --------------------------------------------------------------------
-
- /**
- * Write the session data
- *
- * @return void
- */
- public function sess_write()
- {
- // Are we saving custom data to the DB? If not, all we do is update the cookie
- if ($this->sess_use_database === FALSE)
- {
- $this->_set_cookie();
- return;
- }
-
- // set the custom userdata, the session data we will set in a second
- $custom_userdata = $this->userdata;
- $cookie_userdata = array();
-
- // Before continuing, we need to determine if there is any custom data to deal with.
- // Let's determine this by removing the default indexes to see if there's anything left in the array
- // and set the session data while we're at it
- foreach (array('session_id','ip_address','user_agent','last_activity') as $val)
- {
- unset($custom_userdata[$val]);
- $cookie_userdata[$val] = $this->userdata[$val];
- }
-
- // Did we find any custom data? If not, we turn the empty array into a string
- // since there's no reason to serialize and store an empty array in the DB
- if (count($custom_userdata) === 0)
- {
- $custom_userdata = '';
- }
- else
- {
- // Serialize the custom data array so we can store it
- $custom_userdata = $this->_serialize($custom_userdata);
- }
-
- // Run the update query
- $this->CI->db->where('session_id', $this->userdata['session_id']);
- $this->CI->db->update($this->sess_table_name, array('last_activity' => $this->userdata['last_activity'], 'user_data' => $custom_userdata));
-
- // Write the cookie. Notice that we manually pass the cookie data array to the
- // _set_cookie() function. Normally that function will store $this->userdata, but
- // in this case that array contains custom data, which we do not want in the cookie.
- $this->_set_cookie($cookie_userdata);
- }
-
- // --------------------------------------------------------------------
-
- /**
- * Create a new session
- *
- * @return void
- */
- public function sess_create()
- {
- $sessid = '';
- do
- {
- $sessid .= mt_rand(0, mt_getrandmax());
- }
- while (strlen($sessid) < 32);
-
- // To make the session ID even more secure we'll combine it with the user's IP
- $sessid .= $this->CI->input->ip_address();
-
- $this->userdata = array(
- 'session_id' => md5(uniqid($sessid, TRUE)),
- 'ip_address' => $this->CI->input->ip_address(),
- 'user_agent' => substr($this->CI->input->user_agent(), 0, 120),
- 'last_activity' => $this->now,
- 'user_data' => ''
- );
-
- // Save the data to the DB if needed
- if ($this->sess_use_database === TRUE)
- {
- $this->CI->db->query($this->CI->db->insert_string($this->sess_table_name, $this->userdata));
- }
-
- // Write the cookie
- $this->_set_cookie();
- }
-
- // --------------------------------------------------------------------
-
- /**
- * Update an existing session
- *
- * @return void
- */
- public function sess_update()
- {
- // We only update the session every five minutes by default
- if (($this->userdata['last_activity'] + $this->sess_time_to_update) >= $this->now)
- {
- return;
- }
-
- // _set_cookie() will handle this for us if we aren't using database sessions
- // by pushing all userdata to the cookie.
- $cookie_data = NULL;
-
- /* Changing the session ID during an AJAX call causes problems,
- * so we'll only update our last_activity
- */
- if ($this->CI->input->is_ajax_request())
- {
- $this->userdata['last_activity'] = $this->now;
-
- // Update the session ID and last_activity field in the DB if needed
- if ($this->sess_use_database === TRUE)
- {
- // set cookie explicitly to only have our session data
- $cookie_data = array();
- foreach (array('session_id','ip_address','user_agent','last_activity') as $val)
- {
- $cookie_data[$val] = $this->userdata[$val];
- }
-
- $this->CI->db->query($this->CI->db->update_string($this->sess_table_name,
- array('last_activity' => $this->userdata['last_activity']),
- array('session_id' => $this->userdata['session_id'])));
- }
-
- return $this->_set_cookie($cookie_data);
- }
-
- // Save the old session id so we know which record to
- // update in the database if we need it
- $old_sessid = $this->userdata['session_id'];
- $new_sessid = '';
- do
- {
- $new_sessid .= mt_rand(0, mt_getrandmax());
- }
- while (strlen($new_sessid) < 32);
-
- // To make the session ID even more secure we'll combine it with the user's IP
- $new_sessid .= $this->CI->input->ip_address();
-
- // Turn it into a hash and update the session data array
- $this->userdata['session_id'] = $new_sessid = md5(uniqid($new_sessid, TRUE));
- $this->userdata['last_activity'] = $this->now;
-
- // Update the session ID and last_activity field in the DB if needed
- if ($this->sess_use_database === TRUE)
- {
- // set cookie explicitly to only have our session data
- $cookie_data = array();
- foreach (array('session_id','ip_address','user_agent','last_activity') as $val)
- {
- $cookie_data[$val] = $this->userdata[$val];
- }
-
- $this->CI->db->query($this->CI->db->update_string($this->sess_table_name, array('last_activity' => $this->now, 'session_id' => $new_sessid), array('session_id' => $old_sessid)));
- }
-
- // Write the cookie
- $this->_set_cookie($cookie_data);
- }
-
- // --------------------------------------------------------------------
-
- /**
- * Destroy the current session
- *
- * @return void
- */
- public function sess_destroy()
- {
- // Kill the session DB row
- if ($this->sess_use_database === TRUE && isset($this->userdata['session_id']))
- {
- $this->CI->db->where('session_id', $this->userdata['session_id']);
- $this->CI->db->delete($this->sess_table_name);
- }
-
- // Kill the cookie
- setcookie(
- $this->sess_cookie_name,
- addslashes(serialize(array())),
- ($this->now - 31500000),
- $this->cookie_path,
- $this->cookie_domain,
- 0
- );
- }
-
- // --------------------------------------------------------------------
-
- /**
- * Fetch a specific item from the session array
- *
- * @param string
- * @return string
- */
- public function userdata($item)
- {
- return isset($this->userdata[$item]) ? $this->userdata[$item] : FALSE;
- }
-
- // --------------------------------------------------------------------
-
- /**
- * Fetch all session data
- *
- * @return array
- */
- public function all_userdata()
- {
- return $this->userdata;
- }
-
- // --------------------------------------------------------------------------
-
- /**
- * Fetch all flashdata
- *
- * @return array
- */
- public function all_flashdata()
- {
- $out = array();
-
- // loop through all userdata
- foreach ($this->all_userdata() as $key => $val)
- {
- // if it contains flashdata, add it
- if (strpos($key, 'flash:old:') !== FALSE)
- {
- $out[$key] = $val;
- }
- }
- return $out;
- }
-
- // --------------------------------------------------------------------
-
- /**
- * Add or change data in the "userdata" array
- *
- * @param mixed
- * @param string
- * @return void
- */
- public function set_userdata($newdata = array(), $newval = '')
- {
- if (is_string($newdata))
- {
- $newdata = array($newdata => $newval);
- }
-
- if (count($newdata) > 0)
- {
- foreach ($newdata as $key => $val)
- {
- $this->userdata[$key] = $val;
- }
- }
-
- $this->sess_write();
- }
-
- // --------------------------------------------------------------------
-
- /**
- * Delete a session variable from the "userdata" array
- *
- * @return void
- */
- public function unset_userdata($newdata = array())
- {
- if (is_string($newdata))
- {
- $newdata = array($newdata => '');
- }
-
- if (count($newdata) > 0)
- {
- foreach ($newdata as $key => $val)
- {
- unset($this->userdata[$key]);
- }
- }
-
- $this->sess_write();
- }
-
- // ------------------------------------------------------------------------
-
- /**
- * Add or change flashdata, only available
- * until the next request
- *
- * @param mixed
- * @param string
- * @return void
- */
- public function set_flashdata($newdata = array(), $newval = '')
- {
- if (is_string($newdata))
- {
- $newdata = array($newdata => $newval);
- }
-
- if (count($newdata) > 0)
- {
- foreach ($newdata as $key => $val)
- {
- $this->set_userdata($this->flashdata_key.':new:'.$key, $val);
- }
- }
- }
-
- // ------------------------------------------------------------------------
-
- /**
- * Keeps existing flashdata available to next request.
- *
- * @param string
- * @return void
- */
- public function keep_flashdata($key)
- {
- // 'old' flashdata gets removed. Here we mark all
- // flashdata as 'new' to preserve it from _flashdata_sweep()
- // Note the function will return FALSE if the $key
- // provided cannot be found
- $value = $this->userdata($this->flashdata_key.':old:'.$key);
-
- $this->set_userdata($this->flashdata_key.':new:'.$key, $value);
- }
-
- // ------------------------------------------------------------------------
-
- /**
- * Fetch a specific flashdata item from the session array
- *
- * @param string
- * @return string
- */
- public function flashdata($key)
- {
- return $this->userdata($this->flashdata_key.':old:'.$key);
- }
-
- // ------------------------------------------------------------------------
-
- /**
- * Identifies flashdata as 'old' for removal
- * when _flashdata_sweep() runs.
- *
- * @return void
- */
- protected function _flashdata_mark()
- {
- $userdata = $this->all_userdata();
- foreach ($userdata as $name => $value)
- {
- $parts = explode(':new:', $name);
- if (is_array($parts) && count($parts) === 2)
- {
- $this->set_userdata($this->flashdata_key.':old:'.$parts[1], $value);
- $this->unset_userdata($name);
- }
- }
- }
-
- // ------------------------------------------------------------------------
-
- /**
- * Removes all flashdata marked as 'old'
- *
- * @return void
- */
- protected function _flashdata_sweep()
- {
- $userdata = $this->all_userdata();
- foreach ($userdata as $key => $value)
- {
- if (strpos($key, ':old:'))
- {
- $this->unset_userdata($key);
- }
- }
-
- }
-
- // --------------------------------------------------------------------
-
- /**
- * Get the "now" time
- *
- * @return string
- */
- protected function _get_time()
- {
- return (strtolower($this->time_reference) === 'gmt')
- ? mktime(gmdate('H'), gmdate('i'), gmdate('s'), gmdate('m'), gmdate('d'), gmdate('Y'))
- : time();
- }
-
- // --------------------------------------------------------------------
-
- /**
- * Write the session cookie
- *
- * @return void
- */
- protected function _set_cookie($cookie_data = NULL)
- {
- if (is_null($cookie_data))
- {
- $cookie_data = $this->userdata;
- }
-
- // Serialize the userdata for the cookie
- $cookie_data = $this->_serialize($cookie_data);
-
- if ($this->sess_encrypt_cookie == TRUE)
- {
- $cookie_data = $this->CI->encrypt->encode($cookie_data);
- }
- else
- {
- // if encryption is not used, we provide an md5 hash to prevent userside tampering
- $cookie_data = $cookie_data.md5($cookie_data.$this->encryption_key);
- }
-
- $expire = ($this->sess_expire_on_close === TRUE) ? 0 : $this->sess_expiration + time();
-
- // Set the cookie
- setcookie(
- $this->sess_cookie_name,
- $cookie_data,
- $expire,
- $this->cookie_path,
- $this->cookie_domain,
- $this->cookie_secure,
- $this->cookie_httponly
- );
- }
-
- // --------------------------------------------------------------------
-
- /**
- * Serialize an array
- *
- * This function first converts any slashes found in the array to a temporary
- * marker, so when it gets unserialized the slashes will be preserved
- *
- * @param array
- * @return string
- */
- protected function _serialize($data)
- {
- if (is_array($data))
- {
- array_walk_recursive($data, array(&$this, '_escape_slashes'));
- }
- elseif (is_string($data))
- {
- $data = str_replace('\\', '{{slash}}', $data);
- }
- return serialize($data);
- }
-
- /**
- * Escape slashes
- *
- * This function converts any slashes found into a temporary marker
- *
- * @param string
- * @param string
- * @return void
- */
- protected function _escape_slashes(&$val, $key)
- {
- if (is_string($val))
- {
- $val = str_replace('\\', '{{slash}}', $val);
- }
- }
-
- // --------------------------------------------------------------------
-
- /**
- * Unserialize
- *
- * This function unserializes a data string, then converts any
- * temporary slash markers back to actual slashes
- *
- * @param array
- * @return string
- */
- protected function _unserialize($data)
- {
- $data = @unserialize(strip_slashes(trim($data)));
-
- if (is_array($data))
- {
- array_walk_recursive($data, array(&$this, '_unescape_slashes'));
- return $data;
- }
-
- return is_string($data) ? str_replace('{{slash}}', '\\', $data) : $data;
- }
-
- // --------------------------------------------------------------------
-
- /**
- * Unescape slashes
- *
- * This function converts any slash markers back into actual slashes
- *
- * @param string
- * @param string
- * @return void
- */
- protected function _unescape_slashes(&$val, $key)
- {
- if (is_string($val))
- {
- $val= str_replace('{{slash}}', '\\', $val);
- }
- }
-
- // --------------------------------------------------------------------
-
- /**
- * Garbage collection
- *
- * This deletes expired session rows from database
- * if the probability percentage is met
- *
- * @return void
- */
- protected function _sess_gc()
- {
- if ($this->sess_use_database != TRUE)
- {
- return;
- }
-
- srand(time());
- if ((rand() % 100) < $this->gc_probability)
- {
- $expire = $this->now - $this->sess_expiration;
-
- $this->CI->db->where('last_activity < '.$expire);
- $this->CI->db->delete($this->sess_table_name);
-
- log_message('debug', 'Session garbage collection performed.');
- }
- }
-
-}
-
-/* End of file Session.php */
-/* Location: ./system/libraries/Session.php */ \ No newline at end of file
diff --git a/system/libraries/Session/Session.php b/system/libraries/Session/Session.php
new file mode 100644
index 000000000..85a483592
--- /dev/null
+++ b/system/libraries/Session/Session.php
@@ -0,0 +1,753 @@
+<?php
+/**
+ * CodeIgniter
+ *
+ * An open source application development framework for PHP 5.2.4 or newer
+ *
+ * NOTICE OF LICENSE
+ *
+ * Licensed under the Open Software License version 3.0
+ *
+ * This source file is subject to the Open Software License (OSL 3.0) that is
+ * bundled with this package in the files license.txt / license.rst. It is
+ * also available through the world wide web at this URL:
+ * http://opensource.org/licenses/OSL-3.0
+ * If you did not receive a copy of the license and are unable to obtain it
+ * through the world wide web, please send an email to
+ * licensing@ellislab.com so we can send you a copy immediately.
+ *
+ * @package CodeIgniter
+ * @author EllisLab Dev Team
+ * @copyright Copyright (c) 2008 - 2012, EllisLab, Inc. (http://ellislab.com/)
+ * @license http://opensource.org/licenses/OSL-3.0 Open Software License (OSL 3.0)
+ * @link http://codeigniter.com
+ * @since Version 2.0
+ * @filesource
+ */
+defined('BASEPATH') OR exit('No direct script access allowed');
+
+/**
+ * CodeIgniter Session Class
+ *
+ * The user interface defined by EllisLabs, now with puggable drivers to manage different storage mechanisms.
+ * By default, the cookie session driver will load, but the 'sess_driver' config/param item (see above) can be
+ * used to specify the 'native' driver, or any other you might create.
+ * Once loaded, this driver setup is a drop-in replacement for the former CI_Session library, taking its place as the
+ * 'session' member of the global controller framework (e.g.: $CI->session or $this->session).
+ * In keeping with the CI_Driver methodology, multiple drivers may be loaded, although this might be a bit confusing.
+ * The CI_Session library class keeps track of the most recently loaded driver as "current" to call for driver methods.
+ * Ideally, one driver is loaded and all calls go directly through the main library interface. However, any methods
+ * called through the specific driver will switch the "current" driver to itself before invoking the library method
+ * (which will then call back into the driver for low-level operations). So, alternation between two drivers can be
+ * achieved by specifying which driver to use for each call (e.g.: $this->session->native->set_userdata('foo', 'bar');
+ * $this->session->cookie->userdata('foo'); $this->session->native->unset_userdata('foo');). Notice in the previous
+ * example that the _native_ userdata value 'foo' would be set to 'bar', which would NOT be returned by the call for
+ * the _cookie_ userdata 'foo', nor would the _cookie_ value be unset by the call to unset the _native_ 'foo' value.
+ *
+ * @package CodeIgniter
+ * @subpackage Libraries
+ * @category Sessions
+ * @author EllisLab Dev Team
+ * @link http://codeigniter.com/user_guide/libraries/sessions.html
+ */
+class CI_Session extends CI_Driver_Library {
+
+ /**
+ * Initialization parameters
+ *
+ * @var array
+ */
+ public $params = array();
+
+ /**
+ * Current driver in use
+ *
+ * @var string
+ */
+ protected $current = NULL;
+
+ /**
+ * User data
+ *
+ * @var array
+ */
+ protected $userdata = array();
+
+ // ------------------------------------------------------------------------
+
+ const FLASHDATA_KEY = 'flash';
+ const FLASHDATA_NEW = ':new:';
+ const FLASHDATA_OLD = ':old:';
+ const FLASHDATA_EXP = ':exp:';
+ const EXPIRATION_KEY = '__expirations';
+ const TEMP_EXP_DEF = 300;
+
+ // ------------------------------------------------------------------------
+
+ /**
+ * CI_Session constructor
+ *
+ * The constructor loads the configured driver ('sess_driver' in config.php or as a parameter), running
+ * routines in its constructor, and manages flashdata aging.
+ *
+ * @param array Configuration parameters
+ * @return void
+ */
+ public function __construct(array $params = array())
+ {
+ $CI =& get_instance();
+
+ // No sessions under CLI
+ if ($CI->input->is_cli_request())
+ {
+ return;
+ }
+
+ log_message('debug', 'CI_Session Class Initialized');
+
+ // Get valid drivers list
+ $this->valid_drivers = array(
+ 'native',
+ 'cookie'
+ );
+ $key = 'sess_valid_drivers';
+ $drivers = isset($params[$key]) ? $params[$key] : $CI->config->item($key);
+ if ($drivers)
+ {
+ // Add driver names to valid list
+ foreach ((array) $drivers as $driver)
+ {
+ if ( ! in_array(strtolower($driver), array_map('strtolower', $this->valid_drivers)))
+ {
+ $this->valid_drivers[] = $driver;
+ }
+ }
+ }
+
+ // Get driver to load
+ $key = 'sess_driver';
+ $driver = isset($params[$key]) ? $params[$key] : $CI->config->item($key);
+ if ( ! $driver)
+ {
+ $driver = 'cookie';
+ }
+
+ if ( ! in_array(strtolower($driver), array_map('strtolower', $this->valid_drivers)))
+ {
+ $this->valid_drivers[] = $driver;
+ }
+
+ // Save a copy of parameters in case drivers need access
+ $this->params = $params;
+
+ // Load driver and get array reference
+ $this->load_driver($driver);
+
+ // Delete 'old' flashdata (from last request)
+ $this->_flashdata_sweep();
+
+ // Mark all new flashdata as old (data will be deleted before next request)
+ $this->_flashdata_mark();
+
+ // Delete expired tempdata
+ $this->_tempdata_sweep();
+
+ log_message('debug', 'CI_Session routines successfully run');
+ }
+
+ // ------------------------------------------------------------------------
+
+ /**
+ * Loads session storage driver
+ *
+ * @param string Driver classname
+ * @return object Loaded driver object
+ */
+ public function load_driver($driver)
+ {
+ // Save reference to most recently loaded driver as library default and sync userdata
+ $this->current = parent::load_driver($driver);
+ $this->userdata =& $this->current->get_userdata();
+ return $this->current;
+ }
+
+ // ------------------------------------------------------------------------
+
+ /**
+ * Select default session storage driver
+ *
+ * @param string Driver name
+ * @return void
+ */
+ public function select_driver($driver)
+ {
+ // Validate driver name
+ $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
+ if (isset($this->$child))
+ {
+ // See if driver is already current
+ if ($this->$child !== $this->current)
+ {
+ // Make driver current and sync userdata
+ $this->current = $this->$child;
+ $this->userdata =& $this->current->get_userdata();
+ }
+ }
+ else
+ {
+ // Load new driver
+ $this->load_driver($child);
+ }
+ }
+ }
+
+ // ------------------------------------------------------------------------
+
+ /**
+ * Destroy the current session
+ *
+ * @return void
+ */
+ public function sess_destroy()
+ {
+ // Just call destroy on driver
+ $this->current->sess_destroy();
+ }
+
+ // ------------------------------------------------------------------------
+
+ /**
+ * Regenerate the current session
+ *
+ * @param bool Destroy session data flag (default: false)
+ * @return void
+ */
+ public function sess_regenerate($destroy = FALSE)
+ {
+ // Call regenerate on driver and resync userdata
+ $this->current->sess_regenerate($destroy);
+ $this->userdata =& $this->current->get_userdata();
+ }
+
+ // ------------------------------------------------------------------------
+
+ /**
+ * Fetch a specific item from the session array
+ *
+ * @param string Item key
+ * @return string Item value or NULL if not found
+ */
+ public function userdata($item)
+ {
+ return isset($this->userdata[$item]) ? $this->userdata[$item] : NULL;
+ }
+
+ // ------------------------------------------------------------------------
+
+ /**
+ * Fetch all session data
+ *
+ * @return array User data array
+ */
+ public function all_userdata()
+ {
+ return isset($this->userdata) ? $this->userdata : NULL;
+ }
+
+ // ------------------------------------------------------------------------
+
+ /**
+ * Fetch all flashdata
+ *
+ * @return array Flash data array
+ */
+ public function all_flashdata()
+ {
+ $out = array();
+
+ // loop through all userdata
+ foreach ($this->all_userdata() as $key => $val)
+ {
+ // if it contains flashdata, add it
+ if (strpos($key, self::FLASHDATA_KEY.self::FLASHDATA_OLD) !== FALSE)
+ {
+ $key = str_replace(self::FLASHDATA_KEY.self::FLASHDATA_OLD, '', $key);
+ $out[$key] = $val;
+ }
+ }
+ return $out;
+ }
+
+ // ------------------------------------------------------------------------
+
+ /**
+ * Add or change data in the "userdata" array
+ *
+ * @param mixed Item name or array of items
+ * @param string Item value or empty string
+ * @return void
+ */
+ public function set_userdata($newdata = array(), $newval = '')
+ {
+ // Wrap params as array if singular
+ if (is_string($newdata))
+ {
+ $newdata = array($newdata => $newval);
+ }
+
+ // Set each name/value pair
+ if (count($newdata) > 0)
+ {
+ foreach ($newdata as $key => $val)
+ {
+ $this->userdata[$key] = $val;
+ }
+ }
+
+ // Tell driver data changed
+ $this->current->sess_save();
+ }
+
+ // ------------------------------------------------------------------------
+
+ /**
+ * Delete a session variable from the "userdata" array
+ *
+ * @param mixed Item name or array of item names
+ * @return void
+ */
+ public function unset_userdata($newdata = array())
+ {
+ // Wrap single name as array
+ if (is_string($newdata))
+ {
+ $newdata = array($newdata => '');
+ }
+
+ // Unset each item name
+ if (count($newdata) > 0)
+ {
+ foreach (array_keys($newdata) as $key)
+ {
+ unset($this->userdata[$key]);
+ }
+ }
+
+ // Tell driver data changed
+ $this->current->sess_save();
+ }
+
+ // ------------------------------------------------------------------------
+
+ /**
+ * Determine if an item exists
+ *
+ * @param string Item name
+ * @return bool
+ */
+ public function has_userdata($item)
+ {
+ return isset($this->userdata[$item]);
+ }
+
+ // ------------------------------------------------------------------------
+
+ /**
+ * Add or change flashdata, only available until the next request
+ *
+ * @param mixed Item name or array of items
+ * @param string Item value or empty string
+ * @return void
+ */
+ public function set_flashdata($newdata = array(), $newval = '')
+ {
+ // Wrap item as array if singular
+ if (is_string($newdata))
+ {
+ $newdata = array($newdata => $newval);
+ }
+
+ // Prepend each key name and set value
+ if (count($newdata) > 0)
+ {
+ foreach ($newdata as $key => $val)
+ {
+ $flashdata_key = self::FLASHDATA_KEY.self::FLASHDATA_NEW.$key;
+ $this->set_userdata($flashdata_key, $val);
+ }
+ }
+ }
+
+ // ------------------------------------------------------------------------
+
+ /**
+ * Keeps existing flashdata available to next request.
+ *
+ * @param mixed Item key(s)
+ * @return void
+ */
+ public function keep_flashdata($key)
+ {
+
+ if (is_array($key))
+ {
+ foreach ($key as $k)
+ {
+ $this->keep_flashdata($k);
+ }
+
+ return;
+ }
+
+ // 'old' flashdata gets removed. Here we mark all flashdata as 'new' to preserve it from _flashdata_sweep()
+ // Note the function will return NULL if the $key provided cannot be found
+ $old_flashdata_key = self::FLASHDATA_KEY.self::FLASHDATA_OLD.$key;
+ $value = $this->userdata($old_flashdata_key);
+
+ $new_flashdata_key = self::FLASHDATA_KEY.self::FLASHDATA_NEW.$key;
+ $this->set_userdata($new_flashdata_key, $value);
+ }
+
+ // ------------------------------------------------------------------------
+
+ /**
+ * Fetch a specific flashdata item from the session array
+ *
+ * @param string Item key
+ * @return string
+ */
+ public function flashdata($key)
+ {
+ // Prepend key and retrieve value
+ $flashdata_key = self::FLASHDATA_KEY.self::FLASHDATA_OLD.$key;
+ return $this->userdata($flashdata_key);
+ }
+
+ // ------------------------------------------------------------------------
+
+ /**
+ * Add or change tempdata, only available until expiration
+ *
+ * @param mixed Item name or array of items
+ * @param string Item value or empty string
+ * @param int Item lifetime in seconds or 0 for default
+ * @return void
+ */
+ public function set_tempdata($newdata = array(), $newval = '', $expire = 0)
+ {
+ // Set expiration time
+ $expire = time() + ($expire ? $expire : self::TEMP_EXP_DEF);
+
+ // Wrap item as array if singular
+ if (is_string($newdata))
+ {
+ $newdata = array($newdata => $newval);
+ }
+
+ // Get or create expiration list
+ $expirations = $this->userdata(self::EXPIRATION_KEY);
+ if ( ! $expirations)
+ {
+ $expirations = array();
+ }
+
+ // Prepend each key name and set value
+ if (count($newdata) > 0)
+ {
+ foreach ($newdata as $key => $val)
+ {
+ $tempdata_key = self::FLASHDATA_KEY.self::FLASHDATA_EXP.$key;
+ $expirations[$tempdata_key] = $expire;
+ $this->set_userdata($tempdata_key, $val);
+ }
+ }
+
+ // Update expiration list
+ $this->set_userdata(self::EXPIRATION_KEY, $expirations);
+ }
+
+ // ------------------------------------------------------------------------
+
+ /**
+ * Delete a temporary session variable from the "userdata" array
+ *
+ * @param mixed Item name or array of item names
+ * @return void
+ */
+ public function unset_tempdata($newdata = array())
+ {
+ // Get expirations list
+ $expirations = $this->userdata(self::EXPIRATION_KEY);
+ if (empty($expirations))
+ {
+ // Nothing to do
+ return;
+ }
+
+ // Wrap single name as array
+ if (is_string($newdata))
+ {
+ $newdata = array($newdata => '');
+ }
+
+ // Prepend each item name and unset
+ if (count($newdata) > 0)
+ {
+ foreach (array_keys($newdata) as $key)
+ {
+ $tempdata_key = self::FLASHDATA_KEY.self::FLASHDATA_EXP.$key;
+ unset($expirations[$tempdata_key]);
+ $this->unset_userdata($tempdata_key);
+ }
+ }
+
+ // Update expiration list
+ $this->set_userdata(self::EXPIRATION_KEY, $expirations);
+ }
+
+ // ------------------------------------------------------------------------
+
+ /**
+ * Fetch a specific tempdata item from the session array
+ *
+ * @param string Item key
+ * @return string
+ */
+ public function tempdata($key)
+ {
+ // Prepend key and return value
+ $tempdata_key = self::FLASHDATA_KEY.self::FLASHDATA_EXP.$key;
+ return $this->userdata($tempdata_key);
+ }
+
+ // ------------------------------------------------------------------------
+
+ /**
+ * Identifies flashdata as 'old' for removal
+ * when _flashdata_sweep() runs.
+ *
+ * @return void
+ */
+ protected function _flashdata_mark()
+ {
+ foreach ($this->all_userdata() as $name => $value)
+ {
+ $parts = explode(self::FLASHDATA_NEW, $name);
+ if (count($parts) === 2)
+ {
+ $new_name = self::FLASHDATA_KEY.self::FLASHDATA_OLD.$parts[1];
+ $this->set_userdata($new_name, $value);
+ $this->unset_userdata($name);
+ }
+ }
+ }
+
+ // ------------------------------------------------------------------------
+
+ /**
+ * Removes all flashdata marked as 'old'
+ *
+ * @return void
+ */
+ protected function _flashdata_sweep()
+ {
+ $userdata = $this->all_userdata();
+ foreach (array_keys($userdata) as $key)
+ {
+ if (strpos($key, self::FLASHDATA_OLD))
+ {
+ $this->unset_userdata($key);
+ }
+ }
+ }
+
+ // ------------------------------------------------------------------------
+
+ /**
+ * Removes all expired tempdata
+ *
+ * @return void
+ */
+ protected function _tempdata_sweep()
+ {
+ // Get expirations list
+ $expirations = $this->userdata(self::EXPIRATION_KEY);
+ if (empty($expirations))
+ {
+ // Nothing to do
+ return;
+ }
+
+ // Unset expired elements
+ $now = time();
+ $userdata = $this->all_userdata();
+ foreach (array_keys($userdata) as $key)
+ {
+ if (strpos($key, self::FLASHDATA_EXP) && $expirations[$key] < $now)
+ {
+ unset($expirations[$key]);
+ $this->unset_userdata($key);
+ }
+ }
+
+ // Update expiration list
+ $this->set_userdata(self::EXPIRATION_KEY, $expirations);
+ }
+
+}
+
+// ------------------------------------------------------------------------
+
+/**
+ * CI_Session_driver Class
+ *
+ * Extend this class to make a new CI_Session driver.
+ * A CI_Session driver basically manages an array of name/value pairs with some sort of storage mechanism.
+ * To make a new driver, derive from (extend) CI_Session_driver. Overload the initialize method and read or create
+ * session data. Then implement a save handler to write changed data to storage (sess_save), a destroy handler
+ * to remove deleted data (sess_destroy), and an access handler to expose the data (get_userdata).
+ * Put your driver in the libraries/Session/drivers folder anywhere in the loader paths. This includes the
+ * application directory, the system directory, or any path you add with $CI->load->add_package_path().
+ * Your driver must be named CI_Session_<name>, and your filename must be Session_<name>.php,
+ * preferably also capitalized. (e.g.: CI_Session_foo in libraries/Session/drivers/Session_foo.php)
+ * Then specify the driver by setting 'sess_driver' in your config file or as a parameter when loading the CI_Session
+ * object. (e.g.: $config['sess_driver'] = 'foo'; OR $CI->load->driver('session', array('sess_driver' => 'foo')); )
+ * Already provided are the Native driver, which manages the native PHP $_SESSION array, and
+ * the Cookie driver, which manages the data in a browser cookie, with optional extra storage in a database table.
+ *
+ * @package CodeIgniter
+ * @subpackage Libraries
+ * @category Sessions
+ * @author EllisLab Dev Team
+ */
+abstract class CI_Session_driver extends CI_Driver {
+
+ /**
+ * CI Singleton
+ *
+ * @see get_instance()
+ * @var object
+ */
+ protected $CI;
+
+ // ------------------------------------------------------------------------
+
+ /**
+ * Constructor
+ *
+ * Gets the CI singleton, so that individual drivers
+ * don't have to do it separately.
+ *
+ * @return void
+ */
+ public function __construct()
+ {
+ $this->CI =& get_instance();
+ }
+
+ // ------------------------------------------------------------------------
+
+ /**
+ * Decorate
+ *
+ * Decorates the child with the parent driver lib's methods and properties
+ *
+ * @param object Parent library object
+ * @return void
+ */
+ public function decorate($parent)
+ {
+ // Call base class decorate first
+ parent::decorate($parent);
+
+ // Call initialize method now that driver has access to $this->_parent
+ $this->initialize();
+ }
+
+ // ------------------------------------------------------------------------
+
+ /**
+ * __call magic method
+ *
+ * Handles access to the parent driver library's methods
+ *
+ * @param string Library method name
+ * @param array Method arguments (default: none)
+ * @return mixed
+ */
+ public function __call($method, $args = array())
+ {
+ // Make sure the parent library uses this driver
+ $this->_parent->select_driver(get_class($this));
+ return parent::__call($method, $args);
+ }
+
+ // ------------------------------------------------------------------------
+
+ /**
+ * Initialize driver
+ *
+ * @return void
+ */
+ protected function initialize()
+ {
+ // Overload this method to implement initialization
+ }
+
+ // ------------------------------------------------------------------------
+
+ /**
+ * Save the session data
+ *
+ * Data in the array has changed - perform any storage synchronization
+ * necessary. The child class MUST implement this abstract method!
+ *
+ * @return void
+ */
+ abstract public function sess_save();
+
+ // ------------------------------------------------------------------------
+
+ /**
+ * Destroy the current session
+ *
+ * Clean up storage for this session - it has been terminated.
+ * The child class MUST implement this abstract method!
+ *
+ * @return void
+ */
+ abstract public function sess_destroy();
+
+ // ------------------------------------------------------------------------
+
+ /**
+ * Regenerate the current session
+ *
+ * Regenerate the session ID.
+ * The child class MUST implement this abstract method!
+ *
+ * @param bool Destroy session data flag (default: false)
+ * @return void
+ */
+ abstract public function sess_regenerate($destroy = FALSE);
+
+ // ------------------------------------------------------------------------
+
+ /**
+ * Get a reference to user data array
+ *
+ * Give array access to the main CI_Session object.
+ * The child class MUST implement this abstract method!
+ *
+ * @return array Reference to userdata
+ */
+ abstract public function &get_userdata();
+
+}
+
+/* End of file Session.php */
+/* Location: ./system/libraries/Session/Session.php */ \ No newline at end of file
diff --git a/system/libraries/Session/drivers/Session_cookie.php b/system/libraries/Session/drivers/Session_cookie.php
new file mode 100644
index 000000000..6d926ae3d
--- /dev/null
+++ b/system/libraries/Session/drivers/Session_cookie.php
@@ -0,0 +1,845 @@
+<?php
+/**
+ * CodeIgniter
+ *
+ * An open source application development framework for PHP 5.2.4 or newer
+ *
+ * NOTICE OF LICENSE
+ *
+ * Licensed under the Open Software License version 3.0
+ *
+ * This source file is subject to the Open Software License (OSL 3.0) that is
+ * bundled with this package in the files license.txt / license.rst. It is
+ * also available through the world wide web at this URL:
+ * http://opensource.org/licenses/OSL-3.0
+ * If you did not receive a copy of the license and are unable to obtain it
+ * through the world wide web, please send an email to
+ * licensing@ellislab.com so we can send you a copy immediately.
+ *
+ * @package CodeIgniter
+ * @author EllisLab Dev Team
+ * @copyright Copyright (c) 2008 - 2012, EllisLab, Inc. (http://ellislab.com/)
+ * @license http://opensource.org/licenses/OSL-3.0 Open Software License (OSL 3.0)
+ * @link http://codeigniter.com
+ * @since Version 1.0
+ * @filesource
+ */
+defined('BASEPATH') OR exit('No direct script access allowed');
+
+/**
+ * Cookie-based session management driver
+ *
+ * This is the classic CI_Session functionality, as written by EllisLab, abstracted out to a driver.
+ *
+ * @package CodeIgniter
+ * @subpackage Libraries
+ * @category Sessions
+ * @author EllisLab Dev Team
+ * @link http://codeigniter.com/user_guide/libraries/sessions.html
+ */
+class CI_Session_cookie extends CI_Session_driver {
+
+ /**
+ * Whether to encrypt the session cookie
+ *
+ * @var bool
+ */
+ public $sess_encrypt_cookie = FALSE;
+
+ /**
+ * Whether to use to the database for session storage
+ *
+ * @var bool
+ */
+ public $sess_use_database = FALSE;
+
+ /**
+ * Name of the database table in which to store sessions
+ *
+ * @var string
+ */
+ public $sess_table_name = '';
+
+ /**
+ * Length of time (in seconds) for sessions to expire
+ *
+ * @var int
+ */
+ public $sess_expiration = 7200;
+
+ /**
+ * Whether to kill session on close of browser window
+ *
+ * @var bool
+ */
+ public $sess_expire_on_close = FALSE;
+
+ /**
+ * Whether to match session on ip address
+ *
+ * @var bool
+ */
+ public $sess_match_ip = FALSE;
+
+ /**
+ * Whether to match session on user-agent
+ *
+ * @var bool
+ */
+ public $sess_match_useragent = TRUE;
+
+ /**
+ * Name of session cookie
+ *
+ * @var string
+ */
+ public $sess_cookie_name = 'ci_session';
+
+ /**
+ * Session cookie prefix
+ *
+ * @var string
+ */
+ public $cookie_prefix = '';
+
+ /**
+ * Session cookie path
+ *
+ * @var string
+ */
+ public $cookie_path = '';
+
+ /**
+ * Session cookie domain
+ *
+ * @var string
+ */
+ public $cookie_domain = '';
+
+ /**
+ * Whether to set the cookie only on HTTPS connections
+ *
+ * @var bool
+ */
+ public $cookie_secure = FALSE;
+
+ /**
+ * Whether cookie should be allowed only to be sent by the server
+ *
+ * @var bool
+ */
+ public $cookie_httponly = FALSE;
+
+ /**
+ * Interval at which to update session
+ *
+ * @var int
+ */
+ public $sess_time_to_update = 300;
+
+ /**
+ * Key with which to encrypt the session cookie
+ *
+ * @var string
+ */
+ public $encryption_key = '';
+
+ /**
+ * Timezone to use for the current time
+ *
+ * @var string
+ */
+ public $time_reference = 'local';
+
+ /**
+ * Session data
+ *
+ * @var array
+ */
+ public $userdata = array();
+
+ /**
+ * Current time
+ *
+ * @var int
+ */
+ public $now;
+
+ /**
+ * Default userdata keys
+ *
+ * @var array
+ */
+ protected $defaults = array(
+ 'session_id' => NULL,
+ 'ip_address' => NULL,
+ 'user_agent' => NULL,
+ 'last_activity' => NULL
+ );
+
+ /**
+ * Data needs DB update flag
+ *
+ * @var bool
+ */
+ protected $data_dirty = FALSE;
+
+ /**
+ * Initialize session driver object
+ *
+ * @return void
+ */
+ protected function initialize()
+ {
+ // Set all the session preferences, which can either be set
+ // manually via the $params array or via the config file
+ $prefs = array(
+ 'sess_encrypt_cookie',
+ 'sess_use_database',
+ 'sess_table_name',
+ 'sess_expiration',
+ 'sess_expire_on_close',
+ 'sess_match_ip',
+ 'sess_match_useragent',
+ 'sess_cookie_name',
+ 'cookie_path',
+ 'cookie_domain',
+ 'cookie_secure',
+ 'cookie_httponly',
+ 'sess_time_to_update',
+ 'time_reference',
+ 'cookie_prefix',
+ 'encryption_key'
+ );
+
+ foreach ($prefs as $key)
+ {
+ $this->$key = isset($this->_parent->params[$key])
+ ? $this->_parent->params[$key]
+ : $this->CI->config->item($key);
+ }
+
+ if (empty($this->encryption_key))
+ {
+ show_error('In order to use the Cookie Session driver you are required to set an encryption key in your config file.');
+ }
+
+ // Do we need encryption? If so, load the encryption class
+ if ($this->sess_encrypt_cookie === TRUE)
+ {
+ $this->CI->load->library('encrypt');
+ }
+
+ // Check for database
+ if ($this->sess_use_database === TRUE && $this->sess_table_name !== '')
+ {
+ // Load database driver
+ $this->CI->load->database();
+
+ // Register shutdown function
+ register_shutdown_function(array($this, '_update_db'));
+ }
+
+ // Set the "now" time. Can either be GMT or server time, based on the config prefs.
+ // We use this to set the "last activity" time
+ $this->now = $this->_get_time();
+
+ // Set the session length. If the session expiration is
+ // set to zero we'll set the expiration two years from now.
+ if ($this->sess_expiration === 0)
+ {
+ $this->sess_expiration = (60*60*24*365*2);
+ }
+
+ // Set the cookie name
+ $this->sess_cookie_name = $this->cookie_prefix.$this->sess_cookie_name;
+
+ // Run the Session routine. If a session doesn't exist we'll
+ // create a new one. If it does, we'll update it.
+ if ( ! $this->_sess_read())
+ {
+ $this->_sess_create();
+ }
+ else
+ {
+ $this->_sess_update();
+ }
+
+ // Delete expired sessions if necessary
+ $this->_sess_gc();
+ }
+
+ // ------------------------------------------------------------------------
+
+ /**
+ * Write the session data
+ *
+ * @return void
+ */
+ public function sess_save()
+ {
+ // Check for database
+ if ($this->sess_use_database === TRUE)
+ {
+ // Mark custom data as dirty so we know to update the DB
+ $this->data_dirty = TRUE;
+ }
+
+ // Write the cookie
+ $this->_set_cookie();
+ }
+
+ // ------------------------------------------------------------------------
+
+ /**
+ * Destroy the current session
+ *
+ * @return void
+ */
+ public function sess_destroy()
+ {
+ // Kill the session DB row
+ if ($this->sess_use_database === TRUE && isset($this->userdata['session_id']))
+ {
+ $this->CI->db->delete($this->sess_table_name, array('session_id' => $this->userdata['session_id']));
+ $this->data_dirty = FALSE;
+ }
+
+ // Kill the cookie
+ $this->_setcookie($this->sess_cookie_name, '', ($this->now - 31500000),
+ $this->cookie_path, $this->cookie_domain, 0);
+
+ // Kill session data
+ $this->userdata = array();
+ }
+
+ // ------------------------------------------------------------------------
+
+ /**
+ * Regenerate the current session
+ *
+ * Regenerate the session id
+ *
+ * @param bool Destroy session data flag (default: false)
+ * @return void
+ */
+ public function sess_regenerate($destroy = FALSE)
+ {
+ // Check destroy flag
+ if ($destroy)
+ {
+ // Destroy old session and create new one
+ $this->sess_destroy();
+ $this->_sess_create();
+ }
+ else
+ {
+ // Just force an update to recreate the id
+ $this->_sess_update(TRUE);
+ }
+ }
+
+ // ------------------------------------------------------------------------
+
+ /**
+ * Get a reference to user data array
+ *
+ * @return array Reference to userdata
+ */
+ public function &get_userdata()
+ {
+ return $this->userdata;
+ }
+
+ // ------------------------------------------------------------------------
+
+ /**
+ * Fetch the current session data if it exists
+ *
+ * @return bool
+ */
+ protected function _sess_read()
+ {
+ // Fetch the cookie
+ $session = $this->CI->input->cookie($this->sess_cookie_name);
+
+ // No cookie? Goodbye cruel world!...
+ if ($session === NULL)
+ {
+ log_message('debug', 'A session cookie was not found.');
+ return FALSE;
+ }
+
+ $len = strlen($session) - 40;
+
+ if ($len < 0)
+ {
+ log_message('debug', 'The session cookie was not signed.');
+ return FALSE;
+ }
+
+ // Check cookie authentication
+ $hmac = substr($session, $len);
+ $session = substr($session, 0, $len);
+
+ if ($hmac !== hash_hmac('sha1', $session, $this->encryption_key))
+ {
+ log_message('error', 'The session cookie data did not match what was expected.');
+ $this->sess_destroy();
+ return FALSE;
+ }
+
+ // Check for encryption
+ if ($this->sess_encrypt_cookie === TRUE)
+ {
+ // Decrypt the cookie data
+ $session = $this->CI->encrypt->decode($session);
+ }
+
+ // Unserialize the session array
+ $session = $this->_unserialize($session);
+
+ // Is the session data we unserialized an array with the correct format?
+ if ( ! is_array($session) OR ! isset($session['session_id'], $session['ip_address'], $session['user_agent'], $session['last_activity']))
+ {
+ $this->sess_destroy();
+ return FALSE;
+ }
+
+ // Is the session current?
+ if (($session['last_activity'] + $this->sess_expiration) < $this->now OR $session['last_activity'] > $this->now)
+ {
+ $this->sess_destroy();
+ return FALSE;
+ }
+
+ // Does the IP match?
+ if ($this->sess_match_ip === TRUE && $session['ip_address'] !== $this->CI->input->ip_address())
+ {
+ $this->sess_destroy();
+ return FALSE;
+ }
+
+ // Does the User Agent Match?
+ if ($this->sess_match_useragent === TRUE &&
+ trim($session['user_agent']) !== trim(substr($this->CI->input->user_agent(), 0, 120)))
+ {
+ $this->sess_destroy();
+ return FALSE;
+ }
+
+ // Is there a corresponding session in the DB?
+ if ($this->sess_use_database === TRUE)
+ {
+ $this->CI->db->where('session_id', $session['session_id']);
+
+ if ($this->sess_match_ip === TRUE)
+ {
+ $this->CI->db->where('ip_address', $session['ip_address']);
+ }
+
+ if ($this->sess_match_useragent === TRUE)
+ {
+ $this->CI->db->where('user_agent', $session['user_agent']);
+ }
+
+ // Is caching in effect? Turn it off
+ $db_cache = $this->CI->db->cache_on;
+ $this->CI->db->cache_off();
+
+ $query = $this->CI->db->limit(1)->get($this->sess_table_name);
+
+ // Was caching in effect?
+ if ($db_cache)
+ {
+ // Turn it back on
+ $this->CI->db->cache_on();
+ }
+
+ // No result? Kill it!
+ if ($query->num_rows() === 0)
+ {
+ $this->sess_destroy();
+ return FALSE;
+ }
+
+ // Is there custom data? If so, add it to the main session array
+ $row = $query->row();
+ if ( ! empty($row->user_data))
+ {
+ $custom_data = $this->_unserialize($row->user_data);
+
+ if (is_array($custom_data))
+ {
+ $session = $session + $custom_data;
+ }
+ }
+ }
+
+ // Session is valid!
+ $this->userdata = $session;
+ return TRUE;
+ }
+
+ // ------------------------------------------------------------------------
+
+ /**
+ * Create a new session
+ *
+ * @return void
+ */
+ protected function _sess_create()
+ {
+ // Initialize userdata
+ $this->userdata = array(
+ 'session_id' => $this->_make_sess_id(),
+ 'ip_address' => $this->CI->input->ip_address(),
+ 'user_agent' => substr($this->CI->input->user_agent(), 0, 120),
+ 'last_activity' => $this->now,
+ );
+
+ // Check for database
+ if ($this->sess_use_database === TRUE)
+ {
+ // Add empty user_data field and save the data to the DB
+ $this->CI->db->set('user_data', '')->insert($this->sess_table_name, $this->userdata);
+ }
+
+ // Write the cookie
+ $this->_set_cookie();
+ }
+
+ // ------------------------------------------------------------------------
+
+ /**
+ * Update an existing session
+ *
+ * @param bool Force update flag (default: false)
+ * @return void
+ */
+ protected function _sess_update($force = FALSE)
+ {
+ // We only update the session every five minutes by default (unless forced)
+ if ( ! $force && ($this->userdata['last_activity'] + $this->sess_time_to_update) >= $this->now)
+ {
+ return;
+ }
+
+ // Update last activity to now
+ $this->userdata['last_activity'] = $this->now;
+
+ // Save the old session id so we know which DB record to update
+ $old_sessid = $this->userdata['session_id'];
+
+ // Changing the session ID during an AJAX call causes problems
+ if ( ! $this->CI->input->is_ajax_request())
+ {
+ // Get new id
+ $this->userdata['session_id'] = $this->_make_sess_id();
+ }
+
+ // Check for database
+ if ($this->sess_use_database === TRUE)
+ {
+ $this->CI->db->where('session_id', $old_sessid);
+
+ if ($this->sess_match_ip === TRUE)
+ {
+ $this->CI->db->where('ip_address', $this->CI->input->ip_address());
+ }
+
+ if ($this->sess_match_useragent === TRUE)
+ {
+ $this->CI->db->where('user_agent', trim(substr($this->CI->input->user_agent(), 0, 120)));
+ }
+
+ // Update the session ID and last_activity field in the DB
+ $this->CI->db->update($this->sess_table_name,
+ array(
+ 'last_activity' => $this->now,
+ 'session_id' => $this->userdata['session_id']
+ )
+ );
+ }
+
+ // Write the cookie
+ $this->_set_cookie();
+ }
+
+ // ------------------------------------------------------------------------
+
+ /**
+ * Update database with current data
+ *
+ * This gets called from the shutdown function and also
+ * registered with PHP to run at the end of the request
+ * so it's guaranteed to update even when a fatal error
+ * occurs. The first call makes the update and clears the
+ * dirty flag so it won't happen twice.
+ *
+ * @return void
+ */
+ public function _update_db()
+ {
+ // Check for database and dirty flag and unsaved
+ if ($this->sess_use_database === TRUE && $this->data_dirty === TRUE)
+ {
+ // Set up activity and data fields to be set
+ // If we don't find custom data, user_data will remain an empty string
+ $set = array(
+ 'last_activity' => $this->userdata['last_activity'],
+ 'user_data' => ''
+ );
+
+ // Get the custom userdata, leaving out the defaults
+ // (which get stored in the cookie)
+ $userdata = array_diff_key($this->userdata, $this->defaults);
+
+ // Did we find any custom data?
+ if ( ! empty($userdata))
+ {
+ // Serialize the custom data array so we can store it
+ $set['user_data'] = $this->_serialize($userdata);
+ }
+
+ // Run the update query
+ // Any time we change the session id, it gets updated immediately,
+ // so our where clause below is always safe
+ $this->CI->db->where('session_id', $this->userdata['session_id']);
+
+ if ($this->sess_match_ip === TRUE)
+ {
+ $this->CI->db->where('ip_address', $this->CI->input->ip_address());
+ }
+
+ if ($this->sess_match_useragent === TRUE)
+ {
+ $this->CI->db->where('user_agent', trim(substr($this->CI->input->user_agent(), 0, 120)));
+ }
+
+ $this->CI->db->update($this->sess_table_name, $set);
+
+ // Clear dirty flag to prevent double updates
+ $this->data_dirty = FALSE;
+
+ log_message('debug', 'CI_Session Data Saved To DB');
+ }
+ }
+
+ // ------------------------------------------------------------------------
+
+ /**
+ * Generate a new session id
+ *
+ * @return string Hashed session id
+ */
+ protected function _make_sess_id()
+ {
+ $new_sessid = '';
+ do
+ {
+ $new_sessid .= mt_rand(0, mt_getrandmax());
+ }
+ while (strlen($new_sessid) < 32);
+
+ // To make the session ID even more secure we'll combine it with the user's IP
+ $new_sessid .= $this->CI->input->ip_address();
+
+ // Turn it into a hash and return
+ return md5(uniqid($new_sessid, TRUE));
+ }
+
+ // ------------------------------------------------------------------------
+
+ /**
+ * Get the "now" time
+ *
+ * @return int Time
+ */
+ protected function _get_time()
+ {
+ if ($this->time_reference === 'local' OR $this->time_reference === date_default_timezone_get())
+ {
+ return time();
+ }
+
+ $datetime = new DateTime('now', new DateTimeZone($this->time_reference));
+ sscanf($datetime->format('j-n-Y G:i:s'), '%d-%d-%d %d:%d:%d', $day, $month, $year, $hour, $minute, $second);
+
+ return mktime($hour, $minute, $second, $month, $day, $year);
+ }
+
+ // ------------------------------------------------------------------------
+
+ /**
+ * Write the session cookie
+ *
+ * @return void
+ */
+ protected function _set_cookie()
+ {
+ // Get userdata (only defaults if database)
+ $cookie_data = ($this->sess_use_database === TRUE)
+ ? array_intersect_key($this->userdata, $this->defaults)
+ : $this->userdata;
+
+ // Serialize the userdata for the cookie
+ $cookie_data = $this->_serialize($cookie_data);
+
+ if ($this->sess_encrypt_cookie === TRUE)
+ {
+ $cookie_data = $this->CI->encrypt->encode($cookie_data);
+ }
+
+ // Require message authentication
+ $cookie_data .= hash_hmac('sha1', $cookie_data, $this->encryption_key);
+
+ $expire = ($this->sess_expire_on_close === TRUE) ? 0 : $this->sess_expiration + time();
+
+ // Set the cookie
+ $this->_setcookie($this->sess_cookie_name, $cookie_data, $expire, $this->cookie_path, $this->cookie_domain,
+ $this->cookie_secure, $this->cookie_httponly);
+ }
+
+ // ------------------------------------------------------------------------
+
+ /**
+ * Set a cookie with the system
+ *
+ * This abstraction of the setcookie call allows overriding for unit testing
+ *
+ * @param string Cookie name
+ * @param string Cookie value
+ * @param int Expiration time
+ * @param string Cookie path
+ * @param string Cookie domain
+ * @param bool Secure connection flag
+ * @param bool HTTP protocol only flag
+ * @return void
+ */
+ protected function _setcookie($name, $value = '', $expire = 0, $path = '', $domain = '', $secure = FALSE, $httponly = FALSE)
+ {
+ setcookie($name, $value, $expire, $path, $domain, $secure, $httponly);
+ }
+
+ // ------------------------------------------------------------------------
+
+ /**
+ * Serialize an array
+ *
+ * This function first converts any slashes found in the array to a temporary
+ * marker, so when it gets unserialized the slashes will be preserved
+ *
+ * @param mixed Data to serialize
+ * @return string Serialized data
+ */
+ protected function _serialize($data)
+ {
+ if (is_array($data))
+ {
+ array_walk_recursive($data, array(&$this, '_escape_slashes'));
+ }
+ elseif (is_string($data))
+ {
+ $data = str_replace('\\', '{{slash}}', $data);
+ }
+
+ return serialize($data);
+ }
+
+ // ------------------------------------------------------------------------
+
+ /**
+ * Escape slashes
+ *
+ * This function converts any slashes found into a temporary marker
+ *
+ * @param string Value
+ * @param string Key
+ * @return void
+ */
+ protected function _escape_slashes(&$val, $key)
+ {
+ if (is_string($val))
+ {
+ $val = str_replace('\\', '{{slash}}', $val);
+ }
+ }
+
+ // ------------------------------------------------------------------------
+
+ /**
+ * Unserialize
+ *
+ * This function unserializes a data string, then converts any
+ * temporary slash markers back to actual slashes
+ *
+ * @param mixed Data to unserialize
+ * @return mixed Unserialized data
+ */
+ protected function _unserialize($data)
+ {
+ $data = @unserialize(trim($data));
+
+ if (is_array($data))
+ {
+ array_walk_recursive($data, array(&$this, '_unescape_slashes'));
+ return $data;
+ }
+
+ return is_string($data) ? str_replace('{{slash}}', '\\', $data) : $data;
+ }
+
+ // ------------------------------------------------------------------------
+
+ /**
+ * Unescape slashes
+ *
+ * This function converts any slash markers back into actual slashes
+ *
+ * @param string Value
+ * @param string Key
+ * @return void
+ */
+ protected function _unescape_slashes(&$val, $key)
+ {
+ if (is_string($val))
+ {
+ $val= str_replace('{{slash}}', '\\', $val);
+ }
+ }
+
+ // ------------------------------------------------------------------------
+
+ /**
+ * Garbage collection
+ *
+ * This deletes expired session rows from database
+ * if the probability percentage is met
+ *
+ * @return void
+ */
+ protected function _sess_gc()
+ {
+ if ($this->sess_use_database !== TRUE)
+ {
+ return;
+ }
+
+ $probability = ini_get('session.gc_probability');
+ $divisor = ini_get('session.gc_divisor');
+
+ srand(time());
+ if ((mt_rand(0, $divisor) / $divisor) < $probability)
+ {
+ $expire = $this->now - $this->sess_expiration;
+ $this->CI->db->delete($this->sess_table_name, 'last_activity < '.$expire);
+
+ log_message('debug', 'Session garbage collection performed.');
+ }
+ }
+
+}
+
+/* End of file Session_cookie.php */
+/* Location: ./system/libraries/Session/drivers/Session_cookie.php */ \ No newline at end of file
diff --git a/system/libraries/Session/drivers/Session_native.php b/system/libraries/Session/drivers/Session_native.php
new file mode 100644
index 000000000..3e700ad5d
--- /dev/null
+++ b/system/libraries/Session/drivers/Session_native.php
@@ -0,0 +1,242 @@
+<?php
+/**
+ * CodeIgniter
+ *
+ * An open source application development framework for PHP 5.2.4 or newer
+ *
+ * NOTICE OF LICENSE
+ *
+ * Licensed under the Open Software License version 3.0
+ *
+ * This source file is subject to the Open Software License (OSL 3.0) that is
+ * bundled with this package in the files license.txt / license.rst. It is
+ * also available through the world wide web at this URL:
+ * http://opensource.org/licenses/OSL-3.0
+ * If you did not receive a copy of the license and are unable to obtain it
+ * through the world wide web, please send an email to
+ * licensing@ellislab.com so we can send you a copy immediately.
+ *
+ * @package CodeIgniter
+ * @author EllisLab Dev Team
+ * @copyright Copyright (c) 2008 - 2012, EllisLab, Inc. (http://ellislab.com/)
+ * @license http://opensource.org/licenses/OSL-3.0 Open Software License (OSL 3.0)
+ * @link http://codeigniter.com
+ * @since Version 1.0
+ * @filesource
+ */
+defined('BASEPATH') OR exit('No direct script access allowed');
+
+/**
+ * Native PHP session management driver
+ *
+ * This is the driver that uses the native PHP $_SESSION array through the Session driver library.
+ *
+ * @package CodeIgniter
+ * @subpackage Libraries
+ * @category Sessions
+ * @author EllisLab Dev Team
+ */
+class CI_Session_native extends CI_Session_driver {
+
+ /**
+ * Initialize session driver object
+ *
+ * @return void
+ */
+ protected function initialize()
+ {
+ // Get config parameters
+ $config = array();
+ $prefs = array(
+ 'sess_cookie_name',
+ 'sess_expire_on_close',
+ 'sess_expiration',
+ 'sess_match_ip',
+ 'sess_match_useragent',
+ 'sess_time_to_update',
+ 'cookie_prefix',
+ 'cookie_path',
+ 'cookie_domain',
+ 'cookie_secure',
+ 'cookie_httponly'
+ );
+
+ foreach ($prefs as $key)
+ {
+ $config[$key] = isset($this->_parent->params[$key])
+ ? $this->_parent->params[$key]
+ : $this->CI->config->item($key);
+ }
+
+ // Set session name, if specified
+ if ($config['sess_cookie_name'])
+ {
+ // Differentiate name from cookie driver with '_id' suffix
+ $name = $config['sess_cookie_name'].'_id';
+ if ($config['cookie_prefix'])
+ {
+ // Prepend cookie prefix
+ $name = $config['cookie_prefix'].$name;
+ }
+ session_name($name);
+ }
+
+ // Set expiration, path, and domain
+ $expire = 7200;
+ $path = '/';
+ $domain = '';
+ $secure = (bool) $config['cookie_secure'];
+ $http_only = (bool) $config['cookie_httponly'];
+
+ if ($config['sess_expiration'] !== FALSE)
+ {
+ // Default to 2 years if expiration is "0"
+ $expire = ($config['sess_expiration'] == 0) ? (60*60*24*365*2) : $config['sess_expiration'];
+ }
+
+ if ($config['cookie_path'])
+ {
+ // Use specified path
+ $path = $config['cookie_path'];
+ }
+
+ if ($config['cookie_domain'])
+ {
+ // Use specified domain
+ $domain = $config['cookie_domain'];
+ }
+
+ session_set_cookie_params($config['sess_expire_on_close'] ? 0 : $expire, $path, $domain, $secure, $http_only);
+
+ // Start session
+ session_start();
+
+ // Check session expiration, ip, and agent
+ $now = time();
+ $destroy = FALSE;
+ if (isset($_SESSION['last_activity']) && (($_SESSION['last_activity'] + $expire) < $now OR $_SESSION['last_activity'] > $now))
+ {
+ // Expired - destroy
+ $destroy = TRUE;
+ }
+ elseif ($config['sess_match_ip'] === TRUE && isset($_SESSION['ip_address'])
+ && $_SESSION['ip_address'] !== $this->CI->input->ip_address())
+ {
+ // IP doesn't match - destroy
+ $destroy = TRUE;
+ }
+ elseif ($config['sess_match_useragent'] === TRUE && isset($_SESSION['user_agent'])
+ && $_SESSION['user_agent'] !== trim(substr($this->CI->input->user_agent(), 0, 50)))
+ {
+ // Agent doesn't match - destroy
+ $destroy = TRUE;
+ }
+
+ // Destroy expired or invalid session
+ if ($destroy)
+ {
+ // Clear old session and start new
+ $this->sess_destroy();
+ session_start();
+ }
+
+ // Check for update time
+ if ($config['sess_time_to_update'] && isset($_SESSION['last_activity'])
+ && ($_SESSION['last_activity'] + $config['sess_time_to_update']) < $now)
+ {
+ // Changing the session ID amidst a series of AJAX calls causes problems
+ if( ! $this->CI->input->is_ajax_request())
+ {
+ // Regenerate ID, but don't destroy session
+ $this->sess_regenerate(FALSE);
+ }
+ }
+
+ // Set activity time
+ $_SESSION['last_activity'] = $now;
+
+ // Set matching values as required
+ if ($config['sess_match_ip'] === TRUE && ! isset($_SESSION['ip_address']))
+ {
+ // Store user IP address
+ $_SESSION['ip_address'] = $this->CI->input->ip_address();
+ }
+
+ if ($config['sess_match_useragent'] === TRUE && ! isset($_SESSION['user_agent']))
+ {
+ // Store user agent string
+ $_SESSION['user_agent'] = trim(substr($this->CI->input->user_agent(), 0, 50));
+ }
+
+ // Make session ID available
+ $_SESSION['session_id'] = session_id();
+ }
+
+ // ------------------------------------------------------------------------
+
+ /**
+ * Save the session data
+ *
+ * @return void
+ */
+ public function sess_save()
+ {
+ // Nothing to do - changes to $_SESSION are automatically saved
+ }
+
+ // ------------------------------------------------------------------------
+
+ /**
+ * Destroy the current session
+ *
+ * @return void
+ */
+ public function sess_destroy()
+ {
+ // Cleanup session
+ $_SESSION = array();
+ $name = session_name();
+ if (isset($_COOKIE[$name]))
+ {
+ // Clear session cookie
+ $params = session_get_cookie_params();
+ setcookie($name, '', time() - 42000, $params['path'], $params['domain'], $params['secure'], $params['httponly']);
+ unset($_COOKIE[$name]);
+ }
+ session_destroy();
+ }
+
+ // ------------------------------------------------------------------------
+
+ /**
+ * Regenerate the current session
+ *
+ * Regenerate the session id
+ *
+ * @param bool Destroy session data flag (default: FALSE)
+ * @return void
+ */
+ public function sess_regenerate($destroy = FALSE)
+ {
+ // Just regenerate id, passing destroy flag
+ session_regenerate_id($destroy);
+ $_SESSION['session_id'] = session_id();
+ }
+
+ // ------------------------------------------------------------------------
+
+ /**
+ * Get a reference to user data array
+ *
+ * @return array Reference to userdata
+ */
+ public function &get_userdata()
+ {
+ // Just return reference to $_SESSION
+ return $_SESSION;
+ }
+
+}
+
+/* End of file Session_native.php */
+/* Location: ./system/libraries/Session/drivers/Session_native.php */ \ No newline at end of file
diff --git a/system/libraries/Session/drivers/index.html b/system/libraries/Session/drivers/index.html
new file mode 100644
index 000000000..c942a79ce
--- /dev/null
+++ b/system/libraries/Session/drivers/index.html
@@ -0,0 +1,10 @@
+<html>
+<head>
+ <title>403 Forbidden</title>
+</head>
+<body>
+
+<p>Directory access is forbidden.</p>
+
+</body>
+</html> \ No newline at end of file
diff --git a/system/libraries/Session/index.html b/system/libraries/Session/index.html
new file mode 100644
index 000000000..c942a79ce
--- /dev/null
+++ b/system/libraries/Session/index.html
@@ -0,0 +1,10 @@
+<html>
+<head>
+ <title>403 Forbidden</title>
+</head>
+<body>
+
+<p>Directory access is forbidden.</p>
+
+</body>
+</html> \ No newline at end of file
diff --git a/system/libraries/Table.php b/system/libraries/Table.php
index 3777d29ff..3d53b1c00 100644
--- a/system/libraries/Table.php
+++ b/system/libraries/Table.php
@@ -1,4 +1,4 @@
-<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');
+<?php
/**
* CodeIgniter
*
@@ -24,6 +24,7 @@
* @since Version 1.3.1
* @filesource
*/
+defined('BASEPATH') OR exit('No direct script access allowed');
/**
* HTML Table Generating Class
@@ -38,13 +39,60 @@
*/
class CI_Table {
+ /**
+ * Data for table rows
+ *
+ * @var array
+ */
public $rows = array();
+
+ /**
+ * Data for table heading
+ *
+ * @var array
+ */
public $heading = array();
+
+ /**
+ * Whether or not to automatically create the table header
+ *
+ * @var bool
+ */
public $auto_heading = TRUE;
+
+ /**
+ * Table caption
+ *
+ * @var string
+ */
public $caption = NULL;
+
+ /**
+ * Table layout template
+ *
+ * @var array
+ */
public $template = NULL;
+
+ /**
+ * Newline setting
+ *
+ * @var string
+ */
public $newline = "\n";
+
+ /**
+ * Contents of empty cells
+ *
+ * @var string
+ */
public $empty_cells = '';
+
+ /**
+ * Callback for custom table layout
+ *
+ * @var function
+ */
public $function = FALSE;
/**
@@ -93,7 +141,7 @@ class CI_Table {
* @param mixed
* @return void
*/
- public function set_heading()
+ public function set_heading($args = array())
{
$args = func_get_args();
$this->heading = $this->_prep_args($args);
@@ -122,7 +170,7 @@ class CI_Table {
// will want headings from a one-dimensional array
$this->auto_heading = FALSE;
- if ($col_limit == 0)
+ if ($col_limit === 0)
{
return $array;
}
@@ -172,7 +220,7 @@ class CI_Table {
* @param mixed
* @return void
*/
- public function add_row()
+ public function add_row($args = array())
{
$args = func_get_args();
$this->rows[] = $this->_prep_args($args);
@@ -251,7 +299,7 @@ class CI_Table {
}
elseif (is_array($table_data))
{
- $set_heading = (count($this->heading) !== 0 OR $this->auto_heading != FALSE);
+ $set_heading = (count($this->heading) !== 0 OR $this->auto_heading !== FALSE);
$this->_set_from_array($table_data, $set_heading);
}
}
@@ -289,7 +337,7 @@ class CI_Table {
foreach ($heading as $key => $val)
{
- if ($key != 'data')
+ if ($key !== 'data')
{
$temp = str_replace('<th', '<th '.$key.'="'.$val.'"', $temp);
}
@@ -420,6 +468,7 @@ class CI_Table {
* Set table data from an array
*
* @param array
+ * @param bool
* @return void
*/
protected function _set_from_array($data, $set_heading = TRUE)
@@ -433,7 +482,7 @@ class CI_Table {
foreach ($data as $row)
{
// If a heading hasn't already been set we'll use the first row of the array as the heading
- if ($i++ === 0 && count($data) > 1 && count($this->heading) === 0 && $set_heading == TRUE)
+ if ($i++ === 0 && count($data) > 1 && count($this->heading) === 0 && $set_heading === TRUE)
{
$this->heading = $this->_prep_args($row);
}
@@ -453,7 +502,7 @@ class CI_Table {
*/
protected function _compile_template()
{
- if ($this->template == NULL)
+ if ($this->template === NULL)
{
$this->template = $this->_default_template();
return;
@@ -478,7 +527,7 @@ class CI_Table {
*/
protected function _default_template()
{
- return array(
+ return array(
'table_open' => '<table border="0" cellpadding="4" cellspacing="0">',
'thead_open' => '<thead>',
diff --git a/system/libraries/Trackback.php b/system/libraries/Trackback.php
index 6761f63a5..d30350340 100644
--- a/system/libraries/Trackback.php
+++ b/system/libraries/Trackback.php
@@ -1,4 +1,4 @@
-<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');
+<?php
/**
* CodeIgniter
*
@@ -24,6 +24,7 @@
* @since Version 1.0
* @filesource
*/
+defined('BASEPATH') OR exit('No direct script access allowed');
/**
* Trackback Class
@@ -38,13 +39,51 @@
*/
class CI_Trackback {
- public $time_format = 'local';
+ /**
+ * Character set
+ *
+ * @var string
+ */
public $charset = 'UTF-8';
- public $data = array('url' => '', 'title' => '', 'excerpt' => '', 'blog_name' => '', 'charset' => '');
+
+ /**
+ * Trackback data
+ *
+ * @var array
+ */
+ public $data = array('url' => '', 'title' => '', 'excerpt' => '', 'blog_name' => '', 'charset' => '');
+
+ /**
+ * Convert ASCII flag
+ *
+ * Whether to convert high-ASCII and MS Word
+ * characters to HTML entities.
+ *
+ * @var bool
+ */
public $convert_ascii = TRUE;
- public $response = '';
- public $error_msg = array();
+ /**
+ * Response
+ *
+ * @var string
+ */
+ public $response = '';
+
+ /**
+ * Error messages list
+ *
+ * @var string[]
+ */
+ public $error_msg = array();
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Constructor
+ *
+ * @return void
+ */
public function __construct()
{
log_message('debug', 'Trackback Class Initialized');
@@ -88,7 +127,7 @@ class CI_Trackback {
}
// Convert High ASCII Characters
- if ($this->convert_ascii == TRUE && in_array($item, array('excerpt', 'title', 'blog_name')))
+ if ($this->convert_ascii === TRUE && in_array($item, array('excerpt', 'title', 'blog_name')))
{
$$item = $this->convert_ascii($$item);
}
@@ -106,7 +145,7 @@ class CI_Trackback {
{
foreach ($ping_url as $url)
{
- if ($this->process($url, $data) == FALSE)
+ if ($this->process($url, $data) === FALSE)
{
$return = FALSE;
}
@@ -132,7 +171,7 @@ class CI_Trackback {
{
foreach (array('url', 'title', 'blog_name', 'excerpt') as $val)
{
- if ( ! isset($_POST[$val]) OR $_POST[$val] == '')
+ if (empty($_POST[$val]))
{
$this->set_error('The following required POST variable is missing: '.$val);
return FALSE;
@@ -140,14 +179,14 @@ class CI_Trackback {
$this->data['charset'] = isset($_POST['charset']) ? strtoupper(trim($_POST['charset'])) : 'auto';
- if ($val != 'url' && MB_ENABLED === TRUE)
+ if ($val !== 'url' && MB_ENABLED === TRUE)
{
$_POST[$val] = mb_convert_encoding($_POST[$val], $this->charset, $this->data['charset']);
}
- $_POST[$val] = ($val != 'url') ? $this->convert_xml(strip_tags($_POST[$val])) : strip_tags($_POST[$val]);
+ $_POST[$val] = ($val !== 'url') ? $this->convert_xml(strip_tags($_POST[$val])) : strip_tags($_POST[$val]);
- if ($val == 'excerpt')
+ if ($val === 'excerpt')
{
$_POST['excerpt'] = $this->limit_characters($_POST['excerpt']);
}
@@ -355,7 +394,7 @@ class CI_Trackback {
}
}
- return preg_match('/^[0-9]+$/', $tb_id) ? $tb_id : FALSE;
+ return ctype_digit((string) $tb_id) ? $tb_id : FALSE;
}
// --------------------------------------------------------------------
diff --git a/system/libraries/Typography.php b/system/libraries/Typography.php
index 21bbad038..d83bf519b 100644
--- a/system/libraries/Typography.php
+++ b/system/libraries/Typography.php
@@ -1,4 +1,4 @@
-<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');
+<?php
/**
* CodeIgniter
*
@@ -24,6 +24,7 @@
* @since Version 1.0
* @filesource
*/
+defined('BASEPATH') OR exit('No direct script access allowed');
/**
* Typography Class
@@ -36,22 +37,46 @@
*/
class CI_Typography {
- // Block level elements that should not be wrapped inside <p> tags
+ /**
+ * Block level elements that should not be wrapped inside <p> tags
+ *
+ * @var string
+ */
public $block_elements = 'address|blockquote|div|dl|fieldset|form|h\d|hr|noscript|object|ol|p|pre|script|table|ul';
- // Elements that should not have <p> and <br /> tags within them.
+ /**
+ * Elements that should not have <p> and <br /> tags within them.
+ *
+ * @var string
+ */
public $skip_elements = 'p|pre|ol|ul|dl|object|table|h\d';
- // Tags we want the parser to completely ignore when splitting the string.
+ /**
+ * Tags we want the parser to completely ignore when splitting the string.
+ *
+ * @var string
+ */
public $inline_elements = 'a|abbr|acronym|b|bdo|big|br|button|cite|code|del|dfn|em|i|img|ins|input|label|map|kbd|q|samp|select|small|span|strong|sub|sup|textarea|tt|var';
- // array of block level elements that require inner content to be within another block level element
+ /**
+ * array of block level elements that require inner content to be within another block level element
+ *
+ * @var array
+ */
public $inner_block_required = array('blockquote');
- // the last block element parsed
+ /**
+ * the last block element parsed
+ *
+ * @var string
+ */
public $last_block_element = '';
- // whether or not to protect quotes within { curly braces }
+ /**
+ * whether or not to protect quotes within { curly braces }
+ *
+ * @var bool
+ */
public $protect_braced_quotes = FALSE;
/**
@@ -71,7 +96,7 @@ class CI_Typography {
*/
public function auto_typography($str, $reduce_linebreaks = FALSE)
{
- if ($str == '')
+ if ($str === '')
{
return '';
}
@@ -149,7 +174,7 @@ class CI_Typography {
$process = ($match[1] === '/');
}
- if ($match[1] == '')
+ if ($match[1] === '')
{
$this->last_block_element = $match[2];
}
@@ -320,7 +345,7 @@ class CI_Typography {
*/
protected function _format_newlines($str)
{
- if ($str == '' OR (strpos($str, "\n") === FALSE && ! in_array($this->last_block_element, $this->inner_block_required)))
+ if ($str === '' OR (strpos($str, "\n") === FALSE && ! in_array($this->last_block_element, $this->inner_block_required)))
{
return $str;
}
@@ -332,7 +357,7 @@ class CI_Typography {
$str = preg_replace("/([^\n])(\n)([^\n])/", '\\1<br />\\2\\3', $str);
// Wrap the whole enchilada in enclosing paragraphs
- if ($str != "\n")
+ if ($str !== "\n")
{
// We trim off the right-side new line so that the closing </p> tag
// will be positioned immediately following the string, matching
diff --git a/system/libraries/Unit_test.php b/system/libraries/Unit_test.php
index 0f6e2dfdd..05c7eef78 100644
--- a/system/libraries/Unit_test.php
+++ b/system/libraries/Unit_test.php
@@ -1,4 +1,4 @@
-<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');
+<?php
/**
* CodeIgniter
*
@@ -24,6 +24,7 @@
* @since Version 1.3.1
* @filesource
*/
+defined('BASEPATH') OR exit('No direct script access allowed');
/**
* Unit Testing Class
@@ -38,13 +39,57 @@
*/
class CI_Unit_test {
- public $active = TRUE;
- public $results = array();
- public $strict = FALSE;
- protected $_template = NULL;
- protected $_template_rows = NULL;
+ /**
+ * Active flag
+ *
+ * @var bool
+ */
+ public $active = TRUE;
+
+ /**
+ * Test results
+ *
+ * @var array
+ */
+ public $results = array();
+
+ /**
+ * Strict comparison flag
+ *
+ * Whether to use === or == when comparing
+ *
+ * @var bool
+ */
+ public $strict = FALSE;
+
+ /**
+ * Template
+ *
+ * @var string
+ */
+ protected $_template = NULL;
+
+ /**
+ * Template rows
+ *
+ * @var string
+ */
+ protected $_template_rows = NULL;
+
+ /**
+ * List of visible test items
+ *
+ * @var array
+ */
protected $_test_items_visible = array();
+ // --------------------------------------------------------------------
+
+ /**
+ * Constructor
+ *
+ * @return void
+ */
public function __construct()
{
// These are the default items visible when a test is run.
@@ -86,14 +131,15 @@ class CI_Unit_test {
*
* Runs the supplied tests
*
- * @param mixed
- * @param mixed
- * @param string
+ * @param mixed $test
+ * @param mixed $expected
+ * @param string $test_name
+ * @param string $notes
* @return string
*/
public function run($test, $expected = TRUE, $test_name = 'undefined', $notes = '')
{
- if ($this->active == FALSE)
+ if ($this->active === FALSE)
{
return FALSE;
}
@@ -106,13 +152,13 @@ class CI_Unit_test {
}
else
{
- $result = ($this->strict == TRUE) ? ($test === $expected) : ($test == $expected);
+ $result = ($this->strict === TRUE) ? ($test === $expected) : ($test == $expected);
$extype = gettype($expected);
}
$back = $this->_backtrace();
- $report[] = array (
+ $report = array (
'test_name' => $test_name,
'test_datatype' => gettype($test),
'res_datatype' => $extype,
@@ -124,7 +170,7 @@ class CI_Unit_test {
$this->results[] = $report;
- return($this->report($this->result($report)));
+ return $this->report($this->result(array($report)));
}
// --------------------------------------------------------------------
@@ -134,6 +180,7 @@ class CI_Unit_test {
*
* Displays a table with the test data
*
+ * @param array $result
* @return string
*/
public function report($result = array())
@@ -155,13 +202,13 @@ class CI_Unit_test {
foreach ($res as $key => $val)
{
- if ($key == $CI->lang->line('ut_result'))
+ if ($key === $CI->lang->line('ut_result'))
{
- if ($val == $CI->lang->line('ut_passed'))
+ if ($val === $CI->lang->line('ut_passed'))
{
$val = '<span style="color: #0C0;">'.$val.'</span>';
}
- elseif ($val == $CI->lang->line('ut_failed'))
+ elseif ($val === $CI->lang->line('ut_failed'))
{
$val = '<span style="color: #C00;">'.$val.'</span>';
}
@@ -213,6 +260,7 @@ class CI_Unit_test {
*
* Returns the raw result data
*
+ * @param array $results
* @return array
*/
public function result($results = array())
@@ -236,25 +284,11 @@ class CI_Unit_test {
continue;
}
- if (is_array($val))
- {
- foreach ($val as $k => $v)
- {
- if (FALSE !== ($line = $CI->lang->line(strtolower('ut_'.$v))))
- {
- $v = $line;
- }
- $temp[$CI->lang->line('ut_'.$k)] = $v;
- }
- }
- else
+ if (FALSE !== ($line = $CI->lang->line(strtolower('ut_'.$val), FALSE)))
{
- if (FALSE !== ($line = $CI->lang->line(strtolower('ut_'.$val))))
- {
- $val = $line;
- }
- $temp[$CI->lang->line('ut_'.$key)] = $val;
+ $val = $line;
}
+ $temp[$CI->lang->line('ut_'.$key, FALSE)] = $val;
}
$retval[] = $temp;
@@ -289,15 +323,11 @@ class CI_Unit_test {
*/
protected function _backtrace()
{
- if (function_exists('debug_backtrace'))
- {
- $back = debug_backtrace();
- return array(
- 'file' => (isset($back[1]['file']) ? $back[1]['file'] : ''),
- 'line' => (isset($back[1]['line']) ? $back[1]['line'] : '')
- );
- }
- return array('file' => 'Unknown', 'line' => 'Unknown');
+ $back = debug_backtrace();
+ return array(
+ 'file' => (isset($back[1]['file']) ? $back[1]['file'] : ''),
+ 'line' => (isset($back[1]['line']) ? $back[1]['line'] : '')
+ );
}
// --------------------------------------------------------------------
@@ -344,18 +374,26 @@ class CI_Unit_test {
}
/**
- * Helper functions to test boolean true/false
+ * Helper function to test boolean TRUE
*
+ * @param mixed $test
* @return bool
*/
function is_true($test)
{
- return (is_bool($test) && $test === TRUE);
+ return ($test === TRUE);
}
+
+/**
+ * Helper function to test boolean FALSE
+ *
+ * @param mixed $test
+ * @return bool
+ */
function is_false($test)
{
- return (is_bool($test) && $test === FALSE);
+ return ($test === FALSE);
}
/* End of file Unit_test.php */
-/* Location: ./system/libraries/Unit_test.php */ \ No newline at end of file
+/* Location: ./system/libraries/Unit_test.php */
diff --git a/system/libraries/Upload.php b/system/libraries/Upload.php
index 8ad67050d..4f65c9eb1 100644
--- a/system/libraries/Upload.php
+++ b/system/libraries/Upload.php
@@ -1,4 +1,4 @@
-<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');
+<?php
/**
* CodeIgniter
*
@@ -24,6 +24,7 @@
* @since Version 1.0
* @filesource
*/
+defined('BASEPATH') OR exit('No direct script access allowed');
/**
* File Uploading Class
@@ -36,39 +37,224 @@
*/
class CI_Upload {
+ /**
+ * Maximum file size
+ *
+ * @var int
+ */
public $max_size = 0;
+
+ /**
+ * Maximum image width
+ *
+ * @var int
+ */
public $max_width = 0;
+
+ /**
+ * Maximum image height
+ *
+ * @var int
+ */
public $max_height = 0;
+
+ /**
+ * Minimum image width
+ *
+ * @var int
+ */
+ public $min_width = 0;
+
+ /**
+ * Minimum image height
+ *
+ * @var int
+ */
+ public $min_height = 0;
+
+ /**
+ * Maximum filename length
+ *
+ * @var int
+ */
public $max_filename = 0;
+
+ /**
+ * Maximum duplicate filename increment ID
+ *
+ * @var int
+ */
public $max_filename_increment = 100;
+
+ /**
+ * Allowed file types
+ *
+ * @var string
+ */
public $allowed_types = '';
+
+ /**
+ * Temporary filename
+ *
+ * @var string
+ */
public $file_temp = '';
+
+ /**
+ * Filename
+ *
+ * @var string
+ */
public $file_name = '';
+
+ /**
+ * Original filename
+ *
+ * @var string
+ */
public $orig_name = '';
+
+ /**
+ * File type
+ *
+ * @var string
+ */
public $file_type = '';
- public $file_size = '';
+
+ /**
+ * File size
+ *
+ * @var int
+ */
+ public $file_size = NULL;
+
+ /**
+ * Filename extension
+ *
+ * @var string
+ */
public $file_ext = '';
+
+ /**
+ * Upload path
+ *
+ * @var string
+ */
public $upload_path = '';
+
+ /**
+ * Overwrite flag
+ *
+ * @var bool
+ */
public $overwrite = FALSE;
+
+ /**
+ * Obfuscate filename flag
+ *
+ * @var bool
+ */
public $encrypt_name = FALSE;
+
+ /**
+ * Is image flag
+ *
+ * @var bool
+ */
public $is_image = FALSE;
- public $image_width = '';
- public $image_height = '';
+
+ /**
+ * Image width
+ *
+ * @var int
+ */
+ public $image_width = NULL;
+
+ /**
+ * Image height
+ *
+ * @var int
+ */
+ public $image_height = NULL;
+
+ /**
+ * Image type
+ *
+ * @var string
+ */
public $image_type = '';
+
+ /**
+ * Image size string
+ *
+ * @var string
+ */
public $image_size_str = '';
+
+ /**
+ * Error messages list
+ *
+ * @var array
+ */
public $error_msg = array();
+
+ /**
+ * MIME types list
+ *
+ * @var array
+ */
public $mimes = array();
+
+ /**
+ * Remove spaces flag
+ *
+ * @var bool
+ */
public $remove_spaces = TRUE;
+
+ /**
+ * MIME detection flag
+ *
+ * @var bool
+ */
+ public $detect_mime = TRUE;
+
+ /**
+ * XSS filter flag
+ *
+ * @var bool
+ */
public $xss_clean = FALSE;
+
+ /**
+ * Temporary filename prefix
+ *
+ * @var string
+ */
public $temp_prefix = 'temp_file_';
+
+ /**
+ * Filename sent by the client
+ *
+ * @var bool
+ */
public $client_name = '';
+ // --------------------------------------------------------------------
+
+ /**
+ * Filename override
+ *
+ * @var string
+ */
protected $_file_name_override = '';
+ // --------------------------------------------------------------------
+
/**
* Constructor
*
- * @param array
+ * @param array $props
* @return void
*/
public function __construct($props = array())
@@ -78,6 +264,8 @@ class CI_Upload {
$this->initialize($props);
}
+ $this->mimes =& get_mimes();
+
log_message('debug', 'Upload Class Initialized');
}
@@ -86,7 +274,7 @@ class CI_Upload {
/**
* Initialize preferences
*
- * @param array
+ * @param array $config
* @return void
*/
public function initialize($config = array())
@@ -95,6 +283,8 @@ class CI_Upload {
'max_size' => 0,
'max_width' => 0,
'max_height' => 0,
+ 'min_width' => 0,
+ 'min_height' => 0,
'max_filename' => 0,
'max_filename_increment' => 100,
'allowed_types' => '',
@@ -102,25 +292,24 @@ class CI_Upload {
'file_name' => '',
'orig_name' => '',
'file_type' => '',
- 'file_size' => '',
+ 'file_size' => NULL,
'file_ext' => '',
'upload_path' => '',
'overwrite' => FALSE,
'encrypt_name' => FALSE,
'is_image' => FALSE,
- 'image_width' => '',
- 'image_height' => '',
+ 'image_width' => NULL,
+ 'image_height' => NULL,
'image_type' => '',
'image_size_str' => '',
'error_msg' => array(),
- 'mimes' => array(),
'remove_spaces' => TRUE,
+ 'detect_mime' => TRUE,
'xss_clean' => FALSE,
'temp_prefix' => 'temp_file_',
'client_name' => ''
);
-
foreach ($defaults as $key => $val)
{
if (isset($config[$key]))
@@ -151,6 +340,7 @@ class CI_Upload {
/**
* Perform the file upload
*
+ * @param string $field
* @return bool
*/
public function do_upload($field = 'userfile')
@@ -208,7 +398,13 @@ class CI_Upload {
// Set the uploaded data as class variables
$this->file_temp = $_FILES[$field]['tmp_name'];
$this->file_size = $_FILES[$field]['size'];
- $this->_file_mime_type($_FILES[$field]);
+
+ // Skip MIME type detection?
+ if ($this->detect_mime !== FALSE)
+ {
+ $this->_file_mime_type($_FILES[$field]);
+ }
+
$this->file_type = preg_replace('/^(.+?);.*$/', '\\1', $this->file_type);
$this->file_type = strtolower(trim(stripslashes($this->file_type), '"'));
$this->file_name = $this->_prep_filename($_FILES[$field]['name']);
@@ -223,7 +419,7 @@ class CI_Upload {
}
// if we're overriding, let's now make sure the new name and type is allowed
- if ($this->_file_name_override != '')
+ if ($this->_file_name_override !== '')
{
$this->file_name = $this->_prep_filename($this->_file_name_override);
@@ -276,7 +472,7 @@ class CI_Upload {
}
// Remove white spaces in the name
- if ($this->remove_spaces == TRUE)
+ if ($this->remove_spaces === TRUE)
{
$this->file_name = preg_replace('/\s+/', '_', $this->file_name);
}
@@ -289,7 +485,7 @@ class CI_Upload {
*/
$this->orig_name = $this->file_name;
- if ($this->overwrite == FALSE)
+ if ($this->overwrite === FALSE)
{
$this->file_name = $this->set_filename($this->upload_path, $this->file_name);
@@ -346,11 +542,12 @@ class CI_Upload {
* Returns an associative array containing all of the information
* related to the upload, allowing the developer easy access in one array.
*
- * @return array
+ * @param string $index
+ * @return mixed
*/
- public function data()
+ public function data($index = NULL)
{
- return array(
+ $data = array(
'file_name' => $this->file_name,
'file_type' => $this->file_type,
'file_path' => $this->upload_path,
@@ -366,6 +563,13 @@ class CI_Upload {
'image_type' => $this->image_type,
'image_size_str' => $this->image_size_str,
);
+
+ if ( ! empty($index))
+ {
+ return isset($data[$index]) ? $data[$index] : NULL;
+ }
+
+ return $data;
}
// --------------------------------------------------------------------
@@ -373,7 +577,7 @@ class CI_Upload {
/**
* Set Upload Path
*
- * @param string
+ * @param string $path
* @return void
*/
public function set_upload_path($path)
@@ -391,13 +595,13 @@ class CI_Upload {
* existence of a file with the same name. If found, it will append a
* number to the end of the filename to avoid overwriting a pre-existing file.
*
- * @param string
- * @param string
+ * @param string $path
+ * @param string $filename
* @return string
*/
public function set_filename($path, $filename)
{
- if ($this->encrypt_name == TRUE)
+ if ($this->encrypt_name === TRUE)
{
mt_srand();
$filename = md5(uniqid(mt_rand())).$this->file_ext;
@@ -420,7 +624,7 @@ class CI_Upload {
}
}
- if ($new_filename == '')
+ if ($new_filename === '')
{
$this->set_error('upload_bad_filename');
return FALSE;
@@ -436,7 +640,7 @@ class CI_Upload {
/**
* Set Maximum File Size
*
- * @param int
+ * @param int $n
* @return void
*/
public function set_max_filesize($n)
@@ -449,7 +653,7 @@ class CI_Upload {
/**
* Set Maximum File Name Length
*
- * @param int
+ * @param int $n
* @return void
*/
public function set_max_filename($n)
@@ -462,7 +666,7 @@ class CI_Upload {
/**
* Set Maximum Image Width
*
- * @param int
+ * @param int $n
* @return void
*/
public function set_max_width($n)
@@ -475,7 +679,7 @@ class CI_Upload {
/**
* Set Maximum Image Height
*
- * @param int
+ * @param int $n
* @return void
*/
public function set_max_height($n)
@@ -486,9 +690,35 @@ class CI_Upload {
// --------------------------------------------------------------------
/**
+ * Set minimum image width
+ *
+ * @param int $n
+ * @return void
+ */
+ public function set_min_width($n)
+ {
+ $this->min_width = ((int) $n < 0) ? 0 : (int) $n;
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Set minimum image height
+ *
+ * @param int $n
+ * @return void
+ */
+ public function set_min_height($n)
+ {
+ $this->min_height = ((int) $n < 0) ? 0 : (int) $n;
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
* Set Allowed File Types
*
- * @param string
+ * @param string $types
* @return void
*/
public function set_allowed_types($types)
@@ -508,7 +738,7 @@ class CI_Upload {
*
* Uses GD to determine the width/height/type of image
*
- * @param string
+ * @param string $path
* @return void
*/
public function set_image_properties($path = '')
@@ -540,12 +770,12 @@ class CI_Upload {
* Enables the XSS flag so that the file that was uploaded
* will be run through the XSS filter.
*
- * @param bool
+ * @param bool $flag
* @return void
*/
public function set_xss_clean($flag = FALSE)
{
- $this->xss_clean = ($flag == TRUE);
+ $this->xss_clean = ($flag === TRUE);
}
// --------------------------------------------------------------------
@@ -582,7 +812,7 @@ class CI_Upload {
/**
* Verify that the filetype is allowed
*
- * @param bool
+ * @param bool $ignore_mime
* @return bool
*/
public function is_allowed_filetype($ignore_mime = FALSE)
@@ -641,7 +871,7 @@ class CI_Upload {
*/
public function is_allowed_filesize()
{
- return ($this->max_size == 0 OR $this->max_size > $this->file_size);
+ return ($this->max_size === 0 OR $this->max_size > $this->file_size);
}
// --------------------------------------------------------------------
@@ -671,6 +901,16 @@ class CI_Upload {
{
return FALSE;
}
+
+ if ($this->min_width > 0 && $D[0] < $this->min_width)
+ {
+ return FALSE;
+ }
+
+ if ($this->min_height > 0 && $D[1] < $this->min_height)
+ {
+ return FALSE;
+ }
}
return TRUE;
@@ -687,13 +927,13 @@ class CI_Upload {
*/
public function validate_upload_path()
{
- if ($this->upload_path == '')
+ if ($this->upload_path === '')
{
$this->set_error('upload_no_filepath');
return FALSE;
}
- if (function_exists('realpath') && @realpath($this->upload_path) !== FALSE)
+ if (@realpath($this->upload_path) !== FALSE)
{
$this->upload_path = str_replace('\\', '/', realpath($this->upload_path));
}
@@ -719,13 +959,13 @@ class CI_Upload {
/**
* Extract the file extension
*
- * @param string
+ * @param string $filename
* @return string
*/
public function get_extension($filename)
{
$x = explode('.', $filename);
- return '.'.end($x);
+ return (count($x) !== 1) ? '.'.end($x) : '';
}
// --------------------------------------------------------------------
@@ -733,7 +973,7 @@ class CI_Upload {
/**
* Clean the file name for security
*
- * @param string
+ * @param string $filename
* @return string
*/
public function clean_file_name($filename)
@@ -747,6 +987,8 @@ class CI_Upload {
';',
'?',
'/',
+ '!',
+ '#',
'%20',
'%22',
'%3c', // <
@@ -771,7 +1013,8 @@ class CI_Upload {
/**
* Limit the File Name Length
*
- * @param string
+ * @param string $filename
+ * @param int $length
* @return string
*/
public function limit_filename_length($filename, $length)
@@ -812,17 +1055,17 @@ class CI_Upload {
return FALSE;
}
- if (function_exists('memory_get_usage') && memory_get_usage() && ini_get('memory_limit') != '')
+ if (memory_get_usage() && ($memory_limit = ini_get('memory_limit')))
{
- $current = ini_get('memory_limit') * 1024 * 1024;
+ $memory_limit *= 1024 * 1024;
// There was a bug/behavioural change in PHP 5.2, where numbers over one million get output
// into scientific notation. number_format() ensures this number is an integer
// http://bugs.php.net/bug.php?id=43053
- $new_memory = number_format(ceil(filesize($file) + $current), 0, '.', '');
+ $memory_limit = number_format(ceil(filesize($file) + $memory_limit), 0, '.', '');
- ini_set('memory_limit', $new_memory); // When an integer is used, the value is measured in bytes. - PHP.net
+ ini_set('memory_limit', $memory_limit); // When an integer is used, the value is measured in bytes. - PHP.net
}
// If the file being uploaded is an image, then we should have no problem with XSS attacks (in theory), but
@@ -846,10 +1089,8 @@ class CI_Upload {
// <a, <body, <head, <html, <img, <plaintext, <pre, <script, <table, <title
// title is basically just in SVG, but we filter it anyhow
- if ( ! preg_match('/<(a|body|head|html|img|plaintext|pre|script|table|title)[\s>]/i', $opening_bytes))
- {
- return TRUE; // its an image, no "triggers" detected in the first 256 bytes, we're good
- }
+ // if its an image or no "triggers" detected in the first 256 bytes - we're good
+ return ! preg_match('/<(a|body|head|html|img|plaintext|pre|script|table|title)[\s>]/i', $opening_bytes);
}
if (($data = @file_get_contents($file)) === FALSE)
@@ -866,7 +1107,7 @@ class CI_Upload {
/**
* Set an error message
*
- * @param string
+ * @param string $msg
* @return void
*/
public function set_error($msg)
@@ -878,14 +1119,14 @@ class CI_Upload {
{
foreach ($msg as $val)
{
- $msg = ($CI->lang->line($val) == FALSE) ? $val : $CI->lang->line($val);
+ $msg = ($CI->lang->line($val) === FALSE) ? $val : $CI->lang->line($val);
$this->error_msg[] = $msg;
log_message('error', $msg);
}
}
else
{
- $msg = ($CI->lang->line($msg) == FALSE) ? $msg : $CI->lang->line($msg);
+ $msg = ($CI->lang->line($msg) === FALSE) ? $msg : $CI->lang->line($msg);
$this->error_msg[] = $msg;
log_message('error', $msg);
}
@@ -896,8 +1137,8 @@ class CI_Upload {
/**
* Display the error message
*
- * @param string
- * @param string
+ * @param string $open
+ * @param string $close
* @return string
*/
public function display_errors($open = '<p>', $close = '</p>')
@@ -913,31 +1154,11 @@ class CI_Upload {
* This is a list of mime types. We use it to validate
* the "allowed types" set by the developer
*
- * @param string
+ * @param string $mime
* @return string
*/
public function mimes_types($mime)
{
- global $mimes;
-
- if (count($this->mimes) == 0)
- {
- if (defined('ENVIRONMENT') && is_file(APPPATH.'config/'.ENVIRONMENT.'/mimes.php'))
- {
- include(APPPATH.'config/'.ENVIRONMENT.'/mimes.php');
- }
- elseif (is_file(APPPATH.'config/mimes.php'))
- {
- include(APPPATH.'config/mimes.php');
- }
- else
- {
- return FALSE;
- }
-
- $this->mimes = $mimes;
- }
-
return isset($this->mimes[$mime]) ? $this->mimes[$mime] : FALSE;
}
@@ -946,15 +1167,17 @@ class CI_Upload {
/**
* Prep Filename
*
- * Prevents possible script execution from Apache's handling of files multiple extensions
- * http://httpd.apache.org/docs/1.3/mod/mod_mime.html#multipleext
+ * Prevents possible script execution from Apache's handling
+ * of files' multiple extensions.
+ *
+ * @link http://httpd.apache.org/docs/1.3/mod/mod_mime.html#multipleext
*
- * @param string
+ * @param string $filename
* @return string
*/
protected function _prep_filename($filename)
{
- if (strpos($filename, '.') === FALSE OR $this->allowed_types == '*')
+ if (strpos($filename, '.') === FALSE OR $this->allowed_types === '*')
{
return $filename;
}
@@ -986,7 +1209,7 @@ class CI_Upload {
* Detects the (actual) MIME type of the uploaded file, if possible.
* The input array is expected to be $_FILES[$field]
*
- * @param array
+ * @param array $file
* @return void
*/
protected function _file_mime_type($file)
@@ -1001,7 +1224,7 @@ class CI_Upload {
*/
if (function_exists('finfo_file'))
{
- $finfo = finfo_open(FILEINFO_MIME);
+ $finfo = @finfo_open(FILEINFO_MIME);
if (is_resource($finfo)) // It is possible that a FALSE value is returned, if there is no magic MIME database file found on the system
{
$mime = @finfo_file($finfo, $file['tmp_name']);
@@ -1032,9 +1255,11 @@ class CI_Upload {
*/
if (DIRECTORY_SEPARATOR !== '\\')
{
- $cmd = 'file --brief --mime ' . escapeshellarg($file['tmp_name']) . ' 2>&1';
+ $cmd = function_exists('escapeshellarg')
+ ? 'file --brief --mime '.escapeshellarg($file['tmp_name']).' 2>&1'
+ : 'file --brief --mime '.$file['tmp_name'].' 2>&1';
- if (function_exists('exec'))
+ if (function_usable('exec'))
{
/* This might look confusing, as $mime is being populated with all of the output when set in the second parameter.
* However, we only neeed the last line, which is the actual return value of exec(), and as such - it overwrites
@@ -1049,7 +1274,7 @@ class CI_Upload {
}
}
- if ( (bool) @ini_get('safe_mode') === FALSE && function_exists('shell_exec'))
+ if ( (bool) @ini_get('safe_mode') === FALSE && function_usable('shell_exec'))
{
$mime = @shell_exec($cmd);
if (strlen($mime) > 0)
@@ -1063,7 +1288,7 @@ class CI_Upload {
}
}
- if (function_exists('popen'))
+ if (function_usable('popen'))
{
$proc = @popen($cmd, 'r');
if (is_resource($proc))
diff --git a/system/libraries/User_agent.php b/system/libraries/User_agent.php
index b8e0d37fb..659371ab5 100644
--- a/system/libraries/User_agent.php
+++ b/system/libraries/User_agent.php
@@ -1,4 +1,4 @@
-<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');
+<?php
/**
* CodeIgniter
*
@@ -24,6 +24,7 @@
* @since Version 1.0
* @filesource
*/
+defined('BASEPATH') OR exit('No direct script access allowed');
/**
* User Agent Class
@@ -38,25 +39,110 @@
*/
class CI_User_agent {
- public $agent = NULL;
+ /**
+ * Current user-agent
+ *
+ * @var string
+ */
+ public $agent = NULL;
+
+ /**
+ * Flag for if the user-agent belongs to a browser
+ *
+ * @var bool
+ */
+ public $is_browser = FALSE;
+
+ /**
+ * Flag for if the user-agent is a robot
+ *
+ * @var bool
+ */
+ public $is_robot = FALSE;
+
+ /**
+ * Flag for if the user-agent is a mobile browser
+ *
+ * @var bool
+ */
+ public $is_mobile = FALSE;
+
+ /**
+ * Languages accepted by the current user agent
+ *
+ * @var array
+ */
+ public $languages = array();
+
+ /**
+ * Character sets accepted by the current user agent
+ *
+ * @var array
+ */
+ public $charsets = array();
+
+ /**
+ * List of platforms to compare against current user agent
+ *
+ * @var array
+ */
+ public $platforms = array();
+
+ /**
+ * List of browsers to compare against current user agent
+ *
+ * @var array
+ */
+ public $browsers = array();
+
+ /**
+ * List of mobile browsers to compare against current user agent
+ *
+ * @var array
+ */
+ public $mobiles = array();
- public $is_browser = FALSE;
- public $is_robot = FALSE;
- public $is_mobile = FALSE;
+ /**
+ * List of robots to compare against current user agent
+ *
+ * @var array
+ */
+ public $robots = array();
+
+ /**
+ * Current user-agent platform
+ *
+ * @var string
+ */
+ public $platform = '';
+
+ /**
+ * Current user-agent browser
+ *
+ * @var string
+ */
+ public $browser = '';
- public $languages = array();
- public $charsets = array();
+ /**
+ * Current user-agent version
+ *
+ * @var string
+ */
+ public $version = '';
- public $platforms = array();
- public $browsers = array();
- public $mobiles = array();
- public $robots = array();
+ /**
+ * Current user-agent mobile name
+ *
+ * @var string
+ */
+ public $mobile = '';
- public $platform = '';
- public $browser = '';
- public $version = '';
- public $mobile = '';
- public $robot = '';
+ /**
+ * Current user-agent robot name
+ *
+ * @var string
+ */
+ public $robot = '';
/**
* Constructor
@@ -224,6 +310,7 @@ class CI_User_agent {
{
$this->is_robot = TRUE;
$this->robot = $val;
+ $this->_set_mobile();
return TRUE;
}
}
@@ -245,7 +332,7 @@ class CI_User_agent {
{
foreach ($this->mobiles as $key => $val)
{
- if (FALSE !== (strpos(strtolower($this->agent), $key)))
+ if (FALSE !== (stripos($this->agent, $key)))
{
$this->is_mobile = TRUE;
$this->mobile = $val;
@@ -302,6 +389,7 @@ class CI_User_agent {
/**
* Is Browser
*
+ * @param string $key
* @return bool
*/
public function is_browser($key = NULL)
@@ -326,6 +414,7 @@ class CI_User_agent {
/**
* Is Robot
*
+ * @param string $key
* @return bool
*/
public function is_robot($key = NULL)
@@ -350,6 +439,7 @@ class CI_User_agent {
/**
* Is Mobile
*
+ * @param string $key
* @return bool
*/
public function is_mobile($key = NULL)
@@ -378,7 +468,13 @@ class CI_User_agent {
*/
public function is_referral()
{
- return ! empty($_SERVER['HTTP_REFERER']);
+ if (empty($_SERVER['HTTP_REFERER']))
+ {
+ return FALSE;
+ }
+
+ $referer = parse_url($_SERVER['HTTP_REFERER']);
+ return ! (empty($referer['host']) && strpos(config_item('base_url'), $referer['host']) !== FALSE);
}
// --------------------------------------------------------------------
@@ -503,6 +599,7 @@ class CI_User_agent {
/**
* Test for a particular language
*
+ * @param string $lang
* @return bool
*/
public function accept_lang($lang = 'en')
@@ -515,6 +612,7 @@ class CI_User_agent {
/**
* Test for a particular character set
*
+ * @param string $charset
* @return bool
*/
public function accept_charset($charset = 'utf-8')
diff --git a/system/libraries/Xmlrpc.php b/system/libraries/Xmlrpc.php
index fea560c2e..529089914 100644
--- a/system/libraries/Xmlrpc.php
+++ b/system/libraries/Xmlrpc.php
@@ -1,4 +1,4 @@
-<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');
+<?php
/**
* CodeIgniter
*
@@ -24,6 +24,14 @@
* @since Version 1.0
* @filesource
*/
+defined('BASEPATH') OR exit('No direct script access allowed');
+
+if ( ! function_exists('xml_parser_create'))
+{
+ show_error('Your PHP installation does not support XML');
+}
+
+// ------------------------------------------------------------------------
/**
* XML-RPC request handler class
@@ -34,56 +42,212 @@
* @author EllisLab Dev Team
* @link http://codeigniter.com/user_guide/libraries/xmlrpc.html
*/
-
-if ( ! function_exists('xml_parser_create'))
-{
- show_error('Your PHP installation does not support XML');
-}
-
-// ------------------------------------------------------------------------
-
class CI_Xmlrpc {
- public $debug = FALSE; // Debugging on or off
+ /**
+ * Debug flag
+ *
+ * @var bool
+ */
+ public $debug = FALSE;
+
+ /**
+ * I4 data type
+ *
+ * @var string
+ */
public $xmlrpcI4 = 'i4';
+
+ /**
+ * Integer data type
+ *
+ * @var string
+ */
public $xmlrpcInt = 'int';
+
+ /**
+ * Boolean data type
+ *
+ * @var string
+ */
public $xmlrpcBoolean = 'boolean';
+
+ /**
+ * Double data type
+ *
+ * @var string
+ */
public $xmlrpcDouble = 'double';
+
+ /**
+ * String data type
+ *
+ * @var string
+ */
public $xmlrpcString = 'string';
+
+ /**
+ * DateTime format
+ *
+ * @var string
+ */
public $xmlrpcDateTime = 'dateTime.iso8601';
+
+ /**
+ * Base64 data type
+ *
+ * @var string
+ */
public $xmlrpcBase64 = 'base64';
+
+ /**
+ * Array data type
+ *
+ * @var string
+ */
public $xmlrpcArray = 'array';
+
+ /**
+ * Struct data type
+ *
+ * @var string
+ */
public $xmlrpcStruct = 'struct';
+ /**
+ * Data types list
+ *
+ * @var array
+ */
public $xmlrpcTypes = array();
+
+ /**
+ * Valid parents list
+ *
+ * @var array
+ */
public $valid_parents = array();
- public $xmlrpcerr = array(); // Response numbers
- public $xmlrpcstr = array(); // Response strings
+ /**
+ * Response error numbers list
+ *
+ * @var array
+ */
+ public $xmlrpcerr = array();
+
+ /**
+ * Response error messages list
+ *
+ * @var string[]
+ */
+ public $xmlrpcstr = array();
+
+ /**
+ * Encoding charset
+ *
+ * @var string
+ */
public $xmlrpc_defencoding = 'UTF-8';
+
+ /**
+ * XML-RPC client name
+ *
+ * @var string
+ */
public $xmlrpcName = 'XML-RPC for CodeIgniter';
+
+ /**
+ * XML-RPC version
+ *
+ * @var string
+ */
public $xmlrpcVersion = '1.1';
- public $xmlrpcerruser = 800; // Start of user errors
- public $xmlrpcerrxml = 100; // Start of XML Parse errors
- public $xmlrpc_backslash = ''; // formulate backslashes for escaping regexp
+ /**
+ * Start of user errors
+ *
+ * @var int
+ */
+ public $xmlrpcerruser = 800;
+
+ /**
+ * Start of XML parse errors
+ *
+ * @var int
+ */
+ public $xmlrpcerrxml = 100;
+
+ /**
+ * Backslash replacement value
+ *
+ * @var string
+ */
+ public $xmlrpc_backslash = '';
+
+ /**
+ * XML-RPC Client object
+ *
+ * @var object
+ */
public $client;
+
+ /**
+ * XML-RPC Method name
+ *
+ * @var string
+ */
public $method;
+
+ /**
+ * XML-RPC Data
+ *
+ * @var array
+ */
public $data;
+
+ /**
+ * XML-RPC Message
+ *
+ * @var string
+ */
public $message = '';
- public $error = ''; // Error string for request
+
+ /**
+ * Request error message
+ *
+ * @var string
+ */
+ public $error = '';
+
+ /**
+ * XML-RPC result object
+ *
+ * @var object
+ */
public $result;
- public $response = array(); // Response from remote server
+ /**
+ * XML-RPC Reponse
+ *
+ * @var array
+ */
+ public $response = array(); // Response from remote server
+
+ /**
+ * XSS Filter flag
+ *
+ * @var bool
+ */
public $xss_clean = TRUE;
+ // --------------------------------------------------------------------
/**
* Constructor
*
* Initializes property default values
*
- * @param array
+ * @param array $config
* @return void
*/
public function __construct($config = array())
@@ -101,34 +265,33 @@ class CI_Xmlrpc {
$this->xmlrpcBase64 => '1',
$this->xmlrpcArray => '2',
$this->xmlrpcStruct => '3'
- );
+ );
// Array of Valid Parents for Various XML-RPC elements
- $this->valid_parents = array('BOOLEAN' => array('VALUE'),
- 'I4' => array('VALUE'),
- 'INT' => array('VALUE'),
- 'STRING' => array('VALUE'),
- 'DOUBLE' => array('VALUE'),
- 'DATETIME.ISO8601' => array('VALUE'),
- 'BASE64' => array('VALUE'),
- 'ARRAY' => array('VALUE'),
- 'STRUCT' => array('VALUE'),
- 'PARAM' => array('PARAMS'),
- 'METHODNAME' => array('METHODCALL'),
- 'PARAMS' => array('METHODCALL', 'METHODRESPONSE'),
- 'MEMBER' => array('STRUCT'),
- 'NAME' => array('MEMBER'),
- 'DATA' => array('ARRAY'),
- 'FAULT' => array('METHODRESPONSE'),
- 'VALUE' => array('MEMBER', 'DATA', 'PARAM', 'FAULT')
- );
-
+ $this->valid_parents = array('BOOLEAN' => array('VALUE'),
+ 'I4' => array('VALUE'),
+ 'INT' => array('VALUE'),
+ 'STRING' => array('VALUE'),
+ 'DOUBLE' => array('VALUE'),
+ 'DATETIME.ISO8601' => array('VALUE'),
+ 'BASE64' => array('VALUE'),
+ 'ARRAY' => array('VALUE'),
+ 'STRUCT' => array('VALUE'),
+ 'PARAM' => array('PARAMS'),
+ 'METHODNAME' => array('METHODCALL'),
+ 'PARAMS' => array('METHODCALL', 'METHODRESPONSE'),
+ 'MEMBER' => array('STRUCT'),
+ 'NAME' => array('MEMBER'),
+ 'DATA' => array('ARRAY'),
+ 'FAULT' => array('METHODRESPONSE'),
+ 'VALUE' => array('MEMBER', 'DATA', 'PARAM', 'FAULT')
+ );
// XML-RPC Responses
$this->xmlrpcerr['unknown_method'] = '1';
$this->xmlrpcstr['unknown_method'] = 'This is not a known method for this XML-RPC Server';
$this->xmlrpcerr['invalid_return'] = '2';
- $this->xmlrpcstr['invalid_return'] = 'The XML data received was either invalid or not in the correct form for XML-RPC. Turn on debugging to examine the XML data further.';
+ $this->xmlrpcstr['invalid_return'] = 'The XML data received was either invalid or not in the correct form for XML-RPC. Turn on debugging to examine the XML data further.';
$this->xmlrpcerr['incorrect_params'] = '3';
$this->xmlrpcstr['incorrect_params'] = 'Incorrect parameters were passed to method';
$this->xmlrpcerr['introspect_unknown'] = '4';
@@ -136,7 +299,7 @@ class CI_Xmlrpc {
$this->xmlrpcerr['http_error'] = '5';
$this->xmlrpcstr['http_error'] = "Did not receive a '200 OK' response from remote server.";
$this->xmlrpcerr['no_data'] = '6';
- $this->xmlrpcstr['no_data'] ='No data received from server.';
+ $this->xmlrpcstr['no_data'] = 'No data received from server.';
$this->initialize($config);
@@ -148,7 +311,7 @@ class CI_Xmlrpc {
/**
* Initialize
*
- * @param array
+ * @param array $config
* @return void
*/
public function initialize($config = array())
@@ -170,11 +333,13 @@ class CI_Xmlrpc {
/**
* Parse server URL
*
- * @param string url
- * @param int port
+ * @param string $url
+ * @param int $port
+ * @param string $proxy
+ * @param int $proxy_port
* @return void
*/
- public function server($url, $port = 80)
+ public function server($url, $port = 80, $proxy = FALSE, $proxy_port = 8080)
{
if (strpos($url, 'http') !== 0)
{
@@ -190,7 +355,7 @@ class CI_Xmlrpc {
$path .= '?'.$parts['query'];
}
- $this->client = new XML_RPC_Client($path, $parts['host'], $port);
+ $this->client = new XML_RPC_Client($path, $parts['host'], $port, $proxy, $proxy_port);
}
// --------------------------------------------------------------------
@@ -198,7 +363,7 @@ class CI_Xmlrpc {
/**
* Set Timeout
*
- * @param int seconds
+ * @param int $seconds
* @return void
*/
public function timeout($seconds = 5)
@@ -214,7 +379,7 @@ class CI_Xmlrpc {
/**
* Set Methods
*
- * @param string method name
+ * @param string $function Method name
* @return void
*/
public function method($function)
@@ -227,7 +392,7 @@ class CI_Xmlrpc {
/**
* Take Array of Data and Create Objects
*
- * @param array
+ * @param array $incoming
* @return void
*/
public function request($incoming)
@@ -251,12 +416,12 @@ class CI_Xmlrpc {
/**
* Set Debug
*
- * @param bool
+ * @param bool $flag
* @return void
*/
public function set_debug($flag = TRUE)
{
- $this->debug = ($flag == TRUE);
+ $this->debug = ($flag === TRUE);
}
// --------------------------------------------------------------------
@@ -264,7 +429,7 @@ class CI_Xmlrpc {
/**
* Values Parsing
*
- * @param mixed
+ * @param mixed $value
* @return object
*/
public function values_parsing($value)
@@ -277,7 +442,7 @@ class CI_Xmlrpc {
}
else
{
- if (is_array($value[0]) && ($value[1] == 'struct' OR $value[1] == 'array'))
+ if (is_array($value[0]) && ($value[1] === 'struct' OR $value[1] === 'array'))
{
while (list($k) = each($value[0]))
{
@@ -347,8 +512,8 @@ class CI_Xmlrpc {
/**
* Sends an Error Message for Server Request
*
- * @param int
- * @param string
+ * @param int $number
+ * @param string $message
* @return object
*/
public function send_error_message($number, $message)
@@ -361,7 +526,7 @@ class CI_Xmlrpc {
/**
* Send Response for Server Request
*
- * @param array
+ * @param array $response
* @return object
*/
public function send_response($response)
@@ -382,29 +547,90 @@ class CI_Xmlrpc {
*/
class XML_RPC_Client extends CI_Xmlrpc
{
+ /**
+ * Path
+ *
+ * @var string
+ */
public $path = '';
+
+ /**
+ * Server hostname
+ *
+ * @var string
+ */
public $server = '';
+
+ /**
+ * Server port
+ *
+ * @var int
+ */
public $port = 80;
+
+ /**
+ * Proxy hostname
+ *
+ * @var string
+ */
+ public $proxy = FALSE;
+
+ /**
+ * Proxy port
+ *
+ * @var int
+ */
+ public $proxy_port = 8080;
+
+ /**
+ * Error number
+ *
+ * @var string
+ */
public $errno = '';
+
+ /**
+ * Error message
+ *
+ * @var string
+ */
public $errstring = '';
+
+ /**
+ * Timeout in seconds
+ *
+ * @var int
+ */
public $timeout = 5;
+
+ /**
+ * No Multicall flag
+ *
+ * @var bool
+ */
public $no_multicall = FALSE;
+ // --------------------------------------------------------------------
+
/**
* Constructor
*
- * @param string
- * @param object
- * @param int
+ * @param string $path
+ * @param object $server
+ * @param int $port
+ * @param string $proxy
+ * @param int $proxy_port
* @return void
*/
- public function __construct($path, $server, $port = 80)
+ public function __construct($path, $server, $port = 80, $proxy = FALSE, $proxy_port = 8080)
{
parent::__construct();
$this->port = $port;
$this->server = $server;
$this->path = $path;
+ $this->proxy = $proxy;
+ $this->proxy_port = $proxy_port;
}
// --------------------------------------------------------------------
@@ -412,7 +638,7 @@ class XML_RPC_Client extends CI_Xmlrpc
/**
* Send message
*
- * @param mixed
+ * @param mixed $msg
* @return object
*/
public function send($msg)
@@ -431,12 +657,23 @@ class XML_RPC_Client extends CI_Xmlrpc
/**
* Send payload
*
- * @param object
+ * @param object $msg
* @return object
*/
public function sendPayload($msg)
{
- $fp = @fsockopen($this->server, $this->port,$this->errno, $this->errstr, $this->timeout);
+ if ($this->proxy === FALSE)
+ {
+ $server = $this->server;
+ $port = $this->port;
+ }
+ else
+ {
+ $server = $this->proxy;
+ $port = $this->proxy_port;
+ }
+
+ $fp = @fsockopen($server, $port, $this->errno, $this->errstring, $this->timeout);
if ( ! is_resource($fp))
{
@@ -458,7 +695,7 @@ class XML_RPC_Client extends CI_Xmlrpc
.'Content-Length: '.strlen($msg->payload).$r.$r
.$msg->payload;
- if ( ! fputs($fp, $op, strlen($op)))
+ if ( ! fwrite($fp, $op, strlen($op)))
{
error_log($this->xmlrpcstr['http_error']);
return new XML_RPC_Response(0, $this->xmlrpcerr['http_error'], $this->xmlrpcstr['http_error']);
@@ -480,23 +717,55 @@ class XML_RPC_Client extends CI_Xmlrpc
*/
class XML_RPC_Response
{
+
+ /**
+ * Value
+ *
+ * @var mixed
+ */
public $val = 0;
+
+ /**
+ * Error number
+ *
+ * @var int
+ */
public $errno = 0;
+
+ /**
+ * Error message
+ *
+ * @var string
+ */
public $errstr = '';
+
+ /**
+ * Headers list
+ *
+ * @var array
+ */
public $headers = array();
+
+ /**
+ * XSS Filter flag
+ *
+ * @var bool
+ */
public $xss_clean = TRUE;
+ // --------------------------------------------------------------------
+
/**
* Constructor
*
- * @param mixed
- * @param int
- * @param string
+ * @param mixed $val
+ * @param int $code
+ * @param string $fstr
* @return void
*/
public function __construct($val, $code = 0, $fstr = '')
{
- if ($code != 0)
+ if ($code !== 0)
{
// error
$this->errno = $code;
@@ -636,11 +905,11 @@ class XML_RPC_Response
{
$kind = $xmlrpc_val->kindOf();
- if ($kind == 'scalar')
+ if ($kind === 'scalar')
{
return $xmlrpc_val->scalarval();
}
- elseif ($kind == 'array')
+ elseif ($kind === 'array')
{
reset($xmlrpc_val->me);
$b = current($xmlrpc_val->me);
@@ -652,7 +921,7 @@ class XML_RPC_Response
}
return $arr;
}
- elseif ($kind == 'struct')
+ elseif ($kind === 'struct')
{
reset($xmlrpc_val->me['struct']);
$arr = array();
@@ -676,11 +945,11 @@ class XML_RPC_Response
*/
public function iso8601_decode($time, $utc = FALSE)
{
- // return a time in the localtime, or UTC
+ // Return a time in the localtime, or UTC
$t = 0;
if (preg_match('/([0-9]{4})([0-9]{2})([0-9]{2})T([0-9]{2}):([0-9]{2}):([0-9]{2})/', $time, $regs))
{
- $fnc = ($utc == TRUE) ? 'gmmktime' : 'mktime';
+ $fnc = ($utc === TRUE) ? 'gmmktime' : 'mktime';
$t = $fnc($regs[4], $regs[5], $regs[6], $regs[2], $regs[3], $regs[1]);
}
return $t;
@@ -697,16 +966,42 @@ class XML_RPC_Response
*/
class XML_RPC_Message extends CI_Xmlrpc
{
+
+ /**
+ * Payload
+ *
+ * @var string
+ */
public $payload;
+
+ /**
+ * Method name
+ *
+ * @var string
+ */
public $method_name;
+
+ /**
+ * Parameter list
+ *
+ * @var array
+ */
public $params = array();
+
+ /**
+ * XH?
+ *
+ * @var array
+ */
public $xh = array();
+ // --------------------------------------------------------------------
+
/**
* Constructor
*
- * @param string method name
- * @param array
+ * @param string $method
+ * @param array $pars
* @return void
*/
public function __construct($method, $pars = FALSE)
@@ -778,14 +1073,14 @@ class XML_RPC_Message extends CI_Xmlrpc
}
// Check for HTTP 200 Response
- if (strncmp($data, 'HTTP', 4) === 0 && ! preg_match('/^HTTP\/[0-9\.]+ 200 /', $data))
+ if (strpos($data, 'HTTP') === 0 && ! preg_match('/^HTTP\/[0-9\.]+ 200 /', $data))
{
$errstr = substr($data, 0, strpos($data, "\n")-1);
return new XML_RPC_Response(0, $this->xmlrpcerr['http_error'], $this->xmlrpcstr['http_error'].' ('.$errstr.')');
}
//-------------------------------------
- // Create and Set Up XML Parser
+ // Create and Set Up XML Parser
//-------------------------------------
$parser = xml_parser_create($this->xmlrpc_defencoding);
@@ -823,7 +1118,7 @@ class XML_RPC_Message extends CI_Xmlrpc
$errstr = sprintf('XML error: %s at line %d',
xml_error_string(xml_get_error_code($parser)),
xml_get_current_line_number($parser));
- //error_log($errstr);
+
$r = new XML_RPC_Response(0, $this->xmlrpcerr['invalid_return'], $this->xmlrpcstr['invalid_return']);
xml_parser_free($parser);
return $r;
@@ -873,7 +1168,7 @@ class XML_RPC_Message extends CI_Xmlrpc
$errstr_v = $v->me['struct']['faultString'];
$errno = $errno_v->scalarval();
- if ($errno == 0)
+ if ($errno === 0)
{
// FAULT returned, errno needs to reflect that
$errno = -1;
@@ -921,9 +1216,9 @@ class XML_RPC_Message extends CI_Xmlrpc
if ($this->xh[$the_parser]['isf'] > 1) return;
// Evaluate and check for correct nesting of XML elements
- if (count($this->xh[$the_parser]['stack']) == 0)
+ if (count($this->xh[$the_parser]['stack']) === 0)
{
- if ($name != 'METHODRESPONSE' && $name != 'METHODCALL')
+ if ($name !== 'METHODRESPONSE' && $name !== 'METHODCALL')
{
$this->xh[$the_parser]['isf'] = 2;
$this->xh[$the_parser]['isf_reason'] = 'Top level XML-RPC element is missing';
@@ -934,7 +1229,7 @@ class XML_RPC_Message extends CI_Xmlrpc
elseif ( ! in_array($this->xh[$the_parser]['stack'][0], $this->valid_parents[$name], TRUE))
{
$this->xh[$the_parser]['isf'] = 2;
- $this->xh[$the_parser]['isf_reason'] = 'XML-RPC element $name cannot be child of '.$this->xh[$the_parser]['stack'][0];
+ $this->xh[$the_parser]['isf_reason'] = 'XML-RPC element '.$name.' cannot be child of '.$this->xh[$the_parser]['stack'][0];
return;
}
@@ -968,11 +1263,11 @@ class XML_RPC_Message extends CI_Xmlrpc
case 'DOUBLE':
case 'DATETIME.ISO8601':
case 'BASE64':
- if ($this->xh[$the_parser]['vt'] != 'value')
+ if ($this->xh[$the_parser]['vt'] !== 'value')
{
//two data elements inside a value: an error occurred!
$this->xh[$the_parser]['isf'] = 2;
- $this->xh[$the_parser]['isf_reason'] = "'Twas a ".$name.' element following a '
+ $this->xh[$the_parser]['isf_reason'] = 'There is a '.$name.' element following a '
.$this->xh[$the_parser]['vt'].' element inside a single value';
return;
}
@@ -1002,7 +1297,7 @@ class XML_RPC_Message extends CI_Xmlrpc
// Add current element name to stack, to allow validation of nesting
array_unshift($this->xh[$the_parser]['stack'], $name);
- $name == 'VALUE' OR $this->xh[$the_parser]['lv'] = 0;
+ $name === 'VALUE' OR $this->xh[$the_parser]['lv'] = 0;
}
// --------------------------------------------------------------------
@@ -1045,20 +1340,20 @@ class XML_RPC_Message extends CI_Xmlrpc
case 'BASE64':
$this->xh[$the_parser]['vt'] = strtolower($name);
- if ($name == 'STRING')
+ if ($name === 'STRING')
{
$this->xh[$the_parser]['value'] = $this->xh[$the_parser]['ac'];
}
- elseif ($name == 'DATETIME.ISO8601')
+ elseif ($name === 'DATETIME.ISO8601')
{
$this->xh[$the_parser]['vt'] = $this->xmlrpcDateTime;
$this->xh[$the_parser]['value'] = $this->xh[$the_parser]['ac'];
}
- elseif ($name == 'BASE64')
+ elseif ($name === 'BASE64')
{
$this->xh[$the_parser]['value'] = base64_decode($this->xh[$the_parser]['ac']);
}
- elseif ($name == 'BOOLEAN')
+ elseif ($name === 'BOOLEAN')
{
// Translated BOOLEAN values to TRUE AND FALSE
$this->xh[$the_parser]['value'] = (bool) $this->xh[$the_parser]['ac'];
@@ -1076,7 +1371,7 @@ class XML_RPC_Message extends CI_Xmlrpc
// we have an I4/INT
// we must check that only 0123456789-<space> are characters here
$this->xh[$the_parser]['value'] = preg_match('/^[+-]?[0-9\t ]+$/', $this->xh[$the_parser]['ac'])
- ? (int) $this->xh[$the_parset]['ac']
+ ? (int) $this->xh[$the_parser]['ac']
: 'ERROR_NON_NUMERIC_FOUND';
}
$this->xh[$the_parser]['ac'] = '';
@@ -1084,7 +1379,7 @@ class XML_RPC_Message extends CI_Xmlrpc
break;
case 'VALUE':
// This if() detects if no scalar was inside <VALUE></VALUE>
- if ($this->xh[$the_parser]['vt']=='value')
+ if ($this->xh[$the_parser]['vt'] == 'value')
{
$this->xh[$the_parser]['value'] = $this->xh[$the_parser]['ac'];
$this->xh[$the_parser]['vt'] = $this->xmlrpcString;
@@ -1093,7 +1388,7 @@ class XML_RPC_Message extends CI_Xmlrpc
// build the XML-RPC value out of the data received, and substitute it
$temp = new XML_RPC_Values($this->xh[$the_parser]['value'], $this->xh[$the_parser]['vt']);
- if (count($this->xh[$the_parser]['valuestack']) && $this->xh[$the_parser]['valuestack'][0]['type'] == 'ARRAY')
+ if (count($this->xh[$the_parser]['valuestack']) && $this->xh[$the_parser]['valuestack'][0]['type'] === 'ARRAY')
{
// Array
$this->xh[$the_parser]['valuestack'][0]['values'][] = $temp;
@@ -1151,9 +1446,9 @@ class XML_RPC_Message extends CI_Xmlrpc
if ($this->xh[$the_parser]['isf'] > 1) return; // XML Fault found already
// If a value has not been found
- if ($this->xh[$the_parser]['lv'] != 3)
+ if ($this->xh[$the_parser]['lv'] !== 3)
{
- if ($this->xh[$the_parser]['lv'] == 1)
+ if ($this->xh[$the_parser]['lv'] === 1)
{
$this->xh[$the_parser]['lv'] = 2; // Found a value
}
@@ -1204,7 +1499,7 @@ class XML_RPC_Message extends CI_Xmlrpc
{
// 'bits' is for the MetaWeblog API image bits
// @todo - this needs to be made more general purpose
- $array[$key] = ($key == 'bits' OR $this->xss_clean == FALSE) ? $array[$key] : $CI->security->xss_clean($array[$key]);
+ $array[$key] = ($key === 'bits' OR $this->xss_clean === FALSE) ? $array[$key] : $CI->security->xss_clean($array[$key]);
}
}
@@ -1242,11 +1537,11 @@ class XML_RPC_Message extends CI_Xmlrpc
{
$kind = $param->kindOf();
- if ($kind == 'scalar')
+ if ($kind === 'scalar')
{
return $param->scalarval();
}
- elseif ($kind == 'array')
+ elseif ($kind === 'array')
{
reset($param->me);
$b = current($param->me);
@@ -1259,7 +1554,7 @@ class XML_RPC_Message extends CI_Xmlrpc
return $arr;
}
- elseif ($kind == 'struct')
+ elseif ($kind === 'struct')
{
reset($param->me['struct']);
$arr = array();
@@ -1284,27 +1579,40 @@ class XML_RPC_Message extends CI_Xmlrpc
*/
class XML_RPC_Values extends CI_Xmlrpc
{
+ /**
+ * Value data
+ *
+ * @var array
+ */
public $me = array();
+
+ /**
+ * Value type
+ *
+ * @var int
+ */
public $mytype = 0;
+ // --------------------------------------------------------------------
+
/**
* Constructor
*
- * @param mixed
- * @param string
+ * @param mixed $val
+ * @param string $type
* @return void
*/
public function __construct($val = -1, $type = '')
{
parent::__construct();
- if ($val != -1 OR $type != '')
+ if ($val !== -1 OR $type !== '')
{
- $type = $type == '' ? 'string' : $type;
+ $type = $type === '' ? 'string' : $type;
if ($this->xmlrpcTypes[$type] == 1)
{
- $this->addScalar($val,$type);
+ $this->addScalar($val, $type);
}
elseif ($this->xmlrpcTypes[$type] == 2)
{
@@ -1330,7 +1638,7 @@ class XML_RPC_Values extends CI_Xmlrpc
{
$typeof = $this->xmlrpcTypes[$type];
- if ($this->mytype == 1)
+ if ($this->mytype === 1)
{
echo '<strong>XML_RPC_Values</strong>: scalar can have only one value<br />';
return 0;
@@ -1342,12 +1650,12 @@ class XML_RPC_Values extends CI_Xmlrpc
return 0;
}
- if ($type == $this->xmlrpcBoolean)
+ if ($type === $this->xmlrpcBoolean)
{
- $val = (int) (strcasecmp($val,'true') === 0 OR $val === 1 OR ($val === TRUE && strcasecmp($val, 'false')));
+ $val = (int) (strcasecmp($val, 'true') === 0 OR $val === 1 OR ($val === TRUE && strcasecmp($val, 'false')));
}
- if ($this->mytype == 2)
+ if ($this->mytype === 2)
{
// adding to an array here
$ar = $this->me['array'];
@@ -1374,7 +1682,7 @@ class XML_RPC_Values extends CI_Xmlrpc
*/
public function addArray($vals)
{
- if ($this->mytype != 0)
+ if ($this->mytype !== 0)
{
echo '<strong>XML_RPC_Values</strong>: already initialized as a [' . $this->kindOf() . ']<br />';
return 0;
@@ -1395,7 +1703,7 @@ class XML_RPC_Values extends CI_Xmlrpc
*/
public function addStruct($vals)
{
- if ($this->mytype != 0)
+ if ($this->mytype !== 0)
{
echo '<strong>XML_RPC_Values</strong>: already initialized as a [' . $this->kindOf() . ']<br />';
return 0;
diff --git a/system/libraries/Xmlrpcs.php b/system/libraries/Xmlrpcs.php
index 6d270c2ea..d6c3416c9 100644
--- a/system/libraries/Xmlrpcs.php
+++ b/system/libraries/Xmlrpcs.php
@@ -1,4 +1,4 @@
-<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');
+<?php
/**
* CodeIgniter
*
@@ -24,6 +24,7 @@
* @since Version 1.0
* @filesource
*/
+defined('BASEPATH') OR exit('No direct script access allowed');
if ( ! function_exists('xml_parser_create'))
{
@@ -46,14 +47,42 @@ if ( ! class_exists('CI_Xmlrpc'))
* @author EllisLab Dev Team
* @link http://codeigniter.com/user_guide/libraries/xmlrpc.html
*/
-class CI_Xmlrpcs extends CI_Xmlrpc
-{
- public $methods = array(); //array of methods mapped to function names and signatures
- public $debug_msg = ''; // Debug Message
- public $system_methods = array(); // XML RPC Server methods
- public $controller_obj;
- public $object = FALSE;
+class CI_Xmlrpcs extends CI_Xmlrpc {
+
+ /**
+ * Array of methods mapped to function names and signatures
+ *
+ * @var array
+ */
+ public $methods = array();
+
+ /**
+ * Debug Message
+ *
+ * @var string
+ */
+ public $debug_msg = '';
+
+ /**
+ * XML RPC Server methods
+ *
+ * @var array
+ */
+ public $system_methods = array();
+
+ /**
+ * Configuration object
+ *
+ * @var object
+ */
+ public $object = FALSE;
+ /**
+ * Initialize XMLRPC class
+ *
+ * @param array $config
+ * @return void
+ */
public function __construct($config = array())
{
parent::__construct();
@@ -158,9 +187,9 @@ class CI_Xmlrpcs extends CI_Xmlrpc
public function add_to_map($methodname, $function, $sig, $doc)
{
$this->methods[$methodname] = array(
- 'function' => $function,
- 'signature' => $sig,
- 'docstring' => $doc
+ 'function' => $function,
+ 'signature' => $sig,
+ 'docstring' => $doc
);
}
@@ -180,7 +209,7 @@ class CI_Xmlrpcs extends CI_Xmlrpc
// Get Data
//-------------------------------------
- if ($data == '')
+ if ($data === '')
{
$data = $HTTP_RAW_POST_DATA;
}
@@ -202,21 +231,21 @@ class CI_Xmlrpcs extends CI_Xmlrpc
);
xml_set_object($parser, $parser_object);
- xml_parser_set_option($parser, XML_OPTION_CASE_FOLDING, true);
+ xml_parser_set_option($parser, XML_OPTION_CASE_FOLDING, TRUE);
xml_set_element_handler($parser, 'open_tag', 'closing_tag');
xml_set_character_data_handler($parser, 'character_data');
//xml_set_default_handler($parser, 'default_handler');
//-------------------------------------
- // PARSE + PROCESS XML DATA
+ // PARSE + PROCESS XML DATA
//-------------------------------------
if ( ! xml_parse($parser, $data, 1))
{
- // return XML error as a faultCode
+ // Return XML error as a faultCode
$r = new XML_RPC_Response(0,
- $this->xmlrpcerrxml + xml_get_error_code($parser),
- sprintf('XML error: %s at line %d',
+ $this->xmlrpcerrxml + xml_get_error_code($parser),
+ sprintf('XML error: %s at line %d',
xml_error_string(xml_get_error_code($parser)),
xml_get_current_line_number($parser)));
xml_parser_free($parser);
@@ -230,7 +259,7 @@ class CI_Xmlrpcs extends CI_Xmlrpc
xml_parser_free($parser);
$m = new XML_RPC_Message($parser_object->xh[$parser]['method']);
- $plist='';
+ $plist = '';
for ($i = 0, $c = count($parser_object->xh[$parser]['params']); $i < $c; $i++)
{
@@ -251,7 +280,7 @@ class CI_Xmlrpcs extends CI_Xmlrpc
}
//-------------------------------------
- // SET DEBUGGING MESSAGE
+ // SET DEBUGGING MESSAGE
//-------------------------------------
if ($this->debug === TRUE)
@@ -275,15 +304,15 @@ class CI_Xmlrpcs extends CI_Xmlrpc
$methName = $m->method_name;
// Check to see if it is a system call
- $system_call = (strncmp($methName, 'system', 5) === 0);
+ $system_call = (strpos($methName, 'system') === 0);
- if ($this->xss_clean == FALSE)
+ if ($this->xss_clean === FALSE)
{
$m->xss_clean = FALSE;
}
//-------------------------------------
- // Valid Method
+ // Valid Method
//-------------------------------------
if ( ! isset($this->methods[$methName]['function']))
@@ -292,11 +321,11 @@ class CI_Xmlrpcs extends CI_Xmlrpc
}
//-------------------------------------
- // Check for Method (and Object)
+ // Check for Method (and Object)
//-------------------------------------
$method_parts = explode('.', $this->methods[$methName]['function']);
- $objectCall = (isset($method_parts[1]) && $method_parts[1] != '');
+ $objectCall = (isset($method_parts[1]) && $method_parts[1] !== '');
if ($system_call === TRUE)
{
@@ -313,7 +342,7 @@ class CI_Xmlrpcs extends CI_Xmlrpc
}
//-------------------------------------
- // Checking Methods Signature
+ // Checking Methods Signature
//-------------------------------------
if (isset($this->methods[$methName]['signature']))
@@ -328,9 +357,9 @@ class CI_Xmlrpcs extends CI_Xmlrpc
for ($n = 0, $mc = count($m->params); $n < $mc; $n++)
{
$p = $m->params[$n];
- $pt = ($p->kindOf() == 'scalar') ? $p->scalarval() : $p->kindOf();
+ $pt = ($p->kindOf() === 'scalar') ? $p->scalarval() : $p->kindOf();
- if ($pt != $current_sig[$n+1])
+ if ($pt !== $current_sig[$n+1])
{
$pno = $n+1;
$wanted = $current_sig[$n+1];
@@ -346,7 +375,7 @@ class CI_Xmlrpcs extends CI_Xmlrpc
}
//-------------------------------------
- // Calls the Function
+ // Calls the Function
//-------------------------------------
if ($objectCall === TRUE)
@@ -365,7 +394,6 @@ class CI_Xmlrpcs extends CI_Xmlrpc
else
{
return $this->object->$method_parts[1]($m);
- //return call_user_func(array(&$method_parts['0'],$method_parts['1']), $m);
}
}
}
@@ -378,7 +406,7 @@ class CI_Xmlrpcs extends CI_Xmlrpc
// --------------------------------------------------------------------
/**
- * Server Function: List Methods
+ * Server Function: List Methods
*
* @param mixed
* @return object
@@ -405,7 +433,7 @@ class CI_Xmlrpcs extends CI_Xmlrpc
// --------------------------------------------------------------------
/**
- * Server Function: Return Signature for Method
+ * Server Function: Return Signature for Method
*
* @param mixed
* @return object
@@ -439,13 +467,13 @@ class CI_Xmlrpcs extends CI_Xmlrpc
return new XML_RPC_Response(new XML_RPC_Values('undef', 'string'));
}
- return new XML_RPC_Response(0,$this->xmlrpcerr['introspect_unknown'], $this->xmlrpcstr['introspect_unknown']);
+ return new XML_RPC_Response(0, $this->xmlrpcerr['introspect_unknown'], $this->xmlrpcstr['introspect_unknown']);
}
// --------------------------------------------------------------------
/**
- * Server Function: Doc String for Method
+ * Server Function: Doc String for Method
*
* @param mixed
* @return object
@@ -470,7 +498,7 @@ class CI_Xmlrpcs extends CI_Xmlrpc
// --------------------------------------------------------------------
/**
- * Server Function: Multi-call
+ * Server Function: Multi-call
*
* @param mixed
* @return object
@@ -487,10 +515,8 @@ class CI_Xmlrpcs extends CI_Xmlrpc
foreach ($calls as $value)
{
- //$attempt = $this->_execute(new XML_RPC_Message($value[0], $value[1]));
-
$m = new XML_RPC_Message($value[0]);
- $plist='';
+ $plist = '';
for ($i = 0, $c = count($value[1]); $i < $c; $i++)
{
@@ -499,7 +525,7 @@ class CI_Xmlrpcs extends CI_Xmlrpc
$attempt = $this->_execute($m);
- if ($attempt->faultCode() != 0)
+ if ($attempt->faultCode() !== 0)
{
return $attempt;
}
@@ -513,14 +539,14 @@ class CI_Xmlrpcs extends CI_Xmlrpc
// --------------------------------------------------------------------
/**
- * Multi-call Function: Error Handling
+ * Multi-call Function: Error Handling
*
* @param mixed
* @return object
*/
public function multicall_error($err)
{
- $str = is_string($err) ? $this->xmlrpcstr["multicall_${err}"] : $err->faultString();
+ $str = is_string($err) ? $this->xmlrpcstr["multicall_${err}"] : $err->faultString();
$code = is_string($err) ? $this->xmlrpcerr["multicall_${err}"] : $err->faultCode();
$struct['faultCode'] = new XML_RPC_Values($code, 'int');
@@ -532,14 +558,14 @@ class CI_Xmlrpcs extends CI_Xmlrpc
// --------------------------------------------------------------------
/**
- * Multi-call Function: Processes method
+ * Multi-call Function: Processes method
*
* @param mixed
* @return object
*/
public function do_multicall($call)
{
- if ($call->kindOf() != 'struct')
+ if ($call->kindOf() !== 'struct')
{
return $this->multicall_error('notstruct');
}
@@ -548,14 +574,14 @@ class CI_Xmlrpcs extends CI_Xmlrpc
return $this->multicall_error('nomethod');
}
- list($scalar_type,$scalar_value)=each($methName->me);
- $scalar_type = $scalar_type == $this->xmlrpcI4 ? $this->xmlrpcInt : $scalar_type;
+ list($scalar_type, $scalar_value) = each($methName->me);
+ $scalar_type = $scalar_type === $this->xmlrpcI4 ? $this->xmlrpcInt : $scalar_type;
- if ($methName->kindOf() != 'scalar' OR $scalar_type != 'string')
+ if ($methName->kindOf() !== 'scalar' OR $scalar_type !== 'string')
{
return $this->multicall_error('notstring');
}
- elseif ($scalar_value == 'system.multicall')
+ elseif ($scalar_value === 'system.multicall')
{
return $this->multicall_error('recursion');
}
@@ -563,12 +589,12 @@ class CI_Xmlrpcs extends CI_Xmlrpc
{
return $this->multicall_error('noparams');
}
- elseif ($params->kindOf() != 'array')
+ elseif ($params->kindOf() !== 'array')
{
return $this->multicall_error('notarray');
}
- list($a,$b) = each($params->me);
+ list($a, $b) = each($params->me);
$msg = new XML_RPC_Message($scalar_value);
for ($i = 0, $numParams = count($b); $i < $numParams; $i++)
@@ -578,7 +604,7 @@ class CI_Xmlrpcs extends CI_Xmlrpc
$result = $this->_execute($msg);
- if ($result->faultCode() != 0)
+ if ($result->faultCode() !== 0)
{
return $this->multicall_error($result);
}
diff --git a/system/libraries/Zip.php b/system/libraries/Zip.php
index 80438546b..9ecd0de9f 100644
--- a/system/libraries/Zip.php
+++ b/system/libraries/Zip.php
@@ -1,4 +1,4 @@
-<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');
+<?php
/**
* CodeIgniter
*
@@ -24,6 +24,7 @@
* @since Version 1.0
* @filesource
*/
+defined('BASEPATH') OR exit('No direct script access allowed');
/**
* Zip Compression Class
@@ -40,15 +41,55 @@
* @author EllisLab Dev Team
* @link http://codeigniter.com/user_guide/libraries/zip.html
*/
-class CI_Zip {
+class CI_Zip {
+ /**
+ * Zip data in string form
+ *
+ * @var string
+ */
public $zipdata = '';
+
+ /**
+ * Zip data for a directory in string form
+ *
+ * @var string
+ */
public $directory = '';
+
+ /**
+ * Number of files/folder in zip file
+ *
+ * @var int
+ */
public $entries = 0;
+
+ /**
+ * Number of files in zip
+ *
+ * @var int
+ */
public $file_num = 0;
+
+ /**
+ * relative offset of local header
+ *
+ * @var int
+ */
public $offset = 0;
+
+ /**
+ * Reference to time at init
+ *
+ * @var int
+ */
public $now;
+ /**
+ * Initialize zip compression class
+ *
+ * @return void
+ */
public function __construct()
{
$this->now = time();
diff --git a/system/libraries/javascript/Jquery.php b/system/libraries/javascript/Jquery.php
index f30d7c639..2bf47957f 100644
--- a/system/libraries/javascript/Jquery.php
+++ b/system/libraries/javascript/Jquery.php
@@ -1,4 +1,4 @@
-<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');
+<?php
/**
* CodeIgniter
*
@@ -24,8 +24,7 @@
* @since Version 1.0
* @filesource
*/
-
-// ------------------------------------------------------------------------
+defined('BASEPATH') OR exit('No direct script access allowed');
/**
* Jquery Class
@@ -36,17 +35,65 @@
* @author EllisLab Dev Team
* @link http://codeigniter.com/user_guide/libraries/javascript.html
*/
-
class CI_Jquery extends CI_Javascript {
+ /**
+ * JavaScript directory location
+ *
+ * @var string
+ */
protected $_javascript_folder = 'js';
+
+ /**
+ * JQuery code for load
+ *
+ * @var array
+ */
public $jquery_code_for_load = array();
+
+ /**
+ * JQuery code for compile
+ *
+ * @var array
+ */
public $jquery_code_for_compile = array();
+
+ /**
+ * JQuery corner active flag
+ *
+ * @var bool
+ */
public $jquery_corner_active = FALSE;
+
+ /**
+ * JQuery table sorter active flag
+ *
+ * @var bool
+ */
public $jquery_table_sorter_active = FALSE;
+
+ /**
+ * JQuery table sorder pager active
+ *
+ * @var bool
+ */
public $jquery_table_sorter_pager_active = FALSE;
+
+ /**
+ * JQuery AJAX image
+ *
+ * @var string
+ */
public $jquery_ajax_img = '';
+ // --------------------------------------------------------------------
+
+ /**
+ * Constructor
+ *
+ * @param array $params
+ * @return void
+ */
public function __construct($params)
{
$this->CI =& get_instance();
@@ -57,7 +104,7 @@ class CI_Jquery extends CI_Javascript {
$this->script();
}
- log_message('debug', "Jquery Class Initialized");
+ log_message('debug', 'Jquery Class Initialized');
}
// --------------------------------------------------------------------
@@ -103,19 +150,16 @@ class CI_Jquery extends CI_Javascript {
*
* @param string The element to attach the event to
* @param string The code to execute
- * @param boolean whether or not to return false
+ * @param bool whether or not to return false
* @return string
*/
protected function _click($element = 'this', $js = '', $ret_false = TRUE)
{
- if ( ! is_array($js))
- {
- $js = array($js);
- }
+ is_array($js) OR $js = array($js);
if ($ret_false)
{
- $js[] = "return false;";
+ $js[] = 'return false;';
}
return $this->_add_event($element, $js, 'click');
@@ -183,7 +227,7 @@ class CI_Jquery extends CI_Javascript {
*/
protected function _hover($element = 'this', $over, $out)
{
- $event = "\n\t$(" . $this->_prep_element($element) . ").hover(\n\t\tfunction()\n\t\t{\n\t\t\t{$over}\n\t\t}, \n\t\tfunction()\n\t\t{\n\t\t\t{$out}\n\t\t});\n";
+ $event = "\n\t$(".$this->_prep_element($element).").hover(\n\t\tfunction()\n\t\t{\n\t\t\t{$over}\n\t\t}, \n\t\tfunction()\n\t\t{\n\t\t\t{$out}\n\t\t});\n";
$this->jquery_code_for_compile[] = $event;
@@ -309,11 +353,10 @@ class CI_Jquery extends CI_Javascript {
*
* Outputs script directly
*
- * @param string The element to attach the event to
- * @param string The code to execute
- * @return string
+ * @param array $array_js = array()
+ * @return void
*/
- protected function _output($array_js = '')
+ protected function _output($array_js = array())
{
if ( ! is_array($array_js))
{
@@ -322,7 +365,7 @@ class CI_Jquery extends CI_Javascript {
foreach ($array_js as $js)
{
- $this->jquery_code_for_compile[] = "\t$js\n";
+ $this->jquery_code_for_compile[] = "\t".$js."\n";
}
}
@@ -383,13 +426,14 @@ class CI_Jquery extends CI_Javascript {
*
* Outputs a jQuery addClass event
*
- * @param string - element
+ * @param string $element
+ * @param string $class
* @return string
*/
- protected function _addClass($element = 'this', $class='')
+ protected function _addClass($element = 'this', $class = '')
{
$element = $this->_prep_element($element);
- return "$({$element}).addClass(\"$class\");";
+ return '$('.$element.').addClass("'.$class.'");';
}
// --------------------------------------------------------------------
@@ -399,9 +443,10 @@ class CI_Jquery extends CI_Javascript {
*
* Outputs a jQuery animate event
*
- * @param string - element
- * @param string - One of 'slow', 'normal', 'fast', or time in milliseconds
- * @param string - Javascript callback function
+ * @param string $element
+ * @param array $params
+ * @param string $speed 'slow', 'normal', 'fast', or time in milliseconds
+ * @param string $extra
* @return string
*/
protected function _animate($element = 'this', $params = array(), $speed = '', $extra = '')
@@ -411,24 +456,24 @@ class CI_Jquery extends CI_Javascript {
$animations = "\t\t\t";
- foreach ($params as $param=>$value)
+ foreach ($params as $param => $value)
{
- $animations .= $param.': \''.$value.'\', ';
+ $animations .= $param.": '".$value."', ";
}
$animations = substr($animations, 0, -2); // remove the last ", "
- if ($speed != '')
+ if ($speed !== '')
{
$speed = ', '.$speed;
}
- if ($extra != '')
+ if ($extra !== '')
{
$extra = ', '.$extra;
}
- return "$({$element}).animate({\n$animations\n\t\t}".$speed.$extra.");";
+ return "$({$element}).animate({\n$animations\n\t\t}".$speed.$extra.');';
}
// --------------------------------------------------------------------
@@ -448,7 +493,7 @@ class CI_Jquery extends CI_Javascript {
$element = $this->_prep_element($element);
$speed = $this->_validate_speed($speed);
- if ($callback != '')
+ if ($callback !== '')
{
$callback = ", function(){\n{$callback}\n}";
}
@@ -473,12 +518,12 @@ class CI_Jquery extends CI_Javascript {
$element = $this->_prep_element($element);
$speed = $this->_validate_speed($speed);
- if ($callback != '')
+ if ($callback !== '')
{
$callback = ", function(){\n{$callback}\n}";
}
- return "$({$element}).fadeOut({$speed}{$callback});";
+ return '$('.$element.').fadeOut('.$speed.$callback.');';
}
// --------------------------------------------------------------------
@@ -498,7 +543,7 @@ class CI_Jquery extends CI_Javascript {
$element = $this->_prep_element($element);
$speed = $this->_validate_speed($speed);
- if ($callback != '')
+ if ($callback !== '')
{
$callback = ", function(){\n{$callback}\n}";
}
@@ -513,13 +558,14 @@ class CI_Jquery extends CI_Javascript {
*
* Outputs a jQuery remove class event
*
- * @param string - element
+ * @param string $element
+ * @param string $class
* @return string
*/
- protected function _removeClass($element = 'this', $class='')
+ protected function _removeClass($element = 'this', $class = '')
{
$element = $this->_prep_element($element);
- return "$({$element}).removeClass(\"$class\");";
+ return '$('.$element.').removeClass("'.$class.'");';
}
// --------------------------------------------------------------------
@@ -539,12 +585,12 @@ class CI_Jquery extends CI_Javascript {
$element = $this->_prep_element($element);
$speed = $this->_validate_speed($speed);
- if ($callback != '')
+ if ($callback !== '')
{
$callback = ", function(){\n{$callback}\n}";
}
- return "$({$element}).slideUp({$speed}{$callback});";
+ return '$('.$element.').slideUp('.$speed.$callback.');';
}
// --------------------------------------------------------------------
@@ -564,12 +610,12 @@ class CI_Jquery extends CI_Javascript {
$element = $this->_prep_element($element);
$speed = $this->_validate_speed($speed);
- if ($callback != '')
+ if ($callback !== '')
{
$callback = ", function(){\n{$callback}\n}";
}
- return "$({$element}).slideDown({$speed}{$callback});";
+ return '$('.$element.').slideDown('.$speed.$callback.');';
}
// --------------------------------------------------------------------
@@ -589,12 +635,12 @@ class CI_Jquery extends CI_Javascript {
$element = $this->_prep_element($element);
$speed = $this->_validate_speed($speed);
- if ($callback != '')
+ if ($callback !== '')
{
$callback = ", function(){\n{$callback}\n}";
}
- return "$({$element}).slideToggle({$speed}{$callback});";
+ return '$('.$element.').slideToggle('.$speed.$callback.');';
}
// --------------------------------------------------------------------
@@ -610,7 +656,7 @@ class CI_Jquery extends CI_Javascript {
protected function _toggle($element = 'this')
{
$element = $this->_prep_element($element);
- return "$({$element}).toggle();";
+ return '$('.$element.').toggle();';
}
// --------------------------------------------------------------------
@@ -620,13 +666,14 @@ class CI_Jquery extends CI_Javascript {
*
* Outputs a jQuery toggle class event
*
- * @param string - element
+ * @param string $element
+ * @param string $class
* @return string
*/
- protected function _toggleClass($element = 'this', $class='')
+ protected function _toggleClass($element = 'this', $class = '')
{
$element = $this->_prep_element($element);
- return "$({$element}).toggleClass(\"$class\");";
+ return '$('.$element.').toggleClass("'.$class.'");';
}
// --------------------------------------------------------------------
@@ -646,12 +693,12 @@ class CI_Jquery extends CI_Javascript {
$element = $this->_prep_element($element);
$speed = $this->_validate_speed($speed);
- if ($callback != '')
+ if ($callback !== '')
{
$callback = ", function(){\n{$callback}\n}";
}
- return "$({$element}).show({$speed}{$callback});";
+ return '$('.$element.').show('.$speed.$callback.');';
}
// --------------------------------------------------------------------
@@ -674,30 +721,29 @@ class CI_Jquery extends CI_Javascript {
$controller = (strpos('://', $controller) === FALSE) ? $controller : $this->CI->config->site_url($controller);
// ajaxStart and ajaxStop are better choices here... but this is a stop gap
- if ($this->CI->config->item('javascript_ajax_img') == '')
+ if ($this->CI->config->item('javascript_ajax_img') === '')
{
- $loading_notifier = "Loading...";
+ $loading_notifier = 'Loading...';
}
else
{
- $loading_notifier = '<img src=\''.$this->CI->config->slash_item('base_url').$this->CI->config->item('javascript_ajax_img').'\' alt=\'Loading\' />';
+ $loading_notifier = '<img src="'.$this->CI->config->slash_item('base_url').$this->CI->config->item('javascript_ajax_img').'" alt="Loading" />';
}
- $updater = "$($container).empty();\n" // anything that was in... get it out
- . "\t\t$($container).prepend(\"$loading_notifier\");\n"; // to replace with an image
+ $updater = '$('.$container.").empty();\n" // anything that was in... get it out
+ ."\t\t$(".$container.').prepend("'.$loading_notifier."\");\n"; // to replace with an image
$request_options = '';
- if ($options != '')
+ if ($options !== '')
{
$request_options .= ', {'
- . (is_array($options) ? "'".implode("', '", $options)."'" : "'".str_replace(":", "':'", $options)."'")
- . '}';
+ .(is_array($options) ? "'".implode("', '", $options)."'" : "'".str_replace(':', "':'", $options)."'")
+ .'}';
}
return $updater."\t\t$($container).load('$controller'$request_options);";
}
-
// --------------------------------------------------------------------
// Pre-written handy stuff
// --------------------------------------------------------------------
@@ -705,18 +751,19 @@ class CI_Jquery extends CI_Javascript {
/**
* Zebra tables
*
- * @param string table name
- * @param string plugin location
+ * @param string $class
+ * @param string $odd
+ * @param string $hover
* @return string
*/
protected function _zebraTables($class = '', $odd = 'odd', $hover = '')
{
- $class = ($class != '') ? '.'.$class : '';
- $zebra = "\t\$(\"table{$class} tbody tr:nth-child(even)\").addClass(\"{$odd}\");";
+ $class = ($class !== '') ? '.'.$class : '';
+ $zebra = "\t\$(\"table{$class} tbody tr:nth-child(even)\").addClass(\"{$odd}\");";
$this->jquery_code_for_compile[] = $zebra;
- if ($hover != '')
+ if ($hover !== '')
{
$hover = $this->hover("table{$class} tbody tr", "$(this).addClass('hover');", "$(this).removeClass('hover');");
}
@@ -731,9 +778,9 @@ class CI_Jquery extends CI_Javascript {
/**
* Corner Plugin
*
- * http://www.malsup.com/jquery/corner/
- *
- * @param string target
+ * @link http://www.malsup.com/jquery/corner/
+ * @param string $element
+ * @param string $corner_style
* @return string
*/
public function corner($element = '', $corner_style = '')
@@ -741,21 +788,23 @@ class CI_Jquery extends CI_Javascript {
// may want to make this configurable down the road
$corner_location = '/plugins/jquery.corner.js';
- if ($corner_style != '')
+ if ($corner_style !== '')
{
$corner_style = '"'.$corner_style.'"';
}
- return "$(" . $this->_prep_element($element) . ").corner(".$corner_style.");";
+ return '$('.$this->_prep_element($element).').corner('.$corner_style.');';
}
// --------------------------------------------------------------------
/**
- * modal window
+ * Modal window
*
* Load a thickbox modal window
*
+ * @param string $src
+ * @param bool $relative
* @return void
*/
public function modal($src, $relative = FALSE)
@@ -770,6 +819,8 @@ class CI_Jquery extends CI_Javascript {
*
* Load an Effect library
*
+ * @param string $src
+ * @param bool $relative
* @return void
*/
public function effect($src, $relative = FALSE)
@@ -784,6 +835,8 @@ class CI_Jquery extends CI_Javascript {
*
* Load a plugin library
*
+ * @param string $src
+ * @param bool $relative
* @return void
*/
public function plugin($src, $relative = FALSE)
@@ -798,12 +851,15 @@ class CI_Jquery extends CI_Javascript {
*
* Load a user interface library
*
+ * @param string $src
+ * @param bool $relative
* @return void
*/
public function ui($src, $relative = FALSE)
{
$this->jquery_code_for_load[] = $this->external($src, $relative);
}
+
// --------------------------------------------------------------------
/**
@@ -811,26 +867,27 @@ class CI_Jquery extends CI_Javascript {
*
* Creates a jQuery sortable
*
- * @return void
+ * @param string $element
+ * @param array $options
+ * @return string
*/
public function sortable($element, $options = array())
{
-
if (count($options) > 0)
{
$sort_options = array();
foreach ($options as $k=>$v)
{
- $sort_options[] = "\n\t\t".$k.': '.$v."";
+ $sort_options[] = "\n\t\t".$k.': '.$v;
}
- $sort_options = implode(",", $sort_options);
+ $sort_options = implode(',', $sort_options);
}
else
{
$sort_options = '';
}
- return "$(" . $this->_prep_element($element) . ").sortable({".$sort_options."\n\t});";
+ return '$('.$this->_prep_element($element).').sortable({'.$sort_options."\n\t});";
}
// --------------------------------------------------------------------
@@ -844,7 +901,7 @@ class CI_Jquery extends CI_Javascript {
*/
public function tablesorter($table = '', $options = '')
{
- $this->jquery_code_for_compile[] = "\t$(" . $this->_prep_element($table) . ").tablesorter($options);\n";
+ $this->jquery_code_for_compile[] = "\t$(".$this->_prep_element($table).').tablesorter('.$options.");\n";
}
// --------------------------------------------------------------------
@@ -869,7 +926,7 @@ class CI_Jquery extends CI_Javascript {
}
- $event = "\n\t$(" . $this->_prep_element($element) . ").{$event}(function(){\n\t\t{$js}\n\t});\n";
+ $event = "\n\t$(".$this->_prep_element($element).').'.$event."(function(){\n\t\t{$js}\n\t});\n";
$this->jquery_code_for_compile[] = $event;
return $event;
}
@@ -882,7 +939,9 @@ class CI_Jquery extends CI_Javascript {
* As events are specified, they are stored in an array
* This funciton compiles them all for output on a page
*
- * @return string
+ * @param string $view_var
+ * @param bool $script_tags
+ * @return void
*/
protected function _compile($view_var = 'script_foot', $script_tags = TRUE)
{
@@ -898,13 +957,12 @@ class CI_Jquery extends CI_Javascript {
// Inline references
$script = '$(document).ready(function() {'."\n"
- . implode('', $this->jquery_code_for_compile)
- . '});';
+ .implode('', $this->jquery_code_for_compile)
+ .'});';
$output = ($script_tags === FALSE) ? $script : $this->inline($script);
$this->CI->load->vars(array($view_var => $output));
-
}
// --------------------------------------------------------------------
@@ -928,14 +986,12 @@ class CI_Jquery extends CI_Javascript {
*
* A wrapper for writing document.ready()
*
- * @return string
+ * @param array $js
+ * @return void
*/
protected function _document_ready($js)
{
- if ( ! is_array($js))
- {
- $js = array($js);
- }
+ is_array($js) OR $js = array($js);
foreach ($js as $script)
{
@@ -950,7 +1006,8 @@ class CI_Jquery extends CI_Javascript {
*
* Outputs the script tag that loads the jquery.js file into an HTML document
*
- * @param string
+ * @param string $library_src
+ * @param bool $relative
* @return string
*/
public function script($library_src = '', $relative = FALSE)
@@ -974,7 +1031,7 @@ class CI_Jquery extends CI_Javascript {
*/
protected function _prep_element($element)
{
- if ($element != 'this')
+ if ($element !== 'this')
{
$element = '"'.$element.'"';
}
@@ -998,7 +1055,7 @@ class CI_Jquery extends CI_Javascript {
{
return '"'.$speed.'"';
}
- elseif (preg_match("/[^0-9]/", $speed))
+ elseif (preg_match('/[^0-9]/', $speed))
{
return '';
}
@@ -1009,4 +1066,4 @@ class CI_Jquery extends CI_Javascript {
}
/* End of file Jquery.php */
-/* Location: ./system/libraries/Jquery.php */
+/* Location: ./system/libraries/Jquery.php */ \ No newline at end of file
diff --git a/system/libraries/javascript/index.html b/system/libraries/javascript/index.html
new file mode 100644
index 000000000..c942a79ce
--- /dev/null
+++ b/system/libraries/javascript/index.html
@@ -0,0 +1,10 @@
+<html>
+<head>
+ <title>403 Forbidden</title>
+</head>
+<body>
+
+<p>Directory access is forbidden.</p>
+
+</body>
+</html> \ No newline at end of file