Compare commits
1 Commits
leenooks-3
...
master
Author | SHA1 | Date | |
---|---|---|---|
|
68c7f4f159 |
@ -1,13 +1,13 @@
|
|||||||
# Developing locally
|
# 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 it's version:
|
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/master
|
||||||
- 3.2/develop
|
- 3.2/develop
|
||||||
- 3.3/master
|
- 3.3/master
|
||||||
- 3.3/develop
|
- 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.
|
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
|
## Branch name meanings
|
||||||
|
|
||||||
@ -17,7 +17,7 @@ and so on. All development of versions happens in the develop branch of that ver
|
|||||||
- **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/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.
|
- **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.
|
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.
|
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.
|
Release branch names follow the same convention in both kohana/kohana and kohana/core.
|
||||||
@ -37,7 +37,7 @@ To work on 3.3.x you'd do the following:
|
|||||||
> git submodule foreach "git fetch && git checkout 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
|
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
|
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:
|
a `git submodule update` and run `git status` you'll be told:
|
||||||
|
|
||||||
@ -48,7 +48,7 @@ a `git submodule update` and run `git status` you'll be told:
|
|||||||
|
|
||||||
# Contributing to the project
|
# Contributing to the project
|
||||||
|
|
||||||
All features and bugfixes must be fully tested and reference an issue in the [tracker](http://dev.kohanaframework.org/projects/kohana3), **there are absolutely no exceptions**.
|
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.
|
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.
|
||||||
|
|
||||||
@ -68,7 +68,7 @@ The naming convention for feature branches is:
|
|||||||
3.2/feature/4045-rewriting-config-system
|
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
|
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
|
`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.
|
detailing what branch you're merging from. This makes it a lot easier to analyse a feature's history.
|
||||||
|
|
||||||
Here's a quick example:
|
Here's a quick example:
|
||||||
@ -81,7 +81,7 @@ Here's a quick example:
|
|||||||
|
|
||||||
> git merge --no-ff 3.2/feature/4045-rewriting-everything
|
> 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!**
|
**If a change you make intentionally breaks the API then please correct the relevant tests before pushing!**
|
||||||
|
|
||||||
## Bug fixing
|
## Bug fixing
|
||||||
|
|
||||||
@ -92,7 +92,7 @@ using the `@ticket` notation in the test to reference the bug's issue number
|
|||||||
If you run the unit tests then the one you've just made should fail.
|
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
|
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.
|
fix actually works, then commit both the fix and the test.
|
||||||
|
|
||||||
**Bug fixes without tests written will be rejected! There are NO exceptions.**
|
**Bug fixes without tests written will be rejected! There are NO exceptions.**
|
||||||
|
|
||||||
@ -101,11 +101,11 @@ branch is perfectly acceptable.
|
|||||||
|
|
||||||
## Tagging releases
|
## Tagging releases
|
||||||
|
|
||||||
Tag names should be prefixed with a `v`, this helps to separate tag references from branch references in git.
|
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`
|
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
|
# Merging changes from remote repositories
|
||||||
|
|
||||||
Now that you have a remote repository, you can pull changes in the remote "kohana" repository
|
Now that you have a remote repository, you can pull changes in the remote "kohana" repository
|
||||||
into your local repository:
|
into your local repository:
|
||||||
@ -115,14 +115,14 @@ into your local repository:
|
|||||||
**Note:** Before you pull changes you should make sure that any modifications you've made locally
|
**Note:** Before you pull changes you should make sure that any modifications you've made locally
|
||||||
have been committed.
|
have been committed.
|
||||||
|
|
||||||
Sometimes a commit you've made locally will conflict with one made in the "kohana" one.
|
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:
|
There are a couple of scenarios where this might happen:
|
||||||
|
|
||||||
## The conflict is to do with a few unrelated commits and you want to keep changes made in both commits
|
## 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"
|
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
|
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
|
## You've fixed something locally which someone else has already done in the remote repo
|
||||||
|
|
||||||
@ -147,14 +147,14 @@ i.e.
|
|||||||
|
|
||||||
> git rebase -i 57d0b28
|
> git rebase -i 57d0b28
|
||||||
|
|
||||||
A text editor will open with a list of commits, delete the line containing the offending commit
|
A text editor will open with a list of commits. Delete the line containing the offending commit
|
||||||
before saving the file & closing your editor.
|
before saving the file & closing your editor.
|
||||||
|
|
||||||
Git will remove the commit and you can then pull/merge the remote changes.
|
Git will remove the commit and you can then pull/merge the remote changes.
|
||||||
|
|
||||||
# Unit Testing
|
# Unit Testing
|
||||||
|
|
||||||
Kohana currently uses phpunit for unit testing. This is installed with composer.
|
Kohana currently uses PHPUnit for unit testing. This is installed with composer.
|
||||||
|
|
||||||
## How to run the tests
|
## How to run the tests
|
||||||
|
|
||||||
@ -164,4 +164,4 @@ Kohana currently uses phpunit for unit testing. This is installed with composer.
|
|||||||
* Run `php composer.phar install` from the root of this repository
|
* Run `php composer.phar install` from the root of this repository
|
||||||
* Finally, run `phing test`
|
* 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.
|
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.
|
||||||
|
@ -131,6 +131,15 @@ Kohana::modules(array(
|
|||||||
// 'userguide' => MODPATH.'userguide', // User guide and API documentation
|
// '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
|
* Set the routes. Each route must have a minimum of a name, a URI and a set of
|
||||||
* defaults for the URI.
|
* defaults for the URI.
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"require": {
|
"require": {
|
||||||
"phpunit/phpunit": "3.7.24",
|
"phpunit/phpunit": "3.7.24 - 4",
|
||||||
"phing/phing": "dev-master"
|
"phing/phing": "dev-master"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
37
modules/auth/.travis.yml
Normal file
37
modules/auth/.travis.yml
Normal 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
|
@ -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:
|
I've forked the main Auth module because there were some fundamental flaws with it:
|
||||||
|
|
||||||
|
@ -24,10 +24,18 @@
|
|||||||
"kohana/core": ">=3.3",
|
"kohana/core": ">=3.3",
|
||||||
"php": ">=5.3.3"
|
"php": ">=5.3.3"
|
||||||
},
|
},
|
||||||
|
"require-dev": {
|
||||||
|
"kohana/core": "3.3.*@dev",
|
||||||
|
"kohana/unittest": "3.3.*@dev",
|
||||||
|
"kohana/koharness": "*@dev"
|
||||||
|
},
|
||||||
"extra": {
|
"extra": {
|
||||||
"branch-alias": {
|
"branch-alias": {
|
||||||
"dev-3.3/develop": "3.3.x-dev",
|
"dev-3.3/develop": "3.3.x-dev",
|
||||||
"dev-3.4/develop": "3.4.x-dev"
|
"dev-3.4/develop": "3.4.x-dev"
|
||||||
|
},
|
||||||
|
"installer-paths": {
|
||||||
|
"vendor/{$vendor}/{$name}": ["type:kohana-module"]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
8
modules/auth/koharness.php
Normal file
8
modules/auth/koharness.php
Normal 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
45
modules/cache/.travis.yml
vendored
Normal 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
|
6
modules/cache/README.md
vendored
6
modules/cache/README.md
vendored
@ -1,6 +1,12 @@
|
|||||||
Kohana Cache library
|
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.
|
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
|
Supported cache solutions
|
||||||
|
3
modules/cache/classes/Cache/Apcu.php
vendored
Normal file
3
modules/cache/classes/Cache/Apcu.php
vendored
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
<?php defined('SYSPATH') or die('No direct script access.');
|
||||||
|
|
||||||
|
class Cache_Apcu extends Kohana_Cache_Apcu {}
|
10
modules/cache/classes/Kohana/Cache.php
vendored
10
modules/cache/classes/Kohana/Cache.php
vendored
@ -36,7 +36,7 @@
|
|||||||
* Below is an example of a _memcache_ server configuration.
|
* Below is an example of a _memcache_ server configuration.
|
||||||
*
|
*
|
||||||
* return array(
|
* return array(
|
||||||
* 'default' => array( // Default group
|
* 'memcache' => array( // Name of group
|
||||||
* 'driver' => 'memcache', // using Memcache driver
|
* 'driver' => 'memcache', // using Memcache driver
|
||||||
* 'servers' => array( // Available server definitions
|
* 'servers' => array( // Available server definitions
|
||||||
* array(
|
* array(
|
||||||
@ -49,8 +49,12 @@
|
|||||||
* ),
|
* ),
|
||||||
* )
|
* )
|
||||||
*
|
*
|
||||||
* In cases where only one cache group is required, if the group is named `default` there is
|
* In cases where only one cache group is required, set `Cache::$default` (in your bootstrap,
|
||||||
* no need to pass the group name when instantiating a cache instance.
|
* 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
|
* #### General cache group configuration settings
|
||||||
*
|
*
|
||||||
|
174
modules/cache/classes/Kohana/Cache/Apcu.php
vendored
Normal file
174
modules/cache/classes/Kohana/Cache/Apcu.php
vendored
Normal 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
|
93
modules/cache/classes/Kohana/Cache/File.php
vendored
93
modules/cache/classes/Kohana/Cache/File.php
vendored
@ -140,17 +140,21 @@ class Kohana_Cache_File extends Cache implements Cache_GarbageCollect {
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// Open the file and parse data
|
// Test the expiry
|
||||||
$created = $file->getMTime();
|
if ($this->_is_expired($file))
|
||||||
$data = $file->openFile();
|
|
||||||
$lifetime = $data->fgets();
|
|
||||||
|
|
||||||
// If we're at the EOF at this point, corrupted!
|
|
||||||
if ($data->eof())
|
|
||||||
{
|
{
|
||||||
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 = '';
|
$cache = '';
|
||||||
|
|
||||||
while ($data->eof() === FALSE)
|
while ($data->eof() === FALSE)
|
||||||
@ -158,17 +162,7 @@ class Kohana_Cache_File extends Cache implements Cache_GarbageCollect {
|
|||||||
$cache .= $data->fgets();
|
$cache .= $data->fgets();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Test the expiry
|
return unserialize($cache);
|
||||||
if (($created + (int) $lifetime) < time())
|
|
||||||
{
|
|
||||||
// Delete the file
|
|
||||||
$this->_delete_file($file, NULL, TRUE);
|
|
||||||
return $default;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
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 the directory path is not a directory
|
||||||
if ( ! $dir->isDir())
|
if ( ! $dir->isDir())
|
||||||
{
|
{
|
||||||
// Create the directory
|
$this->_make_directory($directory, 0777, TRUE);
|
||||||
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);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Open file to inspect
|
// 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));
|
$filename = Cache_File::filename($this->_sanitize_id($id));
|
||||||
$directory = $this->_resolve_directory($filename);
|
$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
|
else
|
||||||
{
|
{
|
||||||
// Assess the file expiry to flag it for deletion
|
// Assess the file expiry to flag it for deletion
|
||||||
$json = $file->openFile('r')->current();
|
$delete = $this->_is_expired($file);
|
||||||
$data = json_decode($json);
|
|
||||||
$delete = $data->expiry < time();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// If the delete flag is set delete 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
|
// Create new file resource
|
||||||
$fp = new SplFileInfo($files->getRealPath());
|
$fp = new SplFileInfo($files->getRealPath());
|
||||||
// Delete the file
|
// Delete the file
|
||||||
$this->_delete_file($fp);
|
$this->_delete_file($fp, $retain_parent_directory, $ignore_errors, $only_expired);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Move the file pointer on
|
// Move the file pointer on
|
||||||
@ -446,21 +431,55 @@ class Kohana_Cache_File extends Cache implements Cache_GarbageCollect {
|
|||||||
* `mkdir` to ensure DRY principles
|
* `mkdir` to ensure DRY principles
|
||||||
*
|
*
|
||||||
* @link http://php.net/manual/en/function.mkdir.php
|
* @link http://php.net/manual/en/function.mkdir.php
|
||||||
* @param string $directory
|
* @param string $directory directory path
|
||||||
* @param integer $mode
|
* @param integer $mode chmod mode
|
||||||
* @param boolean $recursive
|
* @param boolean $recursive allows nested directories creation
|
||||||
* @param resource $context
|
* @param resource $context a stream context
|
||||||
* @return SplFileInfo
|
* @return SplFileInfo
|
||||||
* @throws Cache_Exception
|
* @throws Cache_Exception
|
||||||
*/
|
*/
|
||||||
protected function _make_directory($directory, $mode = 0777, $recursive = FALSE, $context = NULL)
|
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));
|
throw new Cache_Exception('Failed to create the defined cache directory : :directory', array(':directory' => $directory));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// chmod to solve potential umask issues
|
||||||
chmod($directory, $mode);
|
chmod($directory, $mode);
|
||||||
|
|
||||||
return new SplFileInfo($directory);
|
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()));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
6
modules/cache/classes/Kohana/HTTP/Cache.php
vendored
6
modules/cache/classes/Kohana/HTTP/Cache.php
vendored
@ -1,6 +1,6 @@
|
|||||||
<?php defined('SYSPATH') or die('No direct script access.');
|
<?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
|
* [Request_Client] class, using HTTP cache control logic as defined in
|
||||||
* RFC 2616.
|
* RFC 2616.
|
||||||
*
|
*
|
||||||
@ -36,7 +36,7 @@ class Kohana_HTTP_Cache {
|
|||||||
* )
|
* )
|
||||||
* );
|
* );
|
||||||
*
|
*
|
||||||
* @uses [Cache]
|
* @uses Cache
|
||||||
* @param mixed $cache cache engine to use
|
* @param mixed $cache cache engine to use
|
||||||
* @param array $options options to set to this class
|
* @param array $options options to set to this class
|
||||||
* @return HTTP_Cache
|
* @return HTTP_Cache
|
||||||
@ -298,7 +298,7 @@ class Kohana_HTTP_Cache {
|
|||||||
* Controls whether the response can be cached. Uses HTTP
|
* Controls whether the response can be cached. Uses HTTP
|
||||||
* protocol to determine whether the response can be cached.
|
* 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
|
* @param Response $response The Response
|
||||||
* @return boolean
|
* @return boolean
|
||||||
*/
|
*/
|
||||||
|
10
modules/cache/composer.json
vendored
10
modules/cache/composer.json
vendored
@ -24,10 +24,18 @@
|
|||||||
"kohana/core": ">=3.3",
|
"kohana/core": ">=3.3",
|
||||||
"php": ">=5.3.3"
|
"php": ">=5.3.3"
|
||||||
},
|
},
|
||||||
|
"require-dev": {
|
||||||
|
"kohana/core": "3.3.*@dev",
|
||||||
|
"kohana/unittest": "3.3.*@dev",
|
||||||
|
"kohana/koharness": "*@dev"
|
||||||
|
},
|
||||||
"extra": {
|
"extra": {
|
||||||
"branch-alias": {
|
"branch-alias": {
|
||||||
"dev-3.3/develop": "3.3.x-dev",
|
"dev-3.3/develop": "3.3.x-dev",
|
||||||
"dev-3.4/develop": "3.4.x-dev"
|
"dev-3.4/develop": "3.4.x-dev"
|
||||||
}
|
},
|
||||||
|
"installer-paths": {
|
||||||
|
"vendor/{$vendor}/{$name}": ["type:kohana-module"]
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
12
modules/cache/guide/cache/config.md
vendored
12
modules/cache/guide/cache/config.md
vendored
@ -55,7 +55,7 @@ failure_callback | __NO__ | (_[callback](http://www.php.net/manual/en/language
|
|||||||
'driver' => 'memcache',
|
'driver' => 'memcache',
|
||||||
'default_expire' => 3600,
|
'default_expire' => 3600,
|
||||||
'compression' => FALSE, // Use Zlib compression
|
'compression' => FALSE, // Use Zlib compression
|
||||||
(can cause issues with integers)
|
// (can cause issues with integers)
|
||||||
'servers' => array
|
'servers' => array
|
||||||
(
|
(
|
||||||
'local' => array
|
'local' => array
|
||||||
@ -71,7 +71,7 @@ failure_callback | __NO__ | (_[callback](http://www.php.net/manual/en/language
|
|||||||
'driver' => 'memcachetag',
|
'driver' => 'memcachetag',
|
||||||
'default_expire' => 3600,
|
'default_expire' => 3600,
|
||||||
'compression' => FALSE, // Use Zlib compression
|
'compression' => FALSE, // Use Zlib compression
|
||||||
(can cause issues with integers)
|
// (can cause issues with integers)
|
||||||
'servers' => array
|
'servers' => array
|
||||||
(
|
(
|
||||||
'local' => array
|
'local' => array
|
||||||
@ -90,7 +90,15 @@ failure_callback | __NO__ | (_[callback](http://www.php.net/manual/en/language
|
|||||||
'driver' => 'apc',
|
'driver' => 'apc',
|
||||||
'default_expire' => 3600,
|
'default_expire' => 3600,
|
||||||
),
|
),
|
||||||
|
|
||||||
|
## APCu settings
|
||||||
|
|
||||||
|
'apcu' => array
|
||||||
|
(
|
||||||
|
'driver' => 'apcu',
|
||||||
|
'default_expire' => 3600,
|
||||||
|
),
|
||||||
|
|
||||||
## SQLite settings
|
## SQLite settings
|
||||||
|
|
||||||
'sqlite' => array
|
'sqlite' => array
|
||||||
|
10
modules/cache/guide/cache/index.md
vendored
10
modules/cache/guide/cache/index.md
vendored
@ -6,7 +6,7 @@ instances of cache engines through a grouped singleton pattern.
|
|||||||
|
|
||||||
## Supported cache engines
|
## Supported cache engines
|
||||||
|
|
||||||
* APC ([Cache_Apc])
|
* APC/APCu ([Cache_Apc])
|
||||||
* File ([Cache_File])
|
* File ([Cache_File])
|
||||||
* Memcached ([Cache_Memcache])
|
* Memcached ([Cache_Memcache])
|
||||||
* Memcached-tags ([Cache_Memcachetag])
|
* Memcached-tags ([Cache_Memcachetag])
|
||||||
@ -16,13 +16,13 @@ instances of cache engines through a grouped singleton pattern.
|
|||||||
## Introduction to caching
|
## Introduction to caching
|
||||||
|
|
||||||
Caching should be implemented with consideration. Generally, caching the result of resources
|
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.
|
a complex set of instructions.
|
||||||
|
|
||||||
Caching engines that use memory are considerably faster than file based alternatives. But
|
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.
|
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)
|
## 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
|
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
|
Wincache | __Memory__ | Excellent | No | No | Yes | Windows variant of APC
|
||||||
File | __Disk__ | Poor | No | No | No | Marginally faster than execution
|
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
|
Memcache (tag) | __Memory__ | Good | No (yes) | Yes | Yes | Generally fast distributed solution, but has a speed hit due to variable network latency and serialization
|
||||||
@ -54,4 +54,4 @@ It is possible to have hybrid cache solutions that use a combination of the engi
|
|||||||
## Minimum requirements
|
## Minimum requirements
|
||||||
|
|
||||||
* Kohana 3.0.4
|
* Kohana 3.0.4
|
||||||
* PHP 5.2.4 or greater
|
* PHP 5.2.4 or greater
|
||||||
|
10
modules/cache/guide/cache/usage.md
vendored
10
modules/cache/guide/cache/usage.md
vendored
@ -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
|
// Create a new instance of cache using the default group
|
||||||
$cache = Cache::instance();
|
$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.
|
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.
|
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
|
// Check for the existance of the cache driver
|
||||||
if (isset(Cache::$instances['memcache']))
|
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.
|
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
|
||||||
|
|
||||||
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.
|
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.
|
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
|
// Get an instance of cache
|
||||||
$cache = Cache::instance('memcachetag');
|
$cache = Cache::instance('memcachetag');
|
||||||
|
9
modules/cache/koharness.php
vendored
Normal file
9
modules/cache/koharness.php
vendored
Normal 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'
|
||||||
|
),
|
||||||
|
);
|
@ -164,6 +164,17 @@ TESTTEXT;
|
|||||||
),
|
),
|
||||||
'foo bar snafu'
|
'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(
|
||||||
array(
|
array(
|
||||||
'id' => 'bar',
|
'id' => 'bar',
|
||||||
@ -196,6 +207,28 @@ TESTTEXT;
|
|||||||
'default' => NULL,
|
'default' => NULL,
|
||||||
),
|
),
|
||||||
$html_text
|
$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'
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
9
modules/cache/tests/cache/CacheTest.php
vendored
9
modules/cache/tests/cache/CacheTest.php
vendored
@ -90,14 +90,13 @@ class Kohana_CacheTest extends PHPUnit_Framework_TestCase {
|
|||||||
*/
|
*/
|
||||||
public function test_cloning_fails()
|
public function test_cloning_fails()
|
||||||
{
|
{
|
||||||
if ( ! Kohana::$config->load('cache.file'))
|
$cache = $this->getMockBuilder('Cache')
|
||||||
{
|
->disableOriginalConstructor()
|
||||||
$this->markTestSkipped('Unable to load File configuration');
|
->getMockForAbstractClass();
|
||||||
}
|
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
$cache_clone = clone(Cache::instance('file'));
|
clone($cache);
|
||||||
}
|
}
|
||||||
catch (Cache_Exception $e)
|
catch (Cache_Exception $e)
|
||||||
{
|
{
|
||||||
|
69
modules/cache/tests/cache/FileTest.php
vendored
69
modules/cache/tests/cache/FileTest.php
vendored
@ -30,7 +30,21 @@ class Kohana_Cache_FileTest extends Kohana_CacheBasicMethodsTest {
|
|||||||
|
|
||||||
if ( ! Kohana::$config->load('cache.file'))
|
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'));
|
$this->cache(Cache::instance('file'));
|
||||||
@ -45,7 +59,7 @@ class Kohana_Cache_FileTest extends Kohana_CacheBasicMethodsTest {
|
|||||||
{
|
{
|
||||||
$cache = $this->cache();
|
$cache = $this->cache();
|
||||||
$config = Kohana::$config->load('cache')->file;
|
$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
|
// Lets pollute the cache folder
|
||||||
file_put_contents($file, 'foobar');
|
file_put_contents($file, 'foobar');
|
||||||
@ -95,4 +109,55 @@ class Kohana_Cache_FileTest extends Kohana_CacheBasicMethodsTest {
|
|||||||
$this->assertSame($expected, $cache->get('utf8'));
|
$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
|
} // End Kohana_SqliteTest
|
||||||
|
11
modules/cache/tests/cache/SqliteTest.php
vendored
11
modules/cache/tests/cache/SqliteTest.php
vendored
@ -35,7 +35,16 @@ class Kohana_SqliteTest extends Kohana_CacheBasicMethodsTest {
|
|||||||
|
|
||||||
if ( ! Kohana::$config->load('cache.sqlite'))
|
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'));
|
$this->cache(Cache::instance('sqlite'));
|
||||||
|
72
modules/cache/tests/cache/WincacheTest.php
vendored
72
modules/cache/tests/cache/WincacheTest.php
vendored
@ -1,39 +1,49 @@
|
|||||||
<?php
|
<?php
|
||||||
include_once(Kohana::find_file('tests/cache', '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
|
||||||
* @package Kohana/Cache
|
// any unexpected skipped tests.
|
||||||
* @group kohana
|
print "Skipping all Wincache driver tests as these will never run on Travis.".\PHP_EOL;
|
||||||
* @group kohana.cache
|
return;
|
||||||
* @category Test
|
}
|
||||||
* @author Kohana Team
|
else
|
||||||
* @copyright (c) 2009-2012 Kohana Team
|
{
|
||||||
* @license http://kohanaphp.com/license
|
include_once(Kohana::find_file('tests/cache', 'CacheBasicMethodsTest'));
|
||||||
*/
|
|
||||||
class Kohana_WincacheTest extends Kohana_CacheBasicMethodsTest {
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This method MUST be implemented by each driver to setup the `Cache`
|
* @package Kohana/Cache
|
||||||
* instance for each test.
|
* @group kohana
|
||||||
*
|
* @group kohana.cache
|
||||||
* This method should do the following tasks for each driver test:
|
* @category Test
|
||||||
*
|
* @author Kohana Team
|
||||||
* - Test the Cache instance driver is available, skip test otherwise
|
* @copyright (c) 2009-2012 Kohana Team
|
||||||
* - Setup the Cache instance
|
* @license http://kohanaphp.com/license
|
||||||
* - Call the parent setup method, `parent::setUp()`
|
|
||||||
*
|
|
||||||
* @return void
|
|
||||||
*/
|
*/
|
||||||
public function setUp()
|
class Kohana_WincacheTest extends Kohana_CacheBasicMethodsTest {
|
||||||
{
|
|
||||||
parent::setUp();
|
|
||||||
|
|
||||||
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
|
|
||||||
|
14
modules/cache/tests/cache/arithmetic/ApcTest.php
vendored
14
modules/cache/tests/cache/arithmetic/ApcTest.php
vendored
@ -39,6 +39,18 @@ class Kohana_ApcTest extends Kohana_CacheArithmeticMethodsTest {
|
|||||||
'place "apc.enable_cli=1" in your php.ini file');
|
'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'));
|
$this->cache(Cache::instance('apc'));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -57,7 +69,7 @@ class Kohana_ApcTest extends Kohana_CacheArithmeticMethodsTest {
|
|||||||
*
|
*
|
||||||
* @dataProvider provider_set_get
|
* @dataProvider provider_set_get
|
||||||
*
|
*
|
||||||
* @param array data
|
* @param array data
|
||||||
* @param mixed expected
|
* @param mixed expected
|
||||||
* @return void
|
* @return void
|
||||||
*/
|
*/
|
||||||
|
87
modules/cache/tests/cache/arithmetic/ApcuTest.php
vendored
Normal file
87
modules/cache/tests/cache/arithmetic/ApcuTest.php
vendored
Normal 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
|
@ -35,7 +35,28 @@ class Kohana_CacheArithmeticMemcacheTest extends Kohana_CacheArithmeticMethodsTe
|
|||||||
}
|
}
|
||||||
if ( ! $config = Kohana::$config->load('cache.memcache'))
|
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;
|
$memcache = new Memcache;
|
||||||
|
37
modules/codebench/.travis.yml
Normal file
37
modules/codebench/.travis.yml
Normal 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
|
@ -24,10 +24,18 @@
|
|||||||
"kohana/core": ">=3.3",
|
"kohana/core": ">=3.3",
|
||||||
"php": ">=5.3.3"
|
"php": ">=5.3.3"
|
||||||
},
|
},
|
||||||
|
"require-dev": {
|
||||||
|
"kohana/core": "3.3.*@dev",
|
||||||
|
"kohana/unittest": "3.3.*@dev",
|
||||||
|
"kohana/koharness": "*@dev"
|
||||||
|
},
|
||||||
"extra": {
|
"extra": {
|
||||||
"branch-alias": {
|
"branch-alias": {
|
||||||
"dev-3.3/develop": "3.3.x-dev",
|
"dev-3.3/develop": "3.3.x-dev",
|
||||||
"dev-3.4/develop": "3.4.x-dev"
|
"dev-3.4/develop": "3.4.x-dev"
|
||||||
}
|
},
|
||||||
|
"installer-paths": {
|
||||||
|
"vendor/{$vendor}/{$name}": ["type:kohana-module"]
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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.
|
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 several ways to validate HTML color values](codebench_screenshot1.png)
|
||||||
**Benchmarking seven ways to validate HTML color values**
|
**Benchmarking seven ways to validate HTML color values**
|
||||||
@ -73,4 +73,4 @@ Here is another short example with some extra explanations.
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
And the winner is… [ltrim](http://php.net/ltrim). Happy benchmarking!
|
And the winner is… [ltrim](http://php.net/ltrim). Happy benchmarking!
|
||||||
|
8
modules/codebench/koharness.php
Normal file
8
modules/codebench/koharness.php
Normal 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'
|
||||||
|
),
|
||||||
|
);
|
37
modules/database/.travis.yml
Normal file
37
modules/database/.travis.yml
Normal 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/database/README.md
Normal file
6
modules/database/README.md
Normal 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) |
|
3
modules/database/classes/Database/MySQLi.php
Normal file
3
modules/database/classes/Database/MySQLi.php
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
<?php defined('SYSPATH') OR die('No direct script access.');
|
||||||
|
|
||||||
|
class Database_MySQLi extends Kohana_Database_MySQLi {}
|
3
modules/database/classes/Database/MySQLi/Result.php
Normal file
3
modules/database/classes/Database/MySQLi/Result.php
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
<?php defined('SYSPATH') OR die('No direct script access.');
|
||||||
|
|
||||||
|
class Database_MySQLi_Result extends Kohana_Database_MySQLi_Result {}
|
@ -9,7 +9,7 @@
|
|||||||
* @copyright (c) 2012 Kohana Team
|
* @copyright (c) 2012 Kohana Team
|
||||||
* @license http://kohanaframework.org/license
|
* @license http://kohanaframework.org/license
|
||||||
*/
|
*/
|
||||||
class Kohana_Config_Database extends Kohana_Config_Database_Writer
|
class Kohana_Config_Database extends Config_Database_Writer
|
||||||
{
|
{
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -3,6 +3,15 @@
|
|||||||
/**
|
/**
|
||||||
* Database writer for the config system
|
* 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
|
* @package Kohana
|
||||||
* @category Configuration
|
* @category Configuration
|
||||||
* @author Kohana Team
|
* @author Kohana Team
|
||||||
|
@ -51,6 +51,9 @@ class Kohana_Database_MySQL_Result extends Database_Result {
|
|||||||
// Increment internal row for optimization assuming rows are fetched in order
|
// Increment internal row for optimization assuming rows are fetched in order
|
||||||
$this->_internal_row++;
|
$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)
|
if ($this->_as_object === TRUE)
|
||||||
{
|
{
|
||||||
// Return an stdClass
|
// Return an stdClass
|
||||||
@ -58,8 +61,32 @@ class Kohana_Database_MySQL_Result extends Database_Result {
|
|||||||
}
|
}
|
||||||
elseif (is_string($this->_as_object))
|
elseif (is_string($this->_as_object))
|
||||||
{
|
{
|
||||||
// Return an object of given class name
|
/* The second and third argument for mysql_fetch_object are optional, but do
|
||||||
return mysql_fetch_object($this->_result, $this->_as_object, $this->_object_params);
|
* 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
|
else
|
||||||
{
|
{
|
||||||
|
422
modules/database/classes/Kohana/Database/MySQLi.php
Normal file
422
modules/database/classes/Kohana/Database/MySQLi.php
Normal 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
|
71
modules/database/classes/Kohana/Database/MySQLi/Result.php
Normal file
71
modules/database/classes/Kohana/Database/MySQLi/Result.php
Normal 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
|
@ -60,6 +60,12 @@ class Kohana_Database_PDO extends Database {
|
|||||||
array(':error' => $e->getMessage()),
|
array(':error' => $e->getMessage()),
|
||||||
$e->getCode());
|
$e->getCode());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ( ! empty($this->_config['charset']))
|
||||||
|
{
|
||||||
|
// Set the character set
|
||||||
|
$this->set_charset($this->_config['charset']);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -80,7 +80,7 @@ abstract class Kohana_Database_Query_Builder extends Database_Query {
|
|||||||
// Convert "val = NULL" to "val IS NULL"
|
// Convert "val = NULL" to "val IS NULL"
|
||||||
$op = 'IS';
|
$op = 'IS';
|
||||||
}
|
}
|
||||||
elseif ($op === '!=')
|
elseif ($op === '!=' OR $op === '<>')
|
||||||
{
|
{
|
||||||
// Convert "val != NULL" to "valu IS NOT NULL"
|
// Convert "val != NULL" to "valu IS NOT NULL"
|
||||||
$op = 'IS NOT';
|
$op = 'IS NOT';
|
||||||
|
@ -31,7 +31,7 @@ class Kohana_Database_Query_Builder_Insert extends Database_Query_Builder {
|
|||||||
if ($table)
|
if ($table)
|
||||||
{
|
{
|
||||||
// Set the inital table name
|
// Set the inital table name
|
||||||
$this->_table = $table;
|
$this->table($table);
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($columns)
|
if ($columns)
|
||||||
@ -47,11 +47,14 @@ class Kohana_Database_Query_Builder_Insert extends Database_Query_Builder {
|
|||||||
/**
|
/**
|
||||||
* Sets the table to insert into.
|
* Sets the table to insert into.
|
||||||
*
|
*
|
||||||
* @param mixed $table table name or array($table, $alias) or object
|
* @param string $table table name
|
||||||
* @return $this
|
* @return $this
|
||||||
*/
|
*/
|
||||||
public function table($table)
|
public function table($table)
|
||||||
{
|
{
|
||||||
|
if ( ! is_string($table))
|
||||||
|
throw new Kohana_Exception('INSERT INTO syntax does not allow table aliasing');
|
||||||
|
|
||||||
$this->_table = $table;
|
$this->_table = $table;
|
||||||
|
|
||||||
return $this;
|
return $this;
|
||||||
@ -86,8 +89,11 @@ class Kohana_Database_Query_Builder_Insert extends Database_Query_Builder {
|
|||||||
|
|
||||||
// Get all of the passed values
|
// Get all of the passed values
|
||||||
$values = func_get_args();
|
$values = func_get_args();
|
||||||
|
|
||||||
$this->_values = array_merge($this->_values, $values);
|
foreach ($values as $value)
|
||||||
|
{
|
||||||
|
$this->_values[] = $value;
|
||||||
|
}
|
||||||
|
|
||||||
return $this;
|
return $this;
|
||||||
}
|
}
|
||||||
|
@ -309,7 +309,7 @@ class Kohana_Database_Query_Builder_Select extends Database_Query_Builder_Where
|
|||||||
*/
|
*/
|
||||||
public function offset($number)
|
public function offset($number)
|
||||||
{
|
{
|
||||||
$this->_offset = $number;
|
$this->_offset = ($number === NULL) ? NULL : (int) $number;
|
||||||
|
|
||||||
return $this;
|
return $this;
|
||||||
}
|
}
|
||||||
@ -404,13 +404,14 @@ class Kohana_Database_Query_Builder_Select extends Database_Query_Builder_Where
|
|||||||
|
|
||||||
if ( ! empty($this->_union))
|
if ( ! empty($this->_union))
|
||||||
{
|
{
|
||||||
|
$query = '('.$query.')';
|
||||||
foreach ($this->_union as $u) {
|
foreach ($this->_union as $u) {
|
||||||
$query .= ' UNION ';
|
$query .= ' UNION ';
|
||||||
if ($u['all'] === TRUE)
|
if ($u['all'] === TRUE)
|
||||||
{
|
{
|
||||||
$query .= 'ALL ';
|
$query .= 'ALL ';
|
||||||
}
|
}
|
||||||
$query .= $u['select']->compile($db);
|
$query .= '('.$u['select']->compile($db).')';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -172,7 +172,7 @@ abstract class Kohana_Database_Query_Builder_Where extends Database_Query_Builde
|
|||||||
*/
|
*/
|
||||||
public function limit($number)
|
public function limit($number)
|
||||||
{
|
{
|
||||||
$this->_limit = $number;
|
$this->_limit = ($number === NULL) ? NULL : (int) $number;
|
||||||
|
|
||||||
return $this;
|
return $this;
|
||||||
}
|
}
|
||||||
|
@ -204,6 +204,9 @@ class Kohana_Session_Database extends Session {
|
|||||||
// Execute the query
|
// Execute the query
|
||||||
$query->execute($this->_db);
|
$query->execute($this->_db);
|
||||||
|
|
||||||
|
// Delete the old session id
|
||||||
|
$this->_update_id = NULL;
|
||||||
|
|
||||||
// Delete the cookie
|
// Delete the cookie
|
||||||
Cookie::delete($this->_name);
|
Cookie::delete($this->_name);
|
||||||
}
|
}
|
||||||
|
@ -22,8 +22,13 @@
|
|||||||
"require": {
|
"require": {
|
||||||
"composer/installers": "~1.0",
|
"composer/installers": "~1.0",
|
||||||
"kohana/core": ">=3.3",
|
"kohana/core": ">=3.3",
|
||||||
"php": ">=5.3.3"
|
"php": ">=5.3.6"
|
||||||
},
|
},
|
||||||
|
"require-dev": {
|
||||||
|
"kohana/core": "3.3.*@dev",
|
||||||
|
"kohana/unittest": "3.3.*@dev",
|
||||||
|
"kohana/koharness": "*@dev"
|
||||||
|
},
|
||||||
"suggest": {
|
"suggest": {
|
||||||
"ext-mysql": "*",
|
"ext-mysql": "*",
|
||||||
"ext-pdo": "*"
|
"ext-pdo": "*"
|
||||||
@ -32,6 +37,9 @@
|
|||||||
"branch-alias": {
|
"branch-alias": {
|
||||||
"dev-3.3/develop": "3.3.x-dev",
|
"dev-3.3/develop": "3.3.x-dev",
|
||||||
"dev-3.4/develop": "3.4.x-dev"
|
"dev-3.4/develop": "3.4.x-dev"
|
||||||
}
|
},
|
||||||
|
"installer-paths": {
|
||||||
|
"vendor/{$vendor}/{$name}": ["type:kohana-module"]
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -53,4 +53,38 @@ return array
|
|||||||
'charset' => 'utf8',
|
'charset' => 'utf8',
|
||||||
'caching' => FALSE,
|
'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,
|
||||||
|
// ),
|
||||||
);
|
);
|
||||||
|
@ -10,6 +10,7 @@ The database configuration file contains an array of configuration groups. The s
|
|||||||
'table_prefix' => string TABLE_PREFIX,
|
'table_prefix' => string TABLE_PREFIX,
|
||||||
'charset' => string CHARACTER_SET,
|
'charset' => string CHARACTER_SET,
|
||||||
),
|
),
|
||||||
|
|
||||||
|
|
||||||
Understanding each of these settings is important.
|
Understanding each of these settings is important.
|
||||||
|
|
||||||
@ -17,7 +18,7 @@ INSTANCE_NAME
|
|||||||
: Connections can be named anything you want, but you should always have at least one connection called "default".
|
: Connections can be named anything you want, but you should always have at least one connection called "default".
|
||||||
|
|
||||||
DATABASE_TYPE
|
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
|
CONNECTION_ARRAY
|
||||||
: Specific driver options for connecting to your database. (Driver options are explained [below](#connection-settings).)
|
: Specific driver options for connecting to your database. (Driver options are explained [below](#connection-settings).)
|
||||||
@ -49,7 +50,7 @@ The example file below shows 2 MySQL connections, one local and one remote.
|
|||||||
(
|
(
|
||||||
'default' => array
|
'default' => array
|
||||||
(
|
(
|
||||||
'type' => 'mysql',
|
'type' => 'MySQL',
|
||||||
'connection' => array(
|
'connection' => array(
|
||||||
'hostname' => 'localhost',
|
'hostname' => 'localhost',
|
||||||
'username' => 'dbuser',
|
'username' => 'dbuser',
|
||||||
@ -61,7 +62,7 @@ The example file below shows 2 MySQL connections, one local and one remote.
|
|||||||
'charset' => 'utf8',
|
'charset' => 'utf8',
|
||||||
),
|
),
|
||||||
'remote' => array(
|
'remote' => array(
|
||||||
'type' => 'mysql',
|
'type' => 'MySQL',
|
||||||
'connection' => array(
|
'connection' => array(
|
||||||
'hostname' => '55.55.55.55',
|
'hostname' => '55.55.55.55',
|
||||||
'username' => 'remote_user',
|
'username' => 'remote_user',
|
||||||
@ -74,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
|
## 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.
|
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.
|
||||||
@ -114,6 +117,24 @@ Type | Option | Description | Default value
|
|||||||
`boolean` | persistent | Persistent connections | `FALSE`
|
`boolean` | persistent | Persistent connections | `FALSE`
|
||||||
`string` | database | Database name | `kohana`
|
`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
|
### PDO
|
||||||
|
|
||||||
A [PDO database](http://php.net/manual/en/book.pdo.php) can accept these options in the `connection` array:
|
A [PDO database](http://php.net/manual/en/book.pdo.php) can accept these options in the `connection` array:
|
||||||
@ -128,4 +149,4 @@ Type | Option | Description | Default value
|
|||||||
|
|
||||||
The connection character set should be configured using the DSN string or `options` array.
|
The connection character set should be configured using the DSN string or `options` array.
|
||||||
|
|
||||||
[!!] If you are using PDO and are not sure what to use for the `dsn` option, review [PDO::__construct](http://php.net/pdo.construct).
|
[!!] If you are using PDO and are not sure what to use for the `dsn` option, review [PDO::__construct](http://php.net/pdo.construct).
|
||||||
|
@ -25,7 +25,7 @@ In this example, we loop through an array of whitelisted input fields and for ea
|
|||||||
|
|
||||||
//copy the query & execute it
|
//copy the query & execute it
|
||||||
$pagination_query = clone $query;
|
$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
|
//pass the total item count to Pagination
|
||||||
$config = Kohana::$config->load('pagination');
|
$config = Kohana::$config->load('pagination');
|
||||||
@ -49,4 +49,4 @@ In this example, we loop through an array of whitelisted input fields and for ea
|
|||||||
|
|
||||||
TODO: example goes here
|
TODO: example goes here
|
||||||
|
|
||||||
[!!] We could use more examples on this page.
|
[!!] We could use more examples on this page.
|
||||||
|
@ -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.
|
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:
|
This query would generate the following SQL:
|
||||||
|
|
||||||
@ -248,4 +248,4 @@ Once you are done building, you can execute the query using `execute()` and use
|
|||||||
|
|
||||||
To use a different database [config group](config) pass either the name or the config object to `execute()`.
|
To use a different database [config group](config) pass either the name or the config object to `execute()`.
|
||||||
|
|
||||||
$result = $query->execute('config_name')
|
$result = $query->execute('config_name')
|
||||||
|
8
modules/database/koharness.php
Normal file
8
modules/database/koharness.php
Normal 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
37
modules/image/.travis.yml
Normal 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
|
@ -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) |
|
@ -23,6 +23,7 @@ abstract class Kohana_Image {
|
|||||||
const VERTICAL = 0x12;
|
const VERTICAL = 0x12;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* @deprecated - provide an image.default_driver value in your configuration instead
|
||||||
* @var string default driver: GD, ImageMagick, etc
|
* @var string default driver: GD, ImageMagick, etc
|
||||||
*/
|
*/
|
||||||
public static $default_driver = 'GD';
|
public static $default_driver = 'GD';
|
||||||
@ -44,8 +45,9 @@ abstract class Kohana_Image {
|
|||||||
{
|
{
|
||||||
if ($driver === NULL)
|
if ($driver === NULL)
|
||||||
{
|
{
|
||||||
// Use the default driver
|
// Use the driver from configuration file or default one
|
||||||
$driver = Image::$default_driver;
|
$configured_driver = Kohana::$config->load('image.default_driver');
|
||||||
|
$driver = ($configured_driver) ? $configured_driver : Image::$default_driver;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set the class name
|
// Set the class name
|
||||||
|
@ -611,6 +611,7 @@ class Kohana_Image_GD extends Image {
|
|||||||
switch (strtolower($extension))
|
switch (strtolower($extension))
|
||||||
{
|
{
|
||||||
case 'jpg':
|
case 'jpg':
|
||||||
|
case 'jpe':
|
||||||
case 'jpeg':
|
case 'jpeg':
|
||||||
// Save a JPG file
|
// Save a JPG file
|
||||||
$save = 'imagejpeg';
|
$save = 'imagejpeg';
|
||||||
|
@ -314,6 +314,7 @@ class Kohana_Image_Imagick extends Image {
|
|||||||
switch ($format)
|
switch ($format)
|
||||||
{
|
{
|
||||||
case 'jpg':
|
case 'jpg':
|
||||||
|
case 'jpe':
|
||||||
case 'jpeg':
|
case 'jpeg':
|
||||||
$type = IMAGETYPE_JPEG;
|
$type = IMAGETYPE_JPEG;
|
||||||
break;
|
break;
|
||||||
|
@ -24,6 +24,11 @@
|
|||||||
"kohana/core": ">=3.3",
|
"kohana/core": ">=3.3",
|
||||||
"php": ">=5.3.3"
|
"php": ">=5.3.3"
|
||||||
},
|
},
|
||||||
|
"require-dev": {
|
||||||
|
"kohana/core": "3.3.*@dev",
|
||||||
|
"kohana/unittest": "3.3.*@dev",
|
||||||
|
"kohana/koharness": "*@dev"
|
||||||
|
},
|
||||||
"suggest": {
|
"suggest": {
|
||||||
"ext-gd": "*"
|
"ext-gd": "*"
|
||||||
},
|
},
|
||||||
@ -31,6 +36,9 @@
|
|||||||
"branch-alias": {
|
"branch-alias": {
|
||||||
"dev-3.3/develop": "3.3.x-dev",
|
"dev-3.3/develop": "3.3.x-dev",
|
||||||
"dev-3.4/develop": "3.4.x-dev"
|
"dev-3.4/develop": "3.4.x-dev"
|
||||||
}
|
},
|
||||||
|
"installer-paths": {
|
||||||
|
"vendor/{$vendor}/{$name}": ["type:kohana-module"]
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
8
modules/image/config/image.php
Normal file
8
modules/image/config/image.php
Normal 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,
|
||||||
|
);
|
@ -4,7 +4,24 @@ Kohana 3.x provides a simple yet powerful image manipulation module. The [Image]
|
|||||||
|
|
||||||
## Drivers
|
## 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
|
## Getting Started
|
||||||
|
|
||||||
@ -18,4 +35,4 @@ Kohana::modules(array(
|
|||||||
));
|
));
|
||||||
~~~
|
~~~
|
||||||
|
|
||||||
Next: [Using the image module](using).
|
Next: [Using the image module](using).
|
||||||
|
8
modules/image/koharness.php
Normal file
8
modules/image/koharness.php
Normal 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'
|
||||||
|
),
|
||||||
|
);
|
37
modules/minion/.travis.yml
Normal file
37
modules/minion/.travis.yml
Normal 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
|
@ -1,5 +1,10 @@
|
|||||||
# Minion
|
# 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.
|
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.
|
The system is inspired by ruckusing, which had a nice system for defining tasks but lacked the desired flexibility for kohana integration.
|
||||||
|
@ -170,7 +170,7 @@ class Kohana_Minion_CLI {
|
|||||||
// Create temporary file
|
// Create temporary file
|
||||||
file_put_contents($vbscript, 'wscript.echo(InputBox("'.addslashes($text).'"))');
|
file_put_contents($vbscript, 'wscript.echo(InputBox("'.addslashes($text).'"))');
|
||||||
|
|
||||||
$password = shell_exec('cscript //nologo '.escapeshellarg($text));
|
$password = shell_exec('cscript //nologo '.escapeshellarg($vbscript));
|
||||||
|
|
||||||
// Remove temporary file.
|
// Remove temporary file.
|
||||||
unlink($vbscript);
|
unlink($vbscript);
|
||||||
@ -278,7 +278,7 @@ class Kohana_Minion_CLI {
|
|||||||
* @copyright 2010 - 2011 Fuel Development Team
|
* @copyright 2010 - 2011 Fuel Development Team
|
||||||
* @link http://fuelphp.com
|
* @link http://fuelphp.com
|
||||||
* @param string $text the text to color
|
* @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
|
* @param string $background the background color
|
||||||
* @return string the color coded string
|
* @return string the color coded string
|
||||||
*/
|
*/
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
<?php defined('SYSPATH') or die('No direct script access.');
|
<?php defined('SYSPATH') or die('No direct script access.');
|
||||||
/**
|
/**
|
||||||
* Minipn exception
|
* Minion exception
|
||||||
*
|
*
|
||||||
* @package Kohana
|
* @package Kohana
|
||||||
* @category Minion
|
* @category Minion
|
||||||
@ -15,8 +15,6 @@ class Kohana_Minion_Exception extends Kohana_Exception {
|
|||||||
*
|
*
|
||||||
* Should this display a stack trace? It's useful.
|
* 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
|
* @uses Kohana_Exception::text
|
||||||
* @param Exception $e
|
* @param Exception $e
|
||||||
* @return boolean
|
* @return boolean
|
||||||
@ -25,6 +23,9 @@ class Kohana_Minion_Exception extends Kohana_Exception {
|
|||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
// Log the exception
|
||||||
|
Kohana_Exception::log($e);
|
||||||
|
|
||||||
if ($e instanceof Minion_Exception)
|
if ($e instanceof Minion_Exception)
|
||||||
{
|
{
|
||||||
echo $e->format_for_cli();
|
echo $e->format_for_cli();
|
||||||
|
@ -24,10 +24,18 @@
|
|||||||
"kohana/core": ">=3.3",
|
"kohana/core": ">=3.3",
|
||||||
"php": ">=5.3.3"
|
"php": ">=5.3.3"
|
||||||
},
|
},
|
||||||
|
"require-dev": {
|
||||||
|
"kohana/core": "3.3.*@dev",
|
||||||
|
"kohana/unittest": "3.3.*@dev",
|
||||||
|
"kohana/koharness": "*@dev"
|
||||||
|
},
|
||||||
"extra": {
|
"extra": {
|
||||||
"branch-alias": {
|
"branch-alias": {
|
||||||
"dev-3.3/develop": "3.3.x-dev",
|
"dev-3.3/develop": "3.3.x-dev",
|
||||||
"dev-3.4/develop": "3.4.x-dev"
|
"dev-3.4/develop": "3.4.x-dev"
|
||||||
}
|
},
|
||||||
|
"installer-paths": {
|
||||||
|
"vendor/{$vendor}/{$name}": ["type:kohana-module"]
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
8
modules/minion/koharness.php
Normal file
8
modules/minion/koharness.php
Normal 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'
|
||||||
|
),
|
||||||
|
);
|
@ -1,70 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Test case for Minion_Util
|
|
||||||
*
|
|
||||||
* @package Kohana/Minion
|
|
||||||
* @group kohana
|
|
||||||
* @group kohana.minion
|
|
||||||
* @category Test
|
|
||||||
* @author Kohana Team
|
|
||||||
* @copyright (c) 2009-2012 Kohana Team
|
|
||||||
* @license http://kohanaframework.org/license
|
|
||||||
*/
|
|
||||||
|
|
||||||
class Minion_TaskTest extends Kohana_Unittest_TestCase
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
* Provides test data for test_convert_task_to_class_name()
|
|
||||||
*
|
|
||||||
* @return array
|
|
||||||
*/
|
|
||||||
public function provider_convert_task_to_class_name()
|
|
||||||
{
|
|
||||||
return array(
|
|
||||||
array('Task_Db_Migrate', 'db:migrate'),
|
|
||||||
array('Task_Db_Status', 'db:status'),
|
|
||||||
array('', ''),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Tests that a task can be converted to a class name
|
|
||||||
*
|
|
||||||
* @test
|
|
||||||
* @covers Minion_Task::convert_task_to_class_name
|
|
||||||
* @dataProvider provider_convert_task_to_class_name
|
|
||||||
* @param string Expected class name
|
|
||||||
* @param string Input task name
|
|
||||||
*/
|
|
||||||
public function test_convert_task_to_class_name($expected, $task_name)
|
|
||||||
{
|
|
||||||
$this->assertSame($expected, Minion_Task::convert_task_to_class_name($task_name));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Provides test data for test_convert_class_to_task()
|
|
||||||
*
|
|
||||||
* @return array
|
|
||||||
*/
|
|
||||||
public function provider_convert_class_to_task()
|
|
||||||
{
|
|
||||||
return array(
|
|
||||||
array('db:migrate', 'Task_Db_Migrate'),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Tests that the task name can be found from a class name / object
|
|
||||||
*
|
|
||||||
* @test
|
|
||||||
* @covers Minion_Task::convert_class_to_task
|
|
||||||
* @dataProvider provider_convert_class_to_task
|
|
||||||
* @param string Expected task name
|
|
||||||
* @param mixed Input class
|
|
||||||
*/
|
|
||||||
public function test_convert_class_to_task($expected, $class)
|
|
||||||
{
|
|
||||||
$this->assertSame($expected, Minion_Task::convert_class_to_task($class));
|
|
||||||
}
|
|
||||||
}
|
|
37
modules/orm/.travis.yml
Normal file
37
modules/orm/.travis.yml
Normal 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
6
modules/orm/README.md
Normal 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) |
|
@ -1627,7 +1627,7 @@ class Kohana_ORM extends Model implements serializable {
|
|||||||
if ($method['name'] == 'select')
|
if ($method['name'] == 'select')
|
||||||
{
|
{
|
||||||
// Ignore any selected columns for now
|
// Ignore any selected columns for now
|
||||||
$selects[] = $method;
|
$selects[$key] = $method;
|
||||||
unset($this->_db_pending[$key]);
|
unset($this->_db_pending[$key]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -25,10 +25,19 @@
|
|||||||
"kohana/database": ">=3.3",
|
"kohana/database": ">=3.3",
|
||||||
"php": ">=5.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": {
|
"extra": {
|
||||||
"branch-alias": {
|
"branch-alias": {
|
||||||
"dev-3.3/develop": "3.3.x-dev",
|
"dev-3.3/develop": "3.3.x-dev",
|
||||||
"dev-3.4/develop": "3.4.x-dev"
|
"dev-3.4/develop": "3.4.x-dev"
|
||||||
}
|
},
|
||||||
|
"installer-paths": {
|
||||||
|
"vendor/{$vendor}/{$name}": ["type:kohana-module"]
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
8
modules/orm/koharness.php
Normal file
8
modules/orm/koharness.php
Normal 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'
|
||||||
|
),
|
||||||
|
);
|
37
modules/unittest/.travis.yml
Normal file
37
modules/unittest/.travis.yml
Normal 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
|
@ -1,13 +1,29 @@
|
|||||||
# Kohana-PHPUnit integration
|
# 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.
|
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.
|
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
|
## Usage
|
||||||
|
|
||||||
|
@ -121,5 +121,10 @@ if (($ob_len = ob_get_length()) !== FALSE)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Enable the unittest module
|
// Enable the unittest module if it is not already loaded - use the absolute path
|
||||||
Kohana::modules(Kohana::modules() + array('unittest' => MODPATH.'unittest'));
|
$modules = Kohana::modules();
|
||||||
|
$unittest_path = realpath(__DIR__).DIRECTORY_SEPARATOR;
|
||||||
|
if ( ! in_array($unittest_path, $modules)) {
|
||||||
|
$modules['unittest'] = $unittest_path;
|
||||||
|
Kohana::modules($modules);
|
||||||
|
}
|
||||||
|
@ -9,7 +9,7 @@ $modules = array();
|
|||||||
|
|
||||||
foreach ($modules_iterator as $module)
|
foreach ($modules_iterator as $module)
|
||||||
{
|
{
|
||||||
if ($module->isDir())
|
if ($module->isDir() AND ! $module->isDot())
|
||||||
{
|
{
|
||||||
$modules[$module->getFilename()] = MODPATH.$module->getFilename();
|
$modules[$module->getFilename()] = MODPATH.$module->getFilename();
|
||||||
}
|
}
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
<?php
|
<?php defined('SYSPATH') or die('No direct script access.');
|
||||||
/**
|
/**
|
||||||
* TestCase for testing a database
|
* TestCase for testing a database
|
||||||
*
|
*
|
||||||
@ -10,11 +10,6 @@
|
|||||||
*/
|
*/
|
||||||
abstract class Kohana_Unittest_Database_TestCase extends PHPUnit_Extensions_Database_TestCase {
|
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
|
* Make sure PHPUnit backs up globals
|
||||||
@ -49,16 +44,6 @@ abstract class Kohana_Unittest_Database_TestCase extends PHPUnit_Extensions_Data
|
|||||||
*/
|
*/
|
||||||
public function setUp()
|
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->_helpers = new Kohana_Unittest_Helpers;
|
||||||
|
|
||||||
$this->setEnvironment($this->environmentDefault);
|
$this->setEnvironment($this->environmentDefault);
|
||||||
@ -161,151 +146,4 @@ abstract class Kohana_Unittest_Database_TestCase extends PHPUnit_Extensions_Data
|
|||||||
return Kohana_Unittest_Helpers::has_internet();
|
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);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
<?php
|
<?php defined('SYSPATH') or die('No direct script access.');
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Unit testing helpers
|
* Unit testing helpers
|
||||||
|
@ -6,12 +6,6 @@
|
|||||||
*/
|
*/
|
||||||
abstract class Kohana_Unittest_TestCase extends PHPUnit_Framework_TestCase {
|
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
|
* Make sure PHPUnit backs up globals
|
||||||
* @var boolean
|
* @var boolean
|
||||||
@ -39,16 +33,6 @@ abstract class Kohana_Unittest_TestCase extends PHPUnit_Framework_TestCase {
|
|||||||
*/
|
*/
|
||||||
public function setUp()
|
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->_helpers = new Unittest_Helpers;
|
||||||
|
|
||||||
$this->setEnvironment($this->environmentDefault);
|
$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
|
* NOTE:
|
||||||
* @param mixed $actual
|
* Overriding this method to remove the deprecation error
|
||||||
* @param string $message
|
* when tested with PHPUnit 4.2.0+
|
||||||
* @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
|
* TODO:
|
||||||
* @param string $attributeName
|
* this should be removed when phpunit-dom-assertions gets released
|
||||||
* @param mixed $classOrObject
|
* https://github.com/phpunit/phpunit-dom-assertions
|
||||||
|
*
|
||||||
|
* @param array $matcher
|
||||||
|
* @param string $actual
|
||||||
* @param string $message
|
* @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 assertTag($matcher, $actual, $message = '', $isHtml = true)
|
||||||
{
|
{
|
||||||
if(self::$_assert_type_compatability)
|
//trigger_error(__METHOD__ . ' is deprecated', E_USER_DEPRECATED);
|
||||||
{
|
|
||||||
return self::assertAttributeType($expected, $attributeName, $classOrObject, $message);
|
|
||||||
}
|
|
||||||
|
|
||||||
return parent::assertAttributeInstanceOf($expected, $attributeName, $classOrObject, $message);
|
$matched = static::tag_match($matcher, $actual, $message, $isHtml);
|
||||||
|
static::assertTrue($matched, $message);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Asserts that a variable is not of a given type.
|
* This assertion is the exact opposite of assertTag
|
||||||
*
|
*
|
||||||
* @param string $expected
|
* Rather than asserting that $matcher results in a match, it asserts that
|
||||||
* @param mixed $actual
|
* $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
|
* @param string $message
|
||||||
* @since Method available since Release 3.5.0
|
* @param bool $isHtml
|
||||||
|
* @uses Unittest_TestCase::tag_match
|
||||||
*/
|
*/
|
||||||
public static function assertNotInstanceOf($expected, $actual, $message = '')
|
public static function assertNotTag($matcher, $actual, $message = '', $isHtml = true)
|
||||||
{
|
{
|
||||||
if(self::$_assert_type_compatability)
|
//trigger_error(__METHOD__ . ' is deprecated', E_USER_DEPRECATED);
|
||||||
{
|
|
||||||
return self::assertNotType($expected, $actual, $message);
|
|
||||||
}
|
|
||||||
|
|
||||||
return parent::assertNotInstanceOf($expected, $actual, $message);
|
$matched = static::tag_match($matcher, $actual, $message, $isHtml);
|
||||||
|
static::assertFalse($matched, $message);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Asserts that an attribute is of a given type.
|
* Helper function to match HTML string tags against certain criteria
|
||||||
*
|
*
|
||||||
* @param string $expected
|
* TODO:
|
||||||
* @param string $attributeName
|
* this should be removed when phpunit-dom-assertions gets released
|
||||||
* @param mixed $classOrObject
|
* https://github.com/phpunit/phpunit-dom-assertions
|
||||||
* @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 parent::assertAttributeNotInstanceOf($expected, $attributeName, $classOrObject, $message);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Asserts that a variable is of a given type.
|
|
||||||
*
|
*
|
||||||
* @param string $expected
|
* @param array $matcher
|
||||||
* @param mixed $actual
|
* @param string $actual
|
||||||
* @param string $message
|
* @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 assertInternalType($expected, $actual, $message = '')
|
protected static function tag_match($matcher, $actual, $message = '', $isHtml = true)
|
||||||
{
|
{
|
||||||
if(self::$_assert_type_compatability)
|
$dom = PHPUnit_Util_XML::load($actual, $isHtml);
|
||||||
{
|
$tags = PHPUnit_Util_XML::findNodes($dom, $matcher, $isHtml);
|
||||||
return self::assertType($expected, $actual, $message);
|
return count($tags) > 0 && $tags[0] instanceof DOMNode;
|
||||||
}
|
|
||||||
|
|
||||||
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 parent::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 parent::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 parent::assertAttributeNotInternalType($expected, $attributeName, $classOrObject, $message);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
<?php
|
<?php defined('SYSPATH') or die('No direct script access.');
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Transparent extension for Kohana_Unittest_Database_TestCase
|
* Transparent extension for Kohana_Unittest_Database_TestCase
|
||||||
|
@ -23,12 +23,19 @@
|
|||||||
"composer/installers": "~1.0",
|
"composer/installers": "~1.0",
|
||||||
"kohana/core": ">=3.3",
|
"kohana/core": ">=3.3",
|
||||||
"php": ">=5.3.3",
|
"php": ">=5.3.3",
|
||||||
"phpunit/phpunit": "3.7.*"
|
"phpunit/phpunit": "3.7.24 - 4"
|
||||||
},
|
},
|
||||||
|
"require-dev": {
|
||||||
|
"kohana/core": "3.3.*@dev",
|
||||||
|
"kohana/koharness": "*@dev"
|
||||||
|
},
|
||||||
"extra": {
|
"extra": {
|
||||||
"branch-alias": {
|
"branch-alias": {
|
||||||
"dev-3.3/develop": "3.3.x-dev",
|
"dev-3.3/develop": "3.3.x-dev",
|
||||||
"dev-3.4/develop": "3.4.x-dev"
|
"dev-3.4/develop": "3.4.x-dev"
|
||||||
}
|
},
|
||||||
|
"installer-paths": {
|
||||||
|
"vendor/{$vendor}/{$name}": ["type:kohana-module"]
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
7
modules/unittest/koharness.php
Normal file
7
modules/unittest/koharness.php
Normal 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__
|
||||||
|
),
|
||||||
|
);
|
37
modules/userguide/.travis.yml
Normal file
37
modules/userguide/.travis.yml
Normal 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
|
@ -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?
|
## 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.
|
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.
|
||||||
@ -66,4 +73,4 @@ If you want to have parameters, only put the brackets around the class and funct
|
|||||||
|
|
||||||
You may include a view by putting the name of the view in double curly brackets. **If the view is not found, no exception or error will be shown!** The curly brackets and view will simply be shown an the page as is.
|
You may include a view by putting the name of the view in double curly brackets. **If the view is not found, no exception or error will be shown!** The curly brackets and view will simply be shown an the page as is.
|
||||||
|
|
||||||
{{some/view}}
|
{{some/view}}
|
||||||
|
@ -3,8 +3,10 @@
|
|||||||
* Kohana user guide and api browser.
|
* Kohana user guide and api browser.
|
||||||
*
|
*
|
||||||
* @package Kohana/Userguide
|
* @package Kohana/Userguide
|
||||||
* @category Controllers
|
* @category Controller
|
||||||
* @author Kohana Team
|
* @author Kohana Team
|
||||||
|
* @copyright (c) 2008-2013 Kohana Team
|
||||||
|
* @license http://kohanaframework.org/license
|
||||||
*/
|
*/
|
||||||
abstract class Kohana_Controller_Userguide extends Controller_Template {
|
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
|
// 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();
|
$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
|
// Prevent "guide/module" and "guide/module/index" from having duplicate content
|
||||||
if ( $page == 'index')
|
if ($page == 'index')
|
||||||
{
|
{
|
||||||
return $this->error('Userguide page not found');
|
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 a module is set, but no page was provided in the url, show the index page
|
||||||
if ( ! $page )
|
if ( ! $page)
|
||||||
{
|
{
|
||||||
$page = 'index';
|
$page = 'index';
|
||||||
}
|
}
|
||||||
@ -141,12 +143,14 @@ abstract class Kohana_Controller_Userguide extends Controller_Template {
|
|||||||
Kodoc_Markdown::$image_url = URL::site($this->media->uri()).'/'.$module.'/';
|
Kodoc_Markdown::$image_url = URL::site($this->media->uri()).'/'.$module.'/';
|
||||||
|
|
||||||
// Set the page title
|
// 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
|
// 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));
|
$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
|
// Attach this module's menu to the template
|
||||||
$this->template->menu = Kodoc_Markdown::markdown($this->_get_all_menu_markdown());
|
$this->template->menu = Kodoc_Markdown::markdown($this->_get_all_menu_markdown());
|
||||||
@ -358,11 +362,7 @@ abstract class Kohana_Controller_Userguide extends Controller_Template {
|
|||||||
if ($file AND $text = file_get_contents($file))
|
if ($file AND $text = file_get_contents($file))
|
||||||
{
|
{
|
||||||
// Add spans around non-link categories. This is a terrible hack.
|
// 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);
|
$text = preg_replace('/^(\s*[\-\*\+]\s*)([^\[\]]+)$/m','$1<span>$2</span>',$text);
|
||||||
//echo Debug::vars($text);
|
|
||||||
$markdown .= $text;
|
$markdown .= $text;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -5,8 +5,8 @@
|
|||||||
* @package Kohana/Userguide
|
* @package Kohana/Userguide
|
||||||
* @category Base
|
* @category Base
|
||||||
* @author Kohana Team
|
* @author Kohana Team
|
||||||
* @copyright (c) 2008-2012 Kohana Team
|
* @copyright (c) 2008-2013 Kohana Team
|
||||||
* @license http://kohanaphp.com/license
|
* @license http://kohanaframework.org/license
|
||||||
*/
|
*/
|
||||||
class Kohana_Kodoc {
|
class Kohana_Kodoc {
|
||||||
|
|
||||||
@ -34,6 +34,10 @@ class Kohana_Kodoc {
|
|||||||
{
|
{
|
||||||
$member = '#property:'.substr($matches[3], 1);
|
$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
|
else
|
||||||
{
|
{
|
||||||
$member = '#'.$matches[3];
|
$member = '#'.$matches[3];
|
||||||
@ -275,7 +279,7 @@ class Kohana_Kodoc {
|
|||||||
* @param string $text Content of the tag
|
* @param string $text Content of the tag
|
||||||
* @return void
|
* @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
|
// Don't show @access lines, they are shown elsewhere
|
||||||
if ($tag !== 'access')
|
if ($tag !== 'access')
|
||||||
@ -290,7 +294,7 @@ class Kohana_Kodoc {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
$comment = $tag = null;
|
$comment = $tag = NULL;
|
||||||
$end = count($lines[1]) - 1;
|
$end = count($lines[1]) - 1;
|
||||||
|
|
||||||
foreach ($lines[1] as $i => $line)
|
foreach ($lines[1] as $i => $line)
|
||||||
@ -415,12 +419,12 @@ class Kohana_Kodoc {
|
|||||||
*
|
*
|
||||||
* Module developers can therefore add their own transparent extension
|
* Module developers can therefore add their own transparent extension
|
||||||
* namespaces and exclude them from the userguide.
|
* namespaces and exclude them from the userguide.
|
||||||
*
|
*
|
||||||
* @param string $class The name of the class to check for transparency
|
* @param string $class The name of the class to check for transparency
|
||||||
* @param array $classes An optional list of all defined classes
|
* @param array $classes An optional list of all defined classes
|
||||||
* @return false If this is not a transparent extension class
|
* @return false If this is not a transparent extension class
|
||||||
* @return string The name of the class that extends this (in the case provided)
|
* @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
|
* @throws InvalidArgumentException If the $classes array is provided and the $class variable is not lowercase
|
||||||
*/
|
*/
|
||||||
public static function is_transparent($class, $classes = NULL)
|
public static function is_transparent($class, $classes = NULL)
|
||||||
{
|
{
|
||||||
@ -447,11 +451,11 @@ class Kohana_Kodoc {
|
|||||||
// Cater for Foo extends Module_Foo naming
|
// Cater for Foo extends Module_Foo naming
|
||||||
$child_class = $segments[1];
|
$child_class = $segments[1];
|
||||||
}
|
}
|
||||||
|
|
||||||
// It is only a transparent class if the unprefixed class also exists
|
// It is only a transparent class if the unprefixed class also exists
|
||||||
if ($classes AND ! isset($classes[$child_class]))
|
if ($classes AND ! isset($classes[$child_class]))
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
|
||||||
// Return the name of the child class
|
// Return the name of the child class
|
||||||
return $child_class;
|
return $child_class;
|
||||||
}
|
}
|
||||||
@ -462,5 +466,4 @@ class Kohana_Kodoc {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
} // End Kodoc
|
} // End Kodoc
|
||||||
|
@ -5,8 +5,8 @@
|
|||||||
* @package Kohana/Userguide
|
* @package Kohana/Userguide
|
||||||
* @category Base
|
* @category Base
|
||||||
* @author Kohana Team
|
* @author Kohana Team
|
||||||
* @copyright (c) 2009-2012 Kohana Team
|
* @copyright (c) 2008-2013 Kohana Team
|
||||||
* @license http://kohanaphp.com/license
|
* @license http://kohanaframework.org/license
|
||||||
*/
|
*/
|
||||||
class Kohana_Kodoc_Class extends Kodoc {
|
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
|
* the class. Reads the class modifiers, constants and comment. Parses the
|
||||||
* comment to find the description and tags.
|
* comment to find the description and tags.
|
||||||
*
|
*
|
||||||
* @param string class name
|
* @param string Class name
|
||||||
* @return void
|
* @return void
|
||||||
*/
|
*/
|
||||||
public function __construct($class)
|
public function __construct($class)
|
||||||
@ -59,7 +59,7 @@ class Kohana_Kodoc_Class extends Kodoc {
|
|||||||
|
|
||||||
$this->constants = $this->class->getConstants();
|
$this->constants = $this->class->getConstants();
|
||||||
|
|
||||||
// If ReflectionClass::getParentClass() won't work if the class in
|
// If ReflectionClass::getParentClass() won't work if the class in
|
||||||
// question is an interface
|
// question is an interface
|
||||||
if ($this->class->isInterface())
|
if ($this->class->isInterface())
|
||||||
{
|
{
|
||||||
@ -154,7 +154,7 @@ class Kohana_Kodoc_Class extends Kodoc {
|
|||||||
|
|
||||||
return $props;
|
return $props;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected function _prop_sort($a, $b)
|
protected function _prop_sort($a, $b)
|
||||||
{
|
{
|
||||||
// If one property is public, and the other is not, it goes on top
|
// If one property is public, and the other is not, it goes on top
|
||||||
@ -162,13 +162,13 @@ class Kohana_Kodoc_Class extends Kodoc {
|
|||||||
return -1;
|
return -1;
|
||||||
if ($b->isPublic() AND ( ! $a->isPublic()))
|
if ($b->isPublic() AND ( ! $a->isPublic()))
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
// If one property is protected and the other is private, it goes on top
|
// If one property is protected and the other is private, it goes on top
|
||||||
if ($a->isProtected() AND $b->isPrivate())
|
if ($a->isProtected() AND $b->isPrivate())
|
||||||
return -1;
|
return -1;
|
||||||
if ($b->isProtected() AND $a->isPrivate())
|
if ($b->isProtected() AND $a->isPrivate())
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
// Otherwise just do alphabetical
|
// Otherwise just do alphabetical
|
||||||
return strcmp($a->name, $b->name);
|
return strcmp($a->name, $b->name);
|
||||||
}
|
}
|
||||||
@ -191,14 +191,15 @@ class Kohana_Kodoc_Class extends Kodoc {
|
|||||||
|
|
||||||
return $methods;
|
return $methods;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sort methods based on their visibility and declaring class based on:
|
* 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
|
* declared by the current class
|
||||||
* - lastly, they will be sorted alphabetically
|
* * lastly, they will be sorted alphabetically
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
protected function _method_sort($a, $b)
|
protected function _method_sort($a, $b)
|
||||||
{
|
{
|
||||||
@ -207,16 +208,16 @@ class Kohana_Kodoc_Class extends Kodoc {
|
|||||||
return -1;
|
return -1;
|
||||||
if ($b->isPublic() AND ( ! $a->isPublic()))
|
if ($b->isPublic() AND ( ! $a->isPublic()))
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
// If one method is protected and the other is private, it goes on top
|
// If one method is protected and the other is private, it goes on top
|
||||||
if ($a->isProtected() AND $b->isPrivate())
|
if ($a->isProtected() AND $b->isPrivate())
|
||||||
return -1;
|
return -1;
|
||||||
if ($b->isProtected() AND $a->isPrivate())
|
if ($b->isProtected() AND $a->isPrivate())
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
// The methods have the same visibility, so check the declaring class depth:
|
// The methods have the same visibility, so check the declaring class depth:
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
echo Debug::vars('a is '.$a->class.'::'.$a->name,'b is '.$b->class.'::'.$b->name,
|
echo Debug::vars('a is '.$a->class.'::'.$a->name,'b is '.$b->class.'::'.$b->name,
|
||||||
'are the classes the same?', $a->class == $b->class,'if they are, the result is:',strcmp($a->name, $b->name),
|
'are the classes the same?', $a->class == $b->class,'if they are, the result is:',strcmp($a->name, $b->name),
|
||||||
@ -276,4 +277,5 @@ class Kohana_Kodoc_Class extends Kodoc {
|
|||||||
|
|
||||||
return $result;
|
return $result;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
} // End Kodoc_Class
|
||||||
|
@ -5,8 +5,8 @@
|
|||||||
* @package Kohana/Userguide
|
* @package Kohana/Userguide
|
||||||
* @category Base
|
* @category Base
|
||||||
* @author Kohana Team
|
* @author Kohana Team
|
||||||
* @copyright (c) 2009-2012 Kohana Team
|
* @copyright (c) 2008-2013 Kohana Team
|
||||||
* @license http://kohanaphp.com/license
|
* @license http://kohanaframework.org/license
|
||||||
*/
|
*/
|
||||||
class Kohana_Kodoc_Markdown extends MarkdownExtra_Parser {
|
class Kohana_Kodoc_Markdown extends MarkdownExtra_Parser {
|
||||||
|
|
||||||
@ -21,9 +21,10 @@ class Kohana_Kodoc_Markdown extends MarkdownExtra_Parser {
|
|||||||
public static $image_url = '';
|
public static $image_url = '';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Currently defined heading ids.
|
* Currently defined heading ids.
|
||||||
* Used to prevent creating multiple headings with same id.
|
* Used to prevent creating multiple headings with same id.
|
||||||
* @var array
|
*
|
||||||
|
* @var array
|
||||||
*/
|
*/
|
||||||
protected $_heading_ids = 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
|
* 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.
|
* 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]
|
* Transform some text using [Kodoc_Markdown]
|
||||||
@ -78,8 +79,8 @@ class Kohana_Kodoc_Markdown extends MarkdownExtra_Parser {
|
|||||||
// Show table of contents for userguide pages
|
// Show table of contents for userguide pages
|
||||||
$this->document_gamut['doTOC'] = 100;
|
$this->document_gamut['doTOC'] = 100;
|
||||||
|
|
||||||
// PHP4 makes me sad.
|
// Call parent constructor.
|
||||||
parent::MarkdownExtra_Parser();
|
parent::__construct();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -88,25 +89,27 @@ class Kohana_Kodoc_Markdown extends MarkdownExtra_Parser {
|
|||||||
* Heading 1
|
* Heading 1
|
||||||
* =========
|
* =========
|
||||||
*
|
*
|
||||||
* @param array Matches from regex call
|
* @param array Matches from regex call
|
||||||
* @return string Generated html
|
* @return string Generated html
|
||||||
*/
|
*/
|
||||||
function _doHeaders_callback_setext($matches)
|
function _doHeaders_callback_setext($matches)
|
||||||
{
|
{
|
||||||
if ($matches[3] == '-' && preg_match('{^- }', $matches[1]))
|
if ($matches[3] == '-' AND preg_match('{^- }', $matches[1]))
|
||||||
return $matches[0];
|
return $matches[0];
|
||||||
$level = $matches[3]{0} == '=' ? 1 : 2;
|
$level = ($matches[3]{0} == '=') ? 1 : 2;
|
||||||
$attr = $this->_doHeaders_attr($id =& $matches[2]);
|
$attr = $this->_doHeaders_attr($id =& $matches[2]);
|
||||||
|
|
||||||
// Only auto-generate id if one doesn't exist
|
// Only auto-generate id if one doesn't exist
|
||||||
if(empty($attr))
|
if (empty($attr))
|
||||||
|
{
|
||||||
$attr = ' id="'.$this->make_heading_id($matches[1]).'"';
|
$attr = ' id="'.$this->make_heading_id($matches[1]).'"';
|
||||||
|
}
|
||||||
|
|
||||||
// Add this header to the page toc
|
// Add this header to the page toc
|
||||||
$this->_add_to_toc($level,$matches[1],$this->make_heading_id($matches[1]));
|
$this->_add_to_toc($level,$matches[1],$this->make_heading_id($matches[1]));
|
||||||
|
|
||||||
$block = "<h$level$attr>".$this->runSpanGamut($matches[1])."</h$level>";
|
$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,23 +117,25 @@ class Kohana_Kodoc_Markdown extends MarkdownExtra_Parser {
|
|||||||
*
|
*
|
||||||
* # Heading 1
|
* # Heading 1
|
||||||
*
|
*
|
||||||
* @param array Matches from regex call
|
* @param array Matches from regex call
|
||||||
* @return string Generated html
|
* @return string Generated html
|
||||||
*/
|
*/
|
||||||
function _doHeaders_callback_atx($matches)
|
function _doHeaders_callback_atx($matches)
|
||||||
{
|
{
|
||||||
$level = strlen($matches[1]);
|
$level = strlen($matches[1]);
|
||||||
$attr = $this->_doHeaders_attr($id =& $matches[3]);
|
$attr = $this->_doHeaders_attr($id =& $matches[3]);
|
||||||
|
|
||||||
// Only auto-generate id if one doesn't exist
|
// Only auto-generate id if one doesn't exist
|
||||||
if(empty($attr))
|
if (empty($attr))
|
||||||
|
{
|
||||||
$attr = ' id="'.$this->make_heading_id($matches[2]).'"';
|
$attr = ' id="'.$this->make_heading_id($matches[2]).'"';
|
||||||
|
}
|
||||||
|
|
||||||
// Add this header to the page toc
|
// 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]));
|
$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>";
|
$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
|
* Makes a heading id from the heading text
|
||||||
* If any heading share the same name then subsequent headings will have an integer appended
|
* If any heading share the same name then subsequent headings will have an integer appended
|
||||||
*
|
*
|
||||||
* @param string The heading text
|
* @param string The heading text
|
||||||
* @return string ID for the heading
|
* @return string ID for the heading
|
||||||
*/
|
*/
|
||||||
function make_heading_id($heading)
|
function make_heading_id($heading)
|
||||||
{
|
{
|
||||||
$id = url::title($heading, '-', TRUE);
|
$id = url::title($heading, '-', TRUE);
|
||||||
|
|
||||||
if(isset($this->_heading_ids[$id]))
|
if (isset($this->_heading_ids[$id]))
|
||||||
{
|
{
|
||||||
$id .= '-';
|
$id .= '-';
|
||||||
|
|
||||||
@ -155,8 +160,8 @@ class Kohana_Kodoc_Markdown extends MarkdownExtra_Parser {
|
|||||||
{
|
{
|
||||||
$id .= $count;
|
$id .= $count;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return $id;
|
return $id;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -166,8 +171,6 @@ class Kohana_Kodoc_Markdown extends MarkdownExtra_Parser {
|
|||||||
{
|
{
|
||||||
$replace = array();
|
$replace = array();
|
||||||
|
|
||||||
$replace = array();
|
|
||||||
|
|
||||||
foreach ($matches as $set)
|
foreach ($matches as $set)
|
||||||
{
|
{
|
||||||
list($search, $view) = $set;
|
list($search, $view) = $set;
|
||||||
@ -203,7 +206,7 @@ class Kohana_Kodoc_Markdown extends MarkdownExtra_Parser {
|
|||||||
*
|
*
|
||||||
* [filesystem](about.filesystem "Optional title")
|
* [filesystem](about.filesystem "Optional title")
|
||||||
*
|
*
|
||||||
* @param string span text
|
* @param string Span text
|
||||||
* @return string
|
* @return string
|
||||||
*/
|
*/
|
||||||
public function doBaseURL($text)
|
public function doBaseURL($text)
|
||||||
@ -217,7 +220,7 @@ class Kohana_Kodoc_Markdown extends MarkdownExtra_Parser {
|
|||||||
*
|
*
|
||||||
* ![Install Page](img/install.png "Optional title")
|
* ![Install Page](img/install.png "Optional title")
|
||||||
*
|
*
|
||||||
* @param string span text
|
* @param string Span text
|
||||||
* @return string
|
* @return string
|
||||||
*/
|
*/
|
||||||
public function doImageURL($text)
|
public function doImageURL($text)
|
||||||
@ -231,7 +234,7 @@ class Kohana_Kodoc_Markdown extends MarkdownExtra_Parser {
|
|||||||
*
|
*
|
||||||
* [Class_Name], [Class::method] or [Class::$property]
|
* [Class_Name], [Class::method] or [Class::$property]
|
||||||
*
|
*
|
||||||
* @param string span text
|
* @param string Span text
|
||||||
* @return string
|
* @return string
|
||||||
*/
|
*/
|
||||||
public function doAPI($text)
|
public function doAPI($text)
|
||||||
@ -244,7 +247,7 @@ class Kohana_Kodoc_Markdown extends MarkdownExtra_Parser {
|
|||||||
*
|
*
|
||||||
* [!!] Remember the milk!
|
* [!!] Remember the milk!
|
||||||
*
|
*
|
||||||
* @param string span text
|
* @param string Span text
|
||||||
* @return string
|
* @return string
|
||||||
*/
|
*/
|
||||||
public function doNotes($text)
|
public function doNotes($text)
|
||||||
@ -264,7 +267,7 @@ class Kohana_Kodoc_Markdown extends MarkdownExtra_Parser {
|
|||||||
'name' => $name,
|
'name' => $name,
|
||||||
'id' => $id);
|
'id' => $id);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function doTOC($text)
|
public function doTOC($text)
|
||||||
{
|
{
|
||||||
// Only add the toc do userguide pages, not api since they already have one
|
// Only add the toc do userguide pages, not api since they already have one
|
||||||
|
@ -5,28 +5,28 @@
|
|||||||
* @package Kohana/Userguide
|
* @package Kohana/Userguide
|
||||||
* @category Base
|
* @category Base
|
||||||
* @author Kohana Team
|
* @author Kohana Team
|
||||||
* @copyright (c) 2009 Kohana Team
|
* @copyright (c) 2008-2013 Kohana Team
|
||||||
* @license http://kohanaphp.com/license
|
* @license http://kohanaframework.org/license
|
||||||
*/
|
*/
|
||||||
class Kohana_Kodoc_Method extends Kodoc {
|
class Kohana_Kodoc_Method extends Kodoc {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @var ReflectionMethod The ReflectionMethod for this class
|
* @var ReflectionMethod The ReflectionMethod for this class
|
||||||
*/
|
*/
|
||||||
public $method;
|
public $method;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @var array array of Kodoc_Method_Param
|
* @var array Array of Kodoc_Method_Param
|
||||||
*/
|
*/
|
||||||
public $params;
|
public $params;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @var array the things this function can return
|
* @var array The things this function can return
|
||||||
*/
|
*/
|
||||||
public $return = array();
|
public $return = array();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @var string the source code for this function
|
* @var string The source code for this function
|
||||||
*/
|
*/
|
||||||
public $source;
|
public $source;
|
||||||
|
|
||||||
|
@ -5,8 +5,8 @@
|
|||||||
* @package Kohana/Userguide
|
* @package Kohana/Userguide
|
||||||
* @category Base
|
* @category Base
|
||||||
* @author Kohana Team
|
* @author Kohana Team
|
||||||
* @copyright (c) 2009 Kohana Team
|
* @copyright (c) 2008-2013 Kohana Team
|
||||||
* @license http://kohanaphp.com/license
|
* @license http://kohanaframework.org/license
|
||||||
*/
|
*/
|
||||||
class Kohana_Kodoc_Method_Param extends Kodoc {
|
class Kohana_Kodoc_Method_Param extends Kodoc {
|
||||||
|
|
||||||
|
@ -7,6 +7,8 @@
|
|||||||
* @package Kohana/Userguide
|
* @package Kohana/Userguide
|
||||||
* @category Undocumented
|
* @category Undocumented
|
||||||
* @author Kohana Team
|
* @author Kohana Team
|
||||||
|
* @copyright (c) 2008-2013 Kohana Team
|
||||||
|
* @license http://kohanaframework.org/license
|
||||||
* @since 3.0.7
|
* @since 3.0.7
|
||||||
*/
|
*/
|
||||||
abstract class Kohana_Kodoc_Missing {
|
abstract class Kohana_Kodoc_Missing {
|
||||||
|
@ -5,8 +5,8 @@
|
|||||||
* @package Kohana/Userguide
|
* @package Kohana/Userguide
|
||||||
* @category Base
|
* @category Base
|
||||||
* @author Kohana Team
|
* @author Kohana Team
|
||||||
* @copyright (c) 2009-2012 Kohana Team
|
* @copyright (c) 2008-2013 Kohana Team
|
||||||
* @license http://kohanaphp.com/license
|
* @license http://kohanaframework.org/license
|
||||||
*/
|
*/
|
||||||
class Kohana_Kodoc_Property extends Kodoc {
|
class Kohana_Kodoc_Property extends Kodoc {
|
||||||
|
|
||||||
|
@ -24,10 +24,18 @@
|
|||||||
"kohana/core": ">=3.3",
|
"kohana/core": ">=3.3",
|
||||||
"php": ">=5.3.3"
|
"php": ">=5.3.3"
|
||||||
},
|
},
|
||||||
|
"require-dev": {
|
||||||
|
"kohana/core": "3.3.*@dev",
|
||||||
|
"kohana/unittest": "3.3.*@dev",
|
||||||
|
"kohana/koharness": "*@dev"
|
||||||
|
},
|
||||||
"extra": {
|
"extra": {
|
||||||
"branch-alias": {
|
"branch-alias": {
|
||||||
"dev-3.3/develop": "3.3.x-dev",
|
"dev-3.3/develop": "3.3.x-dev",
|
||||||
"dev-3.4/develop": "3.4.x-dev"
|
"dev-3.4/develop": "3.4.x-dev"
|
||||||
}
|
},
|
||||||
|
"installer-paths": {
|
||||||
|
"vendor/{$vendor}/{$name}": ["type:kohana-module"]
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -20,16 +20,16 @@ return array
|
|||||||
|
|
||||||
// Whether this modules userguide pages should be shown
|
// Whether this modules userguide pages should be shown
|
||||||
'enabled' => TRUE,
|
'enabled' => TRUE,
|
||||||
|
|
||||||
// The name that should show up on the userguide index page
|
// The name that should show up on the userguide index page
|
||||||
'name' => 'Userguide',
|
'name' => 'Userguide',
|
||||||
|
|
||||||
// A short description of this module, shown on the index page
|
// A short description of this module, shown on the index page
|
||||||
'description' => 'Documentation viewer and api generation.',
|
'description' => 'Documentation viewer and api generation.',
|
||||||
|
|
||||||
// Copyright message, shown in the footer for this module
|
// Copyright message, shown in the footer for this module
|
||||||
'copyright' => '© 2008–2012 Kohana Team',
|
'copyright' => '© 2008–2014 Kohana Team',
|
||||||
)
|
)
|
||||||
),
|
),
|
||||||
|
|
||||||
// Set transparent class name segments
|
// Set transparent class name segments
|
||||||
|
@ -1,38 +1,42 @@
|
|||||||
# Adding your module to the userguide
|
# Adding your module
|
||||||
|
|
||||||
Making your module work with the userguide is simple.
|
Making your module work with the User Guide is simple.
|
||||||
|
|
||||||
First, copy this config and place in it `<module>/config/userguide.php`, replacing anything in `<>` with the appropriate things:
|
First, copy this config and place in it `<module>/config/userguide.php`, replacing anything in `<>` with the appropriate values:
|
||||||
|
|
||||||
return array
|
return array
|
||||||
(
|
(
|
||||||
// Leave this alone
|
// Leave this alone
|
||||||
'modules' => array(
|
'modules' => array(
|
||||||
|
|
||||||
// This should be the path to this modules userguide pages, without the 'guide/'. Ex: '/guide/modulename/' would be 'modulename'
|
/*
|
||||||
|
* The path to this module's userguide pages, without the 'guide/'.
|
||||||
|
*
|
||||||
|
* For example, '/guide/modulename/' would be 'modulename'
|
||||||
|
*/
|
||||||
'<modulename>' => array(
|
'<modulename>' => array(
|
||||||
|
|
||||||
// Whether this modules userguide pages should be shown
|
// Whether this module's user guide pages should be shown
|
||||||
'enabled' => TRUE,
|
'enabled' => TRUE,
|
||||||
|
|
||||||
// The name that should show up on the userguide index page
|
// The name that should show up on the user guide index page
|
||||||
'name' => '<Module Name>',
|
'name' => '<Module Name>',
|
||||||
|
|
||||||
// A short description of this module, shown on the index page
|
// A short description of this module, shown on the index page
|
||||||
'description' => '<Description goes here.>',
|
'description' => '<Description goes here>',
|
||||||
|
|
||||||
// Copyright message, shown in the footer for this module
|
// Copyright message, shown in the footer for this module
|
||||||
'copyright' => '© 2010–2011 <Your Name>',
|
'copyright' => '© 2012 <Your Name>',
|
||||||
)
|
)
|
||||||
),
|
),
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* If you use transparent extension outside the Kohana_ namespace,
|
* If you use transparent extensions outside the Kohana_ namespace,
|
||||||
* add your class prefix here. Both common Kohana naming conventions are
|
* add your class prefix here. Both common Kohana naming conventions are
|
||||||
* excluded:
|
* excluded:
|
||||||
* - Modulename extends Modulename_Core
|
* - Modulename extends Modulename_Core
|
||||||
* - Foo extends Modulename_Foo
|
* - Foo extends Modulename_Foo
|
||||||
*
|
*
|
||||||
* For example, if you use Modulename_<class_name> for your base classes
|
* For example, if you use Modulename_<class_name> for your base classes
|
||||||
* then you would define:
|
* then you would define:
|
||||||
*/
|
*/
|
||||||
@ -41,7 +45,11 @@ First, copy this config and place in it `<module>/config/userguide.php`, replaci
|
|||||||
)
|
)
|
||||||
);
|
);
|
||||||
|
|
||||||
Next, create a folder in your module directory called `guide/<modulename>` and create `index.md` and `menu.md`. All userguide pages use [Markdown](markdown). The index page is what is shown on the index of your module, the menu is what shows up in the side column. The menu should be formatted like this:
|
Next, create a folder in your module directory called `guide/<modulename>` and create `index.md` and `menu.md`. The contents of `index.md` is what is shown on the index page of your module.
|
||||||
|
|
||||||
|
## Creating the side menu
|
||||||
|
|
||||||
|
The contents of the `menu.md` file is what shows up in the side column and should be formatted like this:
|
||||||
|
|
||||||
## [Module Name]()
|
## [Module Name]()
|
||||||
- [Page name](page-path)
|
- [Page name](page-path)
|
||||||
@ -52,4 +60,16 @@ Next, create a folder in your module directory called `guide/<modulename>` and c
|
|||||||
- Categories do not have to be a link to a page
|
- Categories do not have to be a link to a page
|
||||||
- [Etcetera](etc)
|
- [Etcetera](etc)
|
||||||
|
|
||||||
Page paths are relative to `guide/<modulename>`. So `[Page name](path-path)` would look for `guide/<modulename>/page-name.md` and `[Another](category/another)` would look for `guide/<modulename>/page-name.md`. The guide pages can be named or arranged any way you want within that folder (with the exception of `menu.md` and `index.md`). The breadcrumbs and page titles are pulled from the `menu.md file`, not the file names or paths. You can have items that are not pages (a category that doesn't have a corresponding page). To link to the `index.md` page, you should have an empty link, e.g. `[Module Name]()`. Do not include `.md` in your links.
|
You can have items that are not linked pages (a category that doesn't have a corresponding page).
|
||||||
|
|
||||||
|
Guide pages can be named or arranged any way you want within that folder (with the exception of `index.md` and `menu.md` which must appear directly below the `guide/` folder).
|
||||||
|
|
||||||
|
## Formatting page titles and links
|
||||||
|
|
||||||
|
Page paths are relative to `guide/<modulename>`. So `[Page name](page-name)` would look for `guide/<modulename>/page-name.md` and `[Another](category/another)` would look for `guide/<modulename>/category/another.md`.
|
||||||
|
|
||||||
|
The breadcrumbs and page titles are pulled from the `menu.md` file, not the filenames or paths.
|
||||||
|
|
||||||
|
To link to the `index.md` page, you should have an empty link, e.g. `[Module Name]()`. Do not include `.md` in your links.
|
||||||
|
|
||||||
|
All user guide pages use [Markdown](markdown).
|
@ -1,7 +1,10 @@
|
|||||||
## [Userguide]()
|
## [Userguide]()
|
||||||
- [Using the Userguide](using)
|
|
||||||
- [How userguide works](works)
|
- Getting Started
|
||||||
- [Contributing](contributing)
|
- [Using the Userguide](using)
|
||||||
- [Markdown Syntax](markdown)
|
- [How the Userguide works](works)
|
||||||
- [Configuration](config)
|
- [Configuration](config)
|
||||||
- [Adding your module](adding)
|
- Learning More
|
||||||
|
- [Contributing](contributing)
|
||||||
|
- [Markdown Syntax](markdown)
|
||||||
|
- [Adding your module](adding)
|
8
modules/userguide/koharness.php
Normal file
8
modules/userguide/koharness.php
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
<?php
|
||||||
|
// Configuration for koharness - builds a standalone skeleton Kohana app for running unit tests
|
||||||
|
return array(
|
||||||
|
'modules' => array(
|
||||||
|
'userguide' => __DIR__,
|
||||||
|
'unittest' => __DIR__ . '/vendor/kohana/unittest'
|
||||||
|
),
|
||||||
|
);
|
@ -99,7 +99,7 @@ h6:hover a.permalink {
|
|||||||
#kodoc-content,
|
#kodoc-content,
|
||||||
#kodoc-footer { float: left; clear: both; width: 100%; }
|
#kodoc-footer { float: left; clear: both; width: 100%; }
|
||||||
|
|
||||||
#kodoc-header { padding: 58px 0 2em; background: #77c244 url(../img/header.png) center top repeat-x; }
|
#kodoc-header { padding: 20px 0 2em; background: #77c244 url(../img/header.png) center top repeat-x; }
|
||||||
#kodoc-logo { display: block; float: left; }
|
#kodoc-logo { display: block; float: left; }
|
||||||
#kodoc-menu { float: right; margin-top: 12px; background: #113c32; -moz-border-radius: 5px; -webkit-border-radius: 5px; }
|
#kodoc-menu { float: right; margin-top: 12px; background: #113c32; -moz-border-radius: 5px; -webkit-border-radius: 5px; }
|
||||||
#kodoc-menu ul { float: left; margin: 0; padding: 0 0.5em 0 0; }
|
#kodoc-menu ul { float: left; margin: 0; padding: 0 0.5em 0 0; }
|
||||||
@ -125,11 +125,23 @@ h6:hover a.permalink {
|
|||||||
|
|
||||||
#kodoc-topics { }
|
#kodoc-topics { }
|
||||||
#kodoc-topics ul,
|
#kodoc-topics ul,
|
||||||
#kodoc-topics ol { list-style-type:none; margin: 0; padding: 0;}
|
#kodoc-topics ol { list-style-type:none; margin: 0 0 0 0; padding: 0;}
|
||||||
#kodoc-topics ul li,
|
#kodoc-topics ul li,
|
||||||
#kodoc-topics ol li { margin:0; padding: 0; margin-left: 1em; }
|
#kodoc-topics ol li { margin:0; padding: 0; margin-left: 1em; }
|
||||||
#kodoc-topics ul li a.current,
|
#kodoc-topics ul li a.current,
|
||||||
#kodoc-topics ol li a.current { font-weight: bold; }
|
#kodoc-topics ol li a.current { font-weight: bold; }
|
||||||
|
|
||||||
|
#kodoc-topics > ul > li {
|
||||||
|
margin-bottom: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#kodoc-topics > ul > li > a,
|
||||||
|
#kodoc-topics > ul > li > span {
|
||||||
|
font-weight: bold;
|
||||||
|
color: #EE8C0E;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
#kodoc-topics span,
|
#kodoc-topics span,
|
||||||
#kodoc-topics a { display: block; padding: 0; margin: 0; }
|
#kodoc-topics a { display: block; padding: 0; margin: 0; }
|
||||||
#kodoc-topics span { cursor: pointer; }
|
#kodoc-topics span { cursor: pointer; }
|
||||||
|
@ -32,41 +32,6 @@ $(document).ready(function()
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
// Collapsing menus
|
|
||||||
$('#kodoc-topics li:has(li)').each(function()
|
|
||||||
{
|
|
||||||
var $this = $(this);
|
|
||||||
var toggle = $('<span class="toggle"></span>');
|
|
||||||
var menu = $this.find('>ul,>ol');
|
|
||||||
|
|
||||||
toggle.click(function()
|
|
||||||
{
|
|
||||||
if (menu.is(':visible'))
|
|
||||||
{
|
|
||||||
menu.stop(true, true).slideUp('fast');
|
|
||||||
toggle.html('+');
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
menu.stop(true, true).slideDown('fast');
|
|
||||||
toggle.html('–');
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
$this.find('>span').click(function()
|
|
||||||
{
|
|
||||||
// Menu without a link
|
|
||||||
toggle.click();
|
|
||||||
});
|
|
||||||
|
|
||||||
if ( ! $this.is(':has(a.current)'))
|
|
||||||
{
|
|
||||||
menu.hide();
|
|
||||||
}
|
|
||||||
|
|
||||||
toggle.html(menu.is(':visible') ? '–' : '+').prependTo($this);
|
|
||||||
});
|
|
||||||
|
|
||||||
// Show source links
|
// Show source links
|
||||||
|
|
||||||
$('#kodoc-main .method-source').each(function()
|
$('#kodoc-main .method-source').each(function()
|
||||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user