Merge pull request #594 from ktomk/patch-8

CI_Loader::driver() processes empty library. Fixed.
diff --git a/application/config/constants.php b/application/config/constants.php
index 4a879d3..ee177f5 100644
--- a/application/config/constants.php
+++ b/application/config/constants.php
@@ -36,6 +36,18 @@
 define('FOPEN_WRITE_CREATE_STRICT',				'xb');
 define('FOPEN_READ_WRITE_CREATE_STRICT',		'x+b');
 
+/*
+|--------------------------------------------------------------------------
+| Display Debug backtrace
+|--------------------------------------------------------------------------
+|
+| If set to TRUE, a backtrace will be displayed along with php errors. If 
+| error_reporting is disabled, the backtrace will not display, regardless 
+| of this setting
+|
+*/
+define('SHOW_DEBUG_BACKTRACE', TRUE);
+
 
 /* End of file constants.php */
 /* Location: ./application/config/constants.php */
\ No newline at end of file
diff --git a/application/config/migration.php b/application/config/migration.php
index 1f532f1..3ca47f6 100644
--- a/application/config/migration.php
+++ b/application/config/migration.php
@@ -1,71 +1,71 @@
-<?php defined('BASEPATH') OR exit('No direct script access allowed');

-/*

-|--------------------------------------------------------------------------

-| Enable/Disable Migrations

-|--------------------------------------------------------------------------

-|

-| Migrations are disabled by default for security reasons.

-| You should enable migrations whenever you intend to do a schema migration

-| and disable it back when you're done.

-|

-*/

-$config['migration_enabled'] = FALSE;

-

-/*

-|--------------------------------------------------------------------------

-| Migrations table

-|--------------------------------------------------------------------------

-|

-| This is the name of the table that will store the current migrations state.

-| When migrations runs it will store in a database table which migration 

-| level the system is at. It then compares the migration level in the this

-| table to the $config['migration_version'] if they are not the same it

-| will migrate up. This must be set.

-|

-*/

-$config['migration_table'] = 'migrations';

-

-

-/*

-|--------------------------------------------------------------------------

-| Auto Migrate To Latest

-|--------------------------------------------------------------------------

-|

-| If this is set to TRUE when you load the migrations class and have 

-| $config['migration_enabled'] set to TRUE the system will auto migrate

-| to your latest migration (whatever $config['migration_version'] is

-| set to). This way you do not have to call migrations anywhere else

-| in your code to have the latest migration.

-|

-*/

-$config['migration_auto_latest'] = FALSE;

-

-

-/*

-|--------------------------------------------------------------------------

-| Migrations version

-|--------------------------------------------------------------------------

-|

-| This is used to set migration version that the file system should be on.

-| If you run $this->migration->latest() this is the version that schema will

-| be upgraded / downgraded to.

-|

-*/

-$config['migration_version'] = 0;

-

-

-/*

-|--------------------------------------------------------------------------

-| Migrations Path

-|--------------------------------------------------------------------------

-|

-| Path to your migrations folder.

-| Typically, it will be within your application path.

-| Also, writing permission is required within the migrations path.

-|

-*/

-$config['migration_path'] = APPPATH . 'migrations/';

-

-

-/* End of file migration.php */

+<?php defined('BASEPATH') OR exit('No direct script access allowed');
+/*
+|--------------------------------------------------------------------------
+| Enable/Disable Migrations
+|--------------------------------------------------------------------------
+|
+| Migrations are disabled by default for security reasons.
+| You should enable migrations whenever you intend to do a schema migration
+| and disable it back when you're done.
+|
+*/
+$config['migration_enabled'] = FALSE;
+
+/*
+|--------------------------------------------------------------------------
+| Migrations table
+|--------------------------------------------------------------------------
+|
+| This is the name of the table that will store the current migrations state.
+| When migrations runs it will store in a database table which migration 
+| level the system is at. It then compares the migration level in the this
+| table to the $config['migration_version'] if they are not the same it
+| will migrate up. This must be set.
+|
+*/
+$config['migration_table'] = 'migrations';
+
+
+/*
+|--------------------------------------------------------------------------
+| Auto Migrate To Latest
+|--------------------------------------------------------------------------
+|
+| If this is set to TRUE when you load the migrations class and have 
+| $config['migration_enabled'] set to TRUE the system will auto migrate
+| to your latest migration (whatever $config['migration_version'] is
+| set to). This way you do not have to call migrations anywhere else
+| in your code to have the latest migration.
+|
+*/
+$config['migration_auto_latest'] = FALSE;
+
+
+/*
+|--------------------------------------------------------------------------
+| Migrations version
+|--------------------------------------------------------------------------
+|
+| This is used to set migration version that the file system should be on.
+| If you run $this->migration->latest() this is the version that schema will
+| be upgraded / downgraded to.
+|
+*/
+$config['migration_version'] = 0;
+
+
+/*
+|--------------------------------------------------------------------------
+| Migrations Path
+|--------------------------------------------------------------------------
+|
+| Path to your migrations folder.
+| Typically, it will be within your application path.
+| Also, writing permission is required within the migrations path.
+|
+*/
+$config['migration_path'] = APPPATH . 'migrations/';
+
+
+/* End of file migration.php */
 /* Location: ./application/config/migration.php */
\ No newline at end of file
diff --git a/application/errors/error_php.php b/application/errors/error_php.php
index f085c20..514e477 100644
--- a/application/errors/error_php.php
+++ b/application/errors/error_php.php
@@ -7,4 +7,21 @@
 <p>Filename: <?php echo $filepath; ?></p>
 <p>Line Number: <?php echo $line; ?></p>
 
+<?php if(defined('SHOW_DEBUG_BACKTRACE') && SHOW_DEBUG_BACKTRACE === TRUE): ?>
+	
+	<p>Backtrace: </p>
+	<?php foreach(debug_backtrace() as $error): ?>
+	
+		<?php if(isset($error['file']) &&  ! stristr($error['file'], SYSDIR)): ?>
+			<p style="margin-left:10px">
+			File: <?php echo $error['file'] ?><br />
+			Line: <?php echo $error['line'] ?><br />
+			Function: <?php echo $error['function'] ?>
+			</p>
+		<? endif ?>
+	
+	<? endforeach ?></p>
+
+<?php endif ?>
+
 </div>
\ No newline at end of file
diff --git a/system/database/DB_active_rec.php b/system/database/DB_active_rec.php
index 8351823..f99d13e 100644
--- a/system/database/DB_active_rec.php
+++ b/system/database/DB_active_rec.php
@@ -28,39 +28,42 @@
  */
 class CI_DB_active_record extends CI_DB_driver {
 
-	var $ar_select				= array();
-	var $ar_distinct			= FALSE;
-	var $ar_from				= array();
-	var $ar_join				= array();
-	var $ar_where				= array();
-	var $ar_like				= array();
-	var $ar_groupby				= array();
-	var $ar_having				= array();
-	var $ar_keys				= array();
-	var $ar_limit				= FALSE;
-	var $ar_offset				= FALSE;
-	var $ar_order				= FALSE;
-	var $ar_orderby				= array();
-	var $ar_set					= array();
-	var $ar_wherein				= array();
-	var $ar_aliased_tables		= array();
-	var $ar_store_array			= array();
+	protected $return_delete_sql	= FALSE;
+	protected $reset_delete_data	= FALSE;
+	
+	protected $ar_select			= array();
+	protected $ar_distinct			= FALSE;
+	protected $ar_from				= array();
+	protected $ar_join				= array();
+	protected $ar_where				= array();
+	protected $ar_like				= array();
+	protected $ar_groupby			= array();
+	protected $ar_having			= array();
+	protected $ar_keys				= array();
+	protected $ar_limit				= FALSE;
+	protected $ar_offset			= FALSE;
+	protected $ar_order				= FALSE;
+	protected $ar_orderby			= array();
+	protected $ar_set				= array();
+	protected $ar_wherein			= array();
+	protected $ar_aliased_tables	= array();
+	protected $ar_store_array		= array();
 
 	// Active Record Caching variables
-	var $ar_caching				= FALSE;
-	var $ar_cache_exists		= array();
-	var $ar_cache_select		= array();
-	var $ar_cache_from			= array();
-	var $ar_cache_join			= array();
-	var $ar_cache_where			= array();
-	var $ar_cache_like			= array();
-	var $ar_cache_groupby		= array();
-	var $ar_cache_having		= array();
-	var $ar_cache_orderby		= array();
-	var $ar_cache_set			= array();
+	protected $ar_caching			= FALSE;
+	protected $ar_cache_exists		= array();
+	protected $ar_cache_select		= array();
+	protected $ar_cache_from		= array();
+	protected $ar_cache_join		= array();
+	protected $ar_cache_where		= array();
+	protected $ar_cache_like		= array();
+	protected $ar_cache_groupby		= array();
+	protected $ar_cache_having		= array();
+	protected $ar_cache_orderby		= array();
+	protected $ar_cache_set			= array();
 	
-	var $ar_no_escape 			= array();
-	var $ar_cache_no_escape     = array();
+	protected $ar_no_escape 		= array();
+	protected $ar_cache_no_escape    = array();
 
 	// --------------------------------------------------------------------
 
@@ -660,7 +663,7 @@
 			$prefix = (count($this->ar_like) == 0) ? '' : $type;
 
 			$v = $this->escape_like_str($v);
-			
+
 			if ($side == 'none')
 			{
 				$like_statement = $prefix." $k $not LIKE '{$v}'";
@@ -931,7 +934,37 @@
 
 		return $this;
 	}
+	
+	// --------------------------------------------------------------------
 
+	/**
+	 * Get SELECT query string
+	 *
+	 * Compiles a SELECT query string and returns the sql.
+	 *
+	 * @access	public
+	 * @param	string	the table name to select from (optional)
+	 * @param	boolean	TRUE: resets AR values; FALSE: leave AR vaules alone
+	 * @return	string
+	 */
+	public function get_compiled_select($table = '', $reset = TRUE) 
+	{
+		if ($table != '')
+		{
+			$this->_track_aliases($table);
+			$this->from($table);
+		}
+		
+		$select =  $this->_compile_select();
+		
+		if ($reset === TRUE)
+		{
+			$this->_reset_select();
+		}
+		
+		return $select;
+	}
+	
 	// --------------------------------------------------------------------
 
 	/**
@@ -1148,6 +1181,41 @@
 
 		return $this;
 	}
+	
+	// --------------------------------------------------------------------
+
+	/**
+	 * Get INSERT query string
+	 *
+	 * Compiles an insert query and returns the sql
+	 *
+	 * @access	public
+	 * @param	string	the table to insert into
+	 * @param	boolean	TRUE: reset AR values; FALSE: leave AR values alone
+	 * @return	string
+	 */
+	public function get_compiled_insert($table = '', $reset = TRUE)
+	{	
+		if ($this->_validate_insert($table) === FALSE)
+		{
+			return FALSE;
+		}
+		
+		$sql = $this->_insert(
+			$this->_protect_identifiers(
+				$this->ar_from[0], TRUE, NULL, FALSE
+			),
+			array_keys($this->ar_set), 
+			array_values($this->ar_set)
+		);
+		
+		if ($reset === TRUE)
+		{
+			$this->_reset_write();
+		}
+		
+		return $sql;
+	}
 
 	// --------------------------------------------------------------------
 
@@ -1156,17 +1224,50 @@
 	 *
 	 * Compiles an insert string and runs the query
 	 *
+	 * @access	public
 	 * @param	string	the table to insert data into
 	 * @param	array	an associative array of insert values
 	 * @return	object
 	 */
-	function insert($table = '', $set = NULL)
+	public function insert($table = '', $set = NULL)
 	{
 		if ( ! is_null($set))
 		{
 			$this->set($set);
 		}
+		
+		if ($this->_validate_insert($table) === FALSE)
+		{
+			return FALSE;
+		}
+		
+		$sql = $this->_insert(
+			$this->_protect_identifiers(
+				$this->ar_from[0], TRUE, NULL, FALSE
+			), 
+			array_keys($this->ar_set), 
+			array_values($this->ar_set)
+		);
 
+		$this->_reset_write();
+		return $this->query($sql);
+	}
+	
+	// --------------------------------------------------------------------
+
+	/**
+	 * Validate Insert
+	 *
+	 * This method is used by both insert() and get_compiled_insert() to
+	 * validate that the there data is actually being set and that table
+	 * has been chosen to be inserted into.
+	 *
+	 * @access	public
+	 * @param	string	the table to insert data into
+	 * @return	string
+	 */
+	protected function _validate_insert($table = '') 
+	{
 		if (count($this->ar_set) == 0)
 		{
 			if ($this->db_debug)
@@ -1186,14 +1287,13 @@
 				}
 				return FALSE;
 			}
-
-			$table = $this->ar_from[0];
 		}
-
-		$sql = $this->_insert($this->_protect_identifiers($table, TRUE, NULL, FALSE), array_keys($this->ar_set), array_values($this->ar_set));
-
-		$this->_reset_write();
-		return $this->query($sql);
+		else
+		{
+			$this->ar_from[0] = $table;
+		}
+		
+		return TRUE;
 	}
 
 	// --------------------------------------------------------------------
@@ -1242,7 +1342,39 @@
 		$this->_reset_write();
 		return $this->query($sql);
 	}
+	
+	// --------------------------------------------------------------------
 
+	/**
+	 * Get UPDATE query string
+	 *
+	 * Compiles an update query and returns the sql
+	 *
+	 * @access	public
+	 * @param	string	the table to update
+	 * @param	boolean	TRUE: reset AR values; FALSE: leave AR values alone
+	 * @return	string
+	 */
+	public function get_compiled_update($table = '', $reset = TRUE)
+	{
+		// Combine any cached components with the current statements
+		$this->_merge_cache();
+	
+		if ($this->_validate_update($table) === FALSE)
+		{
+			return FALSE;
+		}
+		
+		$sql = $this->_update($this->_protect_identifiers($this->ar_from[0], TRUE, NULL, FALSE), $this->ar_set, $this->ar_where, $this->ar_orderby, $this->ar_limit);
+		
+		if ($reset === TRUE)
+		{
+			$this->_reset_write();
+		}
+		
+		return $sql;
+	}
+	
 	// --------------------------------------------------------------------
 
 	/**
@@ -1265,6 +1397,42 @@
 			$this->set($set);
 		}
 
+		if ($this->_validate_update($table) === FALSE)
+		{
+			return FALSE;
+		}
+
+		if ($where != NULL)
+		{
+			$this->where($where);
+		}
+
+		if ($limit != NULL)
+		{
+			$this->limit($limit);
+		}
+
+		$sql = $this->_update($this->_protect_identifiers($this->ar_from[0], TRUE, NULL, FALSE), $this->ar_set, $this->ar_where, $this->ar_orderby, $this->ar_limit);
+
+		$this->_reset_write();
+		return $this->query($sql);
+	}
+		
+	// --------------------------------------------------------------------
+
+	/**
+	 * Validate Update
+	 *
+	 * This method is used by both update() and get_compiled_update() to
+	 * validate that data is actually being set and that a table has been
+	 * chosen to be update.
+	 *
+	 * @access	public
+	 * @param	string	the table to update data on
+	 * @return	string
+	 */
+	protected function _validate_update($table = '')
+	{
 		if (count($this->ar_set) == 0)
 		{
 			if ($this->db_debug)
@@ -1284,27 +1452,13 @@
 				}
 				return FALSE;
 			}
-
-			$table = $this->ar_from[0];
 		}
-
-		if ($where != NULL)
+		else
 		{
-			$this->where($where);
+			$this->ar_from[0] = $table;
 		}
-
-		if ($limit != NULL)
-		{
-			$this->limit($limit);
-		}
-
-		$sql = $this->_update($this->_protect_identifiers($table, TRUE, NULL, FALSE), $this->ar_set, $this->ar_where, $this->ar_orderby, $this->ar_limit);
-
-		$this->_reset_write();
-		return $this->query($sql);
 	}
-
-
+	
 	// --------------------------------------------------------------------
 
 	/**
@@ -1503,7 +1657,27 @@
 
 		return $this->query($sql);
 	}
+	
+	// --------------------------------------------------------------------
 
+	/**
+	 * Get DELETE query string
+	 *
+	 * Compiles a delete query string and returns the sql
+	 *
+	 * @access	public
+	 * @param	string	the table to delete from
+	 * @param	boolean	TRUE: reset AR values; FALSE: leave AR values alone
+	 * @return	string
+	 */
+	public function get_compiled_delete($table = '', $reset = TRUE)
+	{
+		$this->return_delete_sql = TRUE;
+		$sql = $this->delete($table, '', NULL, $reset);
+		$this->return_delete_sql = FALSE;
+		return $sql;
+	}
+	
 	// --------------------------------------------------------------------
 
 	/**
@@ -1576,10 +1750,15 @@
 		{
 			$this->_reset_write();
 		}
+		
+		if ($this->return_delete_sql === true)
+		{
+			return $sql;
+		}
 
 		return $this->query($sql);
 	}
-
+	
 	// --------------------------------------------------------------------
 
 	/**
@@ -1659,7 +1838,7 @@
 			}
 		}
 	}
-
+	
 	// --------------------------------------------------------------------
 
 	/**
@@ -1965,6 +2144,22 @@
 
 		$this->ar_no_escape = $this->ar_cache_no_escape;
 	}
+	
+	// --------------------------------------------------------------------
+
+	/**
+	 * Reset Active Record values.
+	 * 
+	 * Publicly-visible method to reset the AR values.
+	 *
+	 * @access	public
+	 * @return	void
+	 */
+	public function reset_query()
+	{
+		$this->_reset_select();
+		$this->_reset_write();
+	}
 
 	// --------------------------------------------------------------------
 
diff --git a/system/database/DB_cache.php b/system/database/DB_cache.php
index 3bf065c..ad1c28d 100644
--- a/system/database/DB_cache.php
+++ b/system/database/DB_cache.php
@@ -33,7 +33,7 @@
 	 * Grabs the CI super object instance so we can access it.
 	 *
 	 */
-	function CI_DB_Cache(&$db)
+	function __construct(&$db)
 	{
 		// Assign the main CI object to $this->CI
 		// and load the file helper since we use it a lot
diff --git a/system/database/DB_driver.php b/system/database/DB_driver.php
index 237a4fc..d7b63b9 100644
--- a/system/database/DB_driver.php
+++ b/system/database/DB_driver.php
@@ -78,7 +78,7 @@
 	 *
 	 * @param array
 	 */
-	function CI_DB_driver($params)
+	function __construct($params)
 	{
 		if (is_array($params))
 		{
diff --git a/system/database/DB_forge.php b/system/database/DB_forge.php
index 0dd29c2..6bc4041 100644
--- a/system/database/DB_forge.php
+++ b/system/database/DB_forge.php
@@ -35,7 +35,7 @@
 	 * Grabs the CI super object instance so we can access it.
 	 *
 	 */
-	function CI_DB_forge()
+	function __construct()
 	{
 		// Assign the main database object to $this->db
 		$CI =& get_instance();
diff --git a/system/database/DB_utility.php b/system/database/DB_utility.php
index a5f174f..52196b7 100644
--- a/system/database/DB_utility.php
+++ b/system/database/DB_utility.php
@@ -33,7 +33,7 @@
 	 * Grabs the CI super object instance so we can access it.
 	 *
 	 */
-	function CI_DB_utility()
+	function __construct()
 	{
 		// Assign the main database object to $this->db
 		$CI =& get_instance();
diff --git a/system/database/drivers/odbc/odbc_driver.php b/system/database/drivers/odbc/odbc_driver.php
index 08cd27b..bcd7937 100644
--- a/system/database/drivers/odbc/odbc_driver.php
+++ b/system/database/drivers/odbc/odbc_driver.php
@@ -48,9 +48,9 @@
 	var $_random_keyword;
 
 
-	function CI_DB_odbc_driver($params)
+	function __construct($params)
 	{
-		parent::CI_DB_driver($params);
+		parent::__construct($params);
 
 		$this->_random_keyword = ' RND('.time().')'; // database specific random keyword
 	}
diff --git a/system/helpers/captcha_helper.php b/system/helpers/captcha_helper.php
index 19ec0c7..2bbb9d3 100644
--- a/system/helpers/captcha_helper.php
+++ b/system/helpers/captcha_helper.php
@@ -243,4 +243,4 @@
 // ------------------------------------------------------------------------
 
 /* End of file captcha_helper.php */
-/* Location: ./system/heleprs/captcha_helper.php */
\ No newline at end of file
+/* Location: ./system/helpers/captcha_helper.php */
\ No newline at end of file
diff --git a/system/libraries/Cache/drivers/Cache_apc.php b/system/libraries/Cache/drivers/Cache_apc.php
index de75719..79d91b3 100644
--- a/system/libraries/Cache/drivers/Cache_apc.php
+++ b/system/libraries/Cache/drivers/Cache_apc.php
@@ -132,7 +132,7 @@
 	 */
 	public function is_supported()
 	{
-		if ( ! extension_loaded('apc') OR ! function_exists('apc_store'))
+		if ( ! extension_loaded('apc') OR ini_get('apc.enabled') != "1")
 		{
 			log_message('error', 'The APC PHP extension must be loaded to use APC Cache.');
 			return FALSE;
@@ -148,4 +148,4 @@
 // End Class
 
 /* End of file Cache_apc.php */
-/* Location: ./system/libraries/Cache/drivers/Cache_apc.php */
\ No newline at end of file
+/* Location: ./system/libraries/Cache/drivers/Cache_apc.php */
diff --git a/system/libraries/Session.php b/system/libraries/Session.php
index 8ee08c5..867314b 100644
--- a/system/libraries/Session.php
+++ b/system/libraries/Session.php
@@ -688,13 +688,7 @@
 	{
 		if (is_array($data))
 		{
-			foreach ($data as $key => $val)
-			{
-				if (is_string($val))
-				{
-					$data[$key] = str_replace('\\', '{{slash}}', $val);
-				}
-			}
+			array_walk_recursive($data, array(&$this, '_escape_slashes'));
 		}
 		else
 		{
@@ -703,9 +697,23 @@
 				$data = str_replace('\\', '{{slash}}', $data);
 			}
 		}
-
 		return serialize($data);
 	}
+	
+	/**
+	 * Escape slashes
+	 *
+	 * This function converts any slashes found into a temporary marker
+	 *
+	 * @access	private
+	 */
+	function _escape_slashes(&$val, $key)
+	{
+		if (is_string($val))
+		{
+			$val = str_replace('\\', '{{slash}}', $val);
+		}
+	}
 
 	// --------------------------------------------------------------------
 
@@ -725,19 +733,27 @@
 
 		if (is_array($data))
 		{
-			foreach ($data as $key => $val)
-			{
-				if (is_string($val))
-				{
-					$data[$key] = str_replace('{{slash}}', '\\', $val);
-				}
-			}
-
+			array_walk_recursive($data, array(&$this, '_unescape_slashes'));
 			return $data;
 		}
 
 		return (is_string($data)) ? str_replace('{{slash}}', '\\', $data) : $data;
 	}
+	
+	/**
+	 * Unescape slashes
+	 *
+	 * This function converts any slash markers back into actual slashes
+	 *
+	 * @access	private
+	 */
+	function _unescape_slashes(&$val, $key)
+	{
+		if (is_string($val))
+		{
+	 		$val= str_replace('{{slash}}', '\\', $val);
+		}
+	}
 
 	// --------------------------------------------------------------------
 
diff --git a/user_guide_src/source/_themes/eldocs/layout.html b/user_guide_src/source/_themes/eldocs/layout.html
index da59e53..a79720e 100644
--- a/user_guide_src/source/_themes/eldocs/layout.html
+++ b/user_guide_src/source/_themes/eldocs/layout.html
@@ -124,7 +124,15 @@
 	
 	{%- block footer %}			
 		<div id="footer">
-			<p class="top"><a href="#header" title="Return to top">Return to top</a></p>
+			<p class="top">
+				{% if prev %}
+				<span class="prev">Previous Topic: <a href="{{ prev.link }}">{{ prev.title }}</a></span>
+				{% endif %}
+				{% if next %}
+				<span class="next">Next Topic: <a href="{{ next.link }}">{{ next.title }}</a></span>
+				{% endif %}
+				<a href="#header" title="Return to top">Return to top</a>
+			</p>
 			<p><a href="{{ project_url }}">{{ project }}</a> &ndash; Copyright &copy; {{ copyright }}</a> &ndash; Last updated: {{ last_updated }}</p>
 		</div><!-- /#footer -->
 	{%- endblock %}
diff --git a/user_guide_src/source/_themes/eldocs/static/asset/css/common.css b/user_guide_src/source/_themes/eldocs/static/asset/css/common.css
index c216c36..28182a1 100644
--- a/user_guide_src/source/_themes/eldocs/static/asset/css/common.css
+++ b/user_guide_src/source/_themes/eldocs/static/asset/css/common.css
@@ -119,6 +119,8 @@
 fieldset{ border: 0; }
 
 .top{ float: right; }
+.next{ padding: 0 20px 0 10px; }
+.prev{ padding-right: 10px; }
 
 .highlight-ci,
 .highlight-ee,
diff --git a/user_guide_src/source/changelog.rst b/user_guide_src/source/changelog.rst
index 925785d..8249b63 100644
--- a/user_guide_src/source/changelog.rst
+++ b/user_guide_src/source/changelog.rst
@@ -9,6 +9,7 @@
 
 -  General Changes
 
+   -  Added an optional backtrace to php-error template.
    -  Added Android to the list of user agents.
    -  Added Windows 7 to the list of user platforms.
    -  Callback validation rules can now accept parameters like any other
@@ -30,22 +31,25 @@
    -  Altered form helper - made action on form_open_multipart helper
       function call optional. Fixes (#65)
    -  url_title() will now trim extra dashes from beginning and end.
-   -  Improved speed of <a href="helpers/string_helper.html">String Helper</a>'s <b>random_string()</b> method
-   -  Added XHTML Basic 1.1 doctype to <a href="helpers/html_helper.html">HTML Helper</a>.
+   -  Improved speed of :doc:`String Helper <helpers/string_helper>`'s random_string() method
+   -  Added XHTML Basic 1.1 doctype to :doc:`HTML Helper <helpers/html_helper>`.
 
 -  Database
 
-   -  Added a `CUBRID <http://www.cubrid.org/>`_ driver to the `Database
+   -  Added a `CUBRID <http://www.cubrid.org/>`_ driver to the :doc:`Database
       Driver <database/index>`. Thanks to the CUBRID team for
       supplying this patch.
-   -  Added a PDO driver to the <a href="database/index.html">Database Driver</a>.
+   -  Added a PDO driver to the :doc:`Database Driver <database/index>`.
    -  Typecast limit and offset in the :doc:`Database
       Driver <database/queries>` to integers to avoid possible
       injection.
    -  Added additional option 'none' for the optional third argument for
       $this->db->like() in the :doc:`Database
       Driver <database/active_record>`.
-   -  Added <kbd>$this->db->insert_batch()</kbd> support to the OCI8 (Oracle) driver.
+   -  Added $this->db->insert_batch() support to the OCI8 (Oracle) driver.
+   -  Added new :doc:`Active Record <database/active_record>` methods that return 
+      the SQL string of queries without executing them: get_compiled_select(), 
+      get_compiled_insert(), get_compiled_update(), get_compiled_delete().
 
 -  Libraries
 
@@ -55,13 +59,15 @@
    -  Added support to set an optional parameter in your callback rules
       of validation using the :doc:`Form Validation
       Library <libraries/form_validation>`.
+   -  Added a :doc:`Migration Library <libraries/migration>` to assist with applying
+      incremental updates to your database schema.
    -  Driver children can be located in any package path.
    -  Added max_filename_increment config setting for Upload library.
    -  CI_Loader::_ci_autoloader() is now a protected method.
    -  Added is_unique to the :doc:`Form Validation
       library <libraries/form_validation>`.
    -  Modified valid_ip() to use PHP's filter_var() when possible (>= PHP 5.2) in the <a href="libraries/form_validation.html">Form Validation</a> library.
-   -  Added <kbd>$config['use_page_numbers']</kbd> to the <a href="libraries/pagination.html">Pagination library</a>, which enables real page numbers in the URI.
+   -  Added $config['use_page_numbers'] to the :doc:`Pagination library <libraries/pagination>`, which enables real page numbers in the URI.
    -  Added TLS and SSL Encryption for SMTP.
 
 -  Core
@@ -108,6 +114,7 @@
 -  Fixed a bug (#484) - First time _csrf_set_hash() is called, hash is never set to the cookie (in Security.php).
 -  Fixed a bug (#60) - Added _file_mime_type() method to the `File Uploading Library <libraries/file_uploading>` in order to fix a possible MIME-type injection.
 -  Fixed a bug (#537) - Support for all wav type in browser.
+-  Fixed a bug (#576) - Using ini_get() function to detect if apc is enabled or not.
 
 Version 2.0.3
 =============
@@ -145,16 +152,8 @@
       Thanks to epallerols for the patch.
    -  Added "application/x-csv" to mimes.php.
    -  Added CSRF protection URI whitelisting.
-   -  Fixed a bug where `Email library <libraries/email>`
+   -  Fixed a bug where :doc:`Email library <libraries/email>`
       attachments with a "." in the name would using invalid MIME-types.
-   -  Added support for
-      pem,p10,p12,p7a,p7c,p7m,p7r,p7s,crt,crl,der,kdb,rsa,cer,sst,csr
-      Certs to mimes.php.
-   -  Added support pgp,gpg to mimes.php.
-   -  Added support 3gp, 3g2, mp4, wmv, f4v, vlc Video files to
-      mimes.php.
-   -  Added support m4a, aac, m4u, xspf, au, ac3, flac, ogg Audio files
-      to mimes.php.
 
 -  Helpers
 
@@ -319,6 +318,8 @@
 -  Fixed a bug (Reactor #69) where the SHA1 library was named
    incorrectly.
 
+.. _2.0.0-changelog:
+
 Version 2.0.0
 =============
 
diff --git a/user_guide_src/source/database/active_record.rst b/user_guide_src/source/database/active_record.rst
index e1fc00b..5555a30 100644
--- a/user_guide_src/source/database/active_record.rst
+++ b/user_guide_src/source/database/active_record.rst
@@ -54,6 +54,37 @@
 Please visit the :doc:`result functions <results>` page for a full
 discussion regarding result generation.
 
+$this->db->get_compiled_select()
+================================
+
+Compiles the selection query just like `$this->db->get()`_ but does not *run* 
+the query. This method simply returns the SQL query as a string.
+
+Example::
+
+	$sql = $this->db->get_compiled_select('mytable');
+	echo $sql;
+	
+	// Produces string: SELECT * FROM mytable
+	
+The second parameter enables you to set whether or not the active record query 
+will be reset (by default it will be&mdash;just like `$this->db->get()`)::
+
+	echo $this->db->limit(10,20)->get_compiled_select('mytable', FALSE);
+	// Produces string: SELECT * FROM mytable LIMIT 20, 10 
+	// (in MySQL. Other databases have slightly different syntax)
+	
+	echo $this->db->select('title, content, date')->get_compiled_select();
+
+	// Produces string: SELECT title, content, date FROM mytable
+	
+The key thing to notice in the above example is that the second query did not 
+utilize `$this->db->from()`_ and did not pass a table name into the first 
+parameter. The reason for this outcome is because the query has not been 
+executed using `$this->db->get()`_ which resets values or reset directly 
+using `$this-db->reset_query()`_.
+
+
 $this->db->get_where()
 ======================
 
@@ -540,6 +571,41 @@
 
 .. note:: All values are escaped automatically producing safer queries.
 
+$this->db->get_compiled_insert()
+================================
+Compiles the insertion query just like `$this->db->insert()`_ but does not 
+*run* the query. This method simply returns the SQL query as a string.
+
+Example::
+
+	$data = array(
+		'title' => 'My title',
+		'name'  => 'My Name',
+		'date'  => 'My date'
+	);
+	
+	$sql = $this->db->set($data)->get_compiled_insert('mytable');
+	echo $sql;
+	
+	// Produces string: INSERT INTO mytable (title, name, date) VALUES ('My title', 'My name', 'My date')
+
+The second parameter enables you to set whether or not the active record query 
+will be reset (by default it will be--just like `$this->db->insert()`_)::
+	
+	echo $this->db->set('title', 'My Title')->get_compiled_insert('mytable', FALSE);
+	
+	// Produces string: INSERT INTO mytable (title) VALUES ('My Title')
+	
+	echo $this->db->set('content', 'My Content')->get_compiled_insert();
+
+	// Produces string: INSERT INTO mytable (title, content) VALUES ('My Title', 'My Content')
+	
+The key thing to notice in the above example is that the second query did not 
+utlize `$this->db->from()`_ nor did it pass a table name into the first 
+parameter. The reason this worked is because the query has not been executed 
+using `$this->db->insert()`_ which resets values or reset directly using 
+`$this->db->reset_query()`_.
+
 $this->db->insert_batch()
 =========================
 
@@ -717,6 +783,14 @@
 
 .. note:: All values are escaped automatically producing safer queries.
 
+$this->db->get_compiled_update()
+================================
+
+This works exactly the same way as ``$this->db->get_compiled_insert()`` except
+that it produces an UPDATE SQL string instead of an INSERT SQL string.
+
+For more information view documentation for `$this->get_compiled_insert()`_.
+
 
 *************
 Deleting Data
@@ -784,6 +858,13 @@
 
 .. note:: If the TRUNCATE command isn't available, truncate() will
 	execute as "DELETE FROM table".
+	
+$this->db->get_compiled_delete()
+================================
+This works exactly the same way as ``$this->db->get_compiled_insert()`` except
+that it produces a DELETE SQL string instead of an INSERT SQL string.
+
+For more information view documentation for `$this->get_compiled_insert()`_.
 
 ***************
 Method Chaining
@@ -854,3 +935,31 @@
 	where, like, group_by, having, order_by, set
 
 
+
+*******************
+Reset Active Record
+*******************
+
+Resetting Active Record allows you to start fresh with your query without 
+executing it first using a method like $this->db->get() or $this->db->insert(). 
+Just like the methods that execute a query, this will *not* reset items you've 
+cached using `Active Record Caching`_.
+
+This is useful in situations where you are using Active Record to generate SQL 
+(ex. ``$this->db->get_compiled_select()``) but then choose to, for instance, 
+run the query::
+
+	// Note that the second parameter of the get_compiled_select method is FALSE
+	$sql = $this->db->select(array('field1','field2'))
+					->where('field3',5)
+					->get_compiled_select('mytable', FALSE);
+
+	// ...
+	// Do something crazy with the SQL code... like add it to a cron script for
+	// later execution or something...
+	// ...
+
+	$data = $this->db->get()->result_array();
+
+	// Would execute and return an array of results of the following query:
+	// SELECT field1, field1 from mytable where field3 = 5;
diff --git a/user_guide_src/source/database/index.rst b/user_guide_src/source/database/index.rst
index 3b59986..ab12b7c 100644
--- a/user_guide_src/source/database/index.rst
+++ b/user_guide_src/source/database/index.rst
@@ -6,24 +6,20 @@
 class that supports both traditional structures and Active Record
 patterns. The database functions offer clear, simple syntax.
 
--  :doc:`Quick Start: Usage Examples <examples>`
--  :doc:`Database Configuration <configuration>`
--  :doc:`Connecting to a Database <connecting>`
--  :doc:`Running Queries <queries>`
--  :doc:`Generating Query Results <results>`
--  :doc:`Query Helper Functions <helpers>`
--  :doc:`Active Record Class <active_record>`
--  :doc:`Transactions <transactions>`
--  :doc:`Table MetaData <table_data>`
--  :doc:`Field MetaData <fields>`
--  :doc:`Custom Function Calls <call_function>`
--  :doc:`Query Caching <caching>`
--  :doc:`Database manipulation with Database Forge <forge>`
--  :doc:`Database Utilities Class <utilities>`
-
 .. toctree::
-	:glob:
 	:titlesonly:
-	:hidden:
 	
-	*
\ No newline at end of file
+	Quick Start: Usage Examples <examples>
+	Database Configuration <configuration>
+	Connecting to a Database <connecting>
+	Running Queries <queries>
+	Generating Query Results <results>
+	Query Helper Functions <helpers>
+	Active Record Class <active_record>
+	Transactions <transactions>
+	Table MetaData <table_data>
+	Field MetaData <fields>
+	Custom Function Calls <call_function>
+	Query Caching <caching>
+	Database Manipulation with Database Forge <forge>
+	Database Utilities Class <utilities>
\ No newline at end of file
diff --git a/user_guide_src/source/general/index.rst b/user_guide_src/source/general/index.rst
index ae0d096..2162b81 100644
--- a/user_guide_src/source/general/index.rst
+++ b/user_guide_src/source/general/index.rst
@@ -1,39 +1,32 @@
-##################
-General
-##################
-
-
--  :doc:`CodeIgniter URLs <urls>`
--  :doc:`Controllers <controllers>`
--  :doc:`Reserved Names <reserved_names>`
--  :doc:`Views <views>`
--  :doc:`Models <models>`
--  :doc:`Helpers <helpers>`
--  :doc:`Using CodeIgniter Libraries <libraries>`
--  :doc:`Creating Your Own Libraries <creating_libraries>`
--  :doc:`Using CodeIgniter Drivers <drivers>`
--  :doc:`Creating Your Own Drivers <creating_drivers>`
--  :doc:`Creating Core Classes <core_classes>`
--  :doc:`Creating Ancillary Classes  <ancillary_classes>`
--  :doc:`Hooks - Extending the Core <hooks>`
--  :doc:`Auto-loading Resources <autoloader>`
--  :doc:`Common Function <common_functions>`
--  :doc:`URI Routing <routing>`
--  :doc:`Error Handling <errors>`
--  :doc:`Caching <caching>`
--  :doc:`Profiling Your Application <profiling>`
--  :doc:`Running via the CLI <cli>`
--  :doc:`Managing Applications <managing_apps>`
--  :doc:`Handling Multiple Environments <environments>`
--  :doc:`Alternative PHP Syntax <alternative_php>`
--  :doc:`Security <security>`
--  :doc:`PHP Style Guide <styleguide>`
--  :doc:`Server Requirements <requirements>`
--  :doc:`Credits <credits>`
+##############
+General Topics
+##############
 
 .. toctree::
-	:glob:
 	:titlesonly:
-	:hidden:
 	
-	*
\ No newline at end of file
+	urls
+	controllers
+	reserved_names
+	views
+	models
+	Helpers <helpers>
+	libraries
+	creating_libraries
+	drivers
+	creating_drivers
+	core_classes
+	ancillary_classes
+	hooks
+	autoloader
+	common_functions
+	routing
+	errors
+	Caching <caching>
+	profiling
+	cli
+	managing_apps
+	environments
+	alternative_php
+	security
+	PHP Style Guide <styleguide>
diff --git a/user_guide_src/source/general/styleguide.rst b/user_guide_src/source/general/styleguide.rst
index 0373fc7..b3dc088 100644
--- a/user_guide_src/source/general/styleguide.rst
+++ b/user_guide_src/source/general/styleguide.rst
@@ -1,6 +1,7 @@
-########################
-General Style and Syntax
-########################
+###############
+PHP Style Guide
+###############
+
 
 The following page describes the use of coding rules adhered to when
 developing CodeIgniter.
diff --git a/user_guide_src/source/helpers/date_helper.rst b/user_guide_src/source/helpers/date_helper.rst
index 378ff36..ad06dd6 100644
--- a/user_guide_src/source/helpers/date_helper.rst
+++ b/user_guide_src/source/helpers/date_helper.rst
@@ -162,7 +162,8 @@
 
 ::
 
-	$mysql = '20061124092345';  $unix = mysql_to_unix($mysql);
+	$mysql = '20061124092345';
+	$unix = mysql_to_unix($mysql);
 
 unix_to_human()
 ===============
diff --git a/user_guide_src/source/helpers/directory_helper.rst b/user_guide_src/source/helpers/directory_helper.rst
index 6c259ad..fd16988 100644
--- a/user_guide_src/source/helpers/directory_helper.rst
+++ b/user_guide_src/source/helpers/directory_helper.rst
@@ -18,15 +18,20 @@
 
 The following functions are available:
 
-directory_map('source directory')
-=================================
+directory_map()
+===============
 
 This function reads the directory path specified in the first parameter
 and builds an array representation of it and all its contained files.
+	
+.. php:method:: directory_map($source_dir[, $directory_depth = 0[, $hidden = FALSE]])
 
-Example
-
-::
+	:param string	$source_dir: path to the ource directory
+	:param integer	$directory_depth: depth of directories to traverse (0 =
+		fully recursive, 1 = current dir, etc)
+	:param boolean	$hidden: whether to include hidden directories
+	
+Examples::
 
 	$map = directory_map('./mydirectory/');
 
@@ -35,23 +40,17 @@
 
 Sub-folders contained within the directory will be mapped as well. If
 you wish to control the recursion depth, you can do so using the second
-parameter (integer). A depth of 1 will only map the top level directory
-
-::
+parameter (integer). A depth of 1 will only map the top level directory::
 
 	$map = directory_map('./mydirectory/', 1);
 
 By default, hidden files will not be included in the returned array. To
-override this behavior, you may set a third parameter to true (boolean)
-
-::
+override this behavior, you may set a third parameter to true (boolean)::
 
 	$map = directory_map('./mydirectory/', FALSE, TRUE);
 
 Each folder name will be an array index, while its contained files will
-be numerically indexed. Here is an example of a typical array
-
-::
+be numerically indexed. Here is an example of a typical array::
 
 	Array (    
 		[libraries] => Array    
diff --git a/user_guide_src/source/index.rst b/user_guide_src/source/index.rst
index e531825..6cdeb24 100644
--- a/user_guide_src/source/index.rst
+++ b/user_guide_src/source/index.rst
@@ -37,9 +37,13 @@
 	
 	*
 	overview/index
+	general/requirements
 	installation/index
 	general/index
 	libraries/index
-	database/index
 	helpers/index
-	documentation/index
\ No newline at end of file
+	database/index
+	documentation/index
+	tutorial/index
+	general/quick_reference
+	general/credits
\ No newline at end of file
diff --git a/user_guide_src/source/installation/upgrade_200.rst b/user_guide_src/source/installation/upgrade_200.rst
index 064e1b5..0bcbd5c 100644
--- a/user_guide_src/source/installation/upgrade_200.rst
+++ b/user_guide_src/source/installation/upgrade_200.rst
@@ -5,6 +5,10 @@
 Before performing an update you should take your site offline by
 replacing the index.php file with a static one.
 
+*******************
+Update Instructions
+*******************
+
 Step 1: Update your CodeIgniter files
 =====================================
 
@@ -88,3 +92,51 @@
 
 Please replace your local copy of the user guide with the new version,
 including the image files.
+
+
+************
+Update Notes
+************
+
+Please refer to the :ref:`2.0.0 Change Log <2.0.0-changelog>` for full
+details, but here are some of the larger changes that are more likely to
+impact your code:
+
+- CodeIgniter now requires PHP 5.1.6.
+- Scaffolding has been removed.
+- The CAPTCHA plugin in now a :doc:`helper </helpers/captcha_helper>`.
+- The JavaScript calendar plugin was removed.
+- The *system/cache* and *system/logs* directories are now in the application
+  directory.
+- The Validation class has been removed.  Please see the
+  :doc:`Form Validation library </libraries/form_validation>`
+- "default" is now a reserved name.
+- The xss_clean() function has moved to the :doc:`Security Class
+  </libraries/security>`.
+- do_xss_clean() now returns FALSE if the uploaded file fails XSS checks.
+- The :doc:`Session Class </libraries/sessions>` requires now the use of an
+  encryption key set in the config file.
+- The following deprecated Active Record functions have been removed:
+  ``orwhere``, ``orlike``, ``groupby``, ``orhaving``, ``orderby``,
+  ``getwhere``.
+- ``_drop_database()`` and ``_create_database()`` functions have been removed
+  from the db utility drivers.
+- The ``dohash()`` function of the :doc:`Security helper
+  </helpers/security_helper>`
+  has been renamed to ``do_hash()`` for naming consistency.
+
+The config folder
+=================
+
+The following files have been changed:
+
+- config.php
+- database.php
+- mimes.php
+- routes.php
+- user_agents.php
+
+The following files have been added:
+
+- foreign_chars.php
+- profiler.php
diff --git a/user_guide_src/source/overview/index.rst b/user_guide_src/source/overview/index.rst
index d541e79..dc91f78 100644
--- a/user_guide_src/source/overview/index.rst
+++ b/user_guide_src/source/overview/index.rst
@@ -4,15 +4,13 @@
 
 The following pages describe the broad concepts behind CodeIgniter:
 
--  :doc:`CodeIgniter at a Glance <at_a_glance>`
--  :doc:`Supported Features <features>`
--  :doc:`Application Flow Chart <appflow>`
--  :doc:`Introduction to the Model-View-Controller <mvc>`
--  :doc:`Design and Architectural Goals <goals>`
-
 .. toctree::
-	:glob:
-	:hidden:
 	:titlesonly:
 	
-	*
\ No newline at end of file
+	Getting Started <getting_started>
+	CodeIgniter at a Glance <at_a_glance>
+	CodeIgniter Cheatsheets <cheatsheets>
+	Supported Features <features>
+	Application Flow Chart <appflow>
+	Model-View-Controller <mvc>
+	Architectural Goals <goals>
\ No newline at end of file
diff --git a/user_guide_src/source/tutorial/conclusion.rst b/user_guide_src/source/tutorial/conclusion.rst
new file mode 100644
index 0000000..48fbdcc
--- /dev/null
+++ b/user_guide_src/source/tutorial/conclusion.rst
@@ -0,0 +1,26 @@
+##########
+Conclusion
+##########
+
+This tutorial did not cover all of the things you might expect of a
+full-fledged content management system, but it introduced you to the
+more important topics of routing, writing controllers, and models. We
+hope this tutorial gave you an insight into some of CodeIgniter's basic
+design patterns, which you can expand upon.
+
+Now that you've completed this tutorial, we recommend you check out the
+rest of the documentation. CodeIgniter is often praised because of its
+comprehensive documentation. Use this to your advantage and read the
+"Introduction" and "General Topics" sections thoroughly. You should read
+the class and helper references when needed.
+
+Every intermediate PHP programmer should be able to get the hang of
+CodeIgniter within a few days.
+
+If you still have questions about the framework or your own CodeIgniter
+code, you can:
+
+-  Check out our `forums <http://codeigniter.com/forums>`_
+-  Visit our `IRC chatroom <http://codeigniter.com/wiki/IRC>`_
+-  Explore the `Wiki <http://codeigniter.com/wiki/>`_
+
diff --git a/user_guide_src/source/tutorial/create_news_items.rst b/user_guide_src/source/tutorial/create_news_items.rst
new file mode 100644
index 0000000..003b94b
--- /dev/null
+++ b/user_guide_src/source/tutorial/create_news_items.rst
@@ -0,0 +1,153 @@
+#################
+Create news items
+#################
+
+You now know how you can read data from a database using CodeIgnite, but
+you haven't written any information to the database yet. In this section
+you'll expand your news controller and model created earlier to include
+this functionality.
+
+Create a form
+-------------
+
+To input data into the database you need to create a form where you can
+input the information to be stored. This means you'll be needing a form
+with two fields, one for the title and one for the text. You'll derive
+the slug from our title in the model. Create the new view at
+application/views/news/create.php.
+
+::
+
+    <h2>Create a news item</h2>
+
+    <?php echo validation_errors(); ?>
+
+    <?php echo form_open('news/create') ?>
+
+        <label for="title">Title</label> 
+        <input type="input" name="title" /><br />
+
+        <label for="text">Text</label>
+        <textarea name="text"></textarea><br />
+
+        <input type="submit" name="submit" value="Create news item" /> 
+
+    </form>
+
+There are only two things here that probably look unfamiliar to you: the
+form_open() function and the validation_errors() function.
+
+The first function is provided by the `form
+helper <../helpers/form_helper.html>`_ and renders the form element and
+adds extra functionality, like adding a hidden `CSFR prevention
+field <../libraries/security.html>`_. The latter is used to report
+errors related to form validation.
+
+Go back to your news controller. You're going to do two things here,
+check whether the form was submitted and whether the submitted data
+passed the validation rules. You'll use the `form
+validation <../libraries/form_validation.html>`_ library to do this.
+
+::
+
+    public function create()
+    {
+        $this->load->helper('form');
+        $this->load->library('form_validation');
+        
+        $data['title'] = 'Create a news item';
+        
+        $this->form_validation->set_rules('title', 'Title', 'required');
+        $this->form_validation->set_rules('text', 'text', 'required');
+        
+        if ($this->form_validation->run() === FALSE)
+        {
+            $this->load->view('templates/header', $data);   
+            $this->load->view('news/create');
+            $this->load->view('templates/footer');
+            
+        }
+        else
+        {
+            $this->news_model->set_news();
+            $this->load->view('news/success');
+        }
+    }
+
+The code above adds a lot of functionality. The first few lines load the
+form helper and the form validation library. After that, rules for the
+form validation are set. The set\_rules() method takes three arguments;
+the name of the input field, the name to be used in error messages, and
+the rule. In this case the title and text fields are required.
+
+CodeIgniter has a powerful form validation library as demonstrated
+above. You can read `more about this library
+here <../libraries/form_validation.html>`_.
+
+Continuing down, you can see a condition that checks whether the form
+validation ran successfully. If it did not, the form is displayed, if it
+was submitted **and** passed all the rules, the model is called. After
+this, a view is loaded to display a success message. Create a view at
+application/view/news/success.php and write a success message.
+
+Model
+-----
+
+The only thing that remains is writing a method that writes the data to
+the database. You'll use the Active Record class to insert the
+information and use the input library to get the posted data. Open up
+the model created earlier and add the following:
+
+::
+
+    public function set_news()
+    {
+        $this->load->helper('url');
+        
+        $slug = url_title($this->input->post('title'), 'dash', TRUE);
+        
+        $data = array(
+            'title' => $this->input->post('title'),
+            'slug' => $slug,
+            'text' => $this->input->post('text')
+        );
+        
+        return $this->db->insert('news', $data);
+    }
+
+This new method takes care of inserting the news item into the database.
+The third line contains a new function, url\_title(). This function -
+provided by the `URL helper <../helpers/url_helper.html>`_ - strips down
+the string you pass it, replacing all spaces by dashes (-) and makes
+sure everything is in lowercase characters. This leaves you with a nice
+slug, perfect for creating URIs.
+
+Let's continue with preparing the record that is going to be inserted
+later, inside the $data array. Each element corresponds with a column in
+the database table created earlier. You might notice a new method here,
+namely the post() method from the `input
+library <../libraries/input.html>`_. This method makes sure the data is
+sanitized, protecting you from nasty attacks from others. The input
+library is loaded by default. At last, you insert our $data array into
+our database.
+
+Routing
+-------
+
+Before you can start adding news items into your CodeIgniter application
+you have to add an extra rule to config/routes.php file. Make sure your
+file contains the following. This makes sure CodeIgniter sees 'create'
+as a method instead of a news item's slug.
+
+::
+
+    $route['news/create'] = 'news/create';
+    $route['news/(:any)'] = 'news/view/$1';
+    $route['news'] = 'news';
+    $route['(:any)'] = 'pages/view/$1';
+    $route['default_controller'] = 'pages/view';
+
+Now point your browser to your local development environment where you
+installed CodeIgniter and add index.php/news/create to the URL.
+Congratulations, you just created your first CodeIgniter application!
+Add some news and check out the different pages you made.
diff --git a/user_guide_src/source/tutorial/index.rst b/user_guide_src/source/tutorial/index.rst
new file mode 100644
index 0000000..c959d04
--- /dev/null
+++ b/user_guide_src/source/tutorial/index.rst
@@ -0,0 +1,46 @@
+########
+Tutorial
+########
+
+This tutorial is intended to introduce you to the CodeIgniter framework
+and the basic principles of MVC architecture. It will show you how a
+basic CodeIgniter application is constructed in step-by-step fashion.
+
+In this tutorial, you will be creating a **basic news application**. You
+will begin by writing the code that can load static pages. Next, you
+will create a news section that reads news items from a database.
+Finally, you'll add a form to create news items in the database.
+
+This tutorial will primarily focus on:
+
+-  Model-View-Controller basics
+-  Routing basics
+-  Form validation
+-  Performing basic database queries using "Active Record"
+
+The entire tutorial is split up over several pages, each explaining a
+small part of the functionality of the CodeIgniter framework. You'll go
+through the following pages:
+
+-  Introduction, this page, which gives you an overview of what to
+   expect.
+-  `Static pages <static_pages.html>`_, which will teach you the basics
+   of controllers, views and routing.
+-  `News section <news_section.html>`_, where you'll start using models
+   and will be doing some basic database operations.
+-  `Create news items <create_news_items.html>`_, which will introduce
+   more advanced database operations and form validation.
+-  `Conclusion <conclusion.html>`_, which will give you some pointers on
+   further reading and other resources.
+
+Enjoy your exploration of the CodeIgniter framework.
+
+.. toctree::
+	:glob:
+	:hidden:
+	:titlesonly:
+	
+	static_pages
+	news_section
+	create_news_items
+	conclusion
\ No newline at end of file
diff --git a/user_guide_src/source/tutorial/news_section.rst b/user_guide_src/source/tutorial/news_section.rst
new file mode 100644
index 0000000..fe8e416
--- /dev/null
+++ b/user_guide_src/source/tutorial/news_section.rst
@@ -0,0 +1,214 @@
+############
+News section
+############
+
+In the last section, we went over some basic concepts of the framework
+by writing a class that includes static pages. We cleaned up the URI by
+adding custom routing rules. Now it's time to introduce dynamic content
+and start using a database.
+
+Setting up your model
+---------------------
+
+Instead of writing database operations right in the controller, queries
+should be placed in a model, so they can easily be reused later. Models
+are the place where you retrieve, insert, and update information in your
+database or other data stores. They represent your data.
+
+Open up the application/models directory and create a new file called
+news_model.php and add the following code. Make sure you've configured
+your database properly as described
+`here <../database/configuration.html>`_.
+
+::
+
+    <?php
+    class News_model extends CI_Model {
+
+        public function __construct()
+        {
+            $this->load->database();
+        }
+    }
+
+This code looks similar to the controller code that was used earlier. It
+creates a new model by extending CI\_Model and loads the database
+library. This will make the database class available through the
+$this->db object.
+
+Before querying the database, a database schema has to be created.
+Connect to your database and run the SQL command below. Also add some
+seed records.
+
+::
+
+    CREATE TABLE news (
+        id int(11) NOT NULL AUTO_INCREMENT,
+        title varchar(128) NOT NULL,
+        slug varchar(128) NOT NULL,
+        text text NOT NULL,
+        PRIMARY KEY (id),
+        KEY slug (slug)
+    );
+
+Now that the database and a model have been set up, you'll need a method
+to get all of our posts from our database. To do this, the database
+abstraction layer that is included with CodeIgniter — `Active
+Record <../database/active_record.html>`_ — is used. This makes it
+possible to write your 'queries' once and make them work on `all
+supported database systems <../general/requirements.html>`_. Add the
+following code to your model.
+
+::
+
+    public function get_news($slug = FALSE)
+    {
+        if ($slug === FALSE)
+        {
+            $query = $this->db->get('news');
+            return $query->result_array();
+        }
+        
+        $query = $this->db->get_where('news', array('slug' => $slug));
+        return $query->row_array();
+    }
+
+With this code you can perform two different queries. You can get all
+news records, or get a news item by its `slug <#>`_. You might have
+noticed that the $slug variable wasn't sanitized before running the
+query; Active Record does this for you.
+
+Display the news
+----------------
+
+Now that the queries are written, the model should be tied to the views
+that are going to display the news items to the user. This could be done
+in our pages controller created earlier, but for the sake of clarity, a
+new "news" controller is defined. Create the new controller at
+application/controllers/news.php.
+
+::
+
+    <?php
+    class News extends CI_Controller {
+
+        public function __construct()
+        {
+            parent::__construct();
+            $this->load->model('news_model');
+        }
+
+        public function index()
+        {
+            $data['news'] = $this->news_model->get_news();
+        }
+
+        public function view($slug)
+        {
+            $data['news'] = $this->news_model->get_news($slug);
+        }
+    }
+
+Looking at the code, you may see some similarity with the files we
+created earlier. First, the "\_\_construct" method: it calls the
+constructor of its parent class (CI\_Controller) and loads the model, so
+it can be used in all other methods in this controller.
+
+Next, there are two methods to view all news items and one for a
+specific news item. You can see that the $slug variable is passed to the
+model's method in the second method. The model is using this slug to
+identify the news item to be returned.
+
+Now the data is retrieved by the controller through our model, but
+nothing is displayed yet. The next thing to do is passing this data to
+the views.
+
+::
+
+    public function index()
+    {
+        $data['news'] = $this->news_model->get_news();
+        $data['title'] = 'News archive';
+
+        $this->load->view('templates/header', $data);
+        $this->load->view('news/index', $data);
+        $this->load->view('templates/footer');
+    }
+
+The code above gets all news records from the model and assigns it to a
+variable. The value for the title is also assigned to the $data['title']
+element and all data is passed to the views. You now need to create a
+view to render the news items. Create application/views/news/index.php
+and add the next piece of code.
+
+::
+
+    <?php foreach ($news as $news_item): ?>
+
+        <h2><?php echo $news_item['title'] ?></h2>
+        <div id="main">
+            <?php echo $news_item['text'] ?>
+        </div>
+        <p><a href="news/<?php echo $news_item['slug'] ?>">View article</a></p>
+
+    <?php endforeach ?>
+
+Here, each news item is looped and displayed to the user. You can see we
+wrote our template in PHP mixed with HTML. If you prefer to use a
+template language, you can use CodeIgniter's `Template
+Parser <../libraries/parser.html>`_ class or a third party parser.
+
+The news overview page is now done, but a page to display individual
+news items is still absent. The model created earlier is made in such
+way that it can easily be used for this functionality. You only need to
+add some code to the controller and create a new view. Go back to the
+news controller and add the following lines to the file.
+
+::
+
+    public function view($slug)
+    {
+        $data['news_item'] = $this->news_model->get_news($slug);
+
+        if (empty($data['news_item']))
+        {
+            show_404();
+        }
+
+        $data['title'] = $data['news_item']['title'];
+
+        $this->load->view('templates/header', $data);
+        $this->load->view('news/view', $data);
+        $this->load->view('templates/footer');
+    }
+
+Instead of calling the get\_news() method without a parameter, the $slug
+variable is passed, so it will return the specific news item. The only
+things left to do is create the corresponding view at
+application/views/news/view.php. Put the following code in this file.
+
+::
+
+    <?php
+    echo '<h2>'.$news_item['title'].'</h2>';
+    echo $news_item['text'];
+
+Routing
+-------
+
+Because of the wildcard routing rule created earlier, you need need an
+extra route to view the controller that you just made. Modify your
+routing file (application/config/routes.php) so it looks as follows.
+This makes sure the requests reaches the news controller instead of
+going directly to the pages controller. The first line routes URI's with
+a slug to the view method in the news controller.
+
+::
+
+    $route['news/(:any)'] = 'news/view/$1';
+    $route['news'] = 'news';
+    $route['(:any)'] = 'pages/view/$1';
+    $route['default_controller'] = 'pages/view';
+
+Point your browser to your document root, followed by index.php/news and
+watch your news page.
diff --git a/user_guide_src/source/tutorial/static_pages.rst b/user_guide_src/source/tutorial/static_pages.rst
new file mode 100644
index 0000000..0bbf51b
--- /dev/null
+++ b/user_guide_src/source/tutorial/static_pages.rst
@@ -0,0 +1,170 @@
+############
+Static pages
+############
+
+**Note:** This tutorial assumes you've downloaded CodeIgniter and
+`installed the framework <../installation/index.html>`_ in your
+development environment.
+
+The first thing you're going to do is set up a **controller** to handle
+static pages. A controller is simply a class that helps delegate work.
+It is the glue of your web application.
+
+For example, when a call is made to:
+``http://example.com/news/latest/10`` We might imagine that there is a
+controller named "news". The method being called on news would be
+"latest". The news method's job could be to grab 10 news items, and
+render them on the page. Very often in MVC, you'll see URL patterns that
+match:
+``http://example.com/[controller-class]/[controller-method]/[arguments]``
+As URL schemes become more complex, this may change. But for now, this
+is all we will need to know.
+
+Create a file at application/controllers/pages.php with the following
+code.
+
+::
+
+    <?php 
+    class Pages extends CI_Controller { 
+
+        public function view($page == 'home') 
+        {
+	
+        }
+		 
+    }
+
+You have created a class named "pages", with a view method that accepts
+one argument named $page. The pages class is extending the
+CI_Controller class. This means that the new pages class can access the
+methods and variables defined in the CI_Controller class
+(system/core/Controller.php).
+
+The **controller is what will become the center of every request** to
+your web application. In very technical CodeIgniter discussions, it may
+be referred to as the *super object*. Like any php class, you refer to
+it within your controllers as $this. Referring to $this is how you will
+load libraries, views, and generally command the framework.
+
+Now you've created your first method, it's time to make some basic page
+templates. We will be creating two "views" (page templates) that act as
+our page footer and header.
+
+Create the header at application/views/templates/header.php and add the
+following code.
+
+::
+
+    <html>
+        <head>
+            <title>CodeIgniter 2 Tutorial</title>
+        </head>
+        <body>
+
+            <h1>CodeIgniter 2 Tutorial<h1>
+
+The header contains the basic HTML code that you'll want to display
+before loading the main view, together with a heading. It will also
+output the $title variable, which we'll define later in the controller.
+Now create a footer at application/views/templates/footer.php that
+includes the following code:
+
+::
+
+            <em>&copy; 2011</em>
+        </body>
+    <html>
+
+Adding logic to the controller
+------------------------------
+
+Earlier you set up a controller with a view() method. The method accepts
+one parameter, which is the name of the page to be loaded. The static
+page templates will be located in the application/views/pages/
+directory.
+
+In that directory, create two files named home.php and about.php. Within
+those files, type some text − anything you'd like − and save them. If
+you like to be particularly un-original, try "Hello World!".
+
+In order to load those pages, you'll have to check whether the requested
+page actually exists:
+
+::
+
+    <?php 
+    public function view($page = 'home')
+    {
+                
+        if ( ! file_exists('application/views/pages/'.$page.'.php'))
+        {
+            // Whoops, we don't have a page for that!
+            show_404();
+        }
+        
+        $data['title'] = ucfirst($page); // Capitalize the first letter
+        
+        $this->load->view('templates/header', $data);
+        $this->load->view('pages/'.$page, $data);
+        $this->load->view('templates/footer', $data);
+
+    }
+
+Now, when the page does exist, it is loaded, including the header and
+footer, and displayed to the user. If the page doesn't exist, a "404
+Page not found" error is shown.
+
+The first line in this method checks whether the page actually exists.
+PHP's native file\_exists() function is used to check whether the file
+is where it's expected to be. show\_404() is a built-in CodeIgniter
+function that renders the default error page.
+
+In the header template, the $title variable was used to customize the
+page title. The value of title is defined in this method, but instead of
+assigning the value to a variable, it is assigned to the title element
+in the $data array.
+
+The last thing that has to be done is loading the views in the order
+they should be displayed. The second parameter in the view() method is
+used to pass values to the view. Each value in the $data array is
+assigned to a variable with the name of its key. So the value of
+$data['title'] in the controller is equivalent to $title in the view.
+
+Routing
+-------
+
+The controller is now functioning! Point your browser to
+[your-site-url]index.php/pages/view to see your page. When you visit
+index.php/pages/view/about you'll see the about page, again including
+the header and footer.
+
+Using custom routing rules, you have the power to map any URI to any
+controller and method, and break free from the normal convention:
+``http://example.com/[controller-class]/[controller-method]/[arguments]``
+
+Let's do that. Open the routing file located at
+application/config/routes.php and add the following two lines. Remove
+all other code that sets any element in the $route array.
+
+::
+
+    $route['default_controller'] = 'pages/view';
+    $route['(:any)'] = 'pages/view/$1';
+
+CodeIgniter reads its routing rules from top to bottom and routes the
+request to the first matching rule. Each rule is a regular expression
+(left-side) mapped to a controller and method name separated by slashes
+(right-side). When a request comes in, CodeIgniter looks for the first
+match, and calls the appropriate controller and method, possibly with
+arguments.
+
+More information about routing can be found in the URI Routing
+`documentation <../general/routing.html>`_.
+
+Here, the second rule in the $routes array matches **any** request using
+the wildcard string (:any). and passes the parameter to the view()
+method of the pages class.
+
+Now visit index.php/about. Did it get routed correctly to the view()
+method in the pages controller? Awesome!