Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

Merging in 3.0.x branch

  • Loading branch information...
commit 928c6ff96556c1d550f89d528afc3b8cc7f7a6a8 1 parent c5471e3
@isaiahdw isaiahdw authored
Showing with 3,724 additions and 78 deletions.
  1. +6 −2 classes/kohana/config.php
  2. +6 −2 classes/kohana/config/file.php
  3. +3 −1 classes/kohana/config/reader.php
  4. +2 −2 classes/kohana/controller.php
  5. +6 −0 classes/kohana/controller/rest.php
  6. +1 −1  classes/kohana/controller/template.php
  7. +86 −47 classes/kohana/core.php
  8. +4 −2 classes/kohana/encrypt.php
  9. +3 −1 classes/kohana/fragment.php
  10. +6 −0 classes/kohana/html.php
  11. +3 −1 classes/kohana/i18n.php
  12. +10 −2 classes/kohana/inflector.php
  13. +9 −5 classes/kohana/log.php
  14. +3 −1 classes/kohana/log/file.php
  15. +3 −1 classes/kohana/log/syslog.php
  16. +3 −1 classes/kohana/profiler.php
  17. +18 −6 classes/kohana/session.php
  18. +13 −0 classes/kohana/session/cookie.php
  19. +16 −0 classes/kohana/session/native.php
  20. +2 −2 classes/kohana/utf8.php
  21. +23 −0 config/userguide.php
  22. +69 −0 guide/kohana/autoloading.md
  23. +164 −0 guide/kohana/bootstrap.md
  24. +1 −0  guide/kohana/controllers.md
  25. +306 −0 guide/kohana/conventions.md
  26. +89 −0 guide/kohana/cookies.md
  27. +20 −0 guide/kohana/debugging.md
  28. +85 −0 guide/kohana/errors.md
  29. +101 −0 guide/kohana/extension.md
  30. +83 −0 guide/kohana/files.md
  31. +41 −0 guide/kohana/files/classes.md
  32. +95 −0 guide/kohana/files/config.md
  33. +1 −0  guide/kohana/files/i18n.md
  34. +5 −0 guide/kohana/files/messages.md
  35. +26 −0 guide/kohana/flow.md
  36. +135 −0 guide/kohana/fragments.md
  37. +53 −0 guide/kohana/helpers.md
  38. +19 −0 guide/kohana/index.md
  39. +33 −0 guide/kohana/install.md
  40. +48 −0 guide/kohana/menu.md
  41. +1 −0  guide/kohana/models.md
  42. +38 −0 guide/kohana/modules.md
  43. +3 −0  guide/kohana/mvc.md
  44. +189 −0 guide/kohana/mvc/controllers.md
  45. +1 −0  guide/kohana/mvc/models.md
  46. +161 −0 guide/kohana/mvc/views.md
  47. +54 −0 guide/kohana/profiling.md
  48. +15 −0 guide/kohana/requests.md
  49. +240 −0 guide/kohana/routing.md
  50. +1 −0  guide/kohana/security.md
  51. +3 −0  guide/kohana/security/cookies.md
  52. +5 −0 guide/kohana/security/database.md
  53. +81 −0 guide/kohana/security/deploying.md
  54. +1 −0  guide/kohana/security/encryption.md
  55. +247 −0 guide/kohana/security/validation.md
  56. +17 −0 guide/kohana/security/xss.md
  57. +167 −0 guide/kohana/sessions.md
  58. +33 −0 guide/kohana/tips.md
  59. +17 −0 guide/kohana/tutorials.md
  60. +80 −0 guide/kohana/tutorials/clean-urls.md
  61. +168 −0 guide/kohana/tutorials/error-pages.md
  62. +129 −0 guide/kohana/tutorials/git.md
  63. +106 −0 guide/kohana/tutorials/hello-world.md
  64. +3 −0  guide/kohana/tutorials/routes-and-links.md
  65. +54 −0 guide/kohana/tutorials/sharing-kohana.md
  66. +1 −0  guide/kohana/tutorials/simple-mvc.md
  67. +7 −0 guide/kohana/tutorials/templates.md
  68. +5 −0 guide/kohana/tutorials/translation.md
  69. +292 −0 guide/kohana/upgrading.md
  70. BIN  media/guide/kohana/cascading_filesystem.png
  71. BIN  media/guide/kohana/hello_world_1.png
  72. BIN  media/guide/kohana/hello_world_2.png
  73. BIN  media/guide/kohana/hello_world_2_error.png
  74. BIN  media/guide/kohana/install.png
  75. BIN  media/guide/kohana/welcome.png
  76. +5 −1 tests/kohana/HTMLTest.php
View
8 classes/kohana/config.php
@@ -11,7 +11,9 @@
*/
class Kohana_Config {
- // Singleton static instance
+ /**
+ * @var Kohana_Config Singleton static instance
+ */
protected static $_instance;
/**
@@ -32,7 +34,9 @@ public static function instance()
return Config::$_instance;
}
- // Configuration readers
+ /**
+ * @var array Configuration readers
+ */
protected $_readers = array();
/**
View
8 classes/kohana/config/file.php
@@ -11,10 +11,14 @@
*/
class Kohana_Config_File extends Config_Reader {
- // Configuration group name
+ /**
+ * @var string Configuration group name
+ */
protected $_configuration_group;
- // Has the config group changed?
+ /**
+ * @var bool Has the config group changed?
+ */
protected $_configuration_modified = FALSE;
public function __construct($directory = 'config')
View
4 classes/kohana/config/reader.php
@@ -11,7 +11,9 @@
*/
abstract class Kohana_Config_Reader extends ArrayObject {
- // Configuration group name
+ /**
+ * @var string Configuration group name
+ */
protected $_configuration_group;
/**
View
4 classes/kohana/controller.php
@@ -23,7 +23,7 @@
abstract class Kohana_Controller {
/**
- * @var object Request that created the controller
+ * @var Request Request that created the controller
*/
public $request;
@@ -36,7 +36,7 @@
* Creates a new controller instance. Each controller must be constructed
* with the request object that created it.
*
- * @param object Request that created the controller
+ * @param Request Request that created the controller
* @return void
*/
public function __construct(Kohana_Request $request, Kohana_Response $response)
View
6 classes/kohana/controller/rest.php
@@ -30,6 +30,9 @@
*/
abstract class Kohana_Controller_REST extends Controller {
+ /**
+ * @var array REST types
+ */
protected $_action_map = array
(
Http_Request::GET => 'index',
@@ -38,6 +41,9 @@
Http_Request::DELETE => 'delete',
);
+ /**
+ * @var string requested action
+ */
protected $_action_requested = '';
/**
View
2  classes/kohana/controller/template.php
@@ -11,7 +11,7 @@
abstract class Kohana_Controller_Template extends Controller {
/**
- * @var string page template
+ * @var View page template
*/
public $template = 'template';
View
133 classes/kohana/core.php
@@ -32,32 +32,32 @@ class Kohana_Core {
const FILE_CACHE = ":header \n\n// :name\n\n:data\n";
/**
- * @var string current environment name
+ * @var string Current environment name
*/
public static $environment = Kohana::DEVELOPMENT;
/**
- * @var boolean command line environment?
+ * @var boolean True if Kohana is running from the command line
*/
public static $is_cli = FALSE;
/**
- * @var boolean Windows environment?
+ * @var boolean True if Kohana is running on windows
*/
public static $is_windows = FALSE;
/**
- * @var boolean magic quotes enabled?
+ * @var boolean True if [magic quotes](http://php.net/manual/en/security.magicquotes.php) is enabled.
*/
public static $magic_quotes = FALSE;
/**
- * @var boolean log errors and exceptions?
+ * @var boolean Should errors and exceptions be logged
*/
public static $log_errors = FALSE;
/**
- * @var boolean safe mode enabled?
+ * @var boolean TRUE if PHP safe mode is on
*/
public static $safe_mode = FALSE;
@@ -87,37 +87,37 @@ class Kohana_Core {
public static $base_url = '/';
/**
- * @var string application index file
+ * @var string Application index file, added to links generated by Kohana. Set by [Kohana::init]
*/
public static $index_file = 'index.php';
/**
- * @var string cache directory
+ * @var string Cache directory, used by [Kohana::cache]. Set by [Kohana::init]
*/
public static $cache_dir;
/**
- * @var integer default lifetime for caching, in seconds
+ * @var integer Default lifetime for caching, in seconds, used by [Kohana::cache]. Set by [Kohana::init]
*/
public static $cache_life = 60;
/**
- * @var boolean enabling internal caching?
+ * @var boolean Whether to use internal caching for [Kohana::find_file], does not apply to [Kohana::cache]. Set by [Kohana::init]
*/
public static $caching = FALSE;
/**
- * @var boolean enable core profiling?
+ * @var boolean Whether to enable [profiling](kohana/profiling). Set by [Kohana::init]
*/
public static $profiling = TRUE;
/**
- * @var boolean enable error handling?
+ * @var boolean Enable Kohana catching and displaying PHP errors and exceptions. Set by [Kohana::init]
*/
public static $errors = TRUE;
/**
- * @var array types of errors to display at shutdown
+ * @var array Types of errors to display at shutdown
*/
public static $shutdown_errors = array(E_PARSE, E_ERROR, E_USER_ERROR);
@@ -136,19 +136,29 @@ class Kohana_Core {
*/
public static $config;
- // Is the environment initialized?
+ /**
+ * @var boolean Has [Kohana::init] been called?
+ */
protected static $_init = FALSE;
- // Currently active modules
+ /**
+ * @var array Currently active modules
+ */
protected static $_modules = array();
- // Include paths that are used to find files
+ /**
+ * @var array Include paths that are used to find files
+ */
protected static $_paths = array(APPPATH, SYSPATH);
- // File path cache
+ /**
+ * @var array File path cache, used when caching is true in [Kohana::init]
+ */
protected static $_files = array();
- // Has the file cache changed?
+ /**
+ * @var boolean Has the file path cache changed during this execution? Used internally when when caching is true in [Kohana::init]
+ */
protected static $_files_changed = FALSE;
/**
@@ -160,21 +170,20 @@ class Kohana_Core {
* - Sanitizes GET, POST, and COOKIE variables
* - Converts GET, POST, and COOKIE variables to the global character set
*
- * Any of the global settings can be set here:
+ * The following settings can be set:
*
* Type | Setting | Description | Default Value
* ----------|------------|------------------------------------------------|---------------
- * `boolean` | errors | use internal error and exception handling? | `TRUE`
- * `boolean` | profile | do internal benchmarking? | `TRUE`
- * `boolean` | caching | cache the location of files between requests? | `FALSE`
- * `string` | charset | character set used for all input and output | `"utf-8"`
- * `string` | base_url | set the base URL for the application | `"/"`
- * `string` | index_file | set the index.php file name | `"index.php"`
- * `string` | cache_dir | set the cache directory path | `APPPATH."cache"`
- * `integer` | cache_life | set the default cache lifetime | `60`
+ * `string` | base_url | The base URL for your application. This should be the *relative* path from your DOCROOT to your `index.php` file, in other words, if Kohana is in a subfolder, set this to the subfolder name, otherwise leave it as the default. **The leading slash is required**, trailing slash is optional. | `"/"`
+ * `string` | index_file | The name of the [front controller](http://en.wikipedia.org/wiki/Front_Controller_pattern). This is used by Kohana to generate relative urls like [HTML::anchor()] and [URL::base()]. This is usually `index.php`. To [remove index.php from your urls](tutorials/clean-urls), set this to `FALSE`. | `"index.php"`
+ * `string` | charset | Character set used for all input and output | `"utf-8"`
+ * `string` | cache_dir | Kohana's cache directory. Used by [Kohana::cache] for simple internal caching, like [Fragments](kohana/fragments) and **\[caching database queries](this should link somewhere)**. This has nothing to do with the [Cache module](cache). | `APPPATH."cache"`
+ * `integer` | cache_life | Lifetime, in seconds, of items cached by [Kohana::cache] | `60`
+ * `boolean` | errors | Should Kohana catch PHP errors and uncaught Exceptions and show the `error_view`. See [Error Handling](kohana/errors) for more info. <br /> <br /> Recommended setting: `TRUE` while developing, `FALSE` on production servers. | `TRUE`
+ * `boolean` | profile | Whether to enable the [Profiler](kohana/profiling). <br /> <br />Recommended setting: `TRUE` while developing, `FALSE` on production servers. | `TRUE` * `boolean` | caching | Cache file locations to speed up [Kohana::find_file]. This has nothing to do with [Kohana::cache], [Fragments](kohana/fragments) or the [Cache module](cache). <br /> <br /> Recommended setting: `FALSE` while developing, `TRUE` on production servers. | `FALSE`
*
* @throws Kohana_Exception
- * @param array global settings
+ * @param array Array of settings. See above.
* @return void
* @uses Kohana::globals
* @uses Kohana::sanitize
@@ -371,12 +380,14 @@ public static function deinit()
/**
* Reverts the effects of the `register_globals` PHP setting by unsetting
- * all global varibles except for the default super globals (GPCS, etc).
+ * all global varibles except for the default super globals (GPCS, etc),
+ * which is a [potential security hole.][ref-wikibooks]
*
- * if (ini_get('register_globals'))
- * {
- * Kohana::globals();
- * }
+ * This is called automatically by [Kohana::init] if `register_globals` is
+ * on.
+ *
+ *
+ * [ref-wikibooks]: http://en.wikibooks.org/wiki/PHP_Programming/Register_Globals
*
* @return void
*/
@@ -452,8 +463,9 @@ public static function sanitize($value)
}
/**
- * Provides auto-loading support of Kohana classes, as well as transparent
- * extension of classes that have a _Core suffix.
+ * Provides auto-loading support of classes that follow Kohana's [class
+ * naming conventions](kohana/conventions#class-names-and-file-location).
+ * See [Loading Classes](kohana/autoloading) for more information.
*
* Class names are converted to file names by making the class name
* lowercase and converting underscores to slashes:
@@ -461,6 +473,13 @@ public static function sanitize($value)
* // Loads classes/my/class/name.php
* Kohana::auto_load('My_Class_Name');
*
+ * You should never have to call this function, as simply calling a class
+ * will cause it to be called.
+ *
+ * This function must be enabled as an autoloader in the bootstrap:
+ *
+ * spl_autoload_register(array('Kohana', 'auto_load'));
+ *
* @param string class name
* @return boolean
*/
@@ -549,7 +568,7 @@ public static function modules(array $modules = NULL)
/**
* Returns the the currently active include paths, including the
- * application and system paths.
+ * application, system, and each module's path.
*
* @return array
*/
@@ -559,13 +578,17 @@ public static function include_paths()
}
/**
- * Finds the path of a file by directory, filename, and extension.
- * If no extension is given, the default EXT extension will be used.
+ * Searches for a file in the [Cascading Filesystem](kohana/files), and
+ * returns the path to the file that has the highest precedence, so that it
+ * can be included.
*
- * When searching the "config" or "i18n" directories, or when the
- * $array flag is set to true, an array of files
- * will be returned. These files will return arrays which must be
- * merged together.
+ * When searching the "config", "messages", or "i18n" directories, or when
+ * the `$array` flag is set to true, an array of all the files that match
+ * that path in the [Cascading Filesystem](kohana/files) will be returned.
+ * These files will return arrays which must be merged together.
+ *
+ * If no extension is given, the default extension (`EXT` set in
+ * `index.php`) will be used.
*
* // Returns an absolute path to views/template.php
* Kohana::find_file('views', 'template');
@@ -573,7 +596,7 @@ public static function include_paths()
* // Returns an absolute path to media/css/style.css
* Kohana::find_file('media', 'css/style', 'css');
*
- * // Returns an array of all the "mimes" configuration file
+ * // Returns an array of all the "mimes" configuration files
* Kohana::find_file('config', 'mimes');
*
* @param string directory name (views, i18n, classes, extensions, etc.)
@@ -670,8 +693,11 @@ public static function find_file($dir, $file, $ext = NULL, $array = FALSE)
}
/**
- * Recursively finds all of the files in the specified directory.
+ * Recursively finds all of the files in the specified directory at any
+ * location in the [Cascading Filesystem](kohana/files), and returns an
+ * array of all the files found, sorted alphabetically.
*
+ * // Find all view files.
* $views = Kohana::list_files('views');
*
* @param string directory name
@@ -764,7 +790,17 @@ public static function load($file)
}
/**
- * Creates a new configuration object for the requested group.
+ * Returns the configuration array for the requested group. See
+ * [configuration files](kohana/files/config) for more information.
+ *
+ * // Get all the configuration in config/database.php
+ * $config = Kohana::config('database');
+ *
+ * // Get only the default connection configuration
+ * $default = Kohana::config('database.default')
+ *
+ * // Get only the hostname of the default connection
+ * $host = Kohana::config('database.default.connection.hostname')
*
* @param string group name
* @return Config
@@ -808,6 +844,8 @@ public static function config($group)
* Caching objects may not work as expected. Storing references or an
* object or array that has recursion will cause an E_FATAL.
*
+ * The cache directory and default cache lifetime is set by [Kohana::init]
+ *
* [ref-var]: http://php.net/var_export
*
* @throws Kohana_Exception
@@ -885,8 +923,9 @@ public static function cache($name, $data = NULL, $lifetime = NULL)
/**
* Get a message from a file. Messages are arbitary strings that are stored
- * in the messages/ directory and reference by a key. Translation is not
- * performed on the returned values.
+ * in the `messages/` directory and reference by a key. Translation is not
+ * performed on the returned values. See [message files](kohana/files/messages)
+ * for more information.
*
* // Get "username" from messages/text.php
* $username = Kohana::message('text', 'username');
View
6 classes/kohana/encrypt.php
@@ -35,7 +35,9 @@ class Kohana_Encrypt {
*/
public static $instances = array();
- // OS-dependent RAND type to use
+ /**
+ * @var string OS-dependent RAND type to use
+ */
protected static $_rand;
/**
@@ -45,7 +47,7 @@ class Kohana_Encrypt {
* $encrypt = Encrypt::instance();
*
* @param string configuration group name
- * @return object
+ * @return Encrypt
*/
public static function instance($name = NULL)
{
View
4 classes/kohana/fragment.php
@@ -29,7 +29,9 @@ class Kohana_Fragment {
*/
public static $i18n = FALSE;
- // List of buffer => cache key
+ /**
+ * @var array list of buffer => cache key
+ */
protected static $_caches = array();
/**
View
6 classes/kohana/html.php
@@ -364,6 +364,12 @@ public static function attributes(array $attributes = NULL)
continue;
}
+ if (is_int($key))
+ {
+ // Assume non-associative keys are mirrored attributes
+ $key = $value;
+ }
+
// Add the attribute value
$compiled .= ' '.$key.'="'.HTML::chars($value).'"';
}
View
4 classes/kohana/i18n.php
@@ -32,7 +32,9 @@ class Kohana_I18n {
*/
public static $source = 'en-us';
- // Cache of loaded languages
+ /**
+ * @var array cache of loaded languages
+ */
protected static $_cache = array();
/**
View
12 classes/kohana/inflector.php
@@ -13,11 +13,19 @@
*/
class Kohana_Inflector {
- // Cached inflections
+ /**
+ * @var array cached inflections
+ */
protected static $cache = array();
- // Uncountable and irregular words
+ /**
+ * @var array uncountable words
+ */
protected static $uncountable;
+
+ /**
+ * @var array irregular words
+ */
protected static $irregular;
/**
View
14 classes/kohana/log.php
@@ -63,10 +63,14 @@ public static function instance()
return Log::$_instance;
}
- // List of added messages
+ /**
+ * @var array list of added messages
+ */
protected $_messages = array();
- // List of log writers
+ /**
+ * @var array list of log writers
+ */
protected $_writers = array();
/**
@@ -78,7 +82,7 @@ public static function instance()
* @param object Log_Writer instance
* @param mixed array of messages levels to write OR max level to write
* @param integer min level to write IF $levels is not an array
- * @return $this
+ * @return Log
*/
public function attach(Log_Writer $writer, $levels = array(), $min_level = 0)
{
@@ -102,7 +106,7 @@ public function attach(Log_Writer $writer, $levels = array(), $min_level = 0)
* $log->detach($writer);
*
* @param object Log_Writer instance
- * @return $this
+ * @return Log
*/
public function detach(Log_Writer $writer)
{
@@ -123,7 +127,7 @@ public function detach(Log_Writer $writer)
* @param string level of message
* @param string message body
* @param array values to replace in the message
- * @return $this
+ * @return Log
*/
public function add($level, $message, array $values = NULL)
{
View
4 classes/kohana/log/file.php
@@ -10,7 +10,9 @@
*/
class Kohana_Log_File extends Log_Writer {
- // Directory to place log files in
+ /**
+ * @var string Directory to place log files in
+ */
protected $_directory;
/**
View
4 classes/kohana/log/syslog.php
@@ -10,7 +10,9 @@
*/
class Kohana_Log_Syslog extends Log_Writer {
- // The syslog identifier
+ /**
+ * @var string The syslog identifier
+ */
protected $_ident;
/**
View
4 classes/kohana/profiler.php
@@ -18,7 +18,9 @@ class Kohana_Profiler {
*/
public static $rollover = 1000;
- // Collected benchmarks
+ /**
+ * @var array collected benchmarks
+ */
protected static $_marks = array();
/**
View
24 classes/kohana/session.php
@@ -15,7 +15,9 @@
*/
public static $default = 'native';
- // Session instances
+ /**
+ * @var array session instances
+ */
protected static $instances = array();
/**
@@ -58,19 +60,29 @@ public static function instance($type = NULL, $id = NULL)
return Session::$instances[$type];
}
- // Cookie name
+ /**
+ * @var string cookie name
+ */
protected $_name = 'session';
- // Cookie lifetime
+ /**
+ * @var int cookie lifetime
+ */
protected $_lifetime = 0;
- // Encrypt session data?
+ /**
+ * @var bool encrypt session data?
+ */
protected $_encrypted = FALSE;
- // Session data
+ /**
+ * @var array session data
+ */
protected $_data = array();
- // Is the session destroyed?
+ /**
+ * @var bool session destroyed?
+ */
protected $_destroyed = FALSE;
/**
View
13 classes/kohana/session/cookie.php
@@ -10,22 +10,35 @@
*/
class Kohana_Session_Cookie extends Session {
+ /**
+ * @param string $id session id
+ * @return string
+ */
protected function _read($id = NULL)
{
return Cookie::get($this->_name, NULL);
}
+ /**
+ * @return null
+ */
protected function _regenerate()
{
// Cookie sessions have no id
return NULL;
}
+ /**
+ * @return bool
+ */
protected function _write()
{
return Cookie::set($this->_name, $this->__toString(), $this->_lifetime);
}
+ /**
+ * @return bool
+ */
protected function _destroy()
{
return Cookie::delete($this->_name);
View
16 classes/kohana/session/native.php
@@ -10,11 +10,18 @@
*/
class Kohana_Session_Native extends Session {
+ /**
+ * @return string
+ */
public function id()
{
return session_id();
}
+ /**
+ * @param string $id session id
+ * @return null
+ */
protected function _read($id = NULL)
{
// Sync up the session cookie with Cookie parameters
@@ -41,6 +48,9 @@ protected function _read($id = NULL)
return NULL;
}
+ /**
+ * @return string
+ */
protected function _regenerate()
{
// Regenerate the session id
@@ -49,6 +59,9 @@ protected function _regenerate()
return session_id();
}
+ /**
+ * @return bool
+ */
protected function _write()
{
// Write and close the session
@@ -57,6 +70,9 @@ protected function _write()
return TRUE;
}
+ /**
+ * @return bool
+ */
protected function _destroy()
{
// Destroy the current session
View
4 classes/kohana/utf8.php
@@ -26,12 +26,12 @@
class Kohana_UTF8 {
/**
- * @var boolean does the server support UTF-8 natively?
+ * @var boolean Does the server support UTF-8 natively?
*/
public static $server_utf8 = NULL;
/**
- * @var array list of called methods
+ * @var array List of called methods that have had their required file included.
*/
public static $called = array();
View
23 config/userguide.php
@@ -0,0 +1,23 @@
+<?php defined('SYSPATH') or die('No direct script access.');
+
+return array(
+ // Leave this alone
+ 'modules' => array(
+
+ // This should be the path to this modules userguide pages, without the 'guide/'. Ex: '/guide/modulename/' would be 'modulename'
+ 'kohana' => array(
+
+ // Whether this modules userguide pages should be shown
+ 'enabled' => TRUE,
+
+ // The name that should show up on the userguide index page
+ 'name' => 'Kohana',
+
+ // A short description of this module, shown on the index page
+ 'description' => 'Documentation for Kohana core/system.',
+
+ // Copyright message, shown in the footer for this module
+ 'copyright' => '&copy; 2008–2010 Kohana Team',
+ )
+ )
+);
View
69 guide/kohana/autoloading.md
@@ -0,0 +1,69 @@
+# Loading Classes
+
+Kohana takes advantage of PHP [autoloading](http://php.net/manual/language.oop5.autoload.php). This removes the need to call [include](http://php.net/include) or [require](http://php.net/require) before using a class. When you use a class Kohana will find and include the class file for you. For instance, when you want to use the [Cookie::set] method, you simply call:
+
+ Cookie::set('mycookie', 'any string value');
+
+Or to load an [Encrypt] instance, just call [Encrypt::instance]:
+
+ $encrypt = Encrypt::instance();
+
+Classes are loaded via the [Kohana::auto_load] method, which makes a simple conversion from class name to file name:
+
+1. Classes are placed in the `classes/` directory of the [filesystem](files)
+2. Any underscore characters in the class name are converted to slashes
+2. The filename is lowercase
+
+When calling a class that has not been loaded (eg: `Session_Cookie`), Kohana will search the filesystem using [Kohana::find_file] for a file named `classes/session/cookie.php`.
+
+If your classes do not follow this convention, they cannot be autoloaded by Kohana. You will have to manually included your files, or add your own [autoload function.](http://us3.php.net/manual/en/function.spl-autoload-register.php)
+
+## Custom Autoloaders
+
+Kohana's default autoloader is enabled in `application/bootstrap.php` using [spl_autoload_register](http://php.net/spl_autoload_register):
+
+ spl_autoload_register(array('Kohana', 'auto_load'));
+
+This allows [Kohana::auto_load] to attempt to find and include any class that does not yet exist when the class is first used.
+
+### Example: Zend
+
+You can easily gain access to other libraries if they include an autoloader. For example, here is how to enable Zend's autoloader so you can use Zend libraries in your Kohana application.
+
+#### Download and install the Zend Framework files
+
+- [Download the latest Zend Framework files](http://framework.zend.com/download/latest).
+- Create a `vendor` directory at `application/vendor`. This keeps third party software separate from your application classes.
+- Move the decompressed Zend folder containing Zend Framework to `application/vendor/Zend`.
+
+
+#### Include Zend's Autoloader in your bootstrap
+
+Somewhere in `application/bootstrap.php`, copy the following code:
+
+ /**
+ * Enable Zend Framework autoloading
+ */
+ if ($path = Kohana::find_file('vendor', 'Zend/Loader'))
+ {
+ ini_set('include_path',
+ ini_get('include_path').PATH_SEPARATOR.dirname(dirname($path)));
+
+ require_once 'Zend/Loader/Autoloader.php';
+ Zend_Loader_Autoloader::getInstance();
+ }
+
+#### Usage example
+
+You can now autoload any Zend Framework classes from inside your Kohana application.
+
+ if ($validate($_POST))
+ {
+ $mailer = new Zend_Mail;
+
+ $mailer->setBodyHtml($view)
+ ->setFrom(Kohana::config('site')->email_from)
+ ->addTo($email)
+ ->setSubject($message)
+ ->send();
+ }
View
164 guide/kohana/bootstrap.md
@@ -0,0 +1,164 @@
+# Bootstrap
+
+The bootstrap is located at `application/bootstrap.php`. It is responsible for setting up the Kohana environment and executing the main response. It is included by `index.php` (see [Request flow](flow))
+
+[!!] The bootstrap is responsible for the flow of your application. In previous versions of Kohana the bootstrap was in `system` and was somewhat of an unseen, uneditible force. In Kohana 3 the bootstrap takes on a much more integral and versatile role. Do not be afraid to edit and change your bootstrap however you see fit.
+
+## Environment setup
+
+First the bootstrap sets the timezone and the locale, and adds Kohana's autoloader so the [cascading filesystem](files) works. You could add any other settings that all your application needed here.
+
+~~~
+// Sample excerpt from bootstrap.php with comments trimmed down
+
+// Set the default time zone.
+date_default_timezone_set('America/Chicago');
+
+// Set the default locale.
+setlocale(LC_ALL, 'en_US.utf-8');
+
+// Enable the Kohana auto-loader.
+spl_autoload_register(array('Kohana', 'auto_load'));
+
+// Enable the Kohana auto-loader for unserialization.
+ini_set('unserialize_callback_func', 'spl_autoload_call');
+~~~
+
+## Initilization and Configuration
+
+Kohana is then initialized by calling [Kohana::init], and the log and [config](files/config) reader/writers are enabled.
+
+~~~
+// Sample excerpt from bootstrap.php with comments trimmed down
+
+Kohana::init(array('
+ base_url' => '/kohana/',
+ index_file => false,
+));
+
+// Attach the file writer to logging. Multiple writers are supported.
+Kohana::$log->attach(new Kohana_Log_File(APPPATH.'logs'));
+
+// Attach a file reader to config. Multiple readers are supported.
+Kohana::$config->attach(new Kohana_Config_File);
+~~~
+
+You can add conditional statements to make the bootstrap have different values based on certain settings. For example, detect whether we are live by checking `$_SERVER['HTTP_HOST']` and set caching, profiling, etc. accordingly. This is just an example, there are many different ways to accomplish the same thing.
+
+~~~
+// Excerpt from http://github.com/isaiahdw/kohanaphp.com/blob/f2afe8e28b/application/bootstrap.php
+... [trimmed]
+
+/**
+ * Set the environment status by the domain.
+ */
+if (strpos($_SERVER['HTTP_HOST'], 'kohanaphp.com') !== FALSE)
+{
+ // We are live!
+ Kohana::$environment = Kohana::PRODUCTION;
+
+ // Turn off notices and strict errors
+ error_reporting(E_ALL ^ E_NOTICE ^ E_STRICT);
+}
+
+/**
+ * Initialize Kohana, setting the default options.
+ ... [trimmed]
+ */
+Kohana::init(array(
+ 'base_url' => Kohana::$environment === Kohana::PRODUCTION ? '/' : '/kohanaphp.com/',
+ 'caching' => Kohana::$environment === Kohana::PRODUCTION,
+ 'profile' => Kohana::$environment !== Kohana::PRODUCTION,
+ 'index_file' => FALSE,
+));
+
+... [trimmed]
+
+try
+{
+ $request = Request::instance()->execute();
+}
+catch (Exception $e)
+{
+ // If we are in development and the error wasn't a 404, show the stack trace.
+ if ( Kohana::$environment == "development" AND $e->getCode() != 404 )
+ {
+ throw $e;
+ }
+...[trimmed]
+~~~
+
+[!!] Note: The default bootstrap will set `Kohana::$environment = $_ENV['KOHANA_ENV']` if set. Docs on how to supply this variable are available in your web server's documentation (e.g. [Apache](http://httpd.apache.org/docs/1.3/mod/mod_env.html#setenv), [Lighttpd](http://redmine.lighttpd.net/wiki/1/Docs:ModSetEnv#Options)). This is considered better practice than many alternative methods to set `Kohana::$enviroment`, as you can change the setting per server, without having to rely on config options or hostnames.
+
+## Modules
+
+**Read the [Modules](modules) page for a more detailed description.**
+
+[Modules](modules) are then loaded using [Kohana::modules()]. Including modules is optional.
+
+Each key in the array should be the name of the module, and the value is the path to the module, either relative or absolute.
+~~~
+// Example excerpt from bootstrap.php
+
+Kohana::modules(array(
+ 'database' => MODPATH.'database',
+ 'orm' => MODPATH.'orm',
+ 'userguide' => MODPATH.'userguide',
+));
+~~~
+
+## Routes
+
+**Read the [Routing](routing) page for a more detailed description and more examples.**
+
+[Routes](routing) are then defined via [Route::set()].
+
+~~~
+// The default route that comes with Kohana 3
+Route::set('default', '(<controller>(/<action>(/<id>)))')
+ ->defaults(array(
+ 'controller' => 'welcome',
+ 'action' => 'index',
+ ));
+~~~
+
+## Execution
+
+Once our environment is initialized and routes defined, it's time to execute our application. This area of the bootstrap is very flexible. Do not be afraid to change this around to whatever suits your needs.
+
+### Basic Example
+The most simple way to do this, and what comes default with Kohana 3 is simply:
+~~~
+// Execute the main request
+echo Request::instance()
+ ->execute()
+ ->send_headers()
+ ->response;
+~~~
+
+### Catching Exceptions
+
+**See [Error Handling](errors) for a more detailed description and more examples.**
+
+The previous example provides no error catching, which means if an error occurs a stack trace would be shown which could show sensitive info, as well as be unfriendly for the user. One way to solve this is to add a `try catch` block. If we get an exception, we will show the view located at `views/errors/404.php`. **Note: Because we catch the exception, Kohana will not log the error! It is your responsibility to log the error.**
+
+~~~
+try
+{
+ // Execute the main request
+ $request = Request::instance()->execute();
+}
+catch (Exception $e)
+{
+ // Be sure to log the error
+ Kohana::$log->add(Kohana::ERROR, Kohana::exception_text($e));
+
+ // If there was an error, send a 404 response and display an error
+ $request->status = 404;
+ $request->response = View::factory('errors/404');
+}
+
+// Send the headers and echo the response
+$request->send_headers();
+echo $request->response;
+~~~
View
1  guide/kohana/controllers.md
@@ -0,0 +1 @@
+This will discuss controller basics, like before() and after(), private function, and about extending controllers like the Controller_Template, or using a parent::before() for authentication.
View
306 guide/kohana/conventions.md
@@ -0,0 +1,306 @@
+# Conventions and Coding Style
+
+It is encouraged that you follow Kohana's [coding style](http://dev.kohanaframework.org/wiki/kohana2/CodingStyle). This makes code more readable and allows for easier code sharing and contributing.
+
+## Class Names and File Location
+
+Class names in Kohana follow a strict convention to facilitate [autoloading](autoloading). Class names should have uppercase first letters with underscores to separate words. Underscores are significant as they directly reflect the file location in the filesystem.
+
+The following conventions apply:
+
+1. CamelCased class names should not be used, except when it is undesirable to create a new directory level.
+2. All class file names and directory names are lowercase.
+3. All classes should be in the `classes` directory. This may be at any level in the [cascading filesystem](files).
+
+[!!] Unlike Kohana v2.x, there is no separation between "controllers", "models", "libraries" and "helpers". All classes are placed in the "classes/" directory, regardless if they are static "helpers" or object "libraries". You can use whatever kind of class design you want: static, singleton, adapter, etc.
+
+### Examples {#class-name-examples}
+
+Remember that in a class, an underscore means a new directory. Consider the following examples:
+
+Class Name | File Path
+----------------------|-------------------------------
+Controller_Template | classes/controller/template.php
+Model_User | classes/model/user.php
+Database | classes/database.php
+Database_Query | classes/database/query.php
+Form | classes/form.php
+
+## Coding Standards
+
+In order to produce highly consistent source code, we ask that everyone follow the coding standards as closely as possible.
+
+### Brackets
+Please use [BSD/Allman Style](http://en.wikipedia.org/wiki/Indent_style#BSD.2FAllman_style) bracketing. Brackets are always on their own line. The exception to this rule is the opening bracket for a class, which can be on the same line.
+
+ if ($foo == 'bar')
+ {
+ $baz->bar();
+ }
+ else
+ {
+ $baz->default();
+ }
+
+ // The opening bracket for a class can be on the same line
+ Class Foobar {
+
+
+### Naming Conventions
+
+Kohana uses under_score naming, not camelCase naming.
+
+#### Classes
+
+ // Controller class, uses Controller_ prefix
+ class Controller_Apple extends Controller {
+
+ // Model class, uses Model_ prefix
+ class Model_Cheese extends Model {
+
+ // Regular class
+ class Peanut {
+
+When creating an instance of a class, don't use parentheses if you're not passing something on to the constructor:
+
+ // Correct:
+ $db = new Database;
+
+ // Incorrect:
+ $db = new Database();
+
+#### Functions and Methods
+
+Functions should be all lowercase, and use under_scores to separate words:
+
+ function drink_beverage($beverage)
+ {
+
+#### Variables
+
+All variables should be lowercase and use under_score, not camelCase:
+
+ // Correct:
+ $foo = 'bar';
+ $long_example = 'uses underscores';
+
+ // Incorrect:
+ $weDontWantThis = 'understood?';
+
+### Indentation
+
+You must use tabs to indent your code. Using spaces for tabbing is strictly forbidden.
+
+Vertical spacing (for multi-line) is done with spaces. Tabs are not good for vertical alignment because different people have different tab widths.
+
+ $text = 'this is a long text block that is wrapped. Normally, we aim for '
+ .'wrapping at 80 chars. Vertical alignment is very important for '
+ .'code readability. Remember that all indentation is done with tabs,'
+ .'but vertical alignment should be completed with spaces, after '
+ .'indenting with tabs.';
+
+### String concatenation
+
+Do not put spaces around the concatenation operator:
+
+ // Correct:
+ $str = 'one'.$var.'two';
+
+ // Incorrect:
+ $str = 'one'. $var .'two';
+ $str = 'one' . $var . 'two';
+
+### Single Line Statements
+
+Single-line IF statements should only be used when breaking normal execution (e.g. return or continue):
+
+ // Acceptable:
+ if ($foo == $bar)
+ return $foo;
+
+ if ($foo == $bar)
+ continue;
+
+ if ($foo == $bar)
+ break;
+
+ if ($foo == $bar)
+ throw new Exception('You screwed up!');
+
+ // Not acceptable:
+ if ($baz == $bun)
+ $baz = $bar + 2;
+
+### Comparison Operations
+
+Please use OR and AND for comparison:
+
+ // Correct:
+ if (($foo AND $bar) OR ($b AND $c))
+
+ // Incorrect:
+ if (($foo && $bar) || ($b && $c))
+
+Please use elseif, not else if:
+
+ // Correct:
+ elseif ($bar)
+
+ // Incorrect:
+ else if($bar)
+
+### Switch structures
+
+Each case, break and default should be on a separate line. The block inside a case or default must be indented by 1 tab.
+
+ switch ($var)
+ {
+ case 'bar':
+ case 'foo':
+ echo 'hello';
+ break;
+ case 1:
+ echo 'one';
+ break;
+ default:
+ echo 'bye';
+ break;
+ }
+
+### Parentheses
+
+There should be one space after statement name, followed by a parenthesis. The ! (bang) character must have a space on either side to ensure maximum readability. Except in the case of a bang or type casting, there should be no whitespace after an opening parenthesis or before a closing parenthesis.
+
+ // Correct:
+ if ($foo == $bar)
+ if ( ! $foo)
+
+ // Incorrect:
+ if($foo == $bar)
+ if(!$foo)
+ if ((int) $foo)
+ if ( $foo == $bar )
+ if (! $foo)
+
+### Ternaries
+
+All ternary operations should follow a standard format. Use parentheses around expressions only, not around just variables.
+
+ $foo = ($bar == $foo) ? $foo : $bar;
+ $foo = $bar ? $foo : $bar;
+
+All comparisons and operations must be done inside of a parentheses group:
+
+ $foo = ($bar > 5) ? ($bar + $foo) : strlen($bar);
+
+When separating complex ternaries (ternaries where the first part goes beyond ~80 chars) into multiple lines, spaces should be used to line up operators, which should be at the front of the successive lines:
+
+ $foo = ($bar == $foo)
+ ? $foo
+ : $bar;
+
+### Type Casting
+
+Type casting should be done with spaces on each side of the cast:
+
+ // Correct:
+ $foo = (string) $bar;
+ if ( (string) $bar)
+
+ // Incorrect:
+ $foo = (string)$bar;
+
+When possible, please use type casting instead of ternary operations:
+
+ // Correct:
+ $foo = (bool) $bar;
+
+ // Incorrect:
+ $foo = ($bar == TRUE) ? TRUE : FALSE;
+
+When casting type to integer or boolean, use the short format:
+
+ // Correct:
+ $foo = (int) $bar;
+ $foo = (bool) $bar;
+
+ // Incorrect:
+ $foo = (integer) $bar;
+ $foo = (boolean) $bar;
+
+### Constants
+
+Always use uppercase for constants:
+
+ // Correct:
+ define('MY_CONSTANT', 'my_value');
+ $a = TRUE;
+ $b = NULL;
+
+ // Incorrect:
+ define('MyConstant', 'my_value');
+ $a = True;
+ $b = null;
+
+Place constant comparisons at the end of tests:
+
+ // Correct:
+ if ($foo !== FALSE)
+
+ // Incorrect:
+ if (FALSE !== $foo)
+
+This is a slightly controversial choice, so I will explain the reasoning. If we were to write the previous example in plain English, the correct example would read:
+
+ if variable $foo is not exactly FALSE
+
+And the incorrect example would read:
+
+ if FALSE is not exactly variable $foo
+
+Since we are reading left to right, it simply doesn't make sense to put the constant first.
+
+### Comments
+
+#### One-line comments
+
+Use //, preferably above the line of code you're commenting on. Leave a space after it and start with a capital. Never use #.
+
+ // Correct
+
+ //Incorrect
+ // incorrect
+ # Incorrect
+
+### Regular expressions
+
+When coding regular expressions please use PCRE rather than the POSIX flavor. PCRE is considered more powerful and faster.
+
+ // Correct:
+ if (preg_match('/abc/i'), $str)
+
+ // Incorrect:
+ if (eregi('abc', $str))
+
+Use single quotes around your regular expressions rather than double quotes. Single-quoted strings are more convenient because of their simplicity. Unlike double-quoted strings they don't support variable interpolation nor integrated backslash sequences like \n or \t, etc.
+
+ // Correct:
+ preg_match('/abc/', $str);
+
+ // Incorrect:
+ preg_match("/abc/", $str);
+
+When performing a regular expression search and replace, please use the $n notation for backreferences. This is preferred over \\n.
+
+ // Correct:
+ preg_replace('/(\d+) dollar/', '$1 euro', $str);
+
+ // Incorrect:
+ preg_replace('/(\d+) dollar/', '\\1 euro', $str);
+
+Finally, please note that the $ character for matching the position at the end of the line allows for a following newline character. Use the D modifier to fix this if needed. [More info](http://blog.php-security.org/archives/76-Holes-in-most-preg_match-filters.html).
+
+ $str = "email@example.com\n";
+
+ preg_match('/^.+@.+$/', $str); // TRUE
+ preg_match('/^.+@.+$/D', $str); // FALSE
View
89 guide/kohana/cookies.md
@@ -0,0 +1,89 @@
+# Cookies
+
+Kohana provides classes that make it easy to work with both cookies and sessions. At a high level both sessions and cookies provide the same functionality. They allow the developer to store temporary or persistent information about a specific client for later retrieval, usually to make something persistent between requests.
+
+[Cookies](http://en.wikipedia.org/wiki/HTTP_cookie) should be used for storing non-private data that is persistent for a long period of time. For example storing a user preference or a language setting. Use the [Cookie] class for getting and setting cookies.
+
+[!!] Kohana uses "signed" cookies. Every cookie that is stored is combined with a secure hash to prevent modification of the cookie. If a cookie is modified outside of Kohana the hash will be incorrect and the cookie will be deleted. This hash is generated using [Cookie::salt()], which uses the [Cookie::$salt] property. You should change this setting when your application is live.
+
+Nothing stops you from using `$_COOKIE` like normal, but you can not mix using the Cookie class and the regular `$_COOKIE` global, because the hash that Kohana uses to sign cookies will not be present, and Kohana will delete the cookie.
+
+## Storing, Retrieving, and Deleting Data
+
+[Cookie] and [Session] provide a very similar API for storing data. The main difference between them is that sessions are accessed using an object, and cookies are accessed using a static class.
+
+### Storing Data
+
+Storing session or cookie data is done using the [Cookie::set] method:
+
+ // Set cookie data
+ Cookie::set($key, $value);
+
+ // Store a user id
+ Cookie::set('user_id', 10);
+
+### Retrieving Data
+
+Getting session or cookie data is done using the [Cookie::get] method:
+
+ // Get cookie data
+ $data = Cookie::get($key, $default_value);
+
+ // Get the user id
+ $user = Cookie::get('user_id');
+
+### Deleting Data
+
+Deleting session or cookie data is done using the [Cookie::delete] method:
+
+ // Delete cookie data
+ Cookie::delete($key);
+
+ // Delete the user id
+ Cookie::delete('user_id');
+
+## Cookie Settings
+
+All of the cookie settings are changed using static properties. You can either change these settings in `bootstrap.php` or by using [transparent extension](extension). Always check these settings before making your application live, as many of them will have a direct affect on the security of your application.
+
+The most important setting is [Cookie::$salt], which is used for secure signing. This value should be changed and kept secret:
+
+ Cookie::$salt = 'your secret is safe with me';
+
+[!!] Changing this value will render all cookies that have been set before invalid.
+
+By default, cookies are stored until the browser is closed. To use a specific lifetime, change the [Cookie::$expiration] setting:
+
+ // Set cookies to expire after 1 week
+ Cookie::$expiration = 604800;
+
+ // Alternative to using raw integers, for better clarity
+ Cookie::$expiration = Date::WEEK;
+
+The path that the cookie can be accessed from can be restricted using the [Cookie::$path] setting.
+
+ // Allow cookies only when going to /public/*
+ Cookie::$path = '/public/';
+
+The domain that the cookie can be accessed from can also be restricted, using the [Cookie::$domain] setting.
+
+ // Allow cookies only on the domain www.example.com
+ Cookie::$domain = 'www.example.com';
+
+If you want to make the cookie accessible on all subdomains, use a dot at the beginning of the domain.
+
+ // Allow cookies to be accessed on example.com and *.example.com
+ Cookie::$domain = '.example.com';
+
+To only allow the cookie to be accessed over a secure (HTTPS) connection, use the [Cookie::$secure] setting.
+
+ // Allow cookies to be accessed only on a secure connection
+ Cookie::$secure = TRUE;
+
+ // Allow cookies to be accessed on any connection
+ Cookie::$secure = FALSE;
+
+To prevent cookies from being accessed using Javascript, you can change the [Cookie::$httponly] setting.
+
+ // Make cookies inaccessible to Javascript
+ Cookie::$httponly = TRUE;
View
20 guide/kohana/debugging.md
@@ -0,0 +1,20 @@
+# Debugging
+
+Kohana includes several tools to help you debug your application.
+
+The most basic of these is [Kohana::debug]. This simple method will display any number of variables, similar to [var_export](http://php.net/var_export) or [print_r](http://php.net/print_r), but using HTML for extra formatting.
+
+ // Display a dump of the $foo and $bar variables
+ echo Kohana::debug($foo, $bar);
+
+Kohana also provides a method to show the source code of a particular file using [Kohana::debug_source].
+
+ // Display this line of source code
+ echo Kohana::debug_source(__FILE__, __LINE__);
+
+If you want to display information about your application files without exposing the installation directory, you can use [Kohana::debug_path]:
+
+ // Displays "APPPATH/cache" rather than the real path
+ echo Kohana::debug_path(APPPATH.'cache');
+
+If you are having trouble getting something to work correctly, you could check your Kohana logs and your webserver logs, as well as using a debugging tool like [Xdebug](http://www.xdebug.org/).
View
85 guide/kohana/errors.md
@@ -0,0 +1,85 @@
+# Error/Exception Handling
+
+Kohana provides both an exception handler and an error handler that transforms errors into exceptions using PHP's [ErrorException](http://php.net/errorexception) class. Many details of the error and the internal state of the application is displayed by the handler:
+
+1. Exception class
+2. Error level
+3. Error message
+4. Source of the error, with the error line highlighted
+5. A [debug backtrace](http://php.net/debug_backtrace) of the execution flow
+6. Included files, loaded extensions, and global variables
+
+## Example
+
+Click any of the links to toggle the display of additional information:
+
+<div>{{userguide/examples/error}}</div>
+
+## Disabling Error/Exception Handling
+
+If you do not want to use the internal error handling, you can disable it when calling [Kohana::init]:
+
+ Kohana::init(array('errors' => FALSE));
+
+## Error Reporting
+
+By default, Kohana displays all errors, including strict mode warnings. This is set using [error_reporting](http://php.net/error_reporting):
+
+ error_reporting(E_ALL | E_STRICT);
+
+When you application is live and in production, a more conservative setting is recommended, such as ignoring notices:
+
+ error_reporting(E_ALL & ~E_NOTICE);
+
+If you get a white screen when an error is triggered, your host probably has disabled displaying errors. You can turn it on again by adding this line just after your `error_reporting` call:
+
+ ini_set('display_errors', TRUE);
+
+Errors should **always** be displayed, even in production, because it allows you to use [exception and error handling](debugging.errors) to serve a nice error page rather than a blank white screen when an error happens.
+
+
+## Last thoughts
+
+In production, **your application should never have any uncaught exceptions**, as this can expose sensitive information (via the stack trace). In the previous example we make the assumption that there is actually a view called 'views/errors/404', which is fairly safe to assume. One solution is to turn 'errors' off in Kohana::init for your production machine, so it displays the normal php errors rather than a stack trace.
+
+~~~
+// snippet from bootstrap.php
+Kohana::init(array('
+ ...
+ 'errors' => false,
+));
+~~~
+
+So rather than displaying the Kohana error page with the stack trace, it will display the default php error. Something like:
+
+**Fatal error: Uncaught Kohana_View_Exception [ 0 ]: The requested view errors/404 could not be found ~ SYSPATH/classes/kohana/view.php [ 215 ] thrown in /var/www/kohanut/docs.kohanaphp.com/3.0/system/classes/kohana/view.php on line 215**
+
+Keep in mind what I said earlier though: **your application should never have any uncaught exceptions**, so this should not be necesarry, though it is a good idea, simply because stack traces on a production environment are a *very* bad idea.
+
+Another solution is to always have a `catch` statement that can't fail, something like an `echo` and an `exit` or a `die()`. This should almost never be necesarry, but it makes some people feel better at night. You can either wrap your entire bootstrap in a try catch, or simply wrap the contents of the catch in another try catch. For example:
+
+~~~
+try
+{
+ // Execute the main request
+ $request->execute();
+}
+catch (Exception $e)
+{
+ try
+ {
+ // Be sure to log the error
+ Kohana::$log->add(Kohana::ERROR, Kohana::exception_text($e));
+
+ // If there was an error, send a 404 response and display an error
+ $request->status = 404;
+ $request->response = View::factory('errors/404');
+ }
+ catch
+ {
+ // This is completely overkill, but helps some people sleep at night
+ echo "Something went terribly wrong. Try again in a few minutes.";
+ exit;
+ }
+}
+~~~
View
101 guide/kohana/extension.md
@@ -0,0 +1,101 @@
+# Transparent Class Extension
+
+The [cascading filesystem](files) allows transparent class extension. For instance, the class [Cookie] is defined in `SYSPATH/classes/cookie.php` as:
+
+ class Cookie extends Kohana_Cookie {}
+
+The default Kohana classes, and many extensions, use this definition so that almost all classes can be extended. You extend any class transparently, by defining your own class in `APPPATH/classes/cookie.php` to add your own methods.
+
+[!!] You should **never** modify any of the files that are distributed with Kohana. Always make modifications to classes using transparent extension to prevent upgrade issues.
+
+For instance, if you wanted to create method that sets encrypted cookies using the [Encrypt] class, you would creat a file at `application/classes/cookie.php` that extends Kohana_Cookie, and adds your functions:
+
+ <?php defined('SYSPATH') or die('No direct script access.');
+
+ class Cookie extends Kohana_Cookie {
+
+ /**
+ * @var mixed default encryption instance
+ */
+ public static $encryption = 'default';
+
+ /**
+ * Sets an encrypted cookie.
+ *
+ * @uses Cookie::set
+ * @uses Encrypt::encode
+ */
+ public static function encrypt($name, $value, $expiration = NULL)
+ {
+ $value = Encrypt::instance(Cookie::$encrpytion)->encode((string) $value);
+
+ parent::set($name, $value, $expiration);
+ }
+
+ /**
+ * Gets an encrypted cookie.
+ *
+ * @uses Cookie::get
+ * @uses Encrypt::decode
+ */
+ public static function decrypt($name, $default = NULL)
+ {
+ if ($value = parent::get($name, NULL))
+ {
+ $value = Encrypt::instance(Cookie::$encryption)->decode($value);
+ }
+
+ return isset($value) ? $value : $default;
+ }
+
+ } // End Cookie
+
+Now calling `Cookie::encrypt('secret', $data)` will create an encrypted cookie which we can decrypt with `$data = Cookie::decrypt('secret')`.
+
+## How it works
+
+To understand how this works, let's look at what happens normally. When you use the Cookie class, [Kohana::autoload] looks for `classes/cookie.php` in the [cascading filesystem](files). It looks in `application`, then each module, then `system`. The file is found in `system` and is included. Of coures, `system/classes/cookie.php` is just an empty class which extends `Kohana_Cookie`. Again, [Kohana::autoload] is called this time looking for `classes/kohana/cookie.php` which it finds in `system`.
+
+When you add your transparently extended cookie class at `application/classes/cookie.php` this file essentially "replaces" the file at `system/classes/cookie.php` without actually touching it. This happens because this time when we use the Cookie class [Kohana::autoload] looks for `classes/cookie.php` and finds the file in `application` and includes that one, instead of the one in system.
+
+## Example: changing [Cookie] settings
+
+If you are using the [Cookie](cookies) class, and want to change a setting, you should do so using transparent extension, rather than editing the file in the system folder. If you edit it directly, and in the future you upgrade your Kohana version by replacing the system folder, your changes will be reverted and your cookies will probably be invalid. Instead, create a cookie.php file either in `application/classes/cookie.php` or a module (`MODPATH/<modulename>/classes/cookie.php`).
+
+ class Cookie extends Kohana_Cookie {
+
+ // Set a new salt
+ public $salt = "some new better random salt phrase";
+
+ // Don't allow javascript access to cookies
+ public $httponly = TRUE;
+
+ }
+
+## Example: TODO: an example
+
+Just post the code and breif descript of what function it adds, you don't have to do the "How it works" like above.
+
+## Example: TODO: something else
+
+Just post the code and breif descript of what function it adds, you don't have to do the "How it works" like above.
+
+## More examples
+
+TODO: Provide some links to modules on github, etc that have examples of transparent extension in use.
+
+## Multiple Levels of Extension
+
+If you are extending a Kohana class in a module, you should maintain transparent extensions. In other words, do not include any variables or function in the "base" class (eg. Cookie). Instead make your own namespaced class, and have the "base" class extend that one. With our Encrypted cookie example we can create `MODPATH/mymod/encrypted/cookie.php`:
+
+ class Encrypted_Cookie extends Kohana_Cookie {
+
+ // Use the same encrypt() and decrypt() methods as above
+
+ }
+
+And create `MODPATH/mymod/cookie.php`:
+
+ class Cookie extends Encrypted_Cookie {}
+
+This will still allow users to add their own extension to [Cookie] while leaving your extensions intact. To do that they would make a cookie class that extends `Encrypted_Cookie` (rather than `Kohana_Cookie`) in their application folder.
View
83 guide/kohana/files.md
@@ -0,0 +1,83 @@
+# Cascading Filesystem
+
+The Kohana filesystem is a heirarchy of similar directory structures that cascade. The heirarchy in Kohana (used when a file is loaded by [Kohana::find_file]) is in the following order:
+
+1. **Application Path**
+ Defined as `APPPATH` in `index.php`. The default value is `application`.
+
+2. **Module Paths**
+ This is set as an associative array using [Kohana::modules] in `APPPATH/bootstrap.php`. Each of the values of the array will be searched **in the order that the modules are added**.
+
+3. **System Path**
+ Defined as `SYSPATH` in `index.php`. The default value is `system`. All of the main or "core" files and classes are defined here.
+
+Files that are in directories higher up the include path order take precedence over files of the same name lower down the order, which makes it is possible to overload any file by placing a file with the same name in a "higher" directory:
+
+![Cascading Filesystem Infographic](cascading_filesystem.png)
+
+This image is only shows certain files, but we can use it to illustrate some examples of the cascading filesystem:
+
+* If Kohana catches an error, it would display the `kohana/error.php` view, So it would call `Kohana::find_file('views', 'kohana/error')`. This would return `application/views/kohana/error.php` because it takes precidence over `system/views/kohana/error.php`. By doing this we can change the error view without editing the system folder.
+
+* If we used `View::factory('welcome')` it would call `Kohana::find_file('views','welcome')` which would return `application/views/welcome.php` because it takes precidence over `modules/common/views/welcome.php`. By doing this, you can overwrite things in a module without editing the modules files.
+
+* If use the Cookie class, [Kohana::auto_load] will call `Kohana::find_file('classes', 'cookie')` which will return `application/classes/cookie.php`. Assuming Cookie extends Kohana_Cookie, the autoloader would then call `Kohana::find_file('classes','kohana/cookie')` which will return `system/classes/kohana/cookie.php` because that file does not exist anywhere higher in the cascade. This is an example of [transparent extension](extension).
+
+* If you used `View::factory('user')` it would call `Kohana::find_file('views','user')` which would return `modules/common/views/user.php`.
+
+* If we wanted to change something in `config/database.php` we could copy the file to `application/config/database.php` and make the changes there. Keep in mind that [config files are merged](files/config#merge) rather than overwritten by the cascade.
+
+## Types of Files
+
+The top level directories of the application, module, and system paths have the following default directories:
+
+classes/
+: All classes that you want to [autoload](autoloading) should be stored here. This includes [controllers](mvc/controllers), [models](mvc/models), and all other classes. All classes must follow the [class naming conventions](conventions#class-names-and-file-location).
+
+config/
+: Configuration files return an associative array of options that can be loaded using [Kohana::config]. Config files are merged rather than overwritten by the cascade. See [config files](files/config) for more information.
+
+i18n/
+: Translation files return an associative array of strings. Translation is done using the `__()` method. To translate "Hello, world!" into Spanish, you would call `__('Hello, world!')` with [I18n::$lang] set to "es-es". I18n files are merged rather than overwritten by the cascade. See [I18n files](files/i18n) for more information.
+
+messages/
+: Message files return an associative array of strings that can be loaded using [Kohana::message]. Messages and i18n files differ in that messages are not translated, but always written in the default language and referred to by a single key. Message files are merged rather than overwritten by the cascade. See [message files](files/messages) for more information.
+
+views/
+: Views are plain PHP files which are used to generate HTML or other output. The view file is loaded into a [View] object and assigned variables, which it then converts into an HTML fragment. Multiple views can be used within each other. See [views](mvc/views) for more information.
+
+*other*
+: You can include any other folders in your cascading filesystem. Examples include, but are not limited to, `guide`, `vendor`, `media`, whatever you want. For example, to find `media/logo.png` in the cascading filesystem you would call `Kohana::find_file('media','logo','png')`.
+
+## Finding Files
+
+The path to any file within the filesystem can be found by calling [Kohana::find_file]:
+
+ // Find the full path to "classes/cookie.php"
+ $path = Kohana::find_file('classes', 'cookie');
+
+ // Find the full path to "views/user/login.php"
+ $path = Kohana::find_file('views', 'user/login');
+
+If the file doesn't have a `.php` extension, pass the extension as the third param.
+
+ // Find the full path to "guide/menu.md"
+ $path = Kohana::find_file('guide', 'menu', 'md');
+
+ // If $name is "2000-01-01-first-post" this would look for "posts/2000-01-01-first-post.textile"
+ $path = Kohana::find_file('posts', $name, '.textile');
+
+
+## Vendor Extensions
+
+We call extensions or external libraries that are not specific to Kohana "vendor" extensions, and they go in the vendor folder, either in application or in a module. Because these libraries do not follow Kohana's file naming conventions, they cannot be autoloaded by Kohana, so you will have to manually included them. Some examples of vendor libraries are [Markdown](http://daringfireball.net/projects/markdown/), [DOMPDF](http://code.google.com/p/dompdf), [Mustache](http://github.com/bobthecow/mustache.php) and [Swiftmailer](http://swiftmailer.org/).
+
+For example, if you wanted to use [DOMPDF](http://code.google.com/p/dompdf), you would copy it to `application/vendor/dompdf` and include the DOMPDF autoloading class. It can be useful to do this in a controller's before method, as part of a module's init.php, or the contstructor of a singleton class.
+
+ require Kohana::find_file('vendor', 'dompdf/dompdf/dompdf_config','inc');
+
+Now you can use DOMPDF without loading any more files:
+
+ $pdf = new DOMPDF;
+
+[!!] If you want to convert views into PDFs using DOMPDF, try the [PDFView](http://github.com/shadowhand/pdfview) module.
View
41 guide/kohana/files/classes.md
@@ -0,0 +1,41 @@
+# Classes
+
+TODO: Brief intro to classes.
+
+[Models](mvc/models) and [Controllers](mvc/controllers) are classes as well, but are treated slightly differently by Kohana. Read their respective pages to learn more.
+
+## Helper or Library?
+
+Kohana 3 does not differentiate between "helper" classes and "library" classes like in previous versions. They are all placed in the `classes/` folder and follow the same conventions. The distinction is that in general, a "helper" class is used statically, (for examples see the [helpers included in Kohana](helpers)), and library classes are typically instanciated and used as objects (like the [Database query builders](../database/query/builder)). The distinction is not black and white, and is irrelevant anyways, since they are treated the same by Kohana.
+
+## Creating a class
+
+To create a new class, simply place a file in the `classes/` directory at any point in the [Cascading Filesystem](files), that follows the [Class naming conventions](conventions#class-names-and-file-location). For example, lets create a `Foobar` class.
+
+ // classes/foobar.php
+
+ class Foobar {
+ static function magic() {
+ // Does something
+ }
+ }
+
+We can now call `Foobar::magic()` any where and Kohana will [autoload](autoloading) the file for us.
+
+We can also put classes in subdirectories.
+
+ // classes/professor/baxter.php
+
+ class Professor_Baxter {
+ static function teach() {
+ // Does something
+ }
+ }
+
+We could now call `Professor_Baxter::teach()` any where we want.
+
+For examples of how to create and use classes, simply look at the 'classes' folder in `system` or any module.
+
+## Namespacing your classes
+
+TODO: Discuss namespacing to provide transparent extension functionality in your own classes/modules.
View
95 guide/kohana/files/config.md
@@ -0,0 +1,95 @@
+# Config Files
+
+Configuration files are used to store any kind of configuration needed for a module, class, or anything else you want. They are plain PHP files, stored in the `config/` directory, which return an associative array:
+
+ <?php defined('SYSPATH') or die('No direct script access.');
+
+ return array(
+ 'setting' => 'value',
+ 'options' => array(
+ 'foo' => 'bar',
+ ),
+ );
+
+If the above configuration file was called `myconf.php`, you could access it using:
+
+ $config = Kohana::config('myconf');
+ $options = $config['options'];
+
+[Kohana::config] also provides a shortcut for accessing individual keys from configuration arrays using "dot paths" similar to [Arr::path].
+
+Get the "options" array:
+
+ $options = Kohana::config('myconf.options');
+
+Get the "foo" key from the "options" array:
+
+ $foo = Kohana::config('myconf.options.foo');
+
+Configuration arrays can also be accessed as objects, if you prefer that method:
+
+ $options = Kohana::config('myconf')->options;
+
+Please note that you can only access the top level of keys as object properties, all child keys must be accessed using standard array syntax:
+
+ $foo = Kohana::config('myconf')->options['foo'];
+
+## Merge
+
+Configuration files are slightly different from most other files within the [cascading filesystem](files) in that they are **merged** rather than overloaded. This means that all configuration files with the same file path are combined to produce the final configuration. The end result is that you can overload *individual* settings rather than duplicating an entire file.
+
+For example, if we wanted to change something in some file
+
+ [TODO]
+
+TODO exmaple of adding something to inflector
+
+## Creating your own config files
+
+Let's say we want a config file to store and easily change things like the title of a website, or the google analytics code. We would create a config file, let's call it `site.php`:
+
+ // config/site.php
+
+ <?php defined('SYSPATH') or die('No direct script access.');
+
+ return array(
+ 'title' => 'Our Shiny Website',
+ 'analytics' => FALSE, // analytics code goes here, set to FALSE to disable
+ );
+
+We could now call `Kohana::config('site.title')` to get the site name, and `Kohana::config('site.analytics')` to get the analytics code.
+
+Let's say we want an archive of versions of some software. We could use config files to store each version, and include links to download, documentation, and issue tracking.
+
+ // config/versions.php
+
+ <?php defined('SYSPATH') or die('No direct script access.');
+
+ return array(
+ '1.0.0' => array(
+ 'codename' => 'Frog',
+ 'download' => 'files/ourapp-1.0.0.tar.gz',
+ 'documentation' => 'docs/1.0.0',
+ 'released' => '06/05/2009',
+ 'issues' => 'link/to/bug/tracker',
+ ),
+ '1.1.0' => array(
+ 'codename' => 'Lizard',
+ 'download' => 'files/ourapp-1.1.0.tar.gz',
+ 'documentation' => 'docs/1.1.0',
+ 'released' => '10/15/2009',
+ 'issues' => 'link/to/bug/tracker',
+ ),
+ /// ... etc ...
+ );
+
+You could then do the following:
+
+ // In your controller
+ $view->versions = Kohana::config('versions');
+
+ // In your view:
+ foreach ($versions as $version)
+ {
+ // echo some html to display each version
+ }
View
1  guide/kohana/files/i18n.md
@@ -0,0 +1 @@
+Discuss the format of i18n files, and how to use them.
View
5 guide/kohana/files/messages.md
@@ -0,0 +1,5 @@
+<http://kohanaframework.org/guide/using.messages>
+
+Add that message files can be in subfolders, and you can use dot notation to retreive an array path: `Kohana::message('folder/subfolder/file','array.subarray.key')`
+
+Also reinforce that messages are merged by the cascade, not overwritten.
View
26 guide/kohana/flow.md
@@ -0,0 +1,26 @@
+# Request Flow
+
+Every application follows the same flow:
+
+1. Application starts from `index.php`.
+ 1. The application, module, and system paths are set. (`APPPATH`, `MODPATH`, and `SYSPATH`)
+ 2. Error reporting levels are set.
+ 3. Install file is loaded, if it exists.
+ 4. The [Kohana] class is loaded.
+ 5. The bootstrap file, `APPPATH/bootstrap.php`, is included.
+2. Once we are in `bootstrap.php`:
+ 7. [Kohana::init] is called, which sets up error handling, caching, and logging.
+ 8. [Kohana_Config] readers and [Kohana_Log] writers are attached.
+ 9. [Kohana::modules] is called to enable additional modules.
+ * Module paths are added to the [cascading filesystem](files).
+ * Includes each module's `init.php` file, if it exists.
+ * The `init.php` file can perform additional environment setup, including adding routes.
+ 10. [Route::set] is called multiple times to define the [application routes](routing).
+ 11. [Request::instance] is called to start processing the request.
+ 1. Checks each route that has been set until a match is found.
+ 2. Creates the controller instance and passes the request to it.
+ 3. Calls the [Controller::before] method.
+ 4. Calls the controller action, which generates the request response.
+ 5. Calls the [Controller::after] method.
+ * The above 5 steps can be repeated multiple times when using [HMVC sub-requests](requests).
+ 12. The main [Request] response is displayed
View
135 guide/kohana/fragments.md
@@ -0,0 +1,135 @@
+# Fragments
+
+Fragments are a quick and simple way to cache HTML or other output. Fragments are not useful for caching objects or raw database results, in which case you should use a more robust caching method, which can be achieved with the [Cache module](../cache). Fragments use [Kohana::cache()] and will be placed in the cache directory (`application/cache` by default).
+
+You should use Fragment (or any caching solution) when reading the cache is faster than reprocessing the result. Reading and parsing a remote file, parsing a complicated template, calculating something, etc.
+
+Fragments are typically used in view files.
+
+## Usage
+
+Fragments are used by calling [Fragment::load()] in an `if` statement at the beginning of what you want cached, and [Fragment::save()] at the end. They use [output buffering](http://www.php.net/manual/en/function.ob-start.php) to capture the output between the two function calls.
+
+You can specify the lifetime (in seconds) of the Fragment using the second parameter of [Fragment::load()]. The default lifetime is 30 seconds. You can use the [Date] helper to make more readable times.
+
+Fragments will store a different cache for each language (using [I18n]) if you pass `true` as the third parameter to [Fragment::load()];
+
+You can force the deletion of a Fragment using [Fragment::delete()], or specify a lifetime of 0.
+
+~~~
+// Cache for 5 minutes, and cache each language
+if ( ! Fragment::load('foobar', Date::MINUTE * 5, true))
+{
+ // Anything that is echo'ed here will be saved
+ Fragment::save();
+}
+~~~
+
+## Example: Calculating Pi
+
+In this example we will calculate pi to 1000 places, and cache the result using a fragment. The first time you run this it will probably take a few seconds, but subsequent loads will be much faster, until the fragment lifetime runs out.
+
+~~~
+if ( ! Fragment::load('pi1000', Date::HOUR * 4))
+{
+ // Change function nesting limit
+ ini_set('xdebug.max_nesting_level',1000);
+
+ // Source: http://mgccl.com/2007/01/22/php-calculate-pi-revisited
+ function bcfact($n)
+ {
+ return ($n == 0 || $n== 1) ? 1 : bcmul($n,bcfact($n-1));
+ }
+ function bcpi($precision)
+ {
+ $num = 0;$k = 0;
+ bcscale($precision+3);
+ $limit = ($precision+3)/14;
+ while($k < $limit)
+ {
+ $num = bcadd($num, bcdiv(bcmul(bcadd('13591409',bcmul('545140134', $k)),bcmul(bcpow(-1, $k), bcfact(6*$k))),bcmul(bcmul(bcpow('640320',3*$k+1),bcsqrt('640320')), bcmul(bcfact(3*$k), bcpow(bcfact($k),3)))));
+ ++$k;
+ }
+ return bcdiv(1,(bcmul(12,($num))),$precision);
+ }
+
+ echo bcpi(1000);
+
+ Fragment::save();
+}
+
+echo View::factory('profiler/stats');
+
+?>
+~~~
+
+## Example: Recent Wikipedia edits
+
+In this example we will use the [Feed] class to retrieve and parse an RSS feed of recent edits to [http://en.wikipedia.org](http://en.wikipedia.org), then use Fragment to cache the results.
+
+~~~
+$feed = "http://en.wikipedia.org/w/index.php?title=Special:RecentChanges&feed=rss";
+$limit = 50;
+
+// Displayed feeds are cached for 30 seconds (default)
+if ( ! Fragment::load('rss:'.$feed)):
+
+ // Parse the feed
+ $items = Feed::parse($feed, $limit);
+
+ foreach ($items as $item):
+
+ // Convert $item to object
+ $item = (object) $item;
+
+ echo HTML::anchor($item->link,$item->title);
+
+ ?>
+ <blockquote>
+ <p>author: <?php echo $item->creator ?></p>
+ <p>date: <?php echo $item->pubDate ?></p>
+ </blockquote>
+ <?php
+
+ endforeach;
+
+ Fragment::save();
+
+endif;
+
+echo View::factory('profiler/stats');
+~~~
+
+## Example: Nested Fragments
+
+You can nest fragments with different lifetimes to provide more specific control. For example, let's say your page has lots of dynamic content so we want to cache it with a lifetime of five minutes, but one of the pieces takes much longer to generate, and only changes every hour anyways. No reason to generate it every 5 minutes, so we will use a nested fragment.
+
+[!!] If a nested fragment has a shorter lifetime than the parent, it will only get processed when the parent has expired.
+
+~~~
+// Cache homepage for five minutes
+if ( ! Fragment::load('homepage', Date::MINUTE * 5)):
+
+ echo "<p>Home page stuff</p>";
+
+ // Pretend like we are actually doing something :)
+ sleep(2);
+
+ // Cache this every hour since it doesn't change as often
+ if ( ! Fragment::load('homepage-subfragment', Date::HOUR)):
+
+ echo "<p>Home page special thingy</p>";
+
+ // Pretend like this takes a long time
+ sleep(5);
+
+ Fragment::save(); endif;
+
+ echo "<p>More home page stuff</p>";
+
+ Fragment::save();
+
+endif;
+
+echo View::factory('profiler/stats');
+~~~
View
53 guide/kohana/helpers.md
@@ -0,0 +1,53 @@
+# Helpers
+
+Kohana comes with many static helper functions to make certain tasks easier.
+
+You can make your own helpers by simply making a class and putting it in the `classes` directory, and you can also extend any helper to modify or add new functions using transparent extension.
+
+ - **[Arr]** - Array functions. Get an array key or default to a set value, get an array key by path, etc.
+
+ - **[CLI]** - Parse command line options.
+
+ - **[Cookie]** - Covered in more detail on the [Cookies](cookies) page.
+
+ - **[Date]** - Useful date functions and constants. Time between two dates, convert between am/pm and military, date offset, etc.
+
+ - **[Encrypt]** - Covered in more detail on the [Security](security) page.
+
+ - **[Feed]** - Parse and create RSS feeds.
+
+ - **[File]** - Get file type by mime, split and merge a file into small pieces.
+
+ - **[Form]** - Create HTML form elements.
+
+ - **[Fragment]** - Simple file based caching. Covered in more detail on the [Fragments](fragments) page.
+
+ - **[HTML]** - Useful HTML functions. Encode, obfuscate, create script, anchor, and image tags, etc.
+
+ - **[I18n]** - Internationalization helper for creating multilanguage sites.
+
+ - **[Inflector]** - Change a word into plural or singular form, camelize or humanize a phrase, etc.
+
+ - **[Kohana]** - The Kohana class is also a helper. Debug variables (like print_r but better), file loading, etc.
+
+ - **[Num]** - Provides locale aware formating and english ordinals (th, st, nd, etc).
+
+ - **[Profiler]** - Covered in more detail on the [Profiling](profiling) page.
+
+ - **[Remote]** - Remote server access helper using [CURL](http://php.net/curl).
+
+ - **[Request]** - Get the current request url, create expire tags, send a file, get the user agent, etc.
+
+ - **[Route]** - Create routes, create an internal link using a route.
+
+ - **[Security]** - Covered in more detail on the [Security](security) page.
+
+ - **[Session]** - Covered in more detail on the [Sessions](sessions) page.
+
+ - **[Text]** - Autolink, prevent window words, convert a number to text, etc.
+
+ - **[URL]** - Create a relative or absolute URL, make a URL-safe title, etc.
+
+ - **[UTF8]** - Provides multi-byte aware string functions like strlen, strpos, substr, etc.
+
+ - **[Upload]** - Helper for uploading files from a form.
View
19 guide/kohana/index.md
@@ -0,0 +1,19 @@
+# What is Kohana?
+
+Kohana is an open source, [object oriented](http://wikipedia.org/wiki/Object-Oriented_Programming) [MVC](http://wikipedia.org/wiki/Model–View–Controller "Model View Controller") [web framework](http://wikipedia.org/wiki/Web_Framework) built using [PHP5](http://php.net/manual/intro-whatis "PHP Hypertext Preprocessor") by a team of volunteers that aims to be swift, secure, and small.
+
+[!!] Kohana is licensed under a [BSD license](http://kohanaframework.org/license), so you can legally use it for any kind of open source, commercial, or personal project.
+
+## What makes Kohana great?
+
+Anything can be extended using the unique [filesystem](about.filesystem) design, little or no [configuration](about.configuration) is necessary, [error handling](debugging.errors) helps locate the source of errors quickly, and [debugging](debugging) and [profiling](debugging.profiling) provide insight into the application.
+
+To help secure your applications, tools for [XSS removal](security.xss), [input validation](security.validation), [signed cookies](security.cookies), [form](security.forms) and [HTML](security.html) generators are all included. The [database](security.database) layer provides protection against [SQL injection](http://wikipedia.org/wiki/SQL_Injection). Of course, all official code is carefully written and reviewed for security.
+
+## Contribute to the Documentation
+
+We are working very hard to provide complete documentation. To help improve the guide, please [fork the userguide](http://github.com/kohana/userguide), make your changes, and send a pull request. If you are not familiar with git, you can also submit a [feature request](http://dev.kohanaframework.org/projects/kohana3/issues) (requires registration).
+
+## Unofficial Documentation
+
+If you are having trouble finding an answer here, have a look through the [unofficial wiki](http://kerkness.ca/wiki/doku.php). Your answer may also be found by searching the [forum](http://forum.kohanaphp.com/) or [stackoverflow](http://stackoverflow.com/questions/tagged/kohana) followed by asking your question on either. Additionally, you can chat with the community of developers on the freenode [#kohana](irc://irc.freenode.net/kohana) IRC channel.
View
33 guide/kohana/install.md
@@ -0,0 +1,33 @@
+# Installation
+
+1. Download the latest **stable** release from the [Kohana website](http://kohanaframework.org/).
+2. Unzip the downloaded package to create a `kohana` directory.
+3. Upload the contents of this folder to your webserver.
+4. Open `application/bootstrap.php` and make the following changes:
+ - Set the default [timezone](http://php.net/timezones) for your application.
+ - Set the `base_url` in the [Kohana::init] call to reflect the location of the kohana folder on your server relative to the document root.
+6. Make sure the `application/cache` and `application/logs` directories are writable by the web server.
+7. Test your installation by opening the URL you set as the `base_url` in your favorite browser.
+
+[!!] Depending on your platform, the installation's subdirs may have lost their permissions thanks to zip extraction. Chmod them all to 755 by running `find . -type d -exec chmod 0755 {} \;` from the root of your Kohana installation.
+
+You should see the installation page. If it reports any errors, you will need to correct them before continuing.
+
+![Install Page](install.png "Example of install page")
+
+Once your install page reports that your environment is set up correctly you need to either rename or delete `install.php` in the root directory. Kohana is now installed and you should see the output of the welcome controller:
+
+![Welcome Page](welcome.png "Example of welcome page")
+
+## Installing Kohana 3.0 From GitHub
+
+The [source code](http://github.com/kohana/kohana) for Kohana 3.0 is hosted with [GitHub](http://github.com). To install Kohana using the github source code first you need to install git. Visit [http://help.github.com](http://help.github.com) for details on how to install git on your platform.
+
+To install the last stable release of Kohana using git run these commands:
+
+ git clone git://github.com/kohana/kohana.git
+ cd kohana/
+ git submodule init
+ git submodule update
+
+[!!] For more information on using Git and Kohana see the [Working with Git](tutorials/git) tutorial.
View
48 guide/kohana/menu.md
@@ -0,0 +1,48 @@