Compare commits

...
This repository has been archived on 2024-04-08. You can view files and clone it, but cannot push or open issues or pull requests.

2 Commits
aer ... master

Author SHA1 Message Date
Deon George
68c7f4f159 Kohana v3.3.5 2016-05-01 20:50:24 +10:00
Deon George
8888719653 Kohana v3.3.2 2014-09-06 23:43:07 +10:00
350 changed files with 6112 additions and 2034 deletions

167
CONTRIBUTING.md Normal file
View File

@ -0,0 +1,167 @@
# Developing locally
Since Kohana maintains many concurrent versions at once, there is no single `master` branch. All versions have branches named with a prefix of its version:
- 3.2/master
- 3.2/develop
- 3.3/master
- 3.3/develop
and so on. All development of versions happens in the develop branch of that version. Before a release, new features are added here. After a major release is actually released, only bugfixes can happen here. New features and API changes must happen in the develop branch of the next version.
## Branch name meanings
- **3.3/master** - master branches are for releases. Only release merge commits can be applied to this branch. You should never make a non-merge commit to this branch, and all merge commits should come from the release branch or hotfix branch (detailed below). This branch lasts forever.
- **3.3/hotfix/*** - hotfix branches are for emergency maintenance after a release. If an important security or other kind of important issue is discovered after a release, it should be done here, and merged to master. This branch should be created from master and merged back into master and develop when complete. This branch is deleted after it's done.
- **3.3/develop** - If a version is not released, this branch is for merging features into. If the version is released, this branch is for applying bugfix commits to. This branch lasts forever.
- **3.3/release/*** - release branches are for maintenance work before a release. This branch should be branched from the develop branch only. Change the version number/code name here, and apply any other maintenance items needed before actually releasing. Merges from master should only come from this branch. It should be merged to develop when it's complete as well. This branch is deleted after it's done.
- **3.3/feature/*** - Details on these branches are outlined below. This branch is deleted after it's done.
If an bug/issue applies to multiple versions of Kohana, it is first fixed in the lowest supported version it applies to, then merged to each higher branch it applies to. Each merge should only happen one version up. 3.1 should merge to 3.2, and 3.2 should merge to 3.3. 3.1 should not merge directly to 3.3.
To work on a specific release branch you need to check it out then check out the appropriate system branch.
Release branch names follow the same convention in both kohana/kohana and kohana/core.
To work on 3.3.x you'd do the following:
> git clone git://github.com/kohana/kohana.git
# ....
> cd kohana
> git submodule update --init
# ....
> git checkout 3.3/develop
# Switched to branch '3.3/develop'
> git submodule foreach "git fetch && git checkout 3.3/develop"
# ...
It's important that you follow the last step, because unlike SVN, Git submodules point at a
specific commit rather than the tip of a branch. If you cd into the system folder after
a `git submodule update` and run `git status` you'll be told:
# Not currently on any branch.
nothing to commit (working directory clean)
***
# Contributing to the project
All features and bugfixes must be fully tested and reference an issue in [GitHub](https://github.com/kohana/kohana/issues), **there are absolutely no exceptions**.
It's highly recommended that you write/run unit tests during development as it can help you pick up on issues early on. See the Unit Testing section below.
## Creating new features
New features or API breaking modifications should be developed in separate branches so as to isolate them
until they're stable.
**Features without tests written will be rejected! There are NO exceptions.**
The naming convention for feature branches is:
{version}/feature/{issue number}-{short hyphenated description}
// e.g.
3.2/feature/4045-rewriting-config-system
When a new feature is complete and fully tested it can be merged into its respective release branch using
`git pull --no-ff`. The `--no-ff` switch is important as it tells Git to always create a commit
detailing what branch you're merging from. This makes it a lot easier to analyse a feature's history.
Here's a quick example:
> git status
# On branch 3.2/feature/4045-rewriting-everything
> git checkout 3.1/develop
# Switched to branch '3.1/develop'
> git merge --no-ff 3.2/feature/4045-rewriting-everything
**If a change you make intentionally breaks the API then please correct the relevant tests before pushing!**
## Bug fixing
If you're making a bugfix then before you start create a unit test which reproduces the bug,
using the `@ticket` notation in the test to reference the bug's issue number
(e.g. `@ticket 4045` for issue #4045).
If you run the unit tests then the one you've just made should fail.
Once you've written the bugfix, run the tests again before you commit to make sure that the
fix actually works, then commit both the fix and the test.
**Bug fixes without tests written will be rejected! There are NO exceptions.**
There is no need to create separate branches for bugfixes, creating them in the main develop
branch is perfectly acceptable.
## Tagging releases
Tag names should be prefixed with a `v`, this helps to separate tag references from branch references in Git.
For example, if you were creating a tag for the `3.1.0` release the tag name would be `v3.1.0`
# Merging changes from remote repositories
Now that you have a remote repository, you can pull changes in the remote "kohana" repository
into your local repository:
> git pull kohana 3.1/master
**Note:** Before you pull changes you should make sure that any modifications you've made locally
have been committed.
Sometimes a commit you've made locally will conflict with one made in the remote "kohana" repo.
There are a couple of scenarios where this might happen:
## The conflict is due to a few unrelated commits and you want to keep changes made in both commits
You'll need to manually modify the files to resolve the conflict, see the "Resolving a merge"
section [in the Git SCM book](http://book.git-scm.com/3_basic_branching_and_merging.html) for more info
## You've fixed something locally which someone else has already done in the remote repo
The simplest way to fix this is to remove all the changes that you've made locally.
You can do this using
> git reset --hard kohana
## You've fixed something locally which someone else has already fixed but you also have separate commits you'd like to keep
If this is the case then you'll want to use a tool called rebase. First of all we need to
get rid of the conflicts created due to the merge:
> git reset --hard HEAD
Then find the hash of the offending local commit and run:
> git rebase -i {offending commit hash}
i.e.
> git rebase -i 57d0b28
A text editor will open with a list of commits. Delete the line containing the offending commit
before saving the file & closing your editor.
Git will remove the commit and you can then pull/merge the remote changes.
# Unit Testing
Kohana currently uses PHPUnit for unit testing. This is installed with composer.
## How to run the tests
* Install [Phing](http://phing.info)
* Make sure you have the [unittest](http://github.com/kohana/unittest) module enabled.
* Install [Composer](http://getcomposer.org)
* Run `php composer.phar install` from the root of this repository
* Finally, run `phing test`
This will run the unit tests for core and all the modules and tell you if anything failed. If you haven't changed anything and you get failures, please create a new issue on [the tracker](http://dev.kohanaframework.org) and paste the output (including the error) in the issue.

View File

@ -56,6 +56,13 @@ spl_autoload_register(array('Kohana', 'auto_load'));
*/
ini_set('unserialize_callback_func', 'spl_autoload_call');
/**
* Set the mb_substitute_character to "none"
*
* @link http://www.php.net/manual/function.mb-substitute-character.php
*/
mb_substitute_character('none');
// -- Configuration and initialization -----------------------------------------
/**
@ -63,6 +70,12 @@ ini_set('unserialize_callback_func', 'spl_autoload_call');
*/
I18n::lang('en-us');
if (isset($_SERVER['SERVER_PROTOCOL']))
{
// Replace the default protocol.
HTTP::$protocol = $_SERVER['SERVER_PROTOCOL'];
}
/**
* Set Kohana::$environment if a 'KOHANA_ENV' environment variable has been supplied.
*
@ -118,6 +131,15 @@ Kohana::modules(array(
// 'userguide' => MODPATH.'userguide', // User guide and API documentation
));
/**
* Cookie Salt
* @see http://kohanaframework.org/3.3/guide/kohana/cookies
*
* If you have not defined a cookie salt in your Cookie class then
* uncomment the line below and define a preferrably long salt.
*/
// Cookie::$salt = NULL;
/**
* Set the routes. Each route must have a minimum of a name, a URI and a set of
* defaults for the URI.

View File

@ -1,5 +1,6 @@
{
"require": {
"phpunit/phpunit": "3.7.*"
"phpunit/phpunit": "3.7.24 - 4",
"phing/phing": "dev-master"
}
}

37
modules/auth/.travis.yml Normal file
View File

@ -0,0 +1,37 @@
sudo: false
language: php
# Only build the main develop/master branches - feature branches will be covered by PRs
branches:
only:
- /^[0-9\.]+\/(develop|master)$/
cache:
directories:
- vendor
- $HOME/.composer/cache
php:
- 5.3
- 5.4
- 5.5
- 5.6
- 7.0
- hhvm
matrix:
include:
- php: 5.3
env: 'COMPOSER_PHPUNIT="lowest"'
before_script:
- composer install --prefer-dist
- if [ "$COMPOSER_PHPUNIT" = "lowest" ]; then composer update --prefer-lowest --with-dependencies phpunit/phpunit; fi;
- vendor/bin/koharness
script:
- cd /tmp/koharness && ./vendor/bin/phpunit --bootstrap=modules/unittest/bootstrap.php modules/unittest/tests.php
notifications:
email: false

View File

@ -1,5 +1,9 @@
New Age Auth
Kohana auth module
---
| ver | Stable | Develop |
|-------|------------------------------------------------------------------------------------------------------------------------------|--------------------------------------------------------------------------------------------------------------------------------|
| 3.3.x | [![Build Status - 3.3/master](https://travis-ci.org/kohana/auth.svg?branch=3.3%2Fmaster)](https://travis-ci.org/kohana/auth) | [![Build Status - 3.3/develop](https://travis-ci.org/kohana/auth.svg?branch=3.3%2Fdevelop)](https://travis-ci.org/kohana/auth) |
| 3.4.x | [![Build Status - 3.4/master](https://travis-ci.org/kohana/auth.svg?branch=3.4%2Fmaster)](https://travis-ci.org/kohana/auth) | [![Build Status - 3.4/develop](https://travis-ci.org/kohana/auth.svg?branch=3.4%2Fdevelop)](https://travis-ci.org/kohana/auth) |
I've forked the main Auth module because there were some fundamental flaws with it:

View File

@ -0,0 +1,41 @@
{
"name": "kohana/auth",
"type": "kohana-module",
"description": "The official Kohana auth module",
"homepage": "http://kohanaframework.org",
"license": "BSD-3-Clause",
"keywords": ["kohana", "framework", "authentication"],
"authors": [
{
"name": "Kohana Team",
"email": "team@kohanaframework.org",
"homepage": "http://kohanaframework.org/team",
"role": "developer"
}
],
"support": {
"issues": "http://dev.kohanaframework.org",
"forum": "http://forum.kohanaframework.org",
"irc": "irc://irc.freenode.net/kohana",
"source": "http://github.com/kohana/core"
},
"require": {
"composer/installers": "~1.0",
"kohana/core": ">=3.3",
"php": ">=5.3.3"
},
"require-dev": {
"kohana/core": "3.3.*@dev",
"kohana/unittest": "3.3.*@dev",
"kohana/koharness": "*@dev"
},
"extra": {
"branch-alias": {
"dev-3.3/develop": "3.3.x-dev",
"dev-3.4/develop": "3.4.x-dev"
},
"installer-paths": {
"vendor/{$vendor}/{$name}": ["type:kohana-module"]
}
}
}

View File

@ -0,0 +1,8 @@
<?php
// Configuration for koharness - builds a standalone skeleton Kohana app for running unit tests
return array(
'modules' => array(
'auth' => __DIR__,
'unittest' => __DIR__ . '/vendor/kohana/unittest'
),
);

45
modules/cache/.travis.yml vendored Normal file
View File

@ -0,0 +1,45 @@
sudo: false
language: php
# Only build the main develop/master branches - feature branches will be covered by PRs
branches:
only:
- /^[0-9\.]+\/(develop|master)$/
cache:
directories:
- vendor
- $HOME/.composer/cache
php:
- 5.3
- 5.4
- 5.5
- 5.6
- 7.0
- hhvm
matrix:
include:
- php: 5.3
env: 'COMPOSER_PHPUNIT="lowest"'
services:
- memcached
before_script:
- if [[ $TRAVIS_PHP_VERSION != "hhvm" ]]; then INI_FILE=~/.phpenv/versions/$(phpenv version-name)/etc/conf.d/travis.ini; else INI_FILE=/etc/hhvm/php.ini; fi;
- if [[ $TRAVIS_PHP_VERSION = 5.* ]]; then echo extension = memcache.so >> $INI_FILE; fi;
- if [[ $TRAVIS_PHP_VERSION = 5.* ]]; then (echo yes | pecl install -f apcu-4.0.10 && echo apc.enable_cli = 1 >> $INI_FILE); fi;
- if [[ $TRAVIS_PHP_VERSION = 7.* ]]; then (echo yes | pecl install -f apcu-5.1.2 && echo apc.enable_cli = 1 >> $INI_FILE); fi;
- if [[ $TRAVIS_PHP_VERSION != "hhvm" ]] ; then echo -e 'apc.max_file_size = 0\napc.cache_by_default = 0' >> $INI_FILE ; fi
- composer install --prefer-dist
- if [ "$COMPOSER_PHPUNIT" = "lowest" ]; then composer update --prefer-lowest --with-dependencies phpunit/phpunit; fi;
- vendor/bin/koharness
script:
- cd /tmp/koharness && ./vendor/bin/phpunit --bootstrap=modules/unittest/bootstrap.php modules/unittest/tests.php
notifications:
email: false

View File

@ -1,6 +1,12 @@
Kohana Cache library
====================
| ver | Stable | Develop |
|-------|--------------------------------------------------------------------------------------------------------------------------------------|----------------------------------------------------------------------------------------------------------------------------------------|
| 3.3.x | [![Build Status - 3.3/master](https://travis-ci.org/kohana/cache.svg?branch=3.3%2Fmaster)](https://travis-ci.org/kohana/cache) | [![Build Status - 3.3/develop](https://travis-ci.org/kohana/cache.svg?branch=3.3%2Fdevelop)](https://travis-ci.org/kohana/cache) |
| 3.4.x | [![Build Status - 3.4/master](https://travis-ci.org/kohana/cache.svg?branch=3.4%2Fmaster)](https://travis-ci.org/kohana/cache) | [![Build Status - 3.4/develop](https://travis-ci.org/kohana/cache.svg?branch=3.4%2Fdevelop)](https://travis-ci.org/kohana/cache) |
The cache library for Kohana 3 provides a simple interface to the most common cache solutions. Developers are free to add their own caching solutions that follow the cache design pattern defined within this module.
Supported cache solutions

3
modules/cache/classes/Cache/Apcu.php vendored Normal file
View File

@ -0,0 +1,3 @@
<?php defined('SYSPATH') or die('No direct script access.');
class Cache_Apcu extends Kohana_Cache_Apcu {}

View File

@ -36,7 +36,7 @@
* Below is an example of a _memcache_ server configuration.
*
* return array(
* 'default' => array( // Default group
* 'memcache' => array( // Name of group
* 'driver' => 'memcache', // using Memcache driver
* 'servers' => array( // Available server definitions
* array(
@ -49,8 +49,12 @@
* ),
* )
*
* In cases where only one cache group is required, if the group is named `default` there is
* no need to pass the group name when instantiating a cache instance.
* In cases where only one cache group is required, set `Cache::$default` (in your bootstrap,
* or by extending `Kohana_Cache` class) to the name of the group, and use:
*
* $cache = Cache::instance(); // instead of Cache::instance('memcache')
*
* It will return the cache instance of the group it has been set in `Cache::$default`.
*
* #### General cache group configuration settings
*

View File

@ -0,0 +1,174 @@
<?php defined('SYSPATH') or die('No direct script access.');
/**
* [Kohana Cache](api/Kohana_Cache) APCu data store driver for Kohana Cache
* library.
*
* ### Configuration example
*
* Below is an example of an _apcu_ server configuration.
*
* return array(
* 'apcu' => array( // Driver group
* 'driver' => 'apcu', // using APCu driver
* ),
* )
*
* In cases where only one cache group is required, if the group is named `default` there is
* no need to pass the group name when instantiating a cache instance.
*
* #### General cache group configuration settings
*
* Below are the settings available to all types of cache driver.
*
* Name | Required | Description
* -------------- | -------- | ---------------------------------------------------------------
* driver | __YES__ | (_string_) The driver type to use
*
* ### System requirements
*
* * Kohana 3.0.x
* * PHP 5.2.4 or greater
* * APCu PHP extension
*
* @package Kohana/Cache
* @category Base
* @author Kohana Team
* @copyright (c) 2009-2012 Kohana Team
* @license http://kohanaphp.com/license
*/
class Kohana_Cache_Apcu extends Cache implements Cache_Arithmetic {
/**
* Check for existence of the APCu extension This method cannot be invoked externally. The driver must
* be instantiated using the `Cache::instance()` method.
*
* @param array $config configuration
* @throws Cache_Exception
*/
protected function __construct(array $config)
{
if ( ! extension_loaded('apcu'))
{
throw new Cache_Exception('PHP APCu extension is not available.');
}
parent::__construct($config);
}
/**
* Retrieve a cached value entry by id.
*
* // Retrieve cache entry from apcu group
* $data = Cache::instance('apcu')->get('foo');
*
* // Retrieve cache entry from apcu group and return 'bar' if miss
* $data = Cache::instance('apcu')->get('foo', 'bar');
*
* @param string $id id of cache to entry
* @param string $default default value to return if cache miss
* @return mixed
* @throws Cache_Exception
*/
public function get($id, $default = NULL)
{
$data = apcu_fetch($this->_sanitize_id($id), $success);
return $success ? $data : $default;
}
/**
* Set a value to cache with id and lifetime
*
* $data = 'bar';
*
* // Set 'bar' to 'foo' in apcu group, using default expiry
* Cache::instance('apcu')->set('foo', $data);
*
* // Set 'bar' to 'foo' in apcu group for 30 seconds
* Cache::instance('apcu')->set('foo', $data, 30);
*
* @param string $id id of cache entry
* @param string $data data to set to cache
* @param integer $lifetime lifetime in seconds
* @return boolean
*/
public function set($id, $data, $lifetime = NULL)
{
if ($lifetime === NULL)
{
$lifetime = Arr::get($this->_config, 'default_expire', Cache::DEFAULT_EXPIRE);
}
return apcu_store($this->_sanitize_id($id), $data, $lifetime);
}
/**
* Delete a cache entry based on id
*
* // Delete 'foo' entry from the apcu group
* Cache::instance('apcu')->delete('foo');
*
* @param string $id id to remove from cache
* @return boolean
*/
public function delete($id)
{
return apcu_delete($this->_sanitize_id($id));
}
/**
* Delete all cache entries.
*
* Beware of using this method when
* using shared memory cache systems, as it will wipe every
* entry within the system for all clients.
*
* // Delete all cache entries in the apcu group
* Cache::instance('apcu')->delete_all();
*
* @return boolean
*/
public function delete_all()
{
return apcu_clear_cache();
}
/**
* Increments a given value by the step value supplied.
* Useful for shared counters and other persistent integer based
* tracking.
*
* @param string id of cache entry to increment
* @param int step value to increment by
* @return integer
* @return boolean
*/
public function increment($id, $step = 1)
{
if (apcu_exists($id)) {
return apcu_inc($id, $step);
} else {
return FALSE;
}
}
/**
* Decrements a given value by the step value supplied.
* Useful for shared counters and other persistent integer based
* tracking.
*
* @param string id of cache entry to decrement
* @param int step value to decrement by
* @return integer
* @return boolean
*/
public function decrement($id, $step = 1)
{
if (apcu_exists($id)) {
return apcu_dec($id, $step);
} else {
return FALSE;
}
}
} // End Kohana_Cache_Apcu

View File

@ -140,17 +140,21 @@ class Kohana_Cache_File extends Cache implements Cache_GarbageCollect {
}
else
{
// Open the file and parse data
$created = $file->getMTime();
$data = $file->openFile();
$lifetime = $data->fgets();
// If we're at the EOF at this point, corrupted!
if ($data->eof())
// Test the expiry
if ($this->_is_expired($file))
{
throw new Cache_Exception(__METHOD__.' corrupted cache file!');
// Delete the file
$this->_delete_file($file, FALSE, TRUE);
return $default;
}
// open the file to read data
$data = $file->openFile();
// Run first fgets(). Cache data starts from the second line
// as the first contains the lifetime timestamp
$data->fgets();
$cache = '';
while ($data->eof() === FALSE)
@ -158,17 +162,7 @@ class Kohana_Cache_File extends Cache implements Cache_GarbageCollect {
$cache .= $data->fgets();
}
// Test the expiry
if (($created + (int) $lifetime) < time())
{
// Delete the file
$this->_delete_file($file, NULL, TRUE);
return $default;
}
else
{
return unserialize($cache);
}
return unserialize($cache);
}
}
@ -219,14 +213,7 @@ class Kohana_Cache_File extends Cache implements Cache_GarbageCollect {
// If the directory path is not a directory
if ( ! $dir->isDir())
{
// Create the directory
if ( ! mkdir($directory, 0777, TRUE))
{
throw new Cache_Exception(__METHOD__.' unable to create directory : :directory', array(':directory' => $directory));
}
// chmod to solve potential umask issues
chmod($directory, 0777);
$this->_make_directory($directory, 0777, TRUE);
}
// Open file to inspect
@ -267,7 +254,7 @@ class Kohana_Cache_File extends Cache implements Cache_GarbageCollect {
$filename = Cache_File::filename($this->_sanitize_id($id));
$directory = $this->_resolve_directory($filename);
return $this->_delete_file(new SplFileInfo($directory.$filename), NULL, TRUE);
return $this->_delete_file(new SplFileInfo($directory.$filename), FALSE, TRUE);
}
/**
@ -337,9 +324,7 @@ class Kohana_Cache_File extends Cache implements Cache_GarbageCollect {
else
{
// Assess the file expiry to flag it for deletion
$json = $file->openFile('r')->current();
$data = json_decode($json);
$delete = $data->expiry < time();
$delete = $this->_is_expired($file);
}
// If the delete flag is set delete file
@ -375,7 +360,7 @@ class Kohana_Cache_File extends Cache implements Cache_GarbageCollect {
// Create new file resource
$fp = new SplFileInfo($files->getRealPath());
// Delete the file
$this->_delete_file($fp);
$this->_delete_file($fp, $retain_parent_directory, $ignore_errors, $only_expired);
}
// Move the file pointer on
@ -446,21 +431,55 @@ class Kohana_Cache_File extends Cache implements Cache_GarbageCollect {
* `mkdir` to ensure DRY principles
*
* @link http://php.net/manual/en/function.mkdir.php
* @param string $directory
* @param integer $mode
* @param boolean $recursive
* @param resource $context
* @param string $directory directory path
* @param integer $mode chmod mode
* @param boolean $recursive allows nested directories creation
* @param resource $context a stream context
* @return SplFileInfo
* @throws Cache_Exception
*/
protected function _make_directory($directory, $mode = 0777, $recursive = FALSE, $context = NULL)
{
if ( ! mkdir($directory, $mode, $recursive, $context))
// call mkdir according to the availability of a passed $context param
$mkdir_result = $context ?
mkdir($directory, $mode, $recursive, $context) :
mkdir($directory, $mode, $recursive);
// throw an exception if unsuccessful
if ( ! $mkdir_result)
{
throw new Cache_Exception('Failed to create the defined cache directory : :directory', array(':directory' => $directory));
}
// chmod to solve potential umask issues
chmod($directory, $mode);
return new SplFileInfo($directory);
}
/**
* Test if cache file is expired
*
* @param SplFileInfo $file the cache file
* @return boolean TRUE if expired false otherwise
*/
protected function _is_expired(SplFileInfo $file)
{
// Open the file and parse data
$created = $file->getMTime();
$data = $file->openFile("r");
$lifetime = (int) $data->fgets();
// If we're at the EOF at this point, corrupted!
if ($data->eof())
{
throw new Cache_Exception(__METHOD__ . ' corrupted cache file!');
}
//close file
$data = null;
// test for expiry and return
return (($lifetime !== 0) AND ( ($created + $lifetime) < time()));
}
}

View File

@ -1,6 +1,6 @@
<?php defined('SYSPATH') or die('No direct script access.');
/**
* HTTT Caching adaptor class that provides caching services to the
* HTTP Caching adaptor class that provides caching services to the
* [Request_Client] class, using HTTP cache control logic as defined in
* RFC 2616.
*
@ -36,7 +36,7 @@ class Kohana_HTTP_Cache {
* )
* );
*
* @uses [Cache]
* @uses Cache
* @param mixed $cache cache engine to use
* @param array $options options to set to this class
* @return HTTP_Cache
@ -298,7 +298,7 @@ class Kohana_HTTP_Cache {
* Controls whether the response can be cached. Uses HTTP
* protocol to determine whether the response can be cached.
*
* @link RFC 2616 http://www.w3.org/Protocols/rfc2616/
* @link http://www.w3.org/Protocols/rfc2616/rfc2616.html RFC 2616
* @param Response $response The Response
* @return boolean
*/

41
modules/cache/composer.json vendored Normal file
View File

@ -0,0 +1,41 @@
{
"name": "kohana/cache",
"type": "kohana-module",
"description": "The official Kohana cache management module",
"homepage": "http://kohanaframework.org",
"license": "BSD-3-Clause",
"keywords": ["kohana", "framework", "cache"],
"authors": [
{
"name": "Kohana Team",
"email": "team@kohanaframework.org",
"homepage": "http://kohanaframework.org/team",
"role": "developer"
}
],
"support": {
"issues": "http://dev.kohanaframework.org",
"forum": "http://forum.kohanaframework.org",
"irc": "irc://irc.freenode.net/kohana",
"source": "http://github.com/kohana/core"
},
"require": {
"composer/installers": "~1.0",
"kohana/core": ">=3.3",
"php": ">=5.3.3"
},
"require-dev": {
"kohana/core": "3.3.*@dev",
"kohana/unittest": "3.3.*@dev",
"kohana/koharness": "*@dev"
},
"extra": {
"branch-alias": {
"dev-3.3/develop": "3.3.x-dev",
"dev-3.4/develop": "3.4.x-dev"
},
"installer-paths": {
"vendor/{$vendor}/{$name}": ["type:kohana-module"]
}
}
}

View File

@ -55,7 +55,7 @@ failure_callback | __NO__ | (_[callback](http://www.php.net/manual/en/language
'driver' => 'memcache',
'default_expire' => 3600,
'compression' => FALSE, // Use Zlib compression
(can cause issues with integers)
// (can cause issues with integers)
'servers' => array
(
'local' => array
@ -71,7 +71,7 @@ failure_callback | __NO__ | (_[callback](http://www.php.net/manual/en/language
'driver' => 'memcachetag',
'default_expire' => 3600,
'compression' => FALSE, // Use Zlib compression
(can cause issues with integers)
// (can cause issues with integers)
'servers' => array
(
'local' => array
@ -91,6 +91,14 @@ failure_callback | __NO__ | (_[callback](http://www.php.net/manual/en/language
'default_expire' => 3600,
),
## APCu settings
'apcu' => array
(
'driver' => 'apcu',
'default_expire' => 3600,
),
## SQLite settings
'sqlite' => array

View File

@ -6,7 +6,7 @@ instances of cache engines through a grouped singleton pattern.
## Supported cache engines
* APC ([Cache_Apc])
* APC/APCu ([Cache_Apc])
* File ([Cache_File])
* Memcached ([Cache_Memcache])
* Memcached-tags ([Cache_Memcachetag])
@ -16,13 +16,13 @@ instances of cache engines through a grouped singleton pattern.
## Introduction to caching
Caching should be implemented with consideration. Generally, caching the result of resources
is faster than reprocessing them. Choosing what, how and when to cache is vital. [PHP APC](http://php.net/manual/en/book.apc.php) is one of the fastest caching systems available, closely followed by [Memcached](http://memcached.org/). [SQLite](http://www.sqlite.org/) and File caching are two of the slowest cache methods, however usually faster than reprocessing
is faster than reprocessing them. Choosing what, how and when to cache is vital. [PHP APCu](http://php.net/manual/en/book.apcu.php) is one of the fastest caching systems available, closely followed by [Memcached](http://memcached.org/). [SQLite](http://www.sqlite.org/) and File caching are two of the slowest cache methods, however usually faster than reprocessing
a complex set of instructions.
Caching engines that use memory are considerably faster than file based alternatives. But
memory is limited whereas disk space is plentiful. If caching large datasets, such as large database result sets, it is best to use file caching.
[!!] Cache drivers require the relevant PHP extensions to be installed. APC, eAccelerator, Memecached and Xcache all require non-standard PHP extensions.
[!!] Cache drivers require the relevant PHP extensions to be installed. APC, eAccelerator, Memecached and Xcache all require non-standard PHP extensions.
## What the Kohana Cache module does (and does not do)
@ -43,7 +43,7 @@ Getting and setting values to cache is very simple when using the _Kohana Cache_
Driver | Storage | Speed | Tags | Distributed | Automatic Garbage Collection | Notes
---------------- | ------------ | --------- | -------- | ----------- | ---------------------------- | -----------------------
APC | __Memory__ | Excellent | No | No | Yes | Widely available PHP opcode caching solution, improves php execution performance
APC/APCu | __Memory__ | Excellent | No | No | Yes | Widely available PHP opcode caching solution, improves php execution performance
Wincache | __Memory__ | Excellent | No | No | Yes | Windows variant of APC
File | __Disk__ | Poor | No | No | No | Marginally faster than execution
Memcache (tag) | __Memory__ | Good | No (yes) | Yes | Yes | Generally fast distributed solution, but has a speed hit due to variable network latency and serialization

View File

@ -9,7 +9,7 @@ Creating a new _Kohana Cache_ instance is simple, however it must be done using
// Create a new instance of cache using the default group
$cache = Cache::instance();
The default group will use whatever is set to [Cache::$default] and must have a corresponding [configuration](cache.config) definition for that group.
The default group will use whatever is set to [Cache::$default] and must have a corresponding [configuration](config) definition for that group.
To create a cache instance using a group other than the _default_, simply provide the group name as an argument.
@ -18,7 +18,7 @@ To create a cache instance using a group other than the _default_, simply provid
If there is a cache instance already instantiated then you can get it directly from the class member.
[!!] Beware that this can cause issues if you do not test for the instance before trying to access it.
[!!] Beware that this can cause issues if you do not test for the instance before trying to access it.
// Check for the existance of the cache driver
if (isset(Cache::$instances['memcache']))
@ -36,11 +36,11 @@ If there is a cache instance already instantiated then you can get it directly f
The cache library supports scalar and object values, utilising object serialization where required (or not supported by the caching engine). This means that the majority or objects can be cached without any modification.
[!!] Serialisation does not work with resource handles, such as filesystem, curl or socket resources.
[!!] Serialisation does not work with resource handles, such as filesystem, curl or socket resources.
### Setting a value to cache
Setting a value to cache using the [Cache::set] method can be done in one of two ways; either using the Cache instance interface, which is good for atomic operations; or getting an instance and using that for multiple operations.
Setting a value to cache using the [Cache::set] method can be done in one of two ways: either using the Cache instance interface, which is good for atomic operations, or getting an instance and using that for multiple operations.
The first example demonstrates how to quickly load and set a value to the default cache instance.
@ -104,7 +104,7 @@ In cases where the requested key is not available or the entry has expired, a de
It is possible to retrieve values from cache grouped by tag, using the [Cache::find] method with drivers that support tagging.
[!!] The __Memcachetag__ driver does not support the `Cache::find($tag)` interface and will throw an exception.
[!!] The __Memcachetag__ driver does not support the `Cache::find($tag)` interface and will throw an exception.
// Get an instance of cache
$cache = Cache::instance('memcachetag');

9
modules/cache/koharness.php vendored Normal file
View File

@ -0,0 +1,9 @@
<?php
// Configuration for koharness - builds a standalone skeleton Kohana app for running unit tests
return array(
'kohana_version' => '3.3',
'modules' => array(
'cache' => __DIR__,
'unittest' => __DIR__ . '/vendor/kohana/unittest'
),
);

View File

@ -164,6 +164,17 @@ TESTTEXT;
),
'foo bar snafu'
),
array(
array(
'id' => 'test ttl 0 means never expire',
'value' => 'cache value that should last',
'ttl' => 0,
'wait' => 1,
'type' => 'string',
'default' => NULL
),
'cache value that should last'
),
array(
array(
'id' => 'bar',
@ -196,6 +207,28 @@ TESTTEXT;
'default' => NULL,
),
$html_text
),
array(
array(
'id' => 'test with 60*5',
'value' => 'blabla',
'ttl' => 60*5,
'wait' => FALSE,
'type' => 'string',
'default' => NULL,
),
'blabla'
),
array(
array(
'id' => 'test with 60*50',
'value' => 'bla bla',
'ttl' => 60*50,
'wait' => FALSE,
'type' => 'string',
'default' => NULL,
),
'bla bla'
)
);
}

View File

@ -90,14 +90,13 @@ class Kohana_CacheTest extends PHPUnit_Framework_TestCase {
*/
public function test_cloning_fails()
{
if ( ! Kohana::$config->load('cache.file'))
{
$this->markTestSkipped('Unable to load File configuration');
}
$cache = $this->getMockBuilder('Cache')
->disableOriginalConstructor()
->getMockForAbstractClass();
try
{
$cache_clone = clone(Cache::instance('file'));
clone($cache);
}
catch (Cache_Exception $e)
{

View File

@ -30,7 +30,21 @@ class Kohana_Cache_FileTest extends Kohana_CacheBasicMethodsTest {
if ( ! Kohana::$config->load('cache.file'))
{
$this->markTestSkipped('Unable to load File configuration');
Kohana::$config->load('cache')
->set(
'file',
array(
'driver' => 'file',
'cache_dir' => APPPATH.'cache',
'default_expire' => 3600,
'ignore_on_delete' => array(
'file_we_want_to_keep.cache',
'.gitignore',
'.git',
'.svn'
)
)
);
}
$this->cache(Cache::instance('file'));
@ -45,7 +59,7 @@ class Kohana_Cache_FileTest extends Kohana_CacheBasicMethodsTest {
{
$cache = $this->cache();
$config = Kohana::$config->load('cache')->file;
$file = $config['cache_dir'].'/.gitignore';
$file = $config['cache_dir'].'/file_we_want_to_keep.cache';
// Lets pollute the cache folder
file_put_contents($file, 'foobar');
@ -95,4 +109,55 @@ class Kohana_Cache_FileTest extends Kohana_CacheBasicMethodsTest {
$this->assertSame($expected, $cache->get('utf8'));
}
/**
* Tests garbage collection.
* Tests if non-expired cache files withstand garbage collection
*
* @test
*/
public function test_garbage_collection()
{
$cache = $this->cache();
$cache->set('persistent', 'dummy persistent data', 3);
$cache->set('volatile', 'dummy volatile data', 1);
$this->assertTrue($this->is_file('persistent'));
$this->assertTrue($this->is_file('volatile'));
// sleep for more than a second
sleep(2);
$cache->garbage_collect();
$this->assertTrue($this->is_file('persistent'));
$this->assertFalse($this->is_file('volatile'));
}
/**
* helper method for test_garbage_collection.
* Tests if cache file exists given cache id.
*
* @param string $id cache id
* @return boolean TRUE if file exists FALSE otherwise
*/
protected function is_file($id)
{
$cache = $this->cache();
$method_sanitize_id = new ReflectionMethod($cache, '_sanitize_id');
$method_sanitize_id->setAccessible(TRUE);
$method_filename = new ReflectionMethod($cache, 'filename');
$method_filename->setAccessible(TRUE);
$method_resolve_directory = new ReflectionMethod($cache, '_resolve_directory');
$method_resolve_directory->setAccessible(TRUE);
$sanitized_id = $method_sanitize_id->invoke($cache, $id);
$filename = $method_filename->invoke($cache, $sanitized_id);
$directory = $method_resolve_directory->invoke($cache, $filename);
$file = new SplFileInfo($directory.$filename);
//var_dump($cache->_is_expired($file));
return $file->isFile();
}
} // End Kohana_SqliteTest

View File

@ -35,7 +35,16 @@ class Kohana_SqliteTest extends Kohana_CacheBasicMethodsTest {
if ( ! Kohana::$config->load('cache.sqlite'))
{
$this->markTestIncomplete('Unable to load sqlite configuration');
Kohana::$config->load('cache')
->set(
'sqlite',
array(
'driver' => 'sqlite',
'default_expire' => 3600,
'database' => 'memory',
'schema' => 'CREATE TABLE caches(id VARCHAR(127) PRIMARY KEY, tags VARCHAR(255), expiration INTEGER, cache TEXT)',
)
);
}
$this->cache(Cache::instance('sqlite'));

View File

@ -1,39 +1,49 @@
<?php
include_once(Kohana::find_file('tests/cache', 'CacheBasicMethodsTest'));
/**
* @package Kohana/Cache
* @group kohana
* @group kohana.cache
* @category Test
* @author Kohana Team
* @copyright (c) 2009-2012 Kohana Team
* @license http://kohanaphp.com/license
*/
class Kohana_WincacheTest extends Kohana_CacheBasicMethodsTest {
if (isset($_ENV['TRAVIS']))
{
// This is really hacky, but without it the result is permanently full of noise that makes it impossible to see
// any unexpected skipped tests.
print "Skipping all Wincache driver tests as these will never run on Travis.".\PHP_EOL;
return;
}
else
{
include_once(Kohana::find_file('tests/cache', 'CacheBasicMethodsTest'));
/**
* This method MUST be implemented by each driver to setup the `Cache`
* instance for each test.
*
* This method should do the following tasks for each driver test:
*
* - Test the Cache instance driver is available, skip test otherwise
* - Setup the Cache instance
* - Call the parent setup method, `parent::setUp()`
*
* @return void
* @package Kohana/Cache
* @group kohana
* @group kohana.cache
* @category Test
* @author Kohana Team
* @copyright (c) 2009-2012 Kohana Team
* @license http://kohanaphp.com/license
*/
public function setUp()
{
parent::setUp();
class Kohana_WincacheTest extends Kohana_CacheBasicMethodsTest {
if ( ! extension_loaded('wincache'))
/**
* This method MUST be implemented by each driver to setup the `Cache`
* instance for each test.
*
* This method should do the following tasks for each driver test:
*
* - Test the Cache instance driver is available, skip test otherwise
* - Setup the Cache instance
* - Call the parent setup method, `parent::setUp()`
*
* @return void
*/
public function setUp()
{
$this->markTestSkipped('Wincache PHP Extension is not available');
parent::setUp();
if ( ! extension_loaded('wincache'))
{
$this->markTestSkipped('Wincache PHP Extension is not available');
}
$this->cache(Cache::instance('wincache'));
}
$this->cache(Cache::instance('wincache'));
}
} // End Kohana_WincacheTest
} // End Kohana_WincacheTest
}

View File

@ -39,6 +39,18 @@ class Kohana_ApcTest extends Kohana_CacheArithmeticMethodsTest {
'place "apc.enable_cli=1" in your php.ini file');
}
if ( ! Kohana::$config->load('cache.apc'))
{
Kohana::$config->load('cache')
->set(
'apc',
array(
'driver' => 'apc',
'default_expire' => 3600,
)
);
}
$this->cache(Cache::instance('apc'));
}

View File

@ -0,0 +1,87 @@
<?php
include_once(Kohana::find_file('tests/cache/arithmetic', 'CacheArithmeticMethods'));
/**
* @package Kohana/Cache
* @group kohana
* @group kohana.cache
* @category Test
* @author Kohana Team
* @copyright (c) 2009-2012 Kohana Team
* @license http://kohanaphp.com/license
*/
class Kohana_ApcuTest extends Kohana_CacheArithmeticMethodsTest {
/**
* This method MUST be implemented by each driver to setup the `Cache`
* instance for each test.
*
* This method should do the following tasks for each driver test:
*
* - Test the Cache instance driver is available, skip test otherwise
* - Setup the Cache instance
* - Call the parent setup method, `parent::setUp()`
*
* @return void
*/
public function setUp()
{
parent::setUp();
if ( ! extension_loaded('apcu'))
{
$this->markTestSkipped('APCu PHP Extension is not available');
}
if ( ! (ini_get('apc.enabled') AND ini_get('apc.enable_cli')))
{
$this->markTestSkipped('APCu is not enabled. To fix '.
'set "apc.enabled=1" and "apc.enable_cli=1" in your php.ini file');
}
if ( ! Kohana::$config->load('cache.apcu'))
{
Kohana::$config->load('cache')
->set(
'apcu',
array(
'driver' => 'apcu',
'default_expire' => 3600,
)
);
}
$this->cache(Cache::instance('apcu'));
}
/**
* Tests the [Cache::set()] method, testing;
*
* - The value is cached
* - The lifetime is respected
* - The returned value type is as expected
* - The default not-found value is respected
*
* This test doesn't test the TTL as there is a known bug/feature
* in APCu that prevents the same request from killing cache on timeout.
*
* @link http://pecl.php.net/bugs/bug.php?id=16814
*
* @dataProvider provider_set_get
*
* @param array data
* @param mixed expected
* @return void
*/
public function test_set_get(array $data, $expected)
{
if ($data['wait'] !== FALSE)
{
$this->markTestSkipped('Unable to perform TTL test in CLI, see: '.
'http://pecl.php.net/bugs/bug.php?id=16814 for more info!');
}
parent::test_set_get($data, $expected);
}
} // End Kohana_ApcuTest

View File

@ -35,7 +35,28 @@ class Kohana_CacheArithmeticMemcacheTest extends Kohana_CacheArithmeticMethodsTe
}
if ( ! $config = Kohana::$config->load('cache.memcache'))
{
$this->markTestSkipped('Unable to load Memcache configuration');
Kohana::$config->load('cache')
->set(
'memcache',
array(
'driver' => 'memcache',
'default_expire' => 3600,
'compression' => FALSE, // Use Zlib compression (can cause issues with integers)
'servers' => array(
'local' => array(
'host' => 'localhost', // Memcache Server
'port' => 11211, // Memcache port number
'persistent' => FALSE, // Persistent connection
'weight' => 1,
'timeout' => 1,
'retry_interval' => 15,
'status' => TRUE,
),
),
'instant_death' => TRUE,
)
);
$config = Kohana::$config->load('cache.memcache');
}
$memcache = new Memcache;

View File

@ -0,0 +1,37 @@
sudo: false
language: php
# Only build the main develop/master branches - feature branches will be covered by PRs
branches:
only:
- /^[0-9\.]+\/(develop|master)$/
cache:
directories:
- vendor
- $HOME/.composer/cache
php:
- 5.3
- 5.4
- 5.5
- 5.6
- 7.0
- hhvm
matrix:
include:
- php: 5.3
env: 'COMPOSER_PHPUNIT="lowest"'
before_script:
- composer install --prefer-dist
- if [ "$COMPOSER_PHPUNIT" = "lowest" ]; then composer update --prefer-lowest --with-dependencies phpunit/phpunit; fi;
- vendor/bin/koharness
script:
- cd /tmp/koharness && ./vendor/bin/phpunit --bootstrap=modules/unittest/bootstrap.php modules/unittest/tests.php
notifications:
email: false

View File

@ -0,0 +1,41 @@
{
"name": "kohana/codebench",
"type": "kohana-module",
"description": "The official Kohana benchmarking module",
"homepage": "http://kohanaframework.org",
"license": "BSD-3-Clause",
"keywords": ["kohana", "framework", "benchmarking"],
"authors": [
{
"name": "Kohana Team",
"email": "team@kohanaframework.org",
"homepage": "http://kohanaframework.org/team",
"role": "developer"
}
],
"support": {
"issues": "http://dev.kohanaframework.org",
"forum": "http://forum.kohanaframework.org",
"irc": "irc://irc.freenode.net/kohana",
"source": "http://github.com/kohana/core"
},
"require": {
"composer/installers": "~1.0",
"kohana/core": ">=3.3",
"php": ">=5.3.3"
},
"require-dev": {
"kohana/core": "3.3.*@dev",
"kohana/unittest": "3.3.*@dev",
"kohana/koharness": "*@dev"
},
"extra": {
"branch-alias": {
"dev-3.3/develop": "3.3.x-dev",
"dev-3.4/develop": "3.4.x-dev"
},
"installer-paths": {
"vendor/{$vendor}/{$name}": ["type:kohana-module"]
}
}
}

View File

@ -26,7 +26,7 @@ Throwing valuable benchmark data away every time I needed to optimize another re
Obviously providing a visual representation of the benchmark results, via simple graphs, would make interpreting them easier. Having not to think about Internet Explorer for once, made writing CSS a whole lot more easy and fun. It resulted in some fine graphs which are fully resizable.
Below are two screenshots of Codebench in action. `Valid_Color` is a class made for benchmarking different ways to validate hexadecimal HTML color values, e.g. `#FFF`. If you are interested in the story behind the actual regular expressions, take a look at [this topic in the Kohana forums](http://forum.kohanaphp.com/comments.php?DiscussionID=2192).
Below are two screenshots of Codebench in action. `Valid_Color` is a class made for benchmarking different ways to validate hexadecimal HTML color values, e.g. `#FFF`. If you are interested in the story behind the actual regular expressions, take a look at [this topic in the Kohana forums](http://forum.kohanaframework.org/discussion/2192).
![Benchmarking several ways to validate HTML color values](codebench_screenshot1.png)
**Benchmarking seven ways to validate HTML color values**

View File

@ -0,0 +1,8 @@
<?php
// Configuration for koharness - builds a standalone skeleton Kohana app for running unit tests
return array(
'modules' => array(
'codebench' => __DIR__,
'unittest' => __DIR__ . '/vendor/kohana/unittest'
),
);

View File

@ -0,0 +1,37 @@
sudo: false
language: php
# Only build the main develop/master branches - feature branches will be covered by PRs
branches:
only:
- /^[0-9\.]+\/(develop|master)$/
cache:
directories:
- vendor
- $HOME/.composer/cache
php:
- 5.3
- 5.4
- 5.5
- 5.6
- 7.0
- hhvm
matrix:
include:
- php: 5.3
env: 'COMPOSER_PHPUNIT="lowest"'
before_script:
- composer install --prefer-dist
- if [ "$COMPOSER_PHPUNIT" = "lowest" ]; then composer update --prefer-lowest --with-dependencies phpunit/phpunit; fi;
- vendor/bin/koharness
script:
- cd /tmp/koharness && ./vendor/bin/phpunit --bootstrap=modules/unittest/bootstrap.php modules/unittest/tests.php
notifications:
email: false

View File

@ -0,0 +1,6 @@
# Kohana - database access module
| ver | Stable | Develop |
|-------|--------------------------------------------------------------------------------------------------------------------------------------|----------------------------------------------------------------------------------------------------------------------------------------|
| 3.3.x | [![Build Status - 3.3/master](https://travis-ci.org/kohana/database.svg?branch=3.3%2Fmaster)](https://travis-ci.org/kohana/database) | [![Build Status - 3.3/develop](https://travis-ci.org/kohana/database.svg?branch=3.3%2Fdevelop)](https://travis-ci.org/kohana/database) |
| 3.4.x | [![Build Status - 3.4/master](https://travis-ci.org/kohana/database.svg?branch=3.4%2Fmaster)](https://travis-ci.org/kohana/database) | [![Build Status - 3.4/develop](https://travis-ci.org/kohana/database.svg?branch=3.4%2Fdevelop)](https://travis-ci.org/kohana/database) |

View File

@ -0,0 +1,3 @@
<?php defined('SYSPATH') OR die('No direct script access.');
class Database_MySQLi extends Kohana_Database_MySQLi {}

View File

@ -0,0 +1,3 @@
<?php defined('SYSPATH') OR die('No direct script access.');
class Database_MySQLi_Result extends Kohana_Database_MySQLi_Result {}

View File

@ -9,7 +9,7 @@
* @copyright (c) 2012 Kohana Team
* @license http://kohanaframework.org/license
*/
class Kohana_Config_Database extends Kohana_Config_Database_Writer
class Kohana_Config_Database extends Config_Database_Writer
{
}

View File

@ -3,6 +3,15 @@
/**
* Database writer for the config system
*
* Schema for configuration table:
*
* CREATE TABLE IF NOT EXISTS `config` (
* `group_name` varchar(128) NOT NULL,
* `config_key` varchar(128) NOT NULL,
* `config_value` text,
* PRIMARY KEY (`group_name`,`config_key`)
* ) ENGINE=InnoDB;
*
* @package Kohana
* @category Configuration
* @author Kohana Team

View File

@ -240,6 +240,7 @@ class Kohana_Database_MySQL extends Database {
'fixed' => array('type' => 'float', 'exact' => TRUE),
'fixed unsigned' => array('type' => 'float', 'exact' => TRUE, 'min' => '0'),
'float unsigned' => array('type' => 'float', 'min' => '0'),
'geometry' => array('type' => 'string', 'binary' => TRUE),
'int unsigned' => array('type' => 'int', 'min' => '0', 'max' => '4294967295'),
'integer unsigned' => array('type' => 'int', 'min' => '0', 'max' => '4294967295'),
'longblob' => array('type' => 'string', 'binary' => TRUE, 'character_maximum_length' => '4294967295'),

View File

@ -51,6 +51,9 @@ class Kohana_Database_MySQL_Result extends Database_Result {
// Increment internal row for optimization assuming rows are fetched in order
$this->_internal_row++;
// FIXME mysql_fetch_object has been deprecated as of php 5.5!
// Please use mysqli_fetch_object or PDOStatement::fetch(PDO::FETCH_OBJ) instead.
if ($this->_as_object === TRUE)
{
// Return an stdClass
@ -58,8 +61,32 @@ class Kohana_Database_MySQL_Result extends Database_Result {
}
elseif (is_string($this->_as_object))
{
// Return an object of given class name
return mysql_fetch_object($this->_result, $this->_as_object, $this->_object_params);
/* The second and third argument for mysql_fetch_object are optional, but do
* not have default values defined. Passing _object_params with a non-array value results
* in undefined behavior that varies by PHP version. For example, if NULL is supplied on
* PHP 5.3, the resulting behavior is identical to calling with array(), which results in the
* classes __construct function being called with no arguments. This is only an issue when
* the _as_object class does not have an explicit __construct method resulting in the
* cryptic error "Class %s does not have a constructor hence you cannot use ctor_params."
* In contrast, the same function call on PHP 5.5 will 'functionally' interpret
* _object_params == NULL as an omission of the third argument, resulting in the original
* intended functionally.
*
* Because the backing code for the mysql_fetch_object has not changed between 5.3 and 5.5,
* I suspect this discrepancy is due to the way the classes are instantiated on a boarder
* level. Additionally, mysql_fetch_object has been deprecated in 5.5 and should probably be
* replaced by mysqli_fetch_object or PDOStatement::fetch(PDO::FETCH_OBJ) in Kohana 3.4.
*/
if ($this->_object_params !== NULL)
{
// Return an object of given class name with constructor params
return mysql_fetch_object($this->_result, $this->_as_object, $this->_object_params);
}
else
{
// Return an object of given class name without constructor params
return mysql_fetch_object($this->_result, $this->_as_object);
}
}
else
{

View File

@ -0,0 +1,422 @@
<?php defined('SYSPATH') OR die('No direct script access.');
/**
* MySQLi database connection.
*
* @package Kohana/Database
* @category Drivers
* @author Kohana Team
* @copyright (c) 2008-2009 Kohana Team
* @license http://kohanaphp.com/license
*/
class Kohana_Database_MySQLi extends Database {
// Database in use by each connection
protected static $_current_databases = array();
// Use SET NAMES to set the character set
protected static $_set_names;
// Identifier for this connection within the PHP driver
protected $_connection_id;
// MySQL uses a backtick for identifiers
protected $_identifier = '`';
public function connect()
{
if ($this->_connection)
return;
if (Database_MySQLi::$_set_names === NULL)
{
// Determine if we can use mysqli_set_charset(), which is only
// available on PHP 5.2.3+ when compiled against MySQL 5.0+
Database_MySQLi::$_set_names = ! function_exists('mysqli_set_charset');
}
// Extract the connection parameters, adding required variabels
extract($this->_config['connection'] + array(
'database' => '',
'hostname' => '',
'username' => '',
'password' => '',
'socket' => '',
'port' => 3306,
'ssl' => NULL,
));
// Prevent this information from showing up in traces
unset($this->_config['connection']['username'], $this->_config['connection']['password']);
try
{
if(is_array($ssl))
{
$this->_connection = mysqli_init();
$this->_connection->ssl_set(
Arr::get($ssl, 'client_key_path'),
Arr::get($ssl, 'client_cert_path'),
Arr::get($ssl, 'ca_cert_path'),
Arr::get($ssl, 'ca_dir_path'),
Arr::get($ssl, 'cipher')
);
$this->_connection->real_connect($hostname, $username, $password, $database, $port, $socket, MYSQLI_CLIENT_SSL);
}
else
{
$this->_connection = new mysqli($hostname, $username, $password, $database, $port, $socket);
}
}
catch (Exception $e)
{
// No connection exists
$this->_connection = NULL;
throw new Database_Exception(':error', array(':error' => $e->getMessage()), $e->getCode());
}
// \xFF is a better delimiter, but the PHP driver uses underscore
$this->_connection_id = sha1($hostname.'_'.$username.'_'.$password);
if ( ! empty($this->_config['charset']))
{
// Set the character set
$this->set_charset($this->_config['charset']);
}
if ( ! empty($this->_config['connection']['variables']))
{
// Set session variables
$variables = array();
foreach ($this->_config['connection']['variables'] as $var => $val)
{
$variables[] = 'SESSION '.$var.' = '.$this->quote($val);
}
$this->_connection->query('SET '.implode(', ', $variables));
}
}
public function disconnect()
{
try
{
// Database is assumed disconnected
$status = TRUE;
if (is_resource($this->_connection))
{
if ($status = $this->_connection->close())
{
// Clear the connection
$this->_connection = NULL;
// Clear the instance
parent::disconnect();
}
}
}
catch (Exception $e)
{
// Database is probably not disconnected
$status = ! is_resource($this->_connection);
}
return $status;
}
public function set_charset($charset)
{
// Make sure the database is connected
$this->_connection or $this->connect();
if (Database_MySQLi::$_set_names === TRUE)
{
// PHP is compiled against MySQL 4.x
$status = (bool) $this->_connection->query('SET NAMES '.$this->quote($charset));
}
else
{
// PHP is compiled against MySQL 5.x
$status = $this->_connection->set_charset($charset);
}
if ($status === FALSE)
{
throw new Database_Exception(':error', array(':error' => $this->_connection->error), $this->_connection->errno);
}
}
public function query($type, $sql, $as_object = FALSE, array $params = NULL)
{
// Make sure the database is connected
$this->_connection or $this->connect();
if (Kohana::$profiling)
{
// Benchmark this query for the current instance
$benchmark = Profiler::start("Database ({$this->_instance})", $sql);
}
// Execute the query
if (($result = $this->_connection->query($sql)) === FALSE)
{
if (isset($benchmark))
{
// This benchmark is worthless
Profiler::delete($benchmark);
}
throw new Database_Exception(':error [ :query ]', array(
':error' => $this->_connection->error,
':query' => $sql
), $this->_connection->errno);
}
if (isset($benchmark))
{
Profiler::stop($benchmark);
}
// Set the last query
$this->last_query = $sql;
if ($type === Database::SELECT)
{
// Return an iterator of results
return new Database_MySQLi_Result($result, $sql, $as_object, $params);
}
elseif ($type === Database::INSERT)
{
// Return a list of insert id and rows created
return array(
$this->_connection->insert_id,
$this->_connection->affected_rows,
);
}
else
{
// Return the number of rows affected
return $this->_connection->affected_rows;
}
}
public function datatype($type)
{
static $types = array
(
'blob' => array('type' => 'string', 'binary' => TRUE, 'character_maximum_length' => '65535'),
'bool' => array('type' => 'bool'),
'bigint unsigned' => array('type' => 'int', 'min' => '0', 'max' => '18446744073709551615'),
'datetime' => array('type' => 'string'),
'decimal unsigned' => array('type' => 'float', 'exact' => TRUE, 'min' => '0'),
'double' => array('type' => 'float'),
'double precision unsigned' => array('type' => 'float', 'min' => '0'),
'double unsigned' => array('type' => 'float', 'min' => '0'),
'enum' => array('type' => 'string'),
'fixed' => array('type' => 'float', 'exact' => TRUE),
'fixed unsigned' => array('type' => 'float', 'exact' => TRUE, 'min' => '0'),
'float unsigned' => array('type' => 'float', 'min' => '0'),
'geometry' => array('type' => 'string', 'binary' => TRUE),
'int unsigned' => array('type' => 'int', 'min' => '0', 'max' => '4294967295'),
'integer unsigned' => array('type' => 'int', 'min' => '0', 'max' => '4294967295'),
'longblob' => array('type' => 'string', 'binary' => TRUE, 'character_maximum_length' => '4294967295'),
'longtext' => array('type' => 'string', 'character_maximum_length' => '4294967295'),
'mediumblob' => array('type' => 'string', 'binary' => TRUE, 'character_maximum_length' => '16777215'),
'mediumint' => array('type' => 'int', 'min' => '-8388608', 'max' => '8388607'),
'mediumint unsigned' => array('type' => 'int', 'min' => '0', 'max' => '16777215'),
'mediumtext' => array('type' => 'string', 'character_maximum_length' => '16777215'),
'national varchar' => array('type' => 'string'),
'numeric unsigned' => array('type' => 'float', 'exact' => TRUE, 'min' => '0'),
'nvarchar' => array('type' => 'string'),
'point' => array('type' => 'string', 'binary' => TRUE),
'real unsigned' => array('type' => 'float', 'min' => '0'),
'set' => array('type' => 'string'),
'smallint unsigned' => array('type' => 'int', 'min' => '0', 'max' => '65535'),
'text' => array('type' => 'string', 'character_maximum_length' => '65535'),
'tinyblob' => array('type' => 'string', 'binary' => TRUE, 'character_maximum_length' => '255'),
'tinyint' => array('type' => 'int', 'min' => '-128', 'max' => '127'),
'tinyint unsigned' => array('type' => 'int', 'min' => '0', 'max' => '255'),
'tinytext' => array('type' => 'string', 'character_maximum_length' => '255'),
'year' => array('type' => 'string'),
);
$type = str_replace(' zerofill', '', $type);
if (isset($types[$type]))
return $types[$type];
return parent::datatype($type);
}
/**
* Start a SQL transaction
*
* @link http://dev.mysql.com/doc/refman/5.0/en/set-transaction.html
*
* @param string $mode Isolation level
* @return boolean
*/
public function begin($mode = NULL)
{
// Make sure the database is connected
$this->_connection or $this->connect();
if ($mode AND ! $this->_connection->query("SET TRANSACTION ISOLATION LEVEL $mode"))
{
throw new Database_Exception(':error', array(
':error' => $this->_connection->error
), $this->_connection->errno);
}
return (bool) $this->_connection->query('START TRANSACTION');
}
/**
* Commit a SQL transaction
*
* @return boolean
*/
public function commit()
{
// Make sure the database is connected
$this->_connection or $this->connect();
return (bool) $this->_connection->query('COMMIT');
}
/**
* Rollback a SQL transaction
*
* @return boolean
*/
public function rollback()
{
// Make sure the database is connected
$this->_connection or $this->connect();
return (bool) $this->_connection->query('ROLLBACK');
}
public function list_tables($like = NULL)
{
if (is_string($like))
{
// Search for table names
$result = $this->query(Database::SELECT, 'SHOW TABLES LIKE '.$this->quote($like), FALSE);
}
else
{
// Find all table names
$result = $this->query(Database::SELECT, 'SHOW TABLES', FALSE);
}
$tables = array();
foreach ($result as $row)
{
$tables[] = reset($row);
}
return $tables;
}
public function list_columns($table, $like = NULL, $add_prefix = TRUE)
{
// Quote the table name
$table = ($add_prefix === TRUE) ? $this->quote_table($table) : $table;
if (is_string($like))
{
// Search for column names
$result = $this->query(Database::SELECT, 'SHOW FULL COLUMNS FROM '.$table.' LIKE '.$this->quote($like), FALSE);
}
else
{
// Find all column names
$result = $this->query(Database::SELECT, 'SHOW FULL COLUMNS FROM '.$table, FALSE);
}
$count = 0;
$columns = array();
foreach ($result as $row)
{
list($type, $length) = $this->_parse_type($row['Type']);
$column = $this->datatype($type);
$column['column_name'] = $row['Field'];
$column['column_default'] = $row['Default'];
$column['data_type'] = $type;
$column['is_nullable'] = ($row['Null'] == 'YES');
$column['ordinal_position'] = ++$count;
switch ($column['type'])
{
case 'float':
if (isset($length))
{
list($column['numeric_precision'], $column['numeric_scale']) = explode(',', $length);
}
break;
case 'int':
if (isset($length))
{
// MySQL attribute
$column['display'] = $length;
}
break;
case 'string':
switch ($column['data_type'])
{
case 'binary':
case 'varbinary':
$column['character_maximum_length'] = $length;
break;
case 'char':
case 'varchar':
$column['character_maximum_length'] = $length;
case 'text':
case 'tinytext':
case 'mediumtext':
case 'longtext':
$column['collation_name'] = $row['Collation'];
break;
case 'enum':
case 'set':
$column['collation_name'] = $row['Collation'];
$column['options'] = explode('\',\'', substr($length, 1, -1));
break;
}
break;
}
// MySQL attributes
$column['comment'] = $row['Comment'];
$column['extra'] = $row['Extra'];
$column['key'] = $row['Key'];
$column['privileges'] = $row['Privileges'];
$columns[$row['Field']] = $column;
}
return $columns;
}
public function escape($value)
{
// Make sure the database is connected
$this->_connection or $this->connect();
if (($value = $this->_connection->real_escape_string( (string) $value)) === FALSE)
{
throw new Database_Exception(':error', array(
':error' => $this->_connection->error,
), $this->_connection->errno);
}
// SQL standard is to use single-quotes for all values
return "'$value'";
}
} // End Database_MySQLi

View File

@ -0,0 +1,71 @@
<?php defined('SYSPATH') OR die('No direct script access.');
/**
* MySQLi database result. See [Results](/database/results) for usage and examples.
*
* @package Kohana/Database
* @category Query/Result
* @author Kohana Team
* @copyright (c) 2008-2009 Kohana Team
* @license http://kohanaphp.com/license
*/
class Kohana_Database_MySQLi_Result extends Database_Result {
protected $_internal_row = 0;
public function __construct($result, $sql, $as_object = FALSE, array $params = NULL)
{
parent::__construct($result, $sql, $as_object, $params);
// Find the number of rows in the result
$this->_total_rows = $result->num_rows;
}
public function __destruct()
{
if (is_resource($this->_result))
{
$this->_result->free();
}
}
public function seek($offset)
{
if ($this->offsetExists($offset) AND $this->_result->data_seek($offset))
{
// Set the current row to the offset
$this->_current_row = $this->_internal_row = $offset;
return TRUE;
}
else
{
return FALSE;
}
}
public function current()
{
if ($this->_current_row !== $this->_internal_row AND ! $this->seek($this->_current_row))
return NULL;
// Increment internal row for optimization assuming rows are fetched in order
$this->_internal_row++;
if ($this->_as_object === TRUE)
{
// Return an stdClass
return $this->_result->fetch_object();
}
elseif (is_string($this->_as_object))
{
// Return an object of given class name
return $this->_result->fetch_object($this->_as_object, (array) $this->_object_params);
}
else
{
// Return an array of the row
return $this->_result->fetch_assoc();
}
}
} // End Database_MySQLi_Result_Select

View File

@ -60,6 +60,12 @@ class Kohana_Database_PDO extends Database {
array(':error' => $e->getMessage()),
$e->getCode());
}
if ( ! empty($this->_config['charset']))
{
// Set the character set
$this->set_charset($this->_config['charset']);
}
}
/**

View File

@ -80,7 +80,7 @@ abstract class Kohana_Database_Query_Builder extends Database_Query {
// Convert "val = NULL" to "val IS NULL"
$op = 'IS';
}
elseif ($op === '!=')
elseif ($op === '!=' OR $op === '<>')
{
// Convert "val != NULL" to "valu IS NOT NULL"
$op = 'IS NOT';

View File

@ -31,7 +31,7 @@ class Kohana_Database_Query_Builder_Insert extends Database_Query_Builder {
if ($table)
{
// Set the inital table name
$this->_table = $table;
$this->table($table);
}
if ($columns)
@ -47,11 +47,14 @@ class Kohana_Database_Query_Builder_Insert extends Database_Query_Builder {
/**
* Sets the table to insert into.
*
* @param mixed $table table name or array($table, $alias) or object
* @param string $table table name
* @return $this
*/
public function table($table)
{
if ( ! is_string($table))
throw new Kohana_Exception('INSERT INTO syntax does not allow table aliasing');
$this->_table = $table;
return $this;
@ -87,7 +90,10 @@ class Kohana_Database_Query_Builder_Insert extends Database_Query_Builder {
// Get all of the passed values
$values = func_get_args();
$this->_values = array_merge($this->_values, $values);
foreach ($values as $value)
{
$this->_values[] = $value;
}
return $this;
}

View File

@ -309,7 +309,7 @@ class Kohana_Database_Query_Builder_Select extends Database_Query_Builder_Where
*/
public function offset($number)
{
$this->_offset = $number;
$this->_offset = ($number === NULL) ? NULL : (int) $number;
return $this;
}
@ -404,13 +404,14 @@ class Kohana_Database_Query_Builder_Select extends Database_Query_Builder_Where
if ( ! empty($this->_union))
{
$query = '('.$query.')';
foreach ($this->_union as $u) {
$query .= ' UNION ';
if ($u['all'] === TRUE)
{
$query .= 'ALL ';
}
$query .= $u['select']->compile($db);
$query .= '('.$u['select']->compile($db).')';
}
}

View File

@ -172,7 +172,7 @@ abstract class Kohana_Database_Query_Builder_Where extends Database_Query_Builde
*/
public function limit($number)
{
$this->_limit = $number;
$this->_limit = ($number === NULL) ? NULL : (int) $number;
return $this;
}

View File

@ -204,6 +204,9 @@ class Kohana_Session_Database extends Session {
// Execute the query
$query->execute($this->_db);
// Delete the old session id
$this->_update_id = NULL;
// Delete the cookie
Cookie::delete($this->_name);
}

View File

@ -0,0 +1,45 @@
{
"name": "kohana/database",
"type": "kohana-module",
"description": "The official Kohana module for database interactions, building queries, and prepared statements",
"homepage": "http://kohanaframework.org",
"license": "BSD-3-Clause",
"keywords": ["kohana", "framework", "database"],
"authors": [
{
"name": "Kohana Team",
"email": "team@kohanaframework.org",
"homepage": "http://kohanaframework.org/team",
"role": "developer"
}
],
"support": {
"issues": "http://dev.kohanaframework.org",
"forum": "http://forum.kohanaframework.org",
"irc": "irc://irc.freenode.net/kohana",
"source": "http://github.com/kohana/core"
},
"require": {
"composer/installers": "~1.0",
"kohana/core": ">=3.3",
"php": ">=5.3.6"
},
"require-dev": {
"kohana/core": "3.3.*@dev",
"kohana/unittest": "3.3.*@dev",
"kohana/koharness": "*@dev"
},
"suggest": {
"ext-mysql": "*",
"ext-pdo": "*"
},
"extra": {
"branch-alias": {
"dev-3.3/develop": "3.3.x-dev",
"dev-3.4/develop": "3.4.x-dev"
},
"installer-paths": {
"vendor/{$vendor}/{$name}": ["type:kohana-module"]
}
}
}

View File

@ -53,4 +53,38 @@ return array
'charset' => 'utf8',
'caching' => FALSE,
),
/**
* MySQLi driver config information
*
* The following options are available for MySQLi:
*
* string hostname server hostname, or socket
* string database database name
* string username database username
* string password database password
* boolean persistent use persistent connections?
* array ssl ssl parameters as "key => value" pairs.
* Available keys: client_key_path, client_cert_path, ca_cert_path, ca_dir_path, cipher
* array variables system variables as "key => value" pairs
*
* Ports and sockets may be appended to the hostname.
*
* MySQLi driver config example:
*
*/
// 'alternate_mysqli' => array
// (
// 'type' => 'MySQLi',
// 'connection' => array(
// 'hostname' => 'localhost',
// 'database' => 'kohana',
// 'username' => FALSE,
// 'password' => FALSE,
// 'persistent' => FALSE,
// 'ssl' => NULL,
// ),
// 'table_prefix' => '',
// 'charset' => 'utf8',
// 'caching' => FALSE,
// ),
);

View File

@ -11,13 +11,14 @@ The database configuration file contains an array of configuration groups. The s
'charset' => string CHARACTER_SET,
),
Understanding each of these settings is important.
INSTANCE_NAME
: Connections can be named anything you want, but you should always have at least one connection called "default".
DATABASE_TYPE
: One of the installed database drivers. Kohana comes with "mysql" and "pdo" drivers. Drivers must extend the Database class.
: One of the installed database drivers. Kohana comes with "MySQL", "MySQLi", and "PDO" drivers. Drivers must extend the Database class. This parameter is case sensitive. Note the mysql php extension used by the MySQL driver is deprecated as of PHP 5.5 and you should look to use an alternative driver.
CONNECTION_ARRAY
: Specific driver options for connecting to your database. (Driver options are explained [below](#connection-settings).)
@ -25,6 +26,21 @@ CONNECTION_ARRAY
TABLE_PREFIX
: Prefix that will be added to all table names by the [query builder](#query_building).
CHARACTER_SET
: The character set to use for the connection with the database.
[!!] Setting Character Set won't work for PDO based connections because of incompatibility with PHP prior to 5.3.6. Use the DSN or options config instead. Example Below:
return array
(
'default' => array
(
'type' => 'PDO',
'connection' => array(
'options' => array(PDO::MYSQL_ATTR_INIT_COMMAND => "SET NAMES utf8"),
),
),
);
## Example
@ -34,7 +50,7 @@ The example file below shows 2 MySQL connections, one local and one remote.
(
'default' => array
(
'type' => 'mysql',
'type' => 'MySQL',
'connection' => array(
'hostname' => 'localhost',
'username' => 'dbuser',
@ -46,7 +62,7 @@ The example file below shows 2 MySQL connections, one local and one remote.
'charset' => 'utf8',
),
'remote' => array(
'type' => 'mysql',
'type' => 'MySQL',
'connection' => array(
'hostname' => '55.55.55.55',
'username' => 'remote_user',
@ -59,6 +75,8 @@ The example file below shows 2 MySQL connections, one local and one remote.
),
);
[!!] Note that the 'type' parameter is case sensitive (eg 'MySQL', 'PDO').
## Connections and Instances
Each configuration group is referred to as a database instance. Each instance can be accessed by calling [Database::instance]. If you don't provide a parameter, the default instance is used.
@ -99,6 +117,24 @@ Type | Option | Description | Default value
`boolean` | persistent | Persistent connections | `FALSE`
`string` | database | Database name | `kohana`
### MySQLi
A [MySQL database](http://php.net/manual/en/book.mysqli.php) can accept the following options in the `connection` array:
Type | Option | Description | Default value
----------|------------|----------------------------| -------------------------
`string` | hostname | Hostname of the database | `localhost`
`integer` | port | Port number | `NULL`
`string` | socket | UNIX socket | `NULL`
`string` | username | Database username | `NULL`
`string` | password | Database password | `NULL`
`boolean` | persistent | Persistent connections | `FALSE`
`string` | database | Database name | `kohana`
`array` | ssl | SSL parameters | `NULL`
SSL parameters should be specified as `key` => `value` pairs.
Available keys: client_key_path, client_cert_path, ca_cert_path, ca_dir_path, cipher
### PDO
A [PDO database](http://php.net/manual/en/book.pdo.php) can accept these options in the `connection` array:

View File

@ -25,7 +25,7 @@ In this example, we loop through an array of whitelisted input fields and for ea
//copy the query & execute it
$pagination_query = clone $query;
$count = $pagination_query->select(DB::expr('COUNT(*)) AS mycount')->execute()->get('mycount');
$count = $pagination_query->select(DB::expr('COUNT(*) AS mycount'))->execute()->get('mycount');
//pass the total item count to Pagination
$config = Kohana::$config->load('pagination');

View File

@ -76,7 +76,7 @@ This query would generate the following SQL:
Often you will want the results in a particular order and rather than sorting the results, it's better to have the results returned to you in the correct order. You can do this by using the order_by() method. It takes the column name and an optional direction string as the parameters. Multiple `order_by()` methods can be used to add additional sorting capability.
$query = DB::select()->from(`posts`)->order_by(`published`, `DESC`);
$query = DB::select()->from('posts')->order_by('published', 'DESC');
This query would generate the following SQL:

View File

@ -0,0 +1,8 @@
<?php
// Configuration for koharness - builds a standalone skeleton Kohana app for running unit tests
return array(
'modules' => array(
'database' => __DIR__,
'unittest' => __DIR__ . '/vendor/kohana/unittest'
),
);

37
modules/image/.travis.yml Normal file
View File

@ -0,0 +1,37 @@
sudo: false
language: php
# Only build the main develop/master branches - feature branches will be covered by PRs
branches:
only:
- /^[0-9\.]+\/(develop|master)$/
cache:
directories:
- vendor
- $HOME/.composer/cache
php:
- 5.3
- 5.4
- 5.5
- 5.6
- 7.0
- hhvm
matrix:
include:
- php: 5.3
env: 'COMPOSER_PHPUNIT="lowest"'
before_script:
- composer install --prefer-dist
- if [ "$COMPOSER_PHPUNIT" = "lowest" ]; then composer update --prefer-lowest --with-dependencies phpunit/phpunit; fi;
- vendor/bin/koharness
script:
- cd /tmp/koharness && ./vendor/bin/phpunit --bootstrap=modules/unittest/bootstrap.php modules/unittest/tests.php
notifications:
email: false

View File

@ -0,0 +1,6 @@
# Kohana - image processing module
| ver | Stable | Develop |
|-------|--------------------------------------------------------------------------------------------------------------------------------|----------------------------------------------------------------------------------------------------------------------------------|
| 3.3.x | [![Build Status - 3.3/master](https://travis-ci.org/kohana/image.svg?branch=3.3%2Fmaster)](https://travis-ci.org/kohana/image) | [![Build Status - 3.3/develop](https://travis-ci.org/kohana/image.svg?branch=3.3%2Fdevelop)](https://travis-ci.org/kohana/image) |
| 3.4.x | [![Build Status - 3.4/master](https://travis-ci.org/kohana/image.svg?branch=3.4%2Fmaster)](https://travis-ci.org/kohana/image) | [![Build Status - 3.4/develop](https://travis-ci.org/kohana/image.svg?branch=3.4%2Fdevelop)](https://travis-ci.org/kohana/image) |

View File

@ -23,6 +23,7 @@ abstract class Kohana_Image {
const VERTICAL = 0x12;
/**
* @deprecated - provide an image.default_driver value in your configuration instead
* @var string default driver: GD, ImageMagick, etc
*/
public static $default_driver = 'GD';
@ -44,8 +45,9 @@ abstract class Kohana_Image {
{
if ($driver === NULL)
{
// Use the default driver
$driver = Image::$default_driver;
// Use the driver from configuration file or default one
$configured_driver = Kohana::$config->load('image.default_driver');
$driver = ($configured_driver) ? $configured_driver : Image::$default_driver;
}
// Set the class name

View File

@ -10,13 +10,17 @@
*/
class Kohana_Image_GD extends Image {
// Is GD bundled or separate?
protected static $_bundled;
// Which GD functions are available?
const IMAGEROTATE = 'imagerotate';
const IMAGECONVOLUTION = 'imageconvolution';
const IMAGEFILTER = 'imagefilter';
const IMAGELAYEREFFECT = 'imagelayereffect';
protected static $_available_functions = array();
/**
* Checks if GD is enabled and bundled. Bundled GD is required for some
* methods to work. Exceptions will be thrown from those methods when GD is
* not bundled.
* Checks if GD is enabled and verify that key methods exist, some of which require GD to
* be bundled with PHP. Exceptions will be thrown from those methods when GD is not
* bundled.
*
* @return boolean
*/
@ -26,19 +30,15 @@ class Kohana_Image_GD extends Image {
{
throw new Kohana_Exception('GD is either not installed or not enabled, check your configuration');
}
if (defined('GD_BUNDLED'))
$functions = array(
Image_GD::IMAGEROTATE,
Image_GD::IMAGECONVOLUTION,
Image_GD::IMAGEFILTER,
Image_GD::IMAGELAYEREFFECT
);
foreach ($functions as $function)
{
// Get the version via a constant, available in PHP 5.
Image_GD::$_bundled = GD_BUNDLED;
}
else
{
// Get the version information
$info = gd_info();
// Extract the bundled status
Image_GD::$_bundled = (bool) preg_match('/\bbundled\b/i', $info['GD Version']);
Image_GD::$_available_functions[$function] = function_exists($function);
}
if (defined('GD_VERSION'))
@ -246,7 +246,7 @@ class Kohana_Image_GD extends Image {
*/
protected function _do_rotate($degrees)
{
if ( ! Image_GD::$_bundled)
if (empty(Image_GD::$_available_functions[Image_GD::IMAGEROTATE]))
{
throw new Kohana_Exception('This method requires :function, which is only available in the bundled version of GD',
array(':function' => 'imagerotate'));
@ -328,7 +328,7 @@ class Kohana_Image_GD extends Image {
*/
protected function _do_sharpen($amount)
{
if ( ! Image_GD::$_bundled)
if (empty(Image_GD::$_available_functions[Image_GD::IMAGECONVOLUTION]))
{
throw new Kohana_Exception('This method requires :function, which is only available in the bundled version of GD',
array(':function' => 'imageconvolution'));
@ -367,7 +367,7 @@ class Kohana_Image_GD extends Image {
*/
protected function _do_reflection($height, $opacity, $fade_in)
{
if ( ! Image_GD::$_bundled)
if (empty(Image_GD::$_available_functions[Image_GD::IMAGEFILTER]))
{
throw new Kohana_Exception('This method requires :function, which is only available in the bundled version of GD',
array(':function' => 'imagefilter'));
@ -448,7 +448,7 @@ class Kohana_Image_GD extends Image {
*/
protected function _do_watermark(Image $watermark, $offset_x, $offset_y, $opacity)
{
if ( ! Image_GD::$_bundled)
if (empty(Image_GD::$_available_functions[Image_GD::IMAGELAYEREFFECT]))
{
throw new Kohana_Exception('This method requires :function, which is only available in the bundled version of GD',
array(':function' => 'imagelayereffect'));
@ -611,6 +611,7 @@ class Kohana_Image_GD extends Image {
switch (strtolower($extension))
{
case 'jpg':
case 'jpe':
case 'jpeg':
// Save a JPG file
$save = 'imagejpeg';

View File

@ -314,6 +314,7 @@ class Kohana_Image_Imagick extends Image {
switch ($format)
{
case 'jpg':
case 'jpe':
case 'jpeg':
$type = IMAGETYPE_JPEG;
break;

View File

@ -0,0 +1,44 @@
{
"name": "kohana/image",
"type": "kohana-module",
"description": "The official Kohana module for manipulating images",
"homepage": "http://kohanaframework.org",
"license": "BSD-3-Clause",
"keywords": ["kohana", "framework", "image"],
"authors": [
{
"name": "Kohana Team",
"email": "team@kohanaframework.org",
"homepage": "http://kohanaframework.org/team",
"role": "developer"
}
],
"support": {
"issues": "http://dev.kohanaframework.org",
"forum": "http://forum.kohanaframework.org",
"irc": "irc://irc.freenode.net/kohana",
"source": "http://github.com/kohana/core"
},
"require": {
"composer/installers": "~1.0",
"kohana/core": ">=3.3",
"php": ">=5.3.3"
},
"require-dev": {
"kohana/core": "3.3.*@dev",
"kohana/unittest": "3.3.*@dev",
"kohana/koharness": "*@dev"
},
"suggest": {
"ext-gd": "*"
},
"extra": {
"branch-alias": {
"dev-3.3/develop": "3.3.x-dev",
"dev-3.4/develop": "3.4.x-dev"
},
"installer-paths": {
"vendor/{$vendor}/{$name}": ["type:kohana-module"]
}
}
}

View File

@ -0,0 +1,8 @@
<?php defined('SYSPATH') OR die('No direct script access.');
return array(
// Provide the default driver to use - eg a value of Imagick will use Image_Imagick as the driver class
// If you set a value for this config key, then the Image::$default_driver static variable that was used
// to configure earlier versions will be ignored.
'default_driver' => NULL,
);

View File

@ -4,7 +4,24 @@ Kohana 3.x provides a simple yet powerful image manipulation module. The [Image]
## Drivers
[Image] module ships with [Image_GD] driver which requires `GD` extension enabled in your PHP installation. This is the default driver. Additional drivers can be created by extending the [Image] class.
[Image] module ships with [Image_GD] driver which requires `GD` extension enabled in your PHP installation, and
[Image_Imagick] driver which requires the `imagick` PHP extension. Additional drivers can be created by extending
the [Image] class.
The [Image_GD] driver is the default. You can change this by providing an `image.default_driver` configuration option
- for example:
~~~
// application/config/image.php
<?php
return array(
'default_driver' => 'Imagick'
);
~~~
[!!] Older versions of Kohana allowed you to configure the driver with the `Image::$default_driver` static variable in
the bootstrap, an extension class, or elsewhere. That variable is now deprecated and will be ignored if you set a
config value.
## Getting Started

View File

@ -0,0 +1,8 @@
<?php
// Configuration for koharness - builds a standalone skeleton Kohana app for running unit tests
return array(
'modules' => array(
'image' => __DIR__,
'unittest' => __DIR__ . '/vendor/kohana/unittest'
),
);

View File

@ -0,0 +1,37 @@
sudo: false
language: php
# Only build the main develop/master branches - feature branches will be covered by PRs
branches:
only:
- /^[0-9\.]+\/(develop|master)$/
cache:
directories:
- vendor
- $HOME/.composer/cache
php:
- 5.3
- 5.4
- 5.5
- 5.6
- 7.0
- hhvm
matrix:
include:
- php: 5.3
env: 'COMPOSER_PHPUNIT="lowest"'
before_script:
- composer install --prefer-dist
- if [ "$COMPOSER_PHPUNIT" = "lowest" ]; then composer update --prefer-lowest --with-dependencies phpunit/phpunit; fi;
- vendor/bin/koharness
script:
- cd /tmp/koharness && ./vendor/bin/phpunit --bootstrap=modules/unittest/bootstrap.php modules/unittest/tests.php
notifications:
email: false

View File

@ -1,5 +1,10 @@
# Minion
| ver | Stable | Develop |
|-------|----------------------------------------------------------------------------------------------------------------------------------|------------------------------------------------------------------------------------------------------------------------------------|
| 3.3.x | [![Build Status - 3.3/master](https://travis-ci.org/kohana/minion.svg?branch=3.3%2Fmaster)](https://travis-ci.org/kohana/minion) | [![Build Status - 3.3/develop](https://travis-ci.org/kohana/minion.svg?branch=3.3%2Fdevelop)](https://travis-ci.org/kohana/minion) |
| 3.4.x | [![Build Status - 3.4/master](https://travis-ci.org/kohana/minion.svg?branch=3.4%2Fmaster)](https://travis-ci.org/kohana/minion) | [![Build Status - 3.4/develop](https://travis-ci.org/kohana/minion.svg?branch=3.4%2Fdevelop)](https://travis-ci.org/kohana/minion) |
Minion is a framework for running tasks via the CLI.
The system is inspired by ruckusing, which had a nice system for defining tasks but lacked the desired flexibility for kohana integration.

View File

@ -170,7 +170,7 @@ class Kohana_Minion_CLI {
// Create temporary file
file_put_contents($vbscript, 'wscript.echo(InputBox("'.addslashes($text).'"))');
$password = shell_exec('cscript //nologo '.escapeshellarg($command));
$password = shell_exec('cscript //nologo '.escapeshellarg($vbscript));
// Remove temporary file.
unlink($vbscript);
@ -278,7 +278,7 @@ class Kohana_Minion_CLI {
* @copyright 2010 - 2011 Fuel Development Team
* @link http://fuelphp.com
* @param string $text the text to color
* @param atring $foreground the foreground color
* @param string $foreground the foreground color
* @param string $background the background color
* @return string the color coded string
*/

View File

@ -1,6 +1,6 @@
<?php defined('SYSPATH') or die('No direct script access.');
/**
* Minipn exception
* Minion exception
*
* @package Kohana
* @category Minion
@ -15,8 +15,6 @@ class Kohana_Minion_Exception extends Kohana_Exception {
*
* Should this display a stack trace? It's useful.
*
* Should this still log? Maybe not as useful since we'll see the error on the screen.
*
* @uses Kohana_Exception::text
* @param Exception $e
* @return boolean
@ -25,6 +23,9 @@ class Kohana_Minion_Exception extends Kohana_Exception {
{
try
{
// Log the exception
Kohana_Exception::log($e);
if ($e instanceof Minion_Exception)
{
echo $e->format_for_cli();
@ -59,6 +60,6 @@ class Kohana_Minion_Exception extends Kohana_Exception {
public function format_for_cli()
{
return Kohana_Exception::text($e);
return Kohana_Exception::text($this);
}
}

View File

@ -206,7 +206,7 @@ abstract class Kohana_Minion_Task {
public function build_validation(Validation $validation)
{
// Add a rule to each key making sure it's in the task
foreach ($validation->as_array() as $key => $value)
foreach ($validation->data() as $key => $value)
{
$validation->rule($key, array($this, 'valid_option'), array(':validation', ':field'));
}

View File

@ -0,0 +1,41 @@
{
"name": "kohana/minion",
"type": "kohana-module",
"description": "The official kohana module for running tasks via the CLI",
"homepage": "http://kohanaframework.org",
"license": "BSD-3-Clause",
"keywords": ["kohana", "framework", "task"],
"authors": [
{
"name": "Kohana Team",
"email": "team@kohanaframework.org",
"homepage": "http://kohanaframework.org/team",
"role": "developer"
}
],
"support": {
"issues": "http://dev.kohanaframework.org",
"forum": "http://forum.kohanaframework.org",
"irc": "irc://irc.freenode.net/kohana",
"source": "http://github.com/kohana/core"
},
"require": {
"composer/installers": "~1.0",
"kohana/core": ">=3.3",
"php": ">=5.3.3"
},
"require-dev": {
"kohana/core": "3.3.*@dev",
"kohana/unittest": "3.3.*@dev",
"kohana/koharness": "*@dev"
},
"extra": {
"branch-alias": {
"dev-3.3/develop": "3.3.x-dev",
"dev-3.4/develop": "3.4.x-dev"
},
"installer-paths": {
"vendor/{$vendor}/{$name}": ["type:kohana-module"]
}
}
}

View File

@ -1,32 +1,3 @@
# Minion Setup
To use minion, you'll need to make a small change to your index.php file:
-/**
- * Execute the main request. A source of the URI can be passed, eg: $_SERVER['PATH_INFO'].
- * If no source is specified, the URI will be automatically detected.
- */
-echo Request::factory()
- ->execute()
- ->send_headers(TRUE)
- ->body();
+if (PHP_SAPI == 'cli') // Try and load minion
+{
+ class_exists('Minion_Task') OR die('minion required!');
+ set_exception_handler(array('Kohana_Minion_Exception_Handler', 'handler'));
+
+ Minion_Task::factory(Minion_CLI::options())->execute();
+}
+else
+{
+ /**
+ * Execute the main request. A source of the URI can be passed, eg: $_SERVER['PATH_INFO'].
+ * If no source is specified, the URI will be automatically detected.
+ */
+ echo Request::factory()
+ ->execute()
+ ->send_headers(TRUE)
+ ->body();
+}
This will short-circuit your index file to intercept any cli calls, and route them to the minion module.
[!!] Since Kohana `3.3.x`, minion requires no additional setup to use.

View File

@ -6,8 +6,8 @@ Writing a task in minion is very easy. Simply create a new class called `Task_<T
class Task_Demo extends Minion_Task
{
protected $_defaults = array(
'foo' = 'bar',
protected $_options = array(
'foo' => 'bar',
'bar' => NULL,
);
@ -28,7 +28,7 @@ You'll notice a few things here:
- You need a main `_execute()` method. It should take one array parameter.
- This parameter contains any command line options passed to the task.
- For example, if you call the task above with `./minion --task=demo --foo=foobar` then `$params` will contain: `array('foo' => 'foobar', 'bar' => NULL)`
- It needs to have a `protected $_defaults` array. This is a list of parameters you want to accept for this task. Any parameters passed to the task not in this list will be rejected.
- It needs to have a `protected $_options` array. This is a list of parameters you want to accept for this task. Any parameters passed to the task not in this list will be rejected.
## Namespacing Tasks

View File

@ -0,0 +1,8 @@
<?php
// Configuration for koharness - builds a standalone skeleton Kohana app for running unit tests
return array(
'modules' => array(
'minion' => __DIR__,
'unittest' => __DIR__ . '/vendor/kohana/unittest'
),
);

37
modules/orm/.travis.yml Normal file
View File

@ -0,0 +1,37 @@
sudo: false
language: php
# Only build the main develop/master branches - feature branches will be covered by PRs
branches:
only:
- /^[0-9\.]+\/(develop|master)$/
cache:
directories:
- vendor
- $HOME/.composer/cache
php:
- 5.3
- 5.4
- 5.5
- 5.6
- 7.0
- hhvm
matrix:
include:
- php: 5.3
env: 'COMPOSER_PHPUNIT="lowest"'
before_script:
- composer install --prefer-dist
- if [ "$COMPOSER_PHPUNIT" = "lowest" ]; then composer update --prefer-lowest --with-dependencies phpunit/phpunit; fi;
- vendor/bin/koharness
script:
- cd /tmp/koharness && ./vendor/bin/phpunit --bootstrap=modules/unittest/bootstrap.php modules/unittest/tests.php
notifications:
email: false

6
modules/orm/README.md Normal file
View File

@ -0,0 +1,6 @@
# Kohana - ORM module
| ver | Stable | Develop |
|-------|----------------------------------------------------------------------------------------------------------------------------|------------------------------------------------------------------------------------------------------------------------------|
| 3.3.x | [![Build Status - 3.3/master](https://travis-ci.org/kohana/orm.svg?branch=3.3%2Fmaster)](https://travis-ci.org/kohana/orm) | [![Build Status - 3.3/develop](https://travis-ci.org/kohana/orm.svg?branch=3.3%2Fdevelop)](https://travis-ci.org/kohana/orm) |
| 3.4.x | [![Build Status - 3.4/master](https://travis-ci.org/kohana/orm.svg?branch=3.4%2Fmaster)](https://travis-ci.org/kohana/orm) | [![Build Status - 3.4/develop](https://travis-ci.org/kohana/orm.svg?branch=3.4%2Fdevelop)](https://travis-ci.org/kohana/orm) |

View File

@ -51,6 +51,10 @@ class Kohana_Auth_ORM extends Auth {
if ( ! $roles->loaded())
return FALSE;
}
else
{
$roles = $role;
}
}
return $user->has('roles', $roles);

View File

@ -288,8 +288,11 @@ class Kohana_ORM extends Model implements serializable {
*/
protected function _initialize()
{
// Set the object name and plural name
$this->_object_name = strtolower(substr(get_class($this), 6));
// Set the object name if none predefined
if (empty($this->_object_name))
{
$this->_object_name = strtolower(substr(get_class($this), 6));
}
// Check if this model has already been initialized
if ( ! $init = Arr::get(ORM::$_init_cache, $this->_object_name, FALSE))
@ -1501,14 +1504,14 @@ class Kohana_ORM extends Model implements serializable {
* Returns the number of relationships
*
* // Counts the number of times the login role is attached to $model
* $model->has('roles', ORM::factory('role', array('name' => 'login')));
* $model->count_relations('roles', ORM::factory('role', array('name' => 'login')));
* // Counts the number of times role 5 is attached to $model
* $model->has('roles', 5);
* $model->count_relations('roles', 5);
* // Counts the number of times any of roles 1, 2, 3, or 4 are attached to
* // $model
* $model->has('roles', array(1, 2, 3, 4));
* $model->count_relations('roles', array(1, 2, 3, 4));
* // Counts the number roles attached to $model
* $model->has('roles')
* $model->count_relations('roles')
*
* @param string $alias Alias of the has_many "through" relationship
* @param mixed $far_keys Related model, primary key, or an array of primary keys
@ -1624,7 +1627,7 @@ class Kohana_ORM extends Model implements serializable {
if ($method['name'] == 'select')
{
// Ignore any selected columns for now
$selects[] = $method;
$selects[$key] = $method;
unset($this->_db_pending[$key]);
}
}
@ -1641,7 +1644,7 @@ class Kohana_ORM extends Model implements serializable {
$this->_build(Database::SELECT);
$records = $this->_db_builder->from(array($this->_table_name, $this->_object_name))
->select(array(DB::expr('COUNT(*)'), 'records_found'))
->select(array(DB::expr('COUNT('.$this->_db->quote_column($this->_object_name.'.'.$this->_primary_key).')'), 'records_found'))
->execute($this->_db)
->get('records_found');
@ -1651,7 +1654,7 @@ class Kohana_ORM extends Model implements serializable {
$this->reset();
// Return the total number of records in a table
return $records;
return (int) $records;
}
/**

43
modules/orm/composer.json Normal file
View File

@ -0,0 +1,43 @@
{
"name": "kohana/orm",
"type": "kohana-module",
"description": "The official Kohana ORM module",
"homepage": "http://kohanaframework.org",
"license": "BSD-3-Clause",
"keywords": ["kohana", "framework", "ORM", "database"],
"authors": [
{
"name": "Kohana Team",
"email": "team@kohanaframework.org",
"homepage": "http://kohanaframework.org/team",
"role": "developer"
}
],
"support": {
"issues": "http://dev.kohanaframework.org",
"forum": "http://forum.kohanaframework.org",
"irc": "irc://irc.freenode.net/kohana",
"source": "http://github.com/kohana/core"
},
"require": {
"composer/installers": "~1.0",
"kohana/core": ">=3.3",
"kohana/database": ">=3.3",
"php": ">=5.3.3"
},
"require-dev": {
"kohana/core": "3.3.*@dev",
"kohana/database": "3.3.*@dev",
"kohana/unittest": "3.3.*@dev",
"kohana/koharness": "*@dev"
},
"extra": {
"branch-alias": {
"dev-3.3/develop": "3.3.x-dev",
"dev-3.4/develop": "3.4.x-dev"
},
"installer-paths": {
"vendor/{$vendor}/{$name}": ["type:kohana-module"]
}
}
}

View File

@ -0,0 +1,8 @@
<?php
// Configuration for koharness - builds a standalone skeleton Kohana app for running unit tests
return array(
'modules' => array(
'orm' => __DIR__,
'unittest' => __DIR__ . '/vendor/kohana/unittest'
),
);

View File

@ -0,0 +1,37 @@
sudo: false
language: php
# Only build the main develop/master branches - feature branches will be covered by PRs
branches:
only:
- /^[0-9\.]+\/(develop|master)$/
cache:
directories:
- vendor
- $HOME/.composer/cache
php:
- 5.3
- 5.4
- 5.5
- 5.6
- 7.0
- hhvm
matrix:
include:
- php: 5.3
env: 'COMPOSER_PHPUNIT="lowest"'
before_script:
- composer install --prefer-dist
- if [ "$COMPOSER_PHPUNIT" = "lowest" ]; then composer update --prefer-lowest --with-dependencies phpunit/phpunit; fi;
- vendor/bin/koharness
script:
- cd /tmp/koharness && ./vendor/bin/phpunit --bootstrap=modules/unittest/bootstrap.php modules/unittest/tests.php
notifications:
email: false

View File

@ -1,13 +1,29 @@
# Kohana-PHPUnit integration
This module integrates PHPUnit with Kohana.
| ver | Stable | Develop |
|-------|--------------------------------------------------------------------------------------------------------------------------------------|----------------------------------------------------------------------------------------------------------------------------------------|
| 3.3.x | [![Build Status - 3.3/master](https://travis-ci.org/kohana/unittest.svg?branch=3.3%2Fmaster)](https://travis-ci.org/kohana/unittest) | [![Build Status - 3.3/develop](https://travis-ci.org/kohana/unittest.svg?branch=3.3%2Fdevelop)](https://travis-ci.org/kohana/unittest) |
| 3.4.x | [![Build Status - 3.4/master](https://travis-ci.org/kohana/unittest.svg?branch=3.4%2Fmaster)](https://travis-ci.org/kohana/unittest) | [![Build Status - 3.4/develop](https://travis-ci.org/kohana/unittest.svg?branch=3.4%2Fdevelop)](https://travis-ci.org/kohana/unittest) |
This module integrates PHPUnit with Kohana and is used to run all the core Kohana tests. In most cases you will not
need to use this module for testing your own projects. If there are particular helpers provided here that you rely on,
that may be a sign that your own code is too closely coupled to the behaviour of the Kohana core classes.
If you look through any of the tests provided in this module you'll probably notice all theHorribleCamelCase.
I've chosen to do this because it's part of the PHPUnit coding conventions and is required for certain features such as auto documentation.
## Requirements
## Requirements and installation
* [PHPUnit](http://www.phpunit.de/) >= 3.4
Dependencies are listed in the composer.json - run `composer install` to install the module and all external requirements.
Note that more usually you will add this module to your own module's composer.json:
```json
{
"require-dev": {
"kohana/unittest": "3.3.*@dev"
}
}
```
## Usage

View File

@ -121,5 +121,10 @@ if (($ob_len = ob_get_length()) !== FALSE)
}
}
// Enable the unittest module
Kohana::modules(Kohana::modules() + array('unittest' => MODPATH.'unittest'));
// Enable the unittest module if it is not already loaded - use the absolute path
$modules = Kohana::modules();
$unittest_path = realpath(__DIR__).DIRECTORY_SEPARATOR;
if ( ! in_array($unittest_path, $modules)) {
$modules['unittest'] = $unittest_path;
Kohana::modules($modules);
}

View File

@ -9,7 +9,7 @@ $modules = array();
foreach ($modules_iterator as $module)
{
if ($module->isDir())
if ($module->isDir() AND ! $module->isDot())
{
$modules[$module->getFilename()] = MODPATH.$module->getFilename();
}

View File

@ -1,4 +1,4 @@
<?php
<?php defined('SYSPATH') or die('No direct script access.');
/**
* TestCase for testing a database
*
@ -10,11 +10,6 @@
*/
abstract class Kohana_Unittest_Database_TestCase extends PHPUnit_Extensions_Database_TestCase {
/**
* Whether we should enable work arounds to make the tests compatible with phpunit 3.4
* @var boolean
*/
protected static $_assert_type_compatability = NULL;
/**
* Make sure PHPUnit backs up globals
@ -49,16 +44,6 @@ abstract class Kohana_Unittest_Database_TestCase extends PHPUnit_Extensions_Data
*/
public function setUp()
{
if(self::$_assert_type_compatability === NULL)
{
if( ! class_exists('PHPUnit_Runner_Version'))
{
require_once 'PHPUnit/Runner/Version.php';
}
self::$_assert_type_compatability = version_compare(PHPUnit_Runner_Version::id(), '3.5.0', '<=');
}
$this->_helpers = new Kohana_Unittest_Helpers;
$this->setEnvironment($this->environmentDefault);
@ -89,9 +74,9 @@ abstract class Kohana_Unittest_Database_TestCase extends PHPUnit_Extensions_Data
// Get the unittesting db connection
$config = Kohana::$config->load('database.'.$this->_database_connection);
if($config['type'] !== 'pdo')
if(strtolower($config['type']) !== 'pdo')
{
$config['connection']['dsn'] = $config['type'].':'.
$config['connection']['dsn'] = strtolower($config['type']).':'.
'host='.$config['connection']['hostname'].';'.
'dbname='.$config['connection']['database'];
}
@ -161,151 +146,4 @@ abstract class Kohana_Unittest_Database_TestCase extends PHPUnit_Extensions_Data
return Kohana_Unittest_Helpers::has_internet();
}
/**
* Asserts that a variable is of a given type.
*
* @param string $expected
* @param mixed $actual
* @param string $message
* @since Method available since Release 3.5.0
*/
public static function assertInstanceOf($expected, $actual, $message = '')
{
if(self::$_assert_type_compatability)
{
return self::assertType($expected, $actual, $message);
}
return parent::assertInstanceOf($expected, $actual, $message);
}
/**
* Asserts that an attribute is of a given type.
*
* @param string $expected
* @param string $attributeName
* @param mixed $classOrObject
* @param string $message
* @since Method available since Release 3.5.0
*/
public static function assertAttributeInstanceOf($expected, $attributeName, $classOrObject, $message = '')
{
if(self::$_assert_type_compatability)
{
return self::assertAttributeType($expected, $attributeName, $classOrObject, $message);
}
return parent::assertAttributeInstanceOf($expected, $attributeName, $classOrObject, $message);
}
/**
* Asserts that a variable is not of a given type.
*
* @param string $expected
* @param mixed $actual
* @param string $message
* @since Method available since Release 3.5.0
*/
public static function assertNotInstanceOf($expected, $actual, $message = '')
{
if(self::$_assert_type_compatability)
{
return self::assertNotType($expected, $actual, $message);
}
return self::assertNotInstanceOf($expected, $actual, $message);
}
/**
* Asserts that an attribute is of a given type.
*
* @param string $expected
* @param string $attributeName
* @param mixed $classOrObject
* @param string $message
* @since Method available since Release 3.5.0
*/
public static function assertAttributeNotInstanceOf($expected, $attributeName, $classOrObject, $message = '')
{
if(self::$_assert_type_compatability)
{
return self::assertAttributeNotType($expected, $attributeName, $classOrObject, $message);
}
return self::assertAttributeNotInstanceOf($expected, $attributeName, $classOrObject, $message);
}
/**
* Asserts that a variable is of a given type.
*
* @param string $expected
* @param mixed $actual
* @param string $message
* @since Method available since Release 3.5.0
*/
public static function assertInternalType($expected, $actual, $message = '')
{
if(self::$_assert_type_compatability)
{
return self::assertType($expected, $actual, $message);
}
return parent::assertInternalType($expected, $actual, $message);
}
/**
* Asserts that an attribute is of a given type.
*
* @param string $expected
* @param string $attributeName
* @param mixed $classOrObject
* @param string $message
* @since Method available since Release 3.5.0
*/
public static function assertAttributeInternalType($expected, $attributeName, $classOrObject, $message = '')
{
if(self::$_assert_type_compatability)
{
return self::assertAttributeType($expected, $attributeName, $classOrObject, $message);
}
return self::assertAttributeInternalType($expected, $attributeName, $classOrObject, $message);
}
/**
* Asserts that a variable is not of a given type.
*
* @param string $expected
* @param mixed $actual
* @param string $message
* @since Method available since Release 3.5.0
*/
public static function assertNotInternalType($expected, $actual, $message = '')
{
if(self::$_assert_type_compatability)
{
return self::assertNotType($expected, $actual, $message);
}
return self::assertNotInternalType($expected, $actual, $message);
}
/**
* Asserts that an attribute is of a given type.
*
* @param string $expected
* @param string $attributeName
* @param mixed $classOrObject
* @param string $message
* @since Method available since Release 3.5.0
*/
public static function assertAttributeNotInternalType($expected, $attributeName, $classOrObject, $message = '')
{
if(self::$_assert_type_compatability)
{
return self::assertAttributeNotType($expected, $attributeName, $classOrObject, $message);
}
return self::assertAttributeNotInternalType($expected, $attributeName, $classOrObject, $message);
}
}

View File

@ -1,4 +1,4 @@
<?php
<?php defined('SYSPATH') or die('No direct script access.');
/**
* Unit testing helpers

View File

@ -6,12 +6,6 @@
*/
abstract class Kohana_Unittest_TestCase extends PHPUnit_Framework_TestCase {
/**
* Whether we should enable work arounds to make the tests compatible with phpunit 3.4
* @var boolean
*/
protected static $_assert_type_compatability = NULL;
/**
* Make sure PHPUnit backs up globals
* @var boolean
@ -39,16 +33,6 @@ abstract class Kohana_Unittest_TestCase extends PHPUnit_Framework_TestCase {
*/
public function setUp()
{
if(self::$_assert_type_compatability === NULL)
{
if( ! class_exists('PHPUnit_Runner_Version'))
{
require_once 'PHPUnit/Runner/Version.php';
}
self::$_assert_type_compatability = version_compare(PHPUnit_Runner_Version::id(), '3.5.0', '<=');
}
$this->_helpers = new Unittest_Helpers;
$this->setEnvironment($this->environmentDefault);
@ -112,150 +96,75 @@ abstract class Kohana_Unittest_TestCase extends PHPUnit_Framework_TestCase {
}
/**
* Asserts that a variable is of a given type.
* Evaluate an HTML or XML string and assert its structure and/or contents.
*
* @param string $expected
* @param mixed $actual
* NOTE:
* Overriding this method to remove the deprecation error
* when tested with PHPUnit 4.2.0+
*
* TODO:
* this should be removed when phpunit-dom-assertions gets released
* https://github.com/phpunit/phpunit-dom-assertions
*
* @param array $matcher
* @param string $actual
* @param string $message
* @since Method available since Release 3.5.0
* @param bool $isHtml
* @uses Unittest_TestCase::tag_match
*/
public static function assertInstanceOf($expected, $actual, $message = '')
public static function assertTag($matcher, $actual, $message = '', $isHtml = true)
{
if(self::$_assert_type_compatability)
{
return self::assertType($expected, $actual, $message);
}
//trigger_error(__METHOD__ . ' is deprecated', E_USER_DEPRECATED);
return parent::assertInstanceOf($expected, $actual, $message);
$matched = static::tag_match($matcher, $actual, $message, $isHtml);
static::assertTrue($matched, $message);
}
/**
* Asserts that an attribute is of a given type.
* This assertion is the exact opposite of assertTag
*
* @param string $expected
* @param string $attributeName
* @param mixed $classOrObject
* Rather than asserting that $matcher results in a match, it asserts that
* $matcher does not match
*
* NOTE:
* Overriding this method to remove the deprecation error
* when tested with PHPUnit 4.2.0+
*
* TODO:
* this should be removed when phpunit-dom-assertions gets released
* https://github.com/phpunit/phpunit-dom-assertions
*
* @param array $matcher
* @param string $actual
* @param string $message
* @since Method available since Release 3.5.0
* @param bool $isHtml
* @uses Unittest_TestCase::tag_match
*/
public static function assertAttributeInstanceOf($expected, $attributeName, $classOrObject, $message = '')
public static function assertNotTag($matcher, $actual, $message = '', $isHtml = true)
{
if(self::$_assert_type_compatability)
{
return self::assertAttributeType($expected, $attributeName, $classOrObject, $message);
}
//trigger_error(__METHOD__ . ' is deprecated', E_USER_DEPRECATED);
return parent::assertAttributeInstanceOf($expected, $attributeName, $classOrObject, $message);
$matched = static::tag_match($matcher, $actual, $message, $isHtml);
static::assertFalse($matched, $message);
}
/**
* Asserts that a variable is not of a given type.
* Helper function to match HTML string tags against certain criteria
*
* @param string $expected
* @param mixed $actual
* @param string $message
* @since Method available since Release 3.5.0
*/
public static function assertNotInstanceOf($expected, $actual, $message = '')
{
if(self::$_assert_type_compatability)
{
return self::assertNotType($expected, $actual, $message);
}
return self::assertNotInstanceOf($expected, $actual, $message);
}
/**
* Asserts that an attribute is of a given type.
* TODO:
* this should be removed when phpunit-dom-assertions gets released
* https://github.com/phpunit/phpunit-dom-assertions
*
* @param string $expected
* @param string $attributeName
* @param mixed $classOrObject
* @param array $matcher
* @param string $actual
* @param string $message
* @since Method available since Release 3.5.0
* @param bool $isHtml
* @return bool TRUE if there is a match FALSE otherwise
*/
public static function assertAttributeNotInstanceOf($expected, $attributeName, $classOrObject, $message = '')
protected static function tag_match($matcher, $actual, $message = '', $isHtml = true)
{
if(self::$_assert_type_compatability)
{
return self::assertAttributeNotType($expected, $attributeName, $classOrObject, $message);
}
return self::assertAttributeNotInstanceOf($expected, $attributeName, $classOrObject, $message);
}
/**
* Asserts that a variable is of a given type.
*
* @param string $expected
* @param mixed $actual
* @param string $message
* @since Method available since Release 3.5.0
*/
public static function assertInternalType($expected, $actual, $message = '')
{
if(self::$_assert_type_compatability)
{
return self::assertType($expected, $actual, $message);
}
return parent::assertInternalType($expected, $actual, $message);
}
/**
* Asserts that an attribute is of a given type.
*
* @param string $expected
* @param string $attributeName
* @param mixed $classOrObject
* @param string $message
* @since Method available since Release 3.5.0
*/
public static function assertAttributeInternalType($expected, $attributeName, $classOrObject, $message = '')
{
if(self::$_assert_type_compatability)
{
return self::assertAttributeType($expected, $attributeName, $classOrObject, $message);
}
return self::assertAttributeInternalType($expected, $attributeName, $classOrObject, $message);
}
/**
* Asserts that a variable is not of a given type.
*
* @param string $expected
* @param mixed $actual
* @param string $message
* @since Method available since Release 3.5.0
*/
public static function assertNotInternalType($expected, $actual, $message = '')
{
if(self::$_assert_type_compatability)
{
return self::assertNotType($expected, $actual, $message);
}
return self::assertNotInternalType($expected, $actual, $message);
}
/**
* Asserts that an attribute is of a given type.
*
* @param string $expected
* @param string $attributeName
* @param mixed $classOrObject
* @param string $message
* @since Method available since Release 3.5.0
*/
public static function assertAttributeNotInternalType($expected, $attributeName, $classOrObject, $message = '')
{
if(self::$_assert_type_compatability)
{
return self::assertAttributeNotType($expected, $attributeName, $classOrObject, $message);
}
return self::assertAttributeNotInternalType($expected, $attributeName, $classOrObject, $message);
$dom = PHPUnit_Util_XML::load($actual, $isHtml);
$tags = PHPUnit_Util_XML::findNodes($dom, $matcher, $isHtml);
return count($tags) > 0 && $tags[0] instanceof DOMNode;
}
}

View File

@ -1,4 +1,4 @@
<?php
<?php defined('SYSPATH') or die('No direct script access.');
/**
* Transparent extension for Kohana_Unittest_Database_TestCase

View File

@ -0,0 +1,41 @@
{
"name": "kohana/unittest",
"type": "kohana-module",
"description": "PHPUnit integration for running unit tests on the Kohana framework",
"homepage": "http://kohanaframework.org",
"license": "BSD-3-Clause",
"keywords": ["kohana", "framework"],
"authors": [
{
"name": "Kohana Team",
"email": "team@kohanaframework.org",
"homepage": "http://kohanaframework.org/team",
"role": "developer"
}
],
"support": {
"issues": "http://dev.kohanaframework.org",
"forum": "http://forum.kohanaframework.org",
"irc": "irc://irc.freenode.net/kohana",
"source": "http://github.com/kohana/core"
},
"require": {
"composer/installers": "~1.0",
"kohana/core": ">=3.3",
"php": ">=5.3.3",
"phpunit/phpunit": "3.7.24 - 4"
},
"require-dev": {
"kohana/core": "3.3.*@dev",
"kohana/koharness": "*@dev"
},
"extra": {
"branch-alias": {
"dev-3.3/develop": "3.3.x-dev",
"dev-3.4/develop": "3.4.x-dev"
},
"installer-paths": {
"vendor/{$vendor}/{$name}": ["type:kohana-module"]
}
}
}

View File

@ -0,0 +1,7 @@
<?php
// Configuration for koharness - builds a standalone skeleton Kohana app for running unit tests
return array(
'modules' => array(
'unittest' => __DIR__
),
);

View File

@ -0,0 +1,37 @@
sudo: false
language: php
# Only build the main develop/master branches - feature branches will be covered by PRs
branches:
only:
- /^[0-9\.]+\/(develop|master)$/
cache:
directories:
- vendor
- $HOME/.composer/cache
php:
- 5.3
- 5.4
- 5.5
- 5.6
- 7.0
- hhvm
matrix:
include:
- php: 5.3
env: 'COMPOSER_PHPUNIT="lowest"'
before_script:
- composer install --prefer-dist
- if [ "$COMPOSER_PHPUNIT" = "lowest" ]; then composer update --prefer-lowest --with-dependencies phpunit/phpunit; fi;
- vendor/bin/koharness
script:
- cd /tmp/koharness && ./vendor/bin/phpunit --bootstrap=modules/unittest/bootstrap.php modules/unittest/tests.php
notifications:
email: false

View File

@ -1,3 +1,10 @@
# Kohana - userguide module
| ver | Stable | Develop |
|-------|----------------------------------------------------------------------------------------------------------------------------------------|------------------------------------------------------------------------------------------------------------------------------------------|
| 3.3.x | [![Build Status - 3.3/master](https://travis-ci.org/kohana/userguide.svg?branch=3.3%2Fmaster)](https://travis-ci.org/kohana/userguide) | [![Build Status - 3.3/develop](https://travis-ci.org/kohana/userguide.svg?branch=3.3%2Fdevelop)](https://travis-ci.org/kohana/userguide) |
| 3.4.x | [![Build Status - 3.4/master](https://travis-ci.org/kohana/userguide.svg?branch=3.4%2Fmaster)](https://travis-ci.org/kohana/userguide) | [![Build Status - 3.4/develop](https://travis-ci.org/kohana/userguide.svg?branch=3.4%2Fdevelop)](https://travis-ci.org/kohana/userguide) |
## What needs to be done?
Most articles are stubs, with a couple links to pages to be used as a reference when writing the page. The idea is to use the information on those links to help write the new ones. Some of the old userguide pages can probably be mostly copied, with a few improvements, others will be better to be completely rewritten. If you ever have questions, please feel free to jump in the kohana irc channel.

View File

@ -3,8 +3,10 @@
* Kohana user guide and api browser.
*
* @package Kohana/Userguide
* @category Controllers
* @category Controller
* @author Kohana Team
* @copyright (c) 2008-2013 Kohana Team
* @license http://kohanaframework.org/license
*/
abstract class Kohana_Controller_Userguide extends Controller_Template {
@ -76,7 +78,7 @@ abstract class Kohana_Controller_Userguide extends Controller_Template {
);
}
// If we are in the api browser, show the menu and show the api browser in the breadcrumbs
else if (Route::name($this->request->route()) == 'docs/api')
elseif (Route::name($this->request->route()) == 'docs/api')
{
$this->template->menu = Kodoc::menu();
@ -116,13 +118,13 @@ abstract class Kohana_Controller_Userguide extends Controller_Template {
}
// Prevent "guide/module" and "guide/module/index" from having duplicate content
if ( $page == 'index')
if ($page == 'index')
{
return $this->error('Userguide page not found');
}
// If a module is set, but no page was provided in the url, show the index page
if ( ! $page )
if ( ! $page)
{
$page = 'index';
}
@ -141,12 +143,14 @@ abstract class Kohana_Controller_Userguide extends Controller_Template {
Kodoc_Markdown::$image_url = URL::site($this->media->uri()).'/'.$module.'/';
// Set the page title
$this->template->title = $page == 'index' ? Kohana::$config->load('userguide.modules.'.$module.'.name') : $this->title($page);
$this->template->title = ($page == 'index')
? Kohana::$config->load('userguide.modules.'.$module.'.name')
: $this->title($page);
// Parse the page contents into the template
Kodoc_Markdown::$show_toc = true;
Kodoc_Markdown::$show_toc = TRUE;
$this->template->content = Kodoc_Markdown::markdown(file_get_contents($file));
Kodoc_Markdown::$show_toc = false;
Kodoc_Markdown::$show_toc = FALSE;
// Attach this module's menu to the template
$this->template->menu = Kodoc_Markdown::markdown($this->_get_all_menu_markdown());
@ -198,7 +202,7 @@ abstract class Kohana_Controller_Userguide extends Controller_Template {
// (different case, orm vs ORM, auth vs Auth) redirect
if ($_class->class->name != $class)
{
$this->request->redirect($this->request->route()->uri(array('class'=>$_class->class->name)));
$this->redirect($this->request->route()->uri(array('class'=>$_class->class->name)));
}
// If this classes immediate parent is Kodoc_Missing, then it should 404
@ -358,11 +362,7 @@ abstract class Kohana_Controller_Userguide extends Controller_Template {
if ($file AND $text = file_get_contents($file))
{
// Add spans around non-link categories. This is a terrible hack.
//echo Debug::vars($text);
//$text = preg_replace('/(\s*[\-\*\+]\s*)(.*)/','$1<span>$2</span>',$text);
$text = preg_replace('/^(\s*[\-\*\+]\s*)([^\[\]]+)$/m','$1<span>$2</span>',$text);
//echo Debug::vars($text);
$markdown .= $text;
}

View File

@ -5,8 +5,8 @@
* @package Kohana/Userguide
* @category Base
* @author Kohana Team
* @copyright (c) 2008-2012 Kohana Team
* @license http://kohanaphp.com/license
* @copyright (c) 2008-2013 Kohana Team
* @license http://kohanaframework.org/license
*/
class Kohana_Kodoc {
@ -34,6 +34,10 @@ class Kohana_Kodoc {
{
$member = '#property:'.substr($matches[3], 1);
}
elseif (preg_match('/^[A-Z_\x7f-\xff][A-Z0-9_\x7f-\xff]*$/', $matches[3]))
{
$member = '#constant:'.substr($matches[3],0);
}
else
{
$member = '#'.$matches[3];
@ -275,7 +279,7 @@ class Kohana_Kodoc {
* @param string $text Content of the tag
* @return void
*/
$add_tag = function($tag, $text) use ($html, &$tags)
$add_tag = function ($tag, $text) use ($html, & $tags)
{
// Don't show @access lines, they are shown elsewhere
if ($tag !== 'access')
@ -290,7 +294,7 @@ class Kohana_Kodoc {
}
};
$comment = $tag = null;
$comment = $tag = NULL;
$end = count($lines[1]) - 1;
foreach ($lines[1] as $i => $line)
@ -416,11 +420,11 @@ class Kohana_Kodoc {
* Module developers can therefore add their own transparent extension
* namespaces and exclude them from the userguide.
*
* @param string $class The name of the class to check for transparency
* @param array $classes An optional list of all defined classes
* @return false If this is not a transparent extension class
* @return string The name of the class that extends this (in the case provided)
* @throws InvalidArgumentException If the $classes array is provided and the $class variable is not lowercase
* @param string $class The name of the class to check for transparency
* @param array $classes An optional list of all defined classes
* @return false If this is not a transparent extension class
* @return string The name of the class that extends this (in the case provided)
* @throws InvalidArgumentException If the $classes array is provided and the $class variable is not lowercase
*/
public static function is_transparent($class, $classes = NULL)
{
@ -462,5 +466,4 @@ class Kohana_Kodoc {
}
}
} // End Kodoc

View File

@ -5,8 +5,8 @@
* @package Kohana/Userguide
* @category Base
* @author Kohana Team
* @copyright (c) 2009-2012 Kohana Team
* @license http://kohanaphp.com/license
* @copyright (c) 2008-2013 Kohana Team
* @license http://kohanaframework.org/license
*/
class Kohana_Kodoc_Class extends Kodoc {
@ -45,7 +45,7 @@ class Kohana_Kodoc_Class extends Kodoc {
* the class. Reads the class modifiers, constants and comment. Parses the
* comment to find the description and tags.
*
* @param string class name
* @param string Class name
* @return void
*/
public function __construct($class)
@ -194,10 +194,11 @@ class Kohana_Kodoc_Class extends Kodoc {
/**
* Sort methods based on their visibility and declaring class based on:
* - methods will be sorted public, protected, then private.
* - methods that are declared by an ancestor will be after classes
*
* * methods will be sorted public, protected, then private.
* * methods that are declared by an ancestor will be after classes
* declared by the current class
* - lastly, they will be sorted alphabetically
* * lastly, they will be sorted alphabetically
*
*/
protected function _method_sort($a, $b)
@ -276,4 +277,5 @@ class Kohana_Kodoc_Class extends Kodoc {
return $result;
}
}
} // End Kodoc_Class

View File

@ -5,8 +5,8 @@
* @package Kohana/Userguide
* @category Base
* @author Kohana Team
* @copyright (c) 2009-2012 Kohana Team
* @license http://kohanaphp.com/license
* @copyright (c) 2008-2013 Kohana Team
* @license http://kohanaframework.org/license
*/
class Kohana_Kodoc_Markdown extends MarkdownExtra_Parser {
@ -23,7 +23,8 @@ class Kohana_Kodoc_Markdown extends MarkdownExtra_Parser {
/**
* Currently defined heading ids.
* Used to prevent creating multiple headings with same id.
* @var array
*
* @var array
*/
protected $_heading_ids = array();
@ -36,7 +37,7 @@ class Kohana_Kodoc_Markdown extends MarkdownExtra_Parser {
* Slightly less terrible way to make it so the TOC only shows up when we
* want it to. set this to true to show the toc.
*/
public static $show_toc = false;
public static $show_toc = FALSE;
/**
* Transform some text using [Kodoc_Markdown]
@ -78,8 +79,8 @@ class Kohana_Kodoc_Markdown extends MarkdownExtra_Parser {
// Show table of contents for userguide pages
$this->document_gamut['doTOC'] = 100;
// PHP4 makes me sad.
parent::MarkdownExtra_Parser();
// Call parent constructor.
parent::__construct();
}
/**
@ -88,25 +89,27 @@ class Kohana_Kodoc_Markdown extends MarkdownExtra_Parser {
* Heading 1
* =========
*
* @param array Matches from regex call
* @return string Generated html
* @param array Matches from regex call
* @return string Generated html
*/
function _doHeaders_callback_setext($matches)
{
if ($matches[3] == '-' && preg_match('{^- }', $matches[1]))
if ($matches[3] == '-' AND preg_match('{^- }', $matches[1]))
return $matches[0];
$level = $matches[3]{0} == '=' ? 1 : 2;
$level = ($matches[3]{0} == '=') ? 1 : 2;
$attr = $this->_doHeaders_attr($id =& $matches[2]);
// Only auto-generate id if one doesn't exist
if(empty($attr))
if (empty($attr))
{
$attr = ' id="'.$this->make_heading_id($matches[1]).'"';
}
// Add this header to the page toc
$this->_add_to_toc($level,$matches[1],$this->make_heading_id($matches[1]));
$block = "<h$level$attr>".$this->runSpanGamut($matches[1])."</h$level>";
return "\n" . $this->hashBlock($block) . "\n\n";
return "\n".$this->hashBlock($block)."\n\n";
}
/**
@ -114,8 +117,8 @@ class Kohana_Kodoc_Markdown extends MarkdownExtra_Parser {
*
* # Heading 1
*
* @param array Matches from regex call
* @return string Generated html
* @param array Matches from regex call
* @return string Generated html
*/
function _doHeaders_callback_atx($matches)
{
@ -123,14 +126,16 @@ class Kohana_Kodoc_Markdown extends MarkdownExtra_Parser {
$attr = $this->_doHeaders_attr($id =& $matches[3]);
// Only auto-generate id if one doesn't exist
if(empty($attr))
if (empty($attr))
{
$attr = ' id="'.$this->make_heading_id($matches[2]).'"';
}
// Add this header to the page toc
$this->_add_to_toc($level, $matches[2], $this->make_heading_id(empty($matches[3]) ? $matches[2] : $matches[3]));
$block = "<h$level$attr>".$this->runSpanGamut($matches[2])."</h$level>";
return "\n" . $this->hashBlock($block) . "\n\n";
return "\n".$this->hashBlock($block)."\n\n";
}
@ -138,14 +143,14 @@ class Kohana_Kodoc_Markdown extends MarkdownExtra_Parser {
* Makes a heading id from the heading text
* If any heading share the same name then subsequent headings will have an integer appended
*
* @param string The heading text
* @return string ID for the heading
* @param string The heading text
* @return string ID for the heading
*/
function make_heading_id($heading)
{
$id = url::title($heading, '-', TRUE);
if(isset($this->_heading_ids[$id]))
if (isset($this->_heading_ids[$id]))
{
$id .= '-';
@ -166,8 +171,6 @@ class Kohana_Kodoc_Markdown extends MarkdownExtra_Parser {
{
$replace = array();
$replace = array();
foreach ($matches as $set)
{
list($search, $view) = $set;
@ -203,7 +206,7 @@ class Kohana_Kodoc_Markdown extends MarkdownExtra_Parser {
*
* [filesystem](about.filesystem "Optional title")
*
* @param string span text
* @param string Span text
* @return string
*/
public function doBaseURL($text)
@ -217,7 +220,7 @@ class Kohana_Kodoc_Markdown extends MarkdownExtra_Parser {
*
* ![Install Page](img/install.png "Optional title")
*
* @param string span text
* @param string Span text
* @return string
*/
public function doImageURL($text)
@ -231,7 +234,7 @@ class Kohana_Kodoc_Markdown extends MarkdownExtra_Parser {
*
* [Class_Name], [Class::method] or [Class::$property]
*
* @param string span text
* @param string Span text
* @return string
*/
public function doAPI($text)
@ -244,7 +247,7 @@ class Kohana_Kodoc_Markdown extends MarkdownExtra_Parser {
*
* [!!] Remember the milk!
*
* @param string span text
* @param string Span text
* @return string
*/
public function doNotes($text)

View File

@ -5,28 +5,28 @@
* @package Kohana/Userguide
* @category Base
* @author Kohana Team
* @copyright (c) 2009 Kohana Team
* @license http://kohanaphp.com/license
* @copyright (c) 2008-2013 Kohana Team
* @license http://kohanaframework.org/license
*/
class Kohana_Kodoc_Method extends Kodoc {
/**
* @var ReflectionMethod The ReflectionMethod for this class
* @var ReflectionMethod The ReflectionMethod for this class
*/
public $method;
/**
* @var array array of Kodoc_Method_Param
* @var array Array of Kodoc_Method_Param
*/
public $params;
/**
* @var array the things this function can return
* @var array The things this function can return
*/
public $return = array();
/**
* @var string the source code for this function
* @var string The source code for this function
*/
public $source;

View File

@ -5,8 +5,8 @@
* @package Kohana/Userguide
* @category Base
* @author Kohana Team
* @copyright (c) 2009 Kohana Team
* @license http://kohanaphp.com/license
* @copyright (c) 2008-2013 Kohana Team
* @license http://kohanaframework.org/license
*/
class Kohana_Kodoc_Method_Param extends Kodoc {

View File

@ -7,6 +7,8 @@
* @package Kohana/Userguide
* @category Undocumented
* @author Kohana Team
* @copyright (c) 2008-2013 Kohana Team
* @license http://kohanaframework.org/license
* @since 3.0.7
*/
abstract class Kohana_Kodoc_Missing {

View File

@ -5,8 +5,8 @@
* @package Kohana/Userguide
* @category Base
* @author Kohana Team
* @copyright (c) 2009-2012 Kohana Team
* @license http://kohanaphp.com/license
* @copyright (c) 2008-2013 Kohana Team
* @license http://kohanaframework.org/license
*/
class Kohana_Kodoc_Property extends Kodoc {

View File

@ -0,0 +1,41 @@
{
"name": "kohana/userguide",
"type": "kohana-module",
"description": "Kohana user guide and live API documentation module",
"homepage": "http://kohanaframework.org",
"license": "BSD-3-Clause",
"keywords": ["kohana", "framework", "docs"],
"authors": [
{
"name": "Kohana Team",
"email": "team@kohanaframework.org",
"homepage": "http://kohanaframework.org/team",
"role": "developer"
}
],
"support": {
"issues": "http://dev.kohanaframework.org",
"forum": "http://forum.kohanaframework.org",
"irc": "irc://irc.freenode.net/kohana",
"source": "http://github.com/kohana/core"
},
"require": {
"composer/installers": "~1.0",
"kohana/core": ">=3.3",
"php": ">=5.3.3"
},
"require-dev": {
"kohana/core": "3.3.*@dev",
"kohana/unittest": "3.3.*@dev",
"kohana/koharness": "*@dev"
},
"extra": {
"branch-alias": {
"dev-3.3/develop": "3.3.x-dev",
"dev-3.4/develop": "3.4.x-dev"
},
"installer-paths": {
"vendor/{$vendor}/{$name}": ["type:kohana-module"]
}
}
}

View File

@ -28,7 +28,7 @@ return array
'description' => 'Documentation viewer and api generation.',
// Copyright message, shown in the footer for this module
'copyright' => '&copy; 20082012 Kohana Team',
'copyright' => '&copy; 20082014 Kohana Team',
)
),

Some files were not shown because too many files have changed in this diff Show More