Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Fetching contributors…

Cannot retrieve contributors at this time

1202 lines (1017 sloc) 30.035 kb
<?php defined('SYSPATH') OR die('No direct access allowed.');
/**
* Provides Kohana-specific helper functions. This is where the magic happens!
*
* @package Kohana
* @author Kohana Team
* @copyright (c) 2007-2009 Kohana Team
* @license http://kohanaphp.com/license
*/
// Test of Kohana is running in Windows
define('KOHANA_IS_WIN', DIRECTORY_SEPARATOR === '\\');
abstract class Kohana_Core {
const VERSION = '2.4';
const CODENAME = 'no_codename';
const CHARSET = 'UTF-8';
const LOCALE = 'en_US';
/**
* The singleton instance of the controller
*
* @var object
* @static
*/
public static $instance;
/**
* Output buffering level
*
* @var int
* @static
*/
protected static $buffer_level;
/**
* The final output that will displayed by Kohana
*
* @var string
* @static
*/
public static $output = '';
/**
* The current locale
*
* @var string
* @static
*/
public static $locale;
/**
* Include paths
*
* @var array
* @static
*/
protected static $include_paths;
/**
* Cache lifetime
*
* @var int
* @static
*/
protected static $cache_lifetime;
// Internal caches and write status
protected static $internal_cache = array();
protected static $include_paths_hash = '';
protected static $write_cache;
protected static $internal_cache_path;
protected static $internal_cache_key;
protected static $internal_cache_encrypt;
/**
* Server API that PHP is using. Allows testing of different APIs.
*
* @var string
* @static
*/
public static $server_api = PHP_SAPI;
/**
* Sets up the PHP environment. Adds error/exception handling, output
* buffering, and adds an auto-loading method for loading classes.
*
* This method is run immediately when this file is loaded, and is
* benchmarked as environment_setup.
*
* For security, this function also destroys the $_REQUEST global variable.
* Using the proper global (GET, POST, COOKIE, etc) is inherently more secure.
* The recommended way to fetch a global variable is using the Input library.
* @see http://www.php.net/globals
*
* @return void
*/
public static function setup()
{
static $run;
// Only run this function once
if ($run === TRUE)
return;
$run = TRUE;
// Start the environment setup benchmark
Benchmark::start(SYSTEM_BENCHMARK.'_environment_setup');
// Define Kohana error constant
define('E_KOHANA', 42);
// Define 404 error constant
define('E_PAGE_NOT_FOUND', 43);
// Define database error constant
define('E_DATABASE_ERROR', 44);
// Set the default charset for mb_* functions
mb_internal_encoding(Kohana::CHARSET);
if (Kohana_Config::instance()->loaded() === FALSE)
{
// Re-parse the include paths
Kohana::include_paths(TRUE);
}
if (Kohana::$cache_lifetime = Kohana::config('core.internal_cache'))
{
// Are we using encryption for caches?
Kohana::$internal_cache_encrypt = Kohana::config('core.internal_cache_encrypt');
if(Kohana::$internal_cache_encrypt===TRUE)
{
Kohana::$internal_cache_key = Kohana::config('core.internal_cache_key');
// Be sure the key is of acceptable length for the mcrypt algorithm used
Kohana::$internal_cache_key = substr(Kohana::$internal_cache_key, 0, 24);
}
// Set the directory to be used for the internal cache
if ( ! Kohana::$internal_cache_path = Kohana::config('core.internal_cache_path'))
{
Kohana::$internal_cache_path = APPPATH.'cache/';
}
// Load cached configuration and language files
Kohana::$internal_cache['configuration'] = Kohana::cache('configuration', Kohana::$cache_lifetime);
Kohana::$internal_cache['language'] = Kohana::cache('language', Kohana::$cache_lifetime);
// Load cached file paths
Kohana::$internal_cache['find_file_paths'] = Kohana::cache('find_file_paths', Kohana::$cache_lifetime);
// Enable cache saving
Event::add('system.shutdown', array('Kohana', 'internal_cache_save'));
}
// Start output buffering
ob_start(array('Kohana', 'output_buffer'));
// Save buffering level
Kohana::$buffer_level = ob_get_level();
// Set autoloader
spl_autoload_register(array('Kohana', 'auto_load'));
// Register a shutdown function to handle system.shutdown events
register_shutdown_function(array('Kohana', 'shutdown'));
// Send default text/html UTF-8 header
header('Content-Type: text/html; charset='.Kohana::CHARSET);
// Load i18n
new I18n;
// Enable exception handling
Kohana_Exception::enable();
// Enable error handling
Kohana_PHP_Exception::enable();
// Load locales
$locales = Kohana::config('locale.language');
// Make first locale the defined Kohana charset
$locales[0] .= '.'.Kohana::CHARSET;
// Set locale information
Kohana::$locale = setlocale(LC_ALL, $locales);
// Default to the default locale when none of the user defined ones where accepted
Kohana::$locale = ! Kohana::$locale ? Kohana::LOCALE.'.'.Kohana::CHARSET : Kohana::$locale;
// Set locale for the I18n system
I18n::set_locale(Kohana::$locale);
// Set and validate the timezone
date_default_timezone_set(Kohana::config('locale.timezone'));
// register_globals is enabled
if (ini_get('register_globals'))
{
if (isset($_REQUEST['GLOBALS']))
{
// Prevent GLOBALS override attacks
exit('Global variable overload attack.');
}
// Destroy the REQUEST global
$_REQUEST = array();
// These globals are standard and should not be removed
$preserve = array('GLOBALS', '_REQUEST', '_GET', '_POST', '_FILES', '_COOKIE', '_SERVER', '_ENV', '_SESSION');
// This loop has the same effect as disabling register_globals
foreach (array_diff(array_keys($GLOBALS), $preserve) as $key)
{
global $$key;
$$key = NULL;
// Unset the global variable
unset($GLOBALS[$key], $$key);
}
// Warn the developer about register globals
Kohana_Log::add('debug', 'Disable register_globals! It is evil and deprecated: http://php.net/register_globals');
}
// Enable Kohana routing
Event::add('system.routing', array('Router', 'find_uri'));
Event::add('system.routing', array('Router', 'setup'));
// Enable Kohana controller initialization
Event::add('system.execute', array('Kohana', 'instance'));
// Enable Kohana 404 pages
Event::add('system.404', array('Kohana_404_Exception', 'trigger'));
if (Kohana::config('core.enable_hooks') === TRUE)
{
// Find all the hook files
$hooks = Kohana::list_files('hooks', TRUE);
foreach ($hooks as $file)
{
// Load the hook
include $file;
}
}
// Stop the environment setup routine
Benchmark::stop(SYSTEM_BENCHMARK.'_environment_setup');
}
/**
* Cleans up the PHP environment. Disables error/exception handling and the
* auto-loading method and closes the output buffer.
*
* This method does not need to be called during normal system execution,
* however in some advanced situations it can be helpful. @see #1781
*
* @return void
*/
public static function cleanup()
{
static $run;
// Only run this function once
if ($run === TRUE)
return;
$run = TRUE;
Kohana_Exception::disable();
Kohana_PHP_Exception::disable();
spl_autoload_unregister(array('Kohana', 'auto_load'));
Kohana::close_buffers();
}
/**
* Loads the controller and initializes it. Runs the pre_controller,
* post_controller_constructor, and post_controller events. Triggers
* a system.404 event when the route cannot be mapped to a controller.
*
* This method is benchmarked as controller_setup and controller_execution.
*
* @return object instance of controller
*/
public static function & instance()
{
if (Kohana::$instance === NULL)
{
Benchmark::start(SYSTEM_BENCHMARK.'_controller_setup');
// Include the Controller file
require_once Router::$controller_path;
try
{
// Start validation of the controller
$class = new ReflectionClass(ucfirst(Router::$controller).'_Controller');
}
catch (ReflectionException $e)
{
// Controller does not exist
Event::run('system.404');
}
if ($class->isAbstract() OR (IN_PRODUCTION AND $class->getConstant('ALLOW_PRODUCTION') == FALSE))
{
// Controller is not allowed to run in production
Event::run('system.404');
}
// Run system.pre_controller
Event::run('system.pre_controller');
// Create a new controller instance
$controller = $class->newInstance();
// Controller constructor has been executed
Event::run('system.post_controller_constructor');
try
{
// Load the controller method
$method = $class->getMethod(Router::$method);
// Method exists
if (Router::$method[0] === '_')
{
// Do not allow access to hidden methods
Event::run('system.404');
}
if ($method->isProtected() or $method->isPrivate())
{
// Do not attempt to invoke protected methods
throw new ReflectionException('protected controller method');
}
// Default arguments
$arguments = Router::$arguments;
}
catch (ReflectionException $e)
{
// Use __call instead
$method = $class->getMethod('__call');
// Use arguments in __call format
$arguments = array(Router::$method, Router::$arguments);
}
// Stop the controller setup benchmark
Benchmark::stop(SYSTEM_BENCHMARK.'_controller_setup');
// Start the controller execution benchmark
Benchmark::start(SYSTEM_BENCHMARK.'_controller_execution');
// Execute the controller method
$method->invokeArgs($controller, $arguments);
// Controller method has been executed
Event::run('system.post_controller');
// Stop the controller execution benchmark
Benchmark::stop(SYSTEM_BENCHMARK.'_controller_execution');
}
return Kohana::$instance;
}
/**
* Get all include paths. APPPATH is the first path, followed by module
* paths in the order they are configured, follow by the SYSPATH.
*
* @param boolean $process re-process the include paths
* @return array
*/
public static function include_paths($process = FALSE)
{
if ($process === TRUE)
{
// Add APPPATH as the first path
Kohana::$include_paths = array(APPPATH);
foreach (Kohana::config('core.modules') as $path)
{
if ($path = str_replace('\\', '/', realpath($path)))
{
// Add a valid path
Kohana::$include_paths[] = $path.'/';
}
}
// Add SYSPATH as the last path
Kohana::$include_paths[] = SYSPATH;
// Create a hash of the include paths so we know what cache to use
Kohana::$include_paths_hash = md5(serialize(Kohana::$include_paths));
}
return Kohana::$include_paths;
}
/**
* Get a config item or group proxies Kohana_Config.
*
* @param string $key item name
* @param boolean $slash force a forward slash (/) at the end of the item
* @param boolean $required is the item required?
* @return mixed
*/
public static function config($key, $slash = FALSE, $required = FALSE)
{
return Kohana_Config::instance()->get($key,$slash,$required);
}
/**
* Load data from a simple cache file. This should only be used internally,
* and is NOT a replacement for the Cache library.
*
* @param string $name unique name of cache
* @param integer $lifetime expiration in seconds
* @return mixed
*/
public static function cache($name, $lifetime)
{
if ($lifetime > 0)
{
$path = Kohana::$internal_cache_path.'kohana_'.$name;
if (is_file($path))
{
// Check the file modification time
if ((time() - filemtime($path)) < $lifetime)
{
// Cache is valid! Now, do we need to decrypt it?
if(Kohana::$internal_cache_encrypt === TRUE)
{
$data = file_get_contents($path);
$iv_size = mcrypt_get_iv_size(MCRYPT_RIJNDAEL_256, MCRYPT_MODE_ECB);
$iv = mcrypt_create_iv($iv_size, MCRYPT_RAND);
$decrypted_text = mcrypt_decrypt(MCRYPT_RIJNDAEL_256, Kohana::$internal_cache_key, $data, MCRYPT_MODE_ECB, $iv);
$cache = unserialize($decrypted_text);
// If the key changed, delete the cache file
if( ! $cache)
{
unlink($path);
}
// If cache is false (as above) return NULL, otherwise, return the cache
return ($cache ? $cache : NULL);
}
else
return unserialize(file_get_contents($path));
}
else
{
// Cache is invalid, delete it
unlink($path);
}
}
}
// No cache found
return NULL;
}
/**
* Save data to a simple cache file. This should only be used internally, and
* is NOT a replacement for the Cache library.
*
* @param string $name cache name
* @param mixed $data data to cache
* @param integer $lifetime expiration in seconds
* @return boolean
*/
public static function cache_save($name, $data, $lifetime)
{
if ($lifetime < 1)
return FALSE;
$path = Kohana::$internal_cache_path.'kohana_'.$name;
if ($data === NULL)
{
// Delete cache
return (is_file($path) and unlink($path));
}
else
{
// Using encryption? Encrypt the data when we write it
if(Kohana::$internal_cache_encrypt === TRUE)
{
// Encrypt and write data to cache file
$iv_size = mcrypt_get_iv_size(MCRYPT_RIJNDAEL_256, MCRYPT_MODE_ECB);
$iv = mcrypt_create_iv($iv_size, MCRYPT_RAND);
// Serialize and encrypt!
$encrypted_text = mcrypt_encrypt(MCRYPT_RIJNDAEL_256, Kohana::$internal_cache_key, serialize($data), MCRYPT_MODE_ECB, $iv);
return (bool) file_put_contents($path, $encrypted_text);
}
else
{
// Write data to cache file
return (bool) file_put_contents($path, serialize($data));
}
}
}
/**
* Kohana output handler. Called during ob_clean, ob_flush, and their variants.
*
* @param string $output current output buffer
* @return string
*/
public static function output_buffer($output)
{
// Could be flushing, so send headers first
if ( ! Event::has_run('system.send_headers'))
{
// Run the send_headers event
Event::run('system.send_headers');
}
// Set final output
Kohana::$output = $output;
// Set and return the final output
return Kohana::$output;
}
/**
* Closes all open output buffers, either by flushing or cleaning, and stores
* output buffer for display during shutdown.
*
* @param boolean $flush disable to clear buffers, rather than flushing
* @return void
*/
public static function close_buffers($flush = TRUE)
{
if (ob_get_level() >= Kohana::$buffer_level)
{
// Set the close function
$close = ($flush === TRUE) ? 'ob_end_flush' : 'ob_end_clean';
while (ob_get_level() > Kohana::$buffer_level)
{
// Flush or clean the buffer
$close();
}
// Store the Kohana output buffer
ob_end_clean();
}
}
/**
* Triggers the shutdown of Kohana by closing the output buffer, runs the system.shutdown and system.display event.
*
* @return void
*/
public static function shutdown()
{
static $run;
// Only run this function once
if ($run === TRUE)
return;
$run = TRUE;
// Run system.shutdown event
Event::run('system.shutdown');
// Close output buffers
Kohana::close_buffers(TRUE);
// Run the output event
Event::run('system.display', Kohana::$output);
// Render the final output
Kohana::render(Kohana::$output);
}
/**
* Inserts global Kohana variables into the generated output and prints it.
*
* @param string $output final output that will displayed
* @return void
*/
public static function render($output)
{
if (empty($output))
return '';
if (Kohana::config('core.render_stats') === TRUE)
{
// Fetch memory usage in MB
$memory = function_exists('memory_get_usage') ? (memory_get_usage() / 1024 / 1024) : 0;
// Fetch benchmark for page execution time
$benchmark = Benchmark::get(SYSTEM_BENCHMARK.'_total_execution');
// Replace the global template variables
$output = str_replace(
array
(
'{kohana_version}',
'{kohana_codename}',
'{execution_time}',
'{memory_usage}',
'{included_files}',
),
array
(
KOHANA::VERSION,
KOHANA::CODENAME,
$benchmark['time'],
number_format($memory, 2).'MB',
count(get_included_files()),
),
$output
);
}
if ($level = Kohana::config('core.output_compression') AND ini_get('output_handler') !== 'ob_gzhandler' AND (int) ini_get('zlib.output_compression') === 0)
{
if ($compress = request::preferred_encoding(array('gzip','deflate'), TRUE))
{
if ($level < 1 OR $level > 9)
{
// Normalize the level to be an integer between 1 and 9. This
// step must be done to prevent gzencode from triggering an error
$level = max(1, min($level, 9));
}
if ($compress === 'gzip')
{
// Compress output using gzip
$output = gzencode($output, $level);
}
elseif ($compress === 'deflate')
{
// Compress output using zlib (HTTP deflate)
$output = gzdeflate($output, $level);
}
// This header must be sent with compressed content to prevent
// browser caches from breaking
header('Vary: Accept-Encoding');
// Send the content encoding header
header('Content-Encoding: '.$compress);
// Sending Content-Length in CGI can result in unexpected behavior
if (stripos(Kohana::$server_api, 'cgi') === FALSE)
{
header('Content-Length: '.strlen($output));
}
}
}
echo $output;
}
/**
* Auto-loads a file in the cascading file system.
* Mainly called manually for loading driver files.
* Used by spl_autoload_register for native class autoloading
*
* ##### Example
*
* echo var_dump(Kohana::auto_load('Log_File_Driver');
*
* // Output:
* (integer) true
*
* @throws Kohana_Exception
* @param string $class name of class
* @return bool
*/
public static function auto_load($class)
{
if (class_exists($class, FALSE) OR interface_exists($class, FALSE))
return TRUE;
if (($suffix = strrpos($class, '_')) > 0)
{
// Find the class suffix
$suffix = substr($class, $suffix + 1);
}
else
{
// No suffix
$suffix = FALSE;
}
if ($suffix === 'Core')
{
$type = 'libraries';
$file = substr($class, 0, -5);
}
elseif ($suffix === 'Controller')
{
$type = 'controllers';
// Lowercase filename
$file = strtolower(substr($class, 0, -11));
}
elseif ($suffix === 'Model')
{
$type = 'models';
// Lowercase filename
$file = strtolower(substr($class, 0, -6));
}
elseif ($suffix === 'Driver')
{
$type = 'libraries/drivers';
$file = str_replace('_', '/', substr($class, 0, -7));
}
else
{
// This could be either a library or a helper, but libraries must
// always be capitalized, so we check if the first character is
// uppercase. If it is, we are loading a library, not a helper.
$type = ($class[0] < 'a') ? 'libraries' : 'helpers';
$file = $class;
}
if ($filename = Kohana::find_file($type, $file))
{
// Load the class
require $filename;
}
else
{
// The class could not be found
return FALSE;
}
if ($filename = Kohana::find_file($type, Kohana::config('core.extension_prefix').$class))
{
// Load the class extension
require $filename;
}
elseif ($suffix !== 'Core' AND class_exists($class.'_Core', FALSE))
{
// Class extension to be evaluated
$extension = 'class '.$class.' extends '.$class.'_Core { }';
// Start class analysis
$core = new ReflectionClass($class.'_Core');
if ($core->isAbstract())
{
// Make the extension abstract
$extension = 'abstract '.$extension;
}
// Transparent class extensions are handled using eval. This is
// a disgusting hack, but it gets the job done.
eval($extension);
}
return TRUE;
}
/**
* Find a resource file in a given directory. Files will be located according
* to the order of the include paths. Configuration, messages and i18n files will be
* returned in reverse order.
*
* Returns a full path name to the file, or an array of path names for config, messages and i18n.
*
* ##### Example
*
* // Extending a controller in a sub-directory (controllers/admin/admin_website.php)
* <?php
* include Kohana::find_file('controllers', 'admin/admin_website');
* class Home_Controller extends Admin_Website_Controller {}
*
* // Finding a list of all configuration files
* echo Kohana::debug(Kohana::find_file('config', 'testing'));
*
* // Output:
* array('/full/path/to/testing.php', '/different/full/path/to/testing.php')
*
* @throws Kohana_Exception if file is required and not found
* @param string $directory directory to search in
* @param string $filename filename to look for (without extension)
* @param boolean $required file required
* @param string $ext file extension
* @return array if the type is config, i18n or l10n
* @return string if the file is found
* @return FALSE if the file is not found
*/
public static function find_file($directory, $filename, $required = FALSE, $ext = FALSE)
{
// NOTE: This test MUST be not be a strict comparison (===), or empty
// extensions will be allowed!
if ($ext == '')
{
// Use the default extension
$ext = EXT;
}
else
{
// Add a period before the extension
$ext = '.'.$ext;
}
// Search path
$search = $directory.'/'.$filename.$ext;
if (isset(Kohana::$internal_cache['find_file_paths'][Kohana::$include_paths_hash][$search]))
return Kohana::$internal_cache['find_file_paths'][Kohana::$include_paths_hash][$search];
// Load include paths
$paths = Kohana::$include_paths;
// Nothing found, yet
$found = NULL;
if ($directory === 'config' OR $directory === 'messages' OR $directory === 'i18n')
{
// Search in reverse, for merging
$paths = array_reverse($paths);
foreach ($paths as $path)
{
if (is_file($path.$search))
{
// A matching file has been found
$found[] = $path.$search;
}
}
}
else
{
foreach ($paths as $path)
{
if (is_file($path.$search))
{
// A matching file has been found
$found = $path.$search;
// Stop searching
break;
}
}
}
if ($found === NULL)
{
if ($required === TRUE)
{
// If the file is required, throw an exception
throw new Kohana_Exception('The requested :resource:, :file:, could not be found', array(':resource:' => __($directory), ':file:' =>$filename));
}
else
{
// Nothing was found, return FALSE
$found = FALSE;
}
}
if ( ! isset(Kohana::$write_cache['find_file_paths']))
{
// Write cache at shutdown
Kohana::$write_cache['find_file_paths'] = TRUE;
}
return Kohana::$internal_cache['find_file_paths'][Kohana::$include_paths_hash][$search] = $found;
}
/**
* Lists all files and directories in a resource path.
*
* @param string $directory directory to search
* @param boolean $recursive list all files to the maximum depth?
* @param string $ext list all files having extension $ext
* @param string $path full path to search (used for recursion, *never* set this manually)
* @return array filenames and directories
*/
public static function list_files($directory, $recursive = FALSE, $ext = EXT, $path = FALSE)
{
$files = array();
if ($path === FALSE)
{
$paths = array_reverse(Kohana::include_paths());
foreach ($paths as $path)
{
// Recursively get and merge all files
$files = array_merge($files, Kohana::list_files($directory, $recursive, $ext, $path.$directory));
}
}
else
{
$path = rtrim($path, '/').'/';
if (is_readable($path) AND $items = glob($path.'*'))
{
$ext_pos = 0 - strlen($ext);
foreach ($items as $index => $item)
{
$item = str_replace('\\', '/', $item);
if (is_dir($item))
{
// Handle recursion
if ($recursive === TRUE)
{
// Filename should only be the basename
$item = pathinfo($item, PATHINFO_BASENAME);
// Append sub-directory search
$files = array_merge($files, Kohana::list_files($directory, TRUE, $ext, $path.$item));
}
}
else
{
// File extension must match
if ($ext_pos === 0 OR substr($item, $ext_pos) === $ext)
{
$files[] = $item;
}
}
}
}
}
return $files;
}
/**
* Fetch a message item. You can specify a folder name by using a / seperator
* Uses the standard dot seperated key syntax to access the data in the file.
*
* #### Example
*
* // Fetches a message item from a file in messages/testing/my_test.php
* echo Kohana::message('testing/my_test.key1');
*
* //Output:
* 'Whatever is in key1'
*
* @param string $key message key to fetch
* @param array $args additional information to insert into the line
* @return string i18n language string, or the requested key if the i18n item is not found
*/
public static function message($key, $args = array())
{
// Extract the main group from the key
$group = explode('.', $key, 2);
$group = $group[0];
if ( ! isset(Kohana::$internal_cache['messages'][$group]))
{
// Messages for this group
$messages = array();
if ($file = Kohana::find_file('messages', $group))
{
include $file[0];
}
if ( ! isset(Kohana::$write_cache['messages']))
{
// Write language cache
Kohana::$write_cache['messages'] = TRUE;
}
Kohana::$internal_cache['messages'][$group] = $messages;
}
// Get the line from cache
$line = Kohana::key_string(Kohana::$internal_cache['messages'], $key);
if ($line === NULL)
{
Kohana_Log::add('error', 'Missing messages entry '.$key.' for message '.$group);
// Return the key string as fallback
return $key;
}
if (is_string($line) AND func_num_args() > 1)
{
$args = array_slice(func_get_args(), 1);
// Add the arguments into the line
$line = vsprintf($line, is_array($args[0]) ? $args[0] : $args);
}
return $line;
}
/**
* Returns the value of a key, defined by a 'dot-noted' string, from an array.
*
* #### Exampls
*
* $source = array('key1' => array('key2' => 'foobar'))
* echo Kohana::key_string($source, 'key1.key2');
*
* //Output:
* 'foobar'
*
* @param array $array array to search
* @param string $keys dot-noted string: foo.bar.baz
* @return string if the key is found
* @return void if the key is not found
*/
public static function key_string($array, $keys)
{
if (empty($array))
return NULL;
// Prepare for loop
$keys = explode('.', $keys);
do
{
// Get the next key
$key = array_shift($keys);
if (isset($array[$key]))
{
if (is_array($array[$key]) AND ! empty($keys))
{
// Dig down to prepare the next loop
$array = $array[$key];
}
else
{
// Requested key was found
return $array[$key];
}
}
else
{
// Requested key is not set
break;
}
}
while ( ! empty($keys));
return NULL;
}
/**
* Sets values in an array by using a 'dot-noted' string.
*
* #### Exampls
*
* $source = array('key1' => array('key2' => 'foobar'))
* Kohana::key_string_set($source, 'key1.key2', 'bar');
* echo Kohana::key_string($source, 'key1.key2');
*
* //Output:
* 'bar'
*
* @param array $array array to set keys in (reference)
* @param string $keys dot-noted string: foo.bar.baz
* @return mixed $fill fill value for the key
* @return void
*/
public static function key_string_set( & $array, $keys, $fill = NULL)
{
if (is_object($array) AND ($array instanceof ArrayObject))
{
// Copy the array
$array_copy = $array->getArrayCopy();
// Is an object
$array_object = TRUE;
}
else
{
if ( ! is_array($array))
{
// Must always be an array
$array = (array) $array;
}
// Copy is a reference to the array
$array_copy =& $array;
}
if (empty($keys))
return $array;
// Create keys
$keys = explode('.', $keys);
// Create reference to the array
$row =& $array_copy;
for ($i = 0, $end = count($keys) - 1; $i <= $end; $i++)
{
// Get the current key
$key = $keys[$i];
if ( ! isset($row[$key]))
{
if (isset($keys[$i + 1]))
{
// Make the value an array
$row[$key] = array();
}
else
{
// Add the fill key
$row[$key] = $fill;
}
}
elseif (isset($keys[$i + 1]))
{
// Make the value an array
$row[$key] = (array) $row[$key];
}
// Go down a level, creating a new row reference
$row =& $row[$key];
}
if (isset($array_object))
{
// Swap the array back in
$array->exchangeArray($array_copy);
}
}
/**
* Quick debugging of any variable. Any number of parameters can be set.
*
* @return string
*/
public static function debug()
{
if (func_num_args() === 0)
return;
// Get params
$params = func_get_args();
$output = array();
foreach ($params as $var)
{
$value = is_bool($var) ? ($var ? 'true' : 'false') : print_r($var, TRUE);
$output[] = '<pre>('.gettype($var).') '.htmlspecialchars($value, ENT_QUOTES, Kohana::CHARSET).'</pre>';
}
return implode("\n", $output);
}
/**
* Saves the internal caches: configuration, include paths, etc. Used internally
*
* @return boolean
*/
public static function internal_cache_save()
{
if ( ! is_array(Kohana::$write_cache))
return FALSE;
// Get internal cache names
$caches = array_keys(Kohana::$write_cache);
// Nothing written
$written = FALSE;
foreach ($caches as $cache)
{
if (isset(Kohana::$internal_cache[$cache]))
{
// Write the cache file
Kohana::cache_save($cache, Kohana::$internal_cache[$cache], Kohana::config('core.internal_cache'));
// A cache has been written
$written = TRUE;
}
}
return $written;
}
} // End Kohana
Jump to Line
Something went wrong with that request. Please try again.