summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--.gitignore9
-rw-r--r--.hgflow8
-rw-r--r--.hgignore7
-rw-r--r--application/config/database.php3
-rw-r--r--application/config/migration.php42
-rw-r--r--application/config/mimes.php2
-rwxr-xr-xsystem/core/CodeIgniter.php51
-rw-r--r--system/core/Controller.php2
-rw-r--r--system/core/Input.php2
-rw-r--r--system/core/Loader.php44
-rw-r--r--system/core/Router.php15
-rw-r--r--system/core/URI.php2
-rw-r--r--system/database/DB_active_rec.php286
-rw-r--r--system/database/DB_driver.php2
-rw-r--r--system/database/drivers/cubrid/cubrid_driver.php791
-rw-r--r--system/database/drivers/cubrid/cubrid_forge.php288
-rw-r--r--system/database/drivers/cubrid/cubrid_result.php202
-rw-r--r--system/database/drivers/cubrid/cubrid_utility.php108
-rw-r--r--system/database/drivers/cubrid/index.html10
-rw-r--r--system/database/drivers/mysql/mysql_driver.php11
-rw-r--r--system/database/drivers/mysql/mysql_forge.php8
-rw-r--r--system/database/drivers/mysql/mysql_utility.php2
-rw-r--r--system/database/drivers/mysqli/mysqli_driver.php11
-rw-r--r--system/database/drivers/mysqli/mysqli_forge.php8
-rw-r--r--system/helpers/form_helper.php6
-rw-r--r--system/helpers/html_helper.php4
-rw-r--r--system/helpers/inflector_helper.php115
-rw-r--r--system/helpers/string_helper.php15
-rw-r--r--system/language/english/form_validation_lang.php1
-rw-r--r--system/language/english/migration_lang.php13
-rw-r--r--system/libraries/Cart.php12
-rw-r--r--system/libraries/Driver.php4
-rw-r--r--system/libraries/Email.php120
-rw-r--r--system/libraries/Form_validation.php119
-rw-r--r--system/libraries/Migration.php338
-rw-r--r--system/libraries/User_agent.php2
-rw-r--r--user_guide/changelog.html54
-rw-r--r--user_guide/database/configuration.html4
-rw-r--r--user_guide/database/queries.html9
-rw-r--r--user_guide/helpers/url_helper.html2
-rw-r--r--user_guide/images/appflowchart.gifbin25276 -> 12363 bytes
-rw-r--r--user_guide/libraries/cart.html20
-rw-r--r--user_guide/libraries/form_validation.html30
-rw-r--r--user_guide/libraries/loader.html6
-rw-r--r--user_guide/overview/appflow.html2
45 files changed, 2358 insertions, 432 deletions
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 000000000..d740c498f
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,9 @@
+.DS_Store
+
+application/cache/*
+!application/cache/index.html
+!application/cache/.htaccess
+
+application/logs/*
+!application/logs/index.html
+!application/logs/.htaccess \ No newline at end of file
diff --git a/.hgflow b/.hgflow
deleted file mode 100644
index ad6e56e0f..000000000
--- a/.hgflow
+++ /dev/null
@@ -1,8 +0,0 @@
-[Basic]
-develop = develop
-feature = feature/
-version_tag =
-publish = default
-release = release/
-hotfix = hotfix/
-
diff --git a/.hgignore b/.hgignore
deleted file mode 100644
index 5ee4d823e..000000000
--- a/.hgignore
+++ /dev/null
@@ -1,7 +0,0 @@
-syntax: glob
-
-.DS_Store
-
-syntax: regexp
-application/cache/(?!index\.html|\.htaccess)
-application/logs/(?!index\.html|\.htaccess)
diff --git a/application/config/database.php b/application/config/database.php
index fa541a734..b4b34bf66 100644
--- a/application/config/database.php
+++ b/application/config/database.php
@@ -27,7 +27,8 @@
| ['char_set'] The character set used in communicating with the database
| ['dbcollat'] The character collation used in communicating with the database
| NOTE: For MySQL and MySQLi databases, this setting is only used
-| as a backup if your server is running PHP < 5.2.3 or MySQL < 5.0.7.
+| as a backup if your server is running PHP < 5.2.3 or MySQL < 5.0.7
+| (and in table creation queries made with DB Forge).
| There is an incompatibility in PHP with mysql_real_escape_string() which
| can make your site vulnerable to SQL injection if you are using a
| multi-byte character set and are running versions lower than these.
diff --git a/application/config/migration.php b/application/config/migration.php
new file mode 100644
index 000000000..dba870010
--- /dev/null
+++ b/application/config/migration.php
@@ -0,0 +1,42 @@
+<?php defined('BASEPATH') OR exit('No direct script access allowed');
+/*
+|--------------------------------------------------------------------------
+| Enable/Disable Migrations
+|--------------------------------------------------------------------------
+|
+| Migrations are disabled by default for security reasons.
+| You should enable migrations whenever you intend to do a schema migration
+| and disable it back when you're done.
+|
+*/
+$config['migration_enabled'] = FALSE;
+
+
+/*
+|--------------------------------------------------------------------------
+| Migrations version
+|--------------------------------------------------------------------------
+|
+| This is used to set migration version that the file system should be on.
+| If you run $this->migration->latest() this is the version that schema will
+| be upgraded / downgraded to.
+|
+*/
+$config['migration_version'] = 0;
+
+
+/*
+|--------------------------------------------------------------------------
+| Migrations Path
+|--------------------------------------------------------------------------
+|
+| Path to your migrations folder.
+| Typically, it will be within your application path.
+| Also, writing permission is required within the migrations path.
+|
+*/
+$config['migration_path'] = APPPATH . 'migrations/';
+
+
+/* End of file migration.php */
+/* Location: ./application/config/migration.php */ \ No newline at end of file
diff --git a/application/config/mimes.php b/application/config/mimes.php
index 8065794ff..82767d7c8 100644
--- a/application/config/mimes.php
+++ b/application/config/mimes.php
@@ -10,7 +10,7 @@
$mimes = array( 'hqx' => 'application/mac-binhex40',
'cpt' => 'application/mac-compactpro',
- 'csv' => array('text/x-comma-separated-values', 'text/comma-separated-values', 'application/octet-stream', 'application/vnd.ms-excel', 'text/x-csv', 'text/csv', 'application/csv', 'application/excel', 'application/vnd.msexcel'),
+ 'csv' => array('text/x-comma-separated-values', 'text/comma-separated-values', 'application/octet-stream', 'application/vnd.ms-excel', 'application/x-csv', 'text/x-csv', 'text/csv', 'application/csv', 'application/excel', 'application/vnd.msexcel'),
'bin' => 'application/macbinary',
'dms' => 'application/octet-stream',
'lha' => 'application/octet-stream',
diff --git a/system/core/CodeIgniter.php b/system/core/CodeIgniter.php
index 4eb918b15..5f795514f 100755
--- a/system/core/CodeIgniter.php
+++ b/system/core/CodeIgniter.php
@@ -27,31 +27,20 @@
* @link http://codeigniter.com/user_guide/
*/
-/*
- * ------------------------------------------------------
- * Define the CodeIgniter Version
- * ------------------------------------------------------
+/**
+ * CodeIgniter Version
+ *
+ * @var string
+ *
*/
- /**
- * CodeIgniter Version
- *
- * @var string
- *
- */
define('CI_VERSION', '2.0.2');
-/*
- * ------------------------------------------------------
- * Define the CodeIgniter Branch (Core = TRUE, Reactor = FALSE)
- * ------------------------------------------------------
+/**
+ * CodeIgniter Branch (Core = TRUE, Reactor = FALSE)
+ *
+ * @var boolean
+ *
*/
-
- /**
- * CodeIgniter Branch (Core = TRUE, Reactor = FALSE)
- *
- * @var string
- *
- */
define('CI_CORE', FALSE);
/*
@@ -280,7 +269,25 @@
OR in_array(strtolower($method), array_map('strtolower', get_class_methods('CI_Controller')))
)
{
- show_404("{$class}/{$method}");
+ if ( ! empty($RTR->routes['404_override']))
+ {
+ $x = explode('/', $RTR->routes['404_override']);
+ $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');
+ }
+ }
+ else
+ {
+ show_404("{$class}/{$method}");
+ }
}
/*
diff --git a/system/core/Controller.php b/system/core/Controller.php
index ec86b7920..fddb81e19 100644
--- a/system/core/Controller.php
+++ b/system/core/Controller.php
@@ -48,7 +48,7 @@ class CI_Controller {
$this->load =& load_class('Loader', 'core');
- $this->load->set_base_classes()->ci_autoloader();
+ $this->load->initialize();
log_message('debug', "Controller Class Initialized");
}
diff --git a/system/core/Input.php b/system/core/Input.php
index dc7612e64..cfbef942d 100644
--- a/system/core/Input.php
+++ b/system/core/Input.php
@@ -672,7 +672,7 @@ class CI_Input {
*/
public function is_cli_request()
{
- return (bool) defined('STDIN');
+ return (php_sapi_name() == 'cli') or defined('STDIN');
}
}
diff --git a/system/core/Loader.php b/system/core/Loader.php
index 721c196cc..a0fbaa82e 100644
--- a/system/core/Loader.php
+++ b/system/core/Loader.php
@@ -62,17 +62,22 @@ class CI_Loader {
// --------------------------------------------------------------------
/**
- * Set _base_classes variable
+ * Initialize the Loader
*
* This method is called once in CI_Controller.
*
* @param array
* @return object
*/
- public function set_base_classes()
+ 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;
}
@@ -389,6 +394,21 @@ class CI_Loader {
// --------------------------------------------------------------------
/**
+ * Get Variable
+ *
+ * Check if a variable is set and retrieve it.
+ *
+ * @param array
+ * @return void
+ */
+ public function get_var($key)
+ {
+ return isset($this->_ci_cached_vars[$key]) ? $this->_ci_cached_vars[$key] : NULL;
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
* Load Helper
*
* This function loads the specified helper file.
@@ -920,22 +940,22 @@ class CI_Loader {
// first, global next
if (defined('ENVIRONMENT') AND file_exists($path .'config/'.ENVIRONMENT.'/'.strtolower($class).'.php'))
{
- include_once($path .'config/'.ENVIRONMENT.'/'.strtolower($class).'.php');
+ include($path .'config/'.ENVIRONMENT.'/'.strtolower($class).'.php');
break;
}
elseif (defined('ENVIRONMENT') AND file_exists($path .'config/'.ENVIRONMENT.'/'.ucfirst(strtolower($class)).'.php'))
{
- include_once($path .'config/'.ENVIRONMENT.'/'.ucfirst(strtolower($class)).'.php');
+ include($path .'config/'.ENVIRONMENT.'/'.ucfirst(strtolower($class)).'.php');
break;
}
elseif (file_exists($path .'config/'.strtolower($class).'.php'))
{
- include_once($path .'config/'.strtolower($class).'.php');
+ include($path .'config/'.strtolower($class).'.php');
break;
}
elseif (file_exists($path .'config/'.ucfirst(strtolower($class)).'.php'))
{
- include_once($path .'config/'.ucfirst(strtolower($class)).'.php');
+ include($path .'config/'.ucfirst(strtolower($class)).'.php');
break;
}
}
@@ -1005,23 +1025,19 @@ class CI_Loader {
* The config/autoload.php file contains an array that permits sub-systems,
* libraries, and helpers to be loaded automatically.
*
- * This function is public, as it's used in the CI_Controller class.
- * However, there is no reason you should ever needs to use it.
- *
* @param array
* @return void
*/
- public function ci_autoloader()
+ private function _ci_autoloader()
{
if (defined('ENVIRONMENT') AND file_exists(APPPATH.'config/'.ENVIRONMENT.'/autoload.php'))
{
- include_once(APPPATH.'config/'.ENVIRONMENT.'/autoload.php');
+ include(APPPATH.'config/'.ENVIRONMENT.'/autoload.php');
}
else
{
- include_once(APPPATH.'config/autoload.php');
+ include(APPPATH.'config/autoload.php');
}
-
if ( ! isset($autoload))
{
diff --git a/system/core/Router.php b/system/core/Router.php
index 5e92a04b1..668ac0954 100644
--- a/system/core/Router.php
+++ b/system/core/Router.php
@@ -244,7 +244,20 @@ class CI_Router {
// Does the requested controller exist in the sub-folder?
if ( ! file_exists(APPPATH.'controllers/'.$this->fetch_directory().$segments[0].'.php'))
{
- show_404($this->fetch_directory().$segments[0]);
+ 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;
+ }
+ else
+ {
+ show_404($this->fetch_directory().$segments[0]);
+ }
}
}
else
diff --git a/system/core/URI.php b/system/core/URI.php
index d56548654..20f0f006b 100644
--- a/system/core/URI.php
+++ b/system/core/URI.php
@@ -62,7 +62,7 @@ class CI_URI {
if (strtoupper($this->config->item('uri_protocol')) == 'AUTO')
{
// Is the request coming from the command line?
- if (defined('STDIN'))
+ if (php_sapi_name() == 'cli' or defined('STDIN'))
{
$this->_set_uri_string($this->_parse_cli_args());
return;
diff --git a/system/database/DB_active_rec.php b/system/database/DB_active_rec.php
index 52bad260a..7bab729f5 100644
--- a/system/database/DB_active_rec.php
+++ b/system/database/DB_active_rec.php
@@ -69,11 +69,10 @@ class CI_DB_active_record extends CI_DB_driver {
*
* Generates the SELECT portion of the query
*
- * @access public
* @param string
* @return object
*/
- function select($select = '*', $escape = NULL)
+ public function select($select = '*', $escape = NULL)
{
if (is_string($select))
{
@@ -107,12 +106,11 @@ class CI_DB_active_record extends CI_DB_driver {
*
* Generates a SELECT MAX(field) portion of a query
*
- * @access public
* @param string the field
* @param string an alias
* @return object
*/
- function select_max($select = '', $alias = '')
+ public function select_max($select = '', $alias = '')
{
return $this->_max_min_avg_sum($select, $alias, 'MAX');
}
@@ -124,12 +122,11 @@ class CI_DB_active_record extends CI_DB_driver {
*
* Generates a SELECT MIN(field) portion of a query
*
- * @access public
* @param string the field
* @param string an alias
* @return object
*/
- function select_min($select = '', $alias = '')
+ public function select_min($select = '', $alias = '')
{
return $this->_max_min_avg_sum($select, $alias, 'MIN');
}
@@ -141,12 +138,11 @@ class CI_DB_active_record extends CI_DB_driver {
*
* Generates a SELECT AVG(field) portion of a query
*
- * @access public
* @param string the field
* @param string an alias
* @return object
*/
- function select_avg($select = '', $alias = '')
+ public function select_avg($select = '', $alias = '')
{
return $this->_max_min_avg_sum($select, $alias, 'AVG');
}
@@ -158,12 +154,11 @@ class CI_DB_active_record extends CI_DB_driver {
*
* Generates a SELECT SUM(field) portion of a query
*
- * @access public
* @param string the field
* @param string an alias
* @return object
*/
- function select_sum($select = '', $alias = '')
+ public function select_sum($select = '', $alias = '')
{
return $this->_max_min_avg_sum($select, $alias, 'SUM');
}
@@ -178,12 +173,11 @@ class CI_DB_active_record extends CI_DB_driver {
* select_avg()
* select_sum()
*
- * @access public
* @param string the field
* @param string an alias
* @return object
*/
- function _max_min_avg_sum($select = '', $alias = '', $type = 'MAX')
+ protected function _max_min_avg_sum($select = '', $alias = '', $type = 'MAX')
{
if ( ! is_string($select) OR $select == '')
{
@@ -220,11 +214,10 @@ class CI_DB_active_record extends CI_DB_driver {
/**
* Determines the alias name based on the table
*
- * @access private
* @param string
* @return string
*/
- function _create_alias_from_table($item)
+ protected function _create_alias_from_table($item)
{
if (strpos($item, '.') !== FALSE)
{
@@ -241,11 +234,10 @@ class CI_DB_active_record extends CI_DB_driver {
*
* Sets a flag which tells the query string compiler to add DISTINCT
*
- * @access public
* @param bool
* @return object
*/
- function distinct($val = TRUE)
+ public function distinct($val = TRUE)
{
$this->ar_distinct = (is_bool($val)) ? $val : TRUE;
return $this;
@@ -258,11 +250,10 @@ class CI_DB_active_record extends CI_DB_driver {
*
* Generates the FROM portion of the query
*
- * @access public
* @param mixed can be a string or array
* @return object
*/
- function from($from)
+ public function from($from)
{
foreach ((array)$from as $val)
{
@@ -311,13 +302,12 @@ class CI_DB_active_record extends CI_DB_driver {
*
* Generates the JOIN portion of the query
*
- * @access public
* @param string
* @param string the join condition
* @param string the type of join
* @return object
*/
- function join($table, $cond, $type = '')
+ public function join($table, $cond, $type = '')
{
if ($type != '')
{
@@ -367,12 +357,11 @@ class CI_DB_active_record extends CI_DB_driver {
* Generates the WHERE portion of the query. Separates
* multiple calls with AND
*
- * @access public
* @param mixed
* @param mixed
* @return object
*/
- function where($key, $value = NULL, $escape = TRUE)
+ public function where($key, $value = NULL, $escape = TRUE)
{
return $this->_where($key, $value, 'AND ', $escape);
}
@@ -385,12 +374,11 @@ class CI_DB_active_record extends CI_DB_driver {
* Generates the WHERE portion of the query. Separates
* multiple calls with OR
*
- * @access public
* @param mixed
* @param mixed
* @return object
*/
- function or_where($key, $value = NULL, $escape = TRUE)
+ public function or_where($key, $value = NULL, $escape = TRUE)
{
return $this->_where($key, $value, 'OR ', $escape);
}
@@ -400,15 +388,14 @@ class CI_DB_active_record extends CI_DB_driver {
/**
* Where
*
- * Called by where() or orwhere()
+ * Called by where() or or_where()
*
- * @access private
* @param mixed
* @param mixed
* @param string
* @return object
*/
- function _where($key, $value = NULL, $type = 'AND ', $escape = NULL)
+ protected function _where($key, $value = NULL, $type = 'AND ', $escape = NULL)
{
if ( ! is_array($key))
{
@@ -471,12 +458,11 @@ class CI_DB_active_record extends CI_DB_driver {
* Generates a WHERE field IN ('item', 'item') SQL query joined with
* AND if appropriate
*
- * @access public
* @param string The field to search
* @param array The values searched on
* @return object
*/
- function where_in($key = NULL, $values = NULL)
+ public function where_in($key = NULL, $values = NULL)
{
return $this->_where_in($key, $values);
}
@@ -489,12 +475,11 @@ class CI_DB_active_record extends CI_DB_driver {
* Generates a WHERE field IN ('item', 'item') SQL query joined with
* OR if appropriate
*
- * @access public
* @param string The field to search
* @param array The values searched on
* @return object
*/
- function or_where_in($key = NULL, $values = NULL)
+ public function or_where_in($key = NULL, $values = NULL)
{
return $this->_where_in($key, $values, FALSE, 'OR ');
}
@@ -507,12 +492,11 @@ class CI_DB_active_record extends CI_DB_driver {
* Generates a WHERE field NOT IN ('item', 'item') SQL query joined
* with AND if appropriate
*
- * @access public
* @param string The field to search
* @param array The values searched on
* @return object
*/
- function where_not_in($key = NULL, $values = NULL)
+ public function where_not_in($key = NULL, $values = NULL)
{
return $this->_where_in($key, $values, TRUE);
}
@@ -525,12 +509,11 @@ class CI_DB_active_record extends CI_DB_driver {
* Generates a WHERE field NOT IN ('item', 'item') SQL query joined
* with OR if appropriate
*
- * @access public
* @param string The field to search
* @param array The values searched on
* @return object
*/
- function or_where_not_in($key = NULL, $values = NULL)
+ public function or_where_not_in($key = NULL, $values = NULL)
{
return $this->_where_in($key, $values, TRUE, 'OR ');
}
@@ -542,14 +525,13 @@ class CI_DB_active_record extends CI_DB_driver {
*
* Called by where_in, where_in_or, where_not_in, where_not_in_or
*
- * @access public
* @param string The field to search
* @param array The values searched on
* @param boolean If the statement would be IN or NOT IN
* @param string
* @return object
*/
- function _where_in($key = NULL, $values = NULL, $not = FALSE, $type = 'AND ')
+ protected function _where_in($key = NULL, $values = NULL, $not = FALSE, $type = 'AND ')
{
if ($key === NULL OR $values === NULL)
{
@@ -592,12 +574,11 @@ class CI_DB_active_record extends CI_DB_driver {
* Generates a %LIKE% portion of the query. Separates
* multiple calls with AND
*
- * @access public
* @param mixed
* @param mixed
* @return object
*/
- function like($field, $match = '', $side = 'both')
+ public function like($field, $match = '', $side = 'both')
{
return $this->_like($field, $match, 'AND ', $side);
}
@@ -610,12 +591,11 @@ class CI_DB_active_record extends CI_DB_driver {
* Generates a NOT LIKE portion of the query. Separates
* multiple calls with AND
*
- * @access public
* @param mixed
* @param mixed
* @return object
*/
- function not_like($field, $match = '', $side = 'both')
+ public function not_like($field, $match = '', $side = 'both')
{
return $this->_like($field, $match, 'AND ', $side, 'NOT');
}
@@ -628,12 +608,11 @@ class CI_DB_active_record extends CI_DB_driver {
* Generates a %LIKE% portion of the query. Separates
* multiple calls with OR
*
- * @access public
* @param mixed
* @param mixed
* @return object
*/
- function or_like($field, $match = '', $side = 'both')
+ public function or_like($field, $match = '', $side = 'both')
{
return $this->_like($field, $match, 'OR ', $side);
}
@@ -646,12 +625,11 @@ class CI_DB_active_record extends CI_DB_driver {
* Generates a NOT LIKE portion of the query. Separates
* multiple calls with OR
*
- * @access public
* @param mixed
* @param mixed
* @return object
*/
- function or_not_like($field, $match = '', $side = 'both')
+ public function or_not_like($field, $match = '', $side = 'both')
{
return $this->_like($field, $match, 'OR ', $side, 'NOT');
}
@@ -663,13 +641,12 @@ class CI_DB_active_record extends CI_DB_driver {
*
* Called by like() or orlike()
*
- * @access private
* @param mixed
* @param mixed
* @param string
* @return object
*/
- function _like($field, $match = '', $type = 'AND ', $side = 'both', $not = '')
+ protected function _like($field, $match = '', $type = 'AND ', $side = 'both', $not = '')
{
if ( ! is_array($field))
{
@@ -719,11 +696,10 @@ class CI_DB_active_record extends CI_DB_driver {
/**
* GROUP BY
*
- * @access public
* @param string
* @return object
*/
- function group_by($by)
+ public function group_by($by)
{
if (is_string($by))
{
@@ -755,12 +731,11 @@ class CI_DB_active_record extends CI_DB_driver {
*
* Separates multiple calls with AND
*
- * @access public
* @param string
* @param string
* @return object
*/
- function having($key, $value = '', $escape = TRUE)
+ public function having($key, $value = '', $escape = TRUE)
{
return $this->_having($key, $value, 'AND ', $escape);
}
@@ -772,12 +747,11 @@ class CI_DB_active_record extends CI_DB_driver {
*
* Separates multiple calls with OR
*
- * @access public
* @param string
* @param string
* @return object
*/
- function or_having($key, $value = '', $escape = TRUE)
+ public function or_having($key, $value = '', $escape = TRUE)
{
return $this->_having($key, $value, 'OR ', $escape);
}
@@ -789,12 +763,11 @@ class CI_DB_active_record extends CI_DB_driver {
*
* Called by having() or or_having()
*
- * @access private
* @param string
* @param string
* @return object
*/
- function _having($key, $value = '', $type = 'AND ', $escape = TRUE)
+ protected function _having($key, $value = '', $type = 'AND ', $escape = TRUE)
{
if ( ! is_array($key))
{
@@ -817,7 +790,7 @@ class CI_DB_active_record extends CI_DB_driver {
if ($v != '')
{
- $v = ' '.$this->escape_str($v);
+ $v = ' '.$this->escape($v);
}
$this->ar_having[] = $prefix.$k.$v;
@@ -836,12 +809,11 @@ class CI_DB_active_record extends CI_DB_driver {
/**
* Sets the ORDER BY value
*
- * @access public
* @param string
* @param string direction: asc or desc
* @return object
*/
- function order_by($orderby, $direction = '')
+ public function order_by($orderby, $direction = '')
{
if (strtolower($direction) == 'random')
{
@@ -892,18 +864,17 @@ class CI_DB_active_record extends CI_DB_driver {
/**
* Sets the LIMIT value
*
- * @access public
* @param integer the limit value
* @param integer the offset value
* @return object
*/
- function limit($value, $offset = '')
+ public function limit($value, $offset = '')
{
- $this->ar_limit = $value;
+ $this->ar_limit = (int) $value;
if ($offset != '')
{
- $this->ar_offset = $offset;
+ $this->ar_offset = (int) $offset;
}
return $this;
@@ -914,11 +885,10 @@ class CI_DB_active_record extends CI_DB_driver {
/**
* Sets the OFFSET value
*
- * @access public
* @param integer the offset value
* @return object
*/
- function offset($offset)
+ public function offset($offset)
{
$this->ar_offset = $offset;
return $this;
@@ -929,13 +899,12 @@ class CI_DB_active_record extends CI_DB_driver {
/**
* The "set" function. Allows key/value pairs to be set for inserting or updating
*
- * @access public
* @param mixed
* @param string
* @param boolean
* @return object
*/
- function set($key, $value = '', $escape = TRUE)
+ public function set($key, $value = '', $escape = TRUE)
{
$key = $this->_object_to_array($key);
@@ -967,13 +936,12 @@ class CI_DB_active_record extends CI_DB_driver {
* Compiles the select statement based on the other functions called
* and runs the query
*
- * @access public
* @param string the table
* @param string the limit clause
* @param string the offset clause
* @return object
*/
- function get($table = '', $limit = null, $offset = null)
+ public function get($table = '', $limit = null, $offset = null)
{
if ($table != '')
{
@@ -999,11 +967,10 @@ class CI_DB_active_record extends CI_DB_driver {
* Generates a platform-specific query string that counts all records
* returned by an Active Record query.
*
- * @access public
* @param string
* @return string
*/
- function count_all_results($table = '')
+ public function count_all_results($table = '')
{
if ($table != '')
{
@@ -1032,13 +999,12 @@ class CI_DB_active_record extends CI_DB_driver {
*
* Allows the where clause, limit and offset to be added directly
*
- * @access public
* @param string the where clause
* @param string the limit clause
* @param string the offset clause
* @return object
*/
- function get_where($table = '', $where = null, $limit = null, $offset = null)
+ public function get_where($table = '', $where = null, $limit = null, $offset = null)
{
if ($table != '')
{
@@ -1069,12 +1035,11 @@ class CI_DB_active_record extends CI_DB_driver {
*
* Compiles batch insert strings and runs the queries
*
- * @access public
* @param string the table to retrieve the results from
* @param array an associative array of insert values
* @return object
*/
- function insert_batch($table = '', $set = NULL)
+ public function insert_batch($table = '', $set = NULL)
{
if ( ! is_null($set))
{
@@ -1127,14 +1092,12 @@ class CI_DB_active_record extends CI_DB_driver {
/**
* The "set_insert_batch" function. Allows key/value pairs to be set for batch inserts
*
- * @access public
* @param mixed
* @param string
* @param boolean
* @return object
*/
-
- function set_insert_batch($key, $value = '', $escape = TRUE)
+ public function set_insert_batch($key, $value = '', $escape = TRUE)
{
$key = $this->_object_to_array_batch($key);
@@ -1189,8 +1152,7 @@ class CI_DB_active_record extends CI_DB_driver {
*
* Compiles an insert string and runs the query
*
- * @access public
- * @param string the table to retrieve the results from
+ * @param string the table to insert data into
* @param array an associative array of insert values
* @return object
*/
@@ -1230,7 +1192,18 @@ class CI_DB_active_record extends CI_DB_driver {
return $this->query($sql);
}
- function replace($table = '', $set = NULL)
+ // --------------------------------------------------------------------
+
+ /**
+ * Replace
+ *
+ * Compiles an replace into string and runs the query
+ *
+ * @param string the table to replace data into
+ * @param array an associative array of insert values
+ * @return object
+ */
+ public function replace($table = '', $set = NULL)
{
if ( ! is_null($set))
{
@@ -1273,13 +1246,12 @@ class CI_DB_active_record extends CI_DB_driver {
*
* Compiles an update string and runs the query
*
- * @access public
* @param string the table to retrieve the results from
* @param array an associative array of update values
* @param mixed the where clause
* @return object
*/
- function update($table = '', $set = NULL, $where = NULL, $limit = NULL)
+ public function update($table = '', $set = NULL, $where = NULL, $limit = NULL)
{
// Combine any cached components with the current statements
$this->_merge_cache();
@@ -1336,13 +1308,12 @@ class CI_DB_active_record extends CI_DB_driver {
*
* Compiles an update string and runs the query
*
- * @access public
* @param string the table to retrieve the results from
* @param array an associative array of update values
* @param string the where key
* @return object
*/
- function update_batch($table = '', $set = NULL, $index = NULL)
+ public function update_batch($table = '', $set = NULL, $index = NULL)
{
// Combine any cached components with the current statements
$this->_merge_cache();
@@ -1351,7 +1322,7 @@ class CI_DB_active_record extends CI_DB_driver {
{
if ($this->db_debug)
{
- return $this->display_error('db_myst_use_index');
+ return $this->display_error('db_must_use_index');
}
return FALSE;
@@ -1402,14 +1373,12 @@ class CI_DB_active_record extends CI_DB_driver {
/**
* The "set_update_batch" function. Allows key/value pairs to be set for batch updating
*
- * @access public
* @param array
* @param string
* @param boolean
* @return object
*/
-
- function set_update_batch($key, $index = '', $escape = TRUE)
+ public function set_update_batch($key, $index = '', $escape = TRUE)
{
$key = $this->_object_to_array_batch($key);
@@ -1462,11 +1431,10 @@ class CI_DB_active_record extends CI_DB_driver {
*
* Compiles a delete string and runs "DELETE FROM table"
*
- * @access public
* @param string the table to empty
* @return object
*/
- function empty_table($table = '')
+ public function empty_table($table = '')
{
if ($table == '')
{
@@ -1502,11 +1470,10 @@ class CI_DB_active_record extends CI_DB_driver {
* If the database does not support the truncate() command
* This function maps to "DELETE FROM table"
*
- * @access public
* @param string the table to truncate
* @return object
*/
- function truncate($table = '')
+ public function truncate($table = '')
{
if ($table == '')
{
@@ -1540,14 +1507,13 @@ class CI_DB_active_record extends CI_DB_driver {
*
* Compiles a delete string and runs the query
*
- * @access public
* @param mixed the table(s) to delete from. String or array
* @param mixed the where clause
* @param mixed the limit clause
* @param boolean
* @return object
*/
- function delete($table = '', $where = '', $limit = NULL, $reset_data = TRUE)
+ public function delete($table = '', $where = '', $limit = NULL, $reset_data = TRUE)
{
// Combine any cached components with the current statements
$this->_merge_cache();
@@ -1617,11 +1583,10 @@ class CI_DB_active_record extends CI_DB_driver {
*
* Prepends a database prefix if one exists in configuration
*
- * @access public
* @param string the table
* @return string
*/
- function dbprefix($table = '')
+ public function dbprefix($table = '')
{
if ($table == '')
{
@@ -1634,15 +1599,29 @@ class CI_DB_active_record extends CI_DB_driver {
// --------------------------------------------------------------------
/**
+ * Set DB Prefix
+ *
+ * Set's the DB Prefix to something new without needing to reconnect
+ *
+ * @param string the prefix
+ * @return string
+ */
+ public function set_dbprefix($prefix = '')
+ {
+ return $this->dbprefix = $prefix;
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
* Track Aliases
*
* Used to track SQL statements written with aliased tables.
*
- * @access private
* @param string The table to inspect
* @return string
*/
- function _track_aliases($table)
+ protected function _track_aliases($table)
{
if (is_array($table))
{
@@ -1685,10 +1664,9 @@ class CI_DB_active_record extends CI_DB_driver {
* Generates a query string based on which functions were used.
* Should not be called directly. The get() function calls it.
*
- * @access private
* @return string
*/
- function _compile_select($select_override = FALSE)
+ protected function _compile_select($select_override = FALSE)
{
// Combine any cached components with the current statements
$this->_merge_cache();
@@ -1716,7 +1694,8 @@ class CI_DB_active_record extends CI_DB_driver {
// is because until the user calls the from() function we don't know if there are aliases
foreach ($this->ar_select as $key => $val)
{
- $this->ar_select[$key] = $this->_protect_identifiers($val, FALSE, $this->ar_no_escape[$key]);
+ $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);
}
$sql .= implode(', ', $this->ar_select);
@@ -1826,11 +1805,10 @@ class CI_DB_active_record extends CI_DB_driver {
*
* Takes an object as input and converts the class variables to array key/vals
*
- * @access public
* @param object
* @return array
*/
- function _object_to_array($object)
+ public function _object_to_array($object)
{
if ( ! is_object($object))
{
@@ -1857,11 +1835,10 @@ class CI_DB_active_record extends CI_DB_driver {
*
* Takes an object as input and converts the class variables to array key/vals
*
- * @access public
* @param object
* @return array
*/
- function _object_to_array_batch($object)
+ public function _object_to_array_batch($object)
{
if ( ! is_object($object))
{
@@ -1897,10 +1874,9 @@ class CI_DB_active_record extends CI_DB_driver {
*
* Starts AR caching
*
- * @access public
* @return void
*/
- function start_cache()
+ public function start_cache()
{
$this->ar_caching = TRUE;
}
@@ -1912,10 +1888,9 @@ class CI_DB_active_record extends CI_DB_driver {
*
* Stops AR caching
*
- * @access public
* @return void
*/
- function stop_cache()
+ public function stop_cache()
{
$this->ar_caching = FALSE;
}
@@ -1930,23 +1905,21 @@ class CI_DB_active_record extends CI_DB_driver {
* @access public
* @return void
*/
- function flush_cache()
+ 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()
- )
- );
+ $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()
+ ));
}
// --------------------------------------------------------------------
@@ -1957,10 +1930,9 @@ class CI_DB_active_record extends CI_DB_driver {
* When called, this function merges any cached AR arrays with
* locally called ones.
*
- * @access private
* @return void
*/
- function _merge_cache()
+ protected function _merge_cache()
{
if (count($this->ar_cache_exists) == 0)
{
@@ -1995,11 +1967,10 @@ class CI_DB_active_record extends CI_DB_driver {
/**
* Resets the active record values. Called by the get() function
*
- * @access private
* @param array An array of fields to reset
* @return void
*/
- function _reset_run($ar_reset_items)
+ protected function _reset_run($ar_reset_items)
{
foreach ($ar_reset_items as $item => $default_value)
{
@@ -2015,28 +1986,27 @@ class CI_DB_active_record extends CI_DB_driver {
/**
* Resets the active record values. Called by the get() function
*
- * @access private
* @return void
*/
- function _reset_select()
+ protected function _reset_select()
{
$ar_reset_items = 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,
- );
+ '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,
+ );
$this->_reset_run($ar_reset_items);
}
@@ -2048,25 +2018,23 @@ class CI_DB_active_record extends CI_DB_driver {
*
* Called by the insert() update() insert_batch() update_batch() and delete() functions
*
- * @access private
* @return void
*/
- function _reset_write()
+ protected function _reset_write()
{
$ar_reset_items = 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
- );
+ 'ar_set' => array(),
+ 'ar_from' => array(),
+ 'ar_where' => array(),
+ 'ar_like' => array(),
+ 'ar_orderby' => array(),
+ 'ar_keys' => array(),
+ 'ar_limit' => FALSE,
+ 'ar_order' => FALSE
+ );
$this->_reset_run($ar_reset_items);
}
-
}
/* End of file DB_active_rec.php */
diff --git a/system/database/DB_driver.php b/system/database/DB_driver.php
index 10e8ed0c0..f3e824daa 100644
--- a/system/database/DB_driver.php
+++ b/system/database/DB_driver.php
@@ -218,7 +218,7 @@ class CI_DB_driver {
// Some DBs have functions that return the version, and don't run special
// SQL queries per se. In these instances, just return the result.
- $driver_version_exceptions = array('oci8', 'sqlite');
+ $driver_version_exceptions = array('oci8', 'sqlite', 'cubrid');
if (in_array($this->dbdriver, $driver_version_exceptions))
{
diff --git a/system/database/drivers/cubrid/cubrid_driver.php b/system/database/drivers/cubrid/cubrid_driver.php
new file mode 100644
index 000000000..3f0109249
--- /dev/null
+++ b/system/database/drivers/cubrid/cubrid_driver.php
@@ -0,0 +1,791 @@
+<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');
+/**
+ * CodeIgniter
+ *
+ * An open source application development framework for PHP 5.1.6 or newer
+ *
+ * @package CodeIgniter
+ * @author Esen Sagynov
+ * @copyright Copyright (c) 2008 - 2011, EllisLab, Inc.
+ * @license http://codeigniter.com/user_guide/license.html
+ * @link http://codeigniter.com
+ * @since Version 2.0.2
+ * @filesource
+ */
+
+// ------------------------------------------------------------------------
+
+/**
+ * CUBRID Database Adapter Class
+ *
+ * Note: _DB is an extender class that the app controller
+ * creates dynamically based on whether the active record
+ * class is being used or not.
+ *
+ * @package CodeIgniter
+ * @subpackage Drivers
+ * @category Database
+ * @author Esen Sagynov
+ * @link http://codeigniter.com/user_guide/database/
+ */
+class CI_DB_cubrid_driver extends CI_DB {
+
+ // Default CUBRID Broker port. Will be used unless user
+ // explicitly specifies another one.
+ const DEFAULT_PORT = 33000;
+
+ var $dbdriver = 'cubrid';
+
+ // The character used for escaping - no need in CUBRID
+ var $_escape_char = '';
+
+ // clause and character used for LIKE escape sequences - not used in CUBRID
+ var $_like_escape_str = '';
+ var $_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.
+ */
+ var $_count_string = 'SELECT COUNT(*) AS ';
+ var $_random_keyword = ' RAND()'; // database specific random keyword
+
+ /**
+ * Non-persistent database connection
+ *
+ * @access private called by the base class
+ * @return resource
+ */
+ function db_connect()
+ {
+ // If no port is defined by the user, use the default value
+ if ($this->port == '')
+ {
+ $this->port = self::DEFAULT_PORT;
+ }
+
+ $conn = cubrid_connect($this->hostname, $this->port, $this->database, $this->username, $this->password);
+
+ if ($conn)
+ {
+ // Check if a user wants to run queries in dry, i.e. run the
+ // queries but not commit them.
+ if (isset($this->auto_commit) && ! $this->auto_commit)
+ {
+ cubrid_set_autocommit($conn, CUBRID_AUTOCOMMIT_FALSE);
+ }
+ else
+ {
+ cubrid_set_autocommit($conn, CUBRID_AUTOCOMMIT_TRUE);
+ $this->auto_commit = TRUE;
+ }
+ }
+
+ return $conn;
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Persistent database connection
+ * In CUBRID persistent DB connection is supported natively in CUBRID
+ * engine which can be configured in the CUBRID Broker configuration
+ * file by setting the CCI_PCONNECT parameter to ON. In that case, all
+ * connections established between the client application and the
+ * server will become persistent. This is calling the same
+ * @cubrid_connect function will establish persisten connection
+ * considering that the CCI_PCONNECT is ON.
+ *
+ * @access private called by the base class
+ * @return resource
+ */
+ function db_pconnect()
+ {
+ return $this->db_connect();
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Reconnect
+ *
+ * Keep / reestablish the db connection if no queries have been
+ * sent for a length of time exceeding the server's idle timeout
+ *
+ * @access public
+ * @return void
+ */
+ function reconnect()
+ {
+ if (cubrid_ping($this->conn_id) === FALSE)
+ {
+ $this->conn_id = FALSE;
+ }
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Select the database
+ *
+ * @access private called by the base class
+ * @return resource
+ */
+ function db_select()
+ {
+ // In CUBRID there is no need to select a database as the database
+ // is chosen at the connection time.
+ // So, to determine if the database is "selected", all we have to
+ // do is ping the server and return that value.
+ return cubrid_ping($this->conn_id);
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Set client character set
+ *
+ * @access public
+ * @param string
+ * @param string
+ * @return resource
+ */
+ function db_set_charset($charset, $collation)
+ {
+ // In CUBRID, there is no need to set charset or collation.
+ // This is why returning true will allow the application continue
+ // its normal process.
+ return TRUE;
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Version number query string
+ *
+ * @access public
+ * @return string
+ */
+ function _version()
+ {
+ // To obtain the CUBRID Server version, no need to run the SQL query.
+ // CUBRID PHP API provides a function to determin this value.
+ // This is why we also need to add 'cubrid' value to the list of
+ // $driver_version_exceptions array in DB_driver class in
+ // version() function.
+ return cubrid_get_server_info($this->conn_id);
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Execute the query
+ *
+ * @access private called by the base class
+ * @param string an SQL query
+ * @return resource
+ */
+ function _execute($sql)
+ {
+ $sql = $this->_prep_query($sql);
+ return @cubrid_query($sql, $this->conn_id);
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Prep the query
+ *
+ * If needed, each database adapter can prep the query string
+ *
+ * @access private called by execute()
+ * @param string an SQL query
+ * @return string
+ */
+ function _prep_query($sql)
+ {
+ // No need to prepare
+ return $sql;
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Begin Transaction
+ *
+ * @access public
+ * @return bool
+ */
+ 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)
+ {
+ return TRUE;
+ }
+
+ // 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;
+
+ if (cubrid_get_autocommit($this->conn_id))
+ {
+ cubrid_set_autocommit($this->conn_id, CUBRID_AUTOCOMMIT_FALSE);
+ }
+
+ return TRUE;
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Commit Transaction
+ *
+ * @access public
+ * @return bool
+ */
+ 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)
+ {
+ return TRUE;
+ }
+
+ cubrid_commit($this->conn_id);
+
+ if ($this->auto_commit && ! cubrid_get_autocommit($this->conn_id))
+ {
+ cubrid_set_autocommit($this->conn_id, CUBRID_AUTOCOMMIT_TRUE);
+ }
+
+ return TRUE;
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Rollback Transaction
+ *
+ * @access public
+ * @return bool
+ */
+ 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)
+ {
+ return TRUE;
+ }
+
+ cubrid_rollback($this->conn_id);
+
+ if ($this->auto_commit && ! cubrid_get_autocommit($this->conn_id))
+ {
+ cubrid_set_autocommit($this->conn_id, CUBRID_AUTOCOMMIT_TRUE);
+ }
+
+ return TRUE;
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Escape String
+ *
+ * @access public
+ * @param string
+ * @param bool whether or not the string will be used in a LIKE condition
+ * @return string
+ */
+ function escape_str($str, $like = FALSE)
+ {
+ if (is_array($str))
+ {
+ foreach ($str as $key => $val)
+ {
+ $str[$key] = $this->escape_str($val, $like);
+ }
+
+ return $str;
+ }
+
+ if (function_exists('cubrid_real_escape_string') AND is_resource($this->conn_id))
+ {
+ $str = cubrid_real_escape_string($str, $this->conn_id);
+ }
+ else
+ {
+ $str = addslashes($str);
+ }
+
+ // escape LIKE condition wildcards
+ if ($like === TRUE)
+ {
+ $str = str_replace(array('%', '_'), array('\\%', '\\_'), $str);
+ }
+
+ return $str;
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Affected Rows
+ *
+ * @access public
+ * @return integer
+ */
+ function affected_rows()
+ {
+ return @cubrid_affected_rows($this->conn_id);
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Insert ID
+ *
+ * @access public
+ * @return integer
+ */
+ function insert_id()
+ {
+ return @cubrid_insert_id($this->conn_id);
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * "Count All" query
+ *
+ * Generates a platform-specific query string that counts all records in
+ * the specified table
+ *
+ * @access public
+ * @param string
+ * @return string
+ */
+ 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();
+ return (int) $row->numrows;
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * List table query
+ *
+ * Generates a platform-specific query string so that the table names can be fetched
+ *
+ * @access private
+ * @param boolean
+ * @return string
+ */
+ function _list_tables($prefix_limit = FALSE)
+ {
+ $sql = "SHOW TABLES";
+
+ if ($prefix_limit !== FALSE AND $this->dbprefix != '')
+ {
+ $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
+ *
+ * @access public
+ * @param string the table name
+ * @return string
+ */
+ function _list_columns($table = '')
+ {
+ return "SHOW COLUMNS FROM ".$this->_protect_identifiers($table, TRUE, NULL, FALSE);
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Field data query
+ *
+ * Generates a platform-specific query so that the column data can be retrieved
+ *
+ * @access public
+ * @param string the table name
+ * @return object
+ */
+ function _field_data($table)
+ {
+ return "SELECT * FROM ".$table." LIMIT 1";
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * The error message string
+ *
+ * @access private
+ * @return string
+ */
+ function _error_message()
+ {
+ return cubrid_error($this->conn_id);
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * The error message number
+ *
+ * @access private
+ * @return integer
+ */
+ function _error_number()
+ {
+ return cubrid_errno($this->conn_id);
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Escape the SQL Identifiers
+ *
+ * This function escapes column and table names
+ *
+ * @access private
+ * @param string
+ * @return string
+ */
+ function _escape_identifiers($item)
+ {
+ if ($this->_escape_char == '')
+ {
+ return $item;
+ }
+
+ foreach ($this->_reserved_identifiers as $id)
+ {
+ if (strpos($item, '.'.$id) !== FALSE)
+ {
+ $str = $this->_escape_char. str_replace('.', $this->_escape_char.'.', $item);
+
+ // remove duplicates if the user already included the escape
+ return preg_replace('/['.$this->_escape_char.']+/', $this->_escape_char, $str);
+ }
+ }
+
+ if (strpos($item, '.') !== FALSE)
+ {
+ $str = $this->_escape_char.str_replace('.', $this->_escape_char.'.'.$this->_escape_char, $item).$this->_escape_char;
+ }
+ else
+ {
+ $str = $this->_escape_char.$item.$this->_escape_char;
+ }
+
+ // remove duplicates if the user already included the escape
+ return preg_replace('/['.$this->_escape_char.']+/', $this->_escape_char, $str);
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * From Tables
+ *
+ * This function implicitly groups FROM tables so there is no confusion
+ * about operator precedence in harmony with SQL standards
+ *
+ * @access public
+ * @param type
+ * @return type
+ */
+ function _from_tables($tables)
+ {
+ if ( ! is_array($tables))
+ {
+ $tables = array($tables);
+ }
+
+ return '('.implode(', ', $tables).')';
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Insert statement
+ *
+ * Generates a platform-specific insert string from the supplied data
+ *
+ * @access public
+ * @param string the table name
+ * @param array the insert keys
+ * @param array the insert values
+ * @return string
+ */
+ function _insert($table, $keys, $values)
+ {
+ return "INSERT INTO ".$table." (\"".implode('", "', $keys)."\") VALUES (".implode(', ', $values).")";
+ }
+
+ // --------------------------------------------------------------------
+
+
+ /**
+ * Replace statement
+ *
+ * Generates a platform-specific replace string from the supplied data
+ *
+ * @access public
+ * @param string the table name
+ * @param array the insert keys
+ * @param array the insert values
+ * @return string
+ */
+ function _replace($table, $keys, $values)
+ {
+ return "REPLACE INTO ".$table." (\"".implode('", "', $keys)."\") VALUES (".implode(', ', $values).")";
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Insert_batch statement
+ *
+ * Generates a platform-specific insert string from the supplied data
+ *
+ * @access public
+ * @param string the table name
+ * @param array the insert keys
+ * @param array the insert values
+ * @return string
+ */
+ function _insert_batch($table, $keys, $values)
+ {
+ return "INSERT INTO ".$table." (\"".implode('", "', $keys)."\") VALUES ".implode(', ', $values);
+ }
+
+ // --------------------------------------------------------------------
+
+
+ /**
+ * Update statement
+ *
+ * Generates a platform-specific update string from the supplied data
+ *
+ * @access public
+ * @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
+ * @return string
+ */
+ function _update($table, $values, $where, $orderby = array(), $limit = FALSE)
+ {
+ foreach ($values as $key => $val)
+ {
+ $valstr[] = sprintf('"%s" = %s', $key, $val);
+ }
+
+ $limit = ( ! $limit) ? '' : ' LIMIT '.$limit;
+
+ $orderby = (count($orderby) >= 1)?' ORDER BY '.implode(", ", $orderby):'';
+
+ $sql = "UPDATE ".$table." SET ".implode(', ', $valstr);
+
+ $sql .= ($where != '' AND count($where) >=1) ? " WHERE ".implode(" ", $where) : '';
+
+ $sql .= $orderby.$limit;
+
+ return $sql;
+ }
+
+ // --------------------------------------------------------------------
+
+
+ /**
+ * Update_Batch statement
+ *
+ * Generates a platform-specific batch update string from the supplied data
+ *
+ * @access public
+ * @param string the table name
+ * @param array the update data
+ * @param array the where clause
+ * @return string
+ */
+ function _update_batch($table, $values, $index, $where = NULL)
+ {
+ $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)
+ {
+ $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, ';
+ }
+
+ $sql .= substr($cases, 0, -2);
+
+ $sql .= ' WHERE '.$where.$index.' IN ('.implode(',', $ids).')';
+
+ return $sql;
+ }
+
+ // --------------------------------------------------------------------
+
+
+ /**
+ * Truncate statement
+ *
+ * Generates a platform-specific truncate string from the supplied data
+ * If the database does not support the truncate() command
+ * This function maps to "DELETE FROM table"
+ *
+ * @access public
+ * @param string the table name
+ * @return string
+ */
+ function _truncate($table)
+ {
+ return "TRUNCATE ".$table;
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Delete statement
+ *
+ * Generates a platform-specific delete string from the supplied data
+ *
+ * @access public
+ * @param string the table name
+ * @param array the where clause
+ * @param string the limit clause
+ * @return string
+ */
+ function _delete($table, $where = array(), $like = array(), $limit = FALSE)
+ {
+ $conditions = '';
+
+ if (count($where) > 0 OR count($like) > 0)
+ {
+ $conditions = "\nWHERE ";
+ $conditions .= implode("\n", $this->ar_where);
+
+ if (count($where) > 0 && count($like) > 0)
+ {
+ $conditions .= " AND ";
+ }
+ $conditions .= implode("\n", $like);
+ }
+
+ $limit = ( ! $limit) ? '' : ' LIMIT '.$limit;
+
+ return "DELETE FROM ".$table.$conditions.$limit;
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Limit string
+ *
+ * Generates a platform-specific LIMIT clause
+ *
+ * @access public
+ * @param string the sql query string
+ * @param integer the number of rows to limit the query to
+ * @param integer the offset value
+ * @return string
+ */
+ function _limit($sql, $limit, $offset)
+ {
+ if ($offset == 0)
+ {
+ $offset = '';
+ }
+ else
+ {
+ $offset .= ", ";
+ }
+
+ return $sql."LIMIT ".$offset.$limit;
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Close DB Connection
+ *
+ * @access public
+ * @param resource
+ * @return void
+ */
+ function _close($conn_id)
+ {
+ @cubrid_close($conn_id);
+ }
+
+}
+
+
+/* End of file cubrid_driver.php */
+/* Location: ./system/database/drivers/cubrid/cubrid_driver.php */ \ No newline at end of file
diff --git a/system/database/drivers/cubrid/cubrid_forge.php b/system/database/drivers/cubrid/cubrid_forge.php
new file mode 100644
index 000000000..bab03f748
--- /dev/null
+++ b/system/database/drivers/cubrid/cubrid_forge.php
@@ -0,0 +1,288 @@
+<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');
+/**
+ * CodeIgniter
+ *
+ * An open source application development framework for PHP 5.1.6 or newer
+ *
+ * @package CodeIgniter
+ * @author Esen Sagynov
+ * @copyright Copyright (c) 2008 - 2011, EllisLab, Inc.
+ * @license http://codeigniter.com/user_guide/license.html
+ * @link http://codeigniter.com
+ * @since Version 1.0
+ * @filesource
+ */
+
+// ------------------------------------------------------------------------
+
+/**
+ * CUBRID Forge Class
+ *
+ * @category Database
+ * @author Esen Sagynov
+ * @link http://codeigniter.com/user_guide/database/
+ */
+class CI_DB_cubrid_forge extends CI_DB_forge {
+
+ /**
+ * Create database
+ *
+ * @access private
+ * @param string the database name
+ * @return bool
+ */
+ function _create_database($name)
+ {
+ // CUBRID does not allow to create a database in SQL. The GUI tools
+ // have to be used for this purpose.
+ return FALSE;
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Drop database
+ *
+ * @access private
+ * @param string the database name
+ * @return bool
+ */
+ function _drop_database($name)
+ {
+ // CUBRID does not allow to drop a database in SQL. The GUI tools
+ // have to be used for this purpose.
+ return FALSE;
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Process Fields
+ *
+ * @access private
+ * @param mixed the fields
+ * @return string
+ */
+ 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) . "\"";
+
+ 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'].')';
+ }
+ }
+ }
+
+ 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.
+ }
+
+ 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';
+ }
+
+ 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 .= ',';
+ }
+ }
+
+ return $sql;
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Create Table
+ *
+ * @access private
+ * @param string the table name
+ * @param mixed the fields
+ * @param mixed primary key(s)
+ * @param mixed key(s)
+ * @param boolean should 'IF NOT EXISTS' be added to the SQL
+ * @return bool
+ */
+ function _create_table($table, $fields, $primary_keys, $keys, $if_not_exists)
+ {
+ $sql = 'CREATE TABLE ';
+
+ if ($if_not_exists === TRUE)
+ {
+ //$sql .= 'IF NOT EXISTS ';
+ // As of version 8.4.0 CUBRID does not support this SQL syntax.
+ }
+
+ $sql .= $this->db->_escape_identifiers($table)." (";
+
+ $sql .= $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));
+
+ $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)
+ {
+ 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) . ")";
+ }
+ }
+
+ $sql .= "\n);";
+
+ return $sql;
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Drop Table
+ *
+ * @access private
+ * @return string
+ */
+ function _drop_table($table)
+ {
+ return "DROP TABLE IF EXISTS ".$this->db->_escape_identifiers($table);
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Alter table query
+ *
+ * Generates a platform-specific query so that a table can be altered
+ * Called by add_column(), drop_column(), and column_alter(),
+ *
+ * @access private
+ * @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
+ * @return object
+ */
+ 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);
+ }
+
+ $sql .= $this->_process_fields($fields);
+
+ if ($after_field != '')
+ {
+ $sql .= ' AFTER ' . $this->db->_protect_identifiers($after_field);
+ }
+
+ return $sql;
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Rename a table
+ *
+ * Generates a platform-specific query so that a table can be renamed
+ *
+ * @access private
+ * @param string the old table name
+ * @param string the new table name
+ * @return string
+ */
+ function _rename_table($table_name, $new_table_name)
+ {
+ $sql = 'RENAME TABLE '.$this->db->_protect_identifiers($table_name)." AS ".$this->db->_protect_identifiers($new_table_name);
+ return $sql;
+ }
+
+}
+
+/* End of file cubrid_forge.php */
+/* Location: ./system/database/drivers/cubrid/cubrid_forge.php */ \ No newline at end of file
diff --git a/system/database/drivers/cubrid/cubrid_result.php b/system/database/drivers/cubrid/cubrid_result.php
new file mode 100644
index 000000000..6f0c2b5f7
--- /dev/null
+++ b/system/database/drivers/cubrid/cubrid_result.php
@@ -0,0 +1,202 @@
+<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');
+/**
+ * CodeIgniter
+ *
+ * An open source application development framework for PHP 5.1.6 or newer
+ *
+ * @package CodeIgniter
+ * @author Esen Sagynov
+ * @copyright Copyright (c) 2008 - 2011, EllisLab, Inc.
+ * @license http://codeigniter.com/user_guide/license.html
+ * @link http://codeigniter.com
+ * @since Version 2.0.2
+ * @filesource
+ */
+
+// --------------------------------------------------------------------
+
+/**
+ * CUBRID Result Class
+ *
+ * This class extends the parent result class: CI_DB_result
+ *
+ * @category Database
+ * @author Esen Sagynov
+ * @link http://codeigniter.com/user_guide/database/
+ */
+class CI_DB_cubrid_result extends CI_DB_result {
+
+ /**
+ * Number of rows in the result set
+ *
+ * @access public
+ * @return integer
+ */
+ function num_rows()
+ {
+ return @cubrid_num_rows($this->result_id);
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Number of fields in the result set
+ *
+ * @access public
+ * @return integer
+ */
+ function num_fields()
+ {
+ return @cubrid_num_fields($this->result_id);
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Fetch Field Names
+ *
+ * Generates an array of column names
+ *
+ * @access public
+ * @return array
+ */
+ function list_fields()
+ {
+ return cubrid_column_names($this->result_id);
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Field data
+ *
+ * Generates an array of objects containing field meta-data
+ *
+ * @access public
+ * @return array
+ */
+ function field_data()
+ {
+ $retval = array();
+
+ $tablePrimaryKeys = array();
+
+ while ($field = cubrid_fetch_field($this->result_id))
+ {
+ $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;
+ }
+
+ return $retval;
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Free the result
+ *
+ * @return null
+ */
+ function free_result()
+ {
+ if(is_resource($this->result_id) ||
+ 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;
+ }
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * 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
+ *
+ * @access private
+ * @return array
+ */
+ function _data_seek($n = 0)
+ {
+ return cubrid_data_seek($this->result_id, $n);
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Result - associative array
+ *
+ * Returns the result set as an array
+ *
+ * @access private
+ * @return array
+ */
+ function _fetch_assoc()
+ {
+ return cubrid_fetch_assoc($this->result_id);
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Result - object
+ *
+ * Returns the result set as an object
+ *
+ * @access private
+ * @return object
+ */
+ function _fetch_object()
+ {
+ return cubrid_fetch_object($this->result_id);
+ }
+
+}
+
+
+/* End of file cubrid_result.php */
+/* Location: ./system/database/drivers/cubrid/cubrid_result.php */ \ No newline at end of file
diff --git a/system/database/drivers/cubrid/cubrid_utility.php b/system/database/drivers/cubrid/cubrid_utility.php
new file mode 100644
index 000000000..cd16d1e18
--- /dev/null
+++ b/system/database/drivers/cubrid/cubrid_utility.php
@@ -0,0 +1,108 @@
+<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');
+/**
+ * CodeIgniter
+ *
+ * An open source application development framework for PHP 5.1.6 or newer
+ *
+ * @package CodeIgniter
+ * @author Esen Sagynov
+ * @copyright Copyright (c) 2008 - 2011, EllisLab, Inc.
+ * @license http://codeigniter.com/user_guide/license.html
+ * @link http://codeigniter.com
+ * @since Version 1.0
+ * @filesource
+ */
+
+// ------------------------------------------------------------------------
+
+/**
+ * CUBRID Utility Class
+ *
+ * @category Database
+ * @author Esen Sagynov
+ * @link http://codeigniter.com/user_guide/database/
+ */
+class CI_DB_cubrid_utility extends CI_DB_utility {
+
+ /**
+ * List databases
+ *
+ * @access private
+ * @return array
+ */
+ function _list_databases()
+ {
+ // CUBRID does not allow to see the list of all databases on the
+ // server. It is the way its architecture is designed. Every
+ // database is independent and isolated.
+ // For this reason we can return only the name of the currect
+ // connected database.
+ if ($this->conn_id)
+ {
+ return "SELECT '" . $this->database . "'";
+ }
+ else
+ {
+ return FALSE;
+ }
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Optimize table query
+ *
+ * Generates a platform-specific query so that a table can be optimized
+ *
+ * @access private
+ * @param string the table name
+ * @return object
+ * @link http://www.cubrid.org/manual/840/en/Optimize%20Database
+ */
+ function _optimize_table($table)
+ {
+ // No SQL based support in CUBRID as of version 8.4.0. Database or
+ // table optimization can be performed using CUBRID Manager
+ // database administration tool. See the link above for more info.
+ return FALSE;
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Repair table query
+ *
+ * Generates a platform-specific query so that a table can be repaired
+ *
+ * @access private
+ * @param string the table name
+ * @return object
+ * @link http://www.cubrid.org/manual/840/en/Checking%20Database%20Consistency
+ */
+ function _repair_table($table)
+ {
+ // Not supported in CUBRID as of version 8.4.0. Database or
+ // table consistency can be checked using CUBRID Manager
+ // database administration tool. See the link above for more info.
+ return FALSE;
+ }
+
+ // --------------------------------------------------------------------
+ /**
+ * CUBRID Export
+ *
+ * @access private
+ * @param array Preferences
+ * @return mixed
+ */
+ function _backup($params = array())
+ {
+ // 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');
+ }
+}
+
+/* End of file cubrid_utility.php */
+/* Location: ./system/database/drivers/cubrid/cubrid_utility.php */ \ No newline at end of file
diff --git a/system/database/drivers/cubrid/index.html b/system/database/drivers/cubrid/index.html
new file mode 100644
index 000000000..c942a79ce
--- /dev/null
+++ b/system/database/drivers/cubrid/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/mysql/mysql_driver.php b/system/database/drivers/mysql/mysql_driver.php
index b7d547cc0..28c75a5e3 100644
--- a/system/database/drivers/mysql/mysql_driver.php
+++ b/system/database/drivers/mysql/mysql_driver.php
@@ -54,6 +54,9 @@ class CI_DB_mysql_driver extends CI_DB {
var $_count_string = 'SELECT COUNT(*) AS ';
var $_random_keyword = ' RAND()'; // database specific random keyword
+ // whether SET NAMES must be used to set the character set
+ var $use_set_names;
+
/**
* Non-persistent database connection
*
@@ -132,15 +135,13 @@ class CI_DB_mysql_driver extends CI_DB {
*/
function db_set_charset($charset, $collation)
{
- static $use_set_names;
-
- if ( ! isset($use_set_names))
+ if ( ! isset($this->use_set_names))
{
// mysql_set_charset() requires PHP >= 5.2.3 and MySQL >= 5.0.7, use SET NAMES as fallback
- $use_set_names = (version_compare(PHP_VERSION, '5.2.3', '>=') && version_compare(mysql_get_server_info(), '5.0.7', '>=')) ? FALSE : TRUE;
+ $this->use_set_names = (version_compare(PHP_VERSION, '5.2.3', '>=') && version_compare(mysql_get_server_info(), '5.0.7', '>=')) ? FALSE : TRUE;
}
- if ($use_set_names)
+ if ($this->use_set_names === TRUE)
{
return @mysql_query("SET NAMES '".$this->escape_str($charset)."' COLLATE '".$this->escape_str($collation)."'", $this->conn_id);
}
diff --git a/system/database/drivers/mysql/mysql_forge.php b/system/database/drivers/mysql/mysql_forge.php
index 529ec980d..c1cae136c 100644
--- a/system/database/drivers/mysql/mysql_forge.php
+++ b/system/database/drivers/mysql/mysql_forge.php
@@ -119,9 +119,13 @@ class CI_DB_mysql_forge extends CI_DB_forge {
$sql .= ' DEFAULT \''.$attributes['DEFAULT'].'\'';
}
- if (array_key_exists('NULL', $attributes))
+ if (array_key_exists('NULL', $attributes) && $attributes['NULL'] === TRUE)
{
- $sql .= ($attributes['NULL'] === TRUE) ? ' NULL' : ' NOT NULL';
+ $sql .= ' NULL';
+ }
+ else
+ {
+ $sql .= ' NOT NULL';
}
if (array_key_exists('AUTO_INCREMENT', $attributes) && $attributes['AUTO_INCREMENT'] === TRUE)
diff --git a/system/database/drivers/mysql/mysql_utility.php b/system/database/drivers/mysql/mysql_utility.php
index e9747c540..48c4d6316 100644
--- a/system/database/drivers/mysql/mysql_utility.php
+++ b/system/database/drivers/mysql/mysql_utility.php
@@ -96,7 +96,7 @@ class CI_DB_mysql_utility extends CI_DB_utility {
}
// Get the table schema
- $query = $this->db->query("SHOW CREATE TABLE `".$this->db->database.'`.'.$table);
+ $query = $this->db->query("SHOW CREATE TABLE `".$this->db->database.'`.`'.$table.'`');
// No result means the table name was invalid
if ($query === FALSE)
diff --git a/system/database/drivers/mysqli/mysqli_driver.php b/system/database/drivers/mysqli/mysqli_driver.php
index b8586c21d..b1796c9df 100644
--- a/system/database/drivers/mysqli/mysqli_driver.php
+++ b/system/database/drivers/mysqli/mysqli_driver.php
@@ -54,6 +54,9 @@ class CI_DB_mysqli_driver extends CI_DB {
*/
var $delete_hack = TRUE;
+ // whether SET NAMES must be used to set the character set
+ var $use_set_names;
+
// --------------------------------------------------------------------
/**
@@ -132,15 +135,13 @@ class CI_DB_mysqli_driver extends CI_DB {
*/
function _db_set_charset($charset, $collation)
{
- static $use_set_names;
-
- if ( ! isset($use_set_names))
+ if ( ! isset($this->use_set_names))
{
// mysqli_set_charset() requires MySQL >= 5.0.7, use SET NAMES as fallback
- $use_set_names = (version_compare(mysqli_get_server_info($this->conn_id), '5.0.7', '>=')) ? FALSE : TRUE;
+ $this->use_set_names = (version_compare(mysqli_get_server_info($this->conn_id), '5.0.7', '>=')) ? FALSE : TRUE;
}
- if ($use_set_names)
+ if ($this->use_set_names === TRUE)
{
return @mysqli_query($this->conn_id, "SET NAMES '".$this->escape_str($charset)."' COLLATE '".$this->escape_str($collation)."'");
}
diff --git a/system/database/drivers/mysqli/mysqli_forge.php b/system/database/drivers/mysqli/mysqli_forge.php
index d5097335e..260549457 100644
--- a/system/database/drivers/mysqli/mysqli_forge.php
+++ b/system/database/drivers/mysqli/mysqli_forge.php
@@ -104,9 +104,13 @@ class CI_DB_mysqli_forge extends CI_DB_forge {
$sql .= ' DEFAULT \''.$attributes['DEFAULT'].'\'';
}
- if (array_key_exists('NULL', $attributes))
+ if (array_key_exists('NULL', $attributes) && $attributes['NULL'] === TRUE)
{
- $sql .= ($attributes['NULL'] === TRUE) ? ' NULL' : ' NOT NULL';
+ $sql .= ' NULL';
+ }
+ else
+ {
+ $sql .= ' NOT NULL';
}
if (array_key_exists('AUTO_INCREMENT', $attributes) && $attributes['AUTO_INCREMENT'] === TRUE)
diff --git a/system/helpers/form_helper.php b/system/helpers/form_helper.php
index 2925d3c7c..47f93e748 100644
--- a/system/helpers/form_helper.php
+++ b/system/helpers/form_helper.php
@@ -64,8 +64,8 @@ if ( ! function_exists('form_open'))
$form .= '>';
- // CSRF
- if ($CI->config->item('csrf_protection') === TRUE)
+ // Add CSRF field if enabled, but leave it out for GET requests and requests to external websites
+ if ($CI->config->item('csrf_protection') === TRUE AND ! (strpos($action, $CI->config->site_url()) === FALSE OR strpos($form, 'method="get"')))
{
$hidden[$CI->security->get_csrf_token_name()] = $CI->security->get_csrf_hash();
}
@@ -249,7 +249,7 @@ if ( ! function_exists('form_textarea'))
{
function form_textarea($data = '', $value = '', $extra = '')
{
- $defaults = array('name' => (( ! is_array($data)) ? $data : ''), 'cols' => '90', 'rows' => '12');
+ $defaults = array('name' => (( ! is_array($data)) ? $data : ''), 'cols' => '40', 'rows' => '10');
if ( ! is_array($data) OR ! isset($data['value']))
{
diff --git a/system/helpers/html_helper.php b/system/helpers/html_helper.php
index 080f622dd..b64b60650 100644
--- a/system/helpers/html_helper.php
+++ b/system/helpers/html_helper.php
@@ -124,6 +124,10 @@ if ( ! function_exists('_list'))
}
$attributes = $atts;
}
+ elseif (is_string($attributes) AND strlen($attributes) > 0)
+ {
+ $attributes = ' '. $attributes;
+ }
// Write the opening list tag
$out .= "<".$type.$attributes.">\n";
diff --git a/system/helpers/inflector_helper.php b/system/helpers/inflector_helper.php
index c7c113b8a..7b99bc5b4 100644
--- a/system/helpers/inflector_helper.php
+++ b/system/helpers/inflector_helper.php
@@ -41,30 +41,48 @@ if ( ! function_exists('singular'))
{
function singular($str)
{
- $str = trim($str);
- $end = substr($str, -3);
-
- $str = preg_replace('/(.*)?([s|c]h)es/i','$1$2',$str);
-
- if (strtolower($end) == 'ies')
+ $result = strval($str);
+
+ $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',
+ '/((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',
+ '/([^u])s$/' => '\1',
+ );
+
+ foreach ($singular_rules as $rule => $replacement)
{
- $str = substr($str, 0, strlen($str)-3).(preg_match('/[a-z]/',$end) ? 'y' : 'Y');
- }
- elseif (strtolower($end) == 'ses')
- {
- $str = substr($str, 0, strlen($str)-2);
- }
- else
- {
- $end = strtolower(substr($str, -1));
-
- if ($end == 's')
+ if (preg_match($rule, $result))
{
- $str = substr($str, 0, strlen($str)-1);
+ $result = preg_replace($rule, $replacement, $result);
+ break;
}
}
- return $str;
+ return $result;
}
}
@@ -83,40 +101,41 @@ if ( ! function_exists('singular'))
if ( ! function_exists('plural'))
{
function plural($str, $force = FALSE)
- {
- $str = trim($str);
- $end = substr($str, -1);
-
- if (preg_match('/y/i',$end))
- {
- // Y preceded by vowel => regular plural
- $vowels = array('a', 'e', 'i', 'o', 'u', 'A', 'E', 'I', 'O', 'U');
- $str = in_array(substr($str, -2, 1), $vowels) ? $str.'s' : substr($str, 0, -1).'ies';
- }
- elseif (preg_match('/h/i',$end))
- {
- if(preg_match('/^[c|s]h$/i',substr($str, -2)))
- {
- $str .= 'es';
- }
- else
- {
- $str .= 's';
- }
- }
- elseif (preg_match('/s/i',$end))
+ {
+ $result = strval($str);
+
+ $plural_rules = array(
+ '/^(ox)$/' => '\1\2en', // ox
+ '/([m|l])ouse$/' => '\1ice', // mouse, louse
+ '/(matr|vert|ind)ix|ex$/' => '\1ices', // matrix, vertex, index
+ '/(x|ch|ss|sh)$/' => '\1es', // search, switch, fix, box, process, address
+ '/([^aeiouy]|qu)y$/' => '\1ies', // query, ability, agency
+ '/(hive)$/' => '\1s', // archive, hive
+ '/(?:([^f])fe|([lr])f)$/' => '\1\2ves', // half, safe, wife
+ '/sis$/' => 'ses', // basis, diagnosis
+ '/([ti])um$/' => '\1a', // datum, medium
+ '/(p)erson$/' => '\1eople', // person, salesperson
+ '/(m)an$/' => '\1en', // man, woman, spokesman
+ '/(c)hild$/' => '\1hildren', // child
+ '/(buffal|tomat)o$/' => '\1\2oes', // buffalo, tomato
+ '/(bu|campu)s$/' => '\1\2ses', // bus, campus
+ '/(alias|status|virus)/' => '\1es', // alias
+ '/(octop)us$/' => '\1i', // octopus
+ '/(ax|cris|test)is$/' => '\1es', // axis, crisis
+ '/s$/' => 's', // no change (compatibility)
+ '/$/' => 's',
+ );
+
+ foreach ($plural_rules as $rule => $replacement)
{
- if ($force == TRUE)
+ if (preg_match($rule, $result))
{
- $str .= 'es';
+ $result = preg_replace($rule, $replacement, $result);
+ break;
}
}
- else
- {
- $str .= 's';
- }
- return $str;
+ return $result;
}
}
diff --git a/system/helpers/string_helper.php b/system/helpers/string_helper.php
index 7765bba31..2f928a7d1 100644
--- a/system/helpers/string_helper.php
+++ b/system/helpers/string_helper.php
@@ -243,6 +243,21 @@ if ( ! function_exists('random_string'))
// ------------------------------------------------------------------------
/**
+ * Add's _1 to a string or increment the ending number to allow _2, _3, etc
+ *
+ * @param string $str required
+ * @return string
+ */
+function increment_string($str, $first = 1, $separator = '_')
+{
+ 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...
diff --git a/system/language/english/form_validation_lang.php b/system/language/english/form_validation_lang.php
index 3f2409007..3418f29ab 100644
--- a/system/language/english/form_validation_lang.php
+++ b/system/language/english/form_validation_lang.php
@@ -17,6 +17,7 @@ $lang['is_numeric'] = "The %s field must contain only numeric characters.";
$lang['integer'] = "The %s field must contain an integer.";
$lang['regex_match'] = "The %s field is not in the correct format.";
$lang['matches'] = "The %s field does not match the %s field.";
+$lang['is_unique'] = "The %s field must contain a unique value.";
$lang['is_natural'] = "The %s field must contain only positive numbers.";
$lang['is_natural_no_zero'] = "The %s field must contain a number greater than zero.";
$lang['decimal'] = "The %s field must contain a decimal number.";
diff --git a/system/language/english/migration_lang.php b/system/language/english/migration_lang.php
new file mode 100644
index 000000000..4763ca243
--- /dev/null
+++ b/system/language/english/migration_lang.php
@@ -0,0 +1,13 @@
+<?php
+
+$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 an 'up' 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/libraries/Cart.php b/system/libraries/Cart.php
index 7f65b48b9..ab5a70c98 100644
--- a/system/libraries/Cart.php
+++ b/system/libraries/Cart.php
@@ -99,7 +99,7 @@ class CI_Cart {
$save_cart = FALSE;
if (isset($items['id']))
{
- if ($this->_insert($items) == TRUE)
+ if (($rowid = $this->_insert($items)))
{
$save_cart = TRUE;
}
@@ -110,7 +110,7 @@ class CI_Cart {
{
if (is_array($val) AND isset($val['id']))
{
- if ($this->_insert($val) == TRUE)
+ if ($this->_insert($val))
{
$save_cart = TRUE;
}
@@ -122,7 +122,7 @@ class CI_Cart {
if ($save_cart == TRUE)
{
$this->_save_cart();
- return TRUE;
+ return isset($rowid) ? $rowid : TRUE;
}
return FALSE;
@@ -244,7 +244,7 @@ class CI_Cart {
}
// Woot!
- return TRUE;
+ return $rowid;
}
// --------------------------------------------------------------------
@@ -374,6 +374,7 @@ class CI_Cart {
// Lets add up the individual prices and set the cart sub-total
$total = 0;
+ $items = 0;
foreach ($this->_cart_contents as $key => $val)
{
// We make sure the array contains the proper indexes
@@ -383,13 +384,14 @@ class CI_Cart {
}
$total += ($val['price'] * $val['qty']);
+ $items += $val['qty'];
// Set the subtotal
$this->_cart_contents[$key]['subtotal'] = ($this->_cart_contents[$key]['price'] * $this->_cart_contents[$key]['qty']);
}
// Set the cart total and total items.
- $this->_cart_contents['total_items'] = count($this->_cart_contents);
+ $this->_cart_contents['total_items'] = $items;
$this->_cart_contents['cart_total'] = $total;
// Is our cart empty? If so we delete it from the session
diff --git a/system/libraries/Driver.php b/system/libraries/Driver.php
index c32f2c1eb..9881c1eec 100644
--- a/system/libraries/Driver.php
+++ b/system/libraries/Driver.php
@@ -54,7 +54,7 @@ class CI_Driver_Library {
if ( ! class_exists($child_class))
{
// check application path first
- foreach (array(APPPATH, BASEPATH) as $path)
+ foreach (get_instance()->load->get_package_paths(TRUE) as $path)
{
// loves me some nesting!
foreach (array(ucfirst($driver_name), $driver_name) as $class)
@@ -226,4 +226,4 @@ class CI_Driver {
// END CI_Driver CLASS
/* End of file Driver.php */
-/* Location: ./system/libraries/Driver.php */
+/* Location: ./system/libraries/Driver.php */ \ No newline at end of file
diff --git a/system/libraries/Email.php b/system/libraries/Email.php
index cd89f8f3d..fb9a75049 100644
--- a/system/libraries/Email.php
+++ b/system/libraries/Email.php
@@ -395,7 +395,7 @@ class CI_Email {
public function attach($filename, $disposition = 'attachment')
{
$this->_attach_name[] = $filename;
- $this->_attach_type[] = $this->_mime_types(next(explode('.', basename($filename))));
+ $this->_attach_type[] = $this->_mime_types(pathinfo($filename, PATHINFO_EXTENSION));
$this->_attach_disp[] = $disposition; // Can also be 'inline' Not sure if it matters
return $this;
}
@@ -405,12 +405,12 @@ class CI_Email {
/**
* Add a Header Item
*
- * @access private
+ * @access protected
* @param string
* @param string
* @return void
*/
- private function _set_header($header, $value)
+ protected function _set_header($header, $value)
{
$this->_headers[$header] = $value;
}
@@ -420,11 +420,11 @@ class CI_Email {
/**
* Convert a String to an Array
*
- * @access private
+ * @access protected
* @param string
* @return array
*/
- private function _str_to_array($email)
+ protected function _str_to_array($email)
{
if ( ! is_array($email))
{
@@ -577,10 +577,10 @@ class CI_Email {
/**
* Set Message Boundary
*
- * @access private
+ * @access protected
* @return void
*/
- private function _set_boundaries()
+ protected function _set_boundaries()
{
$this->_alt_boundary = "B_ALT_".uniqid(''); // multipart/alternative
$this->_atc_boundary = "B_ATC_".uniqid(''); // attachment boundary
@@ -591,10 +591,10 @@ class CI_Email {
/**
* Get the Message ID
*
- * @access private
+ * @access protected
* @return string
*/
- private function _get_message_id()
+ protected function _get_message_id()
{
$from = $this->_headers['Return-Path'];
$from = str_replace(">", "", $from);
@@ -608,11 +608,11 @@ class CI_Email {
/**
* Get Mail Protocol
*
- * @access private
+ * @access protected
* @param bool
* @return string
*/
- private function _get_protocol($return = TRUE)
+ protected function _get_protocol($return = TRUE)
{
$this->protocol = strtolower($this->protocol);
$this->protocol = ( ! in_array($this->protocol, $this->_protocols, TRUE)) ? 'mail' : $this->protocol;
@@ -628,11 +628,11 @@ class CI_Email {
/**
* Get Mail Encoding
*
- * @access private
+ * @access protected
* @param bool
* @return string
*/
- private function _get_encoding($return = TRUE)
+ protected function _get_encoding($return = TRUE)
{
$this->_encoding = ( ! in_array($this->_encoding, $this->_bit_depths)) ? '8bit' : $this->_encoding;
@@ -655,10 +655,10 @@ class CI_Email {
/**
* Get content type (text/html/attachment)
*
- * @access private
+ * @access protected
* @return string
*/
- private function _get_content_type()
+ protected function _get_content_type()
{
if ($this->mailtype == 'html' && count($this->_attach_name) == 0)
{
@@ -683,10 +683,10 @@ class CI_Email {
/**
* Set RFC 822 Date
*
- * @access private
+ * @access protected
* @return string
*/
- private function _set_date()
+ protected function _set_date()
{
$timezone = date("Z");
$operator = (strncmp($timezone, '-', 1) == 0) ? '-' : '+';
@@ -701,10 +701,10 @@ class CI_Email {
/**
* Mime message
*
- * @access private
+ * @access protected
* @return string
*/
- private function _get_mime_message()
+ protected function _get_mime_message()
{
return "This is a multi-part message in MIME format.".$this->newline."Your email application may not support this format.";
}
@@ -802,10 +802,10 @@ class CI_Email {
* If the user hasn't specified his own alternative message
* it creates one by stripping the HTML
*
- * @access private
+ * @access protected
* @return string
*/
- private function _get_alt_message()
+ protected function _get_alt_message()
{
if ($this->alt_message != "")
{
@@ -941,11 +941,11 @@ class CI_Email {
/**
* Build final headers
*
- * @access private
+ * @access protected
* @param string
* @return string
*/
- private function _build_headers()
+ protected function _build_headers()
{
$this->_set_header('X-Sender', $this->clean_email($this->_headers['From']));
$this->_set_header('X-Mailer', $this->useragent);
@@ -959,10 +959,10 @@ class CI_Email {
/**
* Write Headers as a string
*
- * @access private
+ * @access protected
* @return void
*/
- private function _write_headers()
+ protected function _write_headers()
{
if ($this->protocol == 'mail')
{
@@ -994,10 +994,10 @@ class CI_Email {
/**
* Build Final Body and attachments
*
- * @access private
+ * @access protected
* @return void
*/
- private function _build_message()
+ protected function _build_message()
{
if ($this->wordwrap === TRUE AND $this->mailtype != 'html')
{
@@ -1177,12 +1177,12 @@ class CI_Email {
* Prepares string for Quoted-Printable Content-Transfer-Encoding
* Refer to RFC 2045 http://www.ietf.org/rfc/rfc2045.txt
*
- * @access private
+ * @access protected
* @param string
* @param integer
* @return string
*/
- private function _prep_quoted_printable($str, $charlim = '')
+ protected function _prep_quoted_printable($str, $charlim = '')
{
// Set the character limit
// Don't allow over 76, as that will make servers and MUAs barf
@@ -1275,7 +1275,7 @@ class CI_Email {
* @param bool // set to TRUE for processing From: headers
* @return str
*/
- private function _prep_q_encoding($str, $from = FALSE)
+ protected function _prep_q_encoding($str, $from = FALSE)
{
$str = str_replace(array("\r", "\n"), array('', ''), $str);
@@ -1440,10 +1440,10 @@ class CI_Email {
/**
* Unwrap special elements
*
- * @access private
+ * @access protected
* @return void
*/
- private function _unwrap_specials()
+ protected function _unwrap_specials()
{
$this->_finalbody = preg_replace_callback("/\{unwrap\}(.*?)\{\/unwrap\}/si", array($this, '_remove_nl_callback'), $this->_finalbody);
}
@@ -1453,10 +1453,10 @@ class CI_Email {
/**
* Strip line-breaks via callback
*
- * @access private
+ * @access protected
* @return string
*/
- private function _remove_nl_callback($matches)
+ protected function _remove_nl_callback($matches)
{
if (strpos($matches[1], "\r") !== FALSE OR strpos($matches[1], "\n") !== FALSE)
{
@@ -1471,10 +1471,10 @@ class CI_Email {
/**
* Spool mail to the mail server
*
- * @access private
+ * @access protected
* @return bool
*/
- private function _spool_email()
+ protected function _spool_email()
{
$this->_unwrap_specials();
@@ -1516,10 +1516,10 @@ class CI_Email {
/**
* Send using mail()
*
- * @access private
+ * @access protected
* @return bool
*/
- private function _send_with_mail()
+ protected function _send_with_mail()
{
if ($this->_safe_mode == TRUE)
{
@@ -1553,10 +1553,10 @@ class CI_Email {
/**
* Send using Sendmail
*
- * @access private
+ * @access protected
* @return bool
*/
- private function _send_with_sendmail()
+ protected function _send_with_sendmail()
{
$fp = @popen($this->mailpath . " -oi -f ".$this->clean_email($this->_headers['From'])." -t", 'w');
@@ -1591,10 +1591,10 @@ class CI_Email {
/**
* Send using SMTP
*
- * @access private
+ * @access protected
* @return bool
*/
- private function _send_with_smtp()
+ protected function _send_with_smtp()
{
if ($this->smtp_host == '')
{
@@ -1660,11 +1660,11 @@ class CI_Email {
/**
* SMTP Connect
*
- * @access private
+ * @access protected
* @param string
* @return string
*/
- private function _smtp_connect()
+ protected function _smtp_connect()
{
$this->_smtp_connect = fsockopen($this->smtp_host,
$this->smtp_port,
@@ -1687,12 +1687,12 @@ class CI_Email {
/**
* Send SMTP command
*
- * @access private
+ * @access protected
* @param string
* @param string
* @return string
*/
- private function _send_command($cmd, $data = '')
+ protected function _send_command($cmd, $data = '')
{
switch ($cmd)
{
@@ -1754,10 +1754,10 @@ class CI_Email {
/**
* SMTP Authenticate
*
- * @access private
+ * @access protected
* @return bool
*/
- private function _smtp_authenticate()
+ protected function _smtp_authenticate()
{
if ( ! $this->_smtp_auth)
{
@@ -1808,10 +1808,10 @@ class CI_Email {
/**
* Send SMTP data
*
- * @access private
+ * @access protected
* @return bool
*/
- private function _send_data($data)
+ protected function _send_data($data)
{
if ( ! fwrite($this->_smtp_connect, $data . $this->newline))
{
@@ -1829,10 +1829,10 @@ class CI_Email {
/**
* Get SMTP data
*
- * @access private
+ * @access protected
* @return string
*/
- private function _get_smtp_data()
+ protected function _get_smtp_data()
{
$data = "";
@@ -1854,10 +1854,10 @@ class CI_Email {
/**
* Get Hostname
*
- * @access private
+ * @access protected
* @return string
*/
- private function _get_hostname()
+ protected function _get_hostname()
{
return (isset($_SERVER['SERVER_NAME'])) ? $_SERVER['SERVER_NAME'] : 'localhost.localdomain';
}
@@ -1867,10 +1867,10 @@ class CI_Email {
/**
* Get IP
*
- * @access private
+ * @access protected
* @return string
*/
- private function _get_ip()
+ protected function _get_ip()
{
if ($this->_IP !== FALSE)
{
@@ -1933,11 +1933,11 @@ class CI_Email {
/**
* Set Message
*
- * @access private
+ * @access protected
* @param string
* @return string
*/
- private function _set_error_message($msg, $val = '')
+ protected function _set_error_message($msg, $val = '')
{
$CI =& get_instance();
$CI->lang->load('email');
@@ -1957,11 +1957,11 @@ class CI_Email {
/**
* Mime Types
*
- * @access private
+ * @access protected
* @param string
* @return string
*/
- private function _mime_types($ext = "")
+ protected function _mime_types($ext = "")
{
$mimes = array( 'hqx' => 'application/mac-binhex40',
'cpt' => 'application/mac-compactpro',
diff --git a/system/libraries/Form_validation.php b/system/libraries/Form_validation.php
index 6f79a554a..a34809e05 100644
--- a/system/libraries/Form_validation.php
+++ b/system/libraries/Form_validation.php
@@ -26,16 +26,15 @@
*/
class CI_Form_validation {
- var $CI;
- var $_field_data = array();
- var $_config_rules = array();
- var $_error_array = array();
- var $_error_messages = array();
- var $_error_prefix = '<p>';
- var $_error_suffix = '</p>';
- var $error_string = '';
- var $_safe_form_data = FALSE;
-
+ protected $CI;
+ protected $_field_data = array();
+ protected $_config_rules = array();
+ protected $_error_array = array();
+ protected $_error_messages = array();
+ protected $_error_prefix = '<p>';
+ protected $_error_suffix = '</p>';
+ protected $error_string = '';
+ protected $_safe_form_data = FALSE;
/**
* Constructor
@@ -72,7 +71,7 @@ class CI_Form_validation {
* @param string
* @return void
*/
- function set_rules($field, $label = '', $rules = '')
+ public function set_rules($field, $label = '', $rules = '')
{
// No reason to set rules if we have no POST data
if (count($_POST) == 0)
@@ -163,7 +162,7 @@ class CI_Form_validation {
* @param string
* @return string
*/
- function set_message($lang, $val = '')
+ public function set_message($lang, $val = '')
{
if ( ! is_array($lang))
{
@@ -187,7 +186,7 @@ class CI_Form_validation {
* @param string
* @return void
*/
- function set_error_delimiters($prefix = '<p>', $suffix = '</p>')
+ public function set_error_delimiters($prefix = '<p>', $suffix = '</p>')
{
$this->_error_prefix = $prefix;
$this->_error_suffix = $suffix;
@@ -206,7 +205,7 @@ class CI_Form_validation {
* @param string the field name
* @return void
*/
- function error($field = '', $prefix = '', $suffix = '')
+ public function error($field = '', $prefix = '', $suffix = '')
{
if ( ! isset($this->_field_data[$field]['error']) OR $this->_field_data[$field]['error'] == '')
{
@@ -238,7 +237,7 @@ class CI_Form_validation {
* @param string
* @return str
*/
- function error_string($prefix = '', $suffix = '')
+ public function error_string($prefix = '', $suffix = '')
{
// No errrors, validation passes!
if (count($this->_error_array) === 0)
@@ -279,7 +278,7 @@ class CI_Form_validation {
* @access public
* @return bool
*/
- function run($group = '')
+ public function run($group = '')
{
// Do we even have any data to process? Mm?
if (count($_POST) == 0)
@@ -374,7 +373,7 @@ class CI_Form_validation {
* @param integer
* @return mixed
*/
- function _reduce_array($array, $keys, $i = 0)
+ protected function _reduce_array($array, $keys, $i = 0)
{
if (is_array($array))
{
@@ -406,7 +405,7 @@ class CI_Form_validation {
* @access private
* @return null
*/
- function _reset_post_array()
+ protected function _reset_post_array()
{
foreach ($this->_field_data as $field => $row)
{
@@ -468,7 +467,7 @@ class CI_Form_validation {
* @param integer
* @return mixed
*/
- function _execute($row, $rules, $postdata = NULL, $cycles = 0)
+ protected function _execute($row, $rules, $postdata = NULL, $cycles = 0)
{
// If the $_POST data is an array we will run a recursive call
if (is_array($postdata))
@@ -489,7 +488,7 @@ class CI_Form_validation {
if ( ! in_array('required', $rules) AND is_null($postdata))
{
// Before we bail out, does the rule contain a callback?
- if (preg_match("/(callback_\w+)/", implode(' ', $rules), $match))
+ if (preg_match("/(callback_\w+(\[.*?\])?)/", implode(' ', $rules), $match))
{
$callback = TRUE;
$rules = (array('1' => $match[1]));
@@ -695,7 +694,7 @@ class CI_Form_validation {
* @param string the field name
* @return string
*/
- function _translate_fieldname($fieldname)
+ protected function _translate_fieldname($fieldname)
{
// Do we need to translate the field name?
// We look for the prefix lang: to determine this
@@ -727,7 +726,7 @@ class CI_Form_validation {
* @param string
* @return void
*/
- function set_value($field = '', $default = '')
+ public function set_value($field = '', $default = '')
{
if ( ! isset($this->_field_data[$field]))
{
@@ -757,7 +756,7 @@ class CI_Form_validation {
* @param string
* @return string
*/
- function set_select($field = '', $value = '', $default = FALSE)
+ public function set_select($field = '', $value = '', $default = FALSE)
{
if ( ! isset($this->_field_data[$field]) OR ! isset($this->_field_data[$field]['postdata']))
{
@@ -801,7 +800,7 @@ class CI_Form_validation {
* @param string
* @return string
*/
- function set_radio($field = '', $value = '', $default = FALSE)
+ public function set_radio($field = '', $value = '', $default = FALSE)
{
if ( ! isset($this->_field_data[$field]) OR ! isset($this->_field_data[$field]['postdata']))
{
@@ -845,7 +844,7 @@ class CI_Form_validation {
* @param string
* @return string
*/
- function set_checkbox($field = '', $value = '', $default = FALSE)
+ public function set_checkbox($field = '', $value = '', $default = FALSE)
{
if ( ! isset($this->_field_data[$field]) OR ! isset($this->_field_data[$field]['postdata']))
{
@@ -885,7 +884,7 @@ class CI_Form_validation {
* @param string
* @return bool
*/
- function required($str)
+ public function required($str)
{
if ( ! is_array($str))
{
@@ -907,7 +906,7 @@ class CI_Form_validation {
* @param regex
* @return bool
*/
- function regex_match($str, $regex)
+ public function regex_match($str, $regex)
{
if ( ! preg_match($regex, $str))
{
@@ -927,7 +926,7 @@ class CI_Form_validation {
* @param field
* @return bool
*/
- function matches($str, $field)
+ public function matches($str, $field)
{
if ( ! isset($_POST[$field]))
{
@@ -938,6 +937,24 @@ class CI_Form_validation {
return ($str !== $field) ? FALSE : TRUE;
}
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Match one field to another
+ *
+ * @access public
+ * @param string
+ * @param field
+ * @return bool
+ */
+ public function is_unique($str, $field)
+ {
+ list($table, $field)=explode('.', $field);
+ $query = $this->CI->db->limit(1)->get_where($table, array($field => $str));
+
+ return $query->num_rows() === 0;
+ }
// --------------------------------------------------------------------
@@ -949,7 +966,7 @@ class CI_Form_validation {
* @param value
* @return bool
*/
- function min_length($str, $val)
+ public function min_length($str, $val)
{
if (preg_match("/[^0-9]/", $val))
{
@@ -974,7 +991,7 @@ class CI_Form_validation {
* @param value
* @return bool
*/
- function max_length($str, $val)
+ public function max_length($str, $val)
{
if (preg_match("/[^0-9]/", $val))
{
@@ -999,7 +1016,7 @@ class CI_Form_validation {
* @param value
* @return bool
*/
- function exact_length($str, $val)
+ public function exact_length($str, $val)
{
if (preg_match("/[^0-9]/", $val))
{
@@ -1023,7 +1040,7 @@ class CI_Form_validation {
* @param string
* @return bool
*/
- function valid_email($str)
+ public function valid_email($str)
{
return ( ! preg_match("/^([a-z0-9\+_\-]+)(\.[a-z0-9\+_\-]+)*@([a-z0-9\-]+\.)+[a-z]{2,6}$/ix", $str)) ? FALSE : TRUE;
}
@@ -1037,7 +1054,7 @@ class CI_Form_validation {
* @param string
* @return bool
*/
- function valid_emails($str)
+ public function valid_emails($str)
{
if (strpos($str, ',') === FALSE)
{
@@ -1064,7 +1081,7 @@ class CI_Form_validation {
* @param string
* @return string
*/
- function valid_ip($ip)
+ public function valid_ip($ip)
{
return $this->CI->input->valid_ip($ip);
}
@@ -1078,7 +1095,7 @@ class CI_Form_validation {
* @param string
* @return bool
*/
- function alpha($str)
+ public function alpha($str)
{
return ( ! preg_match("/^([a-z])+$/i", $str)) ? FALSE : TRUE;
}
@@ -1092,7 +1109,7 @@ class CI_Form_validation {
* @param string
* @return bool
*/
- function alpha_numeric($str)
+ public function alpha_numeric($str)
{
return ( ! preg_match("/^([a-z0-9])+$/i", $str)) ? FALSE : TRUE;
}
@@ -1106,7 +1123,7 @@ class CI_Form_validation {
* @param string
* @return bool
*/
- function alpha_dash($str)
+ public function alpha_dash($str)
{
return ( ! preg_match("/^([-a-z0-9_-])+$/i", $str)) ? FALSE : TRUE;
}
@@ -1120,7 +1137,7 @@ class CI_Form_validation {
* @param string
* @return bool
*/
- function numeric($str)
+ public function numeric($str)
{
return (bool)preg_match( '/^[\-+]?[0-9]*\.?[0-9]+$/', $str);
@@ -1135,7 +1152,7 @@ class CI_Form_validation {
* @param string
* @return bool
*/
- function is_numeric($str)
+ public function is_numeric($str)
{
return ( ! is_numeric($str)) ? FALSE : TRUE;
}
@@ -1149,7 +1166,7 @@ class CI_Form_validation {
* @param string
* @return bool
*/
- function integer($str)
+ public function integer($str)
{
return (bool) preg_match('/^[\-+]?[0-9]+$/', $str);
}
@@ -1163,7 +1180,7 @@ class CI_Form_validation {
* @param string
* @return bool
*/
- function decimal($str)
+ public function decimal($str)
{
return (bool) preg_match('/^[\-+]?[0-9]+\.[0-9]+$/', $str);
}
@@ -1177,7 +1194,7 @@ class CI_Form_validation {
* @param string
* @return bool
*/
- function greater_than($str, $min)
+ public function greater_than($str, $min)
{
if ( ! is_numeric($str))
{
@@ -1195,7 +1212,7 @@ class CI_Form_validation {
* @param string
* @return bool
*/
- function less_than($str, $max)
+ public function less_than($str, $max)
{
if ( ! is_numeric($str))
{
@@ -1213,7 +1230,7 @@ class CI_Form_validation {
* @param string
* @return bool
*/
- function is_natural($str)
+ public function is_natural($str)
{
return (bool) preg_match( '/^[0-9]+$/', $str);
}
@@ -1227,7 +1244,7 @@ class CI_Form_validation {
* @param string
* @return bool
*/
- function is_natural_no_zero($str)
+ public function is_natural_no_zero($str)
{
if ( ! preg_match( '/^[0-9]+$/', $str))
{
@@ -1254,7 +1271,7 @@ class CI_Form_validation {
* @param string
* @return bool
*/
- function valid_base64($str)
+ public function valid_base64($str)
{
return (bool) ! preg_match('/[^a-zA-Z0-9\/\+=]/', $str);
}
@@ -1271,7 +1288,7 @@ class CI_Form_validation {
* @param string
* @return string
*/
- function prep_for_form($data = '')
+ public function prep_for_form($data = '')
{
if (is_array($data))
{
@@ -1300,7 +1317,7 @@ class CI_Form_validation {
* @param string
* @return string
*/
- function prep_url($str = '')
+ public function prep_url($str = '')
{
if ($str == 'http://' OR $str == '')
{
@@ -1324,7 +1341,7 @@ class CI_Form_validation {
* @param string
* @return string
*/
- function strip_image_tags($str)
+ public function strip_image_tags($str)
{
return $this->CI->input->strip_image_tags($str);
}
@@ -1338,7 +1355,7 @@ class CI_Form_validation {
* @param string
* @return string
*/
- function xss_clean($str)
+ public function xss_clean($str)
{
return $this->CI->security->xss_clean($str);
}
@@ -1352,7 +1369,7 @@ class CI_Form_validation {
* @param string
* @return string
*/
- function encode_php_tags($str)
+ public function encode_php_tags($str)
{
return str_replace(array('<?php', '<?PHP', '<?', '?>'), array('&lt;?php', '&lt;?PHP', '&lt;?', '?&gt;'), $str);
}
diff --git a/system/libraries/Migration.php b/system/libraries/Migration.php
new file mode 100644
index 000000000..3943ec130
--- /dev/null
+++ b/system/libraries/Migration.php
@@ -0,0 +1,338 @@
+<?php defined('BASEPATH') OR exit('No direct script access allowed');
+/**
+ * CodeIgniter
+ *
+ * An open source application development framework for PHP 5.1.6 or newer
+ *
+ * @package CodeIgniter
+ * @author EllisLab Dev Team
+ * @copyright Copyright (c) 2006 - 2011, EllisLab, Inc.
+ * @license http://codeigniter.com/user_guide/license.html
+ * @link http://codeigniter.com
+ * @since Version 1.0
+ * @filesource
+ */
+
+// ------------------------------------------------------------------------
+
+/**
+ * Migration Class
+ *
+ * All migrations should implement this, forces up() and down() and gives
+ * access to the CI super-global.
+ *
+ * @package CodeIgniter
+ * @subpackage Libraries
+ * @category Libraries
+ * @author Reactor Engineers
+ * @link
+ */
+class CI_Migration {
+
+ protected $_migration_enabled = FALSE;
+ protected $_migration_path = NULL;
+ protected $_migration_version = 0;
+
+ protected $_error_string = '';
+
+ public function __construct($config = array())
+ {
+ # Only run this constructor on main library load
+ if (get_parent_class($this) !== FALSE)
+ {
+ return;
+ }
+
+ foreach ($config as $key => $val)
+ {
+ $this->{'_' . $key} = $val;
+ }
+
+ log_message('debug', 'Migrations class initialized');
+
+ // Are they trying to use migrations while it is disabled?
+ if ($this->_migration_enabled !== TRUE)
+ {
+ show_error('Migrations has been loaded but is disabled or set up incorrectly.');
+ }
+
+ // If not set, set it
+ $this->_migration_path == '' OR $this->_migration_path = APPPATH . 'migrations/';
+
+ // Add trailing slash if not set
+ $this->_migration_path = rtrim($this->_migration_path, '/').'/';
+
+ // Load migration language
+ $this->lang->load('migration');
+
+ // They'll probably be using dbforge
+ $this->load->dbforge();
+
+ // If the migrations table is missing, make it
+ if ( ! $this->db->table_exists('migrations'))
+ {
+ $this->dbforge->add_field(array(
+ 'version' => array('type' => 'INT', 'constraint' => 3),
+ ));
+
+ $this->dbforge->create_table('migrations', TRUE);
+
+ $this->db->insert('migrations', array('version' => 0));
+ }
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Migrate to a schema version
+ *
+ * Calls each migration step required to get to the schema version of
+ * choice
+ *
+ * @access public
+ * @param $version integer 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;
+
+ if ($target_version > $current_version)
+ {
+ // Moving Up
+ ++$start;
+ ++$stop;
+ $step = 1;
+ }
+
+ else
+ {
+ // Moving Down
+ $step = -1;
+ }
+
+ $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)
+ {
+ $f = glob(sprintf($this->_migration_path . '%03d_*.php', $i));
+
+ // Only one migration per step is permitted
+ if (count($f) > 1)
+ {
+ $this->_error_string = sprintf($this->lang->line('migration_multiple_version'), $i);
+ 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;
+ }
+
+ // 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);
+ return FALSE;
+ }
+
+ $file = basename($f[0]);
+ $name = basename($f[0], '.php');
+
+ // Filename validations
+ if (preg_match('/^\d{3}_(\w+)$/', $name, $match))
+ {
+ $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)))
+ {
+ $this->_error_string = sprintf($this->lang->line('migration_missing_'.$method.'_method'), $class);
+ return FALSE;
+ }
+
+ $migrations[] = $match[1];
+ }
+ 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)
+ {
+ // Run the migration class
+ $class = 'Migration_' . ucfirst(strtolower($migration));
+ call_user_func(array(new $class, $method));
+
+ $current_version += $step;
+ $this->_update_version($current_version);
+ }
+
+ log_message('debug', 'Finished migrating to '.$current_version);
+
+ return $current_version;
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Set's the schema to the latest migration
+ *
+ * @access public
+ * @return mixed true if already latest, false if failed, int if upgraded
+ */
+ public function latest()
+ {
+ if ( ! $migrations = $this->find_migrations())
+ {
+ $this->_error_string = $this->line->lang('migration_none_found');
+ 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));
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Set's the schema to the migration version set in config
+ *
+ * @access public
+ * @return mixed true if already current, false if failed, int if upgraded
+ */
+ public function current()
+ {
+ return $this->version($this->_migration_version);
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Error string
+ *
+ * @access public
+ * @return string Error message returned as a string
+ */
+ public function error_string()
+ {
+ return $this->_error_string;
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Set's the schema to the latest migration
+ *
+ * @access protected
+ * @return mixed true if already latest, false if failed, int if upgraded
+ */
+ protected function find_migrations()
+ {
+ // Load all *_*.php files in the migrations path
+ $files = glob($this->_migration_path . '*_*.php');
+ $file_count = count($files);
+
+ for ($i = 0; $i < $file_count; $i++)
+ {
+ // Mark wrongly formatted files as false for later filtering
+ $name = basename($files[$i], '.php');
+ if ( ! preg_match('/^\d{3}_(\w+)$/', $name))
+ {
+ $files[$i] = FALSE;
+ }
+ }
+
+ sort($files);
+
+ return $files;
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Retrieves current schema version
+ *
+ * @access protected
+ * @return integer Current Migration
+ */
+ protected function _get_version()
+ {
+ $row = $this->db->get('migrations')->row();
+ return $row ? $row->version : 0;
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Stores the current schema version
+ *
+ * @access protected
+ * @param $migrations integer Migration reached
+ * @return void Outputs a report of the migration
+ */
+ protected function _update_version($migrations)
+ {
+ return $this->db->update('migrations', array(
+ 'version' => $migrations
+ ));
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Enable the use of CI super-global
+ *
+ * @access public
+ * @param $var
+ * @return mixed
+ */
+ public function __get($var)
+ {
+ return get_instance()->$var;
+ }
+}
+
+/* End of file Migration.php */
+/* Location: ./system/libraries/Migration.php */ \ No newline at end of file
diff --git a/system/libraries/User_agent.php b/system/libraries/User_agent.php
index 016102a2a..0b77a7d42 100644
--- a/system/libraries/User_agent.php
+++ b/system/libraries/User_agent.php
@@ -142,7 +142,7 @@ class CI_User_agent {
{
$this->_set_platform();
- foreach (array('_set_browser', '_set_robot', '_set_mobile') as $function)
+ foreach (array('_set_robot', '_set_browser', '_set_mobile') as $function)
{
if ($this->$function() === TRUE)
{
diff --git a/user_guide/changelog.html b/user_guide/changelog.html
index c1ee37fc5..8f0fad783 100644
--- a/user_guide/changelog.html
+++ b/user_guide/changelog.html
@@ -59,6 +59,43 @@ Change Log
<p>The <img src="images/reactor-bullet.png" width="16" height="16" alt="Reactor Marker" /> indicates items that were contributed to CodeIgniter via CodeIgniter Reactor.</p>
+<h2>Version 2.1.0</h2>
+<p>Release Date: Not Released</p>
+
+<ul>
+ <li>General Changes
+ <ul>
+ <li class="reactor">Callback validation rules can now accept parameters like any other validation rule.</li>
+ </ul>
+ </li>
+ <li>Helpers
+ <ul>
+ </ul>
+ </li>
+ <li>Database
+ <ul>
+ <li class="reactor">Added a <a href="http://www.cubrid.org/" target="_blank">CUBRID</a> driver to the <a href="libraries/database.html">Database Driver</a>. Thanks to the CUBRID team for supplying this patch.</li>
+ <li class="reactor">Typecast limit and offset in the <a href="database/queries.html">Database Driver</a> to integers to avoid possible injection.</li>
+ </ul>
+ </li>
+ <li>Libraries
+ <ul>
+ <li class="reactor">Changed <kbd>$this->cart->insert()</kbd> in the <a href="libraries/cart.html">Cart Library</a> to return the Row ID if a single item was inserted successfully.</li>
+ <li class="reactor">Added support to set an optional parameter in your callback rules of validation using the <a href="libraries/form_validation.html">Form Validation Library</a>.</li>
+ <li class="reactor">Added a <a href="libraries/migration.html">Migration Library</a> to assist with applying incremental updates to your database schema.</li>
+ <li class="reactor">Driver children can be located in any package path.</li>
+ </ul>
+ </li>
+</ul>
+
+<h3>Bug fixes for 2.1.0</h3>
+<ul>
+ <li class="reactor">Fixed #378 Robots identified as regular browsers by the User Agent class.</li>
+ <li class="reactor">If a config class was loaded first then a library with the same name is loaded, the config would be ignored.</li>
+ <li class="reactor">Fixed a bug (Reactor #19) where 1) the 404_override route was being ignored in some cases, and 2) auto-loaded libraries were not available to the 404_override controller when a controller existed but the requested method did not.</li>
+ <li class="rector">Fixed a bug (Reactor #89) where MySQL export would fail if the table had hyphens or other non alphanumeric/underscore characters.</li>
+</ul>
+
<h2>Version 2.0.3</h2>
<p>Release Date: Not Released</p>
@@ -67,23 +104,32 @@ Change Log
<ul>
<li>An improvement was made to the MySQL and MySQLi drivers to prevent exposing a potential vector for SQL injection on sites using multi-byte character sets in the database client connection. <p>An incompatibility in PHP versions &lt; 5.2.3 and MySQL &lt; 5.0.7 with <em>mysql_set_charset()</em> creates a situation where using multi-byte character sets on these environments may potentially expose a SQL injection attack vector. Latin-1, UTF-8, and other "low ASCII" character sets are unaffected on all environments.</p> <p class="critical">If you are running or considering running a multi-byte character set for your database connection, please pay close attention to the server environment you are deploying on to ensure you are not vulnerable.</p></li>
</ul>
+ </li>
<li>General Changes
<ul>
<li>Fixed a bug where there was a misspelling within a code comment in the index.php file.</li>
<li>Added Session Class userdata to the output profiler. Additionally, added a show/hide toggle on HTTP Headers, Session Data and Config Variables.</li>
<li>Removed internal usage of the <samp>EXT</samp> constant.</li>
<li>Visual updates to the welcome_message view file and default error templates. Thanks to <a href="https://bitbucket.org/danijelb">danijelb</a> for the pull request.</li>
- <li>Added <samp>insert_batch()</samp> function to the PostgreSQL database driver. Thanks to epallerols for the patch.</li>
+ <li class="reactor">Added <samp>insert_batch()</samp> function to the PostgreSQL database driver. Thanks to epallerols for the patch.</li>
+ <li class="reactor">Added "application/x-csv" to mimes.php.</li>
</ul>
</li>
<li>Helpers
<ul>
<li>Added an optional third parameter to <samp>heading()</samp> which allows adding html attributes to the rendered heading tag.</li>
+ <li class="reactor"><kbd>form_open()</kbd> now only adds a hidden (Cross-site Reference Forgery) protection field when the form's action is internal and is set to the post method. (Reactor #165)</li>
+ <li class="reactor">Re-worked <samp>plural()</samp> and <samp>singular()</samp> functions in the <a href="helpers/inflector_helper.html">Inflector helper</a> to support considerably more words.</li>
</ul>
</li>
<li>Libraries
<ul>
<li>Altered Session to use a longer match against the user_agent string. See upgrade notes if using database sessions.</li>
+ <li class="reactor">Added <kbd>is_unique</kbd> to the <a href="libraries/form_validation.html">Form Validation library</a>.</li>
+ <li class="reactor">Added <kbd>$this->db->set_dbprefix()</kbd> to the <a href="database/queries.html">Database Driver</a>.</li>
+ <li class="reactor">Changed <kbd>$this->cart->insert()</kbd> in the <a href="libraries/cart.html">Cart Library</a> to return the Row ID if a single item was inserted successfully.</li>
+ <li class="reactor">Added <kbd>$this->load->get_var()</kbd> to the <a href="libraries/loader.html">Loader library</a> to retrieve global vars set with <kbd>$this->load->view()</kbd> and <kbd>$this->load->vars()</kbd>.</li>
+ <li class="reactor">Changed <kbd>$this->db->having()</kbd> to insert quotes using escape() rather than escape_str().</li>
</ul>
</li>
</ul>
@@ -96,6 +142,12 @@ Change Log
<li>Fixed a bug (Reactor #231) where Sessions Library database table example SQL did not contain an index on last_activity. See <a href="installation/upgrade_203.html">Upgrade Notes</a>.</li>
<li>Fixed a bug (Reactor #229) where the Sessions Library example SQL in the documentation contained incorrect SQL.</li>
<li>Fixed a bug (Core #340) where when passing in the second parameter to $this->db->select(), column names in subsequent queries would not be properly escaped.</li>
+ <li class="reactor">Fixed issue #199 - Attributes passed as string does not include a space between it and the opening tag.</li>
+ <li class="reactor">Fixed a bug where the method <kbd>$this->cart->total_items()</kbd> from <a href="libraries/cart.html">Cart Library</a> now returns the sum of the quantity of all items in the cart instead of your total count.</li>
+ <li class="reactor">Fixed a bug where not setting 'null' when adding fields in db_forge for MySQL and MySQLi drivers would default to NULL instead of NOT NULL as the docs suggest.</li>
+ <li class="reactor">Fixed a bug where using <kbd>$this->db->select_max()</kdb>, <kbd>$this->db->select_min()</kdb>, etc could throw notices. Thanks to w43l for the patch.</li>
+ <li class="reactor">Replace checks for STDIN with php_sapi_name() == 'cli' which on the whole is more reliable. This should get parameters in crontab working.</li>
+ <li>Fixed a bug where <a href="libraries/email.html">Email library</a> attachments with a "." in the name would using invalid MIME-types.</li>
</ul>
<h2>Version 2.0.2</h2>
diff --git a/user_guide/database/configuration.html b/user_guide/database/configuration.html
index 51d11c9f2..4ea2e6b3d 100644
--- a/user_guide/database/configuration.html
+++ b/user_guide/database/configuration.html
@@ -132,8 +132,8 @@ for the primary connection, but it too can be renamed to something more relevant
<li><strong>cache_on</strong> - TRUE/FALSE (boolean) - Whether database query caching is enabled, see also <a href="caching.html">Database Caching Class</a>.</li>
<li><strong>cachedir</strong> - The absolute server path to your database query cache directory.</li>
<li><strong>char_set</strong> - The character set used in communicating with the database.</li>
-<li><strong>dbcollat</strong> - The character collation used in communicating with the database. <p class="important"><strong>Note:</strong> For MySQL and MySQLi databases, this setting is only used as a backup if your server is running PHP &lt; 5.2.3 or MySQL &lt; 5.0.7. There is an incompatibility in PHP with mysql_real_escape_string() which can make your site vulnerable to SQL injection if you are using a multi-byte character set and are running versions lower than these. Sites using Latin-1 or UTF-8 database character set and collation are unaffected.</p></li>
-<li><strong>swap_pre</strong> - A default table prefix that should be swapped with <var>dbprefix</var>. This is useful for distributed applications where you might run manually written queries, and need the prefix to still be customizable by the end user.</li>
+<li><strong>dbcollat</strong> - The character collation used in communicating with the database. <p class="important"><strong>Note:</strong> For MySQL and MySQLi databases, this setting is only used as a backup if your server is running PHP &lt; 5.2.3 or MySQL &lt; 5.0.7 (and in table creation queries made with DB Forge). There is an incompatibility in PHP with mysql_real_escape_string() which can make your site vulnerable to SQL injection if you are using a multi-byte character set and are running versions lower than these. Sites using Latin-1 or UTF-8 database character set and collation are unaffected.</p></li>
+<li><strong>swap_pre</strong> - A default table prefix that should be swapped with <var>dbprefix</var>. This is useful for distributed applications where you might run manually written queries, and need the prefix to still be customizable by the end user.</li>
<li><strong>autoinit</strong> - Whether or not to automatically connect to the database when the library loads. If set to false, the connection will take place prior to executing the first query.</li>
<li><strong>stricton</strong> - TRUE/FALSE (boolean) - Whether to force "Strict Mode" connections, good for ensuring strict SQL while developing an application.</li>
<li><strong>port</strong> - The database port number. To use this value you have to add a line to the database config array.<code>$db['default']['port'] = 5432;</code>
diff --git a/user_guide/database/queries.html b/user_guide/database/queries.html
index f9f96803f..4c1ddfe7d 100644
--- a/user_guide/database/queries.html
+++ b/user_guide/database/queries.html
@@ -80,11 +80,16 @@ It DOES NOT return a database result set, nor does it set the query timer, or co
It simply lets you submit a query. Most users will rarely use this function.</p>
-<h1>Adding Database prefixes manually</h1>
-<p>If you have configured a database prefix and would like to add it in manually for, you can use the following.</p>
+<h1>Working with Database prefixes manually</h1>
+<p>If you have configured a database prefix and would like to prepend it to a table name for use in a native SQL query for example, then you can use the following:</p>
<p><code>$this-&gt;db-&gt;dbprefix('tablename');<br />
// outputs prefix_tablename</code></p>
+<p>If for any reason you would like to change the prefix programatically without needing to create a new connection, you can use this method:</p>
+<p><code>$this-&gt;db-&gt;set_dbprefix('newprefix');<br /><br />
+$this-&gt;db-&gt;dbprefix('tablename');<br />
+// outputs newprefix_tablename</code></p>
+
<h1>Protecting identifiers</h1>
<p>In many databases it is advisable to protect table and field names - for example with backticks in MySQL. <strong>Active Record queries are automatically protected</strong>, however if you need to manually protect an identifier you can use:</p>
diff --git a/user_guide/helpers/url_helper.html b/user_guide/helpers/url_helper.html
index de28a6f56..ac9d0a68e 100644
--- a/user_guide/helpers/url_helper.html
+++ b/user_guide/helpers/url_helper.html
@@ -27,7 +27,7 @@
<div id="masthead">
<table cellpadding="0" cellspacing="0" border="0" style="width:100%">
<tr>
-<td><h1>CodeIgniter User Guide Version 2.0.0</h1></td>
+<td><h1>CodeIgniter User Guide Version 2.0.2</h1></td>
<td id="breadcrumb_right"><a href="../toc.html">Table of Contents Page</a></td>
</tr>
</table>
diff --git a/user_guide/images/appflowchart.gif b/user_guide/images/appflowchart.gif
index 422332c9e..4328e48fe 100644
--- a/user_guide/images/appflowchart.gif
+++ b/user_guide/images/appflowchart.gif
Binary files differ
diff --git a/user_guide/libraries/cart.html b/user_guide/libraries/cart.html
index f084d5dcf..2e2beed9c 100644
--- a/user_guide/libraries/cart.html
+++ b/user_guide/libraries/cart.html
@@ -61,7 +61,7 @@ Shopping Cart Class
<p>The Cart Class permits items to be added to a session that stays active while a user is browsing your site.
These items can be retrieved and displayed in a standard "shopping cart" format, allowing the user to update the quantity or remove items from the cart.</p>
-<p>Please note that the Cart Class ONLY provides the core "cart" functionality. It does not provide shipping, credit card authorization, or other processing components.</p>
+<p>Please note that the Cart Class ONLY provides the core "cart" functionality. It does not provide shipping, credit card authorization, or other processing components.</p>
<h2>Initializing the Shopping Cart Class</h2>
@@ -106,20 +106,20 @@ It is intended to be used in cases where your product has options associated wit
<li><strong>qty</strong> - The quantity being purchased.
<li><strong>price</strong> - The price of the item.
<li><strong>name</strong> - The name of the item.
-<li><strong>options</strong> - Any additional attributes that are needed to identify the product. These must be passed via an array.
+<li><strong>options</strong> - Any additional attributes that are needed to identify the product. These must be passed via an array.
</ul>
<p>In addition to the five indexes above, there are two reserved words: <dfn>rowid</dfn> and <dfn>subtotal</dfn>. These are used internally by the Cart class, so
please do NOT use those words as index names when inserting data into the cart.</p>
-<p>Your array may contain additional data. Anything you include in your array will be stored in the session. However, it is best to standardize your data among
-all your products in order to make displaying the information in a table easier.</p>
+<p>Your array may contain additional data. Anything you include in your array will be stored in the session. However, it is best to standardize your data among all your products in order to make displaying the information in a table easier.</p>
+
+<p>The insert() method will return the $rowid if you successfully insert a single item.</p>
<h2>Adding Multiple Items to The Cart</h2>
-<p>By using a multi-dimensional array, as shown below, it is possible to add multiple products to the cart in one action. This is useful in cases where you wish to allow
-people to select from among several items on the same page.</p>
+<p>By using a multi-dimensional array, as shown below, it is possible to add multiple products to the cart in one action. This is useful in cases where you wish to allow people to select from among several items on the same page.</p>
<code>
@@ -268,8 +268,8 @@ $this->cart->update($data);
<p><strong>What is a Row ID?</strong>&nbsp; The <kbd>row ID</kbd> is a unique identifier that is generated by the cart code when an item is added to the cart. The reason a
unique ID is created is so that identical products with different options can be managed by the cart.</p>
-<p>For example, let's say someone buys two identical t-shirts (same product ID), but in different sizes. The product ID (and other attributes) will be
-identical for both sizes because it's the same shirt. The only difference will be the size. The cart must therefore have a means of identifying this
+<p>For example, let's say someone buys two identical t-shirts (same product ID), but in different sizes. The product ID (and other attributes) will be
+identical for both sizes because it's the same shirt. The only difference will be the size. The cart must therefore have a means of identifying this
difference so that the two sizes of shirts can be managed independently. It does so by creating a unique "row ID" based on the product ID and any options associated with it.</p>
<p>In nearly all cases, updating the cart will be something the user does via the "view cart" page, so as a developer, it is unlikely that you will ever have to concern yourself
@@ -311,7 +311,7 @@ function when the update form is submitted. Please examine the construction of t
<h2>$this->cart->has_options(rowid);</h2>
-<p>Returns TRUE (boolean) if a particular row in the cart contains options. This function is designed to be used in a loop with <dfn>$this->cart->contents()</dfn>, since you must pass the <kbd>rowid</kbd> to this function, as shown in the <dfn>Displaying the Cart</dfn> example above.</p>
+<p>Returns TRUE (boolean) if a particular row in the cart contains options. This function is designed to be used in a loop with <dfn>$this->cart->contents()</dfn>, since you must pass the <kbd>rowid</kbd> to this function, as shown in the <dfn>Displaying the Cart</dfn> example above.</p>
<h2>$this->cart->product_options(rowid);</h2>
@@ -322,7 +322,7 @@ function when the update form is submitted. Please examine the construction of t
<h2>$this->cart->destroy();</h2>
-<p>Permits you to destroy the cart. This function will likely be called when you are finished processing the customer's order.</p>
+<p>Permits you to destroy the cart. This function will likely be called when you are finished processing the customer's order.</p>
diff --git a/user_guide/libraries/form_validation.html b/user_guide/libraries/form_validation.html
index 8fdcd1446..da2f5e5e8 100644
--- a/user_guide/libraries/form_validation.html
+++ b/user_guide/libraries/form_validation.html
@@ -390,10 +390,10 @@ $this->form_validation->set_rules($config);
<p>CodeIgniter lets you pipe multiple rules together. Let's try it. Change your rules in the third parameter of rule setting function, like this:</p>
<code>
-$this->form_validation->set_rules('username', 'Username', 'required|min_length[5]|max_length[12]');<br />
+$this->form_validation->set_rules('username', 'Username', 'required|min_length[5]|max_length[12]|is_unique[users.username]');<br />
$this->form_validation->set_rules('password', 'Password', 'required|matches[passconf]');<br />
$this->form_validation->set_rules('passconf', 'Password Confirmation', 'required');<br />
-$this->form_validation->set_rules('email', 'Email', 'required|valid_email');<br />
+$this->form_validation->set_rules('email', 'Email', 'required|valid_email|is_unique[users.email]');<br />
</code>
<p>The above code sets the following rules:</p>
@@ -508,15 +508,13 @@ create a callback function that does that. Let's create a example of this.</p>
<code>$this->form_validation->set_rules('username', 'Username', '<kbd>callback_username_check</kbd>');</code>
-
<p>Then add a new function called <dfn>username_check</dfn> to your controller. Here's how your controller should now look:</p>
-
-<textarea class="textarea" style="width:100%" cols="50" rows="44">&lt;?php
+<textarea class="textarea" style="width:100%" cols="50" rows="40">&lt;?php
class Form extends CI_Controller {
- function index()
+ public function index()
{
$this->load->helper(array('form', 'url'));
@@ -525,7 +523,7 @@ class Form extends CI_Controller {
$this->form_validation->set_rules('username', 'Username', 'callback_username_check');
$this->form_validation->set_rules('password', 'Password', 'required');
$this->form_validation->set_rules('passconf', 'Password Confirmation', 'required');
- $this->form_validation->set_rules('email', 'Email', 'required');
+ $this->form_validation->set_rules('email', 'Email', 'required|is_unique[users.email]');
if ($this->form_validation->run() == FALSE)
{
@@ -537,7 +535,7 @@ class Form extends CI_Controller {
}
}
- function username_check($str)
+ public function username_check($str)
{
if ($str == 'test')
{
@@ -556,14 +554,13 @@ class Form extends CI_Controller {
<p><dfn>Reload your form and submit it with the word "test" as the username. You can see that the form field data was passed to your
callback function for you to process.</dfn></p>
-<p><strong>To invoke a callback just put the function name in a rule, with "callback_" as the rule prefix.</strong></p>
+<p>To invoke a callback just put the function name in a rule, with "callback_" as the rule <strong>prefix</strong>. If you need
+to receive an extra parameter in your callback function, just add it normally after the function name between square brackets,
+as in: "callback_foo<strong>[bar]</strong>", then it will be passed as the second argument of your callback function.</p>
-<p>You can also process the form data that is passed to your callback and return it. If your callback returns anything other than a boolean TRUE/FALSE
+<p><strong>Note:</strong> You can also process the form data that is passed to your callback and return it. If your callback returns anything other than a boolean TRUE/FALSE
it is assumed that the data is your newly processed form data.</p>
-
-
-
<a name="settingerrors"></a>
<h2>Setting Error Messages</h2>
@@ -947,6 +944,13 @@ POST array:</p>
</tr>
<tr>
+ <td class="td"><strong>is_unique</strong></td>
+ <td class="td">Yes</td>
+ <td class="td">Returns FALSE if the form element is not unique to the table and field name in the parameter.</td>
+ <td class="td">is_unique[table.field]</td>
+ </tr>
+
+ <tr>
<td class="td"><strong>min_length</strong></td>
<td class="td">Yes</td>
<td class="td">Returns FALSE if the form element is shorter then the parameter value.</td>
diff --git a/user_guide/libraries/loader.html b/user_guide/libraries/loader.html
index 1d93af5ed..a472730ca 100644
--- a/user_guide/libraries/loader.html
+++ b/user_guide/libraries/loader.html
@@ -175,6 +175,12 @@ and merged into one array for conversion to variables.
</p>
+<h2>$this->load->get_var(<samp>$key</samp>)</h2>
+
+<p>This function checks the associative array of variables available to your views. This is useful if for any reason a var is set in a library or another controller method using $this->load->vars().
+</p>
+
+
<h2>$this->load->helper('<var>file_name</var>')</h2>
<p>This function loads helper files, where <var>file_name</var> is the name of the file, without the <kbd>_helper.php</kbd> extension.</p>
diff --git a/user_guide/overview/appflow.html b/user_guide/overview/appflow.html
index bcbc43ff8..7c8d4accb 100644
--- a/user_guide/overview/appflow.html
+++ b/user_guide/overview/appflow.html
@@ -60,7 +60,7 @@ Appflow
<p>The following graphic illustrates how data flows throughout the system:</p>
-<div><img src="../images/appflowchart.gif" width="697" height="205" border="0" alt="CodeIgniter application flow" /></div>
+<div><img src="../images/appflowchart.gif" width="769" height="212" alt="CodeIgniter application flow"></div>
<ol>