diff options
34 files changed, 1380 insertions, 123 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/migration.php b/application/config/migration.php index 509fd90ab..dba870010 100644 --- a/application/config/migration.php +++ b/application/config/migration.php @@ -9,7 +9,7 @@ | and disable it back when you're done.
|
*/
-$config['migration_enabled'] = TRUE;
+$config['migration_enabled'] = FALSE;
/*
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 7b92ddf11..0a1391d18 100755 --- a/system/core/CodeIgniter.php +++ b/system/core/CodeIgniter.php @@ -27,10 +27,11 @@ * @link http://codeigniter.com/user_guide/ */ -/* - * ------------------------------------------------------ - * Define the CodeIgniter Version - * ------------------------------------------------------ +/** + * CodeIgniter Version + * + * @var string + * */ /** * CodeIgniter Version @@ -40,10 +41,11 @@ */ 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) diff --git a/system/core/Config.php b/system/core/Config.php index 5cacf867c..714c4667b 100755 --- a/system/core/Config.php +++ b/system/core/Config.php @@ -218,10 +218,7 @@ class CI_Config { // -------------------------------------------------------------------- /** - * Fetch a config file item - adds slash after item - * - * The second parameter allows a slash to be added to the end of - * the item, in the case of a path. + * Fetch a config file item - adds slash after item (if item is not empty) * * @access public * @param string the config item name @@ -234,6 +231,10 @@ class CI_Config { { return FALSE; } + if( trim($this->config[$item]) == '') + { + return ''; + } return rtrim($this->config[$item], '/').'/'; } @@ -242,6 +243,7 @@ class CI_Config { /** * Site URL + * Returns base_url . index_page [. uri_string] * * @access public * @param string the URI string @@ -256,14 +258,48 @@ class CI_Config { if ($this->item('enable_query_strings') == FALSE) { + $suffix = ($this->item('url_suffix') == FALSE) ? '' : $this->item('url_suffix'); + return $this->slash_item('base_url').$this->slash_item('index_page').$this->_uri_string($uri).$suffix; + } + else + { + return $this->slash_item('base_url').$this->item('index_page').'?'.$this->_uri_string($uri); + } + } + + // ------------------------------------------------------------- + + /** + * Base URL + * Returns base_url [. uri_string] + * + * @access public + * @param string $uri + * @return string + */ + function base_url($uri = '') + { + return $this->slash_item('base_url').ltrim($this->_uri_string($uri),'/'); + } + + // ------------------------------------------------------------- + + /** + * Build URI string for use in Config::site_url() and Config::base_url() + * + * @access protected + * @param $uri + * @return string + */ + protected function _uri_string($uri) + { + if ($this->item('enable_query_strings') == FALSE) + { if (is_array($uri)) { $uri = implode('/', $uri); } - - $index = $this->item('index_page') == '' ? '' : $this->slash_item('index_page'); - $suffix = ($this->item('url_suffix') == FALSE) ? '' : $this->item('url_suffix'); - return $this->slash_item('base_url').$index.trim($uri, '/').$suffix; + $uri = trim($uri, '/'); } else { @@ -277,12 +313,10 @@ class CI_Config { $str .= $prefix.$key.'='.$val; $i++; } - $uri = $str; } - - return $this->slash_item('base_url').$this->item('index_page').'?'.$uri; } + return $uri; } // -------------------------------------------------------------------- diff --git a/system/core/Input.php b/system/core/Input.php index bc202b3fc..5a033e7b8 100755 --- a/system/core/Input.php +++ b/system/core/Input.php @@ -710,7 +710,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 019de82c1..e7fa3d3f6 100755 --- a/system/core/Loader.php +++ b/system/core/Loader.php @@ -1018,22 +1018,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; } } diff --git a/system/core/URI.php b/system/core/URI.php index 10b0b7fa3..a3ae20cc3 100755 --- a/system/core/URI.php +++ b/system/core/URI.php @@ -87,7 +87,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 0a25b3cb5..7bab729f5 100644 --- a/system/database/DB_active_rec.php +++ b/system/database/DB_active_rec.php @@ -870,11 +870,11 @@ class CI_DB_active_record extends CI_DB_driver { */ 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; @@ -1322,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; @@ -1694,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); diff --git a/system/database/DB_forge.php b/system/database/DB_forge.php index a71fca78f..0dd29c238 100644 --- a/system/database/DB_forge.php +++ b/system/database/DB_forge.php @@ -234,7 +234,7 @@ class CI_DB_forge { show_error('A table name is required for that operation.'); } - $sql = $this->_rename_table($table_name, $new_table_name); + $sql = $this->_rename_table($this->db->dbprefix.$table_name, $this->db->dbprefix.$new_table_name); return $this->db->query($sql); } 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/sqlsrv/index.html b/system/database/drivers/sqlsrv/index.html new file mode 100644 index 000000000..c942a79ce --- /dev/null +++ b/system/database/drivers/sqlsrv/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/sqlsrv/sqlsrv_driver.php b/system/database/drivers/sqlsrv/sqlsrv_driver.php new file mode 100644 index 000000000..1d32792ce --- /dev/null +++ b/system/database/drivers/sqlsrv/sqlsrv_driver.php @@ -0,0 +1,598 @@ +<?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 ExpressionEngine Dev Team + * @copyright Copyright (c) 2008 - 2011, EllisLab, Inc. + * @license http://codeigniter.com/user_guide/license.html + * @link http://codeigniter.com + * @since Version 1.0 + * @filesource + */ + +// ------------------------------------------------------------------------ + +/** + * SQLSRV 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 ExpressionEngine Dev Team + * @link http://codeigniter.com/user_guide/database/ + */ +class CI_DB_sqlsrv_driver extends CI_DB { + + var $dbdriver = 'sqlsrv'; + + // The character used for escaping + var $_escape_char = ''; + + // clause and character used for LIKE escape sequences + var $_like_escape_str = " ESCAPE '%s' "; + 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 = ' ASC'; // not currently supported + + /** + * Non-persistent database connection + * + * @access private called by the base class + * @return resource + */ + function db_connect($pooling = false) + { + // Check for a UTF-8 charset being passed as CI's default 'utf8'. + $character_set = (0 === strcasecmp('utf8', $this->char_set)) ? 'UTF-8' : $this->char_set; + + $connection = array( + 'UID' => empty($this->username) ? '' : $this->username, + 'PWD' => empty($this->password) ? '' : $this->password, + 'Database' => $this->database, + 'ConnectionPooling' => $pooling ? 1 : 0, + 'CharacterSet' => $character_set, + 'ReturnDatesAsStrings' => 1 + ); + + // If the username and password are both empty, assume this is a + // 'Windows Authentication Mode' connection. + if(empty($connection['UID']) && empty($connection['PWD'])) { + unset($connection['UID'], $connection['PWD']); + } + + return sqlsrv_connect($this->hostname, $connection); + } + + // -------------------------------------------------------------------- + + /** + * Persistent database connection + * + * @access private called by the base class + * @return resource + */ + function db_pconnect() + { + $this->db_connect(TRUE); + } + + // -------------------------------------------------------------------- + + /** + * 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() + { + // not implemented in MSSQL + } + + // -------------------------------------------------------------------- + + /** + * Select the database + * + * @access private called by the base class + * @return resource + */ + function db_select() + { + return $this->_execute('USE ' . $this->database); + } + + // -------------------------------------------------------------------- + + /** + * Set client character set + * + * @access public + * @param string + * @param string + * @return resource + */ + function db_set_charset($charset, $collation) + { + // @todo - add support if needed + return TRUE; + } + + // -------------------------------------------------------------------- + + /** + * 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 sqlsrv_query($this->conn_id, $sql, null, array( + 'Scrollable' => SQLSRV_CURSOR_STATIC, + 'SendStreamParamsAtExec' => true + )); + } + + // -------------------------------------------------------------------- + + /** + * 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) + { + 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; + + return sqlsrv_begin_transaction($this->conn_id); + } + + // -------------------------------------------------------------------- + + /** + * 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; + } + + return sqlsrv_commit($this->conn_id); + } + + // -------------------------------------------------------------------- + + /** + * 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; + } + + return sqlsrv_rollback($this->conn_id); + } + + // -------------------------------------------------------------------- + + /** + * 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) + { + // Escape single quotes + return str_replace("'", "''", $str); + } + + // -------------------------------------------------------------------- + + /** + * Affected Rows + * + * @access public + * @return integer + */ + function affected_rows() + { + return @sqlrv_rows_affected($this->conn_id); + } + + // -------------------------------------------------------------------- + + /** + * Insert ID + * + * Returns the last id created in the Identity column. + * + * @access public + * @return integer + */ + function insert_id() + { + return $this->query('select @@IDENTITY as insert_id')->row('insert_id'); + } + + // -------------------------------------------------------------------- + + /** + * Parse major version + * + * Grabs the major version number from the + * database server version string passed in. + * + * @access private + * @param string $version + * @return int16 major version number + */ + function _parse_major_version($version) + { + preg_match('/([0-9]+)\.([0-9]+)\.([0-9]+)/', $version, $ver_info); + return $ver_info[1]; // return the major version b/c that's all we're interested in. + } + + // -------------------------------------------------------------------- + + /** + * Version number query string + * + * @access public + * @return string + */ + function _version() + { + $info = sqlsrv_server_info($this->conn_id); + return sprintf("select '%s' as ver", $info['SQLServerVersion']); + } + + // -------------------------------------------------------------------- + + /** + * "Count All" query + * + * Generates a platform-specific query string that counts all records in + * the specified database + * + * @access public + * @param string + * @return string + */ + function count_all($table = '') + { + if ($table == '') + return '0'; + + $query = $this->query("SELECT COUNT(*) AS numrows FROM " . $this->dbprefix . $table); + + if ($query->num_rows() == 0) + return '0'; + + $row = $query->row(); + return $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) + { + return "SELECT name FROM sysobjects WHERE type = 'U' ORDER BY name"; + } + + // -------------------------------------------------------------------- + + /** + * List column query + * + * Generates a platform-specific query string so that the column names can be fetched + * + * @access private + * @param string the table name + * @return string + */ + function _list_columns($table = '') + { + return "SELECT * FROM INFORMATION_SCHEMA.Columns WHERE TABLE_NAME = '".$this->_escape_table($table)."'"; + } + + // -------------------------------------------------------------------- + + /** + * 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 TOP 1 * FROM " . $this->_escape_table($table); + } + + // -------------------------------------------------------------------- + + /** + * The error message string + * + * @access private + * @return string + */ + function _error_message() + { + $error = array_shift(sqlsrv_errors()); + return !empty($error['message']) ? $error['message'] : null; + } + + // -------------------------------------------------------------------- + + /** + * The error message number + * + * @access private + * @return integer + */ + function _error_number() + { + $error = array_shift(sqlsrv_errors()); + return isset($error['SQLSTATE']) ? $error['SQLSTATE'] : null; + } + + // -------------------------------------------------------------------- + + /** + * Escape Table Name + * + * This function adds backticks if the table name has a period + * in it. Some DBs will get cranky unless periods are escaped + * + * @access private + * @param string the table name + * @return string + */ + function _escape_table($table) + { + return $table; + } + + + /** + * Escape the SQL Identifiers + * + * This function escapes column and table names + * + * @access private + * @param string + * @return string + */ + function _escape_identifiers($item) + { + return $item; + } + + // -------------------------------------------------------------------- + + /** + * 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 ".$this->_escape_table($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) + { + foreach($values as $key => $val) + { + $valstr[] = $key." = ".$val; + } + + return "UPDATE ".$this->_escape_table($table)." SET ".implode(', ', $valstr)." WHERE ".implode(" ", $where); + } + + // -------------------------------------------------------------------- + + /** + * 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) + { + return "DELETE FROM ".$this->_escape_table($table)." WHERE ".implode(" ", $where); + } + + // -------------------------------------------------------------------- + + /** + * 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) + { + $i = $limit + $offset; + + return preg_replace('/(^\SELECT (DISTINCT)?)/i','\\1 TOP '.$i.' ', $sql); + } + + // -------------------------------------------------------------------- + + /** + * Close DB Connection + * + * @access public + * @param resource + * @return void + */ + function _close($conn_id) + { + @sqlsrv_close($conn_id); + } + +} + + + +/* End of file mssql_driver.php */ +/* Location: ./system/database/drivers/mssql/mssql_driver.php */
\ No newline at end of file diff --git a/system/database/drivers/sqlsrv/sqlsrv_forge.php b/system/database/drivers/sqlsrv/sqlsrv_forge.php new file mode 100644 index 000000000..cc88ec5ca --- /dev/null +++ b/system/database/drivers/sqlsrv/sqlsrv_forge.php @@ -0,0 +1,248 @@ +<?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 ExpressionEngine Dev Team + * @copyright Copyright (c) 2008 - 2011, EllisLab, Inc. + * @license http://codeigniter.com/user_guide/license.html + * @link http://codeigniter.com + * @since Version 1.0 + * @filesource + */ + +// ------------------------------------------------------------------------ + +/** + * SQLSRV Forge Class + * + * @category Database + * @author ExpressionEngine Dev Team + * @link http://codeigniter.com/user_guide/database/ + */ +class CI_DB_sqlsrv_forge extends CI_DB_forge { + + /** + * Create database + * + * @access private + * @param string the database name + * @return bool + */ + function _create_database($name) + { + return "CREATE DATABASE ".$name; + } + + // -------------------------------------------------------------------- + + /** + * Drop database + * + * @access private + * @param string the database name + * @return bool + */ + function _drop_database($name) + { + return "DROP DATABASE ".$name; + } + + // -------------------------------------------------------------------- + + /** + * Drop Table + * + * @access private + * @return bool + */ + function _drop_table($table) + { + return "DROP TABLE ".$this->db->_escape_identifiers($table); + } + + // -------------------------------------------------------------------- + + /** + * Create Table + * + * @access private + * @param string the table name + * @param array 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 '; + } + + $sql .= $this->db->_escape_identifiers($table)." ("; + $current_field_count = 0; + + foreach ($fields as $field=>$attributes) + { + // Numeric field names aren't allowed in databases, so if the key is + // numeric, we know it was assigned by PHP and the developer manually + // entered the field information, so we'll simply add it to the list + if (is_numeric($field)) + { + $sql .= "\n\t$attributes"; + } + else + { + $attributes = array_change_key_case($attributes, CASE_UPPER); + + $sql .= "\n\t".$this->db->_protect_identifiers($field); + + $sql .= ' '.$attributes['TYPE']; + + if (array_key_exists('CONSTRAINT', $attributes)) + { + $sql .= '('.$attributes['CONSTRAINT'].')'; + } + + if (array_key_exists('UNSIGNED', $attributes) && $attributes['UNSIGNED'] === TRUE) + { + $sql .= ' UNSIGNED'; + } + + if (array_key_exists('DEFAULT', $attributes)) + { + $sql .= ' DEFAULT \''.$attributes['DEFAULT'].'\''; + } + + if (array_key_exists('NULL', $attributes) && $attributes['NULL'] === TRUE) + { + $sql .= ' NULL'; + } + else + { + $sql .= ' NOT NULL'; + } + + if (array_key_exists('AUTO_INCREMENT', $attributes) && $attributes['AUTO_INCREMENT'] === TRUE) + { + $sql .= ' AUTO_INCREMENT'; + } + } + + // don't add a comma on the end of the last field + if (++$current_field_count < count($fields)) + { + $sql .= ','; + } + } + + if (count($primary_keys) > 0) + { + $primary_keys = $this->db->_protect_identifiers($primary_keys); + $sql .= ",\n\tPRIMARY KEY (" . implode(', ', $primary_keys) . ")"; + } + + if (is_array($keys) && count($keys) > 0) + { + foreach ($keys as $key) + { + if (is_array($key)) + { + $key = $this->db->_protect_identifiers($key); + } + else + { + $key = array($this->db->_protect_identifiers($key)); + } + + $sql .= ",\n\tFOREIGN KEY (" . implode(', ', $key) . ")"; + } + } + + $sql .= "\n)"; + + return $sql; + } + + // -------------------------------------------------------------------- + + /** + * Alter table query + * + * Generates a platform-specific query so that a table can be altered + * Called by add_column(), drop_column(), and column_alter(), + * + * @access private + * @param string the ALTER type (ADD, DROP, CHANGE) + * @param string the column name + * @param string the table name + * @param string the column definition + * @param string the default value + * @param boolean should 'NOT NULL' be added + * @param string the field after which we should add the new field + * @return object + */ + function _alter_table($alter_type, $table, $column_name, $column_definition = '', $default_value = '', $null = '', $after_field = '') + { + $sql = 'ALTER TABLE '.$this->db->_protect_identifiers($table)." $alter_type ".$this->db->_protect_identifiers($column_name); + + // DROP has everything it needs now. + if ($alter_type == 'DROP') + { + return $sql; + } + + $sql .= " $column_definition"; + + if ($default_value != '') + { + $sql .= " DEFAULT \"$default_value\""; + } + + if ($null === NULL) + { + $sql .= ' NULL'; + } + else + { + $sql .= ' NOT NULL'; + } + + if ($after_field != '') + { + $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) + { + // I think this syntax will work, but can find little documentation on renaming tables in MSSQL + $sql = 'ALTER TABLE '.$this->db->_protect_identifiers($table_name)." RENAME TO ".$this->db->_protect_identifiers($new_table_name); + return $sql; + } + +} + +/* End of file mssql_forge.php */ +/* Location: ./system/database/drivers/mssql/mssql_forge.php */
\ No newline at end of file diff --git a/system/database/drivers/sqlsrv/sqlsrv_result.php b/system/database/drivers/sqlsrv/sqlsrv_result.php new file mode 100644 index 000000000..bf0abd1c6 --- /dev/null +++ b/system/database/drivers/sqlsrv/sqlsrv_result.php @@ -0,0 +1,169 @@ +<?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 ExpressionEngine Dev Team + * @copyright Copyright (c) 2008 - 2011, EllisLab, Inc. + * @license http://codeigniter.com/user_guide/license.html + * @link http://codeigniter.com + * @since Version 1.0 + * @filesource + */ + +// ------------------------------------------------------------------------ + +/** + * SQLSRV Result Class + * + * This class extends the parent result class: CI_DB_result + * + * @category Database + * @author ExpressionEngine Dev Team + * @link http://codeigniter.com/user_guide/database/ + */ +class CI_DB_sqlsrv_result extends CI_DB_result { + + /** + * Number of rows in the result set + * + * @access public + * @return integer + */ + function num_rows() + { + return @sqlsrv_num_rows($this->result_id); + } + + // -------------------------------------------------------------------- + + /** + * Number of fields in the result set + * + * @access public + * @return integer + */ + function num_fields() + { + return @sqlsrv_num_fields($this->result_id); + } + + // -------------------------------------------------------------------- + + /** + * Fetch Field Names + * + * Generates an array of column names + * + * @access public + * @return array + */ + function list_fields() + { + $field_names = array(); + foreach(sqlsrv_field_metadata($this->result_id) as $offset => $field) + { + $field_names[] = $field['Name']; + } + + return $field_names; + } + + // -------------------------------------------------------------------- + + /** + * Field data + * + * Generates an array of objects containing field meta-data + * + * @access public + * @return array + */ + function field_data() + { + $retval = array(); + foreach(sqlsrv_field_metadata($this->result_id) as $offset => $field) + { + $F = new stdClass(); + $F->name = $field['Name']; + $F->type = $field['Type']; + $F->max_length = $field['Size']; + $F->primary_key = 0; + $F->default = ''; + + $retval[] = $F; + } + + return $retval; + } + + // -------------------------------------------------------------------- + + /** + * Free the result + * + * @return null + */ + function free_result() + { + if (is_resource($this->result_id)) + { + sqlsrv_free_stmt($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) + { + // Not implemented + } + + // -------------------------------------------------------------------- + + /** + * Result - associative array + * + * Returns the result set as an array + * + * @access private + * @return array + */ + function _fetch_assoc() + { + return sqlsrv_fetch_array($this->result_id, SQLSRV_FETCH_ASSOC); + } + + // -------------------------------------------------------------------- + + /** + * Result - object + * + * Returns the result set as an object + * + * @access private + * @return object + */ + function _fetch_object() + { + return sqlsrv_fetch_object($this->result_id); + } + +} + + +/* End of file mssql_result.php */ +/* Location: ./system/database/drivers/mssql/mssql_result.php */
\ No newline at end of file diff --git a/system/database/drivers/sqlsrv/sqlsrv_utility.php b/system/database/drivers/sqlsrv/sqlsrv_utility.php new file mode 100644 index 000000000..13a1850c4 --- /dev/null +++ b/system/database/drivers/sqlsrv/sqlsrv_utility.php @@ -0,0 +1,88 @@ +<?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 ExpressionEngine Dev Team + * @copyright Copyright (c) 2008 - 2011, EllisLab, Inc. + * @license http://codeigniter.com/user_guide/license.html + * @link http://codeigniter.com + * @since Version 1.0 + * @filesource + */ + +// ------------------------------------------------------------------------ + +/** + * SQLSRV Utility Class + * + * @category Database + * @author ExpressionEngine Dev Team + * @link http://codeigniter.com/user_guide/database/ + */ +class CI_DB_sqlsrv_utility extends CI_DB_utility { + + /** + * List databases + * + * @access private + * @return bool + */ + function _list_databases() + { + return "EXEC sp_helpdb"; // Can also be: EXEC sp_databases + } + + // -------------------------------------------------------------------- + + /** + * Optimize table query + * + * Generates a platform-specific query so that a table can be optimized + * + * @access private + * @param string the table name + * @return object + */ + function _optimize_table($table) + { + return FALSE; // Is this supported in MS SQL? + } + + // -------------------------------------------------------------------- + + /** + * Repair table query + * + * Generates a platform-specific query so that a table can be repaired + * + * @access private + * @param string the table name + * @return object + */ + function _repair_table($table) + { + return FALSE; // Is this supported in MS SQL? + } + + // -------------------------------------------------------------------- + + /** + * MSSQL Export + * + * @access private + * @param array Preferences + * @return mixed + */ + function _backup($params = array()) + { + // Currently unsupported + return $this->db->display_error('db_unsuported_feature'); + } + +} + +/* End of file mssql_utility.php */ +/* Location: ./system/database/drivers/mssql/mssql_utility.php */
\ No newline at end of file diff --git a/system/helpers/form_helper.php b/system/helpers/form_helper.php index 5720a06ec..47f93e748 100644 --- a/system/helpers/form_helper.php +++ b/system/helpers/form_helper.php @@ -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..9fa69f46c 100644 --- a/system/helpers/string_helper.php +++ b/system/helpers/string_helper.php @@ -243,6 +243,23 @@ 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 + * @param string $separator What should the duplicate number be appended with + * @param string $first Which number should be used for the first dupe increment + * @return string + */ +function increment_string($str, $separator = '_', $first = 1) +{ + preg_match('/(.+)'.$separator.'([0-9]+)$/', $str, $match); + + return isset($match[2]) ? $match[1].$separator.($match[2] + 1) : $str.$separator.$first; +} + +// ------------------------------------------------------------------------ + +/** * Alternator * * Allows strings to be alternated. See docs... diff --git a/system/helpers/url_helper.php b/system/helpers/url_helper.php index d0516cee6..9f4b85248 100644 --- a/system/helpers/url_helper.php +++ b/system/helpers/url_helper.php @@ -50,18 +50,21 @@ if ( ! function_exists('site_url')) /** * Base URL - * - * Returns the "base_url" item from your config file + * + * Create a local URL based on your basepath. + * Segments can be passed in as a string or an array, same as site_url + * or a URL to a file can be passed in, e.g. to an image file. * * @access public + * @param string * @return string */ if ( ! function_exists('base_url')) { - function base_url() + function base_url($uri = '') { $CI =& get_instance(); - return $CI->config->slash_item('base_url'); + return $CI->config->base_url($uri); } } 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 9b3bc75e1..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; } diff --git a/system/libraries/Form_validation.php b/system/libraries/Form_validation.php index fd95d76fa..a34809e05 100644 --- a/system/libraries/Form_validation.php +++ b/system/libraries/Form_validation.php @@ -1378,4 +1378,4 @@ class CI_Form_validation { // END Form Validation Class /* End of file Form_validation.php */ -/* Location: ./system/libraries/Form_validation.php */
\ No newline at end of file +/* Location: ./system/libraries/Form_validation.php */ 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 e0cefc316..20b1c4e49 100644 --- a/user_guide/changelog.html +++ b/user_guide/changelog.html @@ -59,6 +59,44 @@ 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> + <li class="reactor">Added <samp>increment_string()</samp> to <a href="helpers/string_helper.html">String Helper</a> to turn "foo" into "foo-1" or "foo-1" into "foo-2".</li> + </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> @@ -74,14 +112,15 @@ Change Log <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">Callback validation rules can now accept parameters like any other validation rule.</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 @@ -91,7 +130,7 @@ Change Log <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>Changed <kbd>$this->db->having()</kbd> to insert quotes using escape() rather than escape_str().</li> + <li class="reactor">Changed <kbd>$this->db->having()</kbd> to insert quotes using escape() rather than escape_str().</li> </ul> </li> </ul> @@ -104,9 +143,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>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 (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="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/general/cli.html b/user_guide/general/cli.html index 962954b15..ed6fc85a8 100644 --- a/user_guide/general/cli.html +++ b/user_guide/general/cli.html @@ -72,7 +72,7 @@ Running via the CLI <a name="what"></a> <h2>What is the CLI?</h2> -<p><dfn>The command-line interface is a text-based method of interacting with computers that looks like what most people remember as DOS.</dfn></p> +<p><dfn>The command-line interface is a text-based method of interacting with computers.</dfn> For more information, check the <a href="http://en.wikipedia.org/wiki/Command-line_interface">Wikipedia article</a>.</p> <a name="why"></a> diff --git a/user_guide/helpers/string_helper.html b/user_guide/helpers/string_helper.html index 169ee4ebb..7c1d30c59 100644 --- a/user_guide/helpers/string_helper.html +++ b/user_guide/helpers/string_helper.html @@ -90,6 +90,17 @@ String Helper <code>echo random_string('alnum', 16);</code> +<h2>increment_string()</h2> + +<p>Increments a string by appending a number to it or increasing the number. Useful for creating "copies" or a file or duplicating database content which has unique titles or slugs.</p> + +<p>Usage example:</p> + +<code>echo increment_string('file', '_'); // "file_1"<br/> +echo increment_string('file', '-', 2); // "file-2"<br/> +echo increment_string('file-4'); // "file-5"<br/></code> + + <h2>alternator()</h2> <p>Allows two or more items to be alternated between, when cycling through a loop. Example:</p> diff --git a/user_guide/helpers/url_helper.html b/user_guide/helpers/url_helper.html index d20f1b1e2..ac9d0a68e 100644 --- a/user_guide/helpers/url_helper.html +++ b/user_guide/helpers/url_helper.html @@ -70,7 +70,7 @@ URL Helper <h2>site_url()</h2> <p>Returns your site URL, as specified in your config file. The index.php file (or whatever you have set as your -site <dfn>index_page</dfn> in your config file) will be added to the URL, as will any URI segments you pass to the function.</p> +site <dfn>index_page</dfn> in your config file) will be added to the URL, as will any URI segments you pass to the function, and the <dfn>url_suffix</dfn> as set in your config file.</p> <p>You are encouraged to use this function any time you need to generate a local URL so that your pages become more portable in the event your URL changes.</p> @@ -93,6 +93,20 @@ echo site_url($segments);</code> <p>Returns your site base URL, as specified in your config file. Example:</p> <code>echo base_url();</code> +<p>This function returns the same thing as site_url, without the <dfn>index_page</dfn> or <dfn>url_suffix</dfn> being appended.</p> + +<p>Also like site_url, you can supply segments as a string or an array. Here is a string example:</p> + +<code>echo base_url("blog/post/123");</code> + +<p>The above example would return something like: http://example.com/blog/post/123</p> + +<p>This is useful because unlike site_url(), you can supply a string to a file, such as an image or stylesheet. For example:</p> + +<code>echo base_url("images/icons/edit.png");</code> + +<p>This would give you something like: http://example.com/images/icons/edit.png</p> + <h2>current_url()</h2> <p>Returns the full URL (including segments) of the page being currently viewed.</p> diff --git a/user_guide/libraries/cart.html b/user_guide/libraries/cart.html index 81b43e363..2e2beed9c 100644 --- a/user_guide/libraries/cart.html +++ b/user_guide/libraries/cart.html @@ -109,7 +109,8 @@ It is intended to be used in cases where your product has options associated wit <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>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> @@ -264,7 +265,7 @@ $this->cart->update($data); </code> -<p><strong>What is a Row ID?</strong> 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 +<p><strong>What is a Row ID?</strong> 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 diff --git a/user_guide/libraries/config.html b/user_guide/libraries/config.html index 2433ec4ad..be75801e0 100644 --- a/user_guide/libraries/config.html +++ b/user_guide/libraries/config.html @@ -194,6 +194,11 @@ $site_name = $blog_config['site_name'];</code> <h2>$this->config->site_url();</h2> <p>This function retrieves the URL to your site, along with the "index" value you've specified in the config file.</p> +<h2>$this->config->base_url();</h2> +<p>This function retrieves the URL to your site, plus an optional path such as to a stylesheet or image.</p> + +<p>The two functions above are normally accessed via the corresponding functions in the <a href="../helpers/url_helper.html">URL Helper.</a></p> + <h2>$this->config->system_url();</h2> <p>This function retrieves the URL to your <dfn>system folder</dfn>.</p> diff --git a/user_guide/libraries/form_validation.html b/user_guide/libraries/form_validation.html index bba8f507e..da2f5e5e8 100644 --- a/user_guide/libraries/form_validation.html +++ b/user_guide/libraries/form_validation.html @@ -508,11 +508,9 @@ 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"><?php +<textarea class="textarea" style="width:100%" cols="50" rows="40"><?php class Form extends CI_Controller { @@ -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> |