├── .gitignore ├── .travis.yml ├── CONTRIBUTING.md ├── README.md ├── classes ├── Arr.php ├── Config.php ├── Config │ ├── File.php │ └── Group.php ├── Controller.php ├── Controller │ └── Template.php ├── Cookie.php ├── Date.php ├── Debug.php ├── Encrypt.php ├── Feed.php ├── File.php ├── Form.php ├── Fragment.php ├── HTML.php ├── HTTP.php ├── HTTP │ ├── Exception.php │ ├── Exception │ │ ├── 300.php │ │ ├── 301.php │ │ ├── 302.php │ │ ├── 303.php │ │ ├── 304.php │ │ ├── 305.php │ │ ├── 307.php │ │ ├── 400.php │ │ ├── 401.php │ │ ├── 402.php │ │ ├── 403.php │ │ ├── 404.php │ │ ├── 405.php │ │ ├── 406.php │ │ ├── 407.php │ │ ├── 408.php │ │ ├── 409.php │ │ ├── 410.php │ │ ├── 411.php │ │ ├── 412.php │ │ ├── 413.php │ │ ├── 414.php │ │ ├── 415.php │ │ ├── 416.php │ │ ├── 417.php │ │ ├── 500.php │ │ ├── 501.php │ │ ├── 502.php │ │ ├── 503.php │ │ ├── 504.php │ │ ├── 505.php │ │ ├── Expected.php │ │ └── Redirect.php │ ├── Header.php │ ├── Message.php │ ├── Request.php │ └── Response.php ├── I18n.php ├── Inflector.php ├── Kohana.php ├── Kohana │ ├── Arr.php │ ├── Config.php │ ├── Config │ │ ├── File.php │ │ ├── File │ │ │ └── Reader.php │ │ ├── Group.php │ │ ├── Reader.php │ │ ├── Source.php │ │ └── Writer.php │ ├── Controller.php │ ├── Controller │ │ └── Template.php │ ├── Cookie.php │ ├── Core.php │ ├── Date.php │ ├── Debug.php │ ├── Encrypt.php │ ├── Exception.php │ ├── Feed.php │ ├── File.php │ ├── Form.php │ ├── Fragment.php │ ├── HTML.php │ ├── HTTP.php │ ├── HTTP │ │ ├── Exception.php │ │ ├── Exception │ │ │ ├── 300.php │ │ │ ├── 301.php │ │ │ ├── 302.php │ │ │ ├── 303.php │ │ │ ├── 304.php │ │ │ ├── 305.php │ │ │ ├── 307.php │ │ │ ├── 400.php │ │ │ ├── 401.php │ │ │ ├── 402.php │ │ │ ├── 403.php │ │ │ ├── 404.php │ │ │ ├── 405.php │ │ │ ├── 406.php │ │ │ ├── 407.php │ │ │ ├── 408.php │ │ │ ├── 409.php │ │ │ ├── 410.php │ │ │ ├── 411.php │ │ │ ├── 412.php │ │ │ ├── 413.php │ │ │ ├── 414.php │ │ │ ├── 415.php │ │ │ ├── 416.php │ │ │ ├── 417.php │ │ │ ├── 500.php │ │ │ ├── 501.php │ │ │ ├── 502.php │ │ │ ├── 503.php │ │ │ ├── 504.php │ │ │ ├── 505.php │ │ │ ├── Expected.php │ │ │ └── Redirect.php │ │ ├── Header.php │ │ ├── Message.php │ │ ├── Request.php │ │ └── Response.php │ ├── I18n.php │ ├── Inflector.php │ ├── Kohana │ │ └── Exception.php │ ├── Log.php │ ├── Log │ │ ├── File.php │ │ ├── StdErr.php │ │ ├── StdOut.php │ │ ├── Syslog.php │ │ └── Writer.php │ ├── Model.php │ ├── Num.php │ ├── Profiler.php │ ├── Request.php │ ├── Request │ │ ├── Client.php │ │ ├── Client │ │ │ ├── Curl.php │ │ │ ├── External.php │ │ │ ├── HTTP.php │ │ │ ├── Internal.php │ │ │ ├── Recursion │ │ │ │ └── Exception.php │ │ │ └── Stream.php │ │ └── Exception.php │ ├── Response.php │ ├── Route.php │ ├── Security.php │ ├── Session.php │ ├── Session │ │ ├── Cookie.php │ │ ├── Exception.php │ │ └── Native.php │ ├── Text.php │ ├── URL.php │ ├── UTF8.php │ ├── UTF8 │ │ └── Exception.php │ ├── Upload.php │ ├── Valid.php │ ├── Validation.php │ ├── Validation │ │ └── Exception.php │ ├── View.php │ └── View │ │ └── Exception.php ├── Log.php ├── Log │ ├── File.php │ ├── StdErr.php │ ├── StdOut.php │ ├── Syslog.php │ └── Writer.php ├── Model.php ├── Num.php ├── Profiler.php ├── Request.php ├── Request │ ├── Client.php │ ├── Client │ │ ├── Curl.php │ │ ├── External.php │ │ ├── HTTP.php │ │ ├── Internal.php │ │ ├── Recursion │ │ │ └── Exception.php │ │ └── Stream.php │ └── Exception.php ├── Response.php ├── Route.php ├── Security.php ├── Session.php ├── Session │ ├── Cookie.php │ ├── Exception.php │ └── Native.php ├── Text.php ├── URL.php ├── UTF8.php ├── UTF8 │ └── Exception.php ├── Upload.php ├── Valid.php ├── Validation.php ├── Validation │ └── Exception.php ├── View.php └── View │ └── Exception.php ├── composer.json ├── config ├── credit_cards.php ├── curl.php ├── encrypt.php ├── inflector.php ├── mimes.php ├── session.php ├── url.php ├── user_agents.php └── userguide.php ├── guide └── kohana │ ├── autoloading.md │ ├── bootstrap.md │ ├── config.md │ ├── controllers.md │ ├── conventions.md │ ├── cookies.md │ ├── debugging.md │ ├── errors.md │ ├── extension.md │ ├── files.md │ ├── files │ ├── classes.md │ ├── config.md │ ├── i18n.md │ └── messages.md │ ├── flow.md │ ├── fragments.md │ ├── helpers.md │ ├── index.md │ ├── install.md │ ├── menu.md │ ├── modules.md │ ├── mvc.md │ ├── mvc │ ├── controllers.md │ ├── models.md │ └── views.md │ ├── profiling.md │ ├── requests.md │ ├── routing.md │ ├── security.md │ ├── security │ ├── cookies.md │ ├── database.md │ ├── deploying.md │ ├── encryption.md │ ├── validation.md │ └── xss.md │ ├── sessions.md │ ├── tips.md │ ├── tutorials │ ├── clean-urls.md │ ├── error-pages.md │ ├── git.md │ ├── hello-world.md │ ├── library-kohana.md │ ├── sharing-kohana.md │ └── simple-mvc.md │ ├── upgrading-from-3-3-3-1.md │ └── upgrading.md ├── i18n ├── en.php ├── es.php └── fr.php ├── koharness.php ├── media └── guide │ └── kohana │ ├── cascading_filesystem.png │ ├── hello_world_1.png │ ├── hello_world_2.png │ ├── hello_world_2_error.png │ ├── install.png │ └── welcome.png ├── messages ├── tests │ └── validation │ │ └── error_type_check.php └── validation.php ├── tests ├── kohana │ ├── ArrTest.php │ ├── Config │ │ ├── File │ │ │ └── ReaderTest.php │ │ └── GroupTest.php │ ├── ConfigTest.php │ ├── CookieTest.php │ ├── CoreTest.php │ ├── DateTest.php │ ├── DebugTest.php │ ├── EncryptTest.php │ ├── ExceptionTest.php │ ├── FeedTest.php │ ├── FileTest.php │ ├── FormTest.php │ ├── HTMLTest.php │ ├── HTTPTest.php │ ├── Http │ │ └── HeaderTest.php │ ├── I18nTest.php │ ├── InflectorTest.php │ ├── LogTest.php │ ├── ModelTest.php │ ├── NumTest.php │ ├── RequestTest.php │ ├── ResponseTest.php │ ├── RouteTest.php │ ├── SecurityTest.php │ ├── SessionTest.php │ ├── TextTest.php │ ├── URLTest.php │ ├── UTF8Test.php │ ├── UploadTest.php │ ├── ValidTest.php │ ├── ValidationTest.php │ ├── ViewTest.php │ └── request │ │ ├── ClientTest.php │ │ └── client │ │ ├── ExternalTest.php │ │ └── InternalTest.php └── test_data │ ├── callback_routes.php │ ├── feeds │ ├── activity.atom │ └── example.rss20 │ ├── github.png │ ├── message_tests │ ├── bottom_module │ │ └── messages │ │ │ └── kohana_core_message_tests.php │ └── top_module │ │ └── messages │ │ └── kohana_core_message_tests.php │ └── views │ └── test.css.php ├── utf8 ├── from_unicode.php ├── ltrim.php ├── ord.php ├── rtrim.php ├── str_ireplace.php ├── str_pad.php ├── str_split.php ├── strcasecmp.php ├── strcspn.php ├── stristr.php ├── strlen.php ├── strpos.php ├── strrev.php ├── strrpos.php ├── strspn.php ├── strtolower.php ├── strtoupper.php ├── substr.php ├── substr_replace.php ├── to_unicode.php ├── transliterate_to_ascii.php ├── trim.php ├── ucfirst.php └── ucwords.php └── views ├── kohana ├── error.php ├── generate_logo.php └── logo.php └── profiler ├── stats.php └── style.css /.gitignore: -------------------------------------------------------------------------------- 1 | *~ 2 | *.swp 3 | /composer.lock 4 | /vendor/* 5 | /koharness_bootstrap.php 6 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | sudo: false 2 | 3 | language: php 4 | 5 | # Only build the main develop/master branches - feature branches will be covered by PRs 6 | branches: 7 | only: 8 | - /^[0-9\.]+\/(develop|master)$/ 9 | 10 | cache: 11 | directories: 12 | - $HOME/.composer/cache/files 13 | 14 | php: 15 | - 5.3 16 | - 5.4 17 | - 5.5 18 | - 5.6 19 | - 7.0 20 | - hhvm 21 | 22 | matrix: 23 | include: 24 | - php: 5.3 25 | env: 'COMPOSER_PHPUNIT="lowest"' 26 | 27 | before_script: 28 | - composer self-update 29 | - COMPOSER_ROOT_VERSION=3.3.x-dev composer install --prefer-dist --no-interaction 30 | - if [ "$COMPOSER_PHPUNIT" = "lowest" ]; then COMPOSER_ROOT_VERSION=3.3.x-dev composer update --prefer-lowest --with-dependencies phpunit/phpunit; fi; 31 | - vendor/bin/koharness 32 | 33 | script: 34 | - cd /tmp/koharness && ./vendor/bin/phpunit --bootstrap=modules/unittest/bootstrap.php modules/unittest/tests.php 35 | 36 | notifications: 37 | email: false 38 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | Please refer to the CONTRIBUTING file located under the [kohana](https://github.com/kohana/kohana) repo. -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Kohana PHP Framework - core 2 | 3 | | ver | Stable | Develop | 4 | |-------|------------------------------------------------------------------------------------------------------------------------------|--------------------------------------------------------------------------------------------------------------------------------| 5 | | 3.3.x | [![Build Status - 3.3/master](https://travis-ci.org/kohana/core.svg?branch=3.3%2Fmaster)](https://travis-ci.org/kohana/core) | [![Build Status - 3.3/develop](https://travis-ci.org/kohana/core.svg?branch=3.3%2Fdevelop)](https://travis-ci.org/kohana/core) | 6 | | 3.4.x | [![Build Status - 3.4/master](https://travis-ci.org/kohana/core.svg?branch=3.4%2Fmaster)](https://travis-ci.org/kohana/core) | [![Build Status - 3.4/develop](https://travis-ci.org/kohana/core.svg?branch=3.4%2Fdevelop)](https://travis-ci.org/kohana/core) | 7 | 8 | This is the core package for the [Kohana](http://kohanaframework.org/) object oriented HMVC framework built using PHP5. 9 | It aims to be swift, secure, and small. 10 | 11 | Released under a [BSD license](http://kohanaframework.org/license), Kohana can be used legally for any open source, 12 | commercial, or personal project. 13 | 14 | ## Documentation and installation 15 | 16 | See the [sample application repository](https://github.com/kohana/kohana) for full readme and contributing information. 17 | You will usually add `kohana/core` as a dependency in your own project's composer.json to install and work with this 18 | package. 19 | 20 | ## Installation for development 21 | 22 | To work on this package, you'll want to install it with composer to get the required dependencies. Note that there are 23 | currently circular dependencies between this module and kohana/unittest. These may cause you problems if you are working 24 | on a feature branch, because composer may not be able to figure out which version of kohana core you have. 25 | 26 | To work around this, run composer like: `COMPOSER_ROOT_VERSION=3.3.x-dev composer install`. This tells composer that the 27 | current checkout is a 3.3.* development version. Obviously change the argument if your branch is based on a different 28 | version. 29 | 30 | After installing the dependencies, you'll need a skeleton Kohana application before you can run the unit tests etc. The 31 | simplest way to do this is to use kohana/koharness to build a bare project in `/tmp/koharness`. 32 | 33 | If in doubt, check the install and test steps in the [.travis.yml](.travis.yml) file. 34 | -------------------------------------------------------------------------------- /classes/Arr.php: -------------------------------------------------------------------------------- 1 | _directory = trim($directory, '/'); 29 | } 30 | 31 | /** 32 | * Load and merge all of the configuration files in this group. 33 | * 34 | * $config->load($name); 35 | * 36 | * @param string $group configuration group name 37 | * @return $this current object 38 | * @uses Kohana::load 39 | */ 40 | public function load($group) 41 | { 42 | $config = array(); 43 | 44 | if ($files = Kohana::find_file($this->_directory, $group, NULL, TRUE)) 45 | { 46 | foreach ($files as $file) 47 | { 48 | // Merge each file to the configuration array 49 | $config = Arr::merge($config, Kohana::load($file)); 50 | } 51 | } 52 | 53 | return $config; 54 | } 55 | 56 | } 57 | -------------------------------------------------------------------------------- /classes/Kohana/Config/Group.php: -------------------------------------------------------------------------------- 1 | _parent_instance = $instance; 44 | $this->_group_name = $group; 45 | 46 | parent::__construct($config, ArrayObject::ARRAY_AS_PROPS); 47 | } 48 | 49 | /** 50 | * Return the current group in serialized form. 51 | * 52 | * echo $config; 53 | * 54 | * @return string 55 | */ 56 | public function __toString() 57 | { 58 | return serialize($this->getArrayCopy()); 59 | } 60 | 61 | /** 62 | * Alias for getArrayCopy() 63 | * 64 | * @return array Array copy of the group's config 65 | */ 66 | public function as_array() 67 | { 68 | return $this->getArrayCopy(); 69 | } 70 | 71 | /** 72 | * Returns the config group's name 73 | * 74 | * @return string The group name 75 | */ 76 | public function group_name() 77 | { 78 | return $this->_group_name; 79 | } 80 | 81 | /** 82 | * Get a variable from the configuration or return the default value. 83 | * 84 | * $value = $config->get($key); 85 | * 86 | * @param string $key array key 87 | * @param mixed $default default value 88 | * @return mixed 89 | */ 90 | public function get($key, $default = NULL) 91 | { 92 | return $this->offsetExists($key) ? $this->offsetGet($key) : $default; 93 | } 94 | 95 | /** 96 | * Sets a value in the configuration array. 97 | * 98 | * $config->set($key, $new_value); 99 | * 100 | * @param string $key array key 101 | * @param mixed $value array value 102 | * @return $this 103 | */ 104 | public function set($key, $value) 105 | { 106 | $this->offsetSet($key, $value); 107 | 108 | return $this; 109 | } 110 | 111 | /** 112 | * Overrides ArrayObject::offsetSet() 113 | * This method is called when config is changed via 114 | * 115 | * $config->var = 'asd'; 116 | * 117 | * // OR 118 | * 119 | * $config['var'] = 'asd'; 120 | * 121 | * @param string $key The key of the config item we're changing 122 | * @param mixed $value The new array value 123 | */ 124 | public function offsetSet($key, $value) 125 | { 126 | $this->_parent_instance->_write_config($this->_group_name, $key, $value); 127 | 128 | return parent::offsetSet($key, $value); 129 | } 130 | 131 | } 132 | -------------------------------------------------------------------------------- /classes/Kohana/Config/Reader.php: -------------------------------------------------------------------------------- 1 | auto_render === TRUE) 31 | { 32 | // Load the template 33 | $this->template = View::factory($this->template); 34 | } 35 | } 36 | 37 | /** 38 | * Assigns the template [View] as the request response. 39 | */ 40 | public function after() 41 | { 42 | if ($this->auto_render === TRUE) 43 | { 44 | $this->response->body($this->template->render()); 45 | } 46 | 47 | parent::after(); 48 | } 49 | 50 | } 51 | -------------------------------------------------------------------------------- /classes/Kohana/Exception.php: -------------------------------------------------------------------------------- 1 | $user)); 35 | * 36 | * @param string $message status message, custom content to display with error 37 | * @param array $variables translation variables 38 | * @return void 39 | */ 40 | public function __construct($message = NULL, array $variables = NULL, Exception $previous = NULL) 41 | { 42 | parent::__construct($message, $variables, $this->_code, $previous); 43 | } 44 | 45 | /** 46 | * Store the Request that triggered this exception. 47 | * 48 | * @param Request $request Request object that triggered this exception. 49 | * @return HTTP_Exception 50 | */ 51 | public function request(Request $request = NULL) 52 | { 53 | if ($request === NULL) 54 | return $this->_request; 55 | 56 | $this->_request = $request; 57 | 58 | return $this; 59 | } 60 | 61 | /** 62 | * Generate a Response for the current Exception 63 | * 64 | * @uses Kohana_Exception::response() 65 | * @return Response 66 | */ 67 | public function get_response() 68 | { 69 | return Kohana_Exception::response($this); 70 | } 71 | 72 | } 73 | -------------------------------------------------------------------------------- /classes/Kohana/HTTP/Exception/300.php: -------------------------------------------------------------------------------- 1 | headers('Location'); 19 | 20 | $this->headers('Location', $uri); 21 | 22 | return $this; 23 | } 24 | 25 | /** 26 | * Validate this exception contains everything needed to continue. 27 | * 28 | * @throws Kohana_Exception 29 | * @return bool 30 | */ 31 | public function check() 32 | { 33 | if ($location = $this->headers('location') === NULL) 34 | throw new Kohana_Exception('A \'location\' must be specified for a redirect'); 35 | 36 | if (strpos($location, '://') === FALSE) 37 | throw new Kohana_Exception('An absolute URI to the proxy server must be specified'); 38 | 39 | return TRUE; 40 | } 41 | 42 | } 43 | -------------------------------------------------------------------------------- /classes/Kohana/HTTP/Exception/307.php: -------------------------------------------------------------------------------- 1 | headers('www-authenticate'); 19 | 20 | $this->headers('www-authenticate', $challenge); 21 | 22 | return $this; 23 | } 24 | 25 | /** 26 | * Validate this exception contains everything needed to continue. 27 | * 28 | * @throws Kohana_Exception 29 | * @return bool 30 | */ 31 | public function check() 32 | { 33 | if ($this->headers('www-authenticate') === NULL) 34 | throw new Kohana_Exception('A \'www-authenticate\' header must be specified for a HTTP 401 Unauthorized'); 35 | 36 | return TRUE; 37 | } 38 | 39 | } 40 | -------------------------------------------------------------------------------- /classes/Kohana/HTTP/Exception/402.php: -------------------------------------------------------------------------------- 1 | headers('allow', $methods); 23 | 24 | return $this; 25 | } 26 | 27 | /** 28 | * Validate this exception contains everything needed to continue. 29 | * 30 | * @throws Kohana_Exception 31 | * @return bool 32 | */ 33 | public function check() 34 | { 35 | if ($location = $this->headers('allow') === NULL) 36 | throw new Kohana_Exception('A list of allowed methods must be specified'); 37 | 38 | return TRUE; 39 | } 40 | 41 | } 42 | -------------------------------------------------------------------------------- /classes/Kohana/HTTP/Exception/406.php: -------------------------------------------------------------------------------- 1 | $user)); 26 | * 27 | * @param string $message status message, custom content to display with error 28 | * @param array $variables translation variables 29 | * @return void 30 | */ 31 | public function __construct($message = NULL, array $variables = NULL, Exception $previous = NULL) 32 | { 33 | parent::__construct($message, $variables, $previous); 34 | 35 | // Prepare our response object and set the correct status code. 36 | $this->_response = Response::factory() 37 | ->status($this->_code); 38 | } 39 | 40 | /** 41 | * Gets and sets headers to the [Response]. 42 | * 43 | * @see [Response::headers] 44 | * @param mixed $key 45 | * @param string $value 46 | * @return mixed 47 | */ 48 | public function headers($key = NULL, $value = NULL) 49 | { 50 | $result = $this->_response->headers($key, $value); 51 | 52 | if ( ! $result instanceof Response) 53 | return $result; 54 | 55 | return $this; 56 | } 57 | 58 | /** 59 | * Validate this exception contains everything needed to continue. 60 | * 61 | * @throws Kohana_Exception 62 | * @return bool 63 | */ 64 | public function check() 65 | { 66 | return TRUE; 67 | } 68 | 69 | /** 70 | * Generate a Response for the current Exception 71 | * 72 | * @uses Kohana_Exception::response() 73 | * @return Response 74 | */ 75 | public function get_response() 76 | { 77 | $this->check(); 78 | 79 | return $this->_response; 80 | } 81 | 82 | } 83 | -------------------------------------------------------------------------------- /classes/Kohana/HTTP/Exception/Redirect.php: -------------------------------------------------------------------------------- 1 | headers('Location'); 25 | 26 | if (strpos($uri, '://') === FALSE) 27 | { 28 | // Make the URI into a URL 29 | $uri = URL::site($uri, TRUE, ! empty(Kohana::$index_file)); 30 | } 31 | 32 | $this->headers('Location', $uri); 33 | 34 | return $this; 35 | } 36 | 37 | /** 38 | * Validate this exception contains everything needed to continue. 39 | * 40 | * @throws Kohana_Exception 41 | * @return bool 42 | */ 43 | public function check() 44 | { 45 | if ($this->headers('location') === NULL) 46 | throw new Kohana_Exception('A \'location\' must be specified for a redirect'); 47 | 48 | return TRUE; 49 | } 50 | 51 | } 52 | -------------------------------------------------------------------------------- /classes/Kohana/HTTP/Message.php: -------------------------------------------------------------------------------- 1 | status(404); 22 | * 23 | * // Get the current status 24 | * $status = $response->status(); 25 | * 26 | * @param integer $code Status to set to this response 27 | * @return mixed 28 | */ 29 | public function status($code = NULL); 30 | 31 | } 32 | -------------------------------------------------------------------------------- /classes/Kohana/Log/File.php: -------------------------------------------------------------------------------- 1 | Debug::path($directory))); 33 | } 34 | 35 | // Determine the directory path 36 | $this->_directory = realpath($directory).DIRECTORY_SEPARATOR; 37 | } 38 | 39 | /** 40 | * Writes each of the messages into the log file. The log file will be 41 | * appended to the `YYYY/MM/DD.log.php` file, where YYYY is the current 42 | * year, MM is the current month, and DD is the current day. 43 | * 44 | * $writer->write($messages); 45 | * 46 | * @param array $messages 47 | * @return void 48 | */ 49 | public function write(array $messages) 50 | { 51 | // Set the yearly directory name 52 | $directory = $this->_directory.date('Y'); 53 | 54 | if ( ! is_dir($directory)) 55 | { 56 | // Create the yearly directory 57 | mkdir($directory, 02777); 58 | 59 | // Set permissions (must be manually set to fix umask issues) 60 | chmod($directory, 02777); 61 | } 62 | 63 | // Add the month to the directory 64 | $directory .= DIRECTORY_SEPARATOR.date('m'); 65 | 66 | if ( ! is_dir($directory)) 67 | { 68 | // Create the monthly directory 69 | mkdir($directory, 02777); 70 | 71 | // Set permissions (must be manually set to fix umask issues) 72 | chmod($directory, 02777); 73 | } 74 | 75 | // Set the name of the log file 76 | $filename = $directory.DIRECTORY_SEPARATOR.date('d').EXT; 77 | 78 | if ( ! file_exists($filename)) 79 | { 80 | // Create the log file 81 | file_put_contents($filename, Kohana::FILE_SECURITY.' ?>'.PHP_EOL); 82 | 83 | // Allow anyone to write to log files 84 | chmod($filename, 0666); 85 | } 86 | 87 | foreach ($messages as $message) 88 | { 89 | // Write each message into the log file 90 | file_put_contents($filename, PHP_EOL.$this->format_message($message), FILE_APPEND); 91 | } 92 | } 93 | 94 | } 95 | -------------------------------------------------------------------------------- /classes/Kohana/Log/StdErr.php: -------------------------------------------------------------------------------- 1 | write($messages); 16 | * 17 | * @param array $messages 18 | * @return void 19 | */ 20 | public function write(array $messages) 21 | { 22 | foreach ($messages as $message) 23 | { 24 | // Writes out each message 25 | fwrite(STDERR, $this->format_message($message).PHP_EOL); 26 | } 27 | } 28 | 29 | } 30 | -------------------------------------------------------------------------------- /classes/Kohana/Log/StdOut.php: -------------------------------------------------------------------------------- 1 | write($messages); 17 | * 18 | * @param array $messages 19 | * @return void 20 | */ 21 | public function write(array $messages) 22 | { 23 | foreach ($messages as $message) 24 | { 25 | // Writes out each message 26 | fwrite(STDOUT, $this->format_message($message).PHP_EOL); 27 | } 28 | } 29 | 30 | } 31 | -------------------------------------------------------------------------------- /classes/Kohana/Log/Syslog.php: -------------------------------------------------------------------------------- 1 | _ident = $ident; 30 | 31 | // Open the connection to syslog 32 | openlog($this->_ident, LOG_CONS, $facility); 33 | } 34 | 35 | /** 36 | * Writes each of the messages into the syslog. 37 | * 38 | * @param array $messages 39 | * @return void 40 | */ 41 | public function write(array $messages) 42 | { 43 | foreach ($messages as $message) 44 | { 45 | syslog($message['level'], $message['body']); 46 | 47 | if (isset($message['additional']['exception'])) 48 | { 49 | syslog(Log_Writer::$strace_level, $message['additional']['exception']->getTraceAsString()); 50 | } 51 | } 52 | } 53 | 54 | /** 55 | * Closes the syslog connection 56 | * 57 | * @return void 58 | */ 59 | public function __destruct() 60 | { 61 | // Close connection to syslog 62 | closelog(); 63 | } 64 | 65 | } 66 | -------------------------------------------------------------------------------- /classes/Kohana/Log/Writer.php: -------------------------------------------------------------------------------- 1 | 'EMERGENCY', 33 | LOG_ALERT => 'ALERT', 34 | LOG_CRIT => 'CRITICAL', 35 | LOG_ERR => 'ERROR', 36 | LOG_WARNING => 'WARNING', 37 | LOG_NOTICE => 'NOTICE', 38 | LOG_INFO => 'INFO', 39 | LOG_DEBUG => 'DEBUG', 40 | ); 41 | 42 | /** 43 | * @var int Level to use for stack traces 44 | */ 45 | public static $strace_level = LOG_DEBUG; 46 | 47 | /** 48 | * Write an array of messages. 49 | * 50 | * $writer->write($messages); 51 | * 52 | * @param array $messages 53 | * @return void 54 | */ 55 | abstract public function write(array $messages); 56 | 57 | /** 58 | * Allows the writer to have a unique key when stored. 59 | * 60 | * echo $writer; 61 | * 62 | * @return string 63 | */ 64 | final public function __toString() 65 | { 66 | return spl_object_hash($this); 67 | } 68 | 69 | /** 70 | * Formats a log entry. 71 | * 72 | * @param array $message 73 | * @param string $format 74 | * @return string 75 | */ 76 | public function format_message(array $message, $format = "time --- level: body in file:line") 77 | { 78 | $message['time'] = Date::formatted_time('@'.$message['time'], Log_Writer::$timestamp, Log_Writer::$timezone, TRUE); 79 | $message['level'] = $this->_log_levels[$message['level']]; 80 | 81 | $string = strtr($format, array_filter($message, 'is_scalar')); 82 | 83 | if (isset($message['additional']['exception'])) 84 | { 85 | // Re-use as much as possible, just resetting the body to the trace 86 | $message['body'] = $message['additional']['exception']->getTraceAsString(); 87 | $message['level'] = $this->_log_levels[Log_Writer::$strace_level]; 88 | 89 | $string .= PHP_EOL.strtr($format, array_filter($message, 'is_scalar')); 90 | } 91 | 92 | return $string; 93 | } 94 | 95 | } 96 | -------------------------------------------------------------------------------- /classes/Kohana/Model.php: -------------------------------------------------------------------------------- 1 | HTTPRequest::METH_GET, 58 | HTTP_Request::HEAD => HTTPRequest::METH_HEAD, 59 | HTTP_Request::POST => HTTPRequest::METH_POST, 60 | HTTP_Request::PUT => HTTPRequest::METH_PUT, 61 | HTTP_Request::DELETE => HTTPRequest::METH_DELETE, 62 | HTTP_Request::OPTIONS => HTTPRequest::METH_OPTIONS, 63 | HTTP_Request::TRACE => HTTPRequest::METH_TRACE, 64 | HTTP_Request::CONNECT => HTTPRequest::METH_CONNECT, 65 | ); 66 | 67 | // Create an http request object 68 | $http_request = new HTTPRequest($request->uri(), $http_method_mapping[$request->method()]); 69 | 70 | if ($this->_options) 71 | { 72 | // Set custom options 73 | $http_request->setOptions($this->_options); 74 | } 75 | 76 | // Set headers 77 | $http_request->setHeaders($request->headers()->getArrayCopy()); 78 | 79 | // Set cookies 80 | $http_request->setCookies($request->cookie()); 81 | 82 | // Set query data (?foo=bar&bar=foo) 83 | $http_request->setQueryData($request->query()); 84 | 85 | // Set the body 86 | if ($request->method() == HTTP_Request::PUT) 87 | { 88 | $http_request->addPutData($request->body()); 89 | } 90 | else 91 | { 92 | $http_request->setBody($request->body()); 93 | } 94 | 95 | try 96 | { 97 | $http_request->send(); 98 | } 99 | catch (HTTPRequestException $e) 100 | { 101 | throw new Request_Exception($e->getMessage()); 102 | } 103 | catch (HTTPMalformedHeaderException $e) 104 | { 105 | throw new Request_Exception($e->getMessage()); 106 | } 107 | catch (HTTPEncodingException $e) 108 | { 109 | throw new Request_Exception($e->getMessage()); 110 | } 111 | 112 | // Build the response 113 | $response->status($http_request->getResponseCode()) 114 | ->headers($http_request->getResponseHeader()) 115 | ->cookie($http_request->getResponseCookies()) 116 | ->body($http_request->getResponseBody()); 117 | 118 | return $response; 119 | } 120 | 121 | } 122 | -------------------------------------------------------------------------------- /classes/Kohana/Request/Client/Internal.php: -------------------------------------------------------------------------------- 1 | execute(); 24 | * 25 | * @param Request $request 26 | * @return Response 27 | * @throws Kohana_Exception 28 | * @uses [Kohana::$profiling] 29 | * @uses [Profiler] 30 | */ 31 | public function execute_request(Request $request, Response $response) 32 | { 33 | // Create the class prefix 34 | $prefix = 'Controller_'; 35 | 36 | // Directory 37 | $directory = $request->directory(); 38 | 39 | // Controller 40 | $controller = $request->controller(); 41 | 42 | if ($directory) 43 | { 44 | // Add the directory name to the class prefix 45 | $prefix .= str_replace(array('\\', '/'), '_', trim($directory, '/')).'_'; 46 | } 47 | 48 | if (Kohana::$profiling) 49 | { 50 | // Set the benchmark name 51 | $benchmark = '"'.$request->uri().'"'; 52 | 53 | if ($request !== Request::$initial AND Request::$current) 54 | { 55 | // Add the parent request uri 56 | $benchmark .= ' « "'.Request::$current->uri().'"'; 57 | } 58 | 59 | // Start benchmarking 60 | $benchmark = Profiler::start('Requests', $benchmark); 61 | } 62 | 63 | // Store the currently active request 64 | $previous = Request::$current; 65 | 66 | // Change the current request to this request 67 | Request::$current = $request; 68 | 69 | // Is this the initial request 70 | $initial_request = ($request === Request::$initial); 71 | 72 | try 73 | { 74 | if ( ! class_exists($prefix.$controller)) 75 | { 76 | throw HTTP_Exception::factory(404, 77 | 'The requested URL :uri was not found on this server.', 78 | array(':uri' => $request->uri()) 79 | )->request($request); 80 | } 81 | 82 | // Load the controller using reflection 83 | $class = new ReflectionClass($prefix.$controller); 84 | 85 | if ($class->isAbstract()) 86 | { 87 | throw new Kohana_Exception( 88 | 'Cannot create instances of abstract :controller', 89 | array(':controller' => $prefix.$controller) 90 | ); 91 | } 92 | 93 | // Create a new instance of the controller 94 | $controller = $class->newInstance($request, $response); 95 | 96 | // Run the controller's execute() method 97 | $response = $class->getMethod('execute')->invoke($controller); 98 | 99 | if ( ! $response instanceof Response) 100 | { 101 | // Controller failed to return a Response. 102 | throw new Kohana_Exception('Controller failed to return a Response'); 103 | } 104 | } 105 | catch (HTTP_Exception $e) 106 | { 107 | // Store the request context in the Exception 108 | if ($e->request() === NULL) 109 | { 110 | $e->request($request); 111 | } 112 | 113 | // Get the response via the Exception 114 | $response = $e->get_response(); 115 | } 116 | catch (Exception $e) 117 | { 118 | // Generate an appropriate Response object 119 | $response = Kohana_Exception::_handler($e); 120 | } 121 | 122 | // Restore the previous request 123 | Request::$current = $previous; 124 | 125 | if (isset($benchmark)) 126 | { 127 | // Stop the benchmark 128 | Profiler::stop($benchmark); 129 | } 130 | 131 | // Return the response 132 | return $response; 133 | } 134 | 135 | } 136 | -------------------------------------------------------------------------------- /classes/Kohana/Request/Client/Recursion/Exception.php: -------------------------------------------------------------------------------- 1 | method() === HTTP_Request::GET) ? 'r' : 'r+'; 34 | 35 | // Process cookies 36 | if ($cookies = $request->cookie()) 37 | { 38 | $request->headers('cookie', http_build_query($cookies, NULL, '; ')); 39 | } 40 | 41 | // Get the message body 42 | $body = $request->body(); 43 | 44 | if (is_resource($body)) 45 | { 46 | $body = stream_get_contents($body); 47 | } 48 | 49 | // Set the content length 50 | $request->headers('content-length', (string) strlen($body)); 51 | 52 | list($protocol) = explode('/', $request->protocol()); 53 | 54 | // Create the context 55 | $options = array( 56 | strtolower($protocol) => array( 57 | 'method' => $request->method(), 58 | 'header' => (string) $request->headers(), 59 | 'content' => $body 60 | ) 61 | ); 62 | 63 | // Create the context stream 64 | $context = stream_context_create($options); 65 | 66 | stream_context_set_option($context, $this->_options); 67 | 68 | $uri = $request->uri(); 69 | 70 | if ($query = $request->query()) 71 | { 72 | $uri .= '?'.http_build_query($query, NULL, '&'); 73 | } 74 | 75 | $stream = fopen($uri, $mode, FALSE, $context); 76 | 77 | $meta_data = stream_get_meta_data($stream); 78 | 79 | // Get the HTTP response code 80 | $http_response = array_shift($meta_data['wrapper_data']); 81 | 82 | if (preg_match_all('/(\w+\/\d\.\d) (\d{3})/', $http_response, $matches) !== FALSE) 83 | { 84 | $protocol = $matches[1][0]; 85 | $status = (int) $matches[2][0]; 86 | } 87 | else 88 | { 89 | $protocol = NULL; 90 | $status = NULL; 91 | } 92 | 93 | // Get any exisiting response headers 94 | $response_header = $response->headers(); 95 | 96 | // Process headers 97 | array_map(array($response_header, 'parse_header_string'), array(), $meta_data['wrapper_data']); 98 | 99 | $response->status($status) 100 | ->protocol($protocol) 101 | ->body(stream_get_contents($stream)); 102 | 103 | // Close the stream after use 104 | fclose($stream); 105 | 106 | return $response; 107 | } 108 | 109 | } 110 | -------------------------------------------------------------------------------- /classes/Kohana/Request/Exception.php: -------------------------------------------------------------------------------- 1 | _name, NULL); 20 | } 21 | 22 | /** 23 | * @return null 24 | */ 25 | protected function _regenerate() 26 | { 27 | // Cookie sessions have no id 28 | return NULL; 29 | } 30 | 31 | /** 32 | * @return bool 33 | */ 34 | protected function _write() 35 | { 36 | return Cookie::set($this->_name, $this->__toString(), $this->_lifetime); 37 | } 38 | 39 | /** 40 | * @return bool 41 | */ 42 | protected function _restart() 43 | { 44 | return TRUE; 45 | } 46 | 47 | /** 48 | * @return bool 49 | */ 50 | protected function _destroy() 51 | { 52 | return Cookie::delete($this->_name); 53 | } 54 | 55 | } 56 | -------------------------------------------------------------------------------- /classes/Kohana/Session/Exception.php: -------------------------------------------------------------------------------- 1 | _lifetime, 47 | Cookie::$path, 48 | $session_cookie_domain, 49 | Cookie::$secure, 50 | Cookie::$httponly 51 | ); 52 | 53 | // Do not allow PHP to send Cache-Control headers 54 | session_cache_limiter(FALSE); 55 | 56 | // Set the session cookie name 57 | session_name($this->_name); 58 | 59 | if ($id) 60 | { 61 | // Set the session id 62 | session_id($id); 63 | } 64 | 65 | // Start the session 66 | session_start(); 67 | 68 | // Use the $_SESSION global for storing data 69 | $this->_data =& $_SESSION; 70 | 71 | return NULL; 72 | } 73 | 74 | /** 75 | * @return string 76 | */ 77 | protected function _regenerate() 78 | { 79 | // Regenerate the session id 80 | session_regenerate_id(); 81 | 82 | return session_id(); 83 | } 84 | 85 | /** 86 | * @return bool 87 | */ 88 | protected function _write() 89 | { 90 | // Write and close the session 91 | session_write_close(); 92 | 93 | return TRUE; 94 | } 95 | 96 | /** 97 | * @return bool 98 | */ 99 | protected function _restart() 100 | { 101 | // Fire up a new session 102 | $status = session_start(); 103 | 104 | // Use the $_SESSION global for storing data 105 | $this->_data =& $_SESSION; 106 | 107 | return $status; 108 | } 109 | 110 | /** 111 | * @return bool 112 | */ 113 | protected function _destroy() 114 | { 115 | // Destroy the current session 116 | session_destroy(); 117 | 118 | // Did destruction work? 119 | $status = ! session_id(); 120 | 121 | if ($status) 122 | { 123 | // Make sure the session cannot be restarted 124 | Cookie::delete($this->_name); 125 | } 126 | 127 | return $status; 128 | } 129 | 130 | } 131 | -------------------------------------------------------------------------------- /classes/Kohana/UTF8/Exception.php: -------------------------------------------------------------------------------- 1 | array = $array; 25 | 26 | parent::__construct($message, $values, $code, $previous); 27 | } 28 | 29 | } 30 | -------------------------------------------------------------------------------- /classes/Kohana/View/Exception.php: -------------------------------------------------------------------------------- 1 | =5.3.3" 24 | }, 25 | "require-dev": { 26 | "kohana/unittest": "3.3.*@dev", 27 | "kohana/koharness": "*@dev" 28 | }, 29 | "suggest": { 30 | "ext-http": "*", 31 | "ext-curl": "*", 32 | "ext-mcrypt": "*" 33 | }, 34 | "extra": { 35 | "installer-paths": { 36 | "vendor/{$vendor}/{$name}": ["type:kohana-module"] 37 | }, 38 | "branch-alias": { 39 | "dev-3.3/develop": "3.3.x-dev", 40 | "dev-3.4/develop": "3.4.x-dev" 41 | } 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /config/credit_cards.php: -------------------------------------------------------------------------------- 1 | array( 13 | 'length' => '13,14,15,16,17,18,19', 14 | 'prefix' => '', 15 | 'luhn' => TRUE, 16 | ), 17 | 18 | 'american express' => array( 19 | 'length' => '15', 20 | 'prefix' => '3[47]', 21 | 'luhn' => TRUE, 22 | ), 23 | 24 | 'diners club' => array( 25 | 'length' => '14,16', 26 | 'prefix' => '36|55|30[0-5]', 27 | 'luhn' => TRUE, 28 | ), 29 | 30 | 'discover' => array( 31 | 'length' => '16', 32 | 'prefix' => '6(?:5|011)', 33 | 'luhn' => TRUE, 34 | ), 35 | 36 | 'jcb' => array( 37 | 'length' => '15,16', 38 | 'prefix' => '3|1800|2131', 39 | 'luhn' => TRUE, 40 | ), 41 | 42 | 'maestro' => array( 43 | 'length' => '16,18', 44 | 'prefix' => '50(?:20|38)|6(?:304|759)', 45 | 'luhn' => TRUE, 46 | ), 47 | 48 | 'mastercard' => array( 49 | 'length' => '16', 50 | 'prefix' => '5[1-5]', 51 | 'luhn' => TRUE, 52 | ), 53 | 54 | 'visa' => array( 55 | 'length' => '13,16', 56 | 'prefix' => '4', 57 | 'luhn' => TRUE, 58 | ), 59 | 60 | ); 61 | -------------------------------------------------------------------------------- /config/curl.php: -------------------------------------------------------------------------------- 1 | 'Mozilla/5.0 (compatible; Kohana v'.Kohana::VERSION.' +http://kohanaframework.org/)', 6 | CURLOPT_CONNECTTIMEOUT => 5, 7 | CURLOPT_TIMEOUT => 5, 8 | CURLOPT_HEADER => FALSE, 9 | 10 | ); 11 | -------------------------------------------------------------------------------- /config/encrypt.php: -------------------------------------------------------------------------------- 1 | array( 6 | /** 7 | * The following options must be set: 8 | * 9 | * string key secret passphrase 10 | * integer mode encryption mode, one of MCRYPT_MODE_* 11 | * integer cipher encryption cipher, one of the Mcrpyt cipher constants 12 | */ 13 | 'cipher' => MCRYPT_RIJNDAEL_128, 14 | 'mode' => MCRYPT_MODE_NOFB, 15 | ), 16 | 17 | ); 18 | -------------------------------------------------------------------------------- /config/inflector.php: -------------------------------------------------------------------------------- 1 | array( 6 | 'access', 7 | 'advice', 8 | 'aircraft', 9 | 'art', 10 | 'baggage', 11 | 'bison', 12 | 'dances', 13 | 'deer', 14 | 'equipment', 15 | 'fish', 16 | 'fuel', 17 | 'furniture', 18 | 'heat', 19 | 'honey', 20 | 'homework', 21 | 'impatience', 22 | 'information', 23 | 'knowledge', 24 | 'luggage', 25 | 'media', 26 | 'money', 27 | 'moose', 28 | 'music', 29 | 'news', 30 | 'patience', 31 | 'progress', 32 | 'pollution', 33 | 'research', 34 | 'rice', 35 | 'salmon', 36 | 'sand', 37 | 'series', 38 | 'sheep', 39 | 'sms', 40 | 'spam', 41 | 'species', 42 | 'staff', 43 | 'swine', 44 | 'toothpaste', 45 | 'traffic', 46 | 'understanding', 47 | 'water', 48 | 'weather', 49 | 'work', 50 | ), 51 | 52 | 'irregular' => array( 53 | 'appendix' => 'appendices', 54 | 'cactus' => 'cacti', 55 | 'calf' => 'calves', 56 | 'child' => 'children', 57 | 'crisis' => 'crises', 58 | 'criterion' => 'criteria', 59 | 'curriculum' => 'curricula', 60 | 'diagnosis' => 'diagnoses', 61 | 'elf' => 'elves', 62 | 'ellipsis' => 'ellipses', 63 | 'foot' => 'feet', 64 | 'goose' => 'geese', 65 | 'hero' => 'heroes', 66 | 'hoof' => 'hooves', 67 | 'hypothesis' => 'hypotheses', 68 | 'is' => 'are', 69 | 'knife' => 'knives', 70 | 'leaf' => 'leaves', 71 | 'life' => 'lives', 72 | 'loaf' => 'loaves', 73 | 'man' => 'men', 74 | 'mouse' => 'mice', 75 | 'nucleus' => 'nuclei', 76 | 'oasis' => 'oases', 77 | 'octopus' => 'octopi', 78 | 'ox' => 'oxen', 79 | 'paralysis' => 'paralyses', 80 | 'parenthesis' => 'parentheses', 81 | 'person' => 'people', 82 | 'phenomenon' => 'phenomena', 83 | 'potato' => 'potatoes', 84 | 'quiz' => 'quizzes', 85 | 'radius' => 'radii', 86 | 'scarf' => 'scarves', 87 | 'stimulus' => 'stimuli', 88 | 'syllabus' => 'syllabi', 89 | 'synthesis' => 'syntheses', 90 | 'thief' => 'thieves', 91 | 'tooth' => 'teeth', 92 | 'was' => 'were', 93 | 'wharf' => 'wharves', 94 | 'wife' => 'wives', 95 | 'woman' => 'women', 96 | 'release' => 'releases', 97 | ), 98 | ); 99 | -------------------------------------------------------------------------------- /config/session.php: -------------------------------------------------------------------------------- 1 | array( 6 | 'encrypted' => FALSE, 7 | ), 8 | 9 | ); 10 | -------------------------------------------------------------------------------- /config/url.php: -------------------------------------------------------------------------------- 1 | array( 6 | // Set up your hostnames here 7 | // 8 | // Example: 9 | // 10 | // 'example\.org', 11 | // '.*\.example\.org', 12 | // 13 | // Do not forget to escape your dots (.) as these are regex patterns. 14 | // These patterns should always fully match, 15 | // as they are prepended with `^` and appended with `$` 16 | ), 17 | 18 | ); 19 | -------------------------------------------------------------------------------- /config/userguide.php: -------------------------------------------------------------------------------- 1 | array( 6 | 7 | // This should be the path to this modules userguide pages, without the 'guide/'. Ex: '/guide/modulename/' would be 'modulename' 8 | 'kohana' => array( 9 | 10 | // Whether this modules userguide pages should be shown 11 | 'enabled' => TRUE, 12 | 13 | // The name that should show up on the userguide index page 14 | 'name' => 'Kohana', 15 | 16 | // A short description of this module, shown on the index page 17 | 'description' => 'Documentation for Kohana core/system.', 18 | 19 | // Copyright message, shown in the footer for this module 20 | 'copyright' => '© 2008–2012 Kohana Team', 21 | ), 22 | ), 23 | 24 | ); 25 | -------------------------------------------------------------------------------- /guide/kohana/autoloading.md: -------------------------------------------------------------------------------- 1 | # Loading Classes 2 | 3 | Kohana supports the [PSR-0](https://github.com/php-fig/fig-standards/blob/master/accepted/PSR-0.md) autoloading specification as of version 3.3. This allows you to take advantage of PHP [autoloading](http://php.net/manual/language.oop5.autoload.php), removing 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: 4 | 5 | Cookie::set('mycookie', 'any string value'); 6 | 7 | Or to load an [Encrypt] instance, just call [Encrypt::instance]: 8 | 9 | $encrypt = Encrypt::instance(); 10 | 11 | Classes are loaded via the [Kohana::auto_load] method, which makes a simple conversion from class name to file name: 12 | 13 | 1. Classes are placed in the `classes/` directory of the [filesystem](files) 14 | 2. Any underscore characters in the class name are converted to slashes 15 | 2. The filename must match the case of the class 16 | 17 | 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`. 18 | 19 | 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) 20 | 21 | ## Custom Autoloaders 22 | 23 | Kohana's default autoloader is enabled in `application/bootstrap.php` using [spl_autoload_register](http://php.net/spl_autoload_register): 24 | 25 | spl_autoload_register(array('Kohana', 'auto_load')); 26 | 27 | This allows [Kohana::auto_load] to attempt to find and include any class that does not yet exist when the class is first used as long as it follows the PSR-0 specification. If you wish to support the previous Kohana filename convention (using lowercase filesnames), an additional autoloader is provided by Kohana: 28 | 29 | spl_autoload_register(array('Kohana', 'auto_load_lowercase')); 30 | 31 | 32 | ### Example: Zend 33 | 34 | 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. 35 | 36 | #### Download and install the Zend Framework files 37 | 38 | - [Download the latest Zend Framework files](http://framework.zend.com/download/latest). 39 | - Create a `vendor` directory at `application/vendor`. This keeps third party software separate from your application classes. 40 | - Move the decompressed Zend folder containing Zend Framework to `application/vendor/Zend`. 41 | 42 | 43 | #### Include Zend's Autoloader in your bootstrap 44 | 45 | Somewhere in `application/bootstrap.php`, copy the following code: 46 | 47 | /** 48 | * Enable Zend Framework autoloading 49 | */ 50 | if ($path = Kohana::find_file('vendor', 'Zend/Loader')) 51 | { 52 | ini_set('include_path', 53 | ini_get('include_path').PATH_SEPARATOR.dirname(dirname($path))); 54 | 55 | require_once 'Zend/Loader/Autoloader.php'; 56 | Zend_Loader_Autoloader::getInstance(); 57 | } 58 | 59 | #### Usage example 60 | 61 | You can now autoload any Zend Framework classes from inside your Kohana application. 62 | 63 | if ($validate($this->request->post())) 64 | { 65 | $mailer = new Zend_Mail; 66 | 67 | $mailer->setBodyHtml($view) 68 | ->setFrom(Kohana::$config->load('site')->email_from) 69 | ->addTo($email) 70 | ->setSubject($message) 71 | ->send(); 72 | } 73 | -------------------------------------------------------------------------------- /guide/kohana/controllers.md: -------------------------------------------------------------------------------- 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. -------------------------------------------------------------------------------- /guide/kohana/debugging.md: -------------------------------------------------------------------------------- 1 | # Debugging 2 | 3 | Kohana includes several tools to help you debug your application. 4 | 5 | The most basic of these is [Debug::vars]. 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. 6 | 7 | // Display a dump of the $foo and $bar variables 8 | echo Debug::vars($foo, $bar); 9 | 10 | Kohana also provides a method to show the source code of a particular file using [Debug::source]. 11 | 12 | // Display this line of source code 13 | echo Debug::source(__FILE__, __LINE__); 14 | 15 | If you want to display information about your application files without exposing the installation directory, you can use [Debug::path]: 16 | 17 | // Displays "APPPATH/cache" rather than the real path 18 | echo Debug::path(APPPATH.'cache'); 19 | 20 | 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/). -------------------------------------------------------------------------------- /guide/kohana/errors.md: -------------------------------------------------------------------------------- 1 | # Error/Exception Handling 2 | 3 | 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: 4 | 5 | 1. Exception class 6 | 2. Error level 7 | 3. Error message 8 | 4. Source of the error, with the error line highlighted 9 | 5. A [debug backtrace](http://php.net/debug_backtrace) of the execution flow 10 | 6. Included files, loaded extensions, and global variables 11 | 12 | ## Example 13 | 14 | Click any of the links to toggle the display of additional information: 15 | 16 |
{{userguide/examples/error}}
17 | 18 | ## Disabling Error/Exception Handling 19 | 20 | If you do not want to use the internal error handling, you can disable it (highly discouraged) when calling [Kohana::init]: 21 | 22 | Kohana::init(array('errors' => FALSE)); 23 | 24 | ## Error Reporting 25 | 26 | By default, Kohana displays all errors, including strict mode warnings. This is set using [error_reporting](http://php.net/error_reporting): 27 | 28 | error_reporting(E_ALL | E_STRICT); 29 | 30 | When you application is live and in production, a more conservative setting is recommended, such as ignoring notices: 31 | 32 | error_reporting(E_ALL & ~E_NOTICE); 33 | 34 | 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: 35 | 36 | ini_set('display_errors', TRUE); 37 | 38 | 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. 39 | 40 | ## HTTP Exception Handling 41 | 42 | Kohana comes with a robust system for handing http errors. It includes exception classes for each http status code. To trigger a 404 in your application (the most common scenario): 43 | 44 | throw HTTP_Exception::factory(404, 'File not found!'); 45 | 46 | To register error pages for these, using 404 as an example: 47 | 48 | class HTTP_Exception_404 extends Kohana_HTTP_Exception_404 { 49 | 50 | public function get_response() 51 | { 52 | $response = Response::factory(); 53 | 54 | $view = View::factory('errors/404'); 55 | 56 | // We're inside an instance of Exception here, all the normal stuff is available. 57 | $view->message = $this->getMessage(); 58 | 59 | $response->body($view->render()); 60 | 61 | return $response; 62 | } 63 | 64 | } -------------------------------------------------------------------------------- /guide/kohana/files/classes.md: -------------------------------------------------------------------------------- 1 | # Classes 2 | 3 | TODO: Brief intro to classes. 4 | 5 | [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. 6 | 7 | ## Helper or Library? 8 | 9 | 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 instantiated 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. 10 | 11 | ## Creating a class 12 | 13 | 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. 14 | 15 | // classes/Foobar.php 16 | 17 | class Foobar { 18 | static function magic() { 19 | // Does something 20 | } 21 | } 22 | 23 | We can now call `Foobar::magic()` any where and Kohana will [autoload](autoloading) the file for us. 24 | 25 | We can also put classes in subdirectories. 26 | 27 | // classes/Professor/Baxter.php 28 | 29 | class Professor_Baxter { 30 | static function teach() { 31 | // Does something 32 | } 33 | } 34 | 35 | We could now call `Professor_Baxter::teach()` any where we want. 36 | 37 | For examples of how to create and use classes, simply look at the 'classes' folder in `system` or any module. 38 | 39 | ## Namespacing your classes 40 | 41 | TODO: Discuss namespacing to provide transparent extension functionality in your own classes/modules. 42 | -------------------------------------------------------------------------------- /guide/kohana/files/config.md: -------------------------------------------------------------------------------- 1 | # Config Files 2 | 3 | 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: 4 | 5 | 'value', 9 | 'options' => array( 10 | 'foo' => 'bar', 11 | ), 12 | ); 13 | 14 | If the above configuration file was called `myconf.php`, you could access it using: 15 | 16 | $config = Kohana::$config->load('myconf'); 17 | $options = $config->get('options') 18 | 19 | ## Merge 20 | 21 | 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. 22 | 23 | For example, if we wanted to change or add to an entry in the inflector configuration file, we would not need to duplicate all the other entries from the default configuration file. 24 | 25 | // config/inflector.php 26 | 27 | array( 31 | 'die' => 'dice', // does not exist in default config file 32 | 'mouse' => 'mouses', // overrides 'mouse' => 'mice' in the default config file 33 | ); 34 | 35 | 36 | ## Creating your own config files 37 | 38 | 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`: 39 | 40 | // config/site.php 41 | 42 | 'Our Shiny Website', 46 | 'analytics' => FALSE, // analytics code goes here, set to FALSE to disable 47 | ); 48 | 49 | We could now call `Kohana::$config->load('site.title')` to get the site name, and `Kohana::$config->load('site.analytics')` to get the analytics code. 50 | 51 | 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. 52 | 53 | // config/versions.php 54 | 55 | array( 59 | 'codename' => 'Frog', 60 | 'download' => 'files/ourapp-1.0.0.tar.gz', 61 | 'documentation' => 'docs/1.0.0', 62 | 'released' => '06/05/2009', 63 | 'issues' => 'link/to/bug/tracker', 64 | ), 65 | '1.1.0' => array( 66 | 'codename' => 'Lizard', 67 | 'download' => 'files/ourapp-1.1.0.tar.gz', 68 | 'documentation' => 'docs/1.1.0', 69 | 'released' => '10/15/2009', 70 | 'issues' => 'link/to/bug/tracker', 71 | ), 72 | /// ... etc ... 73 | ); 74 | 75 | You could then do the following: 76 | 77 | // In your controller 78 | $view->versions = Kohana::$config->load('versions'); 79 | 80 | // In your view: 81 | foreach ($versions as $version) 82 | { 83 | // echo some html to display each version 84 | } 85 | -------------------------------------------------------------------------------- /guide/kohana/files/i18n.md: -------------------------------------------------------------------------------- 1 | # I18n 2 | 3 | Kohana has a fairly simple and easy to use i18n system. It is slightly modeled after gettext, but is not as featureful. If you need the features of gettext, please use that :) 4 | 5 | ## __() 6 | 7 | Kohana has a __() function to do your translations for you. This function is only meant for small sections of text, not entire paragraphs or pages of translated text. 8 | 9 | To echo a translated string: 10 | 11 | 12 | 13 | This will echo 'Home' unless you've changed the defined language, which is explained below. 14 | 15 | ## Changing the displayed language 16 | 17 | Use the I18n::lang() method to change the displayed language: 18 | 19 | I18n::lang('fr'); 20 | 21 | This will change the language to 'es-es'. 22 | 23 | ## Defining language files 24 | 25 | To define the language file for the above language change, create a `i18n/fr.php` that contains: 26 | 27 | 'Bonjour, monde!', 32 | ); 33 | 34 | Now when you do `__('Hello, world!')`, you will get `Bonjour, monde!` 35 | 36 | ## I18n variables 37 | 38 | You can define variables in your __() calls like so: 39 | 40 | echo __('Hello, :user', array(':user' => $username)); 41 | 42 | Your i18n key in your translation file will need to be defined as: 43 | 44 | 'Bonjour, :user', 49 | ); 50 | 51 | ## Defining your own __() function 52 | 53 | You can define your own __() function by simply defining your own i18n class: 54 | 55 | 'Hello, world!', 17 | ); 18 | 19 | You can also look in subfolders and sub-keys: 20 | 21 | Kohana::message('forms/contact', 'foobar.bar'); 22 | 23 | This will look in the `messages/forms/contact.php` for the `[foobar][bar]` key: 24 | 25 | array( 29 | 'bar' => 'Hello, world!', 30 | ), 31 | ); 32 | 33 | ## Notes 34 | 35 | * Don't use __() in your messages files, as these files can be cached and will not work properly. 36 | * Messages are merged by the cascading file system, not overwritten like classes and views. 37 | -------------------------------------------------------------------------------- /guide/kohana/flow.md: -------------------------------------------------------------------------------- 1 | # Request Flow 2 | 3 | Every application follows the same flow: 4 | 5 | 1. Application starts from `index.php`. 6 | 1. The application, module, and system paths are set. (`APPPATH`, `MODPATH`, and `SYSPATH`) 7 | 2. Error reporting levels are set. 8 | 3. Install file is loaded, if it exists. 9 | 4. The bootstrap file, `APPPATH/bootstrap.php`, is included. 10 | 2. Once we are in `bootstrap.php`: 11 | 6. The [Kohana] class is loaded. 12 | 7. [Kohana::init] is called, which sets up error handling, caching, and logging. 13 | 8. [Kohana_Config] readers and [Kohana_Log] writers are attached. 14 | 9. [Kohana::modules] is called to enable additional modules. 15 | * Module paths are added to the [cascading filesystem](files). 16 | * Includes each module's `init.php` file, if it exists. 17 | * The `init.php` file can perform additional environment setup, including adding routes. 18 | 10. [Route::set] is called multiple times to define the [application routes](routing). 19 | 11. [Request::factory] is called to start processing the request. 20 | 1. Checks each route that has been set until a match is found. 21 | 2. Creates the controller instance and passes the request to it. 22 | 3. Calls the [Controller::before] method. 23 | 4. Calls the controller action, which generates the request response. 24 | 5. Calls the [Controller::after] method. 25 | * The above 5 steps can be repeated multiple times when using [HMVC sub-requests](requests). 26 | 3. Application flow returns to index.php 27 | 12. The main [Request] response is displayed 28 | -------------------------------------------------------------------------------- /guide/kohana/helpers.md: -------------------------------------------------------------------------------- 1 | # Helpers 2 | 3 | Kohana comes with many static "helper" functions to make certain tasks easier. 4 | 5 | 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. 6 | 7 | - **[Arr]** - Array functions. Get an array key or default to a set value, get an array key by path, etc. 8 | 9 | - **[CLI]** - Parse command line options. 10 | 11 | - **[Cookie]** - Covered in more detail on the [Cookies](cookies) page. 12 | 13 | - **[Date]** - Useful date functions and constants. Time between two dates, convert between am/pm and military, date offset, etc. 14 | 15 | - **[Encrypt]** - Covered in more detail on the [Security](security) page. 16 | 17 | - **[Feed]** - Parse and create RSS feeds. 18 | 19 | - **[File]** - Get file type by mime, split and merge a file into small pieces. 20 | 21 | - **[Form]** - Create HTML form elements. 22 | 23 | - **[Fragment]** - Simple file based caching. Covered in more detail on the [Fragments](fragments) page. 24 | 25 | - **[HTML]** - Useful HTML functions. Encode, obfuscate, create script, anchor, and image tags, etc. 26 | 27 | - **[I18n]** - Internationalization helper for creating multilanguage sites. 28 | 29 | - **[Inflector]** - Change a word into plural or singular form, camelize or humanize a phrase, etc. 30 | 31 | - **[Kohana]** - The Kohana class is also a helper. Debug variables (like print_r but better), file loading, etc. 32 | 33 | - **[Num]** - Provides locale aware formating and english ordinals (th, st, nd, etc). 34 | 35 | - **[Profiler]** - Covered in more detail on the [Profiling](profiling) page. 36 | 37 | - **[Remote]** - Remote server access helper using [CURL](http://php.net/curl). 38 | 39 | - **[Request]** - Get the current request url, create expire tags, send a file, get the user agent, etc. 40 | 41 | - **[Route]** - Create routes, create an internal link using a route. 42 | 43 | - **[Security]** - Covered in more detail on the [Security](security) page. 44 | 45 | - **[Session]** - Covered in more detail on the [Sessions](sessions) page. 46 | 47 | - **[Text]** - Autolink, prevent window words, convert a number to text, etc. 48 | 49 | - **[URL]** - Create a relative or absolute URL, make a URL-safe title, etc. 50 | 51 | - **[UTF8]** - Provides multi-byte aware string functions like strlen, strpos, substr, etc. 52 | 53 | - **[Upload]** - Helper for uploading files from a form. 54 | -------------------------------------------------------------------------------- /guide/kohana/index.md: -------------------------------------------------------------------------------- 1 | # What is Kohana? 2 | 3 | Kohana is an open source, [object oriented](http://en.wikipedia.org/wiki/Object-oriented_programming) [MVC](http://en.wikipedia.org/wiki/Model–view–controller "Model View Controller") [web framework](http://en.wikipedia.org/wiki/Web_application_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. 4 | 5 | [!!] 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. 6 | 7 | ## What makes Kohana great? 8 | 9 | Anything can be extended using the unique [filesystem](files) design, little or no [configuration](config) is necessary, [error handling](errors) helps locate the source of errors quickly, and [debugging](debugging) and [profiling](profiling) provide insight into the application. 10 | 11 | To help secure your applications, tools for [input validation](security/validation), [signed cookies](security/cookies), [form] and [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. 12 | 13 | ## Contribute to the Documentation 14 | 15 | 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). 16 | 17 | ## Unofficial Documentation 18 | 19 | If you are having trouble finding an answer here, have a look through the [unofficial wiki](http://kerkness.ca/kowiki/doku.php). Your answer may also be found by searching the [forum](http://forum.kohanaframework.org/) or [Stack Overflow](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. -------------------------------------------------------------------------------- /guide/kohana/install.md: -------------------------------------------------------------------------------- 1 | # Requirements 2 | 3 | [!!] Before continuing, make sure you have a web server (like Apache) configured with the following requirements. 4 | 5 | - PHP 5.3.3 or newer. 6 | - [Iconv Extension](http://php.net/iconv) 7 | - [Character Type (CTYPE) Extension](http://php.net/ctype) 8 | 9 | # Download 10 | 11 | You can get the latest **stable** release on the [Kohana website](http://kohanaframework.org/). This will give you a fully functional application with an `application`, `modules`, and `system` directory. 12 | 13 | [!!] You can find information about the file structure on the [Cascading Filesystem](files) page. 14 | 15 | Once downloaded, you should extract the Kohana application to a directory where the web server can access it. Going forward, we are going to assume you've extracted the application to a `kohana` directory such that `http://localhost/kohana/index.php` is pointing to the `index.php` file in the Kohana release. 16 | 17 | # Configure 18 | 19 | Before the application can be run, you will need to make a few changes to the `application/bootstrap.php` file. This file is the first one to be included by `index.php` and sets up most of the global options for the application. Open `application/bootstrap.php` and make the following changes: 20 | 21 | - Set the default [timezone](http://php.net/timezones) for your application. 22 | ~~~ 23 | // Example of changing timezone to Sao Paulo, Brazil 24 | date_default_timezone_set('America/Sao_Paulo'); 25 | ~~~ 26 | - 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. 27 | ~~~ 28 | /** 29 | * Example of kohana's installation at /var/www/kohana and 30 | * Apache's DocumentRoot configured to /var/www 31 | */ 32 | Kohana::init(array( 33 | 'base_url' => '/kohana/', 34 | )); 35 | ~~~ 36 | 37 | - List your trusted hosts. Open `application/config/url.php` and add regex patterns of the hosts you expect your application to be accessible from. 38 | 39 | [!!] Do not forget to escape your dots (.) as these are regex patterns. These patterns should always fully match, as they are prepended with `^` and appended with `$`. 40 | ~~~ 41 | return array( 42 | 'trusted_hosts' => array( 43 | 'example\.org', 44 | '.*\.example\.org', 45 | ), 46 | ); 47 | ~~~ 48 | 49 | - Define a salt for the `Cookie` class. 50 | ~~~ 51 | Cookie::$salt = 'some-really-long-cookie-salt-here'; 52 | ~~~ 53 | 54 | - Make sure the `application/cache` and `application/logs` directories are writable by the web server. 55 | ~~~ 56 | sudo chmod -R a+rwx application/cache 57 | sudo chmod -R a+rwx application/logs 58 | ~~~ 59 | 60 | [!!] Make sure to use a unique salt for your application and never to share it. Take a look at the [Cookies](cookies) page for more information on how cookies work in Kohana. If you do not define a `Cookie::$salt` value, Kohana will throw an exception when it encounters any cookie on your domain. 61 | 62 | - Test your installation by opening [http://localhost/kohana](http://localhost/kohana). 63 | 64 | You should see the installation page. If it reports any errors, you will need to correct them before continuing. 65 | 66 | ![Install Page](install.png "Example of install page") 67 | 68 | Once your install page reports that your environment is set up correctly you need to either rename or delete `install.php`. Kohana is now installed and you should see the output of the welcome controller: 69 | 70 | ![Welcome Page](welcome.png "Example of welcome page") 71 | 72 | ## Installing Kohana From GitHub 73 | 74 | The [source code](http://github.com/kohana/kohana) for Kohana is hosted with [GitHub](http://github.com). To install Kohana using the github source code first you need to install [git](http://git-scm.com/). Visit [http://help.github.com](http://help.github.com) for details on how to install git on your platform. 75 | 76 | [!!] For more information on installing Kohana using git, see the [Working with Git](tutorials/git) tutorial. 77 | -------------------------------------------------------------------------------- /guide/kohana/menu.md: -------------------------------------------------------------------------------- 1 | ## [Kohana]() 2 | 3 | - [Installation](install) 4 | - Getting Started 5 | - [Conventions and Style](conventions) 6 | - [Model View Controller](mvc) 7 | - [Controllers](mvc/controllers) 8 | - [Models](mvc/models) 9 | - [Views](mvc/views) 10 | - [Cascading Filesystem](files) 11 | - [Class Files](files/classes) 12 | - [Config Files](files/config) 13 | - [Translation Files](files/i18n) 14 | - [Message Files](files/messages) 15 | - [Configuration](config) 16 | - [Request Flow](flow) 17 | - [Bootstrap](bootstrap) 18 | - [Modules](modules) 19 | - [Routing](routing) 20 | - [Error Handling](errors) 21 | - [Tips & Common Mistakes](tips) 22 | - [Upgrading from v3.2](upgrading) 23 | - [Upgrading from v3.3.3.1](upgrading-from-3-3-3-1) 24 | - Basic Usage 25 | - [Debugging](debugging) 26 | - [Loading Classes](autoloading) 27 | - [Transparent Extension](extension) 28 | - [Helpers](helpers) 29 | - [Requests](requests) 30 | - [Sessions](sessions) 31 | - [Cookies](cookies) 32 | - [Fragments](fragments) 33 | - [Profiling](profiling) 34 | - [Security](security) 35 | - [XSS](security/xss) 36 | - [Validation](security/validation) 37 | - [Cookies](security/cookies) 38 | - [Database](security/database) 39 | - [Encryption](security/encryption) 40 | - [Deploying](security/deploying) 41 | - Tutorials 42 | - [Hello World](tutorials/hello-world) 43 | - [Simple MVC](tutorials/simple-mvc) 44 | - [Custom Error Pages](tutorials/error-pages) 45 | - [Clean URLs](tutorials/clean-urls) 46 | - [Sharing Kohana](tutorials/sharing-kohana) 47 | - [Kohana as a Library](tutorials/library-kohana) 48 | - [Working with Git](tutorials/git) 49 | -------------------------------------------------------------------------------- /guide/kohana/modules.md: -------------------------------------------------------------------------------- 1 | # Modules 2 | 3 | Modules are simply an addition to the [Cascading Filesystem](files). A module can add any kind of file (controllers, views, classes, config files, etc.) to the filesystem available to Kohana (via [Kohana::find_file]). This is useful to make any part of your application more transportable or shareable between different apps. For example, creating a new modeling system, a search engine, a css/js manager, etc. 4 | 5 | ## Where to find modules 6 | 7 | Kolanos has created [kohana-universe](http://github.com/kolanos/kohana-universe/tree/master/modules/), a fairly comprehensive list of modules that are available on Github. To get your module listed there, send him a message via Github. 8 | 9 | Mon Geslani created a [very nice site](http://kohana.mongeslani.com/) that allows you to sort Github modules by activity, watchers, forks, etc. It seems to not be as comprehensive as kohana-universe. 10 | 11 | Andrew Hutchings has created [kohana-modules](http://www.kohana-modules.com) which is similar to the above sites. 12 | 13 | ## Enabling modules 14 | 15 | Modules are enabled by calling [Kohana::modules] and passing an array of `'name' => 'path'`. The name isn't important, but the path obviously is. A module's path does not have to be in `MODPATH`, but usually is. You can only call [Kohana::modules] once. 16 | 17 | Kohana::modules(array( 18 | 'auth' => MODPATH.'auth', // Basic authentication 19 | 'cache' => MODPATH.'cache', // Caching with multiple backends 20 | 'codebench' => MODPATH.'codebench', // Benchmarking tool 21 | 'database' => MODPATH.'database', // Database access 22 | 'image' => MODPATH.'image', // Image manipulation 23 | 'orm' => MODPATH.'orm', // Object Relationship Mapping 24 | 'oauth' => MODPATH.'oauth', // OAuth authentication 25 | 'pagination' => MODPATH.'pagination', // Paging of results 26 | 'unittest' => MODPATH.'unittest', // Unit testing 27 | 'userguide' => MODPATH.'userguide', // User guide and API documentation 28 | )); 29 | 30 | ## Init.php 31 | 32 | When a module is activated, if an `init.php` file exists in that module's directory, it is included. This is the ideal place to have a module include routes or other initialization necessary for the module to function. The Userguide and Codebench modules have init.php files you can look at. 33 | 34 | ## How modules work 35 | 36 | A file in an enabled module is virtually the same as having that exact file in the same place in the application folder. The main difference being that it can be overwritten by a file of the same name in a higher location (a module enabled after it, or the application folder) via the [Cascading Filesystem](files). It also provides an easy way to organize and share your code. 37 | 38 | ## Creating your own module 39 | 40 | To create a module simply create a folder (usually in `DOCROOT/modules`) and place the files you want to be in the module there, and activate that module in your bootstrap. To share your module, you can upload it to [Github](http://github.com). You can look at examples of modules made by [Kohana](http://github.com/kohana) or [other users](#where-to-find-modules). -------------------------------------------------------------------------------- /guide/kohana/mvc.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | Discuss the MVC pattern, as it pertains to Kohana. Perhaps have an image, etc. -------------------------------------------------------------------------------- /guide/kohana/mvc/models.md: -------------------------------------------------------------------------------- 1 | # Models 2 | 3 | From Wikipedia: 4 | 5 | > The model manages the behavior and data of the application domain, 6 | > responds to requests for information about its state (usually from the view), 7 | > and responds to instructions to change state (usually from the controller). 8 | 9 | Creating a simple model: 10 | 11 | class Model_Post extends Model 12 | { 13 | public function do_stuff() 14 | { 15 | // This is where you do domain logic... 16 | } 17 | } 18 | 19 | If you want database access, have your model extend the Model_Database class: 20 | 21 | class Model_Post extends Model_Database 22 | { 23 | public function do_stuff() 24 | { 25 | // This is where you do domain logic... 26 | } 27 | 28 | public function get_stuff() 29 | { 30 | // Get stuff from the database: 31 | return $this->db->query(...); 32 | } 33 | } 34 | 35 | If you want CRUD/ORM capabilities, see the [ORM Module](../../guide/orm) -------------------------------------------------------------------------------- /guide/kohana/profiling.md: -------------------------------------------------------------------------------- 1 | # Profiling 2 | 3 | Kohana provides a very simple way to display statistics about your application: 4 | 5 | 1. Common [Kohana] method calls, such as [Kohana::find_file()]. 6 | 2. Requests. Including the main request, as well as any sub-requests. 7 | 3. [Database] queries 8 | 4. Average execution times for your application 9 | 10 | [!!] In order for profiling to work, the `profile` setting must be `TRUE` in your [Kohana::init()] call in your bootstrap. 11 | 12 | ## Profiling your code 13 | 14 | You can easily add profiling to your own functions and code. This is done using the [Profiler::start()] function. The first parameter is the group, the second parameter is the name of the benchmark. 15 | 16 | public function foobar($input) 17 | { 18 | // Be sure to only profile if it's enabled 19 | if (Kohana::$profiling === TRUE) 20 | { 21 | // Start a new benchmark 22 | $benchmark = Profiler::start('Your Category', __FUNCTION__); 23 | } 24 | 25 | // Do some stuff 26 | 27 | if (isset($benchmark)) 28 | { 29 | // Stop the benchmark 30 | Profiler::stop($benchmark); 31 | } 32 | 33 | return $something; 34 | } 35 | 36 | ## How to read the profiling report 37 | 38 | The benchmarks are sorted into groups. Each benchmark will show its name, how many times it was run (show in parenthesis after the benchmark name), and then the min, max, average, and total time and memory spent on that benchmark. The total column will have shaded backgrounds to show the relative times between benchmarks in the same group. 39 | 40 | At the very end is a group called "Application Execution". This keeps track of how long each execution has taken. The number in parenthesis is how many executions are being compared. It shows the fastest, slowest, and average time and memory usage of the last several requsets. The last box is the time and memory usage of the current request. 41 | 42 | ((This could use a picture of a profiler with some database queries, etc. with annotations to point out each area as just described.)) 43 | 44 | ## Displaying the profiler 45 | 46 | You can display or collect the current [profiler] statistics at any time: 47 | 48 | 49 | 50 | ## Preview 51 | 52 | (This is the actual profiler stats for this page.) 53 | 54 | {{profiler/stats}} -------------------------------------------------------------------------------- /guide/kohana/security.md: -------------------------------------------------------------------------------- 1 | General security concerns, like using the Security class, CSRF, and a brief intro to XSS, database security, etc. Also mention the security features that Kohana provides, like cleaning globals. -------------------------------------------------------------------------------- /guide/kohana/security/cookies.md: -------------------------------------------------------------------------------- 1 | Discuss security of cookies, like changing the encryption key in the config. 2 | 3 | Not sure why I'm linking to this: -------------------------------------------------------------------------------- /guide/kohana/security/database.md: -------------------------------------------------------------------------------- 1 | Discuss database security. 2 | 3 | How to avoid injection, etc. 4 | 5 | Not sure why I'm linking to this: -------------------------------------------------------------------------------- /guide/kohana/security/deploying.md: -------------------------------------------------------------------------------- 1 | Changes that should happen when you deploy. (Production) 2 | 3 | Security settings from: 4 | 5 | 6 | 7 | 8 | ## Setting up a production environment 9 | 10 | There are a few things you'll want to do with your application before moving into production. 11 | 12 | 1. See the [Bootstrap page](bootstrap) in the docs. 13 | This covers most of the global settings that would change between environments. 14 | As a general rule, you should enable caching and disable profiling ([Kohana::init] settings) for production sites. 15 | [Route::cache] can also help if you have a lot of routes. 16 | 2. Turn on APC or some kind of opcode caching. 17 | This is the single easiest performance boost you can make to PHP itself. The more complex your application, the bigger the benefit of using opcode caching. 18 | 19 | /** 20 | * Set the environment string by the domain (defaults to Kohana::DEVELOPMENT). 21 | */ 22 | Kohana::$environment = ($_SERVER['SERVER_NAME'] !== 'localhost') ? Kohana::PRODUCTION : Kohana::DEVELOPMENT; 23 | /** 24 | * Initialise Kohana based on environment 25 | */ 26 | Kohana::init(array( 27 | 'base_url' => '/', 28 | 'index_file' => FALSE, 29 | 'profile' => Kohana::$environment !== Kohana::PRODUCTION, 30 | 'caching' => Kohana::$environment === Kohana::PRODUCTION, 31 | )); 32 | -------------------------------------------------------------------------------- /guide/kohana/security/xss.md: -------------------------------------------------------------------------------- 1 | # Cross-Site Scripting (XSS) Security 2 | 3 | *This page is not comprehensive and should not be considered a complete guide to XSS prevention.* 4 | 5 | The first step to preventing [XSS](http://wikipedia.org/wiki/Cross-Site_Scripting) attacks is knowing when you need to protect yourself. XSS can only be triggered when it is displayed within HTML content, sometimes via a form input or being displayed from database results. Any global variable that contains client information can be tainted. This includes `$_GET`, `$_POST`, and `$_COOKIE` data. 6 | 7 | ## Prevention 8 | 9 | There are a few simple rules to follow to guard your application HTML against XSS. If you do not want HTML in a variable, use [strip_tags](http://php.net/strip_tags) to remove all unwanted HTML tags from a value. 10 | 11 | [!!] If you allow users to submit HTML to your application, it is highly recommended to use an HTML cleaning tool such as [HTML Purifier](http://htmlpurifier.org/) or [HTML Tidy](http://php.net/tidy). 12 | 13 | The second is to always escape data when inserting into HTML. The [HTML] class provides generators for many common tags, including script and stylesheet links, anchors, images, and email (mailto) links. Any untrusted content should be escaped using [HTML::chars]. 14 | 15 | ## References 16 | 17 | * [OWASP XSS Cheat Sheet](http://www.owasp.org/index.php/XSS_(Cross_Site_Scripting)_Prevention_Cheat_Sheet) -------------------------------------------------------------------------------- /guide/kohana/tips.md: -------------------------------------------------------------------------------- 1 | # Tips and Common Mistakes 2 | 3 | This is a collection of tips and common mistakes or errors you may encounter. 4 | 5 | ## Never edit the `system` folder! 6 | 7 | You should (almost) never edit the system folder. Any change you want to make to files in system and modules can be made via the [cascading filesystem](files) and [transparent extension](extension) and won't break when you try to update your Kohana version. 8 | 9 | ## Don't try and use one route for everything 10 | 11 | Kohana 3 [routes](routing) are very powerful and flexible, don't be afraid to use as many as you need to make your app function the way you want! 12 | 13 | ## Files not found on some systems 14 | 15 | As of Kohana 3.3, classes are autoloaded using the case-sensitive PSR-0 autoloader. This means that using the class Foo {} with a file in classes/foo.php will work on case-insensitive file systems (such as the default HFS+ FS used in Mac OS X) but will fail when used on a case-sensitive FS (typical on many production Linux servers). 16 | 17 | ## Handling lots of routes 18 | 19 | Sometimes your application is sufficiently complex that you have many routes and it becomes unmanageable to put them all in bootstrap.php. If this is the case, simply make a `routes.php` file in APPPATH and require that in your bootstrap: `require_once APPPATH.'routes'.EXT;` 20 | 21 | ## Reflection_Exception 22 | 23 | If you get a Reflection_Exception when setting up your site, it is almost certainly because your [Kohana::init] 'base_url' setting is wrong. If your base url is correct something is probably wrong with your [routes](routing). 24 | 25 | ReflectionException [ -1 ]: Class controller_ does not exist 26 | // where is part of the url you entered in your browser 27 | 28 | ### Solution {#reflection-exception-solution} 29 | 30 | Set your [Kohana::init] 'base_url' to the correct setting. The base url should be the path to your index.php file relative to the webserver document root. 31 | 32 | ## ORM/Session __sleep() bug 33 | 34 | There is a bug in php which can corrupt your session after a fatal error. A production server shouldn't have uncaught fatal errors, so this bug should only happen during development, when you do something stupid and cause a fatal error. On the next page load you will get a database connection error, then all subsequent page loads will display the following error: 35 | 36 | ErrorException [ Notice ]: Undefined index: id 37 | MODPATH/orm/classes/kohana/orm.php [ 1308 ] 38 | 39 | ### Solution {#orm-session-sleep-solution} 40 | 41 | To fix this, clear your cookies for that domain to reset your session. This should never happen on a production server, so you won't have to explain to your clients how to clear their cookies. You can see the [discussion on this issue](http://dev.kohanaframework.org/issues/3242) for more details. 42 | -------------------------------------------------------------------------------- /guide/kohana/tutorials/clean-urls.md: -------------------------------------------------------------------------------- 1 | # Clean URLs 2 | 3 | Removing `index.php` from your urls. 4 | 5 | To keep your URLs clean, you will probably want to be able to access your app without having `/index.php/` in the URL. There are two steps to remove `index.php` from the URL. 6 | 7 | 1. Edit the bootstrap file 8 | 2. Set up rewriting 9 | 10 | ## 1. Configure Bootstrap 11 | 12 | The first thing you will need to change is the `index_file` setting of [Kohana::init] to false: 13 | 14 | Kohana::init(array( 15 | 'base_url' => '/myapp/', 16 | 'index_file' => FALSE, 17 | )); 18 | 19 | This change will make it so all of the links generated using [URL::site], [URL::base], and [HTML::anchor] will no longer include "index.php" in the URL. All generated links will start with `/myapp/` instead of `/myapp/index.php/`. 20 | 21 | ## 2. URL Rewriting 22 | 23 | Enabling rewriting is done differently, depending on your web server. 24 | 25 | Rewriting will make it so urls will be passed to index.php. 26 | 27 | ## Apache 28 | 29 | Rename `example.htaccess` to only `.htaccess` and alter the `RewriteBase` line to match the `base_url` setting from your [Kohana::init] 30 | 31 | RewriteBase /myapp/ 32 | 33 | The rest of the `.htaccess file` rewrites all requests through index.php, unless the file exists on the server (so your css, images, favicon, etc. are still loaded like normal). In most cases, you are done! 34 | 35 | ### 404 errors 36 | 37 | If you get a "404 Not Found" error when trying to view a page then it's likely Apache is not configured to read the `.htaccess` file. 38 | 39 | In the main apache configuration file (usually `httpd.conf`), or in the virtual server configuration file, check that the `AccessFileName` directive is set to `.htaccess` and the `AllowOverride` directive is set to `All`. 40 | 41 | AccessFileName .htaccess 42 | 43 | 44 | AllowOverride All 45 | 46 | 47 | 48 | ### Failed! 49 | 50 | If you get a "Internal Server Error" or "No input file specified" error, try changing: 51 | 52 | RewriteRule ^(?:application|modules|system)\b - [F,L] 53 | 54 | Instead, we can try a slash: 55 | 56 | RewriteRule ^(application|modules|system)/ - [F,L] 57 | 58 | If that doesn't work, try changing: 59 | 60 | RewriteRule .* index.php/$0 [PT] 61 | 62 | To something more simple: 63 | 64 | RewriteRule .* index.php [PT] 65 | 66 | ### Still Failed! 67 | 68 | If you are still getting errors, check to make sure that your host supports URL `mod_rewrite`. If you can change the Apache configuration, add these lines to the configuration, usually `httpd.conf`: 69 | 70 | 71 | Order allow,deny 72 | Allow from all 73 | AllowOverride All 74 | 75 | 76 | You should also check your Apache logs to see if they can shed some light on the error. 77 | 78 | ## NGINX 79 | 80 | It is hard to give examples of nginx configuration, but here is a sample for a server: 81 | 82 | location / { 83 | index index.php index.html index.htm; 84 | try_files $uri index.php; 85 | } 86 | 87 | location = index.php { 88 | include fastcgi.conf; 89 | fastcgi_pass 127.0.0.1:9000; 90 | fastcgi_index index.php; 91 | } 92 | 93 | If you are having issues getting this working, enable debug level logging in nginx and check the access and error logs. 94 | -------------------------------------------------------------------------------- /guide/kohana/tutorials/error-pages.md: -------------------------------------------------------------------------------- 1 | # Custom Error Pages 2 | 3 | Custom error pages allow you to display a friendly error message to users, rather than the standard Kohana stack trace. 4 | 5 | ## Prerequisites 6 | 7 | 1. You will need `'errors' => TRUE` passed to [Kohana::init]. This will convert PHP-errors into exceptions which are easier to handle (The default value is `TRUE`). 8 | 2. Custom error pages will only be used to handle throw [HTTP_Exception]'s. If you simply set a status of, for example, 404 via [Respose::status] the custom page will not be used. 9 | 10 | ## Extending the HTTP_Exception classes 11 | 12 | Handling [HTTP_Exception]'s in Kohana has become easier with the changes introduced in 3.3. 13 | 14 | For each [HTTP_Exception] class we can individually override the generation of the [Response] instance. 15 | 16 | [!!] Note: We can also use HMVC to issue a sub-request to another page rather than generating the [Response] in the [HTTP_Exception] itself. 17 | 18 | For example, to handle 404 pages we can do this in APPPATH/classes/HTTP/Exception/404.php: 19 | 20 | class HTTP_Exception_404 extends Kohana_HTTP_Exception_404 { 21 | 22 | /** 23 | * Generate a Response for the 404 Exception. 24 | * 25 | * The user should be shown a nice 404 page. 26 | * 27 | * @return Response 28 | */ 29 | public function get_response() 30 | { 31 | $view = View::factory('errors/404'); 32 | 33 | // Remembering that `$this` is an instance of HTTP_Exception_404 34 | $view->message = $this->getMessage(); 35 | 36 | $response = Response::factory() 37 | ->status(404) 38 | ->body($view->render()); 39 | 40 | return $response; 41 | } 42 | } 43 | 44 | Another example, this time to handle 401 Unauthorized errors (aka "Not Logged In") we can do this in APPPATH/classes/HTTP/Exception/401.php: 45 | 46 | class HTTP_Exception_401 extends Kohana_HTTP_Exception_401 { 47 | 48 | /** 49 | * Generate a Response for the 401 Exception. 50 | * 51 | * The user should be redirect to a login page. 52 | * 53 | * @return Response 54 | */ 55 | public function get_response() 56 | { 57 | $response = Response::factory() 58 | ->status(401) 59 | ->headers('Location', URL::site('account/login')); 60 | 61 | return $response; 62 | } 63 | } 64 | 65 | Finally, to override the default [Response] for all [HTTP_Exception]'s without a more specific override we can do this in APPPATH/classes/HTTP/Exception.php: 66 | 67 | class HTTP_Exception extends Kohana_HTTP_Exception { 68 | 69 | /** 70 | * Generate a Response for all Exceptions without a more specific override 71 | * 72 | * The user should see a nice error page, however, if we are in development 73 | * mode we should show the normal Kohana error page. 74 | * 75 | * @return Response 76 | */ 77 | public function get_response() 78 | { 79 | // Lets log the Exception, Just in case it's important! 80 | Kohana_Exception::log($this); 81 | 82 | if (Kohana::$environment >= Kohana::DEVELOPMENT) 83 | { 84 | // Show the normal Kohana error page. 85 | return parent::get_response(); 86 | } 87 | else 88 | { 89 | // Generate a nicer looking "Oops" page. 90 | $view = View::factory('errors/default'); 91 | 92 | $response = Response::factory() 93 | ->status($this->getCode()) 94 | ->body($view->render()); 95 | 96 | return $response; 97 | } 98 | } 99 | } -------------------------------------------------------------------------------- /guide/kohana/tutorials/sharing-kohana.md: -------------------------------------------------------------------------------- 1 | # Sharing Kohana 2 | 3 | Kohana follows a [front controller pattern](http://en.wikipedia.org/wiki/Front_Controller_pattern "Front Controller pattern") (which means that all requests are sent to `index.php`) and as such the [filesystem](files) is very configurable. Inside of `index.php` you can change the `$application`, `$modules`, and `$system` paths. 4 | 5 | [!!] There is a security check at the top of every Kohana file to prevent it from being accessed without using the front controller. Also, the `.htaccess` file should protect those folders as well. Moving the application, modules, and system directories to a location that cannot be accessed via the web can add another layer of security, but is optional. 6 | 7 | The `$application` variable lets you set the directory that contains your application files. By default, this is `application`. The `$modules` variable lets you set the directory that contains module files. The `$system` variable lets you set the directory that contains the default Kohana files. You can move these three directories anywhere. 8 | 9 | For instance, by default the directories are set up like this: 10 | 11 | www/ 12 | index.php 13 | application/ 14 | modules/ 15 | system/ 16 | 17 | You could move the directories out of the web root so they look like this: 18 | 19 | application/ 20 | modules/ 21 | system/ 22 | www/ 23 | index.php 24 | 25 | Then you would need to change the settings in `index.php` to be: 26 | 27 | $application = '../application'; 28 | $modules = '../modules'; 29 | $system = '../system'; 30 | 31 | ## Sharing system and modules 32 | 33 | To take this a step further, we could point several Kohana apps to the same system and modules folders. For example (and this is just an example, you could arrange these anyway you want): 34 | 35 | apps/ 36 | foobar/ 37 | application/ 38 | www/ 39 | bazbar/ 40 | application/ 41 | www/ 42 | kohana/ 43 | 3.0.6/ 44 | 3.0.7/ 45 | 3.0.8/ 46 | modules/ 47 | 48 | And you would need to change the settings in `index.php` to be: 49 | 50 | $application = '../application'; 51 | $system = '../../../kohana/3.0.6'; 52 | $modules = '../../../kohana/modules'; 53 | 54 | With this method each app can point to a central copy of Kohana, and when you add a new version, allow you to quickly update the apps by editing their respective `index.php` files. -------------------------------------------------------------------------------- /guide/kohana/tutorials/simple-mvc.md: -------------------------------------------------------------------------------- 1 | Simple example of controller model and view working together. -------------------------------------------------------------------------------- /guide/kohana/upgrading-from-3-3-3-1.md: -------------------------------------------------------------------------------- 1 | # Upgrading from 3.3.3.1 2 | 3 | Minor version upgrades are usually done in a drop-in fashion. Unfortunately, however, upgrading from 3.3.3.1 to 3.3.4 needs a little configuration. This is because a [security disclosure from HP Fortify](https://github.com/kohana/kohana/issues/74), that unveiled a serious [host header attack](https://github.com/kohana/core/issues/613) vulnerability. 4 | 5 | [!!] You *might* still be able to have a drop-in upgrade, in case you have set the `base_url` in the [Kohana::init] call to an absolute URL. We advise you however that you follow the step below to make your application secure, in case some day you decide to change your `base_url` to a relative URL. 6 | 7 | ## Trusted Hosts 8 | 9 | You need to setup a list of trusted hosts. Trusted hosts are hosts that you expect your application to be accessible from. 10 | 11 | Open `application/config/url.php` and add regex patterns of these hosts. An example is given hereunder: 12 | 13 | ~~~ 14 | return array( 15 | 'trusted_hosts' => array( 16 | 'example\.org', 17 | '.*\.example\.org', 18 | ), 19 | ); 20 | ~~~ 21 | 22 | [!!] Do not forget to escape your dots (.) as these are regex patterns. These patterns should always fully match, as they are prepended with `^` and appended with `$`. 23 | 24 | -------------------------------------------------------------------------------- /i18n/en.php: -------------------------------------------------------------------------------- 1 | 'Español', 6 | 'Hello, world!' => '¡Hola, mundo!', 7 | 8 | ); 9 | -------------------------------------------------------------------------------- /i18n/fr.php: -------------------------------------------------------------------------------- 1 | 'Français', 6 | 'Hello, world!' => 'Bonjour, monde!', 7 | 8 | ); 9 | -------------------------------------------------------------------------------- /koharness.php: -------------------------------------------------------------------------------- 1 | array( 5 | 'unittest' => __DIR__ . '/vendor/kohana/unittest' 6 | ), 7 | 'syspath' => __DIR__, 8 | ); 9 | -------------------------------------------------------------------------------- /media/guide/kohana/cascading_filesystem.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kohana/core/bdbe81afb5a09cee4269d2e2210a0d293265231a/media/guide/kohana/cascading_filesystem.png -------------------------------------------------------------------------------- /media/guide/kohana/hello_world_1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kohana/core/bdbe81afb5a09cee4269d2e2210a0d293265231a/media/guide/kohana/hello_world_1.png -------------------------------------------------------------------------------- /media/guide/kohana/hello_world_2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kohana/core/bdbe81afb5a09cee4269d2e2210a0d293265231a/media/guide/kohana/hello_world_2.png -------------------------------------------------------------------------------- /media/guide/kohana/hello_world_2_error.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kohana/core/bdbe81afb5a09cee4269d2e2210a0d293265231a/media/guide/kohana/hello_world_2_error.png -------------------------------------------------------------------------------- /media/guide/kohana/install.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kohana/core/bdbe81afb5a09cee4269d2e2210a0d293265231a/media/guide/kohana/install.png -------------------------------------------------------------------------------- /media/guide/kohana/welcome.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kohana/core/bdbe81afb5a09cee4269d2e2210a0d293265231a/media/guide/kohana/welcome.png -------------------------------------------------------------------------------- /messages/tests/validation/error_type_check.php: -------------------------------------------------------------------------------- 1 | array( 6 | 'custom' => 'very nice email address you have there', 7 | ), 8 | 9 | ); 10 | -------------------------------------------------------------------------------- /messages/validation.php: -------------------------------------------------------------------------------- 1 | ':field must contain only letters', 6 | 'alpha_dash' => ':field must contain only numbers, letters and dashes', 7 | 'alpha_numeric' => ':field must contain only letters and numbers', 8 | 'color' => ':field must be a color', 9 | 'credit_card' => ':field must be a credit card number', 10 | 'date' => ':field must be a date', 11 | 'decimal' => ':field must be a decimal with :param2 places', 12 | 'digit' => ':field must be a digit', 13 | 'email' => ':field must be an email address', 14 | 'email_domain' => ':field must contain a valid email domain', 15 | 'equals' => ':field must equal :param2', 16 | 'exact_length' => ':field must be exactly :param2 characters long', 17 | 'in_array' => ':field must be one of the available options', 18 | 'ip' => ':field must be an ip address', 19 | 'matches' => ':field must be the same as :param3', 20 | 'min_length' => ':field must be at least :param2 characters long', 21 | 'max_length' => ':field must not exceed :param2 characters long', 22 | 'not_empty' => ':field must not be empty', 23 | 'numeric' => ':field must be numeric', 24 | 'phone' => ':field must be a phone number', 25 | 'range' => ':field must be within the range of :param2 to :param3', 26 | 'regex' => ':field does not match the required format', 27 | 'url' => ':field must be a url', 28 | 29 | ); 30 | -------------------------------------------------------------------------------- /tests/kohana/Config/File/ReaderTest.php: -------------------------------------------------------------------------------- 1 | 12 | * @author Matt Button 13 | * @copyright (c) 2008-2014 Kohana Team 14 | * @license http://kohanaframework.org/license 15 | */ 16 | class Kohana_Config_File_ReaderTest extends Kohana_Unittest_TestCase { 17 | 18 | /** 19 | * If we don't pass a directory to the reader then it should assume 20 | * that we want to search the dir 'config' by default 21 | * 22 | * @test 23 | * @covers Kohana_Config_File_Reader 24 | */ 25 | public function test_default_search_dir_is_config() 26 | { 27 | $reader = new Kohana_Config_File_Reader; 28 | 29 | $this->assertAttributeSame('config', '_directory', $reader); 30 | } 31 | 32 | /** 33 | * If we pass a directory to the constructor of the file reader it 34 | * should change the search directory 35 | * 36 | * @test 37 | * @covers Kohana_Config_File_Reader 38 | */ 39 | public function test_constructor_sets_search_dir_from_param() 40 | { 41 | $reader = new Kohana_Config_File_Reader('gafloog'); 42 | 43 | $this->assertAttributeSame('gafloog', '_directory', $reader); 44 | } 45 | 46 | /** 47 | * If the config dir does not exist then the function should just 48 | * return an empty array 49 | * 50 | * @test 51 | * @covers Kohana_Config_File_Reader::load 52 | */ 53 | public function test_load_returns_empty_array_if_conf_dir_dnx() 54 | { 55 | $config = new Kohana_Config_File_Reader('gafloogle'); 56 | 57 | $this->assertSame(array(), $config->load('values')); 58 | } 59 | 60 | /** 61 | * If the requested config group does not exist then the reader 62 | * should return an empty array 63 | * 64 | * @test 65 | * @covers Kohana_Config_File_Reader::load 66 | */ 67 | public function test_load_returns_empty_array_if_conf_dnx() 68 | { 69 | $config = new Kohana_Config_File_Reader; 70 | 71 | $this->assertSame(array(), $config->load('gafloogle')); 72 | } 73 | 74 | /** 75 | * Test that the load() function is actually loading the 76 | * configuration from the files. 77 | * 78 | * @test 79 | * @covers Kohana_Config_File_Reader::load 80 | */ 81 | public function test_loads_config_from_files() 82 | { 83 | $config = new Kohana_Config_File_Reader; 84 | 85 | $values = $config->load('inflector'); 86 | 87 | // Due to the way the cascading filesystem works there could be 88 | // any number of modifications to the system config in the 89 | // actual output. Therefore to increase compatability we just 90 | // check that we've got an array and that it's not empty 91 | $this->assertNotSame(array(), $values); 92 | $this->assertInternalType('array', $values); 93 | } 94 | } 95 | -------------------------------------------------------------------------------- /tests/kohana/ExceptionTest.php: -------------------------------------------------------------------------------- 1 | 'b')), 'b', 0), 32 | array(array(':a :b', array(':a' => 'c', ':b' => 'd')), 'c d', 0), 33 | 34 | array(array(':a', NULL, 5), ':a', 5), 35 | // #3358 36 | array(array(':a', NULL, '3F000'), ':a', '3F000'), 37 | // #3404 38 | array(array(':a', NULL, '42S22'), ':a', '42S22'), 39 | // #3927 40 | array(array(':a', NULL, 'b'), ':a', 'b'), 41 | // #4039 42 | array(array(':a', NULL, '25P01'), ':a', '25P01'), 43 | ); 44 | } 45 | 46 | /** 47 | * Tests Kohana_Kohana_Exception::__construct() 48 | * 49 | * @test 50 | * @dataProvider provider_constructor 51 | * @covers Kohana_Kohana_Exception::__construct 52 | * @param array $arguments Arguments 53 | * @param string $expected_message Value from getMessage() 54 | * @param integer|string $expected_code Value from getCode() 55 | */ 56 | public function test_constructor($arguments, $expected_message, $expected_code) 57 | { 58 | switch (count($arguments)) 59 | { 60 | case 1: 61 | $exception = new Kohana_Exception(reset($arguments)); 62 | break; 63 | case 2: 64 | $exception = new Kohana_Exception(reset($arguments), next($arguments)); 65 | break; 66 | default: 67 | $exception = new Kohana_Exception(reset($arguments), next($arguments), next($arguments)); 68 | } 69 | 70 | $this->assertSame($expected_code, $exception->getCode()); 71 | $this->assertSame($expected_message, $exception->getMessage()); 72 | } 73 | 74 | /** 75 | * Provides test data for test_text() 76 | * 77 | * @return array 78 | */ 79 | public function provider_text() 80 | { 81 | return array( 82 | array(new Kohana_Exception('foobar'), $this->dirSeparator('Kohana_Exception [ 0 ]: foobar ~ SYSPATH/tests/kohana/ExceptionTest.php [ '.__LINE__.' ]')), 83 | ); 84 | } 85 | 86 | /** 87 | * Tests Kohana_Exception::text() 88 | * 89 | * @test 90 | * @dataProvider provider_text 91 | * @covers Kohana_Exception::text 92 | * @param object $exception exception to test 93 | * @param string $expected expected output 94 | */ 95 | public function test_text($exception, $expected) 96 | { 97 | $this->assertEquals($expected, Kohana_Exception::text($exception)); 98 | } 99 | } 100 | -------------------------------------------------------------------------------- /tests/kohana/FileTest.php: -------------------------------------------------------------------------------- 1 | 14 | * @copyright (c) 2008-2012 Kohana Team 15 | * @license http://kohanaframework.org/license 16 | */ 17 | class Kohana_FileTest extends Unittest_TestCase 18 | { 19 | /** 20 | * Provides test data for test_sanitize() 21 | * 22 | * @return array 23 | */ 24 | public function provider_mime() 25 | { 26 | return array( 27 | // $value, $result 28 | array(Kohana::find_file('tests', 'test_data/github', 'png'), 'image/png'), 29 | ); 30 | } 31 | 32 | /** 33 | * Tests File::mime() 34 | * 35 | * @test 36 | * @dataProvider provider_mime 37 | * @param boolean $input Input for File::mime 38 | * @param boolean $expected Output for File::mime 39 | */ 40 | public function test_mime($input, $expected) 41 | { 42 | //@todo: File::mime coverage needs significant improvement or to be dropped for a composer package - it's a "horribly unreliable" method with very little testing 43 | $this->assertSame($expected, File::mime($input)); 44 | } 45 | 46 | /** 47 | * Provides test data for test_split_join() 48 | * 49 | * @return array 50 | */ 51 | public function provider_split_join() 52 | { 53 | return array( 54 | // $value, $result 55 | array(Kohana::find_file('tests', 'test_data/github', 'png'), .01, 1), 56 | ); 57 | } 58 | 59 | /** 60 | * Tests File::mime() 61 | * 62 | * @test 63 | * @dataProvider provider_split_join 64 | * @param boolean $input Input for File::split 65 | * @param boolean $peices Input for File::split 66 | * @param boolean $expected Output for File::splut 67 | */ 68 | public function test_split_join($input, $peices, $expected) 69 | { 70 | $this->assertSame($expected, File::split($input, $peices)); 71 | $this->assertSame($expected, File::join($input)); 72 | 73 | foreach (glob(Kohana::find_file('tests', 'test_data/github', 'png').'.*') as $file) 74 | { 75 | unlink($file); 76 | } 77 | } 78 | } 79 | -------------------------------------------------------------------------------- /tests/kohana/I18nTest.php: -------------------------------------------------------------------------------- 1 | 14 | * @copyright (c) 2008-2012 Kohana Team 15 | * @license http://kohanaframework.org/license 16 | */ 17 | class Kohana_I18nTest extends Unittest_TestCase { 18 | 19 | /** 20 | * Default values for the environment, see setEnvironment 21 | * @var array 22 | */ 23 | // @codingStandardsIgnoreStart 24 | protected $environmentDefault = array( 25 | 'I18n::$lang' => 'en-us', 26 | ); 27 | // @codingStandardsIgnoreEnd 28 | 29 | /** 30 | * Provides test data for test_lang() 31 | * 32 | * @return array 33 | */ 34 | public function provider_lang() 35 | { 36 | return array( 37 | // $input, $expected_result 38 | array(NULL, 'en-us'), 39 | array('es-es', 'es-es'), 40 | ); 41 | } 42 | 43 | /** 44 | * Tests I18n::lang() 45 | * 46 | * @test 47 | * @dataProvider provider_lang 48 | * @param boolean $input Input for I18n::lang 49 | * @param boolean $expected Output for I18n::lang 50 | */ 51 | public function test_lang($input, $expected_result) 52 | { 53 | $this->assertSame($expected_result, I18n::lang($input)); 54 | $this->assertSame($expected_result, I18n::lang()); 55 | } 56 | 57 | /** 58 | * Provides test data for test_get() 59 | * 60 | * @return array 61 | */ 62 | public function provider_get() 63 | { 64 | return array( 65 | // $value, $result 66 | array('en-us', 'Hello, world!', 'Hello, world!'), 67 | array('es-es', 'Hello, world!', '¡Hola, mundo!'), 68 | array('fr-fr', 'Hello, world!', 'Bonjour, monde!'), 69 | ); 70 | } 71 | 72 | /** 73 | * Tests i18n::get() 74 | * 75 | * @test 76 | * @dataProvider provider_get 77 | * @param boolean $input Input for File::mime 78 | * @param boolean $expected Output for File::mime 79 | */ 80 | public function test_get($lang, $input, $expected) 81 | { 82 | I18n::lang($lang); 83 | $this->assertSame($expected, I18n::get($input)); 84 | 85 | // Test immediate translation, issue #3085 86 | I18n::lang('en-us'); 87 | $this->assertSame($expected, I18n::get($input, $lang)); 88 | } 89 | 90 | } 91 | -------------------------------------------------------------------------------- /tests/kohana/LogTest.php: -------------------------------------------------------------------------------- 1 | 14 | * @copyright (c) 2008-2012 Kohana Team 15 | * @license http://kohanaframework.org/license 16 | */ 17 | class Kohana_LogTest extends Unittest_TestCase 18 | { 19 | 20 | /** 21 | * Tests that when a new logger is created the list of messages is initially 22 | * empty 23 | * 24 | * @test 25 | * @covers Log 26 | */ 27 | public function test_messages_is_initially_empty() 28 | { 29 | $logger = new Log; 30 | 31 | $this->assertAttributeSame(array(), '_messages', $logger); 32 | } 33 | 34 | /** 35 | * Tests that when a new logger is created the list of writers is initially 36 | * empty 37 | * 38 | * @test 39 | * @covers Log 40 | */ 41 | public function test_writers_is_initially_empty() 42 | { 43 | $logger = new Log; 44 | 45 | $this->assertAttributeSame(array(), '_writers', $logger); 46 | } 47 | 48 | /** 49 | * Test that attaching a log writer using an array of levels adds it to the array of log writers 50 | * 51 | * @TODO Is this test too specific? 52 | * 53 | * @test 54 | * @covers Log::attach 55 | */ 56 | public function test_attach_attaches_log_writer_and_returns_this() 57 | { 58 | $logger = new Log; 59 | $writer = $this->getMockForAbstractClass('Log_Writer'); 60 | 61 | $this->assertSame($logger, $logger->attach($writer)); 62 | 63 | $this->assertAttributeSame( 64 | array(spl_object_hash($writer) => array('object' => $writer, 'levels' => array())), 65 | '_writers', 66 | $logger 67 | ); 68 | } 69 | 70 | /** 71 | * Test that attaching a log writer using a min/max level adds it to the array of log writers 72 | * 73 | * @TODO Is this test too specific? 74 | * 75 | * @test 76 | * @covers Log::attach 77 | */ 78 | public function test_attach_attaches_log_writer_min_max_and_returns_this() 79 | { 80 | $logger = new Log; 81 | $writer = $this->getMockForAbstractClass('Log_Writer'); 82 | 83 | $this->assertSame($logger, $logger->attach($writer, Log::NOTICE, Log::CRITICAL)); 84 | 85 | $this->assertAttributeSame( 86 | array(spl_object_hash($writer) => array('object' => $writer, 'levels' => array(Log::CRITICAL, Log::ERROR, Log::WARNING, Log::NOTICE))), 87 | '_writers', 88 | $logger 89 | ); 90 | } 91 | 92 | /** 93 | * When we call detach() we expect the specified log writer to be removed 94 | * 95 | * @test 96 | * @covers Log::detach 97 | */ 98 | public function test_detach_removes_log_writer_and_returns_this() 99 | { 100 | $logger = new Log; 101 | $writer = $this->getMockForAbstractClass('Log_Writer'); 102 | 103 | $logger->attach($writer); 104 | 105 | $this->assertSame($logger, $logger->detach($writer)); 106 | 107 | $this->assertAttributeSame(array(), '_writers', $logger); 108 | } 109 | 110 | 111 | } 112 | -------------------------------------------------------------------------------- /tests/kohana/ModelTest.php: -------------------------------------------------------------------------------- 1 | 14 | * @copyright (c) 2008-2012 Kohana Team 15 | * @license http://kohanaframework.org/license 16 | */ 17 | class Kohana_ModelTest extends Unittest_TestCase 18 | { 19 | /** 20 | * Test the model's factory. 21 | * 22 | * @test 23 | * @covers Model::factory 24 | */ 25 | public function test_create() 26 | { 27 | $foobar = Model::factory('Foobar'); 28 | 29 | $this->assertEquals(TRUE, $foobar instanceof Model); 30 | } 31 | } 32 | 33 | class Model_Foobar extends Model 34 | { 35 | 36 | } 37 | -------------------------------------------------------------------------------- /tests/kohana/SecurityTest.php: -------------------------------------------------------------------------------- 1 | "), 24 | ); 25 | } 26 | 27 | /** 28 | * Tests Security::encode_php_tags() 29 | * 30 | * @test 31 | * @dataProvider provider_encode_php_tags 32 | * @covers Security::encode_php_tags 33 | */ 34 | public function test_encode_php_tags($expected, $input) 35 | { 36 | $this->assertSame($expected, Security::encode_php_tags($input)); 37 | } 38 | 39 | /** 40 | * Provides test data for test_strip_image_tags() 41 | * 42 | * @return array Test data sets 43 | */ 44 | public function provider_strip_image_tags() 45 | { 46 | return array( 47 | array('foo', ''), 48 | ); 49 | } 50 | 51 | /** 52 | * Tests Security::strip_image_tags() 53 | * 54 | * @test 55 | * @dataProvider provider_strip_image_tags 56 | * @covers Security::strip_image_tags 57 | */ 58 | public function test_strip_image_tags($expected, $input) 59 | { 60 | $this->assertSame($expected, Security::strip_image_tags($input)); 61 | } 62 | 63 | /** 64 | * Provides test data for Security::token() 65 | * 66 | * @return array Test data sets 67 | */ 68 | public function provider_csrf_token() 69 | { 70 | $array = array(); 71 | for ($i = 0; $i <= 4; $i++) 72 | { 73 | Security::$token_name = 'token_'.$i; 74 | $array[] = array(Security::token(TRUE), Security::check(Security::token(FALSE)), $i); 75 | } 76 | return $array; 77 | } 78 | 79 | /** 80 | * Tests Security::token() 81 | * 82 | * @test 83 | * @dataProvider provider_csrf_token 84 | * @covers Security::token 85 | */ 86 | public function test_csrf_token($expected, $input, $iteration) 87 | { 88 | //@todo: the Security::token tests need to be reviewed to check how much of the logic they're actually covering 89 | Security::$token_name = 'token_'.$iteration; 90 | $this->assertSame(TRUE, $input); 91 | $this->assertSame($expected, Security::token(FALSE)); 92 | Session::instance()->delete(Security::$token_name); 93 | } 94 | } 95 | -------------------------------------------------------------------------------- /tests/kohana/ViewTest.php: -------------------------------------------------------------------------------- 1 | realpath(dirname(__FILE__).'/../test_data/') 33 | ); 34 | Kohana::modules($new_modules); 35 | } 36 | 37 | /** 38 | * Restores the module list 39 | * 40 | * @return null 41 | */ 42 | // @codingStandardsIgnoreStart 43 | public static function teardownAfterClass() 44 | // @codingStandardsIgnoreEnd 45 | { 46 | Kohana::modules(self::$old_modules); 47 | } 48 | 49 | /** 50 | * Provider for test_instaniate 51 | * 52 | * @return array 53 | */ 54 | public function provider_instantiate() 55 | { 56 | return array( 57 | array('kohana/error', FALSE), 58 | array('test.css', FALSE), 59 | array('doesnt_exist', TRUE), 60 | ); 61 | } 62 | 63 | /** 64 | * Provider to test_set 65 | * 66 | * @return array 67 | */ 68 | public function provider_set() 69 | { 70 | return array( 71 | array('foo', 'bar', 'foo', 'bar'), 72 | array(array('foo' => 'bar'), NULL, 'foo', 'bar'), 73 | array(new ArrayIterator(array('foo' => 'bar')), NULL, 'foo', 'bar'), 74 | ); 75 | } 76 | 77 | /** 78 | * Tests that we can instantiate a view file 79 | * 80 | * @test 81 | * @dataProvider provider_instantiate 82 | * 83 | * @return null 84 | */ 85 | public function test_instantiate($path, $expects_exception) 86 | { 87 | try 88 | { 89 | $view = new View($path); 90 | $this->assertSame(FALSE, $expects_exception); 91 | } 92 | catch(View_Exception $e) 93 | { 94 | $this->assertSame(TRUE, $expects_exception); 95 | } 96 | } 97 | 98 | /** 99 | * Tests that we can set using string, array or Traversable object 100 | * 101 | * @test 102 | * @dataProvider provider_set 103 | * 104 | * @return null 105 | */ 106 | public function test_set($data_key, $value, $test_key, $expected) 107 | { 108 | $view = View::factory()->set($data_key, $value); 109 | $this->assertSame($expected, $view->$test_key); 110 | } 111 | 112 | /** 113 | * Tests that we can set global using string, array or Traversable object 114 | * 115 | * @test 116 | * @dataProvider provider_set 117 | * 118 | * @return null 119 | */ 120 | public function test_set_global($data_key, $value, $test_key, $expected) 121 | { 122 | $view = View::factory(); 123 | $view::set_global($data_key, $value); 124 | $this->assertSame($expected, $view->$test_key); 125 | } 126 | } 127 | -------------------------------------------------------------------------------- /tests/kohana/request/client/InternalTest.php: -------------------------------------------------------------------------------- 1 | _log_object = Kohana::$log; 31 | Kohana::$log = NULL; 32 | } 33 | 34 | // @codingStandardsIgnoreStart 35 | public function tearDown() 36 | // @codingStandardsIgnoreEnd 37 | { 38 | // re-assign log object 39 | Kohana::$log = $this->_log_object; 40 | 41 | parent::tearDown(); 42 | } 43 | 44 | public function provider_response_failure_status() 45 | { 46 | return array( 47 | array('', 'Welcome', 'missing_action', 'Welcome/missing_action', 404), 48 | array('kohana3', 'missing_controller', 'index', 'kohana3/missing_controller/index', 404), 49 | array('', 'Template', 'missing_action', 'kohana3/Template/missing_action', 500), 50 | ); 51 | } 52 | 53 | /** 54 | * Tests for correct exception messages 55 | * 56 | * @test 57 | * @dataProvider provider_response_failure_status 58 | * 59 | * @return null 60 | */ 61 | public function test_response_failure_status($directory, $controller, $action, $uri, $expected) 62 | { 63 | // Mock for request object 64 | $request = $this->getMock('Request', array('directory', 'controller', 'action', 'uri', 'response', 'method'), array($uri)); 65 | 66 | $request->expects($this->any()) 67 | ->method('directory') 68 | ->will($this->returnValue($directory)); 69 | 70 | $request->expects($this->any()) 71 | ->method('controller') 72 | ->will($this->returnValue($controller)); 73 | 74 | $request->expects($this->any()) 75 | ->method('action') 76 | ->will($this->returnValue($action)); 77 | 78 | $request->expects($this->any()) 79 | ->method('uri') 80 | ->will($this->returnValue($uri)); 81 | 82 | $request->expects($this->any()) 83 | ->method('response') 84 | ->will($this->returnValue($this->getMock('Response'))); 85 | 86 | // mock `method` method to avoid fatals in newer versions of PHPUnit 87 | $request->expects($this->any()) 88 | ->method('method') 89 | ->withAnyParameters(); 90 | 91 | $internal_client = new Request_Client_Internal; 92 | 93 | $response = $internal_client->execute($request); 94 | 95 | $this->assertSame($expected, $response->status()); 96 | } 97 | } 98 | -------------------------------------------------------------------------------- /tests/test_data/callback_routes.php: -------------------------------------------------------------------------------- 1 | 'welcome', 43 | 'action' => 'index', 44 | ); 45 | } 46 | 47 | /** 48 | * Route callback for test_required_parameters_are_needed 49 | * 50 | * @return array 51 | */ 52 | public static function required_parameters_are_needed($uri) 53 | { 54 | if (substr($uri, 0, 5) == 'admin') 55 | { 56 | return array( 57 | 'controller' => 'foo', 58 | 'action' => 'bar', 59 | ); 60 | } 61 | } 62 | 63 | /** 64 | * Route callback for test reverse_routing_returns_routes_uri_if_route_is_static 65 | * 66 | * @return array 67 | */ 68 | public static function reverse_routing_returns_routes_uri_if_route_is_static($uri) 69 | { 70 | if ($uri == 'info/about_us') 71 | { 72 | return array( 73 | 74 | ); 75 | } 76 | } 77 | 78 | /** 79 | * Route callback for test route_filter_modify_params 80 | * 81 | * @return array 82 | */ 83 | public static function route_filter_modify_params_array(Route $route, $params) 84 | { 85 | $params['action'] = 'modified'; 86 | 87 | return $params; 88 | } 89 | 90 | /** 91 | * Route callback for test route_filter_modify_params 92 | * 93 | * @return array 94 | */ 95 | public static function route_filter_modify_params_false(Route $route, $params) 96 | { 97 | return FALSE; 98 | } 99 | 100 | } -------------------------------------------------------------------------------- /tests/test_data/feeds/activity.atom: -------------------------------------------------------------------------------- 1 | 2 | 3 | Kohana v3.x: Activity 4 | 5 | 6 | http://dev.kohanaframework.org/ 7 | http://dev.kohanaframework.org/favicon.ico?1392677580 8 | 2014-08-28T01:52:12Z 9 | 10 | Kohana Development 11 | 12 | 13 | Redmine 14 | 15 | Proposals (Political/Workflow) #4839 (New) 16 | 17 | http://dev.kohanaframework.org/issues/4839 18 | 2014-08-28T01:52:12Z 19 | 20 | Guillaume Poirier-Morency 21 | guillaumepoiriermorency@gmail.com 22 | 23 | 24 | <p>I have a prototype here <a class="external" href="https://github.com/arteymix/kohana-makefile">https://github.com/arteymix/kohana-makefile</a></p> 25 | 26 | 27 | <p>The tool is very useful for settings permissions and running tests.</p> 28 | 29 | 30 | <p>I think we should consider having a good make tool in the sample application for the 3.4.*.</p> 31 | 32 | 33 | Proposals (Political/Workflow) #4782 34 | 35 | http://dev.kohanaframework.org/issues/4782#change-17279 36 | 2014-08-28T01:44:26Z 37 | 38 | Guillaume Poirier-Morency 39 | guillaumepoiriermorency@gmail.com 40 | 41 | 42 | <p>Moving to composer is a nice idea. This will allow Kohana modules to define a wide range of dependencies.</p> 43 | 44 | 45 | <p>Although, I think that modules designed specifically for Kohana should end in modules and external libraries in application/vendor. This makes a clear dinsinction between what gets autoloaded by the CFS and what gets loaded by composer. Technically, we add "vendor-dir": "application/vendor" in "config" in composer.json.</p> 46 | 47 | 48 | <p>Then, only add a line after the modules loading in bootstrap.php</p> 49 | 50 | 51 | <pre> 52 | // Autoloading composer packages 53 | require Kohana::find_file('vendor', 'autoload'); 54 | </pre> 55 | 56 | <p>This is pretty much what I do right now. This doesn't break anything and allow a full access to composer.</p> 57 | 58 | 59 | -------------------------------------------------------------------------------- /tests/test_data/feeds/example.rss20: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | RSS Title 5 | This is an example of an RSS feed 6 | http://www.example.com/main.html 7 | Mon, 06 Sep 2010 00:01:00 +0000 8 | Sun, 06 Sep 2009 16:20:00 +0000 9 | 1800 10 | 11 | 12 | Example entry 13 | Here is some text containing an interesting description. 14 | http://www.example.com/blog/post/1 15 | 7bd204c6-1655-4c27-aeee-53f933c5395f 16 | Sun, 06 Sep 2009 16:20:00 +0000 17 | 18 | 19 | 20 | 21 | -------------------------------------------------------------------------------- /tests/test_data/github.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kohana/core/bdbe81afb5a09cee4269d2e2210a0d293265231a/tests/test_data/github.png -------------------------------------------------------------------------------- /tests/test_data/message_tests/bottom_module/messages/kohana_core_message_tests.php: -------------------------------------------------------------------------------- 1 | 'inherited bottom message', 5 | 'cfs_replaced' => 'inherited cfs_replaced message', 6 | ); 7 | -------------------------------------------------------------------------------- /tests/test_data/message_tests/top_module/messages/kohana_core_message_tests.php: -------------------------------------------------------------------------------- 1 | 'top only message', 5 | 'cfs_replaced' => 'overriding cfs_replaced message', 6 | ); 7 | -------------------------------------------------------------------------------- /tests/test_data/views/test.css.php: -------------------------------------------------------------------------------- 1 | This is a view with a dot in the filename. -------------------------------------------------------------------------------- /utf8/from_unicode.php: -------------------------------------------------------------------------------- 1 | = 0) AND ($arr[$k] <= 0x007f)) 21 | { 22 | echo chr($arr[$k]); 23 | } 24 | // 2 byte sequence 25 | elseif ($arr[$k] <= 0x07ff) 26 | { 27 | echo chr(0xc0 | ($arr[$k] >> 6)); 28 | echo chr(0x80 | ($arr[$k] & 0x003f)); 29 | } 30 | // Byte order mark (skip) 31 | elseif ($arr[$k] == 0xFEFF) 32 | { 33 | // nop -- zap the BOM 34 | } 35 | // Test for illegal surrogates 36 | elseif ($arr[$k] >= 0xD800 AND $arr[$k] <= 0xDFFF) 37 | { 38 | // Found a surrogate 39 | throw new UTF8_Exception("UTF8::from_unicode: Illegal surrogate at index: ':index', value: ':value'", array( 40 | ':index' => $k, 41 | ':value' => $arr[$k], 42 | )); 43 | } 44 | // 3 byte sequence 45 | elseif ($arr[$k] <= 0xffff) 46 | { 47 | echo chr(0xe0 | ($arr[$k] >> 12)); 48 | echo chr(0x80 | (($arr[$k] >> 6) & 0x003f)); 49 | echo chr(0x80 | ($arr[$k] & 0x003f)); 50 | } 51 | // 4 byte sequence 52 | elseif ($arr[$k] <= 0x10ffff) 53 | { 54 | echo chr(0xf0 | ($arr[$k] >> 18)); 55 | echo chr(0x80 | (($arr[$k] >> 12) & 0x3f)); 56 | echo chr(0x80 | (($arr[$k] >> 6) & 0x3f)); 57 | echo chr(0x80 | ($arr[$k] & 0x3f)); 58 | } 59 | // Out of range 60 | else 61 | { 62 | throw new UTF8_Exception("UTF8::from_unicode: Codepoint out of Unicode range at index: ':index', value: ':value'", array( 63 | ':index' => $k, 64 | ':value' => $arr[$k], 65 | )); 66 | } 67 | } 68 | 69 | $result = ob_get_contents(); 70 | ob_end_clean(); 71 | return $result; 72 | } 73 | -------------------------------------------------------------------------------- /utf8/ltrim.php: -------------------------------------------------------------------------------- 1 | = 0 AND $ord0 <= 127) 16 | return $ord0; 17 | 18 | if ( ! isset($chr[1])) 19 | { 20 | throw new UTF8_Exception('Short sequence - at least 2 bytes expected, only 1 seen'); 21 | } 22 | 23 | $ord1 = ord($chr[1]); 24 | 25 | if ($ord0 >= 192 AND $ord0 <= 223) 26 | return ($ord0 - 192) * 64 + ($ord1 - 128); 27 | 28 | if ( ! isset($chr[2])) 29 | { 30 | throw new UTF8_Exception('Short sequence - at least 3 bytes expected, only 2 seen'); 31 | } 32 | 33 | $ord2 = ord($chr[2]); 34 | 35 | if ($ord0 >= 224 AND $ord0 <= 239) 36 | return ($ord0 - 224) * 4096 + ($ord1 - 128) * 64 + ($ord2 - 128); 37 | 38 | if ( ! isset($chr[3])) 39 | { 40 | throw new UTF8_Exception('Short sequence - at least 4 bytes expected, only 3 seen'); 41 | } 42 | 43 | $ord3 = ord($chr[3]); 44 | 45 | if ($ord0 >= 240 AND $ord0 <= 247) 46 | return ($ord0 - 240) * 262144 + ($ord1 - 128) * 4096 + ($ord2-128) * 64 + ($ord3 - 128); 47 | 48 | if ( ! isset($chr[4])) 49 | { 50 | throw new UTF8_Exception('Short sequence - at least 5 bytes expected, only 4 seen'); 51 | } 52 | 53 | $ord4 = ord($chr[4]); 54 | 55 | if ($ord0 >= 248 AND $ord0 <= 251) 56 | return ($ord0 - 248) * 16777216 + ($ord1-128) * 262144 + ($ord2 - 128) * 4096 + ($ord3 - 128) * 64 + ($ord4 - 128); 57 | 58 | if ( ! isset($chr[5])) 59 | { 60 | throw new UTF8_Exception('Short sequence - at least 6 bytes expected, only 5 seen'); 61 | } 62 | 63 | if ($ord0 >= 252 AND $ord0 <= 253) 64 | return ($ord0 - 252) * 1073741824 + ($ord1 - 128) * 16777216 + ($ord2 - 128) * 262144 + ($ord3 - 128) * 4096 + ($ord4 - 128) * 64 + (ord($chr[5]) - 128); 65 | 66 | if ($ord0 >= 254 AND $ord0 <= 255) 67 | { 68 | throw new UTF8_Exception("Invalid UTF-8 with surrogate ordinal ':ordinal'", array( 69 | ':ordinal' => $ord0, 70 | )); 71 | } 72 | } 73 | -------------------------------------------------------------------------------- /utf8/rtrim.php: -------------------------------------------------------------------------------- 1 | $val) 19 | { 20 | $str[$key] = UTF8::str_ireplace($search, $replace, $val, $count); 21 | } 22 | return $str; 23 | } 24 | 25 | if (is_array($search)) 26 | { 27 | $keys = array_keys($search); 28 | 29 | foreach ($keys as $k) 30 | { 31 | if (is_array($replace)) 32 | { 33 | if (array_key_exists($k, $replace)) 34 | { 35 | $str = UTF8::str_ireplace($search[$k], $replace[$k], $str, $count); 36 | } 37 | else 38 | { 39 | $str = UTF8::str_ireplace($search[$k], '', $str, $count); 40 | } 41 | } 42 | else 43 | { 44 | $str = UTF8::str_ireplace($search[$k], $replace, $str, $count); 45 | } 46 | } 47 | return $str; 48 | } 49 | 50 | $search = UTF8::strtolower($search); 51 | $str_lower = UTF8::strtolower($str); 52 | 53 | $total_matched_strlen = 0; 54 | $i = 0; 55 | 56 | while (preg_match('/(.*?)'.preg_quote($search, '/').'/s', $str_lower, $matches)) 57 | { 58 | $matched_strlen = strlen($matches[0]); 59 | $str_lower = substr($str_lower, $matched_strlen); 60 | 61 | $offset = $total_matched_strlen + strlen($matches[1]) + ($i * (strlen($replace) - 1)); 62 | $str = substr_replace($str, $replace, $offset, strlen($search)); 63 | 64 | $total_matched_strlen += $matched_strlen; 65 | $i++; 66 | } 67 | 68 | $count += $i; 69 | return $str; 70 | } 71 | -------------------------------------------------------------------------------- /utf8/str_pad.php: -------------------------------------------------------------------------------- 1 | $pad_type, 51 | )); 52 | } 53 | -------------------------------------------------------------------------------- /utf8/str_split.php: -------------------------------------------------------------------------------- 1 | = $strlen OR ($length < 0 AND $length <= $offset - $strlen)) 24 | return ''; 25 | 26 | // Whole string 27 | if ($offset == 0 AND ($length === NULL OR $length >= $strlen)) 28 | return $str; 29 | 30 | // Build regex 31 | $regex = '^'; 32 | 33 | // Create an offset expression 34 | if ($offset > 0) 35 | { 36 | // PCRE repeating quantifiers must be less than 65536, so repeat when necessary 37 | $x = (int) ($offset / 65535); 38 | $y = (int) ($offset % 65535); 39 | $regex .= ($x == 0) ? '' : ('(?:.{65535}){'.$x.'}'); 40 | $regex .= ($y == 0) ? '' : ('.{'.$y.'}'); 41 | } 42 | 43 | // Create a length expression 44 | if ($length === NULL) 45 | { 46 | $regex .= '(.*)'; // No length set, grab it all 47 | } 48 | // Find length from the left (positive length) 49 | elseif ($length > 0) 50 | { 51 | // Reduce length so that it can't go beyond the end of the string 52 | $length = min($strlen - $offset, $length); 53 | 54 | $x = (int) ($length / 65535); 55 | $y = (int) ($length % 65535); 56 | $regex .= '('; 57 | $regex .= ($x == 0) ? '' : ('(?:.{65535}){'.$x.'}'); 58 | $regex .= '.{'.$y.'})'; 59 | } 60 | // Find length from the right (negative length) 61 | else 62 | { 63 | $x = (int) (-$length / 65535); 64 | $y = (int) (-$length % 65535); 65 | $regex .= '(.*)'; 66 | $regex .= ($x == 0) ? '' : ('(?:.{65535}){'.$x.'}'); 67 | $regex .= '.{'.$y.'}'; 68 | } 69 | 70 | preg_match('/'.$regex.'/us', $str, $matches); 71 | return $matches[1]; 72 | } 73 | -------------------------------------------------------------------------------- /utf8/substr_replace.php: -------------------------------------------------------------------------------- 1 | 'image/png', 'data' => '{$data}'); ?>"); -------------------------------------------------------------------------------- /views/profiler/stats.php: -------------------------------------------------------------------------------- 1 | 2 | 3 | 6 | 7 | 12 | 13 |
14 | $benchmarks): ?> 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | $tokens): ?> 30 | 31 | 32 | 33 | 34 | 42 | 43 | 44 | 45 | 46 | 54 | 55 | 56 | 57 |
s
kB
35 |
36 |
s
37 | 38 |
39 | 40 |
41 |
47 |
48 |
kB
49 | 50 |
51 | 52 |
53 |
58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 |
s
kB
74 |
75 | -------------------------------------------------------------------------------- /views/profiler/style.css: -------------------------------------------------------------------------------- 1 | .kohana table.profiler { width: 99%; margin: 0 auto 1em; border-collapse: collapse; } 2 | .kohana table.profiler th, 3 | .kohana table.profiler td { padding: 0.2em 0.4em; background: #fff; border: solid 1px #999; border-width: 1px 0; text-align: left; font-weight: normal; font-size: 1em; color: #111; vertical-align: top; text-align: right; } 4 | .kohana table.profiler th.name { text-align: left; } 5 | .kohana table.profiler tr.group th { font-size: 1.4em; background: #222; color: #eee; border-color: #222; } 6 | .kohana table.profiler tr.group td { background: #222; color: #777; border-color: #222; } 7 | .kohana table.profiler tr.group td.time { padding-bottom: 0; } 8 | .kohana table.profiler tr.headers th { text-transform: lowercase; font-variant: small-caps; background: #ddd; color: #777; } 9 | .kohana table.profiler tr.mark th.name { width: 40%; font-size: 1.2em; background: #fff; vertical-align: middle; } 10 | .kohana table.profiler tr.mark td { padding: 0; } 11 | .kohana table.profiler tr.mark.final td { padding: 0.2em 0.4em; } 12 | .kohana table.profiler tr.mark td > div { position: relative; padding: 0.2em 0.4em; } 13 | .kohana table.profiler tr.mark td div.value { position: relative; z-index: 2; } 14 | .kohana table.profiler tr.mark td div.graph { position: absolute; top: 0; bottom: 0; right: 0; left: 100%; background: #71bdf0; z-index: 1; } 15 | .kohana table.profiler tr.mark.memory td div.graph { background: #acd4f0; } 16 | .kohana table.profiler tr.mark td.current { background: #eddecc; } 17 | .kohana table.profiler tr.mark td.min { background: #d2f1cb; } 18 | .kohana table.profiler tr.mark td.max { background: #ead3cb; } 19 | .kohana table.profiler tr.mark td.average { background: #ddd; } 20 | .kohana table.profiler tr.mark td.total { background: #d0e3f0; } 21 | .kohana table.profiler tr.time td { border-bottom: 0; font-weight: bold; } 22 | .kohana table.profiler tr.memory td { border-top: 0; } 23 | .kohana table.profiler tr.final th.name { background: #222; color: #fff; } 24 | .kohana table.profiler abbr { border: 0; color: #777; font-weight: normal; } 25 | .kohana table.profiler:hover tr.group td { color: #ccc; } 26 | .kohana table.profiler:hover tr.mark td div.graph { background: #1197f0; } 27 | .kohana table.profiler:hover tr.mark.memory td div.graph { background: #7cc1f0; } --------------------------------------------------------------------------------