summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBharat Mediratta <bharat@menalto.com>2009-03-17 18:56:01 +0000
committerBharat Mediratta <bharat@menalto.com>2009-03-17 18:56:01 +0000
commit208fc9db683c51e3bcf1f24d1e5e0200e0f32d96 (patch)
tree68ef623d8c6e13cc15fc2fe6dbe13a32585b9fa6
parent3f87c16223d7aca44f432efe99b35ab7afb0dbe4 (diff)
Update Kohana to r4081.
This resolves ticket http://dev.kohanaphp.com/ticket/1156 1156: "Table prefix gets append to column name" All tests pass.
-rw-r--r--kohana/config/cache_sqlite.php9
-rw-r--r--kohana/helpers/inflector.php38
-rw-r--r--kohana/helpers/request.php28
-rw-r--r--kohana/libraries/Cache.php90
-rw-r--r--kohana/libraries/Database.php70
-rw-r--r--kohana/libraries/Database_Expression.php26
-rw-r--r--kohana/libraries/Encrypt.php14
-rw-r--r--kohana/libraries/Image.php2
-rw-r--r--kohana/libraries/Input.php8
-rw-r--r--kohana/libraries/ORM.php32
-rw-r--r--kohana/libraries/Router.php92
-rw-r--r--kohana/libraries/Session.php92
-rw-r--r--kohana/libraries/URI.php38
-rw-r--r--kohana/libraries/View.php14
-rw-r--r--kohana/libraries/drivers/Cache.php2
-rw-r--r--kohana/libraries/drivers/Cache/Apc.php27
-rw-r--r--kohana/libraries/drivers/Cache/Eaccelerator.php29
-rw-r--r--kohana/libraries/drivers/Cache/File.php94
-rw-r--r--kohana/libraries/drivers/Cache/Memcache.php142
-rw-r--r--kohana/libraries/drivers/Cache/Sqlite.php101
-rw-r--r--kohana/libraries/drivers/Cache/Xcache.php7
21 files changed, 587 insertions, 368 deletions
diff --git a/kohana/config/cache_sqlite.php b/kohana/config/cache_sqlite.php
index 918224ce..818b8932 100644
--- a/kohana/config/cache_sqlite.php
+++ b/kohana/config/cache_sqlite.php
@@ -4,8 +4,7 @@
*/
$config['schema'] =
'CREATE TABLE caches(
- id varchar(127) PRIMARY KEY,
- hash char(40) NOT NULL,
- tags varchar(255),
- expiration int,
- cache blob);'; \ No newline at end of file
+ id VARCHAR(127) PRIMARY KEY,
+ tags VARCHAR(255),
+ expiration INTEGER,
+ cache TEXT);'; \ No newline at end of file
diff --git a/kohana/helpers/inflector.php b/kohana/helpers/inflector.php
index b619eddb..94e62d36 100644
--- a/kohana/helpers/inflector.php
+++ b/kohana/helpers/inflector.php
@@ -26,16 +26,16 @@ class inflector_Core {
*/
public static function uncountable($str)
{
- if (self::$uncountable === NULL)
+ if (inflector::$uncountable === NULL)
{
// Cache uncountables
- self::$uncountable = Kohana::config('inflector.uncountable');
+ inflector::$uncountable = Kohana::config('inflector.uncountable');
// Make uncountables mirroed
- self::$uncountable = array_combine(self::$uncountable, self::$uncountable);
+ inflector::$uncountable = array_combine(inflector::$uncountable, inflector::$uncountable);
}
- return isset(self::$uncountable[strtolower($str)]);
+ return isset(inflector::$uncountable[strtolower($str)]);
}
/**
@@ -63,19 +63,19 @@ class inflector_Core {
// Cache key name
$key = 'singular_'.$str.$count;
- if (isset(self::$cache[$key]))
- return self::$cache[$key];
+ if (isset(inflector::$cache[$key]))
+ return inflector::$cache[$key];
if (inflector::uncountable($str))
- return self::$cache[$key] = $str;
+ return inflector::$cache[$key] = $str;
- if (empty(self::$irregular))
+ if (empty(inflector::$irregular))
{
// Cache irregular words
- self::$irregular = Kohana::config('inflector.irregular');
+ inflector::$irregular = Kohana::config('inflector.irregular');
}
- if ($irregular = array_search($str, self::$irregular))
+ if ($irregular = array_search($str, inflector::$irregular))
{
$str = $irregular;
}
@@ -93,7 +93,7 @@ class inflector_Core {
$str = substr($str, 0, -1);
}
- return self::$cache[$key] = $str;
+ return inflector::$cache[$key] = $str;
}
/**
@@ -120,21 +120,21 @@ class inflector_Core {
// Cache key name
$key = 'plural_'.$str.$count;
- if (isset(self::$cache[$key]))
- return self::$cache[$key];
+ if (isset(inflector::$cache[$key]))
+ return inflector::$cache[$key];
if (inflector::uncountable($str))
- return self::$cache[$key] = $str;
+ return inflector::$cache[$key] = $str;
- if (empty(self::$irregular))
+ if (empty(inflector::$irregular))
{
// Cache irregular words
- self::$irregular = Kohana::config('inflector.irregular');
+ inflector::$irregular = Kohana::config('inflector.irregular');
}
- if (isset(self::$irregular[$str]))
+ if (isset(inflector::$irregular[$str]))
{
- $str = self::$irregular[$str];
+ $str = inflector::$irregular[$str];
}
elseif (preg_match('/[sxz]$/', $str) OR preg_match('/[^aeioudgkprt]h$/', $str))
{
@@ -151,7 +151,7 @@ class inflector_Core {
}
// Set the cache and return
- return self::$cache[$key] = $str;
+ return inflector::$cache[$key] = $str;
}
/**
diff --git a/kohana/helpers/request.php b/kohana/helpers/request.php
index ba6f68ac..625f9226 100644
--- a/kohana/helpers/request.php
+++ b/kohana/helpers/request.php
@@ -83,7 +83,7 @@ class request_Core {
{
$method = strtolower($_SERVER['REQUEST_METHOD']);
- if ( ! in_array($method, self::$http_methods))
+ if ( ! in_array($method, request::$http_methods))
throw new Kohana_Exception('request.unknown_method', $method);
return $method;
@@ -101,7 +101,7 @@ class request_Core {
request::parse_accept_header();
if ($type === NULL)
- return self::$accept_types;
+ return request::$accept_types;
return (request::accepts_at_quality($type, $explicit_check) > 0);
}
@@ -175,16 +175,16 @@ class request_Core {
$type = explode('/', $type, 2);
// Exact match
- if (isset(self::$accept_types[$type[0]][$type[1]]))
- return self::$accept_types[$type[0]][$type[1]];
-
+ if (isset(request::$accept_types[$type[0]][$type[1]]))
+ return request::$accept_types[$type[0]][$type[1]];
+
// Wildcard match (if not checking explicitly)
- if ($explicit_check === FALSE AND isset(self::$accept_types[$type[0]]['*']))
- return self::$accept_types[$type[0]]['*'];
+ if ($explicit_check === FALSE AND isset(request::$accept_types[$type[0]]['*']))
+ return request::$accept_types[$type[0]]['*'];
// Catch-all wildcard match (if not checking explicitly)
- if ($explicit_check === FALSE AND isset(self::$accept_types['*']['*']))
- return self::$accept_types['*']['*'];
+ if ($explicit_check === FALSE AND isset(request::$accept_types['*']['*']))
+ return request::$accept_types['*']['*'];
// Content type not accepted
return 0;
@@ -198,17 +198,17 @@ class request_Core {
protected static function parse_accept_header()
{
// Run this function just once
- if (self::$accept_types !== NULL)
+ if (request::$accept_types !== NULL)
return;
// Initialize accept_types array
- self::$accept_types = array();
+ request::$accept_types = array();
// No HTTP Accept header found
if (empty($_SERVER['HTTP_ACCEPT']))
{
// Accept everything
- self::$accept_types['*']['*'] = 1;
+ request::$accept_types['*']['*'] = 1;
return;
}
@@ -229,9 +229,9 @@ class request_Core {
$q = (isset($accept_entry[1]) AND preg_match('~\bq\s*+=\s*+([.0-9]+)~', $accept_entry[1], $match)) ? (float) $match[1] : 1;
// Populate accept_types array
- if ( ! isset(self::$accept_types[$type[0]][$type[1]]) OR $q > self::$accept_types[$type[0]][$type[1]])
+ if ( ! isset(request::$accept_types[$type[0]][$type[1]]) OR $q > request::$accept_types[$type[0]][$type[1]])
{
- self::$accept_types[$type[0]][$type[1]] = $q;
+ request::$accept_types[$type[0]][$type[1]] = $q;
}
}
}
diff --git a/kohana/libraries/Cache.php b/kohana/libraries/Cache.php
index 73b80252..3fb5a31c 100644
--- a/kohana/libraries/Cache.php
+++ b/kohana/libraries/Cache.php
@@ -13,6 +13,8 @@
*/
class Cache_Core {
+ protected static $instances = array();
+
// For garbage collection
protected static $loaded;
@@ -25,17 +27,18 @@ class Cache_Core {
/**
* Returns a singleton instance of Cache.
*
- * @param array configuration
+ * @param string configuration
* @return Cache_Core
*/
- public static function instance($config = array())
+ public static function & instance($config = FALSE)
{
- static $obj;
-
- // Create the Cache instance
- ($obj === NULL) and $obj = new Cache($config);
+ if ( ! isset(Cache::$instances[$config]))
+ {
+ // Create a new instance
+ Cache::$instances[$config] = new Cache($config);
+ }
- return $obj;
+ return Cache::$instances[$config];
}
/**
@@ -85,7 +88,7 @@ class Cache_Core {
Kohana::log('debug', 'Cache Library initialized');
- if (self::$loaded !== TRUE)
+ if (Cache::$loaded !== TRUE)
{
$this->config['requests'] = (int) $this->config['requests'];
@@ -98,33 +101,22 @@ class Cache_Core {
}
// Cache has been loaded once
- self::$loaded = TRUE;
+ Cache::$loaded = TRUE;
}
}
/**
- * Fetches a cache by id. Non-string cache items are automatically
- * unserialized before the cache is returned. NULL is returned when
- * a cache item is not found.
+ * Fetches a cache by id. NULL is returned when a cache item is not found.
*
* @param string cache id
* @return mixed cached data or NULL
*/
public function get($id)
{
- // Change slashes to colons
- $id = str_replace(array('/', '\\'), '=', $id);
+ // Sanitize the ID
+ $id = $this->sanitize_id($id);
- if ($data = $this->driver->get($id))
- {
- if (substr($data, 0, 14) === '<{serialized}>')
- {
- // Data has been serialized, unserialize now
- $data = unserialize(substr($data, 14));
- }
- }
-
- return $data;
+ return $this->driver->get($id);
}
/**
@@ -136,22 +128,7 @@ class Cache_Core {
*/
public function find($tag)
{
- if ($ids = $this->driver->find($tag))
- {
- $data = array();
- foreach ($ids as $id)
- {
- // Load each cache item and add it to the array
- if (($cache = $this->get($id)) !== NULL)
- {
- $data[$id] = $cache;
- }
- }
-
- return $data;
- }
-
- return array();
+ return $this->driver->find($tag);
}
/**
@@ -164,22 +141,13 @@ class Cache_Core {
* @param integer number of seconds until the cache expires
* @return boolean
*/
- function set($id, $data, $tags = NULL, $lifetime = NULL)
+ function set($id, $data, array $tags = NULL, $lifetime = NULL)
{
if (is_resource($data))
throw new Kohana_Exception('cache.resources');
- // Change slashes to colons
- $id = str_replace(array('/', '\\'), '=', $id);
-
- if ( ! is_string($data))
- {
- // Serialize all non-string data, so that types can be preserved
- $data = '<{serialized}>'.serialize($data);
- }
-
- // Make sure that tags is an array
- $tags = empty($tags) ? array() : (array) $tags;
+ // Sanitize the ID
+ $id = $this->sanitize_id($id);
if ($lifetime === NULL)
{
@@ -198,8 +166,8 @@ class Cache_Core {
*/
public function delete($id)
{
- // Change slashes to colons
- $id = str_replace(array('/', '\\'), '=', $id);
+ // Sanitize the ID
+ $id = $this->sanitize_id($id);
return $this->driver->delete($id);
}
@@ -212,7 +180,7 @@ class Cache_Core {
*/
public function delete_tag($tag)
{
- return $this->driver->delete(FALSE, $tag);
+ return $this->driver->delete($tag, TRUE);
}
/**
@@ -225,4 +193,16 @@ class Cache_Core {
return $this->driver->delete(TRUE);
}
+ /**
+ * Replaces troublesome characters with underscores.
+ *
+ * @param string cache id
+ * @return string
+ */
+ protected function sanitize_id($id)
+ {
+ // Change slashes and spaces to underscores
+ return str_replace(array('/', '\\', ' '), '_', $id);
+ }
+
} // End Cache
diff --git a/kohana/libraries/Database.php b/kohana/libraries/Database.php
index c1ff0764..c98faffb 100644
--- a/kohana/libraries/Database.php
+++ b/kohana/libraries/Database.php
@@ -264,7 +264,7 @@ class Database_Core {
if ($this->config['benchmark'] == TRUE)
{
// Benchmark the query
- self::$benchmarks[] = array('query' => $sql, 'time' => $stop - $start, 'rows' => count($result));
+ Database::$benchmarks[] = array('query' => $sql, 'time' => $stop - $start, 'rows' => count($result));
}
return $result;
@@ -299,9 +299,9 @@ class Database_Core {
{
if (preg_match('/^DISTINCT\s++(.+)$/i', $val, $matches))
{
- /* ****** Begin Gallery 3 Local Change *********** */
- $val = (strpos($matches[1], '.') !== FALSE) ? $this->config['table_prefix'].$matches[1] : $matches[1];
- /* ****** End Gallery 3 Local Change *********** */
+ // Only prepend with table prefix if table name is specified
+ $val = (strpos($matches[1], '.') !== FALSE) ? $this->config['table_prefix'].$matches[1] : $matches[1];
+
$this->distinct = TRUE;
}
else
@@ -336,27 +336,32 @@ class Database_Core {
}
else
{
- $sql = (array) $sql;
+ $sql = array($sql);
}
foreach ($sql as $val)
{
if (($val = trim($val)) === '') continue;
- // TODO: Temporary solution, this should be moved to database driver (AS is checked for twice)
- if (stripos($val, ' AS ') !== FALSE)
+ if (is_string($val))
{
- $val = str_ireplace(' AS ', ' AS ', $val);
+ // TODO: Temporary solution, this should be moved to database driver (AS is checked for twice)
+ if (stripos($val, ' AS ') !== FALSE)
+ {
+ $val = str_ireplace(' AS ', ' AS ', $val);
- list($table, $alias) = explode(' AS ', $val);
+ list($table, $alias) = explode(' AS ', $val);
- // Attach prefix to both sides of the AS
- $this->from[] = $this->config['table_prefix'].$table.' AS '.$this->config['table_prefix'].$alias;
- }
- else
- {
- $this->from[] = $this->config['table_prefix'].$val;
+ // Attach prefix to both sides of the AS
+ $val = $this->config['table_prefix'].$table.' AS '.$this->config['table_prefix'].$alias;
+ }
+ else
+ {
+ $val = $this->config['table_prefix'].$val;
+ }
}
+
+ $this->from[] = $val;
}
return $this;
@@ -404,23 +409,34 @@ class Database_Core {
$cond[] = $this->driver->where($key, $value, 'AND ', count($cond), FALSE);
}
- if( ! is_array($this->join)) { $this->join = array(); }
+ if ( ! is_array($this->join))
+ {
+ $this->join = array();
+ }
+
+ if ( ! is_array($table))
+ {
+ $table = array($table);
+ }
- foreach ((array) $table as $t)
+ foreach ($table as $t)
{
- // TODO: Temporary solution, this should be moved to database driver (AS is checked for twice)
- if (stripos($t, ' AS ') !== FALSE)
+ if (is_string($t))
{
- $t = str_ireplace(' AS ', ' AS ', $t);
+ // TODO: Temporary solution, this should be moved to database driver (AS is checked for twice)
+ if (stripos($t, ' AS ') !== FALSE)
+ {
+ $t = str_ireplace(' AS ', ' AS ', $t);
- list($table, $alias) = explode(' AS ', $t);
+ list($table, $alias) = explode(' AS ', $t);
- // Attach prefix to both sides of the AS
- $t = $this->config['table_prefix'].$table.' AS '.$this->config['table_prefix'].$alias;
- }
- else
- {
- $t = $this->config['table_prefix'].$t;
+ // Attach prefix to both sides of the AS
+ $t = $this->config['table_prefix'].$table.' AS '.$this->config['table_prefix'].$alias;
+ }
+ else
+ {
+ $t = $this->config['table_prefix'].$t;
+ }
}
$join['tables'][] = $this->driver->escape_column($t);
diff --git a/kohana/libraries/Database_Expression.php b/kohana/libraries/Database_Expression.php
new file mode 100644
index 00000000..3a8427ca
--- /dev/null
+++ b/kohana/libraries/Database_Expression.php
@@ -0,0 +1,26 @@
+<?php defined('SYSPATH') OR die('No direct access allowed.');
+/**
+ * Database expression class to allow for explicit joins and where expressions.
+ *
+ * $Id$
+ *
+ * @package Core
+ * @author Kohana Team
+ * @copyright (c) 2007-2009 Kohana Team
+ * @license http://kohanaphp.com/license.html
+ */
+class Database_Expression_Core {
+
+ protected $expression;
+
+ public function __construct($expression)
+ {
+ $this->expression = $expression;
+ }
+
+ public function __toString()
+ {
+ return (string) $this->expression;
+ }
+
+} // End Database Expr Class \ No newline at end of file
diff --git a/kohana/libraries/Encrypt.php b/kohana/libraries/Encrypt.php
index bfa4c625..31e72438 100644
--- a/kohana/libraries/Encrypt.php
+++ b/kohana/libraries/Encrypt.php
@@ -96,34 +96,34 @@ class Encrypt_Core {
public function encode($data)
{
// Set the rand type if it has not already been set
- if (self::$rand === NULL)
+ if (Encrypt::$rand === NULL)
{
if (KOHANA_IS_WIN)
{
// Windows only supports the system random number generator
- self::$rand = MCRYPT_RAND;
+ Encrypt::$rand = MCRYPT_RAND;
}
else
{
if (defined('MCRYPT_DEV_URANDOM'))
{
// Use /dev/urandom
- self::$rand = MCRYPT_DEV_URANDOM;
+ Encrypt::$rand = MCRYPT_DEV_URANDOM;
}
elseif (defined('MCRYPT_DEV_RANDOM'))
{
// Use /dev/random
- self::$rand = MCRYPT_DEV_RANDOM;
+ Encrypt::$rand = MCRYPT_DEV_RANDOM;
}
else
{
// Use the system random number generator
- self::$rand = MCRYPT_RAND;
+ Encrypt::$rand = MCRYPT_RAND;
}
}
}
- if (self::$rand === MCRYPT_RAND)
+ if (Encrypt::$rand === MCRYPT_RAND)
{
// The system random number generator must always be seeded each
// time it is used, or it will not produce true random results
@@ -131,7 +131,7 @@ class Encrypt_Core {
}
// Create a random initialization vector of the proper size for the current cipher
- $iv = mcrypt_create_iv($this->config['iv_size'], self::$rand);
+ $iv = mcrypt_create_iv($this->config['iv_size'], Encrypt::$rand);
// Encrypt the data using the configured options and generated iv
$data = mcrypt_encrypt($this->config['cipher'], $this->config['key'], $data, $this->config['mode'], $iv);
diff --git a/kohana/libraries/Image.php b/kohana/libraries/Image.php
index c9e82a1c..d740272d 100644
--- a/kohana/libraries/Image.php
+++ b/kohana/libraries/Image.php
@@ -292,7 +292,7 @@ class Image_Core {
*/
public function flip($direction)
{
- if ($direction !== self::HORIZONTAL AND $direction !== self::VERTICAL)
+ if ($direction !== Image::HORIZONTAL AND $direction !== Image::VERTICAL)
throw new Kohana_Exception('image.invalid_flip');
$this->actions['flip'] = $direction;
diff --git a/kohana/libraries/Input.php b/kohana/libraries/Input.php
index 3cdef0b8..04e8ee4d 100644
--- a/kohana/libraries/Input.php
+++ b/kohana/libraries/Input.php
@@ -31,13 +31,13 @@ class Input_Core {
*/
public static function instance()
{
- if (self::$instance === NULL)
+ if (Input::$instance === NULL)
{
// Create a new instance
return new Input;
}
- return self::$instance;
+ return Input::$instance;
}
/**
@@ -51,7 +51,7 @@ class Input_Core {
// Use XSS clean?
$this->use_xss_clean = (bool) Kohana::config('core.global_xss_filtering');
- if (self::$instance === NULL)
+ if (Input::$instance === NULL)
{
// magic_quotes_runtime is enabled
if (get_magic_quotes_runtime())
@@ -140,7 +140,7 @@ class Input_Core {
}
// Create a singleton
- self::$instance = $this;
+ Input::$instance = $this;
Kohana::log('debug', 'Global GET, POST and COOKIE data sanitized');
}
diff --git a/kohana/libraries/ORM.php b/kohana/libraries/ORM.php
index 64229ee2..fbbe9b92 100644
--- a/kohana/libraries/ORM.php
+++ b/kohana/libraries/ORM.php
@@ -258,11 +258,7 @@ class ORM_Core {
*/
public function __get($column)
{
- if (isset($this->ignored_columns[$column]))
- {
- return NULL;
- }
- elseif (array_key_exists($column, $this->object))
+ if (array_key_exists($column, $this->object))
{
return $this->object[$column];
}
@@ -278,7 +274,7 @@ class ORM_Core {
{
// This handles the has_one and belongs_to relationships
- if (in_array($model->object_name, $this->belongs_to) OR ! isset($model->object[$this->foreign_key($column)]))
+ if (in_array($model->object_name, $this->belongs_to) OR ! array_key_exists($this->foreign_key($column), $model->object))
{
// Foreign key lies in this table (this model belongs_to target model) OR an invalid has_one relationship
$where = array($model->table_name.'.'.$model->primary_key => $this->object[$this->foreign_key($column)]);
@@ -339,6 +335,10 @@ class ORM_Core {
->find_all();
}
}
+ elseif (isset($this->ignored_columns[$column]))
+ {
+ return NULL;
+ }
elseif (in_array($column, array
(
'object_name', 'object_plural', // Object
@@ -513,7 +513,7 @@ class ORM_Core {
$this->with_applied[$target_path] = TRUE;
// Use the keys of the empty object to determine the columns
- $select = array_keys($target->as_array());
+ $select = array_keys($target->object);
foreach ($select as $i => $column)
{
// Add the prefix so that load_result can determine the relationship
@@ -523,7 +523,7 @@ class ORM_Core {
// Select all of the prefixed keys in the object
$this->db->select($select);
-
+
if (in_array($target->object_name, $parent->belongs_to) OR ! isset($target->object[$parent->foreign_key($target_name)]))
{
// Parent belongs_to target, use target's primary key as join column
@@ -537,8 +537,11 @@ class ORM_Core {
$join_col1 = $parent->foreign_key($target_name, $target_path);
}
+ // This allows for models to use different table prefixes (sharing the same database)
+ $join_table = new Database_Expression($target->db->table_prefix().$target->table_name.' AS '.$this->db->table_prefix().$target_path);
+
// Join the related object into the result
- $this->db->join($target->table_name.' AS '.$this->db->table_prefix().$target_path, $join_col1, $join_col2, 'LEFT');
+ $this->db->join($join_table, $join_col1, $join_col2, 'LEFT');
return $this;
}
@@ -883,15 +886,15 @@ class ORM_Core {
{
if ($force === TRUE OR empty($this->table_columns))
{
- if (isset(self::$column_cache[$this->object_name]))
+ if (isset(ORM::$column_cache[$this->object_name]))
{
// Use cached column information
- $this->table_columns = self::$column_cache[$this->object_name];
+ $this->table_columns = ORM::$column_cache[$this->object_name];
}
else
{
// Load table columns
- self::$column_cache[$this->object_name] = $this->table_columns = $this->db->list_fields($this->table_name, TRUE);
+ ORM::$column_cache[$this->object_name] = $this->table_columns = $this->db->list_fields($this->table_name, TRUE);
}
}
@@ -907,7 +910,8 @@ class ORM_Core {
*/
public function has(ORM $model, $any = FALSE)
{
- $related = $model->object_plural;
+ // Determine plural or singular relation name
+ $related = ($model->table_names_plural === TRUE) ? $model->object_plural : $model->object_name;
if (($join_table = array_search($related, $this->has_and_belongs_to_many)) === FALSE)
return FALSE;
@@ -1141,7 +1145,7 @@ class ORM_Core {
}
else
{
- if ( ! is_string($table) OR ! isset($this->object[$table.'_'.$this->primary_key]))
+ if ( ! is_string($table) OR ! array_key_exists($table.'_'.$this->primary_key, $this->object))
{
// Use this table
$table = $this->table_name;
diff --git a/kohana/libraries/Router.php b/kohana/libraries/Router.php
index 49ed1246..172c5f92 100644
--- a/kohana/libraries/Router.php
+++ b/kohana/libraries/Router.php
@@ -38,57 +38,57 @@ class Router_Core {
if ( ! empty($_SERVER['QUERY_STRING']))
{
// Set the query string to the current query string
- self::$query_string = '?'.trim($_SERVER['QUERY_STRING'], '&/');
+ Router::$query_string = '?'.trim($_SERVER['QUERY_STRING'], '&/');
}
- if (self::$routes === NULL)
+ if (Router::$routes === NULL)
{
// Load routes
- self::$routes = Kohana::config('routes');
+ Router::$routes = Kohana::config('routes');
}
// Default route status
$default_route = FALSE;
- if (self::$current_uri === '')
+ if (Router::$current_uri === '')
{
// Make sure the default route is set
- if ( ! isset(self::$routes['_default']))
+ if ( ! isset(Router::$routes['_default']))
throw new Kohana_Exception('core.no_default_route');
// Use the default route when no segments exist
- self::$current_uri = self::$routes['_default'];
+ Router::$current_uri = Router::$routes['_default'];
// Default route is in use
$default_route = TRUE;
}
// Make sure the URL is not tainted with HTML characters
- self::$current_uri = html::specialchars(self::$current_uri, FALSE);
+ Router::$current_uri = html::specialchars(Router::$current_uri, FALSE);
// Remove all dot-paths from the URI, they are not valid
- self::$current_uri = preg_replace('#\.[\s./]*/#', '', self::$current_uri);
+ Router::$current_uri = preg_replace('#\.[\s./]*/#', '', Router::$current_uri);
// At this point segments, rsegments, and current URI are all the same
- self::$segments = self::$rsegments = self::$current_uri = trim(self::$current_uri, '/');
+ Router::$segments = Router::$rsegments = Router::$current_uri = trim(Router::$current_uri, '/');
// Set the complete URI
- self::$complete_uri = self::$current_uri.self::$query_string;
+ Router::$complete_uri = Router::$current_uri.Router::$query_string;
// Explode the segments by slashes
- self::$segments = ($default_route === TRUE OR self::$segments === '') ? array() : explode('/', self::$segments);
+ Router::$segments = ($default_route === TRUE OR Router::$segments === '') ? array() : explode('/', Router::$segments);
- if ($default_route === FALSE AND count(self::$routes) > 1)
+ if ($default_route === FALSE AND count(Router::$routes) > 1)
{
// Custom routing
- self::$rsegments = self::routed_uri(self::$current_uri);
+ Router::$rsegments = Router::routed_uri(Router::$current_uri);
}
// The routed URI is now complete
- self::$routed_uri = self::$rsegments;
+ Router::$routed_uri = Router::$rsegments;
// Routed segments will never be empty
- self::$rsegments = explode('/', self::$rsegments);
+ Router::$rsegments = explode('/', Router::$rsegments);
// Prepare to find the controller
$controller_path = '';
@@ -97,7 +97,7 @@ class Router_Core {
// Paths to search
$paths = Kohana::include_paths();
- foreach (self::$rsegments as $key => $segment)
+ foreach (Router::$rsegments as $key => $segment)
{
// Add the segment to the search path
$controller_path .= $segment;
@@ -114,14 +114,14 @@ class Router_Core {
$found = TRUE;
// The controller must be a file that exists with the search path
- if ($c = str_replace('\\', '/', realpath($dir.$controller_path.EXT))
+ if ($c = str_replace('\\', '/', realpath($dir.$controller_path.EXT))
AND is_file($c) AND strpos($c, $dir) === 0)
{
// Set controller name
- self::$controller = $segment;
+ Router::$controller = $segment;
// Change controller path
- self::$controller_path = $c;
+ Router::$controller_path = $c;
// Set the method segment
$method_segment = $key + 1;
@@ -142,22 +142,22 @@ class Router_Core {
$controller_path .= '/';
}
- if ($method_segment !== NULL AND isset(self::$rsegments[$method_segment]))
+ if ($method_segment !== NULL AND isset(Router::$rsegments[$method_segment]))
{
// Set method
- self::$method = self::$rsegments[$method_segment];
+ Router::$method = Router::$rsegments[$method_segment];
- if (isset(self::$rsegments[$method_segment + 1]))
+ if (isset(Router::$rsegments[$method_segment + 1]))
{
// Set arguments
- self::$arguments = array_slice(self::$rsegments, $method_segment + 1);
+ Router::$arguments = array_slice(Router::$rsegments, $method_segment + 1);
}
}
// Last chance to set routing before a 404 is triggered
Event::run('system.post_routing');
- if (self::$controller === NULL)
+ if (Router::$controller === NULL)
{
// No controller was found, so no page can be rendered
Event::run('system.404');
@@ -176,12 +176,12 @@ class Router_Core {
// Command line requires a bit of hacking
if (isset($_SERVER['argv'][1]))
{
- self::$current_uri = $_SERVER['argv'][1];
+ Router::$current_uri = $_SERVER['argv'][1];
// Remove GET string from segments
- if (($query = strpos(self::$current_uri, '?')) !== FALSE)
+ if (($query = strpos(Router::$current_uri, '?')) !== FALSE)
{
- list (self::$current_uri, $query) = explode('?', self::$current_uri, 2);
+ list (Router::$current_uri, $query) = explode('?', Router::$current_uri, 2);
// Parse the query string into $_GET
parse_str($query, $_GET);
@@ -194,7 +194,7 @@ class Router_Core {
elseif (isset($_GET['kohana_uri']))
{
// Use the URI defined in the query string
- self::$current_uri = $_GET['kohana_uri'];
+ Router::$current_uri = $_GET['kohana_uri'];
// Remove the URI from $_GET
unset($_GET['kohana_uri']);
@@ -204,42 +204,42 @@ class Router_Core {
}
elseif (isset($_SERVER['PATH_INFO']) AND $_SERVER['PATH_INFO'])
{
- self::$current_uri = $_SERVER['PATH_INFO'];
+ Router::$current_uri = $_SERVER['PATH_INFO'];
}
elseif (isset($_SERVER['ORIG_PATH_INFO']) AND $_SERVER['ORIG_PATH_INFO'])
{
- self::$current_uri = $_SERVER['ORIG_PATH_INFO'];
+ Router::$current_uri = $_SERVER['ORIG_PATH_INFO'];
}
elseif (isset($_SERVER['PHP_SELF']) AND $_SERVER['PHP_SELF'])
{
- self::$current_uri = $_SERVER['PHP_SELF'];
+ Router::$current_uri = $_SERVER['PHP_SELF'];
}
// The front controller directory and filename
$fc = substr(realpath($_SERVER['SCRIPT_FILENAME']), strlen(DOCROOT));
- if (($strpos_fc = strpos(self::$current_uri, $fc)) !== FALSE)
+ if (($strpos_fc = strpos(Router::$current_uri, $fc)) !== FALSE)
{
// Remove the front controller from the current uri
- self::$current_uri = substr(self::$current_uri, $strpos_fc + strlen($fc));
+ Router::$current_uri = substr(Router::$current_uri, $strpos_fc + strlen($fc));
}
// Remove slashes from the start and end of the URI
- self::$current_uri = trim(self::$current_uri, '/');
+ Router::$current_uri = trim(Router::$current_uri, '/');
- if (self::$current_uri !== '')
+ if (Router::$current_uri !== '')
{
- if ($suffix = Kohana::config('core.url_suffix') AND strpos(self::$current_uri, $suffix) !== FALSE)
+ if ($suffix = Kohana::config('core.url_suffix') AND strpos(Router::$current_uri, $suffix) !== FALSE)
{
// Remove the URL suffix
- self::$current_uri = preg_replace('#'.preg_quote($suffix).'$#u', '', self::$current_uri);
+ Router::$current_uri = preg_replace('#'.preg_quote($suffix).'$#u', '', Router::$current_uri);
// Set the URL suffix
- self::$url_suffix = $suffix;
+ Router::$url_suffix = $suffix;
}
// Reduce multiple slashes into single slashes
- self::$current_uri = preg_replace('#//+#', '/', self::$current_uri);
+ Router::$current_uri = preg_replace('#//+#', '/', Router::$current_uri);
}
}
@@ -251,24 +251,24 @@ class Router_Core {
*/
public static function routed_uri($uri)
{
- if (self::$routes === NULL)
+ if (Router::$routes === NULL)
{
// Load routes
- self::$routes = Kohana::config('routes');
+ Router::$routes = Kohana::config('routes');
}
// Prepare variables
$routed_uri = $uri = trim($uri, '/');
- if (isset(self::$routes[$uri]))
+ if (isset(Router::$routes[$uri]))
{
// Literal match, no need for regex
- $routed_uri = self::$routes[$uri];
+ $routed_uri = Router::$routes[$uri];
}
else
{
// Loop through the routes and see if anything matches
- foreach (self::$routes as $key => $val)
+ foreach (Router::$routes as $key => $val)
{
if ($key === '_default') continue;
@@ -295,10 +295,10 @@ class Router_Core {
}
}
- if (isset(self::$routes[$routed_uri]))
+ if (isset(Router::$routes[$routed_uri]))
{
// Check for double routing (without regex)
- $routed_uri = self::$routes[$routed_uri];
+ $routed_uri = Router::$routes[$routed_uri];
}
return trim($routed_uri, '/');
diff --git a/kohana/libraries/Session.php b/kohana/libraries/Session.php
index 4b5feed3..900e5405 100644
--- a/kohana/libraries/Session.php
+++ b/kohana/libraries/Session.php
@@ -12,7 +12,7 @@
class Session_Core {
// Session singleton
- private static $instance;
+ protected static $instance;
// Protected key names (cannot be set by the user)
protected static $protect = array('session_id', 'user_agent', 'last_activity', 'ip_address', 'total_hits', '_kf_flash_');
@@ -32,13 +32,13 @@ class Session_Core {
*/
public static function instance()
{
- if (self::$instance == NULL)
+ if (Session::$instance == NULL)
{
// Create a new instance
new Session;
}
- return self::$instance;
+ return Session::$instance;
}
/**
@@ -49,23 +49,23 @@ class Session_Core {
$this->input = Input::instance();
// This part only needs to be run once
- if (self::$instance === NULL)
+ if (Session::$instance === NULL)
{
// Load config
- self::$config = Kohana::config('session');
+ Session::$config = Kohana::config('session');
// Makes a mirrored array, eg: foo=foo
- self::$protect = array_combine(self::$protect, self::$protect);
+ Session::$protect = array_combine(Session::$protect, Session::$protect);
// Configure garbage collection
- ini_set('session.gc_probability', (int) self::$config['gc_probability']);
+ ini_set('session.gc_probability', (int) Session::$config['gc_probability']);
ini_set('session.gc_divisor', 100);
- ini_set('session.gc_maxlifetime', (self::$config['expiration'] == 0) ? 86400 : self::$config['expiration']);
+ ini_set('session.gc_maxlifetime', (Session::$config['expiration'] == 0) ? 86400 : Session::$config['expiration']);
// Create a new session
$this->create();
- if (self::$config['regenerate'] > 0 AND ($_SESSION['total_hits'] % self::$config['regenerate']) === 0)
+ if (Session::$config['regenerate'] > 0 AND ($_SESSION['total_hits'] % Session::$config['regenerate']) === 0)
{
// Regenerate session id and update session cookie
$this->regenerate();
@@ -73,7 +73,7 @@ class Session_Core {
else
{
// Always update session cookie to keep the session alive
- cookie::set(self::$config['name'], $_SESSION['session_id'], self::$config['expiration']);
+ cookie::set(Session::$config['name'], $_SESSION['session_id'], Session::$config['expiration']);
}
// Close the session just before sending the headers, so that
@@ -84,7 +84,7 @@ class Session_Core {
register_shutdown_function(array($this, 'write_close'));
// Singleton instance
- self::$instance = $this;
+ Session::$instance = $this;
}
Kohana::log('debug', 'Session Library initialized');
@@ -111,45 +111,45 @@ class Session_Core {
// Destroy any current sessions
$this->destroy();
- if (self::$config['driver'] !== 'native')
+ if (Session::$config['driver'] !== 'native')
{
// Set driver name
- $driver = 'Session_'.ucfirst(self::$config['driver']).'_Driver';
+ $driver = 'Session_'.ucfirst(Session::$config['driver']).'_Driver';
// Load the driver
if ( ! Kohana::auto_load($driver))
- throw new Kohana_Exception('core.driver_not_found', self::$config['driver'], get_class($this));
+ throw new Kohana_Exception('core.driver_not_found', Session::$config['driver'], get_class($this));
// Initialize the driver
- self::$driver = new $driver();
+ Session::$driver = new $driver();
// Validate the driver
- if ( ! (self::$driver instanceof Session_Driver))
- throw new Kohana_Exception('core.driver_implements', self::$config['driver'], get_class($this), 'Session_Driver');
+ if ( ! (Session::$driver instanceof Session_Driver))
+ throw new Kohana_Exception('core.driver_implements', Session::$config['driver'], get_class($this), 'Session_Driver');
// Register non-native driver as the session handler
session_set_save_handler
(
- array(self::$driver, 'open'),
- array(self::$driver, 'close'),
- array(self::$driver, 'read'),
- array(self::$driver, 'write'),
- array(self::$driver, 'destroy'),
- array(self::$driver, 'gc')
+ array(Session::$driver, 'open'),
+ array(Session::$driver, 'close'),
+ array(Session::$driver, 'read'),
+ array(Session::$driver, 'write'),
+ array(Session::$driver, 'destroy'),
+ array(Session::$driver, 'gc')
);
}
// Validate the session name
- if ( ! preg_match('~^(?=.*[a-z])[a-z0-9_]++$~iD', self::$config['name']))
- throw new Kohana_Exception('session.invalid_session_name', self::$config['name']);
+ if ( ! preg_match('~^(?=.*[a-z])[a-z0-9_]++$~iD', Session::$config['name']))
+ throw new Kohana_Exception('session.invalid_session_name', Session::$config['name']);
// Name the session, this will also be the name of the cookie
- session_name(self::$config['name']);
+ session_name(Session::$config['name']);
// Set the session cookie parameters
session_set_cookie_params
(
- self::$config['expiration'],
+ Session::$config['expiration'],
Kohana::config('cookie.path'),
Kohana::config('cookie.domain'),
Kohana::config('cookie.secure'),
@@ -173,7 +173,7 @@ class Session_Core {
}
// Set up flash variables
- self::$flash =& $_SESSION['_kf_flash_'];
+ Session::$flash =& $_SESSION['_kf_flash_'];
// Increase total hits
$_SESSION['total_hits'] += 1;
@@ -182,7 +182,7 @@ class Session_Core {
if ($_SESSION['total_hits'] > 1)
{
// Validate the session
- foreach (self::$config['validate'] as $valid)
+ foreach (Session::$config['validate'] as $valid)
{
switch ($valid)
{
@@ -214,17 +214,17 @@ class Session_Core {
$_SESSION['last_activity'] = time();
// Set the new data
- self::set($vars);
+ Session::set($vars);
}
/**
* Regenerates the global session id.
- *
+ *
* @return void
*/
public function regenerate()
{
- if (self::$config['driver'] === 'native')
+ if (Session::$config['driver'] === 'native')
{
// Generate a new session id
// Note: also sets a new session cookie with the updated id
@@ -236,7 +236,7 @@ class Session_Core {
else
{
// Pass the regenerating off to the driver in case it wants to do anything special
- $_SESSION['session_id'] = self::$driver->regenerate();
+ $_SESSION['session_id'] = Session::$driver->regenerate();
}
// Get the session name
@@ -315,7 +315,7 @@ class Session_Core {
foreach ($keys as $key => $val)
{
- if (isset(self::$protect[$key]))
+ if (isset(Session::$protect[$key]))
continue;
// Set the key
@@ -345,8 +345,8 @@ class Session_Core {
if ($key == FALSE)
continue;
- self::$flash[$key] = 'new';
- self::set($key, $val);
+ Session::$flash[$key] = 'new';
+ Session::set($key, $val);
}
}
@@ -358,13 +358,13 @@ class Session_Core {
*/
public function keep_flash($keys = NULL)
{
- $keys = ($keys === NULL) ? array_keys(self::$flash) : func_get_args();
+ $keys = ($keys === NULL) ? array_keys(Session::$flash) : func_get_args();
foreach ($keys as $key)
{
- if (isset(self::$flash[$key]))
+ if (isset(Session::$flash[$key]))
{
- self::$flash[$key] = 'new';
+ Session::$flash[$key] = 'new';
}
}
}
@@ -382,19 +382,19 @@ class Session_Core {
if ($run === TRUE)
return;
- if ( ! empty(self::$flash))
+ if ( ! empty(Session::$flash))
{
- foreach (self::$flash as $key => $state)
+ foreach (Session::$flash as $key => $state)
{
if ($state === 'old')
{
// Flash has expired
- unset(self::$flash[$key], $_SESSION[$key]);
+ unset(Session::$flash[$key], $_SESSION[$key]);
}
else
{
// Flash will expire
- self::$flash[$key] = 'old';
+ Session::$flash[$key] = 'old';
}
}
}
@@ -429,8 +429,8 @@ class Session_Core {
*/
public function get_once($key, $default = FALSE)
{
- $return = self::get($key, $default);
- self::delete($key);
+ $return = Session::get($key, $default);
+ Session::delete($key);
return $return;
}
@@ -447,7 +447,7 @@ class Session_Core {
foreach ($args as $key)
{
- if (isset(self::$protect[$key]))
+ if (isset(Session::$protect[$key]))
continue;
// Unset the key
diff --git a/kohana/libraries/URI.php b/kohana/libraries/URI.php
index 0c99f0f0..f012e78a 100644
--- a/kohana/libraries/URI.php
+++ b/kohana/libraries/URI.php
@@ -40,7 +40,7 @@ class URI_Core extends Router {
{
if (is_string($index))
{
- if (($key = array_search($index, self::$segments)) === FALSE)
+ if (($key = array_search($index, URI::$segments)) === FALSE)
return $default;
$index = $key + 2;
@@ -48,7 +48,7 @@ class URI_Core extends Router {
$index = (int) $index - 1;
- return isset(self::$segments[$index]) ? self::$segments[$index] : $default;
+ return isset(URI::$segments[$index]) ? URI::$segments[$index] : $default;
}
/**
@@ -62,7 +62,7 @@ class URI_Core extends Router {
{
if (is_string($index))
{
- if (($key = array_search($index, self::$rsegments)) === FALSE)
+ if (($key = array_search($index, URI::$rsegments)) === FALSE)
return $default;
$index = $key + 2;
@@ -70,7 +70,7 @@ class URI_Core extends Router {
$index = (int) $index - 1;
- return isset(self::$rsegments[$index]) ? self::$rsegments[$index] : $default;
+ return isset(URI::$rsegments[$index]) ? URI::$rsegments[$index] : $default;
}
/**
@@ -85,7 +85,7 @@ class URI_Core extends Router {
{
if (is_string($index))
{
- if (($key = array_search($index, self::$arguments)) === FALSE)
+ if (($key = array_search($index, URI::$arguments)) === FALSE)
return $default;
$index = $key + 2;
@@ -93,7 +93,7 @@ class URI_Core extends Router {
$index = (int) $index - 1;
- return isset(self::$arguments[$index]) ? self::$arguments[$index] : $default;
+ return isset(URI::$arguments[$index]) ? URI::$arguments[$index] : $default;
}
/**
@@ -105,7 +105,7 @@ class URI_Core extends Router {
*/
public function segment_array($offset = 0, $associative = FALSE)
{
- return $this->build_array(self::$segments, $offset, $associative);
+ return $this->build_array(URI::$segments, $offset, $associative);
}
/**
@@ -117,7 +117,7 @@ class URI_Core extends Router {
*/
public function rsegment_array($offset = 0, $associative = FALSE)
{
- return $this->build_array(self::$rsegments, $offset, $associative);
+ return $this->build_array(URI::$rsegments, $offset, $associative);
}
/**
@@ -129,7 +129,7 @@ class URI_Core extends Router {
*/
public function argument_array($offset = 0, $associative = FALSE)
{
- return $this->build_array(self::$arguments, $offset, $associative);
+ return $this->build_array(URI::$arguments, $offset, $associative);
}
/**
@@ -171,7 +171,7 @@ class URI_Core extends Router {
*/
public function string()
{
- return self::$current_uri;
+ return URI::$current_uri;
}
/**
@@ -181,7 +181,7 @@ class URI_Core extends Router {
*/
public function __toString()
{
- return self::$current_uri;
+ return URI::$current_uri;
}
/**
@@ -191,7 +191,7 @@ class URI_Core extends Router {
*/
public function total_segments()
{
- return count(self::$segments);
+ return count(URI::$segments);
}
/**
@@ -201,7 +201,7 @@ class URI_Core extends Router {
*/
public function total_rsegments()
{
- return count(self::$rsegments);
+ return count(URI::$rsegments);
}
/**
@@ -211,7 +211,7 @@ class URI_Core extends Router {
*/
public function total_arguments()
{
- return count(self::$arguments);
+ return count(URI::$arguments);
}
/**
@@ -225,7 +225,7 @@ class URI_Core extends Router {
if (($end = $this->total_segments()) < 1)
return $default;
- return self::$segments[$end - 1];
+ return URI::$segments[$end - 1];
}
/**
@@ -239,7 +239,7 @@ class URI_Core extends Router {
if (($end = $this->total_segments()) < 1)
return $default;
- return self::$rsegments[$end - 1];
+ return URI::$rsegments[$end - 1];
}
/**
@@ -251,7 +251,7 @@ class URI_Core extends Router {
*/
public function controller_path($full = TRUE)
{
- return ($full) ? url::site(self::$controller_path) : self::$controller_path;
+ return ($full) ? url::site(URI::$controller_path) : URI::$controller_path;
}
/**
@@ -262,7 +262,7 @@ class URI_Core extends Router {
*/
public function controller($full = TRUE)
{
- return ($full) ? url::site(self::$controller_path.self::$controller) : self::$controller;
+ return ($full) ? url::site(URI::$controller_path.URI::$controller) : URI::$controller;
}
/**
@@ -273,7 +273,7 @@ class URI_Core extends Router {
*/
public function method($full = TRUE)
{
- return ($full) ? url::site(self::$controller_path.self::$controller.'/'.self::$method) : self::$method;
+ return ($full) ? url::site(URI::$controller_path.URI::$controller.'/'.URI::$method) : URI::$method;
}
} // End URI Class
diff --git a/kohana/libraries/View.php b/kohana/libraries/View.php
index 5dba706c..87b15fc3 100644
--- a/kohana/libraries/View.php
+++ b/kohana/libraries/View.php
@@ -152,13 +152,13 @@ class View_Core {
foreach ($key as $property)
{
// Set the result to an associative array
- $result[$property] = (array_key_exists($property, $this->kohana_local_data) OR array_key_exists($property, self::$kohana_global_data)) ? TRUE : FALSE;
+ $result[$property] = (array_key_exists($property, $this->kohana_local_data) OR array_key_exists($property, View::$kohana_global_data)) ? TRUE : FALSE;
}
}
else
{
// Otherwise just check one property
- $result = (array_key_exists($key, $this->kohana_local_data) OR array_key_exists($key, self::$kohana_global_data)) ? TRUE : FALSE;
+ $result = (array_key_exists($key, $this->kohana_local_data) OR array_key_exists($key, View::$kohana_global_data)) ? TRUE : FALSE;
}
// Return the result
@@ -192,12 +192,12 @@ class View_Core {
{
foreach ($name as $key => $value)
{
- self::$kohana_global_data[$key] = $value;
+ View::$kohana_global_data[$key] = $value;
}
}
else
{
- self::$kohana_global_data[$name] = $value;
+ View::$kohana_global_data[$name] = $value;
}
}
@@ -225,8 +225,8 @@ class View_Core {
if (isset($this->kohana_local_data[$key]))
return $this->kohana_local_data[$key];
- if (isset(self::$kohana_global_data[$key]))
- return self::$kohana_global_data[$key];
+ if (isset(View::$kohana_global_data[$key]))
+ return View::$kohana_global_data[$key];
if (isset($this->$key))
return $this->$key;
@@ -266,7 +266,7 @@ class View_Core {
if (is_string($this->kohana_filetype))
{
// Merge global and local data, local overrides global with the same name
- $data = array_merge(self::$kohana_global_data, $this->kohana_local_data);
+ $data = array_merge(View::$kohana_global_data, $this->kohana_local_data);
// Load the view in the controller for access to $this
$output = Kohana::$instance->_kohana_load_view($this->kohana_filename, $data);
diff --git a/kohana/libraries/drivers/Cache.php b/kohana/libraries/drivers/Cache.php
index 0e825bcf..6f24ccac 100644
--- a/kohana/libraries/drivers/Cache.php
+++ b/kohana/libraries/drivers/Cache.php
@@ -14,7 +14,7 @@ interface Cache_Driver {
/**
* Set a cache item.
*/
- public function set($id, $data, $tags, $lifetime);
+ public function set($id, $data, array $tags = NULL, $lifetime);
/**
* Find all of the cache ids for a given tag.
diff --git a/kohana/libraries/drivers/Cache/Apc.php b/kohana/libraries/drivers/Cache/Apc.php
index 39d47dd3..29431ed4 100644
--- a/kohana/libraries/drivers/Cache/Apc.php
+++ b/kohana/libraries/drivers/Cache/Apc.php
@@ -22,27 +22,38 @@ class Cache_Apc_Driver implements Cache_Driver {
return (($return = apc_fetch($id)) === FALSE) ? NULL : $return;
}
- public function set($id, $data, $tags, $lifetime)
+ public function set($id, $data, array $tags = NULL, $lifetime)
{
- count($tags) and Kohana::log('error', 'Cache: tags are unsupported by the APC driver');
+ if ( ! empty($tags))
+ {
+ Kohana::log('error', 'Cache: tags are unsupported by the APC driver');
+ }
return apc_store($id, $data, $lifetime);
}
public function find($tag)
{
- return FALSE;
+ Kohana::log('error', 'Cache: tags are unsupported by the APC driver');
+
+ return array();
}
public function delete($id, $tag = FALSE)
{
- if ($id === TRUE)
+ if ($tag === TRUE)
+ {
+ Kohana::log('error', 'Cache: tags are unsupported by the APC driver');
+ return FALSE;
+ }
+ elseif ($id === TRUE)
+ {
return apc_clear_cache('user');
-
- if ($tag == FALSE)
+ }
+ else
+ {
return apc_delete($id);
-
- return TRUE;
+ }
}
public function delete_expired()
diff --git a/kohana/libraries/drivers/Cache/Eaccelerator.php b/kohana/libraries/drivers/Cache/Eaccelerator.php
index 8fd32471..0710d483 100644
--- a/kohana/libraries/drivers/Cache/Eaccelerator.php
+++ b/kohana/libraries/drivers/Cache/Eaccelerator.php
@@ -24,30 +24,43 @@ class Cache_Eaccelerator_Driver implements Cache_Driver {
public function find($tag)
{
- return FALSE;
+ Kohana::log('error', 'tags are unsupported by the eAccelerator driver');
+
+ return array();
}
- public function set($id, $data, $tags, $lifetime)
+ public function set($id, $data, array $tags = NULL, $lifetime)
{
- count($tags) and Kohana::log('error', 'tags are unsupported by the eAccelerator driver');
+ if ( ! empty($tags))
+ {
+ Kohana::log('error', 'tags are unsupported by the eAccelerator driver');
+ }
return eaccelerator_put($id, $data, $lifetime);
}
public function delete($id, $tag = FALSE)
{
- if ($id === TRUE)
+ if ($tag === TRUE)
+ {
+ Kohana::log('error', 'tags are unsupported by the eAccelerator driver');
+ return FALSE;
+ }
+ elseif ($id === TRUE)
+ {
return eaccelerator_clean();
-
- if ($tag == FALSE)
+ }
+ else
+ {
return eaccelerator_rm($id);
-
- return TRUE;
+ }
}
public function delete_expired()
{
eaccelerator_gc();
+
+ return TRUE;
}
} // End Cache eAccelerator Driver \ No newline at end of file
diff --git a/kohana/libraries/drivers/Cache/File.php b/kohana/libraries/drivers/Cache/File.php
index 16fa08e1..db27f02d 100644
--- a/kohana/libraries/drivers/Cache/File.php
+++ b/kohana/libraries/drivers/Cache/File.php
@@ -35,25 +35,25 @@ class Cache_File_Driver implements Cache_Driver {
* @param string cache id or tag
* @param bool search for tags
* @return array of filenames matching the id or tag
- * @return void if no matching files are found
*/
public function exists($id, $tag = FALSE)
{
if ($id === TRUE)
{
// Find all the files
- $files = glob($this->directory.'*~*~*');
+ return glob($this->directory.'*~*~*');
}
- elseif ($tag == TRUE)
+ elseif ($tag === TRUE)
{
// Find all the files that have the tag name
- $files = glob($this->directory.'*~*'.$id.'*~*');
+ $paths = glob($this->directory.'*~*'.$id.'*~*');
// Find all tags matching the given tag
- foreach ($files as $i => $file)
+ $files = array();
+ foreach ($paths as $path)
{
// Split the files
- $tags = explode('~', $file);
+ $tags = explode('~', basename($path));
// Find valid tags
if (count($tags) !== 3 OR empty($tags[1]))
@@ -62,20 +62,20 @@ class Cache_File_Driver implements Cache_Driver {
// Split the tags by plus signs, used to separate tags
$tags = explode('+', $tags[1]);
- if ( ! in_array($tag, $tags))
+ if (in_array($tag, $tags))
{
- // This entry does not match the tag
- unset($files[$i]);
+ // Add the file to the array, it has the requested tag
+ $files[] = $path;
}
}
+
+ return $files;
}
else
{
- // Find all the files matching the given id
- $files = glob($this->directory.$id.'~*');
+ // Find the file matching the given id
+ return glob($this->directory.$id.'~*');
}
-
- return empty($files) ? NULL : $files;
}
/**
@@ -87,7 +87,7 @@ class Cache_File_Driver implements Cache_Driver {
* @param integer lifetime
* @return bool
*/
- public function set($id, $data, $tags, $lifetime)
+ public function set($id, $data, array $tags = NULL, $lifetime)
{
// Remove old cache files
$this->delete($id);
@@ -98,11 +98,14 @@ class Cache_File_Driver implements Cache_Driver {
$lifetime += time();
}
- // Construct the filename
- $filename = $id.'~'.implode('+', $tags).'~'.$lifetime;
+ if ( ! empty($tags))
+ {
+ // Convert the tags into a string list
+ $tags = implode('+', $tags);
+ }
- // Write the file, appending the sha1 signature to the beginning of the data
- return (bool) file_put_contents($this->directory.$filename, sha1($data).$data);
+ // Write out a serialized cache
+ return (bool) file_put_contents($this->directory.$id.'~'.$tags.'~'.$lifetime, serialize($data));
}
/**
@@ -113,23 +116,29 @@ class Cache_File_Driver implements Cache_Driver {
*/
public function find($tag)
{
- if ($files = $this->exists($tag, TRUE))
+ // An array will always be returned
+ $result = array();
+
+ if ($paths = $this->exists($tag, TRUE))
{
// Length of directory name
$offset = strlen($this->directory);
// Find all the files with the given tag
- $array = array();
- foreach ($files as $file)
+ foreach ($paths as $path)
{
// Get the id from the filename
- $array[] = substr(current(explode('~', $file)), $offset);
- }
+ list($id, $junk) = explode('~', basename($path), 2);
- return $array;
+ if (($data = $this->get($id)) !== FALSE)
+ {
+ // Add the result to the array
+ $result[$id] = $data;
+ }
+ }
}
- return FALSE;
+ return $result;
}
/**
@@ -143,7 +152,7 @@ class Cache_File_Driver implements Cache_Driver {
{
if ($file = $this->exists($id))
{
- // Always process the first result
+ // Use the first file
$file = current($file);
// Validate that the cache has not expired
@@ -154,22 +163,22 @@ class Cache_File_Driver implements Cache_Driver {
}
else
{
- $data = file_get_contents($file);
-
- // Find the hash of the data
- $hash = substr($data, 0, 40);
-
- // Remove the hash from the data
- $data = substr($data, 40);
+ // Turn off errors while reading the file
+ $ER = error_reporting(0);
- if ($hash !== sha1($data))
+ if (($data = file_get_contents($file)) !== FALSE)
{
- // Remove this cache, it doesn't validate
- $this->delete($id);
-
- // Unset data to prevent it from being returned
+ // Unserialize the data
+ $data = unserialize($data);
+ }
+ else
+ {
+ // Delete the data
unset($data);
}
+
+ // Turn errors back on
+ error_reporting($ER);
}
}
@@ -216,14 +225,21 @@ class Cache_File_Driver implements Cache_Driver {
{
if ($files = $this->exists(TRUE))
{
+ // Disable all error reporting while deleting
+ $ER = error_reporting(0);
+
foreach ($files as $file)
{
if ($this->expired($file))
{
// The cache file has already expired, delete it
- @unlink($file) or Kohana::log('error', 'Cache: Unable to delete cache file: '.$file);
+ if ( ! unlink($file))
+ Kohana::log('error', 'Cache: Unable to delete cache file: '.$file);
}
}
+
+ // Turn on error reporting again
+ error_reporting($ER);
}
}
diff --git a/kohana/libraries/drivers/Cache/Memcache.php b/kohana/libraries/drivers/Cache/Memcache.php
index ef5b8440..f443b997 100644
--- a/kohana/libraries/drivers/Cache/Memcache.php
+++ b/kohana/libraries/drivers/Cache/Memcache.php
@@ -11,17 +11,28 @@
*/
class Cache_Memcache_Driver implements Cache_Driver {
+ const TAGS_KEY = 'memcache_tags_array';
+
// Cache backend object and flags
protected $backend;
protected $flags;
+ // The persistent lifetime value for expirations of 0
+ protected $persistent_lifetime;
+
+ // Tags array
+ protected $tags;
+
+ // Have the tags been changed?
+ protected $tags_changed = FALSE;
+
public function __construct()
{
if ( ! extension_loaded('memcache'))
throw new Kohana_Exception('cache.extension_not_loaded', 'memcache');
$this->backend = new Memcache;
- $this->flags = Kohana::config('cache_memcache.compression') ? MEMCACHE_COMPRESSED : 0;
+ $this->flags = Kohana::config('cache_memcache.compression') ? MEMCACHE_COMPRESSED : FALSE;
$servers = Kohana::config('cache_memcache.servers');
@@ -34,11 +45,44 @@ class Cache_Memcache_Driver implements Cache_Driver {
$this->backend->addServer($server['host'], $server['port'], (bool) $server['persistent'])
or Kohana::log('error', 'Cache: Connection failed: '.$server['host']);
}
+
+ // Set "persistent lifetime" value to one year
+ $this->persistent_lifetime = strtotime('now +1 year');
+
+ // Load tags
+ $this->tags = $this->backend->get(self::TAGS_KEY);
+
+ if ( ! is_array($this->tags))
+ {
+ // Create a new tags array
+ $this->tags = array();
+
+ // Tags have been created
+ $this->tags_changed = TRUE;
+ }
+ }
+
+ public function __destruct()
+ {
+ if ($this->tags_changed === TRUE)
+ {
+ // Save the tags
+ $this->backend->set(self::TAGS_KEY, $this->tags, $this->flags, $this->persistent_lifetime);
+ }
}
public function find($tag)
{
- return FALSE;
+ if (isset($this->tags[$tag]) AND $results = $this->backend->get($this->tags[$tag]))
+ {
+ // Return all the found caches
+ return $results;
+ }
+ else
+ {
+ // No matching tags
+ return array();
+ }
}
public function get($id)
@@ -46,32 +90,110 @@ class Cache_Memcache_Driver implements Cache_Driver {
return (($return = $this->backend->get($id)) === FALSE) ? NULL : $return;
}
- public function set($id, $data, $tags, $lifetime)
+ public function set($id, $data, array $tags = NULL, $lifetime)
{
- count($tags) and Kohana::log('error', 'Cache: Tags are unsupported by the memcache driver');
+ if ( ! empty($tags))
+ {
+ // Tags will be changed
+ $this->tags_changed = TRUE;
+
+ foreach ($tags as $tag)
+ {
+ // Add the id to each tag
+ $this->tags[$tag][$id] = $id;
+ }
+ }
- // Memcache driver expects unix timestamp
- if ($lifetime !== 0)
+ if ($lifetime === 0)
{
+ // Using an expiration of zero is unreliable, as memcache may delete
+ // it without warning. @see http://php.net/memcache_set
+ $lifetime = $this->persistent_lifetime;
+ }
+ else
+ {
+ // Memcache driver expects unix timestamp
$lifetime += time();
}
+ // Set a new value
return $this->backend->set($id, $data, $this->flags, $lifetime);
}
public function delete($id, $tag = FALSE)
{
+ // Tags will be changed
+ $this->tags_changed = TRUE;
+
if ($id === TRUE)
- return $this->backend->flush();
+ {
+ if ($status = $this->backend->flush())
+ {
+ // Remove all tags, all items have been deleted
+ $this->tags = array();
- if ($tag == FALSE)
- return $this->backend->delete($id);
+ // We must sleep after flushing, or overwriting will not work!
+ // @see http://php.net/manual/en/function.memcache-flush.php#81420
+ sleep(1);
+ }
- return TRUE;
+ return $status;
+ }
+ elseif ($tag === TRUE)
+ {
+ if (isset($this->tags[$id]))
+ {
+ foreach ($this->tags[$id] as $_id)
+ {
+ // Delete each id in the tag
+ $this->backend->delete($_id);
+ }
+
+ // Delete the tag
+ unset($this->tags[$id]);
+ }
+
+ return TRUE;
+ }
+ else
+ {
+ foreach ($this->tags as $tag => $_ids)
+ {
+ if (isset($this->tags[$tag][$id]))
+ {
+ // Remove the id from the tags
+ unset($this->tags[$tag][$id]);
+ }
+ }
+
+ return $this->backend->delete($id);
+ }
}
public function delete_expired()
{
+ // Tags will be changed
+ $this->tags_changed = TRUE;
+
+ foreach ($this->tags as $tag => $_ids)
+ {
+ foreach ($_ids as $id)
+ {
+ if ( ! $this->backend->get($id))
+ {
+ // This id has disappeared, delete it from the tags
+ unset($this->tags[$tag][$id]);
+ }
+ }
+
+ if (empty($this->tags[$tag]))
+ {
+ // The tag no longer has any valid ids
+ unset($this->tags[$tag]);
+ }
+ }
+
+ // Memcache handles garbage collection internally
return TRUE;
}
diff --git a/kohana/libraries/drivers/Cache/Sqlite.php b/kohana/libraries/drivers/Cache/Sqlite.php
index 7413b08c..a86efaba 100644
--- a/kohana/libraries/drivers/Cache/Sqlite.php
+++ b/kohana/libraries/drivers/Cache/Sqlite.php
@@ -91,16 +91,16 @@ class Cache_Sqlite_Driver implements Cache_Driver {
* @param integer lifetime
* @return bool
*/
- public function set($id, $data, $tags, $lifetime)
+ public function set($id, $data, array $tags = NULL, $lifetime)
{
- // Find the data hash
- $hash = sha1($data);
+ // Serialize and escape the data
+ $data = sqlite_escape_string(serialize($data));
- // Escape the data
- $data = sqlite_escape_string($data);
-
- // Escape the tags
- $tags = sqlite_escape_string(implode(',', $tags));
+ if ( ! empty($tags))
+ {
+ // Escape the tags, adding brackets so the tag can be explicitly matched
+ $tags = sqlite_escape_string('<'.implode('>,<', $tags).'>');
+ }
// Cache Sqlite driver expects unix timestamp
if ($lifetime !== 0)
@@ -109,15 +109,21 @@ class Cache_Sqlite_Driver implements Cache_Driver {
}
$query = $this->exists($id)
- ? "UPDATE caches SET hash = '$hash', tags = '$tags', expiration = '$lifetime', cache = '$data' WHERE id = '$id'"
- : "INSERT INTO caches VALUES('$id', '$hash', '$tags', '$lifetime', '$data')";
+ ? "UPDATE caches SET tags = '$tags', expiration = '$lifetime', cache = '$data' WHERE id = '$id'"
+ : "INSERT INTO caches VALUES('$id', '$tags', '$lifetime', '$data')";
// Run the query
$this->db->unbufferedQuery($query, SQLITE_BOTH, $error);
- empty($error) or self::log_error($error);
-
- return empty($error);
+ if ( ! empty($error))
+ {
+ self::log_error($error);
+ return FALSE;
+ }
+ else
+ {
+ return TRUE;
+ }
}
/**
@@ -128,23 +134,32 @@ class Cache_Sqlite_Driver implements Cache_Driver {
*/
public function find($tag)
{
- $query = "SELECT id FROM caches WHERE tags LIKE '%{$tag}%'";
+ $query = "SELECT id,cache FROM caches WHERE tags LIKE '%<{$tag}>%'";
$query = $this->db->query($query, SQLITE_BOTH, $error);
- empty($error) or self::log_error($error);
+ // An array will always be returned
+ $result = array();
- if (empty($error) AND $query->numRows() > 0)
+ if ( ! empty($error))
+ {
+ self::log_error($error);
+ }
+ elseif ($query->numRows() > 0)
{
- $array = array();
+ // Disable notices for unserializing
+ $ER = error_reporting(~E_NOTICE);
+
while ($row = $query->fetchObject())
{
- // Add each id to the array
- $array[] = $row->id;
+ // Add each cache to the array
+ $result[$row->id] = unserialize($row->cache);
}
- return $array;
+
+ // Turn notices back on
+ error_reporting($ER);
}
- return FALSE;
+ return $result;
}
/**
@@ -156,23 +171,31 @@ class Cache_Sqlite_Driver implements Cache_Driver {
*/
public function get($id)
{
- $query = "SELECT id, hash, expiration, cache FROM caches WHERE id = '{$id}' LIMIT 0, 1";
+ $query = "SELECT id, expiration, cache FROM caches WHERE id = '$id' LIMIT 0, 1";
$query = $this->db->query($query, SQLITE_BOTH, $error);
- empty($error) or self::log_error($error);
-
- if (empty($error) AND $cache = $query->fetchObject())
+ if ( ! empty($error))
+ {
+ self::log_error($error);
+ }
+ elseif ($cache = $query->fetchObject())
{
// Make sure the expiration is valid and that the hash matches
- if (($cache->expiration != 0 AND $cache->expiration <= time()) OR $cache->hash !== sha1($cache->cache))
+ if ($cache->expiration != 0 AND $cache->expiration <= time())
{
// Cache is not valid, delete it now
$this->delete($cache->id);
}
else
{
+ // Disable notices for unserializing
+ $ER = error_reporting(~E_NOTICE);
+
// Return the valid cache data
- return $cache->cache;
+ $data = $cache->cache;
+
+ // Turn notices back on
+ error_reporting($ER);
}
}
@@ -184,7 +207,7 @@ class Cache_Sqlite_Driver implements Cache_Driver {
* Deletes a cache item by id or tag
*
* @param string cache id or tag, or TRUE for "all items"
- * @param bool use tags
+ * @param bool delete a tag
* @return bool
*/
public function delete($id, $tag = FALSE)
@@ -194,22 +217,28 @@ class Cache_Sqlite_Driver implements Cache_Driver {
// Delete all caches
$where = '1';
}
- elseif ($tag == FALSE)
+ elseif ($tag === TRUE)
{
- // Delete by id
- $where = "id = '{$id}'";
+ // Delete by tag
+ $where = "tags LIKE '%<{$id}>%'";
}
else
{
- // Delete by tag
- $where = "tags LIKE '%{$tag}%'";
+ // Delete by id
+ $where = "id = '$id'";
}
$this->db->unbufferedQuery('DELETE FROM caches WHERE '.$where, SQLITE_BOTH, $error);
- empty($error) or self::log_error($error);
-
- return empty($error);
+ if ( ! empty($error))
+ {
+ self::log_error($error);
+ return FALSE;
+ }
+ else
+ {
+ return TRUE;
+ }
}
/**
diff --git a/kohana/libraries/drivers/Cache/Xcache.php b/kohana/libraries/drivers/Cache/Xcache.php
index 5d027eec..8d31993a 100644
--- a/kohana/libraries/drivers/Cache/Xcache.php
+++ b/kohana/libraries/drivers/Cache/Xcache.php
@@ -25,9 +25,12 @@ class Cache_Xcache_Driver implements Cache_Driver {
return NULL;
}
- public function set($id, $data, $tags, $lifetime)
+ public function set($id, $data, array $tags = NULL, $lifetime)
{
- count($tags) and Kohana::log('error', 'Cache: tags are unsupported by the Xcache driver');
+ if ( ! empty($tags))
+ {
+ Kohana::log('error', 'Cache: tags are unsupported by the Xcache driver');
+ }
return xcache_set($id, $data, $lifetime);
}