summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--.travis.yml2
-rw-r--r--application/config/config.php4
-rw-r--r--application/config/routes.php4
-rw-r--r--application/config/user_agents.php3
-rw-r--r--contributing.md2
-rw-r--r--system/core/CodeIgniter.php4
-rw-r--r--system/core/Config.php2
-rw-r--r--system/core/Input.php2
-rw-r--r--system/core/Output.php4
-rw-r--r--system/core/URI.php122
-rw-r--r--system/core/Utf8.php4
-rw-r--r--system/database/DB.php7
-rw-r--r--system/database/DB_driver.php78
-rw-r--r--system/database/DB_forge.php36
-rw-r--r--system/database/DB_utility.php14
-rw-r--r--system/database/drivers/mssql/mssql_driver.php14
-rw-r--r--system/database/drivers/mysql/mysql_driver.php57
-rw-r--r--system/database/drivers/mysqli/mysqli_driver.php20
-rw-r--r--system/database/drivers/postgre/postgre_driver.php20
-rw-r--r--system/helpers/download_helper.php38
-rw-r--r--system/helpers/html_helper.php27
-rw-r--r--system/helpers/inflector_helper.php39
-rw-r--r--system/helpers/url_helper.php2
-rw-r--r--system/libraries/Cache/drivers/Cache_memcached.php18
-rw-r--r--system/libraries/Cache/drivers/Cache_redis.php102
-rw-r--r--system/libraries/Email.php2
-rw-r--r--system/libraries/Form_validation.php13
-rw-r--r--system/libraries/Javascript.php4
-rw-r--r--system/libraries/Session/drivers/Session_redis_driver.php72
-rw-r--r--system/libraries/Table.php1
-rw-r--r--tests/codeigniter/database/DB_driver_test.php2
-rw-r--r--tests/codeigniter/helpers/html_helper_test.php26
-rw-r--r--tests/codeigniter/helpers/inflector_helper_test.php19
-rw-r--r--tests/codeigniter/libraries/Form_validation_test.php6
-rw-r--r--user_guide_src/source/changelog.rst46
-rw-r--r--user_guide_src/source/conf.py4
-rw-r--r--user_guide_src/source/database/db_driver_reference.rst12
-rw-r--r--user_guide_src/source/helpers/download_helper.rst17
-rw-r--r--user_guide_src/source/helpers/html_helper.rst22
-rw-r--r--user_guide_src/source/helpers/inflector_helper.rst18
-rw-r--r--user_guide_src/source/installation/downloads.rst3
-rw-r--r--user_guide_src/source/installation/upgrade_310.rst2
-rw-r--r--user_guide_src/source/installation/upgrade_320.rst112
-rw-r--r--user_guide_src/source/installation/upgrading.rst1
-rw-r--r--user_guide_src/source/libraries/caching.rst2
-rw-r--r--user_guide_src/source/libraries/form_validation.rst3
-rw-r--r--user_guide_src/source/libraries/image_lib.rst2
-rw-r--r--user_guide_src/source/libraries/table.rst10
48 files changed, 650 insertions, 374 deletions
diff --git a/.travis.yml b/.travis.yml
index ba2d6b31d..334cb614f 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -1,7 +1,6 @@
language: php
php:
- - 5.3
- 5.4
- 5.5
- 5.6
@@ -30,7 +29,6 @@ script: phpunit -d zend.enable_gc=0 -d date.timezone=UTC --coverage-text --confi
matrix:
allow_failures:
- - php: 5.3
- php: hhvm
- php: 7.1
exclude:
diff --git a/application/config/config.php b/application/config/config.php
index 23ef5a528..0a7b8202b 100644
--- a/application/config/config.php
+++ b/application/config/config.php
@@ -63,6 +63,8 @@ $config['uri_protocol'] = 'REQUEST_URI';
| For more information please see the user guide:
|
| https://codeigniter.com/user_guide/general/urls.html
+|
+| Note: This option is ignored for CLI requests.
*/
$config['url_suffix'] = '';
@@ -157,6 +159,8 @@ $config['composer_autoload'] = FALSE;
|
| DO NOT CHANGE THIS UNLESS YOU FULLY UNDERSTAND THE REPERCUSSIONS!!
|
+| Note: This option is ignored for CLI requests.
+|
*/
$config['permitted_uri_chars'] = 'a-z 0-9~%.:_\-';
diff --git a/application/config/routes.php b/application/config/routes.php
index 1b45740d7..8ebf62bfa 100644
--- a/application/config/routes.php
+++ b/application/config/routes.php
@@ -43,8 +43,8 @@ defined('BASEPATH') OR exit('No direct script access allowed');
| This is not exactly a route, but allows you to automatically route
| controller and method names that contain dashes. '-' isn't a valid
| class or method name character, so it requires translation.
-| When you set this option to TRUE, it will replace ALL dashes in the
-| controller and method URI segments.
+| When you set this option to TRUE, it will replace ALL dashes with
+| underscores in the controller and method URI segments.
|
| Examples: my-controller/index -> my_controller/index
| my-controller/my-method -> my_controller/my_method
diff --git a/application/config/user_agents.php b/application/config/user_agents.php
index 798086b65..1359bbea9 100644
--- a/application/config/user_agents.php
+++ b/application/config/user_agents.php
@@ -87,7 +87,8 @@ $browsers = array(
'amaya' => 'Amaya',
'IBrowse' => 'IBrowse',
'Maxthon' => 'Maxthon',
- 'Ubuntu' => 'Ubuntu Web Browser'
+ 'Ubuntu' => 'Ubuntu Web Browser',
+ 'Vivaldi' => 'Vivaldi'
);
$mobiles = array(
diff --git a/contributing.md b/contributing.md
index 2037e0424..10b89b1db 100644
--- a/contributing.md
+++ b/contributing.md
@@ -29,7 +29,7 @@ If you change anything that requires a change to documentation then you will nee
### Compatibility
-CodeIgniter recommends PHP 5.4 or newer to be used, but it should be
+CodeIgniter recommends PHP 5.5 or newer to be used, but it should be
compatible with PHP 5.2.4 so all code supplied must stick to this
requirement. If PHP 5.3 (and above) functions or features are used then
there must be a fallback for PHP 5.2.4.
diff --git a/system/core/CodeIgniter.php b/system/core/CodeIgniter.php
index 71656be29..66ed9ec8f 100644
--- a/system/core/CodeIgniter.php
+++ b/system/core/CodeIgniter.php
@@ -55,7 +55,7 @@ defined('BASEPATH') OR exit('No direct script access allowed');
* @var string
*
*/
- const CI_VERSION = '3.1.3-dev';
+ const CI_VERSION = '3.2.0-dev';
/*
* ------------------------------------------------------
@@ -298,7 +298,7 @@ if ( ! is_php('5.4'))
* Instantiate the URI class
* ------------------------------------------------------
*/
- $URI =& load_class('URI', 'core');
+ $URI =& load_class('URI', 'core', $CFG);
/*
* ------------------------------------------------------
diff --git a/system/core/Config.php b/system/core/Config.php
index 9fd3e4a7d..e74751639 100644
--- a/system/core/Config.php
+++ b/system/core/Config.php
@@ -169,7 +169,7 @@ class CI_Config {
$this->is_loaded[] = $file_path;
$config = NULL;
$loaded = TRUE;
- log_message('debug', 'Config file loaded: '.$file_path);
+ log_message('info', 'Config file loaded: '.$file_path);
}
}
diff --git a/system/core/Input.php b/system/core/Input.php
index 24fe8a9cc..cbb185a8d 100644
--- a/system/core/Input.php
+++ b/system/core/Input.php
@@ -653,7 +653,7 @@ class CI_Input {
// Sanitize PHP_SELF
$_SERVER['PHP_SELF'] = strip_tags($_SERVER['PHP_SELF']);
- log_message('debug', 'Global POST, GET and COOKIE data sanitized');
+ log_message('info', 'Global POST, GET and COOKIE data sanitized');
}
// --------------------------------------------------------------------
diff --git a/system/core/Output.php b/system/core/Output.php
index 57c78ab19..94a6340e7 100644
--- a/system/core/Output.php
+++ b/system/core/Output.php
@@ -502,7 +502,7 @@ class CI_Output {
echo $output;
log_message('info', 'Final output sent to browser');
- log_message('debug', 'Total execution time: '.$elapsed);
+ log_message('info', 'Total execution time: '.$elapsed);
return;
}
@@ -539,7 +539,7 @@ class CI_Output {
}
log_message('info', 'Final output sent to browser');
- log_message('debug', 'Total execution time: '.$elapsed);
+ log_message('info', 'Total execution time: '.$elapsed);
}
// --------------------------------------------------------------------
diff --git a/system/core/URI.php b/system/core/URI.php
index 544f6c85f..7f07bfe1e 100644
--- a/system/core/URI.php
+++ b/system/core/URI.php
@@ -96,45 +96,40 @@ class CI_URI {
*
* @return void
*/
- public function __construct()
+ public function __construct(CI_Config $config)
{
- $this->config =& load_class('Config', 'core');
+ $this->config = $config;
+ // If it's a CLI request, ignore the configuration
+ if (is_cli())
+ {
+ $this->_set_uri_string($this->_parse_argv(), TRUE);
+ }
// If query strings are enabled, we don't need to parse any segments.
- // However, they don't make sense under CLI.
- if (is_cli() OR $this->config->item('enable_query_strings') !== TRUE)
+ elseif ($this->config->item('enable_query_strings') !== TRUE)
{
$this->_permitted_uri_chars = $this->config->item('permitted_uri_chars');
+ $protocol = $this->config->item('uri_protocol');
+ empty($protocol) && $protocol = 'REQUEST_URI';
- // If it's a CLI request, ignore the configuration
- if (is_cli())
+ switch ($protocol)
{
- $uri = $this->_parse_argv();
+ case 'AUTO': // For BC purposes only
+ case 'REQUEST_URI':
+ $uri = $this->_parse_request_uri();
+ break;
+ case 'QUERY_STRING':
+ $uri = $this->_parse_query_string();
+ break;
+ case 'PATH_INFO':
+ default:
+ $uri = isset($_SERVER[$protocol])
+ ? $_SERVER[$protocol]
+ : $this->_parse_request_uri();
+ break;
}
- else
- {
- $protocol = $this->config->item('uri_protocol');
- empty($protocol) && $protocol = 'REQUEST_URI';
- switch ($protocol)
- {
- case 'AUTO': // For BC purposes only
- case 'REQUEST_URI':
- $uri = $this->_parse_request_uri();
- break;
- case 'QUERY_STRING':
- $uri = $this->_parse_query_string();
- break;
- case 'PATH_INFO':
- default:
- $uri = isset($_SERVER[$protocol])
- ? $_SERVER[$protocol]
- : $this->_parse_request_uri();
- break;
- }
- }
-
- $this->_set_uri_string($uri);
+ $this->_set_uri_string($uri, FALSE);
}
log_message('info', 'URI Class Initialized');
@@ -145,43 +140,66 @@ class CI_URI {
/**
* Set URI String
*
- * @param string $str
+ * @param string $str Input URI string
+ * @param bool $is_cli Whether the input comes from CLI
* @return void
*/
- protected function _set_uri_string($str)
+ protected function _set_uri_string($str, $is_cli = FALSE)
{
- // Filter out control characters and trim slashes
- $this->uri_string = trim(remove_invisible_characters($str, FALSE), '/');
-
- if ($this->uri_string !== '')
+ // CLI requests have a bit simpler logic
+ if ($is_cli)
{
- // Remove the URL suffix, if present
- if (($suffix = (string) $this->config->item('url_suffix')) !== '')
+ if (($this->uri_string = trim($str, '/')) === '')
{
- $slen = strlen($suffix);
-
- if (substr($this->uri_string, -$slen) === $suffix)
- {
- $this->uri_string = substr($this->uri_string, 0, -$slen);
- }
+ return;
}
$this->segments[0] = NULL;
- // Populate the segments array
- foreach (explode('/', trim($this->uri_string, '/')) as $val)
+ foreach (explode('/', $this->uri_string) as $segment)
{
- $val = trim($val);
- // Filter segments for security
- $this->filter_uri($val);
-
- if ($val !== '')
+ if (($segment = trim($segment)) !== '')
{
- $this->segments[] = $val;
+ $this->segments[] = $segment;
}
}
unset($this->segments[0]);
+ return;
+ }
+
+ // Filter out control characters and trim slashes
+ $this->uri_string = trim(remove_invisible_characters($str, FALSE), '/');
+
+ if ($this->uri_string === '')
+ {
+ return;
}
+
+ // Remove the URL suffix, if present
+ if (($suffix = (string) $this->config->item('url_suffix')) !== '')
+ {
+ $slen = strlen($suffix);
+
+ if (substr($this->uri_string, -$slen) === $suffix)
+ {
+ $this->uri_string = substr($this->uri_string, 0, -$slen);
+ }
+ }
+
+ $this->segments[0] = NULL;
+ foreach (explode('/', trim($this->uri_string, '/')) as $segment)
+ {
+ $segment = trim($segment);
+ // Filter segments for security
+ $this->filter_uri($segment);
+
+ if ($segment !== '')
+ {
+ $this->segments[] = $segment;
+ }
+ }
+
+ unset($this->segments[0]);
}
// --------------------------------------------------------------------
diff --git a/system/core/Utf8.php b/system/core/Utf8.php
index f2f42e6ca..93c611675 100644
--- a/system/core/Utf8.php
+++ b/system/core/Utf8.php
@@ -66,12 +66,12 @@ class CI_Utf8 {
)
{
define('UTF8_ENABLED', TRUE);
- log_message('debug', 'UTF-8 Support Enabled');
+ log_message('info', 'UTF-8 Support Enabled');
}
else
{
define('UTF8_ENABLED', FALSE);
- log_message('debug', 'UTF-8 Support Disabled');
+ log_message('info', 'UTF-8 Support Disabled');
}
log_message('info', 'Utf8 Class Initialized');
diff --git a/system/database/DB.php b/system/database/DB.php
index b4b7767e8..37dfdd632 100644
--- a/system/database/DB.php
+++ b/system/database/DB.php
@@ -82,7 +82,7 @@ function &DB($params = '', $query_builder_override = NULL)
}
}
- if ( ! isset($db) OR count($db) === 0)
+ if (empty($db))
{
show_error('No database connection settings were found in the database config file.');
}
@@ -192,10 +192,13 @@ function &DB($params = '', $query_builder_override = NULL)
// Load the DB driver
$driver_file = BASEPATH.'database/drivers/'.$params['dbdriver'].'/'.$params['dbdriver'].'_driver.php';
-
file_exists($driver_file) OR show_error('Invalid DB driver');
require_once($driver_file);
+ // Load the result classes as well
+ require_once(BASEPATH.'database/DB_result.php');
+ require_once(BASEPATH.'database/drivers/'.$params['dbdriver'].'/'.$params['dbdriver'].'_result.php');
+
// Instantiate the DB adapter
$driver = 'CI_DB_'.$params['dbdriver'].'_driver';
$DB = new $driver($params);
diff --git a/system/database/DB_driver.php b/system/database/DB_driver.php
index 151340596..c142a1354 100644
--- a/system/database/DB_driver.php
+++ b/system/database/DB_driver.php
@@ -380,7 +380,8 @@ abstract class CI_DB_driver {
/**
* Initialize Database Settings
*
- * @return bool
+ * @return void
+ * @throws RuntimeException In case of failure
*/
public function initialize()
{
@@ -392,7 +393,7 @@ abstract class CI_DB_driver {
*/
if ($this->conn_id)
{
- return TRUE;
+ return;
}
// ----------------------------------------------------------------
@@ -429,19 +430,9 @@ abstract class CI_DB_driver {
// We still don't have a connection?
if ( ! $this->conn_id)
{
- log_message('error', 'Unable to connect to the database');
-
- if ($this->db_debug)
- {
- $this->display_error('db_unable_to_connect');
- }
-
- return FALSE;
+ throw new RuntimeException('Unable to connect to the database.');
}
}
-
- // Now we set the character set and that's all
- return $this->db_set_charset($this->char_set);
}
// --------------------------------------------------------------------
@@ -517,31 +508,6 @@ abstract class CI_DB_driver {
// --------------------------------------------------------------------
/**
- * Set client character set
- *
- * @param string
- * @return bool
- */
- public function db_set_charset($charset)
- {
- if (method_exists($this, '_db_set_charset') && ! $this->_db_set_charset($charset))
- {
- log_message('error', 'Unable to set database connection charset: '.$charset);
-
- if ($this->db_debug)
- {
- $this->display_error('db_unable_to_set_charset', $charset);
- }
-
- return FALSE;
- }
-
- return TRUE;
- }
-
- // --------------------------------------------------------------------
-
- /**
* The name of the platform in use (mysql, mssql, etc...)
*
* @return string
@@ -634,7 +600,6 @@ abstract class CI_DB_driver {
// cached query if it exists
if ($this->cache_on === TRUE && $return_object === TRUE && $this->_cache_init())
{
- $this->load_rdriver();
if (FALSE !== ($cache = $this->CACHE->read($sql)))
{
return $cache;
@@ -718,9 +683,9 @@ abstract class CI_DB_driver {
return TRUE;
}
- // Load and instantiate the result driver
- $driver = $this->load_rdriver();
- $RES = new $driver($this);
+ // Instantiate the driver-specific result class
+ $driver = 'CI_DB_'.$this->dbdriver.'_result';
+ $RES = new $driver($this);
// Is query caching enabled? If so, we'll serialize the
// result object and save it to a cache file.
@@ -750,26 +715,6 @@ abstract class CI_DB_driver {
// --------------------------------------------------------------------
/**
- * Load the result drivers
- *
- * @return string the name of the result class
- */
- public function load_rdriver()
- {
- $driver = 'CI_DB_'.$this->dbdriver.'_result';
-
- if ( ! class_exists($driver, FALSE))
- {
- require_once(BASEPATH.'database/DB_result.php');
- require_once(BASEPATH.'database/drivers/'.$this->dbdriver.'/'.$this->dbdriver.'_result.php');
- }
-
- return $driver;
- }
-
- // --------------------------------------------------------------------
-
- /**
* Simple Query
* This is a simplified version of the query() function. Internally
* we only use it when running transaction commands since they do
@@ -780,14 +725,7 @@ abstract class CI_DB_driver {
*/
public function simple_query($sql)
{
- if ( ! $this->conn_id)
- {
- if ( ! $this->initialize())
- {
- return FALSE;
- }
- }
-
+ empty($this->conn_id) && $this->initialize();
return $this->_execute($sql);
}
diff --git a/system/database/DB_forge.php b/system/database/DB_forge.php
index ed6f4b672..9add5cab7 100644
--- a/system/database/DB_forge.php
+++ b/system/database/DB_forge.php
@@ -894,21 +894,33 @@ abstract class CI_DB_forge {
return;
}
- if (array_key_exists('DEFAULT', $attributes))
+ if ( ! array_key_exists('DEFAULT', $attributes))
{
- if ($attributes['DEFAULT'] === NULL)
- {
- $field['default'] = empty($this->_null) ? '' : $this->_default.$this->_null;
+ return;
+ }
- // Override the NULL attribute if that's our default
- $attributes['NULL'] = TRUE;
- $field['null'] = empty($this->_null) ? '' : ' '.$this->_null;
- }
- else
- {
- $field['default'] = $this->_default.$this->db->escape($attributes['DEFAULT']);
- }
+ if ($attributes['DEFAULT'] === NULL)
+ {
+ $field['default'] = empty($this->_null) ? '' : $this->_default.$this->_null;
+
+ // Override the NULL attribute if that's our default
+ $attributes['NULL'] = TRUE;
+ $field['null'] = empty($this->_null) ? '' : ' '.$this->_null;
+ return;
}
+
+ // White-list CURRENT_TIMESTAMP & similar (e.g. Oracle has stuff like SYSTIMESTAMP) defaults for date/time fields
+ if (
+ isset($attributes['TYPE'])
+ && (stripos($attributes['TYPE'], 'time') !== FALSE OR stripos($attributes['TYPE'], 'date') !== FALSE)
+ && (stripos($attributes['DEFAULT'], 'time') !== FALSE OR stripos($attributes['DEFAULT'], 'date') !== FALSE)
+ )
+ {
+ $field['default'] = $this->_default.$attributes['DEFAULT'];
+ return;
+ }
+
+ $field['default'] = $this->_default.$this->db->escape($attributes['DEFAULT']);
}
// --------------------------------------------------------------------
diff --git a/system/database/DB_utility.php b/system/database/DB_utility.php
index 70528286c..49cd301df 100644
--- a/system/database/DB_utility.php
+++ b/system/database/DB_utility.php
@@ -235,13 +235,8 @@ abstract class CI_DB_utility {
* @param string $enclosure Enclosure (default: ")
* @return string
*/
- public function csv_from_result($query, $delim = ',', $newline = "\n", $enclosure = '"')
+ public function csv_from_result(CI_DB_result $query, $delim = ',', $newline = "\n", $enclosure = '"')
{
- if ( ! is_object($query) OR ! method_exists($query, 'list_fields'))
- {
- show_error('You must submit a valid result object');
- }
-
$out = '';
// First generate the headings from the table column names
foreach ($query->list_fields() as $name)
@@ -274,13 +269,8 @@ abstract class CI_DB_utility {
* @param array $params Any preferences
* @return string
*/
- public function xml_from_result($query, $params = array())
+ public function xml_from_result(CI_DB_result $query, $params = array())
{
- if ( ! is_object($query) OR ! method_exists($query, 'list_fields'))
- {
- show_error('You must submit a valid result object');
- }
-
// Set our default values
foreach (array('root' => 'root', 'element' => 'element', 'newline' => "\n", 'tab' => "\t") as $key => $val)
{
diff --git a/system/database/drivers/mssql/mssql_driver.php b/system/database/drivers/mssql/mssql_driver.php
index 66d7572e4..76f58564b 100644
--- a/system/database/drivers/mssql/mssql_driver.php
+++ b/system/database/drivers/mssql/mssql_driver.php
@@ -108,6 +108,7 @@ class CI_DB_mssql_driver extends CI_DB {
*/
public function db_connect($persistent = FALSE)
{
+ ini_set('mssql.charset', $this->char_set);
$this->conn_id = ($persistent)
? mssql_pconnect($this->hostname, $this->username, $this->password)
: mssql_connect($this->hostname, $this->username, $this->password);
@@ -249,19 +250,6 @@ class CI_DB_mssql_driver extends CI_DB {
// --------------------------------------------------------------------
/**
- * Set client character set
- *
- * @param string $charset
- * @return bool
- */
- protected function _db_set_charset($charset)
- {
- return (ini_set('mssql.charset', $charset) !== FALSE);
- }
-
- // --------------------------------------------------------------------
-
- /**
* Version number query string
*
* @return string
diff --git a/system/database/drivers/mysql/mysql_driver.php b/system/database/drivers/mysql/mysql_driver.php
index 7804dda58..70b4f68ba 100644
--- a/system/database/drivers/mysql/mysql_driver.php
+++ b/system/database/drivers/mysql/mysql_driver.php
@@ -147,29 +147,41 @@ class CI_DB_mysql_driver extends CI_DB {
: FALSE;
}
- if (isset($this->stricton) && is_resource($this->conn_id))
+ if (is_resource($this->conn_id))
{
- if ($this->stricton)
+ if ( ! mysql_set_charset($this->char_set, $this->conn_id))
{
- $this->simple_query('SET SESSION sql_mode = CONCAT(@@sql_mode, ",", "STRICT_ALL_TABLES")');
+ log_message('error', "Database: Unable to set the configured connection charset ('{$this->char_set}').");
+ $this->close();
+ return ($this->db->debug) ? $this->display_error('db_unable_to_set_charset', $this->char_set) : FALSE;
}
- else
+
+ if (isset($this->stricton))
{
- $this->simple_query(
- 'SET SESSION sql_mode =
- REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(
- @@sql_mode,
- "STRICT_ALL_TABLES,", ""),
- ",STRICT_ALL_TABLES", ""),
- "STRICT_ALL_TABLES", ""),
- "STRICT_TRANS_TABLES,", ""),
- ",STRICT_TRANS_TABLES", ""),
- "STRICT_TRANS_TABLES", "")'
- );
+ if ($this->stricton)
+ {
+ $this->simple_query('SET SESSION sql_mode = CONCAT(@@sql_mode, ",", "STRICT_ALL_TABLES")');
+ }
+ else
+ {
+ $this->simple_query(
+ 'SET SESSION sql_mode =
+ REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(
+ @@sql_mode,
+ "STRICT_ALL_TABLES,", ""),
+ ",STRICT_ALL_TABLES", ""),
+ "STRICT_ALL_TABLES", ""),
+ "STRICT_TRANS_TABLES,", ""),
+ ",STRICT_TRANS_TABLES", ""),
+ "STRICT_TRANS_TABLES", "")'
+ );
+ }
}
+
+ return $this->conn_id;
}
- return $this->conn_id;
+ return FALSE;
}
// --------------------------------------------------------------------
@@ -218,19 +230,6 @@ class CI_DB_mysql_driver extends CI_DB {
// --------------------------------------------------------------------
/**
- * Set client character set
- *
- * @param string $charset
- * @return bool
- */
- protected function _db_set_charset($charset)
- {
- return mysql_set_charset($charset, $this->conn_id);
- }
-
- // --------------------------------------------------------------------
-
- /**
* Database version number
*
* @return string
diff --git a/system/database/drivers/mysqli/mysqli_driver.php b/system/database/drivers/mysqli/mysqli_driver.php
index 4a14eea93..cf931a351 100644
--- a/system/database/drivers/mysqli/mysqli_driver.php
+++ b/system/database/drivers/mysqli/mysqli_driver.php
@@ -213,6 +213,13 @@ class CI_DB_mysqli_driver extends CI_DB {
return ($this->db->db_debug) ? $this->db->display_error($message, '', TRUE) : FALSE;
}
+ if ( ! $this->_mysqli->set_charset($this->char_set))
+ {
+ log_message('error', "Database: Unable to set the configured connection charset ('{$this->char_set}').");
+ $this->_mysqli->close();
+ return ($this->db->db_debug) ? $this->display_error('db_unable_to_set_charset', $this->char_set) : FALSE;
+ }
+
return $this->_mysqli;
}
@@ -265,19 +272,6 @@ class CI_DB_mysqli_driver extends CI_DB {
// --------------------------------------------------------------------
/**
- * Set client character set
- *
- * @param string $charset
- * @return bool
- */
- protected function _db_set_charset($charset)
- {
- return $this->conn_id->set_charset($charset);
- }
-
- // --------------------------------------------------------------------
-
- /**
* Database version number
*
* @return string
diff --git a/system/database/drivers/postgre/postgre_driver.php b/system/database/drivers/postgre/postgre_driver.php
index dfd87f95a..c7c827ea4 100644
--- a/system/database/drivers/postgre/postgre_driver.php
+++ b/system/database/drivers/postgre/postgre_driver.php
@@ -163,6 +163,13 @@ class CI_DB_postgre_driver extends CI_DB {
return FALSE;
}
+ if (pg_set_client_encoding($this->conn_id, $this->char_set) !== 0)
+ {
+ log_message('error', "Database: Unable to set the configured connection charset ('{$this->char_set}').");
+ pg_close($this->conn_id);
+ return ($this->db->db_debug) ? $this->display_error('db_unable_to_set_charset', $this->char_set) : FALSE;
+ }
+
empty($this->schema) OR $this->simple_query('SET search_path TO '.$this->schema.',public');
}
@@ -190,19 +197,6 @@ class CI_DB_postgre_driver extends CI_DB {
// --------------------------------------------------------------------
/**
- * Set client character set
- *
- * @param string $charset
- * @return bool
- */
- protected function _db_set_charset($charset)
- {
- return (pg_set_client_encoding($this->conn_id, $charset) === 0);
- }
-
- // --------------------------------------------------------------------
-
- /**
* Database version number
*
* @return string
diff --git a/system/helpers/download_helper.php b/system/helpers/download_helper.php
index a6463dfd7..9619c61b1 100644
--- a/system/helpers/download_helper.php
+++ b/system/helpers/download_helper.php
@@ -56,7 +56,7 @@ if ( ! function_exists('force_download'))
*
* Generates headers that force a download to happen
*
- * @param string filename
+ * @param mixed filename (or an array of local file path => destination filename)
* @param mixed the data to be downloaded
* @param bool whether to try and send the actual file MIME type
* @return void
@@ -69,14 +69,38 @@ if ( ! function_exists('force_download'))
}
elseif ($data === NULL)
{
- if ( ! @is_file($filename) OR ($filesize = @filesize($filename)) === FALSE)
+ // Is $filename an array as ['local source path' => 'destination filename']?
+ if (is_array($filename))
{
- return;
+ if (count($filename) !== 1)
+ {
+ return;
+ }
+
+ $filepath = key($filename);
+ $filename = current($filename);
+
+ if (is_int($filepath))
+ {
+ return;
+ }
+
+ if ( ! @is_file($filepath) OR ($filesize = @filesize($filepath)) === FALSE)
+ {
+ return;
+ }
+ }
+ else
+ {
+ if ( ! @is_file($filename) OR ($filesize = @filesize($filename)) === FALSE)
+ {
+ return;
+ }
+
+ $filepath = $filename;
+ $filename = explode('/', str_replace(DIRECTORY_SEPARATOR, '/', $filename));
+ $filename = end($filename);
}
-
- $filepath = $filename;
- $filename = explode('/', str_replace(DIRECTORY_SEPARATOR, '/', $filename));
- $filename = end($filename);
}
else
{
diff --git a/system/helpers/html_helper.php b/system/helpers/html_helper.php
index fdc463fca..696f0eee2 100644
--- a/system/helpers/html_helper.php
+++ b/system/helpers/html_helper.php
@@ -229,7 +229,7 @@ if ( ! function_exists('doctype'))
* @param string type The doctype to be generated
* @return string
*/
- function doctype($type = 'xhtml1-strict')
+ function doctype($type = 'html5')
{
static $doctypes;
@@ -360,15 +360,30 @@ if ( ! function_exists('meta'))
$name = array($name);
}
+ $allowed_types = array('charset', 'http-equiv', 'name', 'property');
$str = '';
foreach ($name as $meta)
{
- $type = (isset($meta['type']) && $meta['type'] !== 'name') ? 'http-equiv' : 'name';
- $name = isset($meta['name']) ? $meta['name'] : '';
- $content = isset($meta['content']) ? $meta['content'] : '';
- $newline = isset($meta['newline']) ? $meta['newline'] : "\n";
+ // This is to preserve BC with pre-3.1 versions where only
+ // 'http-equiv' (default) and 'name' were supported.
+ if (isset($meta['type']))
+ {
+ if ($meta['type'] === 'equiv')
+ {
+ $meta['type'] === 'http-equiv';
+ }
+ elseif ( ! in_array($meta['type'], $allowed_types, TRUE))
+ {
+ $meta['type'] = 'name';
+ }
+ }
+
+ $type = isset($meta['type']) ? $meta['type'] : 'name';
+ $name = isset($meta['name']) ? $meta['name'] : '';
+ $content = isset($meta['content']) ? $meta['content'] : '';
+ $newline = isset($meta['newline']) ? $meta['newline'] : "\n";
- $str .= '<meta '.$type.'="'.$name.'" content="'.$content.'" />'.$newline;
+ $str .= '<meta '.$type.'="'.$name.($type === 'charset' ? '' : '" content="'.$content).'" />'.$newline;
}
return $str;
diff --git a/system/helpers/inflector_helper.php b/system/helpers/inflector_helper.php
index f54dac019..f14f57c54 100644
--- a/system/helpers/inflector_helper.php
+++ b/system/helpers/inflector_helper.php
@@ -273,3 +273,42 @@ if ( ! function_exists('is_countable'))
);
}
}
+
+// ------------------------------------------------------------------------
+
+if ( ! function_exists('ordinal_format'))
+{
+ /**
+ * Returns the English ordinal numeral for a given number
+ *
+ * @param int $number
+ * @return string
+ */
+ function ordinal_format($number)
+ {
+ if ( ! ctype_digit((string) $number) OR $number < 1)
+ {
+ return $number;
+ }
+
+ $last_digit = array(
+ 0 => 'th',
+ 1 => 'st',
+ 2 => 'nd',
+ 3 => 'rd',
+ 4 => 'th',
+ 5 => 'th',
+ 6 => 'th',
+ 7 => 'th',
+ 8 => 'th',
+ 9 => 'th'
+ );
+
+ if (($number % 100) >= 11 && ($number % 100) <= 13)
+ {
+ return $number.'th';
+ }
+
+ return $number.$last_digit[$number % 10];
+ }
+}
diff --git a/system/helpers/url_helper.php b/system/helpers/url_helper.php
index fd7b5e116..8a5a75c44 100644
--- a/system/helpers/url_helper.php
+++ b/system/helpers/url_helper.php
@@ -443,7 +443,7 @@ if ( ! function_exists('prep_url'))
*/
function prep_url($str = '')
{
- if ($str === 'http://' OR $str === '')
+ if ($str === '')
{
return '';
}
diff --git a/system/libraries/Cache/drivers/Cache_memcached.php b/system/libraries/Cache/drivers/Cache_memcached.php
index 836336d46..ab8bfab8b 100644
--- a/system/libraries/Cache/drivers/Cache_memcached.php
+++ b/system/libraries/Cache/drivers/Cache_memcached.php
@@ -102,10 +102,22 @@ class CI_Cache_memcached extends CI_Driver {
return;
}
- foreach ($this->_config as $cache_server)
+ foreach ($this->_config as $cache_name => $cache_server)
{
- isset($cache_server['hostname']) OR $cache_server['hostname'] = $defaults['host'];
- isset($cache_server['port']) OR $cache_server['port'] = $defaults['port'];
+ if ( ! isset($cache_server['hostname']))
+ {
+ log_message('debug', 'Cache: Memcache(d) configuration "'.$cache_name.'" doesn\'t include a hostname; ignoring.');
+ continue;
+ }
+ elseif ($cache_server['hostname'][0] === '/')
+ {
+ $cache_server['port'] = 0;
+ }
+ elseif (empty($cache_server['port']))
+ {
+ $cache_server['port'] = $defaults['port'];
+ }
+
isset($cache_server['weight']) OR $cache_server['weight'] = $defaults['weight'];
if ($this->_memcached instanceof Memcache)
diff --git a/system/libraries/Cache/drivers/Cache_redis.php b/system/libraries/Cache/drivers/Cache_redis.php
index d4d95ebb1..2d1ead452 100644
--- a/system/libraries/Cache/drivers/Cache_redis.php
+++ b/system/libraries/Cache/drivers/Cache_redis.php
@@ -55,11 +55,11 @@ class CI_Cache_redis extends CI_Driver
* @var array
*/
protected static $_default_config = array(
- 'socket_type' => 'tcp',
'host' => '127.0.0.1',
'password' => NULL,
'port' => 6379,
- 'timeout' => 0
+ 'timeout' => 0,
+ 'database' => 0
);
/**
@@ -69,13 +69,6 @@ class CI_Cache_redis extends CI_Driver
*/
protected $_redis;
- /**
- * An internal cache for storing keys of serialized values.
- *
- * @var array
- */
- protected $_serialized = array();
-
// ------------------------------------------------------------------------
/**
@@ -112,16 +105,7 @@ class CI_Cache_redis extends CI_Driver
try
{
- if ($config['socket_type'] === 'unix')
- {
- $success = $this->_redis->connect($config['socket']);
- }
- else // tcp socket
- {
- $success = $this->_redis->connect($config['host'], $config['port'], $config['timeout']);
- }
-
- if ( ! $success)
+ if ( ! $this->_redis->connect($config['host'], ($config['host'][0] === '/' ? 0 : $config['port']), $config['timeout']))
{
log_message('error', 'Cache: Redis connection failed. Check your configuration.');
}
@@ -130,15 +114,16 @@ class CI_Cache_redis extends CI_Driver
{
log_message('error', 'Cache: Redis authentication failed.');
}
+
+ if (isset($config['database']) && $config['database'] > 0 && ! $this->_redis->select($config['database']))
+ {
+ log_message('error', 'Cache: Redis select database failed.');
+ }
}
catch (RedisException $e)
{
log_message('error', 'Cache: Redis connection refused ('.$e->getMessage().')');
}
-
- // Initialize the index of serialized values.
- $serialized = $this->_redis->sMembers('_ci_redis_serialized');
- empty($serialized) OR $this->_serialized = array_flip($serialized);
}
// ------------------------------------------------------------------------
@@ -151,14 +136,30 @@ class CI_Cache_redis extends CI_Driver
*/
public function get($key)
{
- $value = $this->_redis->get($key);
+ $data = $this->_redis->hMGet($key, array('__ci_type', '__ci_value'));
- if ($value !== FALSE && isset($this->_serialized[$key]))
+ if ( ! isset($data['__ci_type'], $data['__ci_value']) OR $data['__ci_value'] === FALSE)
{
- return unserialize($value);
+ return FALSE;
}
- return $value;
+ switch ($data['__ci_type'])
+ {
+ case 'array':
+ case 'object':
+ return unserialize($data['__ci_value']);
+ case 'boolean':
+ case 'integer':
+ case 'double': // Yes, 'double' is returned and NOT 'float'
+ case 'string':
+ case 'NULL':
+ return settype($data['__ci_value'], $data['__ci_type'])
+ ? $data['__ci_value']
+ : FALSE;
+ case 'resource':
+ default:
+ return FALSE;
+ }
}
// ------------------------------------------------------------------------
@@ -174,23 +175,33 @@ class CI_Cache_redis extends CI_Driver
*/
public function save($id, $data, $ttl = 60, $raw = FALSE)
{
- if (is_array($data) OR is_object($data))
+ switch ($data_type = gettype($data))
{
- if ( ! $this->_redis->sIsMember('_ci_redis_serialized', $id) && ! $this->_redis->sAdd('_ci_redis_serialized', $id))
- {
+ case 'array':
+ case 'object':
+ $data = serialize($data);
+ break;
+ case 'boolean':
+ case 'integer':
+ case 'double': // Yes, 'double' is returned and NOT 'float'
+ case 'string':
+ case 'NULL':
+ break;
+ case 'resource':
+ default:
return FALSE;
- }
+ }
- isset($this->_serialized[$id]) OR $this->_serialized[$id] = TRUE;
- $data = serialize($data);
+ if ( ! $this->_redis->hMSet($id, array('__ci_type' => $data_type, '__ci_value' => $data)))
+ {
+ return FALSE;
}
- elseif (isset($this->_serialized[$id]))
+ elseif ($ttl)
{
- $this->_serialized[$id] = NULL;
- $this->_redis->sRemove('_ci_redis_serialized', $id);
+ $this->_redis->expireAt($id, time() + $ttl);
}
- return $this->_redis->set($id, $data, $ttl);
+ return TRUE;
}
// ------------------------------------------------------------------------
@@ -203,18 +214,7 @@ class CI_Cache_redis extends CI_Driver
*/
public function delete($key)
{
- if ($this->_redis->delete($key) !== 1)
- {
- return FALSE;
- }
-
- if (isset($this->_serialized[$key]))
- {
- $this->_serialized[$key] = NULL;
- $this->_redis->sRemove('_ci_redis_serialized', $key);
- }
-
- return TRUE;
+ return ($this->_redis->delete($key) === 1);
}
// ------------------------------------------------------------------------
@@ -228,7 +228,7 @@ class CI_Cache_redis extends CI_Driver
*/
public function increment($id, $offset = 1)
{
- return $this->_redis->incr($id, $offset);
+ return $this->_redis->hIncrBy($id, 'data', $offset);
}
// ------------------------------------------------------------------------
@@ -242,7 +242,7 @@ class CI_Cache_redis extends CI_Driver
*/
public function decrement($id, $offset = 1)
{
- return $this->_redis->decr($id, $offset);
+ return $this->_redis->hIncrBy($id, 'data', -$offset);
}
// ------------------------------------------------------------------------
diff --git a/system/libraries/Email.php b/system/libraries/Email.php
index 2e6f5be90..162cc7777 100644
--- a/system/libraries/Email.php
+++ b/system/libraries/Email.php
@@ -147,7 +147,7 @@ class CI_Email {
*
* @var string
*/
- public $charset = 'UTF-8';
+ public $charset = 'utf-8';
/**
* Alternative message (for HTML messages only)
diff --git a/system/libraries/Form_validation.php b/system/libraries/Form_validation.php
index c39b65d89..384caf000 100644
--- a/system/libraries/Form_validation.php
+++ b/system/libraries/Form_validation.php
@@ -164,7 +164,7 @@ class CI_Form_validation {
* @param array $errors
* @return CI_Form_validation
*/
- public function set_rules($field, $label = '', $rules = array(), $errors = array())
+ public function set_rules($field, $label = null, $rules = null, $errors = array())
{
// No reason to set rules if we have no POST data
// or a validation array has not been specified
@@ -197,6 +197,10 @@ class CI_Form_validation {
return $this;
}
+ elseif ( ! isset($rules))
+ {
+ throw new BadMethodCallException('Form_validation: set_rules() called without a $rules parameter');
+ }
// No fields or no rules? Nothing to do...
if ( ! is_string($field) OR $field === '' OR empty($rules))
@@ -1523,12 +1527,7 @@ class CI_Form_validation {
*/
public function prep_url($str = '')
{
- if ($str === 'http://' OR $str === '')
- {
- return '';
- }
-
- if (strpos($str, 'http://') !== 0 && strpos($str, 'https://') !== 0)
+ if ($str !== '' && stripos($str, 'http://') !== 0 && stripos($str, 'https://') !== 0)
{
return 'http://'.$str;
}
diff --git a/system/libraries/Javascript.php b/system/libraries/Javascript.php
index dcf933779..2ddab38ee 100644
--- a/system/libraries/Javascript.php
+++ b/system/libraries/Javascript.php
@@ -650,11 +650,11 @@ class CI_Javascript {
$this->_javascript_location = $this->CI->config->item('javascript_location');
}
- if ($relative === TRUE OR strpos($external_file, 'http://') === 0 OR strpos($external_file, 'https://') === 0)
+ if ($relative === TRUE OR stripos($external_file, 'http://') === 0 OR stripos($external_file, 'https://') === 0)
{
$str = $this->_open_script($external_file);
}
- elseif (strpos($this->_javascript_location, 'http://') !== FALSE)
+ elseif (stripos($this->_javascript_location, 'http://') !== FALSE)
{
$str = $this->_open_script($this->_javascript_location.$external_file);
}
diff --git a/system/libraries/Session/drivers/Session_redis_driver.php b/system/libraries/Session/drivers/Session_redis_driver.php
index a780100b1..233b15619 100644
--- a/system/libraries/Session/drivers/Session_redis_driver.php
+++ b/system/libraries/Session/drivers/Session_redis_driver.php
@@ -92,27 +92,40 @@ class CI_Session_redis_driver extends CI_Session_driver implements SessionHandle
{
log_message('error', 'Session: No Redis save path configured.');
}
- elseif (preg_match('#(?:tcp://)?([^:?]+)(?:\:(\d+))?(\?.+)?#', $this->_config['save_path'], $matches))
+ elseif (preg_match('#^unix://([^\?]+)(?<options>\?.+)?$#', $this->_config['save_path'], $matches))
{
- isset($matches[3]) OR $matches[3] = ''; // Just to avoid undefined index notices below
- $this->_config['save_path'] = array(
- 'host' => $matches[1],
- 'port' => empty($matches[2]) ? NULL : $matches[2],
- 'password' => preg_match('#auth=([^\s&]+)#', $matches[3], $match) ? $match[1] : NULL,
- 'database' => preg_match('#database=(\d+)#', $matches[3], $match) ? (int) $match[1] : NULL,
- 'timeout' => preg_match('#timeout=(\d+\.\d+)#', $matches[3], $match) ? (float) $match[1] : NULL
+ $save_path = array('path' => $matches[1]);
+ }
+ elseif (preg_match('#(?:tcp://)?([^:?]+)(?:\:(\d+))?(?<options>\?.+)?#', $this->_config['save_path'], $matches))
+ {
+ $save_path = array(
+ 'host' => $matches[1],
+ 'port' => empty($matches[2]) ? NULL : $matches[2],
+ 'timeout' => NULL // We always pass this to Redis::connect(), so it needs to exist
);
-
- preg_match('#prefix=([^\s&]+)#', $matches[3], $match) && $this->_key_prefix = $match[1];
}
else
{
log_message('error', 'Session: Invalid Redis save path format: '.$this->_config['save_path']);
}
- if ($this->_config['match_ip'] === TRUE)
+ if (isset($save_path))
{
- $this->_key_prefix .= $_SERVER['REMOTE_ADDR'].':';
+ if (isset($matches['options']))
+ {
+ $save_path['password'] = preg_match('#auth=([^\s&]+)#', $matches['options'], $match) ? $match[1] : NULL;
+ $save_path['database'] = preg_match('#database=(\d+)#', $matches['options'], $match) ? (int) $match[1] : NULL;
+ $save_path['timeout'] = preg_match('#timeout=(\d+\.\d+)#', $matches['options'], $match) ? (float) $match[1] : NULL;
+
+ preg_match('#prefix=([^\s&]+)#', $matches['options'], $match) && $this->_key_prefix = $match[1];
+ }
+
+ $this->_config['save_path'] = $save_path;
+
+ if ($this->_config['match_ip'] === TRUE)
+ {
+ $this->_key_prefix .= $_SERVER['REMOTE_ADDR'].':';
+ }
}
}
@@ -135,22 +148,33 @@ class CI_Session_redis_driver extends CI_Session_driver implements SessionHandle
}
$redis = new Redis();
- if ( ! $redis->connect($this->_config['save_path']['host'], $this->_config['save_path']['port'], $this->_config['save_path']['timeout']))
- {
- log_message('error', 'Session: Unable to connect to Redis with the configured settings.');
- }
- elseif (isset($this->_config['save_path']['password']) && ! $redis->auth($this->_config['save_path']['password']))
- {
- log_message('error', 'Session: Unable to authenticate to Redis instance.');
- }
- elseif (isset($this->_config['save_path']['database']) && ! $redis->select($this->_config['save_path']['database']))
+ $connected = isset($this->_config['save_path']['path'])
+ ? $redis->connect($this->_config['save_path']['path'])
+ : $redis->connect(
+ $this->_config['save_path']['host'],
+ $this->_config['save_path']['port'],
+ $this->_config['save_path']['timeout']
+ );
+
+ if ($connected)
{
- log_message('error', 'Session: Unable to select Redis database with index '.$this->_config['save_path']['database']);
+ if (isset($this->_config['save_path']['password']) && ! $redis->auth($this->_config['save_path']['password']))
+ {
+ log_message('error', 'Session: Unable to authenticate to Redis instance.');
+ }
+ elseif (isset($this->_config['save_path']['database']) && ! $redis->select($this->_config['save_path']['database']))
+ {
+ log_message('error', 'Session: Unable to select Redis database with index '.$this->_config['save_path']['database']);
+ }
+ else
+ {
+ $this->_redis = $redis;
+ return $this->_success;
+ }
}
else
{
- $this->_redis = $redis;
- return $this->_success;
+ log_message('error', 'Session: Unable to connect to Redis with the configured settings.');
}
return $this->_fail();
diff --git a/system/libraries/Table.php b/system/libraries/Table.php
index f2fa434d9..2f1b3b414 100644
--- a/system/libraries/Table.php
+++ b/system/libraries/Table.php
@@ -427,6 +427,7 @@ class CI_Table {
$this->rows = array();
$this->heading = array();
$this->auto_heading = TRUE;
+ $this->caption = NULL;
return $this;
}
diff --git a/tests/codeigniter/database/DB_driver_test.php b/tests/codeigniter/database/DB_driver_test.php
index 26416d3fc..13e9abf84 100644
--- a/tests/codeigniter/database/DB_driver_test.php
+++ b/tests/codeigniter/database/DB_driver_test.php
@@ -7,8 +7,6 @@ class DB_driver_test extends CI_TestCase {
$config = Mock_Database_DB::config(DB_DRIVER);
sscanf(DB_DRIVER, '%[^/]/', $driver_name);
$driver = $this->{$driver_name}($config[DB_DRIVER]);
-
- $this->assertTrue($driver->initialize());
}
protected function pdo($config)
diff --git a/tests/codeigniter/helpers/html_helper_test.php b/tests/codeigniter/helpers/html_helper_test.php
index d66ad895c..029f3f4cd 100644
--- a/tests/codeigniter/helpers/html_helper_test.php
+++ b/tests/codeigniter/helpers/html_helper_test.php
@@ -81,12 +81,24 @@ EOH;
public function test_meta()
{
- $this->assertEquals("<meta name=\"test\" content=\"foo\" />\n", meta('test', 'foo'));
-
- $expect = "<meta name=\"foo\" content=\"\" />\n";
-
- $this->assertEquals($expect, meta(array('name' => 'foo')));
-
+ $this->assertEquals(
+ "<meta name=\"test\" content=\"foo\" />\n",
+ meta('test', 'foo')
+ );
+
+ $this->assertEquals(
+ "<meta name=\"foo\" content=\"\" />\n",
+ meta(array('name' => 'foo'))
+ );
+
+ $this->assertEquals(
+ "<meta charset=\"foo\" />\n",
+ meta(array('name' => 'foo', 'type' => 'charset'))
+ );
+
+ $this->assertEquals(
+ "<meta charset=\"foo\" />\n",
+ meta(array('name' => 'foo', 'type' => 'charset'))
+ );
}
-
} \ No newline at end of file
diff --git a/tests/codeigniter/helpers/inflector_helper_test.php b/tests/codeigniter/helpers/inflector_helper_test.php
index 81ce5e394..4a1e64fae 100644
--- a/tests/codeigniter/helpers/inflector_helper_test.php
+++ b/tests/codeigniter/helpers/inflector_helper_test.php
@@ -93,4 +93,23 @@ class Inflector_helper_test extends CI_TestCase {
}
}
+ // --------------------------------------------------------------------
+
+ public function test_ordinal_format()
+ {
+ $strs = array(
+ 1 => '1st',
+ 2 => '2nd',
+ 4 => '4th',
+ 11 => '11th',
+ 12 => '12th',
+ 13 => '13th',
+ 'something else' => 'something else',
+ );
+
+ foreach ($strs as $str => $expect)
+ {
+ $this->assertEquals($expect, ordinal_format($str));
+ }
+ }
} \ No newline at end of file
diff --git a/tests/codeigniter/libraries/Form_validation_test.php b/tests/codeigniter/libraries/Form_validation_test.php
index 0815300e6..5f4bb9316 100644
--- a/tests/codeigniter/libraries/Form_validation_test.php
+++ b/tests/codeigniter/libraries/Form_validation_test.php
@@ -435,6 +435,12 @@ class Form_validation_test extends CI_TestCase {
$this->assertFalse($form_validation->run('fail'));
}
+ public function test_set_rules_exception()
+ {
+ $this->setExpectedException('BadMethodCallException');
+ $this->form_validation->set_rules('foo', 'bar');
+ }
+
public function test_has_rule()
{
$this->form_validation->reset_validation();
diff --git a/user_guide_src/source/changelog.rst b/user_guide_src/source/changelog.rst
index 4f5efe276..d63f15f67 100644
--- a/user_guide_src/source/changelog.rst
+++ b/user_guide_src/source/changelog.rst
@@ -2,6 +2,52 @@
Change Log
##########
+Version 3.2.0
+=============
+
+Release Date: Not Released
+
+- Core
+
+ - Changed :doc:`URI Library <libraries/uri>` to ignore the ``$config['url_suffix']``, ``$config['permitted_uri_chars']`` configuration settings for CLI requests.
+
+- Libraries
+
+ - Added UNIX socket connection support to :doc:`Session Library <libraries/sessions>` 'redis' driver.
+
+ - :doc:`Cache Library <libraries/caching>` changes include:
+
+ - Added UNIX socket connection support to the 'memcached' driver.
+ - Added 'database' configuration option to the 'redis' driver, allowing to auto-select another database.
+ - Changed the 'memcached' driver to ignore configurations that don't specify a hostname.
+ - Removed the *socket_type* configuration setting from the 'redis' driver.
+ - Changed data serialization logic in 'redis' driver for better performance.
+
+ - :doc:`Form Validation Library <libraries/form_validation>` changes include:
+
+ - Changed method ``set_rules()`` to throw a ``BadMethodCallException`` when its first parameter is not an array and the ``$rules`` one is unused.
+
+ - :doc:`HTML Table Library <libraries/table>` changes include:
+
+ - Changed method ``clear()`` to also reset captions.
+
+- :doc:`Database <database/index>`
+
+ - Changed method ``initialize()`` to return void and instead throw a ``RuntimeException`` in case of failure.
+ - Changed method ``db_connect()`` to always set the connection character set (if supported by the driver) and to fail if it can't.
+ - Removed method ``db_set_charset()`` and the ability to change a connection character set at runtime.
+
+ - :doc:`Database Forge <database/forge>`:
+
+ - Added support for declaring date/time type fields default values as ``CURRENT_TIMESTAMP`` and similar.
+
+- Helpers
+
+ - Added new function :php:func:`ordinal_format()` to :doc:`Inflector Helper <helpers/inflector_helper>`.
+ - Updated :doc:`Download Helper <helpers/download_helper>` :php:func:`force_download()` to allow existing files to be renamed for download.
+ - Updated :doc:`HTML Helper <helpers/html_helper>` function :php:func:`meta()` with support for "charset" and "property" properties.
+ - Changed :doc:`HTML Helper <helpers/html_helper>` function :php:func:`doctype()` default document type to HTML 5.
+
Version 3.1.3
=============
diff --git a/user_guide_src/source/conf.py b/user_guide_src/source/conf.py
index 4d2edbe60..4714b0d62 100644
--- a/user_guide_src/source/conf.py
+++ b/user_guide_src/source/conf.py
@@ -48,9 +48,9 @@ copyright = u'2014 - 2016, British Columbia Institute of Technology'
# built documents.
#
# The short X.Y version.
-version = '3.1.3-dev'
+version = '3.2.0-dev'
# The full version, including alpha/beta/rc tags.
-release = '3.1.3-dev'
+release = '3.2.0-dev'
# The language for content autogenerated by Sphinx. Refer to documentation
# for a list of supported languages.
diff --git a/user_guide_src/source/database/db_driver_reference.rst b/user_guide_src/source/database/db_driver_reference.rst
index 1f036cd77..6f2fa5fb1 100644
--- a/user_guide_src/source/database/db_driver_reference.rst
+++ b/user_guide_src/source/database/db_driver_reference.rst
@@ -17,8 +17,8 @@ This article is intended to be a reference for them.
.. php:method:: initialize()
- :returns: TRUE on success, FALSE on failure
- :rtype: bool
+ :rtype: void
+ :throws: RuntimeException In case of failure
Initialize database settings, establish a connection to
the database.
@@ -61,14 +61,6 @@ This article is intended to be a reference for them.
Select / switch the current database.
- .. php:method:: db_set_charset($charset)
-
- :param string $charset: Character set name
- :returns: TRUE on success, FALSE on failure
- :rtype: bool
-
- Set client character set.
-
.. php:method:: platform()
:returns: Platform name
diff --git a/user_guide_src/source/helpers/download_helper.rst b/user_guide_src/source/helpers/download_helper.rst
index 1a4065073..e11d92a14 100644
--- a/user_guide_src/source/helpers/download_helper.rst
+++ b/user_guide_src/source/helpers/download_helper.rst
@@ -26,7 +26,7 @@ The following functions are available:
.. php:function:: force_download([$filename = ''[, $data = ''[, $set_mime = FALSE]]])
- :param string $filename: Filename
+ :param mixed $filename: Filename
:param mixed $data: File contents
:param bool $set_mime: Whether to try to send the actual MIME type
:rtype: void
@@ -37,8 +37,11 @@ The following functions are available:
file data.
If you set the second parameter to NULL and ``$filename`` is an existing, readable
- file path, then its content will be read instead.
-
+ file path, then its content will be read instead. You may also set ``$filename``
+ as an associative array with a single element, where the key of that element would be
+ the local file you are trying to read and where the value is the name of the downloadable
+ file that will be sent to browser. An example of this is provided below.
+
If you set the third parameter to boolean TRUE, then the actual file MIME type
(based on the filename extension) will be sent, so that if your browser has a
handler for that type - it can use it.
@@ -53,4 +56,10 @@ The following functions are available:
do the following::
// Contents of photo.jpg will be automatically read
- force_download('/path/to/photo.jpg', NULL); \ No newline at end of file
+ force_download('/path/to/photo.jpg', NULL);
+
+ If you want to download an existing file from your server, but change the name
+ of the actual file sent to browser, you will need this::
+
+ // Contents of photo.jpg will be automatically read and sent as my-photo.jpg
+ force_download(array('/path/to/photo.jpg' => 'my-photo.jpg'), NULL); \ No newline at end of file
diff --git a/user_guide_src/source/helpers/html_helper.rst b/user_guide_src/source/helpers/html_helper.rst
index 2c748bea0..b4e56fdca 100644
--- a/user_guide_src/source/helpers/html_helper.rst
+++ b/user_guide_src/source/helpers/html_helper.rst
@@ -286,7 +286,7 @@ The following functions are available:
// Generates: <meta name="description" content="My Great Site" />
echo meta('Content-type', 'text/html; charset=utf-8', 'equiv');
- // Note the third parameter. Can be "equiv" or "name"
+ // Note the third parameter. Can be "charset", "http-equiv", "name" or "property"
// Generates: <meta http-equiv="Content-type" content="text/html; charset=utf-8" />
echo meta(array('name' => 'robots', 'content' => 'no-cache'));
@@ -310,8 +310,13 @@ The following functions are available:
'content' => 'no-cache'
),
array(
- 'name' => 'Content-type',
- 'content' => 'text/html; charset=utf-8', 'type' => 'equiv'
+ 'name' => 'Content-Type',
+ 'type' => 'http-equiv',
+ 'content' => 'text/html; charset=utf-8'
+ ),
+ array(
+ 'name' => 'UTF-8',
+ 'type' => 'charset'
)
);
@@ -321,21 +326,22 @@ The following functions are available:
// <meta name="description" content="My Great Site" />
// <meta name="keywords" content="love, passion, intrigue, deception" />
// <meta name="robots" content="no-cache" />
- // <meta http-equiv="Content-type" content="text/html; charset=utf-8" />
+ // <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
+ // <meta charset="UTF-8" />
-.. php:function:: doctype([$type = 'xhtml1-strict'])
+.. php:function:: doctype([$type = 'html5'])
:param string $type: Doctype name
:returns: HTML DocType tag
:rtype: string
- Helps you generate document type declarations, or DTD's. XHTML 1.0
- Strict is used by default, but many doctypes are available.
+ Helps you generate document type declarations, or DTD's. HTML 5
+ is used by default, but many doctypes are available.
Example::
- echo doctype(); // <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+ echo doctype(); // <!DOCTYPE html>
echo doctype('html4-trans'); // <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
diff --git a/user_guide_src/source/helpers/inflector_helper.rst b/user_guide_src/source/helpers/inflector_helper.rst
index df0c568c0..76cce6f4d 100644
--- a/user_guide_src/source/helpers/inflector_helper.rst
+++ b/user_guide_src/source/helpers/inflector_helper.rst
@@ -93,4 +93,20 @@ The following functions are available:
Checks if the given word has a plural version. Example::
- is_countable('equipment'); // Returns FALSE \ No newline at end of file
+ is_countable('equipment'); // Returns FALSE
+
+.. php:function:: ordinal_format($number)
+
+ :param int $number: non-negative natural number to be converted
+ :returns: Ordinal numeral for given number or original value on failure
+ :rtype: string
+
+ Returns the ordinal numeral (1st, 2nd, 3rd etc.) for a
+ non-negative natural number. If the input is not a natural number
+ greater than 0, the function will return the original value. Examples::
+
+ echo ordinal_format(1); // Returns 1st
+ echo ordinal_format(3); // Returns 3rd
+ echo ordinal_format(21); // Returns 21st
+ echo ordinal_format(102); // Returns 102nd
+ echo ordinal_format(-5); // Invalid input, will return -5
diff --git a/user_guide_src/source/installation/downloads.rst b/user_guide_src/source/installation/downloads.rst
index 5992ba291..ae58e796f 100644
--- a/user_guide_src/source/installation/downloads.rst
+++ b/user_guide_src/source/installation/downloads.rst
@@ -2,7 +2,8 @@
Downloading CodeIgniter
#######################
-- `CodeIgniter v3.1.3 (Current version) <https://codeload.github.com/bcit-ci/CodeIgniter/zip/3.1-stable>`_
+- `CodeIgniter v3.2.0-dev (Current version) <https://codeload.github.com/bcit-ci/CodeIgniter/zip/develop>`_
+- `CodeIgniter v3.1.3-dev <https://codeload.github.com/bcit-ci/CodeIgniter/zip/3.1-stable>`_
- `CodeIgniter v3.1.2 <https://codeload.github.com/bcit-ci/CodeIgniter/zip/3.1.2>`_
- `CodeIgniter v3.1.1 <https://codeload.github.com/bcit-ci/CodeIgniter/zip/3.1.1>`_
- `CodeIgniter v3.1.0 <https://codeload.github.com/bcit-ci/CodeIgniter/zip/3.1.0>`_
diff --git a/user_guide_src/source/installation/upgrade_310.rst b/user_guide_src/source/installation/upgrade_310.rst
index 9e0108691..cae814327 100644
--- a/user_guide_src/source/installation/upgrade_310.rst
+++ b/user_guide_src/source/installation/upgrade_310.rst
@@ -35,4 +35,4 @@ does not provide a function that allows to safely escape user-supplied strings f
inside an SQL query (which our :doc:`Query Builder <../database/query_builder>` relies on).
Thus, user inputs MUST be bound, as shown in :doc:`Running Queries <../database/queries>`,
-under the "Query Bindings" section. \ No newline at end of file
+under the "Query Bindings" section.
diff --git a/user_guide_src/source/installation/upgrade_320.rst b/user_guide_src/source/installation/upgrade_320.rst
new file mode 100644
index 000000000..942a8a3b5
--- /dev/null
+++ b/user_guide_src/source/installation/upgrade_320.rst
@@ -0,0 +1,112 @@
+#############################
+Upgrading from 3.1.x to 3.2.x
+#############################
+
+Before performing an update you should take your site offline by
+replacing the index.php file with a static one.
+
+Step 1: Update your CodeIgniter files
+=====================================
+
+Replace all files and directories in your *system/* directory.
+
+.. note:: If you have any custom developed files in these directories,
+ please make copies of them first.
+
+Step 2: Change database connection handling
+===========================================
+
+"Loading" a database, whether by using the *config/autoload.php* settings
+or manually via calling ``$this->load->database()`` or the less-known
+``DB()`` function, will now throw a ``RuntimeException`` in case of a
+failure.
+
+In addition, being unable to set the configured character set is now also
+considered a connection failure.
+
+.. note:: This has been the case for most database drivers in the in the
+ past as well (i.e. all but the 'mysql', 'mysqli' and 'postgre'
+ drivers).
+
+What this means is that if you're unable to connect to a database, or
+have an erroneous character set configured, CodeIgniter will no longer
+fail silently, but will throw an exception instead.
+
+You may choose to explicitly catch it (and for that purpose you can't use
+*config/autoload.php* to load the :doc:`Database Class <../database/index>`)
+::
+
+ try
+ {
+ $this->load->database();
+ }
+ catch (RuntimeException $e)
+ {
+ // Handle the failure
+ }
+
+Or you may leave it to CodeIgniter's default exception handler, which would
+log the error message and display an error screen if you're running in
+development mode.
+
+Remove db_set_charset() calls
+-----------------------------
+
+With the above-mentioned changes, the purpose of the ``db_set_charset()``
+method would now only be to change the connection character set at runtime.
+That doesn't make sense and that's the reason why most database drivers
+don't support it at all.
+Thus, ``db_set_charset()`` is no longer necessary and is removed.
+
+Step 3: Check logic related to URI parsing of CLI requests
+==========================================================
+
+When running a CodeIgniter application from the CLI, the
+:doc:`URI Library <../libraries/uri>` will now ignore the
+``$config['url_suffix']`` and ``$config['permitted_uri_chars']``
+configuration settings.
+
+These two options don't make sense under the command line (which is why
+this change was made) and therefore you shouldn't be affected by this, but
+if you've relied on them for some reason, you'd probably have to make some
+changes to your code.
+
+Step 4: Check Cache Library configurations for Redis, Memcache(d)
+=================================================================
+
+The new improvements for the 'redis' and 'memcached' drivers of the
+:doc:`Cache Library <../libraries/caching>` may require some small
+adjustments to your configuration values ...
+
+Redis
+-----
+
+If you're using the 'redis' driver with a UNIX socket connection, you'll
+have to move the socket path from ``$config['socket']`` to
+``$config['host']`` instead.
+
+The ``$config['socket_type']`` option is also removed, although that won't
+affect your application - it will be ignored and the connection type will
+be determined by the format used for ``$config['host']`` instead.
+
+Memcache(d)
+-----------
+
+The 'memcached' will now ignore configurations that don't specify a ``host``
+value (previously, it just set the host to the default '127.0.0.1').
+
+Therefore, if you've added a configuration that only sets e.g. a ``port``,
+you will now have to explicitly set the ``host`` to '127.0.0.1' as well.
+
+Step 5: Check usage of doctype() HTML helper
+============================================
+
+The :doc:`HTML Helper <../helpers/html_helper>` function
+:php:func:`doctype()` used to default to 'xhtml1-strict' (XHTML 1.0 Strict)
+when no document type was specified. That default value is now changed to
+'html5', which obviously stands for the modern HTML 5 standard.
+
+Nothing should be really broken by this change, but if your application
+relies on the default value, you should double-check it and either
+explicitly set the desired format, or adapt your front-end to use proper
+HTML 5 formatting.
diff --git a/user_guide_src/source/installation/upgrading.rst b/user_guide_src/source/installation/upgrading.rst
index bc96e209f..14127d42e 100644
--- a/user_guide_src/source/installation/upgrading.rst
+++ b/user_guide_src/source/installation/upgrading.rst
@@ -8,6 +8,7 @@ upgrading from.
.. toctree::
:titlesonly:
+ Upgrading from 3.1.2+ to 3.2.x <upgrade_320>
Upgrading from 3.1.2 to 3.1.3 <upgrade_313>
Upgrading from 3.1.1 to 3.1.2 <upgrade_312>
Upgrading from 3.1.0 to 3.1.1 <upgrade_311>
diff --git a/user_guide_src/source/libraries/caching.rst b/user_guide_src/source/libraries/caching.rst
index a7081ec6b..81019c015 100644
--- a/user_guide_src/source/libraries/caching.rst
+++ b/user_guide_src/source/libraries/caching.rst
@@ -255,8 +255,6 @@ To use it, you need `Redis server and phpredis PHP extension <https://github.com
Config options to connect to redis server must be stored in the application/config/redis.php file.
Available options are::
- $config['socket_type'] = 'tcp'; //`tcp` or `unix`
- $config['socket'] = '/var/run/redis.sock'; // in case of `unix` socket type
$config['host'] = '127.0.0.1';
$config['password'] = NULL;
$config['port'] = 6379;
diff --git a/user_guide_src/source/libraries/form_validation.rst b/user_guide_src/source/libraries/form_validation.rst
index 7792369b2..b503b9be0 100644
--- a/user_guide_src/source/libraries/form_validation.rst
+++ b/user_guide_src/source/libraries/form_validation.rst
@@ -1027,13 +1027,14 @@ Class Reference
.. php:class:: CI_Form_validation
- .. php:method:: set_rules($field[, $label = ''[, $rules = ''[, $errors = array()]]])
+ .. php:method:: set_rules($field[, $label = null[, $rules = null[, $errors = array()]]])
:param string $field: Field name
:param string $label: Field label
:param mixed $rules: Validation rules, as a string list separated by a pipe "|", or as an array or rules
:param array $errors: A list of custom error messages
:returns: CI_Form_validation instance (method chaining)
+ :throws: BadMethodCallException If $field is not an array and $rules was not used
:rtype: CI_Form_validation
Permits you to set validation rules, as described in the tutorial
diff --git a/user_guide_src/source/libraries/image_lib.rst b/user_guide_src/source/libraries/image_lib.rst
index 22407962f..b25d2512f 100644
--- a/user_guide_src/source/libraries/image_lib.rst
+++ b/user_guide_src/source/libraries/image_lib.rst
@@ -283,7 +283,7 @@ Preference Default Value Options Description
**wm_shadow_color** None None The color of the drop shadow, specified in hex. If you leave this blank
a drop shadow will not be used. Both the full 6-length (ie, 993300) and
the short three character abbreviated version (ie, fff) are supported.
-**wm_shadow_distance** 3 None The distance (in pixels) from the font that the drop shadow should
+**wm_shadow_distance** 2 None The distance (in pixels) from the font that the drop shadow should
appear.
======================= =================== =================== ==========================================================================
diff --git a/user_guide_src/source/libraries/table.rst b/user_guide_src/source/libraries/table.rst
index 91ae1ae8d..06dfe59de 100644
--- a/user_guide_src/source/libraries/table.rst
+++ b/user_guide_src/source/libraries/table.rst
@@ -275,11 +275,16 @@ Class Reference
:returns: CI_Table instance (method chaining)
:rtype: CI_Table
- Lets you clear the table heading and row data. If you need to show multiple tables with different data you should to call this method
- after each table has been generated to clear the previous table information. Example::
+ Lets you clear the table heading, row data and caption. If
+ you need to show multiple tables with different data you
+ should to call this method after each table has been
+ generated to clear the previous table information.
+
+ Example ::
$this->load->library('table');
+ $this->table->set_caption('Preferences');
$this->table->set_heading('Name', 'Color', 'Size');
$this->table->add_row('Fred', 'Blue', 'Small');
$this->table->add_row('Mary', 'Red', 'Large');
@@ -289,6 +294,7 @@ Class Reference
$this->table->clear();
+ $this->table->set_caption('Shipping');
$this->table->set_heading('Name', 'Day', 'Delivery');
$this->table->add_row('Fred', 'Wednesday', 'Express');
$this->table->add_row('Mary', 'Monday', 'Air');