Update Kohana to 3.1.3.1
This commit is contained in:
parent
8b658b497a
commit
ff2370c368
@ -1,6 +1,20 @@
|
|||||||
<?php defined('SYSPATH') or die('No direct script access.');
|
<?php defined('SYSPATH') or die('No direct script access.');
|
||||||
|
|
||||||
//-- Environment setup --------------------------------------------------------
|
// -- Environment setup --------------------------------------------------------
|
||||||
|
|
||||||
|
// Load the core Kohana class
|
||||||
|
require SYSPATH.'classes/kohana/core'.EXT;
|
||||||
|
|
||||||
|
if (is_file(APPPATH.'classes/kohana'.EXT))
|
||||||
|
{
|
||||||
|
// Application extends the core
|
||||||
|
require APPPATH.'classes/kohana'.EXT;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Load empty core extension
|
||||||
|
require SYSPATH.'classes/kohana'.EXT;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set the default time zone.
|
* Set the default time zone.
|
||||||
@ -34,7 +48,23 @@ spl_autoload_register(array('Kohana', 'auto_load'));
|
|||||||
*/
|
*/
|
||||||
ini_set('unserialize_callback_func', 'spl_autoload_call');
|
ini_set('unserialize_callback_func', 'spl_autoload_call');
|
||||||
|
|
||||||
//-- Configuration and initialization -----------------------------------------
|
// -- Configuration and initialization -----------------------------------------
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the default language
|
||||||
|
*/
|
||||||
|
I18n::lang('en-us');
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set Kohana::$environment if a 'KOHANA_ENV' environment variable has been supplied.
|
||||||
|
*
|
||||||
|
* Note: If you supply an invalid environment name, a PHP warning will be thrown
|
||||||
|
* saying "Couldn't find constant Kohana::<INVALID_ENV_NAME>"
|
||||||
|
*/
|
||||||
|
if (isset($_SERVER['KOHANA_ENV']))
|
||||||
|
{
|
||||||
|
Kohana::$environment = constant('Kohana::'.strtoupper($_SERVER['KOHANA_ENV']));
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Initialize Kohana, setting the default options.
|
* Initialize Kohana, setting the default options.
|
||||||
@ -57,27 +87,33 @@ Kohana::init(array(
|
|||||||
/**
|
/**
|
||||||
* Attach the file write to logging. Multiple writers are supported.
|
* Attach the file write to logging. Multiple writers are supported.
|
||||||
*/
|
*/
|
||||||
Kohana::$log->attach(new Kohana_Log_File(APPPATH.'logs'));
|
Kohana::$log->attach(new Log_File(APPPATH.'logs'));
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Attach a file reader to config. Multiple readers are supported.
|
* Attach a file reader to config. Multiple readers are supported.
|
||||||
*/
|
*/
|
||||||
Kohana::$config->attach(new Kohana_Config_File);
|
Kohana::$config->attach(new Config_File);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Enable modules. Modules are referenced by a relative or absolute path.
|
* Enable modules. Modules are referenced by a relative or absolute path.
|
||||||
*/
|
*/
|
||||||
Kohana::modules(array(
|
Kohana::modules(array(
|
||||||
'auth' => MODPATH.'auth', // Basic authentication
|
'auth' => SMDPATH.'auth', // Basic authentication
|
||||||
// 'cache' => MODPATH.'cache', // Caching with multiple backends
|
'cache' => SMDPATH.'cache', // Caching with multiple backends
|
||||||
// 'codebench' => MODPATH.'codebench', // Benchmarking tool
|
// 'codebench' => SMDPATH.'codebench', // Benchmarking tool
|
||||||
'database' => MODPATH.'database', // Database access
|
'database' => SMDPATH.'database', // Database access
|
||||||
// 'image' => MODPATH.'image', // Image manipulation
|
// 'image' => SMDPATH.'image', // Image manipulation
|
||||||
'orm' => MODPATH.'orm', // Object Relationship Mapping
|
'orm' => SMDPATH.'orm', // Object Relationship Mapping
|
||||||
// 'oauth' => MODPATH.'oauth', // OAuth authentication
|
// 'unittest' => SMDPATH.'unittest', // Unit testing
|
||||||
// 'pagination' => MODPATH.'pagination', // Paging of results
|
// 'userguide' => SMDPATH.'userguide', // User guide and API documentation
|
||||||
// 'unittest' => MODPATH.'unittest', // Unit testing
|
));
|
||||||
'userguide' => MODPATH.'userguide', // User guide and API documentation
|
|
||||||
|
/**
|
||||||
|
* Enable specalised interfaces
|
||||||
|
*/
|
||||||
|
Route::set('sections', '<directory>/<controller>(/<action>(/<id>(/<sid>)))',
|
||||||
|
array(
|
||||||
|
'directory' => '('.implode('|',Kohana::config('config.method_directory')).')'
|
||||||
));
|
));
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -97,15 +133,4 @@ Route::set('default/media', 'media(/<file>)', array('file' => '.+'))
|
|||||||
'action' => 'media',
|
'action' => 'media',
|
||||||
'file' => NULL,
|
'file' => NULL,
|
||||||
));
|
));
|
||||||
|
?>
|
||||||
if ( ! defined('SUPPRESS_REQUEST'))
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
* Execute the main request. A source of the URI can be passed, eg: $_SERVER['PATH_INFO'].
|
|
||||||
* If no source is specified, the URI will be automatically detected.
|
|
||||||
*/
|
|
||||||
echo Request::instance()
|
|
||||||
->execute()
|
|
||||||
->send_headers()
|
|
||||||
->response;
|
|
||||||
}
|
|
||||||
|
@ -1,3 +1,3 @@
|
|||||||
# Kohana PHP Framework, version 3.0 (dev)
|
# Kohana PHP Framework, version 3.1 (release)
|
||||||
|
|
||||||
This is the current development version of [Kohana](http://kohanaframework.org/).
|
This is the current release version of [Kohana](http://kohanaframework.org/).
|
||||||
|
118
includes/kohana/application/bootstrap.php
Normal file
118
includes/kohana/application/bootstrap.php
Normal file
@ -0,0 +1,118 @@
|
|||||||
|
<?php defined('SYSPATH') or die('No direct script access.');
|
||||||
|
|
||||||
|
// -- Environment setup --------------------------------------------------------
|
||||||
|
|
||||||
|
// Load the core Kohana class
|
||||||
|
require SYSPATH.'classes/kohana/core'.EXT;
|
||||||
|
|
||||||
|
if (is_file(APPPATH.'classes/kohana'.EXT))
|
||||||
|
{
|
||||||
|
// Application extends the core
|
||||||
|
require APPPATH.'classes/kohana'.EXT;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Load empty core extension
|
||||||
|
require SYSPATH.'classes/kohana'.EXT;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the default time zone.
|
||||||
|
*
|
||||||
|
* @see http://kohanaframework.org/guide/using.configuration
|
||||||
|
* @see http://php.net/timezones
|
||||||
|
*/
|
||||||
|
date_default_timezone_set('America/Chicago');
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the default locale.
|
||||||
|
*
|
||||||
|
* @see http://kohanaframework.org/guide/using.configuration
|
||||||
|
* @see http://php.net/setlocale
|
||||||
|
*/
|
||||||
|
setlocale(LC_ALL, 'en_US.utf-8');
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Enable the Kohana auto-loader.
|
||||||
|
*
|
||||||
|
* @see http://kohanaframework.org/guide/using.autoloading
|
||||||
|
* @see http://php.net/spl_autoload_register
|
||||||
|
*/
|
||||||
|
spl_autoload_register(array('Kohana', 'auto_load'));
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Enable the Kohana auto-loader for unserialization.
|
||||||
|
*
|
||||||
|
* @see http://php.net/spl_autoload_call
|
||||||
|
* @see http://php.net/manual/var.configuration.php#unserialize-callback-func
|
||||||
|
*/
|
||||||
|
ini_set('unserialize_callback_func', 'spl_autoload_call');
|
||||||
|
|
||||||
|
// -- Configuration and initialization -----------------------------------------
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the default language
|
||||||
|
*/
|
||||||
|
I18n::lang('en-us');
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set Kohana::$environment if a 'KOHANA_ENV' environment variable has been supplied.
|
||||||
|
*
|
||||||
|
* Note: If you supply an invalid environment name, a PHP warning will be thrown
|
||||||
|
* saying "Couldn't find constant Kohana::<INVALID_ENV_NAME>"
|
||||||
|
*/
|
||||||
|
if (isset($_SERVER['KOHANA_ENV']))
|
||||||
|
{
|
||||||
|
Kohana::$environment = constant('Kohana::'.strtoupper($_SERVER['KOHANA_ENV']));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initialize Kohana, setting the default options.
|
||||||
|
*
|
||||||
|
* The following options are available:
|
||||||
|
*
|
||||||
|
* - string base_url path, and optionally domain, of your application NULL
|
||||||
|
* - string index_file name of your index file, usually "index.php" index.php
|
||||||
|
* - string charset internal character set used for input and output utf-8
|
||||||
|
* - string cache_dir set the internal cache directory APPPATH/cache
|
||||||
|
* - boolean errors enable or disable error handling TRUE
|
||||||
|
* - boolean profile enable or disable internal profiling TRUE
|
||||||
|
* - boolean caching enable or disable internal caching FALSE
|
||||||
|
*/
|
||||||
|
Kohana::init(array(
|
||||||
|
'base_url' => '/',
|
||||||
|
));
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Attach the file write to logging. Multiple writers are supported.
|
||||||
|
*/
|
||||||
|
Kohana::$log->attach(new Log_File(APPPATH.'logs'));
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Attach a file reader to config. Multiple readers are supported.
|
||||||
|
*/
|
||||||
|
Kohana::$config->attach(new Config_File);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Enable modules. Modules are referenced by a relative or absolute path.
|
||||||
|
*/
|
||||||
|
Kohana::modules(array(
|
||||||
|
// 'auth' => MODPATH.'auth', // Basic authentication
|
||||||
|
// 'cache' => MODPATH.'cache', // Caching with multiple backends
|
||||||
|
// 'codebench' => MODPATH.'codebench', // Benchmarking tool
|
||||||
|
// 'database' => MODPATH.'database', // Database access
|
||||||
|
// 'image' => MODPATH.'image', // Image manipulation
|
||||||
|
// 'orm' => MODPATH.'orm', // Object Relationship Mapping
|
||||||
|
// 'unittest' => MODPATH.'unittest', // Unit testing
|
||||||
|
// 'userguide' => MODPATH.'userguide', // User guide and API documentation
|
||||||
|
));
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the routes. Each route must have a minimum of a name, a URI and a set of
|
||||||
|
* defaults for the URI.
|
||||||
|
*/
|
||||||
|
Route::set('default', '(<controller>(/<action>(/<id>)))')
|
||||||
|
->defaults(array(
|
||||||
|
'controller' => 'welcome',
|
||||||
|
'action' => 'index',
|
||||||
|
));
|
10
includes/kohana/application/classes/controller/welcome.php
Normal file
10
includes/kohana/application/classes/controller/welcome.php
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
<?php defined('SYSPATH') or die('No direct script access.');
|
||||||
|
|
||||||
|
class Controller_Welcome extends Controller {
|
||||||
|
|
||||||
|
public function action_index()
|
||||||
|
{
|
||||||
|
$this->response->body('hello, world!');
|
||||||
|
}
|
||||||
|
|
||||||
|
} // End Welcome
|
@ -1,233 +0,0 @@
|
|||||||
<project name="kohana" default="help" basedir=".">
|
|
||||||
<property environment="env"/>
|
|
||||||
|
|
||||||
<property name="basedir" value="${project.basedir}"/>
|
|
||||||
<property name="builddir" value="${basedir}/build"/>
|
|
||||||
|
|
||||||
<property name="repo" value="git@github.com:kohana/kohana.git"/>
|
|
||||||
<property name="branch" value="3.1.x"/>
|
|
||||||
<property name="tag" value="${env.TAG}"/>
|
|
||||||
|
|
||||||
<property name="submodules" value="system,modules/auth,modules/cache,modules/codebench,modules/database,modules/image,modules/oauth,modules/orm,modules/pagination,modules/unittest,modules/userguide"/>
|
|
||||||
<property name="release-excludes" value="**/.git,**/.git*,build.xml,phpunit.xml,DEVELOPERS.md,phpunitcc,code_coverage.xml,release-tag,TESTING.md,**/tests"/>
|
|
||||||
|
|
||||||
<!-- Shows the help message -->
|
|
||||||
<target name="help">
|
|
||||||
<echo message="General Targets"/>
|
|
||||||
<echo message="==============="/>
|
|
||||||
<echo message="phing test Run unit tests."/>
|
|
||||||
<echo message="phing test-log Run unit tests with logging enabled."/>
|
|
||||||
<echo message="phing phpcs Run phpcs."/>
|
|
||||||
<echo message="phing phpcs-log Run phpcs with logging enabled."/>
|
|
||||||
<echo message="phing phpmd Run phpmd."/>
|
|
||||||
<echo message="phing phpmd-log Run phpmd with logging enabled."/>
|
|
||||||
<echo message="phing phpcpd-log Run phpcpd with logging enabled."/>
|
|
||||||
<echo message="phing pdepend-log Run pdepend with logging enabled."/>
|
|
||||||
<echo message="phing phpcb-log Run phpcb with logging enabled."/>
|
|
||||||
<echo message=""/>
|
|
||||||
<echo message="Kohana Developer Targets"/>
|
|
||||||
<echo message="========================"/>
|
|
||||||
<echo message="phing dev-setup Setup for development on Kohana itself."/>
|
|
||||||
<echo message="phing git-status Show the git status of each submodule."/>
|
|
||||||
<echo message="phing git-checkout Checkout a branch accross all submodules."/>
|
|
||||||
<echo message="phing git-pull Perform a pull for each submodule."/>
|
|
||||||
<echo message="phing git-push Perform a push for each submodule."/>
|
|
||||||
<echo message=""/>
|
|
||||||
<echo message="Misc Targets"/>
|
|
||||||
<echo message="============"/>
|
|
||||||
<echo message="phing ci Alias task for continuous integration servers"/>
|
|
||||||
</target>
|
|
||||||
|
|
||||||
<!-- Clean up -->
|
|
||||||
<target name="clean">
|
|
||||||
<delete dir="${builddir}"/>
|
|
||||||
<!-- Create build directories -->
|
|
||||||
<mkdir dir="${builddir}/coverage"/>
|
|
||||||
<mkdir dir="${builddir}/logs"/>
|
|
||||||
<mkdir dir="${builddir}/release"/>
|
|
||||||
<mkdir dir="${builddir}/code-browser"/>
|
|
||||||
</target>
|
|
||||||
|
|
||||||
<target name="dev-setup">
|
|
||||||
<property name="git-checkout-branch" value="${branch}"/> <!-- Prevents git-checkout asking for a branch name -->
|
|
||||||
<exec command="git submodule update --init --recursive" dir="${basedir}" />
|
|
||||||
<phingcall target="_dev-setup-remotes" />
|
|
||||||
<phingcall target="git-pull" />
|
|
||||||
<phingcall target="git-checkout" />
|
|
||||||
</target>
|
|
||||||
|
|
||||||
<target name="git-pull">
|
|
||||||
<phingcall target="_git-pull">
|
|
||||||
<property name="dir" value="." />
|
|
||||||
</phingcall>
|
|
||||||
<foreach list="${submodules}" param="dir" target="_git-pull"/>
|
|
||||||
</target>
|
|
||||||
|
|
||||||
<target name="_git-pull">
|
|
||||||
<exec command="git pull dev" dir="${dir}"/>
|
|
||||||
</target>
|
|
||||||
|
|
||||||
<target name="git-checkout">
|
|
||||||
<if>
|
|
||||||
<not>
|
|
||||||
<isset property="git-checkout-branch"/>
|
|
||||||
</not>
|
|
||||||
<then>
|
|
||||||
<propertyprompt propertyName="git-checkout-branch" defaultValue="${branch}" promptText="Branch name:" />
|
|
||||||
</then>
|
|
||||||
</if>
|
|
||||||
|
|
||||||
<phingcall target="_git-checkout">
|
|
||||||
<property name="dir" value="." />
|
|
||||||
</phingcall>
|
|
||||||
|
|
||||||
<foreach list="${submodules}" param="dir" target="_git-checkout"/>
|
|
||||||
</target>
|
|
||||||
|
|
||||||
<target name="_git-checkout">
|
|
||||||
<exec returnProperty="git-checkout-branch-exists" command="git show-ref --quiet --verify -- 'refs/remotes/dev/${git-checkout-branch}'" dir="${dir}" passthru="true"/>
|
|
||||||
<if>
|
|
||||||
<equals arg1="${git-checkout-branch-exists}" arg2="0"/>
|
|
||||||
<then>
|
|
||||||
<exec command="git checkout --track -b ${git-checkout-branch} dev/${git-checkout-branch}" dir="${dir}" passthru="true"/>
|
|
||||||
</then>
|
|
||||||
<else>
|
|
||||||
<exec command="git checkout -b ${git-checkout-branch}" dir="${dir}" passthru="true"/>
|
|
||||||
</else>
|
|
||||||
</if>
|
|
||||||
</target>
|
|
||||||
|
|
||||||
<target name="git-push">
|
|
||||||
<foreach list="${submodules}" param="dir" target="_git-push"/>
|
|
||||||
<phingcall target="_git-push">
|
|
||||||
<property name="dir" value="." />
|
|
||||||
</phingcall>
|
|
||||||
</target>
|
|
||||||
|
|
||||||
<target name="_git-push">
|
|
||||||
<exec command="git push dev" dir="${dir}" passthru="true"/>
|
|
||||||
</target>
|
|
||||||
|
|
||||||
<target name="git-status">
|
|
||||||
<foreach list="${submodules}" param="dir" target="_git-status"/>
|
|
||||||
<phingcall target="_git-status">
|
|
||||||
<property name="dir" value="." />
|
|
||||||
</phingcall>
|
|
||||||
</target>
|
|
||||||
|
|
||||||
<target name="_git-status">
|
|
||||||
<exec command="git status" dir="${dir}" passthru="true"/>
|
|
||||||
</target>
|
|
||||||
|
|
||||||
<target name="_dev-setup-remotes">
|
|
||||||
<!-- TODO: Clean up... -->
|
|
||||||
<phingcall target="_dev-setup-remote">
|
|
||||||
<property name="repository" value="git@github.com:kohana/kohana.git" />
|
|
||||||
<property name="dir" value="${basedir}" />
|
|
||||||
</phingcall>
|
|
||||||
<phingcall target="_dev-setup-remote">
|
|
||||||
<property name="repository" value="git@github.com:kohana/core.git" />
|
|
||||||
<property name="dir" value="${basedir}/system" />
|
|
||||||
</phingcall>
|
|
||||||
<phingcall target="_dev-setup-remote">
|
|
||||||
<property name="repository" value="git@github.com:kohana/auth.git" />
|
|
||||||
<property name="dir" value="${basedir}/modules/auth" />
|
|
||||||
</phingcall>
|
|
||||||
<phingcall target="_dev-setup-remote">
|
|
||||||
<property name="repository" value="git@github.com:kohana/cache.git" />
|
|
||||||
<property name="dir" value="${basedir}/modules/cache" />
|
|
||||||
</phingcall>
|
|
||||||
<phingcall target="_dev-setup-remote">
|
|
||||||
<property name="repository" value="git@github.com:kohana/codebench.git" />
|
|
||||||
<property name="dir" value="${basedir}/modules/codebench" />
|
|
||||||
</phingcall>
|
|
||||||
<phingcall target="_dev-setup-remote">
|
|
||||||
<property name="repository" value="git@github.com:kohana/database.git" />
|
|
||||||
<property name="dir" value="${basedir}/modules/database" />
|
|
||||||
</phingcall>
|
|
||||||
<phingcall target="_dev-setup-remote">
|
|
||||||
<property name="repository" value="git@github.com:kohana/image.git" />
|
|
||||||
<property name="dir" value="${basedir}/modules/image" />
|
|
||||||
</phingcall>
|
|
||||||
<phingcall target="_dev-setup-remote">
|
|
||||||
<property name="repository" value="git@github.com:kohana/oauth.git" />
|
|
||||||
<property name="dir" value="${basedir}/modules/oauth" />
|
|
||||||
</phingcall>
|
|
||||||
<phingcall target="_dev-setup-remote">
|
|
||||||
<property name="repository" value="git@github.com:kohana/orm.git" />
|
|
||||||
<property name="dir" value="${basedir}/modules/orm" />
|
|
||||||
</phingcall>
|
|
||||||
<phingcall target="_dev-setup-remote">
|
|
||||||
<property name="repository" value="git@github.com:kohana/pagination.git" />
|
|
||||||
<property name="dir" value="${basedir}/modules/pagination" />
|
|
||||||
</phingcall>
|
|
||||||
<phingcall target="_dev-setup-remote">
|
|
||||||
<property name="repository" value="git@github.com:kohana/unittest.git" />
|
|
||||||
<property name="dir" value="${basedir}/modules/unittest" />
|
|
||||||
</phingcall>
|
|
||||||
<phingcall target="_dev-setup-remote">
|
|
||||||
<property name="repository" value="git@github.com:kohana/userguide.git" />
|
|
||||||
<property name="dir" value="${basedir}/modules/userguide" />
|
|
||||||
</phingcall>
|
|
||||||
</target>
|
|
||||||
|
|
||||||
<target name="_dev-setup-remote">
|
|
||||||
<exec command="git remote rm dev" dir="${dir}"/>
|
|
||||||
<exec command="git remote add dev ${repository}" dir="${dir}"/>
|
|
||||||
</target>
|
|
||||||
|
|
||||||
<!-- Run unit tests -->
|
|
||||||
<target name="test">
|
|
||||||
<exec command="phpunit --bootstrap=application/test_bootstrap.php modules/unittest/tests.php" checkreturn="true" passthru="true"/>
|
|
||||||
</target>
|
|
||||||
|
|
||||||
<!-- Run unit tests and generate junit.xml and clover.xml -->
|
|
||||||
<target name="test-log">
|
|
||||||
<exec command="phpunit --bootstrap=application/test_bootstrap.php --coverage-html=${builddir}/coverage --log-junit=${builddir}/logs/junit.xml --coverage-clover=${builddir}/logs/clover.xml modules/unittest/tests.php" checkreturn="true" passthru="true"/>
|
|
||||||
</target>
|
|
||||||
|
|
||||||
<!-- Run PHP Code Sniffer -->
|
|
||||||
<target name="phpcs">
|
|
||||||
<exec command="phpcs --standard=Kohana --ignore=*.js,*.css,**/vendor/**,**/tests/** ${basedir}" passthru="true"/>
|
|
||||||
</target>
|
|
||||||
|
|
||||||
<!-- Run PHP Code Sniffer and generate checkstyle.xml -->
|
|
||||||
<target name="phpcs-log">
|
|
||||||
<exec command="phpcs --standard=Kohana --ignore=*.js,*.css,**/vendor/**,**/tests/** --report=checkstyle --report-file=${builddir}/logs/checkstyle.xml ${basedir}" passthru="false"/>
|
|
||||||
</target>
|
|
||||||
|
|
||||||
<!-- Run PHP Mess Detector -->
|
|
||||||
<target name="phpmd">
|
|
||||||
<exec command="phpmd ${basedir} text codesize,unusedcode --exclude=**/vendor/**" passthru="true"/>
|
|
||||||
</target>
|
|
||||||
|
|
||||||
<!-- Run PHP Mess Detector and generate pmd.xml -->
|
|
||||||
<target name="phpmd-log">
|
|
||||||
<exec command="phpmd ${basedir} xml codesize,unusedcode --exclude=**/vendor/** --reportfile ${builddir}/logs/pmd.xml" passthru="true"/>
|
|
||||||
</target>
|
|
||||||
|
|
||||||
<!-- Run PHP Copy/Paste Detector and generate pmd.xml -->
|
|
||||||
<target name="phpcpd-log">
|
|
||||||
<exec command="phpcpd --log-pmd ${builddir}/logs/pmd-cpd.xml ${basedir}" passthru="true"/>
|
|
||||||
</target>
|
|
||||||
|
|
||||||
<!-- Run PHP Depend and generate jdepend.xml -->
|
|
||||||
<target name="pdepend-log">
|
|
||||||
<exec command="pdepend --jdepend-xml=${builddir}/logs/jdepend.xml ${basedir}" passthru="true"/>
|
|
||||||
</target>
|
|
||||||
|
|
||||||
<!-- Run PHP CodeBrowser and generate output -->
|
|
||||||
<target name="phpcb-log">
|
|
||||||
<exec command="phpcb --log ${builddir}/logs --source ${basedir} --output ${builddir}/code-browser" passthru="true"/>
|
|
||||||
</target>
|
|
||||||
|
|
||||||
<!-- Hudson CI target -->
|
|
||||||
<target name="ci" depends="clean">
|
|
||||||
<phingcall target="test-log"/>
|
|
||||||
<phingcall target="pdepend-log"/>
|
|
||||||
<phingcall target="phpmd-log"/>
|
|
||||||
<phingcall target="phpcpd-log"/>
|
|
||||||
<phingcall target="phpcs-log"/>
|
|
||||||
<phingcall target="phpcb-log"/>
|
|
||||||
</target>
|
|
||||||
</project>
|
|
@ -1,21 +0,0 @@
|
|||||||
# Turn on URL rewriting
|
|
||||||
RewriteEngine On
|
|
||||||
|
|
||||||
# Installation directory
|
|
||||||
RewriteBase /
|
|
||||||
|
|
||||||
# Protect hidden files from being viewed
|
|
||||||
<Files .*>
|
|
||||||
Order Deny,Allow
|
|
||||||
Deny From All
|
|
||||||
</Files>
|
|
||||||
|
|
||||||
# Protect application and system files from being viewed
|
|
||||||
RewriteRule ^(?:application|modules|system)\b.* index.php/$0 [L]
|
|
||||||
|
|
||||||
# Allow any files or directories that exist to be displayed directly
|
|
||||||
RewriteCond %{REQUEST_FILENAME} !-f
|
|
||||||
RewriteCond %{REQUEST_FILENAME} !-d
|
|
||||||
|
|
||||||
# Rewrite all other URLs to index.php/URL
|
|
||||||
RewriteRule .* index.php/$0 [PT]
|
|
@ -1,20 +1,4 @@
|
|||||||
<?php
|
<?php defined('SYSPATH') or exit('Install tests must be loaded from within index.php!'); ?>
|
||||||
|
|
||||||
// Sanity check, install should only be checked from index.php
|
|
||||||
defined('SYSPATH') or exit('Install tests must be loaded from within index.php!');
|
|
||||||
|
|
||||||
if (version_compare(PHP_VERSION, '5.3', '<'))
|
|
||||||
{
|
|
||||||
// Clear out the cache to prevent errors. This typically happens on Windows/FastCGI.
|
|
||||||
clearstatcache();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// Clearing the realpath() cache is only possible PHP 5.3+
|
|
||||||
clearstatcache(TRUE);
|
|
||||||
}
|
|
||||||
|
|
||||||
?>
|
|
||||||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
|
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
|
||||||
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
|
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
|
||||||
|
|
||||||
@ -179,12 +163,20 @@ else
|
|||||||
</p>
|
</p>
|
||||||
|
|
||||||
<table cellspacing="0">
|
<table cellspacing="0">
|
||||||
|
<tr>
|
||||||
|
<th>PECL HTTP Enabled</th>
|
||||||
|
<?php if (extension_loaded('http')): ?>
|
||||||
|
<td class="pass">Pass</td>
|
||||||
|
<?php else: ?>
|
||||||
|
<td class="fail">Kohana can use the <a href="http://php.net/http">http</a> extension for the Request_Client_External class.</td>
|
||||||
|
<?php endif ?>
|
||||||
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<th>cURL Enabled</th>
|
<th>cURL Enabled</th>
|
||||||
<?php if (extension_loaded('curl')): ?>
|
<?php if (extension_loaded('curl')): ?>
|
||||||
<td class="pass">Pass</td>
|
<td class="pass">Pass</td>
|
||||||
<?php else: ?>
|
<?php else: ?>
|
||||||
<td class="fail">Kohana requires <a href="http://php.net/curl">cURL</a> for the Remote class.</td>
|
<td class="fail">Kohana can use the <a href="http://php.net/curl">cURL</a> extension for the Request_Client_External class.</td>
|
||||||
<?php endif ?>
|
<?php endif ?>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
@ -203,6 +195,14 @@ else
|
|||||||
<td class="fail">Kohana requires <a href="http://php.net/gd">GD</a> v2 for the Image class.</td>
|
<td class="fail">Kohana requires <a href="http://php.net/gd">GD</a> v2 for the Image class.</td>
|
||||||
<?php endif ?>
|
<?php endif ?>
|
||||||
</tr>
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<th>MySQL Enabled</th>
|
||||||
|
<?php if (function_exists('mysql_connect')): ?>
|
||||||
|
<td class="pass">Pass</td>
|
||||||
|
<?php else: ?>
|
||||||
|
<td class="fail">Kohana can use the <a href="http://php.net/mysql">MySQL</a> extension to support MySQL databases.</td>
|
||||||
|
<?php endif ?>
|
||||||
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<th>PDO Enabled</th>
|
<th>PDO Enabled</th>
|
||||||
<?php if (class_exists('PDO')): ?>
|
<?php if (class_exists('PDO')): ?>
|
||||||
|
13
includes/kohana/modules/auth/README.md
Normal file
13
includes/kohana/modules/auth/README.md
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
New Age Auth
|
||||||
|
---
|
||||||
|
|
||||||
|
I've forked the main Auth module because there were some fundamental flaws with it:
|
||||||
|
|
||||||
|
1. It's trivial to [bruteforce](http://dev.kohanaframework.org/issues/3163) publicly hidden salt hashes.
|
||||||
|
- I've fixed this by switching the password hashing algorithm to the more secure secret-key based hash_hmac method.
|
||||||
|
2. ORM drivers were included.
|
||||||
|
- I've fixed this by simply removing them. They cause confusion with new users because they think that Auth requires ORM. The only driver currently provided by default is the file driver.
|
||||||
|
3. Auth::get_user()'s api is inconsistent because it returns different data types.
|
||||||
|
- I've fixed this by returning an empty user model by default. You can override what gets returned (if you've changed your user model class name for instance) by overloading the get_user() method in your application.
|
||||||
|
|
||||||
|
These changes should be merged into the mainline branch eventually, but they completely break the API, so likely won't be done until 3.1.
|
@ -27,7 +27,7 @@ abstract class Kohana_Auth {
|
|||||||
|
|
||||||
if ( ! $type = $config->get('driver'))
|
if ( ! $type = $config->get('driver'))
|
||||||
{
|
{
|
||||||
$type = 'ORM';
|
$type = 'file';
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set the session class name
|
// Set the session class name
|
||||||
@ -40,16 +40,6 @@ abstract class Kohana_Auth {
|
|||||||
return Auth::$_instance;
|
return Auth::$_instance;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Create an instance of Auth.
|
|
||||||
*
|
|
||||||
* @return Auth
|
|
||||||
*/
|
|
||||||
public static function factory($config = array())
|
|
||||||
{
|
|
||||||
return new Auth($config);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected $_session;
|
protected $_session;
|
||||||
|
|
||||||
protected $_config;
|
protected $_config;
|
||||||
@ -61,9 +51,6 @@ abstract class Kohana_Auth {
|
|||||||
*/
|
*/
|
||||||
public function __construct($config = array())
|
public function __construct($config = array())
|
||||||
{
|
{
|
||||||
// Clean up the salt pattern and split it into an array
|
|
||||||
$config['salt_pattern'] = preg_split('/,\s*/', Kohana::config('auth')->get('salt_pattern'));
|
|
||||||
|
|
||||||
// Save the config in the object
|
// Save the config in the object
|
||||||
$this->_config = $config;
|
$this->_config = $config;
|
||||||
|
|
||||||
@ -78,13 +65,13 @@ abstract class Kohana_Auth {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets the currently logged in user from the session.
|
* Gets the currently logged in user from the session.
|
||||||
* Returns FALSE if no user is currently logged in.
|
* Returns NULL if no user is currently logged in.
|
||||||
*
|
*
|
||||||
* @return mixed
|
* @return mixed
|
||||||
*/
|
*/
|
||||||
public function get_user()
|
public function get_user($default = NULL)
|
||||||
{
|
{
|
||||||
return $this->_session->get($this->_config['session_key'], FALSE);
|
return $this->_session->get($this->_config['session_key'], $default);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -102,11 +89,8 @@ abstract class Kohana_Auth {
|
|||||||
|
|
||||||
if (is_string($password))
|
if (is_string($password))
|
||||||
{
|
{
|
||||||
// Get the salt from the stored password
|
// Create a hashed password
|
||||||
$salt = $this->find_salt($this->password($username));
|
$password = $this->hash($password);
|
||||||
|
|
||||||
// Create a hashed password using the salt from the stored password
|
|
||||||
$password = $this->hash_password($password, $salt);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return $this->_login($username, $password, $remember);
|
return $this->_login($username, $password, $remember);
|
||||||
@ -148,83 +132,33 @@ abstract class Kohana_Auth {
|
|||||||
*/
|
*/
|
||||||
public function logged_in($role = NULL)
|
public function logged_in($role = NULL)
|
||||||
{
|
{
|
||||||
return FALSE !== $this->get_user();
|
return ($this->get_user() !== NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a hashed password from a plaintext password, inserting salt
|
* Creates a hashed hmac password from a plaintext password. This
|
||||||
* based on the configured salt pattern.
|
* method is deprecated, [Auth::hash] should be used instead.
|
||||||
*
|
*
|
||||||
|
* @deprecated
|
||||||
* @param string plaintext password
|
* @param string plaintext password
|
||||||
* @return string hashed password string
|
|
||||||
*/
|
*/
|
||||||
public function hash_password($password, $salt = FALSE)
|
public function hash_password($password)
|
||||||
{
|
{
|
||||||
if ($salt === FALSE)
|
return $this->hash($password);
|
||||||
{
|
|
||||||
// Create a salt seed, same length as the number of offsets in the pattern
|
|
||||||
$salt = substr($this->hash(uniqid(NULL, TRUE)), 0, count($this->_config['salt_pattern']));
|
|
||||||
}
|
|
||||||
|
|
||||||
// Password hash that the salt will be inserted into
|
|
||||||
$hash = $this->hash($salt.$password);
|
|
||||||
|
|
||||||
// Change salt to an array
|
|
||||||
$salt = str_split($salt, 1);
|
|
||||||
|
|
||||||
// Returned password
|
|
||||||
$password = '';
|
|
||||||
|
|
||||||
// Used to calculate the length of splits
|
|
||||||
$last_offset = 0;
|
|
||||||
|
|
||||||
foreach ($this->_config['salt_pattern'] as $offset)
|
|
||||||
{
|
|
||||||
// Split a new part of the hash off
|
|
||||||
$part = substr($hash, 0, $offset - $last_offset);
|
|
||||||
|
|
||||||
// Cut the current part out of the hash
|
|
||||||
$hash = substr($hash, $offset - $last_offset);
|
|
||||||
|
|
||||||
// Add the part to the password, appending the salt character
|
|
||||||
$password .= $part.array_shift($salt);
|
|
||||||
|
|
||||||
// Set the last offset to the current offset
|
|
||||||
$last_offset = $offset;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Return the password, with the remaining hash appended
|
|
||||||
return $password.$hash;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Perform a hash, using the configured method.
|
* Perform a hmac hash, using the configured method.
|
||||||
*
|
*
|
||||||
* @param string string to hash
|
* @param string string to hash
|
||||||
* @return string
|
* @return string
|
||||||
*/
|
*/
|
||||||
public function hash($str)
|
public function hash($str)
|
||||||
{
|
{
|
||||||
return hash($this->_config['hash_method'], $str);
|
if ( ! $this->_config['hash_key'])
|
||||||
}
|
throw new Kohana_Exception('A valid hash key must be set in your auth config.');
|
||||||
|
|
||||||
/**
|
return hash_hmac($this->_config['hash_method'], $str, $this->_config['hash_key']);
|
||||||
* Finds the salt from a password, based on the configured salt pattern.
|
|
||||||
*
|
|
||||||
* @param string hashed password
|
|
||||||
* @return string
|
|
||||||
*/
|
|
||||||
public function find_salt($password)
|
|
||||||
{
|
|
||||||
$salt = '';
|
|
||||||
|
|
||||||
foreach ($this->_config['salt_pattern'] as $i => $offset)
|
|
||||||
{
|
|
||||||
// Find salt characters, take a good long look...
|
|
||||||
$salt .= substr($password, $offset + $i, 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
return $salt;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected function complete_login($user)
|
protected function complete_login($user)
|
||||||
|
@ -1,27 +0,0 @@
|
|||||||
<?php defined('SYSPATH') or die('No direct access allowed.');
|
|
||||||
/**
|
|
||||||
* Default auth role
|
|
||||||
*
|
|
||||||
* @package Kohana/Auth
|
|
||||||
* @author Kohana Team
|
|
||||||
* @copyright (c) 2007-2010 Kohana Team
|
|
||||||
* @license http://kohanaframework.org/license
|
|
||||||
*/
|
|
||||||
class Model_Auth_Role extends ORM {
|
|
||||||
|
|
||||||
// Relationships
|
|
||||||
protected $_has_many = array('users' => array('through' => 'roles_users'));
|
|
||||||
|
|
||||||
// Validation rules
|
|
||||||
protected $_rules = array(
|
|
||||||
'name' => array(
|
|
||||||
'not_empty' => NULL,
|
|
||||||
'min_length' => array(4),
|
|
||||||
'max_length' => array(32),
|
|
||||||
),
|
|
||||||
'description' => array(
|
|
||||||
'max_length' => array(255),
|
|
||||||
),
|
|
||||||
);
|
|
||||||
|
|
||||||
} // End Auth Role Model
|
|
@ -1,244 +0,0 @@
|
|||||||
<?php defined('SYSPATH') or die('No direct access allowed.');
|
|
||||||
/**
|
|
||||||
* Default auth user
|
|
||||||
*
|
|
||||||
* @package Kohana/Auth
|
|
||||||
* @author Kohana Team
|
|
||||||
* @copyright (c) 2007-2010 Kohana Team
|
|
||||||
* @license http://kohanaframework.org/license
|
|
||||||
*/
|
|
||||||
class Model_Auth_User extends ORM {
|
|
||||||
|
|
||||||
// Relationships
|
|
||||||
protected $_has_many = array(
|
|
||||||
'user_tokens' => array('model' => 'user_token'),
|
|
||||||
'roles' => array('model' => 'role', 'through' => 'roles_users'),
|
|
||||||
);
|
|
||||||
|
|
||||||
// Validation rules
|
|
||||||
protected $_rules = array(
|
|
||||||
'username' => array(
|
|
||||||
'not_empty' => NULL,
|
|
||||||
'min_length' => array(4),
|
|
||||||
'max_length' => array(32),
|
|
||||||
'regex' => array('/^[-\pL\pN_.]++$/uD'),
|
|
||||||
),
|
|
||||||
'password' => array(
|
|
||||||
'not_empty' => NULL,
|
|
||||||
'min_length' => array(5),
|
|
||||||
'max_length' => array(42),
|
|
||||||
),
|
|
||||||
'password_confirm' => array(
|
|
||||||
'matches' => array('password'),
|
|
||||||
),
|
|
||||||
'email' => array(
|
|
||||||
'not_empty' => NULL,
|
|
||||||
'min_length' => array(4),
|
|
||||||
'max_length' => array(127),
|
|
||||||
'email' => NULL,
|
|
||||||
),
|
|
||||||
);
|
|
||||||
|
|
||||||
// Validation callbacks
|
|
||||||
protected $_callbacks = array(
|
|
||||||
'username' => array('username_available'),
|
|
||||||
'email' => array('email_available'),
|
|
||||||
);
|
|
||||||
|
|
||||||
// Field labels
|
|
||||||
protected $_labels = array(
|
|
||||||
'username' => 'username',
|
|
||||||
'email' => 'email address',
|
|
||||||
'password' => 'password',
|
|
||||||
'password_confirm' => 'password confirmation',
|
|
||||||
);
|
|
||||||
|
|
||||||
// Columns to ignore
|
|
||||||
protected $_ignored_columns = array('password_confirm');
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Validates login information from an array, and optionally redirects
|
|
||||||
* after a successful login.
|
|
||||||
*
|
|
||||||
* @param array values to check
|
|
||||||
* @param string URI or URL to redirect to
|
|
||||||
* @return boolean
|
|
||||||
*/
|
|
||||||
public function login(array & $array, $redirect = FALSE)
|
|
||||||
{
|
|
||||||
$fieldname = $this->unique_key($array['username']);
|
|
||||||
$array = Validate::factory($array)
|
|
||||||
->label('username', $this->_labels[$fieldname])
|
|
||||||
->label('password', $this->_labels['password'])
|
|
||||||
->filter(TRUE, 'trim')
|
|
||||||
->rules('username', $this->_rules[$fieldname])
|
|
||||||
->rules('password', $this->_rules['password']);
|
|
||||||
|
|
||||||
// Get the remember login option
|
|
||||||
$remember = isset($array['remember']);
|
|
||||||
|
|
||||||
// Login starts out invalid
|
|
||||||
$status = FALSE;
|
|
||||||
|
|
||||||
if ($array->check())
|
|
||||||
{
|
|
||||||
// Attempt to load the user
|
|
||||||
$this->where($fieldname, '=', $array['username'])->find();
|
|
||||||
|
|
||||||
if ($this->loaded() AND Auth::instance()->login($this, $array['password'], $remember))
|
|
||||||
{
|
|
||||||
if (is_string($redirect))
|
|
||||||
{
|
|
||||||
// Redirect after a successful login
|
|
||||||
Request::instance()->redirect($redirect);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Login is successful
|
|
||||||
$status = TRUE;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
$array->error('username', 'invalid');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return $status;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Validates an array for a matching password and password_confirm field,
|
|
||||||
* and optionally redirects after a successful save.
|
|
||||||
*
|
|
||||||
* @param array values to check
|
|
||||||
* @param string URI or URL to redirect to
|
|
||||||
* @return boolean
|
|
||||||
*/
|
|
||||||
public function change_password(array & $array, $redirect = FALSE)
|
|
||||||
{
|
|
||||||
$array = Validate::factory($array)
|
|
||||||
->label('password', $this->_labels['password'])
|
|
||||||
->label('password_confirm', $this->_labels['password_confirm'])
|
|
||||||
->filter(TRUE, 'trim')
|
|
||||||
->rules('password', $this->_rules['password'])
|
|
||||||
->rules('password_confirm', $this->_rules['password_confirm']);
|
|
||||||
|
|
||||||
if ($status = $array->check())
|
|
||||||
{
|
|
||||||
// Change the password
|
|
||||||
$this->password = $array['password'];
|
|
||||||
|
|
||||||
if ($status = $this->save() AND is_string($redirect))
|
|
||||||
{
|
|
||||||
// Redirect to the success page
|
|
||||||
Request::instance()->redirect($redirect);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return $status;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Complete the login for a user by incrementing the logins and saving login timestamp
|
|
||||||
*
|
|
||||||
* @return void
|
|
||||||
*/
|
|
||||||
public function complete_login()
|
|
||||||
{
|
|
||||||
if ( ! $this->_loaded)
|
|
||||||
{
|
|
||||||
// nothing to do
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Update the number of logins
|
|
||||||
$this->logins = new Database_Expression('logins + 1');
|
|
||||||
|
|
||||||
// Set the last login date
|
|
||||||
$this->last_login = time();
|
|
||||||
|
|
||||||
// Save the user
|
|
||||||
$this->save();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Does the reverse of unique_key_exists() by triggering error if username exists.
|
|
||||||
* Validation callback.
|
|
||||||
*
|
|
||||||
* @param Validate Validate object
|
|
||||||
* @param string field name
|
|
||||||
* @return void
|
|
||||||
*/
|
|
||||||
public function username_available(Validate $array, $field)
|
|
||||||
{
|
|
||||||
if ($this->unique_key_exists($array[$field], 'username'))
|
|
||||||
{
|
|
||||||
$array->error($field, 'username_available', array($array[$field]));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Does the reverse of unique_key_exists() by triggering error if email exists.
|
|
||||||
* Validation callback.
|
|
||||||
*
|
|
||||||
* @param Validate Validate object
|
|
||||||
* @param string field name
|
|
||||||
* @return void
|
|
||||||
*/
|
|
||||||
public function email_available(Validate $array, $field)
|
|
||||||
{
|
|
||||||
if ($this->unique_key_exists($array[$field], 'email'))
|
|
||||||
{
|
|
||||||
$array->error($field, 'email_available', array($array[$field]));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Tests if a unique key value exists in the database.
|
|
||||||
*
|
|
||||||
* @param mixed the value to test
|
|
||||||
* @param string field name
|
|
||||||
* @return boolean
|
|
||||||
*/
|
|
||||||
public function unique_key_exists($value, $field = NULL)
|
|
||||||
{
|
|
||||||
if ($field === NULL)
|
|
||||||
{
|
|
||||||
// Automatically determine field by looking at the value
|
|
||||||
$field = $this->unique_key($value);
|
|
||||||
}
|
|
||||||
|
|
||||||
return (bool) DB::select(array('COUNT("*")', 'total_count'))
|
|
||||||
->from($this->_table_name)
|
|
||||||
->where($field, '=', $value)
|
|
||||||
->where($this->_primary_key, '!=', $this->pk())
|
|
||||||
->execute($this->_db)
|
|
||||||
->get('total_count');
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Allows a model use both email and username as unique identifiers for login
|
|
||||||
*
|
|
||||||
* @param string unique value
|
|
||||||
* @return string field name
|
|
||||||
*/
|
|
||||||
public function unique_key($value)
|
|
||||||
{
|
|
||||||
return Validate::email($value) ? 'email' : 'username';
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Saves the current object. Will hash password if it was changed.
|
|
||||||
*
|
|
||||||
* @return ORM
|
|
||||||
*/
|
|
||||||
public function save()
|
|
||||||
{
|
|
||||||
if (array_key_exists('password', $this->_changed))
|
|
||||||
{
|
|
||||||
$this->_object['password'] = Auth::instance()->hash_password($this->_object['password']);
|
|
||||||
}
|
|
||||||
|
|
||||||
return parent::save();
|
|
||||||
}
|
|
||||||
|
|
||||||
} // End Auth User Model
|
|
@ -2,13 +2,11 @@
|
|||||||
|
|
||||||
return array(
|
return array(
|
||||||
|
|
||||||
'driver' => 'ORM',
|
'driver' => 'file',
|
||||||
'hash_method' => 'sha1',
|
'hash_method' => 'sha256',
|
||||||
'salt_pattern' => '1, 3, 5, 9, 14, 15, 20, 21, 28, 30',
|
'hash_key' => NULL,
|
||||||
'lifetime' => 1209600,
|
'lifetime' => 1209600,
|
||||||
'session_key' => 'auth_user',
|
'session_key' => 'auth_user',
|
||||||
'autologin_key' => 'auth_autologin',
|
|
||||||
'forced_key' => 'auth_forced',
|
|
||||||
|
|
||||||
// Username/password combinations for the Auth File driver
|
// Username/password combinations for the Auth File driver
|
||||||
'users' => array(
|
'users' => array(
|
||||||
|
@ -1,23 +0,0 @@
|
|||||||
<?php defined('SYSPATH') or die('No direct script access.');
|
|
||||||
|
|
||||||
return array(
|
|
||||||
// Leave this alone
|
|
||||||
'modules' => array(
|
|
||||||
|
|
||||||
// This should be the path to this modules userguide pages, without the 'guide/'. Ex: '/guide/modulename/' would be 'modulename'
|
|
||||||
'auth' => array(
|
|
||||||
|
|
||||||
// Whether this modules userguide pages should be shown
|
|
||||||
'enabled' => TRUE,
|
|
||||||
|
|
||||||
// The name that should show up on the userguide index page
|
|
||||||
'name' => 'Auth',
|
|
||||||
|
|
||||||
// A short description of this module, shown on the index page
|
|
||||||
'description' => 'User authentication and authorization.',
|
|
||||||
|
|
||||||
// Copyright message, shown in the footer for this module
|
|
||||||
'copyright' => '© 2008–2010 Kohana Team',
|
|
||||||
)
|
|
||||||
)
|
|
||||||
);
|
|
@ -138,7 +138,7 @@ abstract class Kohana_Cache {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @var Kohana_Config
|
* @var Config
|
||||||
*/
|
*/
|
||||||
protected $_config;
|
protected $_config;
|
||||||
|
|
||||||
|
@ -71,7 +71,9 @@ class Kohana_Cache_Apc extends Cache {
|
|||||||
*/
|
*/
|
||||||
public function get($id, $default = NULL)
|
public function get($id, $default = NULL)
|
||||||
{
|
{
|
||||||
return (($data = apc_fetch($this->_sanitize_id($id))) === FALSE) ? $default : $data;
|
$data = apc_fetch($this->_sanitize_id($id), $success);
|
||||||
|
|
||||||
|
return $success ? $data : $default;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -373,7 +373,7 @@ class Kohana_Cache_File extends Cache implements Kohana_Cache_GarbageCollect {
|
|||||||
$name = $files->getFilename();
|
$name = $files->getFilename();
|
||||||
|
|
||||||
// If the name is not a dot
|
// If the name is not a dot
|
||||||
if ($name != '.' and $name != '..')
|
if ($name != '.' AND $name != '..' AND substr($file->getFilename(), 0, 1) == '.')
|
||||||
{
|
{
|
||||||
// Create new file resource
|
// Create new file resource
|
||||||
$fp = new SplFileInfo($files->getRealPath());
|
$fp = new SplFileInfo($files->getRealPath());
|
||||||
|
@ -29,7 +29,7 @@ class Bench_DateSpan extends Codebench {
|
|||||||
public static function bench_span_original($remote, $local = NULL, $output = 'years,months,weeks,days,hours,minutes,seconds')
|
public static function bench_span_original($remote, $local = NULL, $output = 'years,months,weeks,days,hours,minutes,seconds')
|
||||||
{
|
{
|
||||||
// Array with the output formats
|
// Array with the output formats
|
||||||
$output = preg_split('/[^a-z]+/', strtolower((string) $output));
|
$output = preg_split('/[^a-z]+/', strtolower( (string) $output));
|
||||||
|
|
||||||
// Invalid output
|
// Invalid output
|
||||||
if (empty($output))
|
if (empty($output))
|
||||||
@ -116,7 +116,7 @@ class Bench_DateSpan extends Codebench {
|
|||||||
public static function bench_span_use_array($remote, $local = NULL, $output = 'years,months,weeks,days,hours,minutes,seconds')
|
public static function bench_span_use_array($remote, $local = NULL, $output = 'years,months,weeks,days,hours,minutes,seconds')
|
||||||
{
|
{
|
||||||
// Array with the output formats
|
// Array with the output formats
|
||||||
$output = preg_split('/[^a-z]+/', strtolower((string) $output));
|
$output = preg_split('/[^a-z]+/', strtolower( (string) $output));
|
||||||
|
|
||||||
// Invalid output
|
// Invalid output
|
||||||
if (empty($output))
|
if (empty($output))
|
||||||
|
@ -17,7 +17,9 @@ class Controller_Codebench extends Kohana_Controller_Template {
|
|||||||
{
|
{
|
||||||
// Convert submitted class name to URI segment
|
// Convert submitted class name to URI segment
|
||||||
if (isset($_POST['class']))
|
if (isset($_POST['class']))
|
||||||
|
{
|
||||||
$this->request->redirect('codebench/'.trim($_POST['class']));
|
$this->request->redirect('codebench/'.trim($_POST['class']));
|
||||||
|
}
|
||||||
|
|
||||||
// Pass the class name on to the view
|
// Pass the class name on to the view
|
||||||
$this->template->class = (string) $class;
|
$this->template->class = (string) $class;
|
||||||
|
0
includes/kohana/modules/codebench/media/guide/codebench/codebench_screenshot1.png
Executable file → Normal file
0
includes/kohana/modules/codebench/media/guide/codebench/codebench_screenshot1.png
Executable file → Normal file
Before Width: | Height: | Size: 16 KiB After Width: | Height: | Size: 16 KiB |
0
includes/kohana/modules/codebench/media/guide/codebench/codebench_screenshot2.png
Executable file → Normal file
0
includes/kohana/modules/codebench/media/guide/codebench/codebench_screenshot2.png
Executable file → Normal file
Before Width: | Height: | Size: 13 KiB After Width: | Height: | Size: 13 KiB |
@ -2,7 +2,7 @@
|
|||||||
/**
|
/**
|
||||||
* Codebench — A benchmarking module.
|
* Codebench — A benchmarking module.
|
||||||
*
|
*
|
||||||
* @package Kohana
|
* @package Kohana/Codebench
|
||||||
* @author Kohana Team
|
* @author Kohana Team
|
||||||
* @copyright (c) 2009 Kohana Team
|
* @copyright (c) 2009 Kohana Team
|
||||||
* @license http://kohanaphp.com/license.html
|
* @license http://kohanaphp.com/license.html
|
||||||
@ -14,7 +14,9 @@
|
|||||||
<head>
|
<head>
|
||||||
|
|
||||||
<meta charset="utf-8" />
|
<meta charset="utf-8" />
|
||||||
<title><?php if ($class !== '') echo $class, ' · ' ?>Codebench</title>
|
<title><?php if ($class !== ''): ?>
|
||||||
|
<?php echo $class, ' · ' ?>
|
||||||
|
<?php endif; ?>Codebench</title>
|
||||||
|
|
||||||
<style>
|
<style>
|
||||||
/* General styles*/
|
/* General styles*/
|
||||||
|
@ -1,3 +1,3 @@
|
|||||||
<?php defined('SYSPATH') or die('No direct script access.');
|
<?php defined('SYSPATH') or die('No direct script access.');
|
||||||
|
|
||||||
class OAuth_Consumer extends Kohana_OAuth_Consumer { }
|
class Config_Database extends Kohana_Config_Database {}
|
@ -15,7 +15,7 @@
|
|||||||
* @copyright (c) 2009 Kohana Team
|
* @copyright (c) 2009 Kohana Team
|
||||||
* @license http://kohanaphp.com/license
|
* @license http://kohanaphp.com/license
|
||||||
*/
|
*/
|
||||||
class Kohana_Config_Database extends Kohana_Config_Reader {
|
class Kohana_Config_Database extends Config_Reader {
|
||||||
|
|
||||||
protected $_database_instance = 'default';
|
protected $_database_instance = 'default';
|
||||||
|
|
||||||
|
@ -158,12 +158,18 @@ abstract class Kohana_Database {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Disconnect from the database. This is called automatically by [Database::__destruct].
|
* Disconnect from the database. This is called automatically by [Database::__destruct].
|
||||||
|
* Clears the database instance from [Database::$instances].
|
||||||
*
|
*
|
||||||
* $db->disconnect();
|
* $db->disconnect();
|
||||||
*
|
*
|
||||||
* @return boolean
|
* @return boolean
|
||||||
*/
|
*/
|
||||||
abstract public function disconnect();
|
public function disconnect()
|
||||||
|
{
|
||||||
|
unset(Database::$instances[$this->_instance]);
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set the connection character set. This is called automatically by [Database::connect].
|
* Set the connection character set. This is called automatically by [Database::connect].
|
||||||
@ -196,51 +202,47 @@ abstract class Kohana_Database {
|
|||||||
abstract public function query($type, $sql, $as_object = FALSE, array $params = NULL);
|
abstract public function query($type, $sql, $as_object = FALSE, array $params = NULL);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Count the number of records in the last query, without LIMIT or OFFSET applied.
|
* Start a SQL transaction
|
||||||
*
|
*
|
||||||
* // Get the total number of records that match the last query
|
* // Start the transactions
|
||||||
* $count = $db->count_last_query();
|
* $db->begin();
|
||||||
*
|
*
|
||||||
* @deprecated since v3.0.9
|
* try {
|
||||||
* @return integer
|
* DB::insert('users')->values($user1)...
|
||||||
|
* DB::insert('users')->values($user2)...
|
||||||
|
* // Insert successful commit the changes
|
||||||
|
* $db->commit();
|
||||||
|
* }
|
||||||
|
* catch (Database_Exception $e)
|
||||||
|
* {
|
||||||
|
* // Insert failed. Rolling back changes...
|
||||||
|
* $db->rollback();
|
||||||
|
* }
|
||||||
|
*
|
||||||
|
* @param string transaction mode
|
||||||
|
* @return boolean
|
||||||
*/
|
*/
|
||||||
public function count_last_query()
|
abstract public function begin($mode = NULL);
|
||||||
{
|
|
||||||
if ($sql = $this->last_query)
|
|
||||||
{
|
|
||||||
$sql = trim($sql);
|
|
||||||
if (stripos($sql, 'SELECT') !== 0)
|
|
||||||
{
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (stripos($sql, 'LIMIT') !== FALSE)
|
/**
|
||||||
{
|
* Commit the current transaction
|
||||||
// Remove LIMIT from the SQL
|
*
|
||||||
$sql = preg_replace('/\sLIMIT\s+[^a-z]+/i', ' ', $sql);
|
* // Commit the database changes
|
||||||
}
|
* $db->commit();
|
||||||
|
*
|
||||||
|
* @return boolean
|
||||||
|
*/
|
||||||
|
abstract public function commit();
|
||||||
|
|
||||||
if (stripos($sql, 'OFFSET') !== FALSE)
|
/**
|
||||||
{
|
* Abort the current transaction
|
||||||
// Remove OFFSET from the SQL
|
*
|
||||||
$sql = preg_replace('/\sOFFSET\s+\d+/i', '', $sql);
|
* // Undo the changes
|
||||||
}
|
* $db->rollback();
|
||||||
|
*
|
||||||
// Get the total rows from the last query executed
|
* @return boolean
|
||||||
$result = $this->query
|
*/
|
||||||
(
|
abstract public function rollback();
|
||||||
Database::SELECT,
|
|
||||||
'SELECT COUNT(*) AS '.$this->quote_identifier('total_rows').' '
|
|
||||||
.'FROM ('.$sql.') AS '.$this->quote_table('counted_results'),
|
|
||||||
TRUE
|
|
||||||
);
|
|
||||||
|
|
||||||
// Return the total number of rows from the query
|
|
||||||
return (int) $result->current()->total_rows;
|
|
||||||
}
|
|
||||||
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Count the number of records in a table.
|
* Count the number of records in a table.
|
||||||
@ -254,7 +256,7 @@ abstract class Kohana_Database {
|
|||||||
public function count_records($table)
|
public function count_records($table)
|
||||||
{
|
{
|
||||||
// Quote the table name
|
// Quote the table name
|
||||||
$table = $this->quote_identifier($table);
|
$table = $this->quote_table($table);
|
||||||
|
|
||||||
return $this->query(Database::SELECT, 'SELECT COUNT(*) AS total_row_count FROM '.$table, FALSE)
|
return $this->query(Database::SELECT, 'SELECT COUNT(*) AS total_row_count FROM '.$table, FALSE)
|
||||||
->get('total_row_count');
|
->get('total_row_count');
|
||||||
@ -471,6 +473,90 @@ abstract class Kohana_Database {
|
|||||||
return $this->escape($value);
|
return $this->escape($value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Quote a database column name and add the table prefix if needed.
|
||||||
|
*
|
||||||
|
* $column = $db->quote_column($column);
|
||||||
|
*
|
||||||
|
* You can also use SQL methods within identifiers.
|
||||||
|
*
|
||||||
|
* // The value of "column" will be quoted
|
||||||
|
* $column = $db->quote_column('COUNT("column")');
|
||||||
|
*
|
||||||
|
* @param mixed column name or array(column, alias)
|
||||||
|
* @return string
|
||||||
|
* @uses Database::quote_identifier
|
||||||
|
* @uses Database::table_prefix
|
||||||
|
*/
|
||||||
|
public function quote_column($column)
|
||||||
|
{
|
||||||
|
if (is_array($column))
|
||||||
|
{
|
||||||
|
list($column, $alias) = $column;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($column instanceof Database_Query)
|
||||||
|
{
|
||||||
|
// Create a sub-query
|
||||||
|
$column = '('.$column->compile($this).')';
|
||||||
|
}
|
||||||
|
elseif ($column instanceof Database_Expression)
|
||||||
|
{
|
||||||
|
// Use a raw expression
|
||||||
|
$column = $column->value();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Convert to a string
|
||||||
|
$column = (string) $column;
|
||||||
|
|
||||||
|
if ($column === '*')
|
||||||
|
{
|
||||||
|
return $column;
|
||||||
|
}
|
||||||
|
elseif (strpos($column, '"') !== FALSE)
|
||||||
|
{
|
||||||
|
// Quote the column in FUNC("column") identifiers
|
||||||
|
$column = preg_replace('/"(.+?)"/e', '$this->quote_column("$1")', $column);
|
||||||
|
}
|
||||||
|
elseif (strpos($column, '.') !== FALSE)
|
||||||
|
{
|
||||||
|
$parts = explode('.', $column);
|
||||||
|
|
||||||
|
if ($prefix = $this->table_prefix())
|
||||||
|
{
|
||||||
|
// Get the offset of the table name, 2nd-to-last part
|
||||||
|
$offset = count($parts) - 2;
|
||||||
|
|
||||||
|
// Add the table prefix to the table name
|
||||||
|
$parts[$offset] = $prefix.$parts[$offset];
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach ($parts as & $part)
|
||||||
|
{
|
||||||
|
if ($part !== '*')
|
||||||
|
{
|
||||||
|
// Quote each of the parts
|
||||||
|
$part = $this->_identifier.$part.$this->_identifier;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$column = implode('.', $parts);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
$column = $this->_identifier.$column.$this->_identifier;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isset($alias))
|
||||||
|
{
|
||||||
|
$column .= ' AS '.$this->_identifier.$alias.$this->_identifier;
|
||||||
|
}
|
||||||
|
|
||||||
|
return $column;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Quote a database table name and adds the table prefix if needed.
|
* Quote a database table name and adds the table prefix if needed.
|
||||||
*
|
*
|
||||||
@ -481,40 +567,67 @@ abstract class Kohana_Database {
|
|||||||
* @uses Database::quote_identifier
|
* @uses Database::quote_identifier
|
||||||
* @uses Database::table_prefix
|
* @uses Database::table_prefix
|
||||||
*/
|
*/
|
||||||
public function quote_table($value)
|
public function quote_table($table)
|
||||||
{
|
{
|
||||||
// Assign the table by reference from the value
|
if (is_array($table))
|
||||||
if (is_array($value))
|
|
||||||
{
|
{
|
||||||
$table =& $value[0];
|
list($table, $alias) = $table;
|
||||||
|
}
|
||||||
|
|
||||||
// Attach table prefix to alias
|
if ($table instanceof Database_Query)
|
||||||
$value[1] = $this->table_prefix().$value[1];
|
{
|
||||||
|
// Create a sub-query
|
||||||
|
$table = '('.$table->compile($this).')';
|
||||||
|
}
|
||||||
|
elseif ($table instanceof Database_Expression)
|
||||||
|
{
|
||||||
|
// Use a raw expression
|
||||||
|
$table = $table->value();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
$table =& $value;
|
// Convert to a string
|
||||||
}
|
$table = (string) $table;
|
||||||
|
|
||||||
if (is_string($table) AND strpos($table, '.') === FALSE)
|
if (strpos($table, '.') !== FALSE)
|
||||||
{
|
{
|
||||||
// Add the table prefix for tables
|
$parts = explode('.', $table);
|
||||||
$table = $this->table_prefix().$table;
|
|
||||||
|
if ($prefix = $this->table_prefix())
|
||||||
|
{
|
||||||
|
// Get the offset of the table name, last part
|
||||||
|
$offset = count($parts) - 1;
|
||||||
|
|
||||||
|
// Add the table prefix to the table name
|
||||||
|
$parts[$offset] = $prefix.$parts[$offset];
|
||||||
}
|
}
|
||||||
|
|
||||||
return $this->quote_identifier($value);
|
foreach ($parts as & $part)
|
||||||
|
{
|
||||||
|
// Quote each of the parts
|
||||||
|
$part = $this->_identifier.$part.$this->_identifier;
|
||||||
|
}
|
||||||
|
|
||||||
|
$table = implode('.', $parts);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Add the table prefix
|
||||||
|
$table = $this->_identifier.$this->table_prefix().$table.$this->_identifier;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isset($alias))
|
||||||
|
{
|
||||||
|
// Attach table prefix to alias
|
||||||
|
$table .= ' AS '.$this->_identifier.$this->table_prefix().$alias.$this->_identifier;
|
||||||
|
}
|
||||||
|
|
||||||
|
return $table;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Quote a database identifier, such as a column name. Adds the
|
* Quote a database identifier
|
||||||
* table prefix to the identifier if a table name is present.
|
|
||||||
*
|
|
||||||
* $column = $db->quote_identifier($column);
|
|
||||||
*
|
|
||||||
* You can also use SQL methods within identifiers.
|
|
||||||
*
|
|
||||||
* // The value of "column" will be quoted
|
|
||||||
* $column = $db->quote_identifier('COUNT("column")');
|
|
||||||
*
|
*
|
||||||
* Objects passed to this function will be converted to strings.
|
* Objects passed to this function will be converted to strings.
|
||||||
* [Database_Expression] objects will use the value of the expression.
|
* [Database_Expression] objects will use the value of the expression.
|
||||||
@ -523,69 +636,55 @@ abstract class Kohana_Database {
|
|||||||
*
|
*
|
||||||
* @param mixed any identifier
|
* @param mixed any identifier
|
||||||
* @return string
|
* @return string
|
||||||
* @uses Database::table_prefix
|
|
||||||
*/
|
*/
|
||||||
public function quote_identifier($value)
|
public function quote_identifier($value)
|
||||||
{
|
{
|
||||||
if ($value === '*')
|
if (is_array($value))
|
||||||
{
|
{
|
||||||
return $value;
|
list($value, $alias) = $value;
|
||||||
}
|
}
|
||||||
elseif (is_object($value))
|
|
||||||
{
|
|
||||||
if ($value instanceof Database_Query)
|
if ($value instanceof Database_Query)
|
||||||
{
|
{
|
||||||
// Create a sub-query
|
// Create a sub-query
|
||||||
return '('.$value->compile($this).')';
|
$value = '('.$value->compile($this).')';
|
||||||
}
|
}
|
||||||
elseif ($value instanceof Database_Expression)
|
elseif ($value instanceof Database_Expression)
|
||||||
{
|
{
|
||||||
// Use a raw expression
|
// Use a raw expression
|
||||||
return $value->value();
|
$value = $value->value();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// Convert the object to a string
|
// Convert to a string
|
||||||
return $this->quote_identifier( (string) $value);
|
$value = (string) $value;
|
||||||
}
|
|
||||||
}
|
|
||||||
elseif (is_array($value))
|
|
||||||
{
|
|
||||||
// Separate the column and alias
|
|
||||||
list ($value, $alias) = $value;
|
|
||||||
|
|
||||||
return $this->quote_identifier($value).' AS '.$this->quote_identifier($alias);
|
if (strpos($value, '.') !== FALSE)
|
||||||
}
|
|
||||||
|
|
||||||
if (strpos($value, '"') !== FALSE)
|
|
||||||
{
|
{
|
||||||
// Quote the column in FUNC("ident") identifiers
|
|
||||||
return preg_replace('/"(.+?)"/e', '$this->quote_identifier("$1")', $value);
|
|
||||||
}
|
|
||||||
elseif (strpos($value, '.') !== FALSE)
|
|
||||||
{
|
|
||||||
// Split the identifier into the individual parts
|
|
||||||
$parts = explode('.', $value);
|
$parts = explode('.', $value);
|
||||||
|
|
||||||
if ($prefix = $this->table_prefix())
|
foreach ($parts as & $part)
|
||||||
{
|
{
|
||||||
// Get the offset of the table name, 2nd-to-last part
|
// Quote each of the parts
|
||||||
// This works for databases that can have 3 identifiers (Postgre)
|
$part = $this->_identifier.$part.$this->_identifier;
|
||||||
$offset = count($parts) - 2;
|
|
||||||
|
|
||||||
// Add the table prefix to the table name
|
|
||||||
$parts[$offset] = $prefix.$parts[$offset];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Quote each of the parts
|
$value = implode('.', $parts);
|
||||||
return implode('.', array_map(array($this, __FUNCTION__), $parts));
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
return $this->_identifier.$value.$this->_identifier;
|
$value = $this->_identifier.$value.$this->_identifier;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (isset($alias))
|
||||||
|
{
|
||||||
|
$value .= ' AS '.$this->_identifier.$alias.$this->_identifier;
|
||||||
|
}
|
||||||
|
|
||||||
|
return $value;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sanitize a string by escaping characters that could cause an SQL
|
* Sanitize a string by escaping characters that could cause an SQL
|
||||||
* injection attack.
|
* injection attack.
|
||||||
|
@ -64,9 +64,8 @@ class Kohana_Database_MySQL extends Database {
|
|||||||
// No connection exists
|
// No connection exists
|
||||||
$this->_connection = NULL;
|
$this->_connection = NULL;
|
||||||
|
|
||||||
throw new Database_Exception(':error', array(
|
throw new Database_Exception(':error',
|
||||||
':error' => mysql_error(),
|
array(':error' => mysql_error()),
|
||||||
),
|
|
||||||
mysql_errno());
|
mysql_errno());
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -114,6 +113,9 @@ class Kohana_Database_MySQL extends Database {
|
|||||||
{
|
{
|
||||||
// Clear the connection
|
// Clear the connection
|
||||||
$this->_connection = NULL;
|
$this->_connection = NULL;
|
||||||
|
|
||||||
|
// Clear the instance
|
||||||
|
parent::disconnect();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -256,6 +258,57 @@ class Kohana_Database_MySQL extends Database {
|
|||||||
return parent::datatype($type);
|
return parent::datatype($type);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Start a SQL transaction
|
||||||
|
*
|
||||||
|
* @link http://dev.mysql.com/doc/refman/5.0/en/set-transaction.html
|
||||||
|
*
|
||||||
|
* @param string Isolation level
|
||||||
|
* @return boolean
|
||||||
|
*/
|
||||||
|
public function begin($mode = NULL)
|
||||||
|
{
|
||||||
|
// Make sure the database is connected
|
||||||
|
$this->_connection or $this->connect();
|
||||||
|
|
||||||
|
if ($mode AND ! mysql_query("SET TRANSACTION ISOLATION LEVEL $mode", $this->_connection))
|
||||||
|
{
|
||||||
|
throw new Database_Exception(':error',
|
||||||
|
array(':error' => mysql_error($this->_connection)),
|
||||||
|
mysql_errno($this->_connection));
|
||||||
|
}
|
||||||
|
|
||||||
|
return (bool) mysql_query('START TRANSACTION', $this->_connection);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Commit a SQL transaction
|
||||||
|
*
|
||||||
|
* @param string Isolation level
|
||||||
|
* @return boolean
|
||||||
|
*/
|
||||||
|
public function commit()
|
||||||
|
{
|
||||||
|
// Make sure the database is connected
|
||||||
|
$this->_connection or $this->connect();
|
||||||
|
|
||||||
|
return (bool) mysql_query('COMMIT', $this->_connection);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Rollback a SQL transaction
|
||||||
|
*
|
||||||
|
* @param string Isolation level
|
||||||
|
* @return boolean
|
||||||
|
*/
|
||||||
|
public function rollback()
|
||||||
|
{
|
||||||
|
// Make sure the database is connected
|
||||||
|
$this->_connection or $this->connect();
|
||||||
|
|
||||||
|
return (bool) mysql_query('ROLLBACK', $this->_connection);
|
||||||
|
}
|
||||||
|
|
||||||
public function list_tables($like = NULL)
|
public function list_tables($like = NULL)
|
||||||
{
|
{
|
||||||
if (is_string($like))
|
if (is_string($like))
|
||||||
@ -368,8 +421,8 @@ class Kohana_Database_MySQL extends Database {
|
|||||||
if (($value = mysql_real_escape_string( (string) $value, $this->_connection)) === FALSE)
|
if (($value = mysql_real_escape_string( (string) $value, $this->_connection)) === FALSE)
|
||||||
{
|
{
|
||||||
throw new Database_Exception(':error',
|
throw new Database_Exception(':error',
|
||||||
array(':error' => mysql_errno($this->_connection)),
|
array(':error' => mysql_error($this->_connection)),
|
||||||
mysql_error($this->_connection));
|
mysql_errno($this->_connection));
|
||||||
}
|
}
|
||||||
|
|
||||||
// SQL standard is to use single-quotes for all values
|
// SQL standard is to use single-quotes for all values
|
||||||
|
@ -46,7 +46,7 @@ class Kohana_Database_MySQL_Result extends Database_Result {
|
|||||||
public function current()
|
public function current()
|
||||||
{
|
{
|
||||||
if ($this->_current_row !== $this->_internal_row AND ! $this->seek($this->_current_row))
|
if ($this->_current_row !== $this->_internal_row AND ! $this->seek($this->_current_row))
|
||||||
return FALSE;
|
return NULL;
|
||||||
|
|
||||||
// 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++;
|
||||||
|
@ -56,11 +56,9 @@ class Kohana_Database_PDO extends Database {
|
|||||||
}
|
}
|
||||||
catch (PDOException $e)
|
catch (PDOException $e)
|
||||||
{
|
{
|
||||||
throw new Database_Exception(':error', array(
|
throw new Database_Exception(':error',
|
||||||
':error' => $e->getMessage(),
|
array(':error' => $e->getMessage()),
|
||||||
),
|
$e->getCode());
|
||||||
$e->getCode(),
|
|
||||||
$e);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( ! empty($this->_config['charset']))
|
if ( ! empty($this->_config['charset']))
|
||||||
@ -75,7 +73,7 @@ class Kohana_Database_PDO extends Database {
|
|||||||
// Destroy the PDO object
|
// Destroy the PDO object
|
||||||
$this->_connection = NULL;
|
$this->_connection = NULL;
|
||||||
|
|
||||||
return TRUE;
|
return parent::disconnect();
|
||||||
}
|
}
|
||||||
|
|
||||||
public function set_charset($charset)
|
public function set_charset($charset)
|
||||||
@ -111,12 +109,12 @@ class Kohana_Database_PDO extends Database {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Convert the exception in a database exception
|
// Convert the exception in a database exception
|
||||||
throw new Database_Exception(':error [ :query ]', array(
|
throw new Database_Exception(':error [ :query ]',
|
||||||
|
array(
|
||||||
':error' => $e->getMessage(),
|
':error' => $e->getMessage(),
|
||||||
':query' => $sql
|
':query' => $sql
|
||||||
),
|
),
|
||||||
$e->getCode(),
|
$e->getCode());
|
||||||
$e);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isset($benchmark))
|
if (isset($benchmark))
|
||||||
@ -163,6 +161,30 @@ class Kohana_Database_PDO extends Database {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function begin($mode = NULL)
|
||||||
|
{
|
||||||
|
// Make sure the database is connected
|
||||||
|
$this->_connection or $this->connect();
|
||||||
|
|
||||||
|
return $this->_connection->beginTransaction();
|
||||||
|
}
|
||||||
|
|
||||||
|
public function commit()
|
||||||
|
{
|
||||||
|
// Make sure the database is connected
|
||||||
|
$this->_connection or $this->connect();
|
||||||
|
|
||||||
|
return $this->_connection->commit();
|
||||||
|
}
|
||||||
|
|
||||||
|
public function rollback()
|
||||||
|
{
|
||||||
|
// Make sure the database is connected
|
||||||
|
$this->_connection or $this->connect();
|
||||||
|
|
||||||
|
return $this->_connection->rollBack();
|
||||||
|
}
|
||||||
|
|
||||||
public function list_tables($like = NULL)
|
public function list_tables($like = NULL)
|
||||||
{
|
{
|
||||||
throw new Kohana_Exception('Database method :method is not supported by :class',
|
throw new Kohana_Exception('Database method :method is not supported by :class',
|
||||||
|
@ -14,7 +14,7 @@ class Kohana_Database_Query {
|
|||||||
protected $_type;
|
protected $_type;
|
||||||
|
|
||||||
// Cache lifetime
|
// Cache lifetime
|
||||||
protected $_lifetime;
|
protected $_lifetime = NULL;
|
||||||
|
|
||||||
// SQL statement
|
// SQL statement
|
||||||
protected $_sql;
|
protected $_sql;
|
||||||
@ -55,7 +55,7 @@ class Kohana_Database_Query {
|
|||||||
}
|
}
|
||||||
catch (Exception $e)
|
catch (Exception $e)
|
||||||
{
|
{
|
||||||
return Kohana::exception_text($e);
|
return Kohana_Exception::text($e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -72,7 +72,7 @@ class Kohana_Database_Query {
|
|||||||
/**
|
/**
|
||||||
* Enables the query to be cached for a specified amount of time.
|
* Enables the query to be cached for a specified amount of time.
|
||||||
*
|
*
|
||||||
* @param integer number of seconds to cache or null for default
|
* @param integer number of seconds to cache
|
||||||
* @return $this
|
* @return $this
|
||||||
* @uses Kohana::$cache_life
|
* @uses Kohana::$cache_life
|
||||||
*/
|
*/
|
||||||
@ -209,7 +209,7 @@ class Kohana_Database_Query {
|
|||||||
// Compile the SQL query
|
// Compile the SQL query
|
||||||
$sql = $this->compile($db);
|
$sql = $this->compile($db);
|
||||||
|
|
||||||
if ( ! empty($this->_lifetime) AND $this->_type === Database::SELECT)
|
if ($this->_lifetime !== NULL AND $this->_type === Database::SELECT)
|
||||||
{
|
{
|
||||||
// Set the cache key based on the database instance name and SQL
|
// Set the cache key based on the database instance name and SQL
|
||||||
$cache_key = 'Database::query("'.$db.'", "'.$sql.'")';
|
$cache_key = 'Database::query("'.$db.'", "'.$sql.'")';
|
||||||
|
@ -95,37 +95,31 @@ abstract class Kohana_Database_Query_Builder extends Database_Query {
|
|||||||
// BETWEEN always has exactly two arguments
|
// BETWEEN always has exactly two arguments
|
||||||
list($min, $max) = $value;
|
list($min, $max) = $value;
|
||||||
|
|
||||||
if (is_string($min) AND array_key_exists($min, $this->_parameters))
|
if ((is_string($min) AND array_key_exists($min, $this->_parameters)) === FALSE)
|
||||||
{
|
{
|
||||||
// Set the parameter as the minimum
|
// Quote the value, it is not a parameter
|
||||||
$min = $this->_parameters[$min];
|
$min = $db->quote($min);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (is_string($max) AND array_key_exists($max, $this->_parameters))
|
if ((is_string($max) AND array_key_exists($max, $this->_parameters)) === FALSE)
|
||||||
{
|
{
|
||||||
// Set the parameter as the maximum
|
// Quote the value, it is not a parameter
|
||||||
$max = $this->_parameters[$max];
|
$max = $db->quote($max);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Quote the min and max value
|
// Quote the min and max value
|
||||||
$value = $db->quote($min).' AND '.$db->quote($max);
|
$value = $min.' AND '.$max;
|
||||||
}
|
}
|
||||||
else
|
elseif ((is_string($value) AND array_key_exists($value, $this->_parameters)) === FALSE)
|
||||||
{
|
{
|
||||||
if (is_string($value) AND array_key_exists($value, $this->_parameters))
|
// Quote the value, it is not a parameter
|
||||||
{
|
|
||||||
// Set the parameter as the value
|
|
||||||
$value = $this->_parameters[$value];
|
|
||||||
}
|
|
||||||
|
|
||||||
// Quote the entire value normally
|
|
||||||
$value = $db->quote($value);
|
$value = $db->quote($value);
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($column)
|
if ($column)
|
||||||
{
|
{
|
||||||
// Apply proper quoting to the column
|
// Apply proper quoting to the column
|
||||||
$column = $db->quote_identifier($column);
|
$column = $db->quote_column($column);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Append the statement to the query
|
// Append the statement to the query
|
||||||
@ -155,15 +149,15 @@ abstract class Kohana_Database_Query_Builder extends Database_Query {
|
|||||||
list ($column, $value) = $group;
|
list ($column, $value) = $group;
|
||||||
|
|
||||||
// Quote the column name
|
// Quote the column name
|
||||||
$column = $db->quote_identifier($column);
|
$column = $db->quote_column($column);
|
||||||
|
|
||||||
if (is_string($value) AND array_key_exists($value, $this->_parameters))
|
if ((is_string($value) AND array_key_exists($value, $this->_parameters)) === FALSE)
|
||||||
{
|
{
|
||||||
// Use the parameter value
|
// Quote the value, it is not a parameter
|
||||||
$value = $this->_parameters[$value];
|
$value = $db->quote($value);
|
||||||
}
|
}
|
||||||
|
|
||||||
$set[$column] = $column.' = '.$db->quote($value);
|
$set[$column] = $column.' = '.$value;
|
||||||
}
|
}
|
||||||
|
|
||||||
return implode(', ', $set);
|
return implode(', ', $set);
|
||||||
@ -192,7 +186,7 @@ abstract class Kohana_Database_Query_Builder extends Database_Query {
|
|||||||
if ($column)
|
if ($column)
|
||||||
{
|
{
|
||||||
// Quote the column, if it has a value
|
// Quote the column, if it has a value
|
||||||
$column = $db->quote_identifier($column);
|
$column = $db->quote_column($column);
|
||||||
}
|
}
|
||||||
|
|
||||||
$sort[] = trim($column.' '.$direction);
|
$sort[] = trim($column.' '.$direction);
|
||||||
|
@ -73,7 +73,9 @@ class Kohana_Database_Query_Builder_Delete extends Database_Query_Builder_Where
|
|||||||
$query .= ' LIMIT '.$this->_limit;
|
$query .= ' LIMIT '.$this->_limit;
|
||||||
}
|
}
|
||||||
|
|
||||||
return $query;
|
$this->_sql = $query;
|
||||||
|
|
||||||
|
return parent::compile($db);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function reset()
|
public function reset()
|
||||||
@ -83,6 +85,8 @@ class Kohana_Database_Query_Builder_Delete extends Database_Query_Builder_Where
|
|||||||
|
|
||||||
$this->_parameters = array();
|
$this->_parameters = array();
|
||||||
|
|
||||||
|
$this->_sql = NULL;
|
||||||
|
|
||||||
return $this;
|
return $this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -122,7 +122,7 @@ class Kohana_Database_Query_Builder_Insert extends Database_Query_Builder {
|
|||||||
$query = 'INSERT INTO '.$db->quote_table($this->_table);
|
$query = 'INSERT INTO '.$db->quote_table($this->_table);
|
||||||
|
|
||||||
// Add the column names
|
// Add the column names
|
||||||
$query .= ' ('.implode(', ', array_map(array($db, 'quote_identifier'), $this->_columns)).') ';
|
$query .= ' ('.implode(', ', array_map(array($db, 'quote_column'), $this->_columns)).') ';
|
||||||
|
|
||||||
if (is_array($this->_values))
|
if (is_array($this->_values))
|
||||||
{
|
{
|
||||||
@ -132,16 +132,16 @@ class Kohana_Database_Query_Builder_Insert extends Database_Query_Builder {
|
|||||||
$groups = array();
|
$groups = array();
|
||||||
foreach ($this->_values as $group)
|
foreach ($this->_values as $group)
|
||||||
{
|
{
|
||||||
foreach ($group as $i => $value)
|
foreach ($group as $offset => $value)
|
||||||
{
|
{
|
||||||
if (is_string($value) AND isset($this->_parameters[$value]))
|
if ((is_string($value) AND array_key_exists($value, $this->_parameters)) === FALSE)
|
||||||
{
|
{
|
||||||
// Use the parameter value
|
// Quote the value, it is not a parameter
|
||||||
$group[$i] = $this->_parameters[$value];
|
$group[$offset] = $db->quote($value);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
$groups[] = '('.implode(', ', array_map($quote, $group)).')';
|
$groups[] = '('.implode(', ', $group).')';
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add the values
|
// Add the values
|
||||||
@ -153,7 +153,9 @@ class Kohana_Database_Query_Builder_Insert extends Database_Query_Builder {
|
|||||||
$query .= (string) $this->_values;
|
$query .= (string) $this->_values;
|
||||||
}
|
}
|
||||||
|
|
||||||
return $query;
|
$this->_sql = $query;
|
||||||
|
|
||||||
|
return parent::compile($db);;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function reset()
|
public function reset()
|
||||||
@ -165,6 +167,8 @@ class Kohana_Database_Query_Builder_Insert extends Database_Query_Builder {
|
|||||||
|
|
||||||
$this->_parameters = array();
|
$this->_parameters = array();
|
||||||
|
|
||||||
|
$this->_sql = NULL;
|
||||||
|
|
||||||
return $this;
|
return $this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -19,6 +19,9 @@ class Kohana_Database_Query_Builder_Join extends Database_Query_Builder {
|
|||||||
// ON ...
|
// ON ...
|
||||||
protected $_on = array();
|
protected $_on = array();
|
||||||
|
|
||||||
|
// USING ...
|
||||||
|
protected $_using = array();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a new JOIN statement for a table. Optionally, the type of JOIN
|
* Creates a new JOIN statement for a table. Optionally, the type of JOIN
|
||||||
* can be specified as the second parameter.
|
* can be specified as the second parameter.
|
||||||
@ -49,11 +52,37 @@ class Kohana_Database_Query_Builder_Join extends Database_Query_Builder {
|
|||||||
*/
|
*/
|
||||||
public function on($c1, $op, $c2)
|
public function on($c1, $op, $c2)
|
||||||
{
|
{
|
||||||
|
if ( ! empty($this->_using))
|
||||||
|
{
|
||||||
|
throw new Kohana_Exception('JOIN ... ON ... cannot be combined with JOIN ... USING ...');
|
||||||
|
}
|
||||||
|
|
||||||
$this->_on[] = array($c1, $op, $c2);
|
$this->_on[] = array($c1, $op, $c2);
|
||||||
|
|
||||||
return $this;
|
return $this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adds a new condition for joining.
|
||||||
|
*
|
||||||
|
* @param string column name
|
||||||
|
* @param ...
|
||||||
|
* @return $this
|
||||||
|
*/
|
||||||
|
public function using($columns)
|
||||||
|
{
|
||||||
|
if ( ! empty($this->_on))
|
||||||
|
{
|
||||||
|
throw new Kohana_Exception('JOIN ... ON ... cannot be combined with JOIN ... USING ...');
|
||||||
|
}
|
||||||
|
|
||||||
|
$columns = func_get_args();
|
||||||
|
|
||||||
|
$this->_using = array_merge($this->_using, $columns);
|
||||||
|
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Compile the SQL partial for a JOIN statement and return it.
|
* Compile the SQL partial for a JOIN statement and return it.
|
||||||
*
|
*
|
||||||
@ -72,8 +101,15 @@ class Kohana_Database_Query_Builder_Join extends Database_Query_Builder {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Quote the table name that is being joined
|
// Quote the table name that is being joined
|
||||||
$sql .= ' '.$db->quote_table($this->_table).' ON ';
|
$sql .= ' '.$db->quote_table($this->_table);
|
||||||
|
|
||||||
|
if ( ! empty($this->_using))
|
||||||
|
{
|
||||||
|
// Quote and concat the columns
|
||||||
|
$sql .= ' USING ('.implode(', ', array_map(array($db, 'quote_column'), $this->_using)).')';
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
$conditions = array();
|
$conditions = array();
|
||||||
foreach ($this->_on as $condition)
|
foreach ($this->_on as $condition)
|
||||||
{
|
{
|
||||||
@ -86,12 +122,13 @@ class Kohana_Database_Query_Builder_Join extends Database_Query_Builder {
|
|||||||
$op = ' '.strtoupper($op);
|
$op = ' '.strtoupper($op);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Quote each of the identifiers used for the condition
|
// Quote each of the columns used for the condition
|
||||||
$conditions[] = $db->quote_identifier($c1).$op.' '.$db->quote_identifier($c2);
|
$conditions[] = $db->quote_column($c1).$op.' '.$db->quote_column($c2);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Concat the conditions "... AND ..."
|
// Concat the conditions "... AND ..."
|
||||||
$sql .= '('.implode(' AND ', $conditions).')';
|
$sql .= ' ON ('.implode(' AND ', $conditions).')';
|
||||||
|
}
|
||||||
|
|
||||||
return $sql;
|
return $sql;
|
||||||
}
|
}
|
||||||
|
@ -31,6 +31,9 @@ class Kohana_Database_Query_Builder_Select extends Database_Query_Builder_Where
|
|||||||
// OFFSET ...
|
// OFFSET ...
|
||||||
protected $_offset = NULL;
|
protected $_offset = NULL;
|
||||||
|
|
||||||
|
// UNION ...
|
||||||
|
protected $_union = array();
|
||||||
|
|
||||||
// The last JOIN statement created
|
// The last JOIN statement created
|
||||||
protected $_last_join;
|
protected $_last_join;
|
||||||
|
|
||||||
@ -139,6 +142,22 @@ class Kohana_Database_Query_Builder_Select extends Database_Query_Builder_Where
|
|||||||
return $this;
|
return $this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adds "USING ..." conditions for the last created JOIN statement.
|
||||||
|
*
|
||||||
|
* @param string column name
|
||||||
|
* @param ...
|
||||||
|
* @return $this
|
||||||
|
*/
|
||||||
|
public function using($columns)
|
||||||
|
{
|
||||||
|
$columns = func_get_args();
|
||||||
|
|
||||||
|
call_user_func_array(array($this->_last_join, 'using'), $columns);
|
||||||
|
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a "GROUP BY ..." filter.
|
* Creates a "GROUP BY ..." filter.
|
||||||
*
|
*
|
||||||
@ -266,6 +285,26 @@ class Kohana_Database_Query_Builder_Select extends Database_Query_Builder_Where
|
|||||||
return $this;
|
return $this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adds an other UNION clause.
|
||||||
|
*
|
||||||
|
* @param mixed $select if string, it must be the name of a table. Else
|
||||||
|
* must be an instance of Database_Query_Builder_Select
|
||||||
|
* @param boolean $all decides if it's an UNION or UNION ALL clause
|
||||||
|
* @return $this
|
||||||
|
*/
|
||||||
|
public function union($select, $all = TRUE)
|
||||||
|
{
|
||||||
|
if (is_string($select))
|
||||||
|
{
|
||||||
|
$select = DB::select()->from($select);
|
||||||
|
}
|
||||||
|
if ( ! $select instanceof Database_Query_Builder_Select)
|
||||||
|
throw new Kohana_Exception('first parameter must be a string or an instance of Database_Query_Builder_Select');
|
||||||
|
$this->_union []= array('select' => $select, 'all' => $all);
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Start returning results after "OFFSET ..."
|
* Start returning results after "OFFSET ..."
|
||||||
*
|
*
|
||||||
@ -287,8 +326,8 @@ class Kohana_Database_Query_Builder_Select extends Database_Query_Builder_Where
|
|||||||
*/
|
*/
|
||||||
public function compile(Database $db)
|
public function compile(Database $db)
|
||||||
{
|
{
|
||||||
// Callback to quote identifiers
|
// Callback to quote columns
|
||||||
$quote_ident = array($db, 'quote_identifier');
|
$quote_column = array($db, 'quote_column');
|
||||||
|
|
||||||
// Callback to quote tables
|
// Callback to quote tables
|
||||||
$quote_table = array($db, 'quote_table');
|
$quote_table = array($db, 'quote_table');
|
||||||
@ -310,7 +349,7 @@ class Kohana_Database_Query_Builder_Select extends Database_Query_Builder_Where
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
// Select all columns
|
// Select all columns
|
||||||
$query .= implode(', ', array_unique(array_map($quote_ident, $this->_select)));
|
$query .= implode(', ', array_unique(array_map($quote_column, $this->_select)));
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( ! empty($this->_from))
|
if ( ! empty($this->_from))
|
||||||
@ -334,7 +373,7 @@ class Kohana_Database_Query_Builder_Select extends Database_Query_Builder_Where
|
|||||||
if ( ! empty($this->_group_by))
|
if ( ! empty($this->_group_by))
|
||||||
{
|
{
|
||||||
// Add sorting
|
// Add sorting
|
||||||
$query .= ' GROUP BY '.implode(', ', array_map($quote_ident, $this->_group_by));
|
$query .= ' GROUP BY '.implode(', ', array_map($quote_column, $this->_group_by));
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( ! empty($this->_having))
|
if ( ! empty($this->_having))
|
||||||
@ -361,7 +400,21 @@ class Kohana_Database_Query_Builder_Select extends Database_Query_Builder_Where
|
|||||||
$query .= ' OFFSET '.$this->_offset;
|
$query .= ' OFFSET '.$this->_offset;
|
||||||
}
|
}
|
||||||
|
|
||||||
return $query;
|
if ( ! empty($this->_union))
|
||||||
|
{
|
||||||
|
foreach ($this->_union as $u) {
|
||||||
|
$query .= ' UNION ';
|
||||||
|
if ($u['all'] === TRUE)
|
||||||
|
{
|
||||||
|
$query .= 'ALL ';
|
||||||
|
}
|
||||||
|
$query .= $u['select']->compile($db);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->_sql = $query;
|
||||||
|
|
||||||
|
return parent::compile($db);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function reset()
|
public function reset()
|
||||||
@ -372,7 +425,8 @@ class Kohana_Database_Query_Builder_Select extends Database_Query_Builder_Where
|
|||||||
$this->_where =
|
$this->_where =
|
||||||
$this->_group_by =
|
$this->_group_by =
|
||||||
$this->_having =
|
$this->_having =
|
||||||
$this->_order_by = array();
|
$this->_order_by =
|
||||||
|
$this->_union = array();
|
||||||
|
|
||||||
$this->_distinct = FALSE;
|
$this->_distinct = FALSE;
|
||||||
|
|
||||||
@ -382,7 +436,10 @@ class Kohana_Database_Query_Builder_Select extends Database_Query_Builder_Where
|
|||||||
|
|
||||||
$this->_parameters = array();
|
$this->_parameters = array();
|
||||||
|
|
||||||
|
$this->_sql = NULL;
|
||||||
|
|
||||||
return $this;
|
return $this;
|
||||||
}
|
}
|
||||||
|
|
||||||
} // End Database_Query_Select
|
} // End Database_Query_Select
|
||||||
|
|
||||||
|
@ -109,7 +109,9 @@ class Kohana_Database_Query_Builder_Update extends Database_Query_Builder_Where
|
|||||||
$query .= ' LIMIT '.$this->_limit;
|
$query .= ' LIMIT '.$this->_limit;
|
||||||
}
|
}
|
||||||
|
|
||||||
return $query;
|
$this->_sql = $query;
|
||||||
|
|
||||||
|
return parent::compile($db);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function reset()
|
public function reset()
|
||||||
@ -123,6 +125,8 @@ class Kohana_Database_Query_Builder_Update extends Database_Query_Builder_Where
|
|||||||
|
|
||||||
$this->_parameters = array();
|
$this->_parameters = array();
|
||||||
|
|
||||||
|
$this->_sql = NULL;
|
||||||
|
|
||||||
return $this;
|
return $this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -45,7 +45,7 @@ class Kohana_Database_Result_Cached extends Database_Result {
|
|||||||
public function current()
|
public function current()
|
||||||
{
|
{
|
||||||
// Return an array of the row
|
// Return an array of the row
|
||||||
return $this->valid() ? $this->_result[$this->_current_row] : FALSE;
|
return $this->valid() ? $this->_result[$this->_current_row] : NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
} // End Database_Result_Cached
|
} // End Database_Result_Cached
|
||||||
|
@ -0,0 +1,58 @@
|
|||||||
|
<?php defined('SYSPATH') or die('No direct script access.');
|
||||||
|
/**
|
||||||
|
* Database Model base class.
|
||||||
|
*
|
||||||
|
* @package Kohana/Database
|
||||||
|
* @category Models
|
||||||
|
* @author Kohana Team
|
||||||
|
* @copyright (c) 2008-2010 Kohana Team
|
||||||
|
* @license http://kohanaframework.org/license
|
||||||
|
*/
|
||||||
|
abstract class Kohana_Model_Database extends Model {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a new model instance. A [Database] instance or configuration
|
||||||
|
* group name can be passed to the model. If no database is defined, the
|
||||||
|
* "default" database group will be used.
|
||||||
|
*
|
||||||
|
* $model = Model::factory($name);
|
||||||
|
*
|
||||||
|
* @param string model name
|
||||||
|
* @param mixed Database instance object or string
|
||||||
|
* @return Model
|
||||||
|
*/
|
||||||
|
public static function factory($name, $db = NULL)
|
||||||
|
{
|
||||||
|
// Add the model prefix
|
||||||
|
$class = 'Model_'.$name;
|
||||||
|
|
||||||
|
return new $class($db);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Database instance
|
||||||
|
protected $_db = 'default';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Loads the database.
|
||||||
|
*
|
||||||
|
* $model = new Foo_Model($db);
|
||||||
|
*
|
||||||
|
* @param mixed Database instance object or string
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function __construct($db = NULL)
|
||||||
|
{
|
||||||
|
if ($db !== NULL)
|
||||||
|
{
|
||||||
|
// Set the database instance name
|
||||||
|
$this->_db = $db;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (is_string($this->_db))
|
||||||
|
{
|
||||||
|
// Load the database
|
||||||
|
$this->_db = Database::instance($this->_db);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
} // End Model
|
@ -0,0 +1,3 @@
|
|||||||
|
<?php defined('SYSPATH') or die('No direct script access.');
|
||||||
|
|
||||||
|
abstract class Model_Database extends Kohana_Model_Database {}
|
@ -10,7 +10,7 @@
|
|||||||
*/
|
*/
|
||||||
abstract class Kohana_Image {
|
abstract class Kohana_Image {
|
||||||
|
|
||||||
// Resizing contraints
|
// Resizing constraints
|
||||||
const NONE = 0x01;
|
const NONE = 0x01;
|
||||||
const WIDTH = 0x02;
|
const WIDTH = 0x02;
|
||||||
const HEIGHT = 0x03;
|
const HEIGHT = 0x03;
|
||||||
@ -73,6 +73,11 @@ abstract class Kohana_Image {
|
|||||||
*/
|
*/
|
||||||
public $type;
|
public $type;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var string mime type of the image
|
||||||
|
*/
|
||||||
|
public $mime;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Loads information about the image. Will throw an exception if the image
|
* Loads information about the image. Will throw an exception if the image
|
||||||
* does not exist or is not an image.
|
* does not exist or is not an image.
|
||||||
@ -99,7 +104,7 @@ abstract class Kohana_Image {
|
|||||||
if (empty($file) OR empty($info))
|
if (empty($file) OR empty($info))
|
||||||
{
|
{
|
||||||
throw new Kohana_Exception('Not an image or invalid image: :file',
|
throw new Kohana_Exception('Not an image or invalid image: :file',
|
||||||
array(':file' => Kohana::debug_path($file)));
|
array(':file' => Debug::path($file)));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Store the image information
|
// Store the image information
|
||||||
@ -132,10 +137,10 @@ abstract class Kohana_Image {
|
|||||||
if (is_object(Kohana::$log))
|
if (is_object(Kohana::$log))
|
||||||
{
|
{
|
||||||
// Get the text of the exception
|
// Get the text of the exception
|
||||||
$error = Kohana::exception_text($e);
|
$error = Kohana_Exception::text($e);
|
||||||
|
|
||||||
// Add this exception to the log
|
// Add this exception to the log
|
||||||
Kohana::$log->add(Kohana::ERROR, $error);
|
Kohana::$log->add(Log::ERROR, $error);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Showing any kind of error will be "inside" image data
|
// Showing any kind of error will be "inside" image data
|
||||||
@ -175,20 +180,20 @@ abstract class Kohana_Image {
|
|||||||
// Choose the master dimension automatically
|
// Choose the master dimension automatically
|
||||||
$master = Image::AUTO;
|
$master = Image::AUTO;
|
||||||
}
|
}
|
||||||
// Image::WIDTH and Image::HEIGHT depricated. You can use it in old projects,
|
// Image::WIDTH and Image::HEIGHT deprecated. You can use it in old projects,
|
||||||
// but in new you must pass empty value for non-master dimension
|
// but in new you must pass empty value for non-master dimension
|
||||||
elseif ($master == Image::WIDTH AND ! empty($width))
|
elseif ($master == Image::WIDTH AND ! empty($width))
|
||||||
{
|
{
|
||||||
$master = Image::AUTO;
|
$master = Image::AUTO;
|
||||||
|
|
||||||
// Set empty height for backvard compatibility
|
// Set empty height for backward compatibility
|
||||||
$height = NULL;
|
$height = NULL;
|
||||||
}
|
}
|
||||||
elseif ($master == Image::HEIGHT AND ! empty($height))
|
elseif ($master == Image::HEIGHT AND ! empty($height))
|
||||||
{
|
{
|
||||||
$master = Image::AUTO;
|
$master = Image::AUTO;
|
||||||
|
|
||||||
// Set empty width for backvard compatibility
|
// Set empty width for backward compatibility
|
||||||
$width = NULL;
|
$width = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -599,7 +604,7 @@ abstract class Kohana_Image {
|
|||||||
if ( ! is_writable($file))
|
if ( ! is_writable($file))
|
||||||
{
|
{
|
||||||
throw new Kohana_Exception('File must be writable: :file',
|
throw new Kohana_Exception('File must be writable: :file',
|
||||||
array(':file' => Kohana::debug_path($file)));
|
array(':file' => Debug::path($file)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@ -610,7 +615,7 @@ abstract class Kohana_Image {
|
|||||||
if ( ! is_dir($directory) OR ! is_writable($directory))
|
if ( ! is_dir($directory) OR ! is_writable($directory))
|
||||||
{
|
{
|
||||||
throw new Kohana_Exception('Directory must be writable: :directory',
|
throw new Kohana_Exception('Directory must be writable: :directory',
|
||||||
array(':directory' => Kohana::debug_path($directory)));
|
array(':directory' => Debug::path($directory)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -408,6 +408,8 @@ class Kohana_Image_GD extends Image {
|
|||||||
// Create the watermark image resource
|
// Create the watermark image resource
|
||||||
$overlay = imagecreatefromstring($watermark->render());
|
$overlay = imagecreatefromstring($watermark->render());
|
||||||
|
|
||||||
|
imagesavealpha($overlay, TRUE);
|
||||||
|
|
||||||
// Get the width and height of the watermark
|
// Get the width and height of the watermark
|
||||||
$width = imagesx($overlay);
|
$width = imagesx($overlay);
|
||||||
$height = imagesy($overlay);
|
$height = imagesy($overlay);
|
||||||
@ -417,13 +419,13 @@ class Kohana_Image_GD extends Image {
|
|||||||
// Convert an opacity range of 0-100 to 127-0
|
// Convert an opacity range of 0-100 to 127-0
|
||||||
$opacity = round(abs(($opacity * 127 / 100) - 127));
|
$opacity = round(abs(($opacity * 127 / 100) - 127));
|
||||||
|
|
||||||
// Allocate transparent white
|
// Allocate transparent gray
|
||||||
$color = imagecolorallocatealpha($overlay, 255, 255, 255, $opacity);
|
$color = imagecolorallocatealpha($overlay, 127, 127, 127, $opacity);
|
||||||
|
|
||||||
// The transparent image will overlay the watermark
|
// The transparent image will overlay the watermark
|
||||||
imagelayereffect($overlay, IMG_EFFECT_OVERLAY);
|
imagelayereffect($overlay, IMG_EFFECT_OVERLAY);
|
||||||
|
|
||||||
// Fill the background with transparent white
|
// Fill the background with the transparent color
|
||||||
imagefilledrectangle($overlay, 0, 0, $width, $height, $color);
|
imagefilledrectangle($overlay, 0, 0, $width, $height, $color);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,5 +0,0 @@
|
|||||||
# OAuth for Kohana
|
|
||||||
|
|
||||||
An implementation of the [OAuth](http://oauth.net/) protocol.
|
|
||||||
|
|
||||||
*Does not provide server capabilities!*
|
|
@ -1,217 +0,0 @@
|
|||||||
<?php defined('SYSPATH') OR die('No direct access allowed.');
|
|
||||||
/**
|
|
||||||
* OAuth Library
|
|
||||||
*
|
|
||||||
* @package Kohana/OAuth
|
|
||||||
* @category Base
|
|
||||||
* @author Kohana Team
|
|
||||||
* @copyright (c) 2010 Kohana Team
|
|
||||||
* @license http://kohanaframework.org/license
|
|
||||||
* @since 3.0.7
|
|
||||||
*/
|
|
||||||
abstract class Kohana_OAuth {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @var string OAuth complaince version
|
|
||||||
*/
|
|
||||||
public static $version = '1.0';
|
|
||||||
|
|
||||||
/**
|
|
||||||
* RFC3986 compatible version of urlencode. Passing an array will encode
|
|
||||||
* all of the values in the array. Array keys will not be encoded.
|
|
||||||
*
|
|
||||||
* $input = OAuth::urlencode($input);
|
|
||||||
*
|
|
||||||
* Multi-dimensional arrays are not allowed!
|
|
||||||
*
|
|
||||||
* [!!] This method implements [OAuth 1.0 Spec 5.1](http://oauth.net/core/1.0/#rfc.section.5.1).
|
|
||||||
*
|
|
||||||
* @param mixed input string or array
|
|
||||||
* @return mixed
|
|
||||||
*/
|
|
||||||
public static function urlencode($input)
|
|
||||||
{
|
|
||||||
if (is_array($input))
|
|
||||||
{
|
|
||||||
// Encode the values of the array
|
|
||||||
return array_map(array('OAuth', 'urlencode'), $input);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Encode the input
|
|
||||||
$input = rawurlencode($input);
|
|
||||||
|
|
||||||
if (version_compare(PHP_VERSION, '<', '5.3'))
|
|
||||||
{
|
|
||||||
// rawurlencode() is RFC3986 compliant in PHP 5.3
|
|
||||||
// the only difference is the encoding of tilde
|
|
||||||
$input = str_replace('%7E', '~', $input);
|
|
||||||
}
|
|
||||||
|
|
||||||
return $input;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* RFC3986 complaint version of urldecode. Passing an array will decode
|
|
||||||
* all of the values in the array. Array keys will not be encoded.
|
|
||||||
*
|
|
||||||
* $input = OAuth::urldecode($input);
|
|
||||||
*
|
|
||||||
* Multi-dimensional arrays are not allowed!
|
|
||||||
*
|
|
||||||
* [!!] This method implements [OAuth 1.0 Spec 5.1](http://oauth.net/core/1.0/#rfc.section.5.1).
|
|
||||||
*
|
|
||||||
* @param mixed input string or array
|
|
||||||
* @return mixed
|
|
||||||
*/
|
|
||||||
public static function urldecode($input)
|
|
||||||
{
|
|
||||||
if (is_array($input))
|
|
||||||
{
|
|
||||||
// Decode the values of the array
|
|
||||||
return array_map(array('OAuth', 'urldecode'), $input);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Decode the input
|
|
||||||
return rawurldecode($input);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Normalize all request parameters into a string.
|
|
||||||
*
|
|
||||||
* $query = OAuth::normalize_params($params);
|
|
||||||
*
|
|
||||||
* [!!] This method implements [OAuth 1.0 Spec 9.1.1](http://oauth.net/core/1.0/#rfc.section.9.1.1).
|
|
||||||
*
|
|
||||||
* @param array request parameters
|
|
||||||
* @return string
|
|
||||||
* @uses OAuth::urlencode
|
|
||||||
*/
|
|
||||||
public static function normalize_params(array $params = NULL)
|
|
||||||
{
|
|
||||||
if ( ! $params)
|
|
||||||
{
|
|
||||||
// Nothing to do
|
|
||||||
return '';
|
|
||||||
}
|
|
||||||
|
|
||||||
// Encode the parameter keys and values
|
|
||||||
$keys = OAuth::urlencode(array_keys($params));
|
|
||||||
$values = OAuth::urlencode(array_values($params));
|
|
||||||
|
|
||||||
// Recombine the parameters
|
|
||||||
$params = array_combine($keys, $values);
|
|
||||||
|
|
||||||
// OAuth Spec 9.1.1 (1)
|
|
||||||
// "Parameters are sorted by name, using lexicographical byte value ordering."
|
|
||||||
uksort($params, 'strcmp');
|
|
||||||
|
|
||||||
// Create a new query string
|
|
||||||
$query = array();
|
|
||||||
|
|
||||||
foreach ($params as $name => $value)
|
|
||||||
{
|
|
||||||
if (is_array($value))
|
|
||||||
{
|
|
||||||
// OAuth Spec 9.1.1 (1)
|
|
||||||
// "If two or more parameters share the same name, they are sorted by their value."
|
|
||||||
$value = natsort($value);
|
|
||||||
|
|
||||||
foreach ($value as $duplicate)
|
|
||||||
{
|
|
||||||
$query[] = $name.'='.$duplicate;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
$query[] = $name.'='.$value;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return implode('&', $query);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Parse the query string out of the URL and return it as parameters.
|
|
||||||
* All GET parameters must be removed from the request URL when building
|
|
||||||
* the base string and added to the request parameters.
|
|
||||||
*
|
|
||||||
* // parsed parameters: array('oauth_key' => 'abcdef123456789')
|
|
||||||
* list($url, $params) = OAuth::parse_url('http://example.com/oauth/access?oauth_key=abcdef123456789');
|
|
||||||
*
|
|
||||||
* [!!] This implements [OAuth Spec 9.1.1](http://oauth.net/core/1.0/#rfc.section.9.1.1).
|
|
||||||
*
|
|
||||||
* @param string URL to parse
|
|
||||||
* @return array (clean_url, params)
|
|
||||||
* @uses OAuth::parse_params
|
|
||||||
*/
|
|
||||||
public static function parse_url($url)
|
|
||||||
{
|
|
||||||
if ($query = parse_url($url, PHP_URL_QUERY))
|
|
||||||
{
|
|
||||||
// Remove the query string from the URL
|
|
||||||
list($url) = explode('?', $url, 2);
|
|
||||||
|
|
||||||
// Parse the query string as request parameters
|
|
||||||
$params = OAuth::parse_params($query);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// No parameters are present
|
|
||||||
$params = array();
|
|
||||||
}
|
|
||||||
|
|
||||||
return array($url, $params);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Parse the parameters in a string and return an array. Duplicates are
|
|
||||||
* converted into indexed arrays.
|
|
||||||
*
|
|
||||||
* // Parsed: array('a' => '1', 'b' => '2', 'c' => '3')
|
|
||||||
* $params = OAuth::parse_params('a=1,b=2,c=3');
|
|
||||||
*
|
|
||||||
* // Parsed: array('a' => array('1', '2'), 'c' => '3')
|
|
||||||
* $params = OAuth::parse_params('a=1,a=2,c=3');
|
|
||||||
*
|
|
||||||
* @param string parameter string
|
|
||||||
* @return array
|
|
||||||
*/
|
|
||||||
public static function parse_params($params)
|
|
||||||
{
|
|
||||||
// Split the parameters by &
|
|
||||||
$params = explode('&', trim($params));
|
|
||||||
|
|
||||||
// Create an array of parsed parameters
|
|
||||||
$parsed = array();
|
|
||||||
|
|
||||||
foreach ($params as $param)
|
|
||||||
{
|
|
||||||
// Split the parameter into name and value
|
|
||||||
list($name, $value) = explode('=', $param, 2);
|
|
||||||
|
|
||||||
// Decode the name and value
|
|
||||||
$name = OAuth::urldecode($name);
|
|
||||||
$value = OAuth::urldecode($value);
|
|
||||||
|
|
||||||
if (isset($parsed[$name]))
|
|
||||||
{
|
|
||||||
if ( ! is_array($parsed[$name]))
|
|
||||||
{
|
|
||||||
// Convert the parameter to an array
|
|
||||||
$parsed[$name] = array($parsed[$name]);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Add a new duplicate parameter
|
|
||||||
$parsed[$name][] = $value;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// Add a new parameter
|
|
||||||
$parsed[$name] = $value;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return $parsed;
|
|
||||||
}
|
|
||||||
|
|
||||||
} // End OAuth
|
|
@ -1,99 +0,0 @@
|
|||||||
<?php defined('SYSPATH') OR die('No direct access allowed.');
|
|
||||||
/**
|
|
||||||
* OAuth Consumer
|
|
||||||
*
|
|
||||||
* @package Kohana/OAuth
|
|
||||||
* @category Base
|
|
||||||
* @author Kohana Team
|
|
||||||
* @copyright (c) 2010 Kohana Team
|
|
||||||
* @license http://kohanaframework.org/license
|
|
||||||
* @since 3.0.7
|
|
||||||
*/
|
|
||||||
class Kohana_OAuth_Consumer {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Create a new consumer object.
|
|
||||||
*
|
|
||||||
* $consumer = OAuth_Consumer::factory($options);
|
|
||||||
*
|
|
||||||
* @param array consumer options, key and secret are required
|
|
||||||
* @return OAuth_Consumer
|
|
||||||
*/
|
|
||||||
public static function factory(array $options = NULL)
|
|
||||||
{
|
|
||||||
return new OAuth_Consumer($options);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @var string consumer key
|
|
||||||
*/
|
|
||||||
protected $key;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @var string consumer secret
|
|
||||||
*/
|
|
||||||
protected $secret;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @var string callback URL for OAuth authorization completion
|
|
||||||
*/
|
|
||||||
protected $callback;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Sets the consumer key and secret.
|
|
||||||
*
|
|
||||||
* @param array consumer options, key and secret are required
|
|
||||||
* @return void
|
|
||||||
*/
|
|
||||||
public function __construct(array $options = NULL)
|
|
||||||
{
|
|
||||||
if ( ! isset($options['key']))
|
|
||||||
{
|
|
||||||
throw new Kohana_OAuth_Exception('Required option not passed: :option',
|
|
||||||
array(':option' => 'key'));
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( ! isset($options['secret']))
|
|
||||||
{
|
|
||||||
throw new Kohana_OAuth_Exception('Required option not passed: :option',
|
|
||||||
array(':option' => 'secret'));
|
|
||||||
}
|
|
||||||
|
|
||||||
$this->key = $options['key'];
|
|
||||||
|
|
||||||
$this->secret = $options['secret'];
|
|
||||||
|
|
||||||
if (isset($options['callback']))
|
|
||||||
{
|
|
||||||
$this->callback = $options['callback'];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Return the value of any protected class variable.
|
|
||||||
*
|
|
||||||
* // Get the consumer key
|
|
||||||
* $key = $consumer->key;
|
|
||||||
*
|
|
||||||
* @param string variable name
|
|
||||||
* @return mixed
|
|
||||||
*/
|
|
||||||
public function __get($key)
|
|
||||||
{
|
|
||||||
return $this->$key;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Change the consumer callback.
|
|
||||||
*
|
|
||||||
* @param string new consumer callback
|
|
||||||
* @return $this
|
|
||||||
*/
|
|
||||||
public function callback($callback)
|
|
||||||
{
|
|
||||||
$this->callback = $callback;
|
|
||||||
|
|
||||||
return $this;
|
|
||||||
}
|
|
||||||
|
|
||||||
} // End OAuth_Consumer
|
|
@ -1,12 +0,0 @@
|
|||||||
<?php defined('SYSPATH') OR die('No direct access allowed.');
|
|
||||||
/**
|
|
||||||
* OAuth Exception
|
|
||||||
*
|
|
||||||
* @package Kohana/OAuth
|
|
||||||
* @category Exceptions
|
|
||||||
* @author Kohana Team
|
|
||||||
* @copyright (c) 2010 Kohana Team
|
|
||||||
* @license http://kohanaframework.org/license
|
|
||||||
* @since 3.0.7
|
|
||||||
*/
|
|
||||||
class Kohana_OAuth_Exception extends Kohana_Exception { }
|
|
@ -1,215 +0,0 @@
|
|||||||
<?php defined('SYSPATH') OR die('No direct access allowed.');
|
|
||||||
/**
|
|
||||||
* OAuth Provider
|
|
||||||
*
|
|
||||||
* @package Kohana/OAuth
|
|
||||||
* @category Provider
|
|
||||||
* @author Kohana Team
|
|
||||||
* @copyright (c) 2010 Kohana Team
|
|
||||||
* @license http://kohanaframework.org/license
|
|
||||||
* @since 3.0.7
|
|
||||||
*/
|
|
||||||
abstract class Kohana_OAuth_Provider {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Create a new provider.
|
|
||||||
*
|
|
||||||
* // Load the Twitter provider
|
|
||||||
* $provider = OAuth_Provider::factory('twitter');
|
|
||||||
*
|
|
||||||
* @param string provider name
|
|
||||||
* @param array provider options
|
|
||||||
* @return OAuth_Provider
|
|
||||||
*/
|
|
||||||
public static function factory($name, array $options = NULL)
|
|
||||||
{
|
|
||||||
$class = 'OAuth_Provider_'.$name;
|
|
||||||
|
|
||||||
return new $class($options);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @var string provider name
|
|
||||||
*/
|
|
||||||
public $name;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @var array additional request parameters to be used for remote requests
|
|
||||||
*/
|
|
||||||
protected $params = array();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Overloads default class properties from the options.
|
|
||||||
*
|
|
||||||
* Any of the provider options can be set here:
|
|
||||||
*
|
|
||||||
* Type | Option | Description | Default Value
|
|
||||||
* ----------|---------------|------------------------------------------------|-----------------
|
|
||||||
* mixed | signature | Signature method name or object | provider default
|
|
||||||
*
|
|
||||||
* @param array provider options
|
|
||||||
* @return void
|
|
||||||
*/
|
|
||||||
public function __construct(array $options = NULL)
|
|
||||||
{
|
|
||||||
if (isset($options['signature']))
|
|
||||||
{
|
|
||||||
// Set the signature method name or object
|
|
||||||
$this->signature = $options['signature'];
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( ! is_object($this->signature))
|
|
||||||
{
|
|
||||||
// Convert the signature name into an object
|
|
||||||
$this->signature = OAuth_Signature::factory($this->signature);
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( ! $this->name)
|
|
||||||
{
|
|
||||||
// Attempt to guess the name from the class name
|
|
||||||
$this->name = strtolower(substr(get_class($this), strlen('OAuth_Provider_')));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Return the value of any protected class variable.
|
|
||||||
*
|
|
||||||
* // Get the provider signature
|
|
||||||
* $signature = $provider->signature;
|
|
||||||
*
|
|
||||||
* @param string variable name
|
|
||||||
* @return mixed
|
|
||||||
*/
|
|
||||||
public function __get($key)
|
|
||||||
{
|
|
||||||
return $this->$key;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the request token URL for the provider.
|
|
||||||
*
|
|
||||||
* $url = $provider->url_request_token();
|
|
||||||
*
|
|
||||||
* @return string
|
|
||||||
*/
|
|
||||||
abstract public function url_request_token();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the authorization URL for the provider.
|
|
||||||
*
|
|
||||||
* $url = $provider->url_authorize();
|
|
||||||
*
|
|
||||||
* @return string
|
|
||||||
*/
|
|
||||||
abstract public function url_authorize();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the access token endpoint for the provider.
|
|
||||||
*
|
|
||||||
* $url = $provider->url_access_token();
|
|
||||||
*
|
|
||||||
* @return string
|
|
||||||
*/
|
|
||||||
abstract public function url_access_token();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Ask for a request token from the OAuth provider.
|
|
||||||
*
|
|
||||||
* $token = $provider->request_token($consumer);
|
|
||||||
*
|
|
||||||
* @param OAuth_Consumer consumer
|
|
||||||
* @param array additional request parameters
|
|
||||||
* @return OAuth_Token_Request
|
|
||||||
* @uses OAuth_Request_Token
|
|
||||||
*/
|
|
||||||
public function request_token(OAuth_Consumer $consumer, array $params = NULL)
|
|
||||||
{
|
|
||||||
// Create a new GET request for a request token with the required parameters
|
|
||||||
$request = OAuth_Request::factory('token', 'GET', $this->url_request_token(), array(
|
|
||||||
'oauth_consumer_key' => $consumer->key,
|
|
||||||
'oauth_callback' => $consumer->callback,
|
|
||||||
));
|
|
||||||
|
|
||||||
if ($params)
|
|
||||||
{
|
|
||||||
// Load user parameters
|
|
||||||
$request->params($params);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Sign the request using only the consumer, no token is available yet
|
|
||||||
$request->sign($this->signature, $consumer);
|
|
||||||
|
|
||||||
// Create a response from the request
|
|
||||||
$response = $request->execute();
|
|
||||||
|
|
||||||
// Store this token somewhere useful
|
|
||||||
return OAuth_Token::factory('request', array(
|
|
||||||
'token' => $response->param('oauth_token'),
|
|
||||||
'secret' => $response->param('oauth_token_secret'),
|
|
||||||
));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get the authorization URL for the request token.
|
|
||||||
*
|
|
||||||
* $this->request->redirect($provider->authorize_url($token));
|
|
||||||
*
|
|
||||||
* @param OAuth_Token_Request token
|
|
||||||
* @param array additional request parameters
|
|
||||||
* @return string
|
|
||||||
*/
|
|
||||||
public function authorize_url(OAuth_Token_Request $token, array $params = NULL)
|
|
||||||
{
|
|
||||||
// Create a new GET request for a request token with the required parameters
|
|
||||||
$request = OAuth_Request::factory('authorize', 'GET', $this->url_authorize(), array(
|
|
||||||
'oauth_token' => $token->token,
|
|
||||||
));
|
|
||||||
|
|
||||||
if ($params)
|
|
||||||
{
|
|
||||||
// Load user parameters
|
|
||||||
$request->params($params);
|
|
||||||
}
|
|
||||||
|
|
||||||
return $request->as_url();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Exchange the request token for an access token.
|
|
||||||
*
|
|
||||||
* $token = $provider->access_token($consumer, $token);
|
|
||||||
*
|
|
||||||
* @param OAuth_Consumer consumer
|
|
||||||
* @param OAuth_Token_Request token
|
|
||||||
* @param array additional request parameters
|
|
||||||
* @return OAuth_Token_Access
|
|
||||||
*/
|
|
||||||
public function access_token(OAuth_Consumer $consumer, OAuth_Token_Request $token, array $params = NULL)
|
|
||||||
{
|
|
||||||
// Create a new GET request for a request token with the required parameters
|
|
||||||
$request = OAuth_Request::factory('access', 'GET', $this->url_access_token(), array(
|
|
||||||
'oauth_consumer_key' => $consumer->key,
|
|
||||||
'oauth_token' => $token->token,
|
|
||||||
'oauth_verifier' => $token->verifier,
|
|
||||||
));
|
|
||||||
|
|
||||||
if ($params)
|
|
||||||
{
|
|
||||||
// Load user parameters
|
|
||||||
$request->params($params);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Sign the request using only the consumer, no token is available yet
|
|
||||||
$request->sign($this->signature, $consumer, $token);
|
|
||||||
|
|
||||||
// Create a response from the request
|
|
||||||
$response = $request->execute();
|
|
||||||
|
|
||||||
// Store this token somewhere useful
|
|
||||||
return OAuth_Token::factory('access', array(
|
|
||||||
'token' => $response->param('oauth_token'),
|
|
||||||
'secret' => $response->param('oauth_token_secret'),
|
|
||||||
));
|
|
||||||
}
|
|
||||||
|
|
||||||
} // End OAuth_Signature
|
|
@ -1,55 +0,0 @@
|
|||||||
<?php defined('SYSPATH') or die('No direct script access.');
|
|
||||||
/**
|
|
||||||
* OAuth Google Provider
|
|
||||||
*
|
|
||||||
* Documents for implementing Google OAuth can be found at
|
|
||||||
* <http://code.google.com/apis/accounts/docs/OAuth.html>.
|
|
||||||
* Individual Google APIs have separate documentation. A complete list is
|
|
||||||
* available at <http://code.google.com/more/>.
|
|
||||||
*
|
|
||||||
* [!!] This class does not implement any Google API. It is only an
|
|
||||||
* implementation of standard OAuth with Google as the service provider.
|
|
||||||
*
|
|
||||||
* @package Kohana/OAuth
|
|
||||||
* @category Provider
|
|
||||||
* @author Kohana Team
|
|
||||||
* @copyright (c) 2010 Kohana Team
|
|
||||||
* @license http://kohanaframework.org/license
|
|
||||||
* @since 3.0.7
|
|
||||||
*/
|
|
||||||
class Kohana_OAuth_Provider_Google extends OAuth_Provider {
|
|
||||||
|
|
||||||
public $name = 'google';
|
|
||||||
|
|
||||||
protected $signature = 'HMAC-SHA1';
|
|
||||||
|
|
||||||
public function url_request_token()
|
|
||||||
{
|
|
||||||
return 'https://www.google.com/accounts/OAuthGetRequestToken';
|
|
||||||
}
|
|
||||||
|
|
||||||
public function url_authorize()
|
|
||||||
{
|
|
||||||
return 'https://www.google.com/accounts/OAuthAuthorizeToken';
|
|
||||||
}
|
|
||||||
|
|
||||||
public function url_access_token()
|
|
||||||
{
|
|
||||||
return 'https://www.google.com/accounts/OAuthGetAccessToken';
|
|
||||||
}
|
|
||||||
|
|
||||||
public function request_token(OAuth_Consumer $consumer, array $params = NULL)
|
|
||||||
{
|
|
||||||
if ( ! isset($params['scope']))
|
|
||||||
{
|
|
||||||
// All request tokens must specify the data scope to access
|
|
||||||
// http://code.google.com/apis/accounts/docs/OAuth.html#prepScope
|
|
||||||
throw new Kohana_OAuth_Exception('Required parameter to not passed: :param', array(
|
|
||||||
':param' => 'scope',
|
|
||||||
));
|
|
||||||
}
|
|
||||||
|
|
||||||
return parent::request_token($consumer, $params);
|
|
||||||
}
|
|
||||||
|
|
||||||
} // End OAuth_Provider_Google
|
|
@ -1,39 +0,0 @@
|
|||||||
<?php defined('SYSPATH') or die('No direct script access.');
|
|
||||||
/**
|
|
||||||
* OAuth Twitter Provider
|
|
||||||
*
|
|
||||||
* Documents for implementing Twitter OAuth can be found at
|
|
||||||
* <http://dev.twitter.com/pages/auth>.
|
|
||||||
*
|
|
||||||
* [!!] This class does not implement the Twitter API. It is only an
|
|
||||||
* implementation of standard OAuth with Twitter as the service provider.
|
|
||||||
*
|
|
||||||
* @package Kohana/OAuth
|
|
||||||
* @category Provider
|
|
||||||
* @author Kohana Team
|
|
||||||
* @copyright (c) 2010 Kohana Team
|
|
||||||
* @license http://kohanaframework.org/license
|
|
||||||
* @since 3.0.7
|
|
||||||
*/
|
|
||||||
class Kohana_OAuth_Provider_Twitter extends OAuth_Provider {
|
|
||||||
|
|
||||||
public $name = 'twitter';
|
|
||||||
|
|
||||||
protected $signature = 'HMAC-SHA1';
|
|
||||||
|
|
||||||
public function url_request_token()
|
|
||||||
{
|
|
||||||
return 'https://api.twitter.com/oauth/request_token';
|
|
||||||
}
|
|
||||||
|
|
||||||
public function url_authorize()
|
|
||||||
{
|
|
||||||
return 'https://api.twitter.com/oauth/authenticate';
|
|
||||||
}
|
|
||||||
|
|
||||||
public function url_access_token()
|
|
||||||
{
|
|
||||||
return 'https://api.twitter.com/oauth/access_token';
|
|
||||||
}
|
|
||||||
|
|
||||||
} // End OAuth_Provider_Twitter
|
|
@ -1,509 +0,0 @@
|
|||||||
<?php defined('SYSPATH') OR die('No direct access allowed.');
|
|
||||||
/**
|
|
||||||
* OAuth Request
|
|
||||||
*
|
|
||||||
* @package Kohana/OAuth
|
|
||||||
* @category Request
|
|
||||||
* @author Kohana Team
|
|
||||||
* @copyright (c) 2010 Kohana Team
|
|
||||||
* @license http://kohanaframework.org/license
|
|
||||||
* @since 3.0.7
|
|
||||||
*/
|
|
||||||
class Kohana_OAuth_Request {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Create a new request object.
|
|
||||||
*
|
|
||||||
* $request = OAuth_Request::factory('token', 'http://example.com/oauth/request_token');
|
|
||||||
*
|
|
||||||
* @param string request type
|
|
||||||
* @param string request URL
|
|
||||||
* @param string request method
|
|
||||||
* @param array request parameters
|
|
||||||
* @return OAuth_Request
|
|
||||||
*/
|
|
||||||
public static function factory($type, $method, $url = NULL, array $params = NULL)
|
|
||||||
{
|
|
||||||
$class = 'OAuth_Request_'.$type;
|
|
||||||
|
|
||||||
return new $class($method, $url, $params);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @var integer connection timeout
|
|
||||||
*/
|
|
||||||
public $timeout = 10;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @var boolean send Authorization header?
|
|
||||||
*/
|
|
||||||
public $send_header = TRUE;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @var string request type name: token, authorize, access, resource
|
|
||||||
*/
|
|
||||||
protected $name;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @var string request method: GET, POST, etc
|
|
||||||
*/
|
|
||||||
protected $method = 'GET';
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @var string request URL
|
|
||||||
*/
|
|
||||||
protected $url;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @var array request parameters
|
|
||||||
*/
|
|
||||||
protected $params = array();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @var array upload parameters
|
|
||||||
*/
|
|
||||||
protected $upload = array();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @var array required parameters
|
|
||||||
*/
|
|
||||||
protected $required = array();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Set the request URL, method, and parameters.
|
|
||||||
*
|
|
||||||
* @param string request method
|
|
||||||
* @param string request URL
|
|
||||||
* @param array request parameters
|
|
||||||
* @uses OAuth::parse_url
|
|
||||||
*/
|
|
||||||
public function __construct($method, $url, array $params = NULL)
|
|
||||||
{
|
|
||||||
if ($method)
|
|
||||||
{
|
|
||||||
// Set the request method
|
|
||||||
$this->method = strtoupper($method);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Separate the URL and query string, which will be used as additional
|
|
||||||
// default parameters
|
|
||||||
list ($url, $default) = OAuth::parse_url($url);
|
|
||||||
|
|
||||||
// Set the request URL
|
|
||||||
$this->url = $url;
|
|
||||||
|
|
||||||
if ($default)
|
|
||||||
{
|
|
||||||
// Set the default parameters
|
|
||||||
$this->params($default);
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($params)
|
|
||||||
{
|
|
||||||
// Set the request parameters
|
|
||||||
$this->params($params);
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($this->required('oauth_version') AND ! isset($this->params['oauth_version']))
|
|
||||||
{
|
|
||||||
// Set the version of this request
|
|
||||||
$this->params['oauth_version'] = OAuth::$version;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($this->required('oauth_timestamp') AND ! isset($this->params['oauth_timestamp']))
|
|
||||||
{
|
|
||||||
// Set the timestamp of this request
|
|
||||||
$this->params['oauth_timestamp'] = $this->timestamp();
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($this->required('oauth_nonce') AND ! isset($this->params['oauth_nonce']))
|
|
||||||
{
|
|
||||||
// Set the unique nonce of this request
|
|
||||||
$this->params['oauth_nonce'] = $this->nonce();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Return the value of any protected class variable.
|
|
||||||
*
|
|
||||||
* // Get the request parameters
|
|
||||||
* $params = $request->params;
|
|
||||||
*
|
|
||||||
* // Get the request URL
|
|
||||||
* $url = $request->url;
|
|
||||||
*
|
|
||||||
* @param string variable name
|
|
||||||
* @return mixed
|
|
||||||
*/
|
|
||||||
public function __get($key)
|
|
||||||
{
|
|
||||||
return $this->$key;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Generates the UNIX timestamp for a request.
|
|
||||||
*
|
|
||||||
* $time = $request->timestamp();
|
|
||||||
*
|
|
||||||
* [!!] This method implements [OAuth 1.0 Spec 8](http://oauth.net/core/1.0/#rfc.section.8).
|
|
||||||
*
|
|
||||||
* @return integer
|
|
||||||
*/
|
|
||||||
public function timestamp()
|
|
||||||
{
|
|
||||||
return time();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Generates the nonce for a request.
|
|
||||||
*
|
|
||||||
* $nonce = $request->nonce();
|
|
||||||
*
|
|
||||||
* [!!] This method implements [OAuth 1.0 Spec 8](http://oauth.net/core/1.0/#rfc.section.8).
|
|
||||||
*
|
|
||||||
* @return string
|
|
||||||
* @uses Text::random
|
|
||||||
*/
|
|
||||||
public function nonce()
|
|
||||||
{
|
|
||||||
return Text::random('alnum', 40);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get the base signature string for a request.
|
|
||||||
*
|
|
||||||
* $base = $request->base_string();
|
|
||||||
*
|
|
||||||
* [!!] This method implements [OAuth 1.0 Spec A5.1](http://oauth.net/core/1.0/#rfc.section.A.5.1).
|
|
||||||
*
|
|
||||||
* @param OAuth_Request request to sign
|
|
||||||
* @return string
|
|
||||||
* @uses OAuth::urlencode
|
|
||||||
* @uses OAuth::normalize_params
|
|
||||||
*/
|
|
||||||
public function base_string()
|
|
||||||
{
|
|
||||||
$url = $this->url;
|
|
||||||
|
|
||||||
// Get the request parameters
|
|
||||||
$params = array_diff_key($this->params, $this->upload);
|
|
||||||
|
|
||||||
// "oauth_signature" is never included in the base string!
|
|
||||||
unset($params['oauth_signature']);
|
|
||||||
|
|
||||||
// method & url & sorted-parameters
|
|
||||||
return implode('&', array(
|
|
||||||
$this->method,
|
|
||||||
OAuth::urlencode($url),
|
|
||||||
OAuth::urlencode(OAuth::normalize_params($params)),
|
|
||||||
));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Parameter getter and setter. Setting the value to `NULL` will remove it.
|
|
||||||
*
|
|
||||||
* // Set the "oauth_consumer_key" to a new value
|
|
||||||
* $request->param('oauth_consumer_key', $key);
|
|
||||||
*
|
|
||||||
* // Get the "oauth_consumer_key" value
|
|
||||||
* $key = $request->param('oauth_consumer_key');
|
|
||||||
*
|
|
||||||
* @param string parameter name
|
|
||||||
* @param mixed parameter value
|
|
||||||
* @param boolean allow duplicates?
|
|
||||||
* @return mixed when getting
|
|
||||||
* @return $this when setting
|
|
||||||
* @uses Arr::get
|
|
||||||
*/
|
|
||||||
public function param($name, $value = NULL, $duplicate = FALSE)
|
|
||||||
{
|
|
||||||
if ($value === NULL)
|
|
||||||
{
|
|
||||||
// Get the parameter
|
|
||||||
return Arr::get($this->params, $name);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (isset($this->params[$name]) AND $duplicate)
|
|
||||||
{
|
|
||||||
if ( ! is_array($this->params[$name]))
|
|
||||||
{
|
|
||||||
// Convert the parameter into an array
|
|
||||||
$this->params[$name] = array($this->params[$name]);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Add the duplicate value
|
|
||||||
$this->params[$name][] = $value;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// Set the parameter value
|
|
||||||
$this->params[$name] = $value;
|
|
||||||
}
|
|
||||||
|
|
||||||
return $this;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Set multiple parameters.
|
|
||||||
*
|
|
||||||
* $request->params($params);
|
|
||||||
*
|
|
||||||
* @param array parameters
|
|
||||||
* @param boolean allow duplicates?
|
|
||||||
* @return $this
|
|
||||||
* @uses OAuth_Request::param
|
|
||||||
*/
|
|
||||||
public function params(array $params, $duplicate = FALSE)
|
|
||||||
{
|
|
||||||
foreach ($params as $name => $value)
|
|
||||||
{
|
|
||||||
$this->param($name, $value, $duplicate);
|
|
||||||
}
|
|
||||||
|
|
||||||
return $this;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Upload getter and setter. Setting the value to `NULL` will remove it.
|
|
||||||
*
|
|
||||||
* // Set the "image" file path for uploading
|
|
||||||
* $request->upload('image', $file_path);
|
|
||||||
*
|
|
||||||
* // Get the "image" file path
|
|
||||||
* $key = $request->param('oauth_consumer_key');
|
|
||||||
*
|
|
||||||
* @param string upload name
|
|
||||||
* @param mixed upload file path
|
|
||||||
* @return mixed when getting
|
|
||||||
* @return $this when setting
|
|
||||||
* @uses OAuth_Request::param
|
|
||||||
*/
|
|
||||||
public function upload($name, $value = NULL)
|
|
||||||
{
|
|
||||||
if ($value !== NULL)
|
|
||||||
{
|
|
||||||
// This is an upload parameter
|
|
||||||
$this->upload[$name] = TRUE;
|
|
||||||
|
|
||||||
// Get the mime type of the image
|
|
||||||
$mime = File::mime($value);
|
|
||||||
|
|
||||||
// Format the image path for CURL
|
|
||||||
$value = "@{$value};type={$mime}";
|
|
||||||
}
|
|
||||||
|
|
||||||
return $this->param($name, $value, FALSE);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get and set required parameters.
|
|
||||||
*
|
|
||||||
* $request->required($field, $value);
|
|
||||||
*
|
|
||||||
* @param string parameter name
|
|
||||||
* @param boolean field value
|
|
||||||
* @return boolean when getting
|
|
||||||
* @return $this when setting
|
|
||||||
*/
|
|
||||||
public function required($param, $value = NULL)
|
|
||||||
{
|
|
||||||
if ($value === NULL)
|
|
||||||
{
|
|
||||||
// Get the current status
|
|
||||||
return ! empty($this->required[$param]);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Change the requirement value
|
|
||||||
$this->required[$param] = (boolean) $value;
|
|
||||||
|
|
||||||
return $this;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Convert the request parameters into an `Authorization` header.
|
|
||||||
*
|
|
||||||
* $header = $request->as_header();
|
|
||||||
*
|
|
||||||
* [!!] This method implements [OAuth 1.0 Spec 5.4.1](http://oauth.net/core/1.0/#rfc.section.5.4.1).
|
|
||||||
*
|
|
||||||
* @return string
|
|
||||||
*/
|
|
||||||
public function as_header()
|
|
||||||
{
|
|
||||||
$header = array();
|
|
||||||
|
|
||||||
foreach ($this->params as $name => $value)
|
|
||||||
{
|
|
||||||
if (strpos($name, 'oauth_') === 0)
|
|
||||||
{
|
|
||||||
// OAuth Spec 5.4.1
|
|
||||||
// "Parameter names and values are encoded per Parameter Encoding [RFC 3986]."
|
|
||||||
$header[] = OAuth::urlencode($name).'="'.OAuth::urlencode($value).'"';
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return 'OAuth '.implode(', ', $header);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Convert the request parameters into a query string, suitable for GET and
|
|
||||||
* POST requests.
|
|
||||||
*
|
|
||||||
* $query = $request->as_query();
|
|
||||||
*
|
|
||||||
* [!!] This method implements [OAuth 1.0 Spec 5.2 (2,3)](http://oauth.net/core/1.0/#rfc.section.5.2).
|
|
||||||
*
|
|
||||||
* @param boolean include oauth parameters?
|
|
||||||
* @param boolean return a normalized string?
|
|
||||||
* @return string
|
|
||||||
*/
|
|
||||||
public function as_query($include_oauth = NULL, $as_string = TRUE)
|
|
||||||
{
|
|
||||||
if ($include_oauth === NULL)
|
|
||||||
{
|
|
||||||
// If we are sending a header, OAuth parameters should not be
|
|
||||||
// included in the query string.
|
|
||||||
$include_oauth = ! $this->send_header;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($include_oauth)
|
|
||||||
{
|
|
||||||
$params = $this->params;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
$params = array();
|
|
||||||
foreach ($this->params as $name => $value)
|
|
||||||
{
|
|
||||||
if (strpos($name, 'oauth_') !== 0)
|
|
||||||
{
|
|
||||||
// This is not an OAuth parameter
|
|
||||||
$params[$name] = $value;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return $as_string ? OAuth::normalize_params($params) : $params;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Return the entire request URL with the parameters as a GET string.
|
|
||||||
*
|
|
||||||
* $url = $request->as_url();
|
|
||||||
*
|
|
||||||
* @return string
|
|
||||||
* @uses OAuth_Request::as_query
|
|
||||||
*/
|
|
||||||
public function as_url()
|
|
||||||
{
|
|
||||||
return $this->url.'?'.$this->as_query(TRUE);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Sign the request, setting the `oauth_signature_method` and `oauth_signature`.
|
|
||||||
*
|
|
||||||
* @param OAuth_Signature signature
|
|
||||||
* @param OAuth_Consumer consumer
|
|
||||||
* @param OAuth_Token token
|
|
||||||
* @return $this
|
|
||||||
* @uses OAuth_Signature::sign
|
|
||||||
*/
|
|
||||||
public function sign(OAuth_Signature $signature, OAuth_Consumer $consumer, OAuth_Token $token = NULL)
|
|
||||||
{
|
|
||||||
// Create a new signature class from the method
|
|
||||||
$this->param('oauth_signature_method', $signature->name);
|
|
||||||
|
|
||||||
// Sign the request using the consumer and token
|
|
||||||
$this->param('oauth_signature', $signature->sign($this, $consumer, $token));
|
|
||||||
|
|
||||||
return $this;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Checks that all required request parameters have been set. Throws an
|
|
||||||
* exception if any parameters are missing.
|
|
||||||
*
|
|
||||||
* try
|
|
||||||
* {
|
|
||||||
* $request->check();
|
|
||||||
* }
|
|
||||||
* catch (OAuth_Exception $e)
|
|
||||||
* {
|
|
||||||
* // Request has missing parameters
|
|
||||||
* }
|
|
||||||
*
|
|
||||||
* @return TRUE
|
|
||||||
* @throws Kohana_OAuth_Exception
|
|
||||||
*/
|
|
||||||
public function check()
|
|
||||||
{
|
|
||||||
foreach ($this->required as $param => $required)
|
|
||||||
{
|
|
||||||
if ($required AND ! isset($this->params[$param]))
|
|
||||||
{
|
|
||||||
throw new Kohana_OAuth_Exception('Request to :url requires missing parameter ":param"', array(
|
|
||||||
':url' => $this->url,
|
|
||||||
':param' => $param,
|
|
||||||
));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return TRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Execute the request and return a response.
|
|
||||||
*
|
|
||||||
* @param array additional cURL options
|
|
||||||
* @return string request response body
|
|
||||||
* @uses OAuth_Request::check
|
|
||||||
* @uses Arr::get
|
|
||||||
* @uses Remote::get
|
|
||||||
*/
|
|
||||||
public function execute(array $options = NULL)
|
|
||||||
{
|
|
||||||
// Check that all required fields are set
|
|
||||||
$this->check();
|
|
||||||
|
|
||||||
// Get the URL of the request
|
|
||||||
$url = $this->url;
|
|
||||||
|
|
||||||
if ( ! isset($options[CURLOPT_CONNECTTIMEOUT]))
|
|
||||||
{
|
|
||||||
// Use the request default timeout
|
|
||||||
$options[CURLOPT_CONNECTTIMEOUT] = $this->timeout;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($this->send_header)
|
|
||||||
{
|
|
||||||
// Get the the current headers
|
|
||||||
$headers = Arr::get($options, CURLOPT_HTTPHEADER, array());
|
|
||||||
|
|
||||||
// Add the Authorization header
|
|
||||||
$headers[] = 'Authorization: '.$this->as_header();
|
|
||||||
|
|
||||||
// Store the new headers
|
|
||||||
$options[CURLOPT_HTTPHEADER] = $headers;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($this->method === 'POST')
|
|
||||||
{
|
|
||||||
// Send the request as a POST
|
|
||||||
$options[CURLOPT_POST] = TRUE;
|
|
||||||
|
|
||||||
if ($post = $this->as_query(NULL, empty($this->upload)))
|
|
||||||
{
|
|
||||||
// Attach the post fields to the request
|
|
||||||
$options[CURLOPT_POSTFIELDS] = $post;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
elseif ($query = $this->as_query())
|
|
||||||
{
|
|
||||||
// Append the parameters to the query string
|
|
||||||
$url = "{$url}?{$query}";
|
|
||||||
}
|
|
||||||
|
|
||||||
return Remote::get($url, $options);
|
|
||||||
}
|
|
||||||
|
|
||||||
} // End OAuth_Request
|
|
@ -1,32 +0,0 @@
|
|||||||
<?php defined('SYSPATH') OR die('No direct access allowed.');
|
|
||||||
/**
|
|
||||||
* OAuth Access Request
|
|
||||||
*
|
|
||||||
* @package Kohana/OAuth
|
|
||||||
* @category Request
|
|
||||||
* @author Kohana Team
|
|
||||||
* @copyright (c) 2010 Kohana Team
|
|
||||||
* @license http://kohanaframework.org/license
|
|
||||||
* @since 3.0.7
|
|
||||||
*/
|
|
||||||
class Kohana_OAuth_Request_Access extends OAuth_Request {
|
|
||||||
|
|
||||||
protected $name = 'access';
|
|
||||||
|
|
||||||
protected $required = array(
|
|
||||||
'oauth_consumer_key' => TRUE,
|
|
||||||
'oauth_token' => TRUE,
|
|
||||||
'oauth_signature_method' => TRUE,
|
|
||||||
'oauth_signature' => TRUE,
|
|
||||||
'oauth_timestamp' => TRUE,
|
|
||||||
'oauth_nonce' => TRUE,
|
|
||||||
'oauth_verifier' => TRUE,
|
|
||||||
'oauth_version' => TRUE,
|
|
||||||
);
|
|
||||||
|
|
||||||
public function execute(array $options = NULL)
|
|
||||||
{
|
|
||||||
return OAuth_Response::factory(parent::execute($options));
|
|
||||||
}
|
|
||||||
|
|
||||||
} // End OAuth_Request_Access
|
|
@ -1,26 +0,0 @@
|
|||||||
<?php defined('SYSPATH') OR die('No direct access allowed.');
|
|
||||||
/**
|
|
||||||
* OAuth Authorization Request
|
|
||||||
*
|
|
||||||
* @package Kohana/OAuth
|
|
||||||
* @category Request
|
|
||||||
* @author Kohana Team
|
|
||||||
* @copyright (c) 2010 Kohana Team
|
|
||||||
* @license http://kohanaframework.org/license
|
|
||||||
* @since 3.0.7
|
|
||||||
*/
|
|
||||||
class Kohana_OAuth_Request_Authorize extends OAuth_Request {
|
|
||||||
|
|
||||||
protected $name = 'request';
|
|
||||||
|
|
||||||
// http://oauth.net/core/1.0/#rfc.section.6.2.1
|
|
||||||
protected $required = array(
|
|
||||||
'oauth_token' => TRUE,
|
|
||||||
);
|
|
||||||
|
|
||||||
public function execute(array $options = NULL)
|
|
||||||
{
|
|
||||||
return Request::instance()->redirect($this->as_url());
|
|
||||||
}
|
|
||||||
|
|
||||||
} // End OAuth_Request_Authorize
|
|
@ -1,16 +0,0 @@
|
|||||||
<?php defined('SYSPATH') OR die('No direct access allowed.');
|
|
||||||
/**
|
|
||||||
* OAuth Credentials Request
|
|
||||||
*
|
|
||||||
* @package Kohana/OAuth
|
|
||||||
* @category Request
|
|
||||||
* @author Kohana Team
|
|
||||||
* @copyright (c) 2010 Kohana Team
|
|
||||||
* @license http://kohanaframework.org/license
|
|
||||||
* @since 3.0.7
|
|
||||||
*/
|
|
||||||
class Kohana_OAuth_Request_Credentials extends OAuth_Request {
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
} // End OAuth_Request_Credentials
|
|
@ -1,27 +0,0 @@
|
|||||||
<?php defined('SYSPATH') OR die('No direct access allowed.');
|
|
||||||
/**
|
|
||||||
* OAuth Resource Request
|
|
||||||
*
|
|
||||||
* @package Kohana/OAuth
|
|
||||||
* @category Request
|
|
||||||
* @author Kohana Team
|
|
||||||
* @copyright (c) 2010 Kohana Team
|
|
||||||
* @license http://kohanaframework.org/license
|
|
||||||
* @since 3.0.7
|
|
||||||
*/
|
|
||||||
class Kohana_OAuth_Request_Resource extends OAuth_Request {
|
|
||||||
|
|
||||||
protected $name = 'resource';
|
|
||||||
|
|
||||||
// http://oauth.net/core/1.0/#rfc.section.7
|
|
||||||
protected $required = array(
|
|
||||||
'oauth_consumer_key' => TRUE,
|
|
||||||
'oauth_token' => TRUE,
|
|
||||||
'oauth_signature_method' => TRUE,
|
|
||||||
'oauth_signature' => TRUE,
|
|
||||||
'oauth_timestamp' => TRUE,
|
|
||||||
'oauth_nonce' => TRUE,
|
|
||||||
'oauth_version' => TRUE,
|
|
||||||
);
|
|
||||||
|
|
||||||
} // End OAuth_Request_Resource
|
|
@ -1,32 +0,0 @@
|
|||||||
<?php defined('SYSPATH') or die('No direct script access.');
|
|
||||||
/**
|
|
||||||
* OAuth Token Request
|
|
||||||
*
|
|
||||||
* @package Kohana/OAuth
|
|
||||||
* @category Request
|
|
||||||
* @author Kohana Team
|
|
||||||
* @copyright (c) 2010 Kohana Team
|
|
||||||
* @license http://kohanaframework.org/license
|
|
||||||
* @since 3.0.7
|
|
||||||
*/
|
|
||||||
class Kohana_OAuth_Request_Token extends OAuth_Request {
|
|
||||||
|
|
||||||
protected $name = 'request';
|
|
||||||
|
|
||||||
// http://oauth.net/core/1.0/#rfc.section.6.3.1
|
|
||||||
protected $required = array(
|
|
||||||
'oauth_callback' => TRUE,
|
|
||||||
'oauth_consumer_key' => TRUE,
|
|
||||||
'oauth_signature_method' => TRUE,
|
|
||||||
'oauth_signature' => TRUE,
|
|
||||||
'oauth_timestamp' => TRUE,
|
|
||||||
'oauth_nonce' => TRUE,
|
|
||||||
'oauth_version' => TRUE,
|
|
||||||
);
|
|
||||||
|
|
||||||
public function execute(array $options = NULL)
|
|
||||||
{
|
|
||||||
return OAuth_Response::factory(parent::execute($options));
|
|
||||||
}
|
|
||||||
|
|
||||||
} // End OAuth_Request_Token
|
|
@ -1,51 +0,0 @@
|
|||||||
<?php defined('SYSPATH') OR die('No direct access allowed.');
|
|
||||||
/**
|
|
||||||
* OAuth Response
|
|
||||||
*
|
|
||||||
* @package Kohana/OAuth
|
|
||||||
* @category Base
|
|
||||||
* @author Kohana Team
|
|
||||||
* @copyright (c) 2010 Kohana Team
|
|
||||||
* @license http://kohanaframework.org/license
|
|
||||||
* @since 3.0.7
|
|
||||||
*/
|
|
||||||
class Kohana_OAuth_Response {
|
|
||||||
|
|
||||||
public static function factory($body)
|
|
||||||
{
|
|
||||||
return new OAuth_Response($body);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @var array response parameters
|
|
||||||
*/
|
|
||||||
protected $params = array();
|
|
||||||
|
|
||||||
public function __construct($body = NULL)
|
|
||||||
{
|
|
||||||
if ($body)
|
|
||||||
{
|
|
||||||
$this->params = OAuth::parse_params($body);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Return the value of any protected class variable.
|
|
||||||
*
|
|
||||||
* // Get the response parameters
|
|
||||||
* $params = $response->params;
|
|
||||||
*
|
|
||||||
* @param string variable name
|
|
||||||
* @return mixed
|
|
||||||
*/
|
|
||||||
public function __get($key)
|
|
||||||
{
|
|
||||||
return $this->$key;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function param($name, $default = NULL)
|
|
||||||
{
|
|
||||||
return Arr::get($this->params, $name, $default);
|
|
||||||
}
|
|
||||||
|
|
||||||
} // End OAuth_Response
|
|
@ -1,14 +0,0 @@
|
|||||||
<?php defined('SYSPATH') OR die('No direct access allowed.');
|
|
||||||
/**
|
|
||||||
* OAuth Server
|
|
||||||
*
|
|
||||||
* @package Kohana/OAuth
|
|
||||||
* @category Server
|
|
||||||
* @author Kohana Team
|
|
||||||
* @copyright (c) 2010 Kohana Team
|
|
||||||
* @license http://kohanaframework.org/license
|
|
||||||
* @since 3.0.7
|
|
||||||
*/
|
|
||||||
abstract class Kohana_OAuth_Server {
|
|
||||||
|
|
||||||
} // End OAuth_Server
|
|
@ -1,77 +0,0 @@
|
|||||||
<?php defined('SYSPATH') OR die('No direct access allowed.');
|
|
||||||
/**
|
|
||||||
* OAuth Signature
|
|
||||||
*
|
|
||||||
* @package Kohana/OAuth
|
|
||||||
* @category Signature
|
|
||||||
* @author Kohana Team
|
|
||||||
* @copyright (c) 2010 Kohana Team
|
|
||||||
* @license http://kohanaframework.org/license
|
|
||||||
* @since 3.0.7
|
|
||||||
*/
|
|
||||||
abstract class Kohana_OAuth_Signature {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Create a new signature object by name.
|
|
||||||
*
|
|
||||||
* $signature = OAuth_Signature::factory('HMAC-SHA1');
|
|
||||||
*
|
|
||||||
* @param string signature name: HMAC-SHA1, PLAINTEXT, etc
|
|
||||||
* @param array signature options
|
|
||||||
* @return OAuth_Signature
|
|
||||||
*/
|
|
||||||
public static function factory($name, array $options = NULL)
|
|
||||||
{
|
|
||||||
// Create the class name as a base of this class
|
|
||||||
$class = 'OAuth_Signature_'.str_replace('-', '_', $name);
|
|
||||||
|
|
||||||
return new $class($options);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @var string signature name: HMAC-SHA1, PLAINTEXT, etc
|
|
||||||
*/
|
|
||||||
protected $name;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Return the value of any protected class variables.
|
|
||||||
*
|
|
||||||
* $name = $signature->name;
|
|
||||||
*
|
|
||||||
* @param string variable name
|
|
||||||
* @return mixed
|
|
||||||
*/
|
|
||||||
public function __get($key)
|
|
||||||
{
|
|
||||||
return $this->$key;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get a signing key from a consumer and token.
|
|
||||||
*
|
|
||||||
* $key = $signature->key($consumer, $token);
|
|
||||||
*
|
|
||||||
* [!!] This method implements the signing key of [OAuth 1.0 Spec 9](http://oauth.net/core/1.0/#rfc.section.9).
|
|
||||||
*
|
|
||||||
* @param OAuth_Consumer consumer
|
|
||||||
* @param OAuth_Token token
|
|
||||||
* @return string
|
|
||||||
* @uses OAuth::urlencode
|
|
||||||
*/
|
|
||||||
public function key(OAuth_Consumer $consumer, OAuth_Token $token = NULL)
|
|
||||||
{
|
|
||||||
$key = OAuth::urlencode($consumer->secret).'&';
|
|
||||||
|
|
||||||
if ($token)
|
|
||||||
{
|
|
||||||
$key .= OAuth::urlencode($token->secret);
|
|
||||||
}
|
|
||||||
|
|
||||||
return $key;
|
|
||||||
}
|
|
||||||
|
|
||||||
abstract public function sign(OAuth_Request $request, OAuth_Consumer $consumer, OAuth_Token $token = NULL);
|
|
||||||
|
|
||||||
abstract public function verify($signature, OAuth_Request $request, OAuth_Consumer $consumer, OAuth_Token $token = NULL);
|
|
||||||
|
|
||||||
} // End OAuth_Signature
|
|
@ -1,68 +0,0 @@
|
|||||||
<?php defined('SYSPATH') or die('No direct script access.');
|
|
||||||
/**
|
|
||||||
* The HMAC-SHA1 signature provides secure signing using the HMAC-SHA1
|
|
||||||
* algorithm as defined by [RFC2104](http://tools.ietf.org/html/rfc2104).
|
|
||||||
* It uses [OAuth_Request::base_string] as the text and [OAuth_Signature::key]
|
|
||||||
* as the signing key.
|
|
||||||
*
|
|
||||||
* @package Kohana/OAuth
|
|
||||||
* @category Signature
|
|
||||||
* @author Kohana Team
|
|
||||||
* @copyright (c) 2010 Kohana Team
|
|
||||||
* @license http://kohanaframework.org/license
|
|
||||||
* @since 3.0.7
|
|
||||||
*/
|
|
||||||
class Kohana_OAuth_Signature_HMAC_SHA1 extends OAuth_Signature {
|
|
||||||
|
|
||||||
protected $name = 'HMAC-SHA1';
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Generate a signed hash of the base string using the consumer and token
|
|
||||||
* as the signing key.
|
|
||||||
*
|
|
||||||
* $sig = $signature->sign($request, $consumer, $token);
|
|
||||||
*
|
|
||||||
* [!!] This method implements [OAuth 1.0 Spec 9.2.1](http://oauth.net/core/1.0/#rfc.section.9.2.1).
|
|
||||||
*
|
|
||||||
* @param OAuth_Request request
|
|
||||||
* @param OAuth_Consumer consumer
|
|
||||||
* @param OAuth_Token token
|
|
||||||
* @return string
|
|
||||||
* @uses OAuth_Signature::key
|
|
||||||
* @uses OAuth_Request::base_string
|
|
||||||
*/
|
|
||||||
public function sign(OAuth_Request $request, OAuth_Consumer $consumer, OAuth_Token $token = NULL)
|
|
||||||
{
|
|
||||||
// Get the signing key
|
|
||||||
$key = $this->key($consumer, $token);
|
|
||||||
|
|
||||||
// Get the base string for the signature
|
|
||||||
$base_string = $request->base_string();
|
|
||||||
|
|
||||||
// Sign the base string using the key
|
|
||||||
return base64_encode(hash_hmac('sha1', $base_string, $key, TRUE));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Verify a HMAC-SHA1 signature.
|
|
||||||
*
|
|
||||||
* if ( ! $signature->verify($signature, $request, $consumer, $token))
|
|
||||||
* {
|
|
||||||
* throw new Kohana_OAuth_Exception('Failed to verify signature');
|
|
||||||
* }
|
|
||||||
*
|
|
||||||
* [!!] This method implements [OAuth 1.0 Spec 9.2.2](http://oauth.net/core/1.0/#rfc.section.9.2.2).
|
|
||||||
*
|
|
||||||
* @param string signature to verify
|
|
||||||
* @param OAuth_Request request
|
|
||||||
* @param OAuth_Consumer consumer
|
|
||||||
* @param OAuth_Token token
|
|
||||||
* @return boolean
|
|
||||||
* @uses OAuth_Signature_HMAC_SHA1::sign
|
|
||||||
*/
|
|
||||||
public function verify($signature, OAuth_Request $request, OAuth_Consumer $consumer, OAuth_Token $token = NULL)
|
|
||||||
{
|
|
||||||
return $signature === $this->sign($request, $consumer, $token);
|
|
||||||
}
|
|
||||||
|
|
||||||
} // End OAuth_Signature_HMAC_SHA1
|
|
@ -1,57 +0,0 @@
|
|||||||
<?php defined('SYSPATH') or die('No direct script access.');
|
|
||||||
/**
|
|
||||||
* The PLAINTEXT signature does not provide any security protection and should
|
|
||||||
* only be used over a secure channel such as HTTPS.
|
|
||||||
*
|
|
||||||
* @package Kohana/OAuth
|
|
||||||
* @category Signature
|
|
||||||
* @author Kohana Team
|
|
||||||
* @copyright (c) 2010 Kohana Team
|
|
||||||
* @license http://kohanaframework.org/license
|
|
||||||
* @since 3.0.7
|
|
||||||
*/
|
|
||||||
class Kohana_OAuth_Signature_PLAINTEXT extends OAuth_Signature {
|
|
||||||
|
|
||||||
protected $name = 'PLAINTEXT';
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Generate a plaintext signature for the request _without_ the base string.
|
|
||||||
*
|
|
||||||
* $sig = $signature->sign($request, $consumer, $token);
|
|
||||||
*
|
|
||||||
* [!!] This method implements [OAuth 1.0 Spec 9.4.1](http://oauth.net/core/1.0/#rfc.section.9.4.1).
|
|
||||||
*
|
|
||||||
* @param OAuth_Request request
|
|
||||||
* @param OAuth_Consumer consumer
|
|
||||||
* @param OAuth_Token token
|
|
||||||
* @return $this
|
|
||||||
*/
|
|
||||||
public function sign(OAuth_Request $request, OAuth_Consumer $consumer, OAuth_Token $token = NULL)
|
|
||||||
{
|
|
||||||
// Use the signing key as the signature
|
|
||||||
return $this->key($consumer, $token);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Verify a plaintext signature.
|
|
||||||
*
|
|
||||||
* if ( ! $signature->verify($signature, $request, $consumer, $token))
|
|
||||||
* {
|
|
||||||
* throw new Kohana_OAuth_Exception('Failed to verify signature');
|
|
||||||
* }
|
|
||||||
*
|
|
||||||
* [!!] This method implements [OAuth 1.0 Spec 9.4.2](http://oauth.net/core/1.0/#rfc.section.9.4.2).
|
|
||||||
*
|
|
||||||
* @param string signature to verify
|
|
||||||
* @param OAuth_Request request
|
|
||||||
* @param OAuth_Consumer consumer
|
|
||||||
* @param OAuth_Token token
|
|
||||||
* @return boolean
|
|
||||||
* @uses OAuth_Signature_PLAINTEXT::sign
|
|
||||||
*/
|
|
||||||
public function verify($signature, OAuth_Request $request, OAuth_Consumer $consumer, OAuth_Token $token = NULL)
|
|
||||||
{
|
|
||||||
return $signature === $this->key($consumer, $token);
|
|
||||||
}
|
|
||||||
|
|
||||||
} // End OAuth_Signature_PLAINTEXT
|
|
@ -1,94 +0,0 @@
|
|||||||
<?php defined('SYSPATH') OR die('No direct access allowed.');
|
|
||||||
/**
|
|
||||||
* OAuth Token
|
|
||||||
*
|
|
||||||
* @package Kohana/OAuth
|
|
||||||
* @category Token
|
|
||||||
* @author Kohana Team
|
|
||||||
* @copyright (c) 2010 Kohana Team
|
|
||||||
* @license http://kohanaframework.org/license
|
|
||||||
* @since 3.0.7
|
|
||||||
*/
|
|
||||||
abstract class Kohana_OAuth_Token {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Create a new token object.
|
|
||||||
*
|
|
||||||
* $token = OAuth_Token::factory($name);
|
|
||||||
*
|
|
||||||
* @param string token type
|
|
||||||
* @param array token options
|
|
||||||
* @return OAuth_Token
|
|
||||||
*/
|
|
||||||
public static function factory($name, array $options = NULL)
|
|
||||||
{
|
|
||||||
$class = 'OAuth_Token_'.$name;
|
|
||||||
|
|
||||||
return new $class($options);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @var string token type name: request, access
|
|
||||||
*/
|
|
||||||
protected $name;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @var string token key
|
|
||||||
*/
|
|
||||||
protected $token;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @var string token secret
|
|
||||||
*/
|
|
||||||
protected $secret;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Sets the token and secret values.
|
|
||||||
*
|
|
||||||
* @param array token options
|
|
||||||
* @return void
|
|
||||||
*/
|
|
||||||
public function __construct(array $options = NULL)
|
|
||||||
{
|
|
||||||
if ( ! isset($options['token']))
|
|
||||||
{
|
|
||||||
throw new Kohana_OAuth_Exception('Required option not passed: :option',
|
|
||||||
array(':option' => 'token'));
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( ! isset($options['secret']))
|
|
||||||
{
|
|
||||||
throw new Kohana_OAuth_Exception('Required option not passed: :option',
|
|
||||||
array(':option' => 'secret'));
|
|
||||||
}
|
|
||||||
|
|
||||||
$this->token = $options['token'];
|
|
||||||
|
|
||||||
$this->secret = $options['secret'];
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Return the value of any protected class variable.
|
|
||||||
*
|
|
||||||
* // Get the token secret
|
|
||||||
* $secret = $token->secret;
|
|
||||||
*
|
|
||||||
* @param string variable name
|
|
||||||
* @return mixed
|
|
||||||
*/
|
|
||||||
public function __get($key)
|
|
||||||
{
|
|
||||||
return $this->$key;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the token key.
|
|
||||||
*
|
|
||||||
* @return string
|
|
||||||
*/
|
|
||||||
public function __toString()
|
|
||||||
{
|
|
||||||
return (string) $this->token;
|
|
||||||
}
|
|
||||||
|
|
||||||
} // End OAuth_Token
|
|
@ -1,16 +0,0 @@
|
|||||||
<?php defined('SYSPATH') or die('No direct script access.');
|
|
||||||
/**
|
|
||||||
* OAuth Access Token
|
|
||||||
*
|
|
||||||
* @package Kohana/OAuth
|
|
||||||
* @category Token
|
|
||||||
* @author Kohana Team
|
|
||||||
* @copyright (c) 2010 Kohana Team
|
|
||||||
* @license http://kohanaframework.org/license
|
|
||||||
* @since 3.0.7
|
|
||||||
*/
|
|
||||||
class Kohana_OAuth_Token_Access extends OAuth_Token {
|
|
||||||
|
|
||||||
protected $name = 'access';
|
|
||||||
|
|
||||||
} // End OAuth_Token_Access
|
|
@ -1,36 +0,0 @@
|
|||||||
<?php defined('SYSPATH') or die('No direct script access.');
|
|
||||||
/**
|
|
||||||
* OAuth Request Token
|
|
||||||
*
|
|
||||||
* @package Kohana/OAuth
|
|
||||||
* @category Token
|
|
||||||
* @author Kohana Team
|
|
||||||
* @copyright (c) 2010 Kohana Team
|
|
||||||
* @license http://kohanaframework.org/license
|
|
||||||
* @since 3.0.7
|
|
||||||
*/
|
|
||||||
class Kohana_OAuth_Token_Request extends OAuth_Token {
|
|
||||||
|
|
||||||
protected $name = 'request';
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @var string request token verifier
|
|
||||||
*/
|
|
||||||
protected $verifier;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Change the token verifier.
|
|
||||||
*
|
|
||||||
* $token->verifier($key);
|
|
||||||
*
|
|
||||||
* @param string new verifier
|
|
||||||
* @return $this
|
|
||||||
*/
|
|
||||||
public function verifier($verifier)
|
|
||||||
{
|
|
||||||
$this->verifier = $verifier;
|
|
||||||
|
|
||||||
return $this;
|
|
||||||
}
|
|
||||||
|
|
||||||
} // End OAuth_Token_Request
|
|
@ -1,3 +0,0 @@
|
|||||||
<?php defined('SYSPATH') or die('No direct script access.');
|
|
||||||
|
|
||||||
abstract class OAuth_Provider extends Kohana_OAuth_Provider { }
|
|
@ -1,3 +0,0 @@
|
|||||||
<?php defined('SYSPATH') or die('No direct script access.');
|
|
||||||
|
|
||||||
class OAuth_Provider_Google extends Kohana_OAuth_Provider_Google { }
|
|
@ -1,3 +0,0 @@
|
|||||||
<?php defined('SYSPATH') or die('No direct script access.');
|
|
||||||
|
|
||||||
class OAuth_Provider_Twitter extends Kohana_OAuth_Provider_Twitter { }
|
|
@ -1,3 +0,0 @@
|
|||||||
<?php defined('SYSPATH') or die('No direct script access.');
|
|
||||||
|
|
||||||
abstract class OAuth_Request extends Kohana_OAuth_Request { }
|
|
@ -1,3 +0,0 @@
|
|||||||
<?php defined('SYSPATH') or die('No direct script access.');
|
|
||||||
|
|
||||||
class OAuth_Request_Access extends Kohana_OAuth_Request_Access { }
|
|
@ -1,3 +0,0 @@
|
|||||||
<?php defined('SYSPATH') or die('No direct script access.');
|
|
||||||
|
|
||||||
class OAuth_Request_Authorize extends Kohana_OAuth_Request_Authorize { }
|
|
@ -1,3 +0,0 @@
|
|||||||
<?php defined('SYSPATH') or die('No direct script access.');
|
|
||||||
|
|
||||||
class OAuth_Request_Credentials extends Kohana_OAuth_Request_Credentials { }
|
|
@ -1,3 +0,0 @@
|
|||||||
<?php defined('SYSPATH') or die('No direct script access.');
|
|
||||||
|
|
||||||
class OAuth_Request_Resource extends Kohana_OAuth_Request_Resource { }
|
|
@ -1,3 +0,0 @@
|
|||||||
<?php defined('SYSPATH') or die('No direct script access.');
|
|
||||||
|
|
||||||
abstract class OAuth_Signature extends Kohana_OAuth_Signature { }
|
|
@ -1,3 +0,0 @@
|
|||||||
<?php defined('SYSPATH') or die('No direct script access.');
|
|
||||||
|
|
||||||
class OAuth_Signature_HMAC_SHA1 extends Kohana_OAuth_Signature_HMAC_SHA1 { }
|
|
@ -1,3 +0,0 @@
|
|||||||
<?php defined('SYSPATH') or die('No direct script access.');
|
|
||||||
|
|
||||||
class OAuth_Signature_PLAINTEXT extends Kohana_OAuth_Signature_PLAINTEXT { }
|
|
@ -1,3 +0,0 @@
|
|||||||
<?php defined('SYSPATH') or die('No direct script access.');
|
|
||||||
|
|
||||||
class OAuth_Token_Access extends Kohana_OAuth_Token_Access { }
|
|
@ -1,3 +0,0 @@
|
|||||||
<?php defined('SYSPATH') or die('No direct script access.');
|
|
||||||
|
|
||||||
class OAuth_Token_Request extends Kohana_OAuth_Token_Request { }
|
|
@ -1,15 +0,0 @@
|
|||||||
<?php defined('SYSPATH') or die('No direct script access.');
|
|
||||||
/**
|
|
||||||
* Configuration for OAuth providers.
|
|
||||||
*/
|
|
||||||
return array(
|
|
||||||
/**
|
|
||||||
* Twitter applications can be registered at https://twitter.com/apps.
|
|
||||||
* You will be given a "consumer key" and "consumer secret", which must
|
|
||||||
* be provided when making OAuth requests.
|
|
||||||
*/
|
|
||||||
'twitter' => array(
|
|
||||||
'key' => 'your consumer key',
|
|
||||||
'secret' => 'your consumer secret'
|
|
||||||
),
|
|
||||||
);
|
|
@ -1,23 +0,0 @@
|
|||||||
<?php defined('SYSPATH') or die('No direct script access.');
|
|
||||||
|
|
||||||
return array(
|
|
||||||
// Leave this alone
|
|
||||||
'modules' => array(
|
|
||||||
|
|
||||||
// This should be the path to this modules userguide pages, without the 'guide/'. Ex: '/guide/modulename/' would be 'modulename'
|
|
||||||
'oauth' => array(
|
|
||||||
|
|
||||||
// Whether this modules userguide pages should be shown
|
|
||||||
'enabled' => TRUE,
|
|
||||||
|
|
||||||
// The name that should show up on the userguide index page
|
|
||||||
'name' => 'OAuth',
|
|
||||||
|
|
||||||
// A short description of this module, shown on the index page
|
|
||||||
'description' => 'Open protocol authorization.',
|
|
||||||
|
|
||||||
// Copyright message, shown in the footer for this module
|
|
||||||
'copyright' => '© 2008–2010 Kohana Team',
|
|
||||||
)
|
|
||||||
)
|
|
||||||
);
|
|
@ -1,24 +0,0 @@
|
|||||||
# OAuth Configuration
|
|
||||||
|
|
||||||
All configuration for OAuth is done in the `config/oauth.php` file. The configuration file is organized by the provider name.
|
|
||||||
|
|
||||||
## Example Configuration File
|
|
||||||
|
|
||||||
return array(
|
|
||||||
/**
|
|
||||||
* Twitter application registration: https://twitter.com/apps
|
|
||||||
*/
|
|
||||||
'twitter' => array(
|
|
||||||
'key' => 'your consumer key',
|
|
||||||
'secret' => 'your consumer secret'
|
|
||||||
),
|
|
||||||
/**
|
|
||||||
* Google application registration: https://www.google.com/accounts/ManageDomains
|
|
||||||
*/
|
|
||||||
'google' => array(
|
|
||||||
'key' => 'your domain name',
|
|
||||||
'secret' => 'your consumer secret'
|
|
||||||
),
|
|
||||||
);
|
|
||||||
|
|
||||||
[!!] The consumer key and secret **must** be defined for all providers.
|
|
@ -1,14 +0,0 @@
|
|||||||
# About OAuth
|
|
||||||
|
|
||||||
[OAuth](http://oauth.net/) is an open protocol to allow secure API authorization in a simple and standard method from desktop and web applications. This module provides a pure PHP implementation of the OAuth v1.0 protocol, with support for PLAINTEXT and HMAC-SHA1 signatures.
|
|
||||||
|
|
||||||
## Supported Providers
|
|
||||||
|
|
||||||
The following providers are available by default:
|
|
||||||
|
|
||||||
* [Twitter](http://twitter.com/) using [OAuth_Provider_Twitter]
|
|
||||||
* [Google](http://www.google.com/) using [OAuth_Provider_Google]
|
|
||||||
|
|
||||||
Additional providers can be created by creating an extension of [OAuth_Provider].
|
|
||||||
|
|
||||||
|
|
@ -1,3 +0,0 @@
|
|||||||
## [OAuth]()
|
|
||||||
- [Configuration](config)
|
|
||||||
- [Usage](usage)
|
|
@ -1,3 +0,0 @@
|
|||||||
# OAuth Usage
|
|
||||||
|
|
||||||
[!!] This is a stub. Please see [controller/oauth source](http://github.com/kohana/oauth/tree/206c20033e209f233c9e7dc72836bfb786bd7e34/classes/controller) for now. The methods [OAuth_Provider_Google::user_profile] and [OAuth_Provider_Twitter::update_status] no longer exist in the current git master branch.
|
|
@ -1,15 +0,0 @@
|
|||||||
<?php echo Form::open() ?>
|
|
||||||
|
|
||||||
<dl>
|
|
||||||
<dt><?php echo Form::label('tweet', 'Update Twitter Status?') ?></dt>
|
|
||||||
<dd><?php echo Form::textarea('tweet', $tweet) ?></dd>
|
|
||||||
</dl>
|
|
||||||
|
|
||||||
<?php echo Form::submit(NULL, 'Send') ?>
|
|
||||||
|
|
||||||
<?php echo Form::close() ?>
|
|
||||||
|
|
||||||
<?php if ($response): ?>
|
|
||||||
<p>Response from Twitter:</p>
|
|
||||||
<?php echo $response ?>
|
|
||||||
<?php endif ?>
|
|
@ -20,7 +20,7 @@ CREATE TABLE IF NOT EXISTS `users` (
|
|||||||
`id` int(11) UNSIGNED NOT NULL AUTO_INCREMENT,
|
`id` int(11) UNSIGNED NOT NULL AUTO_INCREMENT,
|
||||||
`email` varchar(127) NOT NULL,
|
`email` varchar(127) NOT NULL,
|
||||||
`username` varchar(32) NOT NULL DEFAULT '',
|
`username` varchar(32) NOT NULL DEFAULT '',
|
||||||
`password` char(50) NOT NULL,
|
`password` varchar(64) NOT NULL,
|
||||||
`logins` int(10) UNSIGNED NOT NULL DEFAULT '0',
|
`logins` int(10) UNSIGNED NOT NULL DEFAULT '0',
|
||||||
`last_login` int(10) UNSIGNED,
|
`last_login` int(10) UNSIGNED,
|
||||||
PRIMARY KEY (`id`),
|
PRIMARY KEY (`id`),
|
||||||
@ -32,7 +32,8 @@ CREATE TABLE IF NOT EXISTS `user_tokens` (
|
|||||||
`id` int(11) UNSIGNED NOT NULL AUTO_INCREMENT,
|
`id` int(11) UNSIGNED NOT NULL AUTO_INCREMENT,
|
||||||
`user_id` int(11) UNSIGNED NOT NULL,
|
`user_id` int(11) UNSIGNED NOT NULL,
|
||||||
`user_agent` varchar(40) NOT NULL,
|
`user_agent` varchar(40) NOT NULL,
|
||||||
`token` varchar(32) NOT NULL,
|
`token` varchar(40) NOT NULL,
|
||||||
|
`type` varchar(100) NOT NULL,
|
||||||
`created` int(10) UNSIGNED NOT NULL,
|
`created` int(10) UNSIGNED NOT NULL,
|
||||||
`expires` int(10) UNSIGNED NOT NULL,
|
`expires` int(10) UNSIGNED NOT NULL,
|
||||||
PRIMARY KEY (`id`),
|
PRIMARY KEY (`id`),
|
@ -18,7 +18,7 @@ CREATE TABLE users
|
|||||||
id serial,
|
id serial,
|
||||||
email varchar(318) NOT NULL,
|
email varchar(318) NOT NULL,
|
||||||
username varchar(32) NOT NULL,
|
username varchar(32) NOT NULL,
|
||||||
"password" varchar(50) NOT NULL,
|
"password" varchar(64) NOT NULL,
|
||||||
logins integer NOT NULL DEFAULT 0,
|
logins integer NOT NULL DEFAULT 0,
|
||||||
last_login integer,
|
last_login integer,
|
||||||
CONSTRAINT users_id_pkey PRIMARY KEY (id),
|
CONSTRAINT users_id_pkey PRIMARY KEY (id),
|
@ -4,7 +4,7 @@
|
|||||||
*
|
*
|
||||||
* @package Kohana/Auth
|
* @package Kohana/Auth
|
||||||
* @author Kohana Team
|
* @author Kohana Team
|
||||||
* @copyright (c) 2007-2010 Kohana Team
|
* @copyright (c) 2007-2011 Kohana Team
|
||||||
* @license http://kohanaframework.org/license
|
* @license http://kohanaframework.org/license
|
||||||
*/
|
*/
|
||||||
class Kohana_Auth_ORM extends Auth {
|
class Kohana_Auth_ORM extends Auth {
|
||||||
@ -12,71 +12,49 @@ class Kohana_Auth_ORM extends Auth {
|
|||||||
/**
|
/**
|
||||||
* Checks if a session is active.
|
* Checks if a session is active.
|
||||||
*
|
*
|
||||||
* @param mixed role name string, role ORM object, or array with role names
|
* @param mixed $role Role name string, role ORM object, or array with role names
|
||||||
* @param boolean check user for every role applied (TRUE, by default) or if any?
|
|
||||||
* @return boolean
|
* @return boolean
|
||||||
*/
|
*/
|
||||||
public function logged_in($role = NULL, $all_required = TRUE)
|
public function logged_in($role = NULL)
|
||||||
{
|
{
|
||||||
$status = FALSE;
|
|
||||||
|
|
||||||
// Get the user from the session
|
// Get the user from the session
|
||||||
$user = $this->get_user();
|
$user = $this->get_user();
|
||||||
|
|
||||||
if (is_object($user) AND $user instanceof Model_User AND $user->loaded())
|
if ( ! $user)
|
||||||
{
|
return FALSE;
|
||||||
// Everything is okay so far
|
|
||||||
$status = TRUE;
|
|
||||||
|
|
||||||
if ( ! empty($role))
|
if ($user instanceof Model_User AND $user->loaded())
|
||||||
{
|
{
|
||||||
// Multiple roles to check
|
// If we don't have a roll no further checking is needed
|
||||||
|
if ( ! $role)
|
||||||
|
return TRUE;
|
||||||
|
|
||||||
if (is_array($role))
|
if (is_array($role))
|
||||||
{
|
{
|
||||||
// set initial status
|
// Get all the roles
|
||||||
$status = (bool) $all_required;
|
$roles = ORM::factory('role')
|
||||||
|
->where('name', 'IN', $role)
|
||||||
|
->find_all()
|
||||||
|
->as_array(NULL, 'id');
|
||||||
|
|
||||||
// Check each role
|
// Make sure all the roles are valid ones
|
||||||
foreach ($role as $_role)
|
if (count($roles) !== count($role))
|
||||||
{
|
return FALSE;
|
||||||
if ( ! is_object($_role))
|
|
||||||
{
|
|
||||||
$_role = ORM::factory('role', array('name' => $_role));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// If the user doesn't have the role
|
|
||||||
if ( ! $user->has('roles', $_role))
|
|
||||||
{
|
|
||||||
// Set the status false and get outta here
|
|
||||||
$status = FALSE;
|
|
||||||
if ($all_required)
|
|
||||||
{
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
elseif ( ! $all_required )
|
|
||||||
{
|
|
||||||
$status = TRUE;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// Single role to check
|
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if ( ! is_object($role))
|
if ( ! is_object($role))
|
||||||
{
|
{
|
||||||
// Load the role
|
// Load the role
|
||||||
$role = ORM::factory('role', array('name' => $role));
|
$roles = ORM::factory('role', array('name' => $role));
|
||||||
}
|
|
||||||
|
|
||||||
// Check that the user has the given role
|
if ( ! $roles->loaded())
|
||||||
$status = $user->has('roles', $role);
|
return FALSE;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return $status;
|
return $user->has('roles', $roles);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -103,7 +81,20 @@ class Kohana_Auth_ORM extends Auth {
|
|||||||
{
|
{
|
||||||
if ($remember === TRUE)
|
if ($remember === TRUE)
|
||||||
{
|
{
|
||||||
$this->remember($user);
|
// Token data
|
||||||
|
$data = array(
|
||||||
|
'user_id' => $user->id,
|
||||||
|
'expires' => time() + $this->_config['lifetime'],
|
||||||
|
'user_agent' => sha1(Request::$user_agent),
|
||||||
|
);
|
||||||
|
|
||||||
|
// Create a new autologin token
|
||||||
|
$token = ORM::factory('user_token')
|
||||||
|
->values($data)
|
||||||
|
->create();
|
||||||
|
|
||||||
|
// Set the autologin cookie
|
||||||
|
Cookie::set('authautologin', $token->token, $this->_config['lifetime']);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Finish the login
|
// Finish the login
|
||||||
@ -137,7 +128,7 @@ class Kohana_Auth_ORM extends Auth {
|
|||||||
if ($mark_session_as_forced === TRUE)
|
if ($mark_session_as_forced === TRUE)
|
||||||
{
|
{
|
||||||
// Mark the session as forced, to prevent users from changing account information
|
// Mark the session as forced, to prevent users from changing account information
|
||||||
$this->_session->set($this->_config['forced_key'], TRUE);
|
$this->_session->set('auth_forced', TRUE);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Run the standard completion
|
// Run the standard completion
|
||||||
@ -151,7 +142,7 @@ class Kohana_Auth_ORM extends Auth {
|
|||||||
*/
|
*/
|
||||||
public function auto_login()
|
public function auto_login()
|
||||||
{
|
{
|
||||||
if ($token = Cookie::get($this->_config['autologin_key']))
|
if ($token = Cookie::get('authautologin'))
|
||||||
{
|
{
|
||||||
// Load the token and user
|
// Load the token and user
|
||||||
$token = ORM::factory('user_token', array('token' => $token));
|
$token = ORM::factory('user_token', array('token' => $token));
|
||||||
@ -164,7 +155,7 @@ class Kohana_Auth_ORM extends Auth {
|
|||||||
$token->save();
|
$token->save();
|
||||||
|
|
||||||
// Set the new token
|
// Set the new token
|
||||||
Cookie::set($this->_config['autologin_key'], $token->token, $token->expires - time());
|
Cookie::set('authautologin', $token->token, $token->expires - time());
|
||||||
|
|
||||||
// Complete the login with the found data
|
// Complete the login with the found data
|
||||||
$this->complete_login($token->user);
|
$this->complete_login($token->user);
|
||||||
@ -187,11 +178,11 @@ class Kohana_Auth_ORM extends Auth {
|
|||||||
*
|
*
|
||||||
* @return mixed
|
* @return mixed
|
||||||
*/
|
*/
|
||||||
public function get_user()
|
public function get_user($default = NULL)
|
||||||
{
|
{
|
||||||
$user = parent::get_user();
|
$user = parent::get_user($default);
|
||||||
|
|
||||||
if ($user === FALSE)
|
if ( ! $user)
|
||||||
{
|
{
|
||||||
// check for "remembered" login
|
// check for "remembered" login
|
||||||
$user = $this->auto_login();
|
$user = $this->auto_login();
|
||||||
@ -210,12 +201,12 @@ class Kohana_Auth_ORM extends Auth {
|
|||||||
public function logout($destroy = FALSE, $logout_all = FALSE)
|
public function logout($destroy = FALSE, $logout_all = FALSE)
|
||||||
{
|
{
|
||||||
// Set by force_login()
|
// Set by force_login()
|
||||||
$this->_session->delete($this->_config['forced_key']);
|
$this->_session->delete('auth_forced');
|
||||||
|
|
||||||
if ($token = Cookie::get($this->_config['autologin_key']))
|
if ($token = Cookie::get('authautologin'))
|
||||||
{
|
{
|
||||||
// Delete the autologin cookie to prevent re-login
|
// Delete the autologin cookie to prevent re-login
|
||||||
Cookie::delete($this->_config['autologin_key']);
|
Cookie::delete('authautologin');
|
||||||
|
|
||||||
// Clear the autologin token from the database
|
// Clear the autologin token from the database
|
||||||
$token = ORM::factory('user_token', array('token' => $token));
|
$token = ORM::factory('user_token', array('token' => $token));
|
||||||
@ -277,46 +268,10 @@ class Kohana_Auth_ORM extends Auth {
|
|||||||
{
|
{
|
||||||
$user = $this->get_user();
|
$user = $this->get_user();
|
||||||
|
|
||||||
if ($user === FALSE)
|
|
||||||
{
|
|
||||||
// nothing to compare
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
$hash = $this->hash_password($password, $this->find_salt($user->password));
|
|
||||||
|
|
||||||
return $hash == $user->password;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Remember user (create token and save it in cookie)
|
|
||||||
*
|
|
||||||
* @param Model_User $user
|
|
||||||
* @return boolean
|
|
||||||
*/
|
|
||||||
public function remember($user = NULL)
|
|
||||||
{
|
|
||||||
if (is_null($user))
|
|
||||||
{
|
|
||||||
$user = $this->get_user();
|
|
||||||
}
|
|
||||||
if ( ! $user)
|
if ( ! $user)
|
||||||
{
|
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
|
||||||
|
|
||||||
// Create a new autologin token
|
return ($this->hash($password) === $user->password);
|
||||||
$token = ORM::factory('user_token');
|
|
||||||
|
|
||||||
// Set token data
|
|
||||||
$token->user_id = $user->id;
|
|
||||||
$token->expires = time() + $this->_config['lifetime'];
|
|
||||||
$token->save();
|
|
||||||
|
|
||||||
// Set the autologin cookie
|
|
||||||
Cookie::set($this->_config['autologin_key'], $token->token, $this->_config['lifetime']);
|
|
||||||
|
|
||||||
return TRUE;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
} // End Auth ORM
|
} // End Auth ORM
|
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,182 @@
|
|||||||
|
<?php defined('SYSPATH') or die('No direct script access.');
|
||||||
|
/**
|
||||||
|
* ORM Validation exceptions.
|
||||||
|
*
|
||||||
|
* @package Kohana/ORM
|
||||||
|
* @author Kohana Team
|
||||||
|
* @copyright (c) 2007-2010 Kohana Team
|
||||||
|
* @license http://kohanaframework.org/license
|
||||||
|
*/
|
||||||
|
class Kohana_ORM_Validation_Exception extends Kohana_Exception {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Array of validation objects
|
||||||
|
* @var array
|
||||||
|
*/
|
||||||
|
protected $_objects = array();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The _object_name property of the main ORM model this exception was created for
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
protected $_object_name = NULL;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructs a new exception for the specified model
|
||||||
|
*
|
||||||
|
* @param string $object_name The _object_name of the model this exception is for
|
||||||
|
* @param Validation $object The Validation object of the model
|
||||||
|
* @param string $message The error message
|
||||||
|
* @param array $values The array of values for the error message
|
||||||
|
* @param integer $code The error code for the exception
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function __construct($object_name, Validation $object, $message = 'Failed to validate array', array $values = NULL, $code = 0)
|
||||||
|
{
|
||||||
|
$this->_object_name = $object_name;
|
||||||
|
$this->_objects['_object'] = $object;
|
||||||
|
|
||||||
|
parent::__construct($message, $values, $code);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adds a Validation object to this exception
|
||||||
|
*
|
||||||
|
* // The following will add a validation object for a profile model
|
||||||
|
* // inside the exception for a user model.
|
||||||
|
* $e->add_object('profile', $validation);
|
||||||
|
* // The errors array will now look something like this
|
||||||
|
* // array
|
||||||
|
* // (
|
||||||
|
* // 'username' => 'This field is required',
|
||||||
|
* // 'profile' => array
|
||||||
|
* // (
|
||||||
|
* // 'first_name' => 'This field is required',
|
||||||
|
* // ),
|
||||||
|
* // );
|
||||||
|
*
|
||||||
|
* @param string $alias The relationship alias from the model
|
||||||
|
* @param Validation $object The Validation object to merge
|
||||||
|
* @param mixed $has_many The array key to use if this exception can be merged multiple times
|
||||||
|
* @return ORM_Validation_Exception
|
||||||
|
*/
|
||||||
|
public function add_object($alias, Validation $object, $has_many = FALSE)
|
||||||
|
{
|
||||||
|
if ($has_many === TRUE)
|
||||||
|
{
|
||||||
|
// This is most likely a has_many relationship
|
||||||
|
$this->_objects[$alias][]['_object'] = $object;
|
||||||
|
}
|
||||||
|
elseif ($has_many)
|
||||||
|
{
|
||||||
|
// This is most likely a has_many relationship
|
||||||
|
$this->_objects[$alias][$has_many]['_object'] = $object;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
$this->_objects[$alias]['_object'] = $object;
|
||||||
|
}
|
||||||
|
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Merges an ORM_Validation_Exception object into the current exception
|
||||||
|
* Useful when you want to combine errors into one array
|
||||||
|
*
|
||||||
|
* @param string $alias The relationship alias from the model
|
||||||
|
* @param ORM_Validation_Exception $object The exception to merge
|
||||||
|
* @param mixed $has_many The array key to use if this exception can be merged multiple times
|
||||||
|
* @return ORM_Validation_Exception
|
||||||
|
*/
|
||||||
|
public function merge($alias, ORM_Validation_Exception $object, $has_many = FALSE)
|
||||||
|
{
|
||||||
|
if ($has_many === TRUE)
|
||||||
|
{
|
||||||
|
// This is most likely a has_many relationship
|
||||||
|
$this->_objects[$alias][] = $object->objects();
|
||||||
|
}
|
||||||
|
elseif ($has_many)
|
||||||
|
{
|
||||||
|
// This is most likely a has_many relationship
|
||||||
|
$this->_objects[$alias][$has_many] = $object->objects();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
$this->_objects[$alias] = $object->objects();
|
||||||
|
}
|
||||||
|
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a merged array of the errors from all the Validation objects in this exception
|
||||||
|
*
|
||||||
|
* // Will load Model_User errors from messages/orm-validation/user.php
|
||||||
|
* $e->errors('orm-validation');
|
||||||
|
*
|
||||||
|
* @param string $directory Directory to load error messages from
|
||||||
|
* @param mixed $translate Translate the message
|
||||||
|
* @return array
|
||||||
|
* @see generate_errors()
|
||||||
|
*/
|
||||||
|
public function errors($directory = NULL, $translate = TRUE)
|
||||||
|
{
|
||||||
|
if ($directory !== NULL)
|
||||||
|
{
|
||||||
|
// Everything starts at $directory/$object_name
|
||||||
|
$directory .= '/'.$this->_object_name;
|
||||||
|
}
|
||||||
|
|
||||||
|
return $this->generate_errors($this->_objects, $directory, $translate);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Recursive method to fetch all the errors in this exception
|
||||||
|
*
|
||||||
|
* @param array $array Array of Validation objects to get errors from
|
||||||
|
* @param string $directory Directory to load error messages from
|
||||||
|
* @param mixed $translate Translate the message
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
protected function generate_errors(array $array, $directory, $translate)
|
||||||
|
{
|
||||||
|
$errors = array();
|
||||||
|
|
||||||
|
foreach ($array as $alias => $object)
|
||||||
|
{
|
||||||
|
if ($directory === NULL)
|
||||||
|
{
|
||||||
|
// Return the raw errors
|
||||||
|
$file = NULL;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
$file = trim($directory.'/'.$alias, '/');
|
||||||
|
}
|
||||||
|
|
||||||
|
if (is_array($object))
|
||||||
|
{
|
||||||
|
// Recursively fill the errors array
|
||||||
|
$errors[$alias] = $this->generate_errors($object, $file, $translate);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Merge in this array of errors
|
||||||
|
$errors += $object->errors($directory, $translate);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return $errors;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the protected _objects property from this exception
|
||||||
|
*
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
public function objects()
|
||||||
|
{
|
||||||
|
return $this->_objects;
|
||||||
|
}
|
||||||
|
} // End Kohana_ORM_Validation_Exception
|
29
includes/kohana/modules/orm/classes/model/auth/role.php
Normal file
29
includes/kohana/modules/orm/classes/model/auth/role.php
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
<?php defined('SYSPATH') or die('No direct access allowed.');
|
||||||
|
/**
|
||||||
|
* Default auth role
|
||||||
|
*
|
||||||
|
* @package Kohana/Auth
|
||||||
|
* @author Kohana Team
|
||||||
|
* @copyright (c) 2007-2009 Kohana Team
|
||||||
|
* @license http://kohanaphp.com/license.html
|
||||||
|
*/
|
||||||
|
class Model_Auth_Role extends ORM {
|
||||||
|
|
||||||
|
// Relationships
|
||||||
|
protected $_has_many = array('users' => array('through' => 'roles_users'));
|
||||||
|
|
||||||
|
public function rules()
|
||||||
|
{
|
||||||
|
return array(
|
||||||
|
'name' => array(
|
||||||
|
array('not_empty'),
|
||||||
|
array('min_length', array(':value', 4)),
|
||||||
|
array('max_length', array(':value', 32)),
|
||||||
|
),
|
||||||
|
'description' => array(
|
||||||
|
array('max_length', array(':value', 255)),
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
} // End Auth Role Model
|
240
includes/kohana/modules/orm/classes/model/auth/user.php
Normal file
240
includes/kohana/modules/orm/classes/model/auth/user.php
Normal file
@ -0,0 +1,240 @@
|
|||||||
|
<?php defined('SYSPATH') or die('No direct access allowed.');
|
||||||
|
/**
|
||||||
|
* Default auth user
|
||||||
|
*
|
||||||
|
* @package Kohana/Auth
|
||||||
|
* @author Kohana Team
|
||||||
|
* @copyright (c) 2007-2011 Kohana Team
|
||||||
|
* @license http://kohanaframework.org/license
|
||||||
|
*/
|
||||||
|
class Model_Auth_User extends ORM {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A user has many tokens and roles
|
||||||
|
*
|
||||||
|
* @var array Relationhips
|
||||||
|
*/
|
||||||
|
protected $_has_many = array(
|
||||||
|
'user_tokens' => array('model' => 'user_token'),
|
||||||
|
'roles' => array('model' => 'role', 'through' => 'roles_users'),
|
||||||
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Rules for the user model. Because the password is _always_ a hash
|
||||||
|
* when it's set,you need to run an additional not_empty rule in your controller
|
||||||
|
* to make sure you didn't hash an empty string. The password rules
|
||||||
|
* should be enforced outside the model or with a model helper method.
|
||||||
|
*
|
||||||
|
* @return array Rules
|
||||||
|
*/
|
||||||
|
public function rules()
|
||||||
|
{
|
||||||
|
return array(
|
||||||
|
'username' => array(
|
||||||
|
array('not_empty'),
|
||||||
|
array('min_length', array(':value', 4)),
|
||||||
|
array('max_length', array(':value', 32)),
|
||||||
|
array('regex', array(':value', '/^[-\pL\pN_.]++$/uD')),
|
||||||
|
array(array($this, 'username_available'), array(':validation', ':field')),
|
||||||
|
),
|
||||||
|
'password' => array(
|
||||||
|
array('not_empty'),
|
||||||
|
),
|
||||||
|
'email' => array(
|
||||||
|
array('not_empty'),
|
||||||
|
array('min_length', array(':value', 4)),
|
||||||
|
array('max_length', array(':value', 127)),
|
||||||
|
array('email'),
|
||||||
|
array(array($this, 'email_available'), array(':validation', ':field')),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Filters to run when data is set in this model. The password filter
|
||||||
|
* automatically hashes the password when it's set in the model.
|
||||||
|
*
|
||||||
|
* @return array Filters
|
||||||
|
*/
|
||||||
|
public function filters()
|
||||||
|
{
|
||||||
|
return array(
|
||||||
|
'password' => array(
|
||||||
|
array(array(Auth::instance(), 'hash'))
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Labels for fields in this model
|
||||||
|
*
|
||||||
|
* @return array Labels
|
||||||
|
*/
|
||||||
|
public function labels()
|
||||||
|
{
|
||||||
|
return array(
|
||||||
|
'username' => 'username',
|
||||||
|
'email' => 'email address',
|
||||||
|
'password' => 'password',
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Complete the login for a user by incrementing the logins and saving login timestamp
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function complete_login()
|
||||||
|
{
|
||||||
|
if ($this->_loaded)
|
||||||
|
{
|
||||||
|
// Update the number of logins
|
||||||
|
$this->logins = new Database_Expression('logins + 1');
|
||||||
|
|
||||||
|
// Set the last login date
|
||||||
|
$this->last_login = time();
|
||||||
|
|
||||||
|
// Save the user
|
||||||
|
$this->update();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Does the reverse of unique_key_exists() by triggering error if username exists.
|
||||||
|
* Validation callback.
|
||||||
|
*
|
||||||
|
* @param Validation Validation object
|
||||||
|
* @param string Field name
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function username_available(Validation $validation, $field)
|
||||||
|
{
|
||||||
|
if ($this->unique_key_exists($validation[$field], 'username'))
|
||||||
|
{
|
||||||
|
$validation->error($field, 'username_available', array($validation[$field]));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Does the reverse of unique_key_exists() by triggering error if email exists.
|
||||||
|
* Validation callback.
|
||||||
|
*
|
||||||
|
* @param Validation Validation object
|
||||||
|
* @param string Field name
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function email_available(Validation $validation, $field)
|
||||||
|
{
|
||||||
|
if ($this->unique_key_exists($validation[$field], 'email'))
|
||||||
|
{
|
||||||
|
$validation->error($field, 'email_available', array($validation[$field]));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tests if a unique key value exists in the database.
|
||||||
|
*
|
||||||
|
* @param mixed the value to test
|
||||||
|
* @param string field name
|
||||||
|
* @return boolean
|
||||||
|
*/
|
||||||
|
public function unique_key_exists($value, $field = NULL)
|
||||||
|
{
|
||||||
|
if ($field === NULL)
|
||||||
|
{
|
||||||
|
// Automatically determine field by looking at the value
|
||||||
|
$field = $this->unique_key($value);
|
||||||
|
}
|
||||||
|
|
||||||
|
return (bool) DB::select(array('COUNT("*")', 'total_count'))
|
||||||
|
->from($this->_table_name)
|
||||||
|
->where($field, '=', $value)
|
||||||
|
->where($this->_primary_key, '!=', $this->pk())
|
||||||
|
->execute($this->_db)
|
||||||
|
->get('total_count');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Allows a model use both email and username as unique identifiers for login
|
||||||
|
*
|
||||||
|
* @param string unique value
|
||||||
|
* @return string field name
|
||||||
|
*/
|
||||||
|
public function unique_key($value)
|
||||||
|
{
|
||||||
|
return Valid::email($value) ? 'email' : 'username';
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Password validation for plain passwords.
|
||||||
|
*
|
||||||
|
* @param array $values
|
||||||
|
* @return Validation
|
||||||
|
*/
|
||||||
|
public static function get_password_validation($values)
|
||||||
|
{
|
||||||
|
return Validation::factory($values)
|
||||||
|
->rule('password', 'min_length', array(':value', 8))
|
||||||
|
->rule('password_confirm', 'matches', array(':validation', ':field', 'password'));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a new user
|
||||||
|
*
|
||||||
|
* Example usage:
|
||||||
|
* ~~~
|
||||||
|
* $user = ORM::factory('user')->create_user($_POST, array(
|
||||||
|
* 'username',
|
||||||
|
* 'password',
|
||||||
|
* 'email',
|
||||||
|
* );
|
||||||
|
* ~~~
|
||||||
|
*
|
||||||
|
* @param array $values
|
||||||
|
* @param array $expected
|
||||||
|
* @throws ORM_Validation_Exception
|
||||||
|
*/
|
||||||
|
public function create_user($values, $expected)
|
||||||
|
{
|
||||||
|
// Validation for passwords
|
||||||
|
$extra_validation = Model_User::get_password_validation($values)
|
||||||
|
->rule('password', 'not_empty');
|
||||||
|
|
||||||
|
return $this->values($values, $expected)->create($extra_validation);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Update an existing user
|
||||||
|
*
|
||||||
|
* [!!] We make the assumption that if a user does not supply a password, that they do not wish to update their password.
|
||||||
|
*
|
||||||
|
* Example usage:
|
||||||
|
* ~~~
|
||||||
|
* $user = ORM::factory('user')
|
||||||
|
* ->where('username', '=', 'kiall')
|
||||||
|
* ->find()
|
||||||
|
* ->update_user($_POST, array(
|
||||||
|
* 'username',
|
||||||
|
* 'password',
|
||||||
|
* 'email',
|
||||||
|
* );
|
||||||
|
* ~~~
|
||||||
|
*
|
||||||
|
* @param array $values
|
||||||
|
* @param array $expected
|
||||||
|
* @throws ORM_Validation_Exception
|
||||||
|
*/
|
||||||
|
public function update_user($values, $expected = NULL)
|
||||||
|
{
|
||||||
|
if (empty($values['password']))
|
||||||
|
{
|
||||||
|
unset($values['password'], $values['password_confirm']);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Validation for passwords
|
||||||
|
$extra_validation = Model_User::get_password_validation($values);
|
||||||
|
|
||||||
|
return $this->values($values, $expected)->update($extra_validation);
|
||||||
|
}
|
||||||
|
|
||||||
|
} // End Auth User Model
|
@ -4,7 +4,7 @@
|
|||||||
*
|
*
|
||||||
* @package Kohana/Auth
|
* @package Kohana/Auth
|
||||||
* @author Kohana Team
|
* @author Kohana Team
|
||||||
* @copyright (c) 2007-2010 Kohana Team
|
* @copyright (c) 2007-2011 Kohana Team
|
||||||
* @license http://kohanaframework.org/license
|
* @license http://kohanaframework.org/license
|
||||||
*/
|
*/
|
||||||
class Model_Auth_User_Token extends ORM {
|
class Model_Auth_User_Token extends ORM {
|
||||||
@ -12,9 +12,6 @@ class Model_Auth_User_Token extends ORM {
|
|||||||
// Relationships
|
// Relationships
|
||||||
protected $_belongs_to = array('user' => array());
|
protected $_belongs_to = array('user' => array());
|
||||||
|
|
||||||
// Current timestamp
|
|
||||||
protected $_now;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Handles garbage collection and deleting of expired objects.
|
* Handles garbage collection and deleting of expired objects.
|
||||||
*
|
*
|
||||||
@ -24,53 +21,19 @@ class Model_Auth_User_Token extends ORM {
|
|||||||
{
|
{
|
||||||
parent::__construct($id);
|
parent::__construct($id);
|
||||||
|
|
||||||
// Set the now, we use this a lot
|
|
||||||
$this->_now = time();
|
|
||||||
|
|
||||||
if (mt_rand(1, 100) === 1)
|
if (mt_rand(1, 100) === 1)
|
||||||
{
|
{
|
||||||
// Do garbage collection
|
// Do garbage collection
|
||||||
$this->delete_expired();
|
$this->delete_expired();
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($this->expires < $this->_now)
|
if ($this->expires < time() AND $this->_loaded)
|
||||||
{
|
{
|
||||||
// This object has expired
|
// This object has expired
|
||||||
$this->delete();
|
$this->delete();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Overload saving to set the created time and to create a new token
|
|
||||||
* when the object is saved.
|
|
||||||
*
|
|
||||||
* @return ORM
|
|
||||||
*/
|
|
||||||
public function save()
|
|
||||||
{
|
|
||||||
if ($this->loaded() === FALSE)
|
|
||||||
{
|
|
||||||
// Set the created time, token, and hash of the user agent
|
|
||||||
$this->created = $this->_now;
|
|
||||||
$this->user_agent = sha1(Request::$user_agent);
|
|
||||||
}
|
|
||||||
|
|
||||||
while (TRUE)
|
|
||||||
{
|
|
||||||
// Generate a new token
|
|
||||||
$this->token = $this->create_token();
|
|
||||||
|
|
||||||
try
|
|
||||||
{
|
|
||||||
return parent::save();
|
|
||||||
}
|
|
||||||
catch (Kohana_Database_Exception $e)
|
|
||||||
{
|
|
||||||
// Collision occurred, token is not unique
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Deletes all expired tokens.
|
* Deletes all expired tokens.
|
||||||
*
|
*
|
||||||
@ -80,22 +43,28 @@ class Model_Auth_User_Token extends ORM {
|
|||||||
{
|
{
|
||||||
// Delete all expired tokens
|
// Delete all expired tokens
|
||||||
DB::delete($this->_table_name)
|
DB::delete($this->_table_name)
|
||||||
->where('expires', '<', $this->_now)
|
->where('expires', '<', time())
|
||||||
->execute($this->_db);
|
->execute($this->_db);
|
||||||
|
|
||||||
return $this;
|
return $this;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
public function create(Validation $validation = NULL)
|
||||||
* Generate a new unique token.
|
{
|
||||||
*
|
$this->token = $this->create_token();
|
||||||
* @return string
|
|
||||||
* @uses Text::random
|
return parent::create($validation);
|
||||||
*/
|
}
|
||||||
|
|
||||||
protected function create_token()
|
protected function create_token()
|
||||||
{
|
{
|
||||||
// Create a random token
|
do
|
||||||
return Text::random('alnum', 32);
|
{
|
||||||
|
$token = sha1(uniqid(Text::random('alnum', 32), TRUE));
|
||||||
|
}
|
||||||
|
while(ORM::factory('user_token', array('token' => $token))->loaded());
|
||||||
|
|
||||||
|
return $token;
|
||||||
}
|
}
|
||||||
|
|
||||||
} // End Auth User Token Model
|
} // End Auth User Token Model
|
@ -0,0 +1,10 @@
|
|||||||
|
<?php defined('SYSPATH') or die('No direct script access.');
|
||||||
|
/**
|
||||||
|
* ORM Validation exceptions.
|
||||||
|
*
|
||||||
|
* @package Kohana/ORM
|
||||||
|
* @author Kohana Team
|
||||||
|
* @copyright (c) 2008-2009 Kohana Team
|
||||||
|
* @license http://kohanaphp.com/license
|
||||||
|
*/
|
||||||
|
class ORM_Validation_Exception extends Kohana_ORM_Validation_Exception {}
|
@ -14,10 +14,10 @@ return array(
|
|||||||
'name' => 'ORM',
|
'name' => 'ORM',
|
||||||
|
|
||||||
// A short description of this module, shown on the index page
|
// A short description of this module, shown on the index page
|
||||||
'description' => 'Object modeling and relation mapping.',
|
'description' => 'Official ORM module, a modeling library for object relational mapping.',
|
||||||
|
|
||||||
// Copyright message, shown in the footer for this module
|
// Copyright message, shown in the footer for this module
|
||||||
'copyright' => '© 2008–2010 Kohana Team',
|
'copyright' => '© 2008–2011 Kohana Team',
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
);
|
);
|
@ -1,8 +1,13 @@
|
|||||||
There will be subpages to this page that have examples. The following is a sample list, don't feel limited by his, or that these are required. Items on the list can be combined, split up, removed or added to.
|
# Examples
|
||||||
|
|
||||||
|
- [Simple](examples/simple): Basic, one table model examples.
|
||||||
|
- [Validation](examples/validation): Full example of creating a user account and handling validation errors.
|
||||||
|
|
||||||
|
## @TODO:
|
||||||
|
|
||||||
|
The following is a sample list of examples that might be useful. Don't feel limited by this list, or consider these required. Items on the list can be combined, split up, removed or added to. All contribution are appreciated.
|
||||||
|
|
||||||
- Simple one table, one class model. Show CRUD examples.
|
|
||||||
- Examples of changing things like $_table_name, $_labels, with, etc.
|
- Examples of changing things like $_table_name, $_labels, with, etc.
|
||||||
- Example of using validation
|
|
||||||
- Example of a one to one relationship.
|
- Example of a one to one relationship.
|
||||||
- Example of one to many
|
- Example of one to many
|
||||||
- Example of many to many.
|
- Example of many to many.
|
@ -1,4 +1,4 @@
|
|||||||
# Simple example
|
# Simple Examples
|
||||||
|
|
||||||
This is a simple example of a single ORM model, that has no relationships, but uses validation on the fields.
|
This is a simple example of a single ORM model, that has no relationships, but uses validation on the fields.
|
||||||
|
|
||||||
@ -7,8 +7,8 @@ This is a simple example of a single ORM model, that has no relationships, but u
|
|||||||
CREATE TABLE IF NOT EXISTS `members` (
|
CREATE TABLE IF NOT EXISTS `members` (
|
||||||
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
|
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
|
||||||
`username` varchar(32) NOT NULL,
|
`username` varchar(32) NOT NULL,
|
||||||
`firstname` varchar(32) NOT NULL,
|
`first_name` varchar(32) NOT NULL,
|
||||||
`lastname` varchar(32) NOT NULL,
|
`last_name` varchar(32) NOT NULL,
|
||||||
`email` varchar(127) DEFAULT NULL,
|
`email` varchar(127) DEFAULT NULL,
|
||||||
PRIMARY KEY (`id`)
|
PRIMARY KEY (`id`)
|
||||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8 AUTO_INCREMENT=1;
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8 AUTO_INCREMENT=1;
|
||||||
@ -19,35 +19,38 @@ This is a simple example of a single ORM model, that has no relationships, but u
|
|||||||
|
|
||||||
class Model_Member extends ORM {
|
class Model_Member extends ORM {
|
||||||
|
|
||||||
protected $_rules = array(
|
public function rules()
|
||||||
|
{
|
||||||
|
return array(
|
||||||
'username' => array(
|
'username' => array(
|
||||||
'not_empty' => NULL,
|
array('not_empty'),
|
||||||
'min_length' => array(4),
|
array('min_length', array(':value', 4)),
|
||||||
'max_length' => array(32),
|
array('max_length', array(':value', 32)),
|
||||||
'regex' => array('/^[-\pL\pN_.]++$/uD'),
|
array('regex', array(':value', '/^[-\pL\pN_.]++$/uD')),
|
||||||
),
|
),
|
||||||
'firstname' => array(
|
'first_name' => array(
|
||||||
'not_empty' => NULL,
|
array('not_empty'),
|
||||||
'min_length' => array(4),
|
array('min_length', array(':value', 4)),
|
||||||
'max_length' => array(32),
|
array('max_length', array(':value', 32)),
|
||||||
'regex' => array('/^[-\pL\pN_.]++$/uD'),
|
array('regex', array(':value', '/^[-\pL\pN_.]++$/uD')),
|
||||||
),
|
),
|
||||||
'lastname' => array(
|
'last_name' => array(
|
||||||
'not_empty' => NULL,
|
array('not_empty'),
|
||||||
'min_length' => array(4),
|
array('min_length', array(':value', 4)),
|
||||||
'max_length' => array(32),
|
array('max_length', array(':value', 32)),
|
||||||
'regex' => array('/^[-\pL\pN_.]++$/uD'),
|
array('regex', array(':value', '/^[-\pL\pN_.]++$/uD')),
|
||||||
),
|
),
|
||||||
'email' => array(
|
'email' => array(
|
||||||
'not_empty' => NULL,
|
array('not_empty'),
|
||||||
'min_length' => array(4),
|
array('min_length', array(':value', 4)),
|
||||||
'max_length' => array(127),
|
array('max_length', array(':value', 127)),
|
||||||
'email' => NULL,
|
array('email'),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
[!!] The `$_rules` array will be passed to a [Validate] object and tested when you call `check()`.
|
[!!] The array returned by `ORM::rules()` will be passed to a [Validation] object and tested when you call `ORM::save()`.
|
||||||
|
|
||||||
[!!] Please notice that defining the primary key "id" in the model is not necessary. Also the table name in the database is plural and the model name is singular.
|
[!!] Please notice that defining the primary key "id" in the model is not necessary. Also the table name in the database is plural and the model name is singular.
|
||||||
|
|
||||||
@ -59,23 +62,23 @@ This is a simple example of a single ORM model, that has no relationships, but u
|
|||||||
|
|
||||||
public function action_index()
|
public function action_index()
|
||||||
{
|
{
|
||||||
// -------------
|
/**
|
||||||
// - Example 1 -
|
* Example 1
|
||||||
// -------------
|
*/
|
||||||
|
|
||||||
// Create an instance of a model
|
// Create an instance of a model
|
||||||
$member = ORM::factory('member');
|
$members = ORM::factory('member');
|
||||||
|
|
||||||
// Get all members with the First name "Peter" find_all()
|
// Get all members with the first name "Peter" find_all()
|
||||||
// means we get all records matching the query.
|
// means we get all records matching the query.
|
||||||
$member->where('firstname', '=', 'Peter')->find_all();
|
$members->where('first_name', '=', 'Peter')->find_all();
|
||||||
|
|
||||||
// Count records in the $member object
|
// Count records in the $members object
|
||||||
$member->count_all();
|
$members->count_all();
|
||||||
|
|
||||||
// -------------
|
/**
|
||||||
// - Example 2 -
|
* Example 2
|
||||||
// -------------
|
*/
|
||||||
|
|
||||||
// Create an instance of a model
|
// Create an instance of a model
|
||||||
$member = ORM::factory('member');
|
$member = ORM::factory('member');
|
||||||
@ -84,37 +87,33 @@ This is a simple example of a single ORM model, that has no relationships, but u
|
|||||||
// we only want the first record matching the query.
|
// we only want the first record matching the query.
|
||||||
$member->where('username', '=', 'bongo')->find();
|
$member->where('username', '=', 'bongo')->find();
|
||||||
|
|
||||||
// -------------
|
/**
|
||||||
// - Example 3 -
|
* Example 3
|
||||||
// -------------
|
*/
|
||||||
|
|
||||||
// Create an instance of a model
|
// Create an instance of a model
|
||||||
$member = ORM::factory('member');
|
$member = ORM::factory('member');
|
||||||
|
|
||||||
// Do a INSERT query
|
// Do an INSERT query
|
||||||
$member->username = 'bongo';
|
$member->username = 'bongo';
|
||||||
$member->firstname = 'Peter';
|
$member->first_name = 'Peter';
|
||||||
$member->lastname = 'Smith';
|
$member->last_name = 'Smith';
|
||||||
$member->save();
|
$member->save();
|
||||||
|
|
||||||
// -------------
|
/**
|
||||||
// - Example 4 -
|
* Example 4
|
||||||
// -------------
|
*/
|
||||||
|
|
||||||
// Create an instance of a model where the
|
// Create an instance of a model where the
|
||||||
// table field "id" is "1"
|
// table field "id" is "1"
|
||||||
$member = ORM::factory('member', 1);
|
$member = ORM::factory('member', 1);
|
||||||
|
|
||||||
// You can create the instance like below
|
// Do an UPDATE query
|
||||||
// If you do not want to use the "id" field
|
|
||||||
$member = ORM::factory('member')->where('username', '=', 'bongo')->find();
|
|
||||||
|
|
||||||
// Do a UPDATE query
|
|
||||||
$member->username = 'bongo';
|
$member->username = 'bongo';
|
||||||
$member->firstname = 'Peter';
|
$member->first_name = 'Peter';
|
||||||
$member->lastname = 'Smith';
|
$member->last_name = 'Smith';
|
||||||
$member->save();
|
$member->save();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
[!!] $member will be a PHP object where you can access the values from the query e.g. echo $member->firstname
|
[!!] $member will be a PHP object where you can access the values from the query e.g. echo $member->first_name
|
||||||
|
137
includes/kohana/modules/orm/guide/orm/examples/validation.md
Normal file
137
includes/kohana/modules/orm/guide/orm/examples/validation.md
Normal file
@ -0,0 +1,137 @@
|
|||||||
|
# Validation Example
|
||||||
|
|
||||||
|
This example will create user accounts and demonstrate how to handle model and controller validation. We will create a form, process it, and display any errors to the user. We will be assuming that the Model_User class contains a method called `hash_password` that is used to turn the plaintext passwords into some kind of hash. The implementation of the hashing methods are beyond the scope of this example and should be provided with the Authentication library you decide to use.
|
||||||
|
|
||||||
|
## SQL schema
|
||||||
|
|
||||||
|
CREATE TABLE IF NOT EXISTS `members` (
|
||||||
|
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
|
||||||
|
`username` varchar(32) NOT NULL,
|
||||||
|
`password` varchar(100) NOT NULL,
|
||||||
|
PRIMARY KEY (`id`)
|
||||||
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8 AUTO_INCREMENT=1;
|
||||||
|
|
||||||
|
## Model
|
||||||
|
|
||||||
|
<?php defined('SYSPATH') or die('No direct access allowed.');
|
||||||
|
|
||||||
|
class Model_Member extends ORM {
|
||||||
|
|
||||||
|
public function rules()
|
||||||
|
{
|
||||||
|
return array(
|
||||||
|
'username' => array(
|
||||||
|
array('not_empty'),
|
||||||
|
array('min_length', array(':value', 4)),
|
||||||
|
array('max_length', array(':value', 32)),
|
||||||
|
array(array($this, 'username_available')),
|
||||||
|
),
|
||||||
|
'password' => array(
|
||||||
|
array('not_empty'),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function filters()
|
||||||
|
{
|
||||||
|
return array(
|
||||||
|
'password' => array(
|
||||||
|
array(array($this, 'hash_password')),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function username_available($username)
|
||||||
|
{
|
||||||
|
// There are simpler ways to do this, but I will use ORM for the sake of the example
|
||||||
|
return ORM::factory('member', array('username' => $username))->loaded();
|
||||||
|
}
|
||||||
|
|
||||||
|
public function hash_password($password)
|
||||||
|
{
|
||||||
|
// Do something to hash the password
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
## HTML Form
|
||||||
|
|
||||||
|
Please forgive my slightly ugly form. I am trying not to use any modules or unrelated magic. :)
|
||||||
|
|
||||||
|
<form action="<?= URL::site('/members'); ?>" method="post" accept-charset="utf-8">
|
||||||
|
<label for="username">Username:</label>
|
||||||
|
<input id="username" type="text" name="username" value="<?= Arr::get($values, 'username'); ?>" />
|
||||||
|
<label for="username" class="error"><?= Arr::get($errors, 'username'); ?>
|
||||||
|
|
||||||
|
<label for="password">Password:</label>
|
||||||
|
<input id="password" type="password" name="password" value="<?= Arr::get($values, 'password'); ?>" />
|
||||||
|
<label for="password" class="error"><?= Arr::get($errors, 'password'); ?>
|
||||||
|
|
||||||
|
<label for="password_confirm">Repeat Password:</label>
|
||||||
|
<input id="password_confirm" type="password" name="_external[password_confirm]" value="<?= Arr::path($values, '_external.password_confirm'); ?>" />
|
||||||
|
<label for="password_confirm" class="error"><?= Arr::path($errors, '_external.password_confirm'); ?>
|
||||||
|
|
||||||
|
<button type="submit">Create</button>
|
||||||
|
</form>
|
||||||
|
|
||||||
|
## Controller
|
||||||
|
|
||||||
|
[!!] Remember that the `password` will be hashed as soon as it is set in the model, for this reason, it is impossible to validate it's length or the fact that it matches the `password_confirm` field. The model should not care about validating the `password_confirm` field, so we add that logic to the controller and simply ask the model to bundle the errors into one tidy array. Read the [filters](filters) section to understand how those work.
|
||||||
|
|
||||||
|
public function action_create()
|
||||||
|
{
|
||||||
|
$view = View::factory('members/create')
|
||||||
|
->set('values', $_POST)
|
||||||
|
->bind('errors', $errors);
|
||||||
|
|
||||||
|
if ($_POST)
|
||||||
|
{
|
||||||
|
$member = ORM::factory('member')
|
||||||
|
// The ORM::values() method is a shortcut to assign many values at once
|
||||||
|
->values($_POST, array('username', 'password'));
|
||||||
|
|
||||||
|
$external_values = array(
|
||||||
|
// The unhashed password is needed for comparing to the password_confirm field
|
||||||
|
'password' => Arr::get($_POST, 'password'),
|
||||||
|
// Add all external values
|
||||||
|
) + Arr::get($_POST, '_external', array());
|
||||||
|
$extra = Validation::factory($external_values)
|
||||||
|
->rule('password_confirm', 'matches', array(':validation', ':field', 'password'));
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
$member->save($extra);
|
||||||
|
// Redirect the user to his page
|
||||||
|
$this->request->redirect('members/'.$member->id);
|
||||||
|
}
|
||||||
|
catch (ORM_Validation_Exception $e)
|
||||||
|
{
|
||||||
|
$errors = $e->errors('models');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->response->body($view);
|
||||||
|
}
|
||||||
|
|
||||||
|
## Messages
|
||||||
|
|
||||||
|
**application/messages/models/member.php**
|
||||||
|
|
||||||
|
return array(
|
||||||
|
'username' => array(
|
||||||
|
'not_empty' => 'You must provide a username.',
|
||||||
|
'min_length' => 'The username must be at least :param2 characters long.',
|
||||||
|
'max_length' => 'The username must be less than :param2 characters long.',
|
||||||
|
'username_available' => 'This username is not available.',
|
||||||
|
),
|
||||||
|
'password' => array(
|
||||||
|
'not_empty' => 'You must provide a password.',
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
|
**application/messages/models/member/_external.php**
|
||||||
|
|
||||||
|
return array(
|
||||||
|
'password_confirm' => array(
|
||||||
|
'matches' => 'The password fields did not match.',
|
||||||
|
),
|
||||||
|
);
|
22
includes/kohana/modules/orm/guide/orm/filters.md
Normal file
22
includes/kohana/modules/orm/guide/orm/filters.md
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
# Filters
|
||||||
|
|
||||||
|
Filters in ORM work much like they used to when they were part of the Validate class in 3.0.x however they have been modified to match the flexible syntax of [Validation] rules in 3.1.x. Filters run as soon as the field is set in your model and should be used to format the data before it is inserted into the Database.
|
||||||
|
|
||||||
|
Define your filters the same way you define rules, as an array returned by the `ORM::filters()` method like the following:
|
||||||
|
|
||||||
|
public function filters()
|
||||||
|
{
|
||||||
|
return array(
|
||||||
|
'username' => array(
|
||||||
|
array('trim'),
|
||||||
|
),
|
||||||
|
'password' => array(
|
||||||
|
array(array($this, 'hash_password')),
|
||||||
|
),
|
||||||
|
'created_on' => array(
|
||||||
|
array('Format::date', array(':value', 'Y-m-d H:i:s')),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
[!!] When defining filters, you may use the parameters `:value`, `:field`, and `:model` to refer to the field value, field name, and the model instance respectively.
|
@ -1,10 +1,10 @@
|
|||||||
# ORM
|
# ORM
|
||||||
|
|
||||||
Kohana 3.X includes a powerful Object Relational Mapping (ORM) module that uses the active record pattern and database introspection to determine a model's column information. ORM is integrated tightly with the [Validate] library.
|
Kohana 3.x includes a powerful Object Relational Mapping (ORM) module that uses the active record pattern and database introspection to determine a model's column information. ORM is integrated tightly with the [Validation] library.
|
||||||
|
|
||||||
The ORM allows for manipulation and control of data within a database as though it was a PHP object. Once you define the relationships ORM allows you to pull data from your database, manipulate the data in any way you like and then save the result back to the database without the use of SQL. By creating relationships between models that follow convention over configuration, much of the repetition of writing queries to create, read, update and delete information from the database can be reduced or entirely removed. All of the relationships can be handled automatically by the ORM library and you can access related data as standard object properties.
|
The ORM allows for manipulation and control of data within a database as though it was a PHP object. Once you define the relationships ORM allows you to pull data from your database, manipulate the data in any way you like, and then save the result back to the database without the use of SQL. By creating relationships between models that follow convention over configuration, much of the repetition of writing queries to create, read, update, and delete information from the database can be reduced or entirely removed. All of the relationships can be handled automatically by the ORM library and you can access related data as standard object properties.
|
||||||
|
|
||||||
ORM is included with the Kohana 3.X install but needs to be enabled before you can use it. In your `application/bootstrap.php` file modify the call to Kohana::modules and include the ORM modules.
|
ORM is included with the Kohana 3.x install but needs to be enabled before you can use it. In your `application/bootstrap.php` file modify the call to Kohana::modules and include the ORM modules.
|
||||||
|
|
||||||
## Getting started
|
## Getting started
|
||||||
|
|
||||||
@ -17,6 +17,6 @@ Before we use ORM, we must enable the modules required
|
|||||||
...
|
...
|
||||||
));
|
));
|
||||||
|
|
||||||
[!!] The database module is requried for the ORM module to work. Of course the database module has to be configured to use a existing database.
|
[!!] The database module is requried for the ORM module to work. Of course the database module has to be configured to use an existing database.
|
||||||
|
|
||||||
You can now created your [models](models) and [use ORM](using).
|
You can now create your [models](models) and [use ORM](using).
|
||||||
|
@ -3,5 +3,7 @@
|
|||||||
- [Basic usage](using)
|
- [Basic usage](using)
|
||||||
- [Relationships](relationships)
|
- [Relationships](relationships)
|
||||||
- [Validation](validation)
|
- [Validation](validation)
|
||||||
|
- [Filters](filters)
|
||||||
- [Examples](examples)
|
- [Examples](examples)
|
||||||
- [Simple](examples/simple)
|
- [Simple](examples/simple)
|
||||||
|
- [Validation](examples/validation)
|
||||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user