diff options
Diffstat (limited to 'system')
151 files changed, 8067 insertions, 4473 deletions
diff --git a/system/core/Benchmark.php b/system/core/Benchmark.php index 2fabdf46e..e80ee54dd 100644 --- a/system/core/Benchmark.php +++ b/system/core/Benchmark.php @@ -1,4 +1,4 @@ -<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed'); +<?php /** * CodeIgniter * @@ -24,9 +24,10 @@ * @since Version 1.0 * @filesource */ +defined('BASEPATH') OR exit('No direct script access allowed'); /** - * CodeIgniter Benchmark Class + * Benchmark Class * * This class enables you to mark points and calculate the time difference * between them. Memory consumption can also be displayed. @@ -40,21 +41,19 @@ class CI_Benchmark { /** - * List of all benchmark markers and when they were added + * List of all benchmark markers * - * @var array + * @var array */ - public $marker = array(); - - // -------------------------------------------------------------------- + public $marker = array(); /** * Set a benchmark marker * * Multiple calls to this function can be made so that several - * execution points can be timed + * execution points can be timed. * - * @param string $name name of the marker + * @param string $name Marker name * @return void */ public function mark($name) @@ -65,6 +64,8 @@ class CI_Benchmark { // -------------------------------------------------------------------- /** + * Elapsed time + * * Calculates the time difference between two marked points. * * If the first parameter is empty this function instead returns the @@ -72,10 +73,13 @@ class CI_Benchmark { * execution time to be shown in a template. The output class will * swap the real value for this variable. * - * @param string a particular marked point - * @param string a particular marked point - * @param integer the number of decimal places - * @return mixed + * @param string $point1 A particular marked point + * @param string $point2 A particular marked point + * @param int $decimals Number of decimal places + * + * @return string Calculated elapsed time on success, + * an '{elapsed_string}' if $point1 is empty + * or an empty string if $point1 is not found. */ public function elapsed_time($point1 = '', $point2 = '', $decimals = 4) { @@ -102,12 +106,13 @@ class CI_Benchmark { /** * Memory Usage * - * This function returns the {memory_usage} pseudo-variable. + * Simply returns the {memory_usage} marker. + * * This permits it to be put it anywhere in a template * without the memory being calculated until the end. * The output class will swap the real value for this variable. * - * @return string + * @return string '{memory_usage}' */ public function memory_usage() { diff --git a/system/core/CodeIgniter.php b/system/core/CodeIgniter.php index 8159b19f5..1cd6403bf 100644 --- a/system/core/CodeIgniter.php +++ b/system/core/CodeIgniter.php @@ -1,4 +1,4 @@ -<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed'); +<?php /** * CodeIgniter * @@ -24,6 +24,7 @@ * @since Version 1.0 * @filesource */ +defined('BASEPATH') OR exit('No direct script access allowed'); /** * System Initialization File @@ -50,7 +51,7 @@ * Load the global functions * ------------------------------------------------------ */ - require(BASEPATH.'core/Common.php'); + require_once(BASEPATH.'core/Common.php'); /* * ------------------------------------------------------ @@ -130,9 +131,12 @@ $CFG =& load_class('Config', 'core'); // Do we have any manually set config items in the index.php file? - if (isset($assign_to_config)) + if (isset($assign_to_config) && is_array($assign_to_config)) { - $CFG->_assign_to_config($assign_to_config); + foreach ($assign_to_config as $key => $value) + { + $CFG->set_item($key, $value); + } } /* @@ -229,7 +233,6 @@ return CI_Controller::get_instance(); } - if (file_exists(APPPATH.'core/'.$CFG->config['subclass_prefix'].'Controller.php')) { require APPPATH.'core/'.$CFG->config['subclass_prefix'].'Controller.php'; @@ -253,23 +256,22 @@ * Security check * ------------------------------------------------------ * - * None of the functions in the app controller or the + * None of the methods in the app controller or the * loader class can be called via the URI, nor can - * controller functions that begin with an underscore + * controller functions that begin with an underscore. */ $class = $RTR->fetch_class(); $method = $RTR->fetch_method(); - if ( ! class_exists($class) - OR strpos($method, '_') === 0 - OR in_array(strtolower($method), array_map('strtolower', get_class_methods('CI_Controller'))) - ) + if ( ! class_exists($class) OR $method[0] === '_' OR method_exists('CI_Controller', $method)) { if ( ! empty($RTR->routes['404_override'])) { - $x = explode('/', $RTR->routes['404_override'], 2); - $class = $x[0]; - $method = isset($x[1]) ? $x[1] : 'index'; + if (sscanf($RTR->routes['404_override'], '%[^/]/%s', $class, $method) !== 2) + { + $method = 'index'; + } + if ( ! class_exists($class)) { if ( ! file_exists(APPPATH.'controllers/'.$class.'.php')) @@ -286,6 +288,38 @@ } } + if (method_exists($class, '_remap')) + { + $params = array($method, array_slice($URI->rsegments, 2)); + $method = '_remap'; + } + else + { + if ( ! is_callable(array($class, $method))) + { + if (empty($RTR->routes['404_override'])) + { + show_404($class.'/'.$method); + } + elseif (sscanf($RTR->routes['404_override'], '%[^/]/%s', $class, $method) !== 2) + { + $method = 'index'; + } + + if ( ! class_exists($class)) + { + if ( ! file_exists(APPPATH.'controllers/'.$class.'.php')) + { + show_404($class.'/'.$method); + } + + include_once(APPPATH.'controllers/'.$class.'.php'); + } + } + + $params = array_slice($URI->rsegments, 2); + } + /* * ------------------------------------------------------ * Is there a "pre_controller" hook? @@ -315,45 +349,7 @@ * Call the requested method * ------------------------------------------------------ */ - // Is there a "remap" function? If so, we call it instead - if (method_exists($CI, '_remap')) - { - $CI->_remap($method, array_slice($URI->rsegments, 2)); - } - else - { - // is_callable() returns TRUE on some versions of PHP 5 for private and protected - // methods, so we'll use this workaround for consistent behavior - if ( ! in_array(strtolower($method), array_map('strtolower', get_class_methods($CI)))) - { - // Check and see if we are using a 404 override and use it. - if ( ! empty($RTR->routes['404_override'])) - { - $x = explode('/', $RTR->routes['404_override'], 2); - $class = $x[0]; - $method = isset($x[1]) ? $x[1] : 'index'; - if ( ! class_exists($class)) - { - if ( ! file_exists(APPPATH.'controllers/'.$class.'.php')) - { - show_404($class.'/'.$method); - } - - include_once(APPPATH.'controllers/'.$class.'.php'); - unset($CI); - $CI = new $class(); - } - } - else - { - show_404($class.'/'.$method); - } - } - - // Call the requested method. - // Any URI segments present (besides the class/function) will be passed to the method for convenience - call_user_func_array(array(&$CI, $method), array_slice($URI->rsegments, 2)); - } + call_user_func_array(array(&$CI, $method), $params); // Mark a benchmark end point $BM->mark('controller_execution_time_( '.$class.' / '.$method.' )_end'); diff --git a/system/core/Common.php b/system/core/Common.php index 57374b07d..3b7ea6ad4 100644 --- a/system/core/Common.php +++ b/system/core/Common.php @@ -1,4 +1,4 @@ -<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed'); +<?php /** * CodeIgniter * @@ -24,6 +24,7 @@ * @since Version 1.0 * @filesource */ +defined('BASEPATH') OR exit('No direct script access allowed'); /** * Common Functions @@ -150,7 +151,7 @@ if ( ! function_exists('load_class')) if (class_exists($name) === FALSE) { - require($path.$directory.'/'.$class.'.php'); + require_once($path.$directory.'/'.$class.'.php'); } break; @@ -164,7 +165,7 @@ if ( ! function_exists('load_class')) if (class_exists($name) === FALSE) { - require(APPPATH.$directory.'/'.config_item('subclass_prefix').$class.'.php'); + require_once(APPPATH.$directory.'/'.config_item('subclass_prefix').$class.'.php'); } } @@ -330,6 +331,24 @@ if ( ! function_exists('get_mimes')) // ------------------------------------------------------------------------ +if ( ! function_exists('is_https')) +{ + /** + * Is HTTPS? + * + * Determines if the application is accessed via an encrypted + * (HTTPS) connection. + * + * @return bool + */ + function is_https() + { + return ( ! empty($_SERVER['HTTPS']) && strtolower($_SERVER['HTTPS']) !== 'off'); + } +} + +// ------------------------------------------------------------------------ + if ( ! function_exists('show_error')) { /** @@ -488,13 +507,9 @@ if ( ! function_exists('set_status_header')) { header('Status: '.$code.' '.$text, TRUE); } - elseif ($server_protocol === 'HTTP/1.0') - { - header('HTTP/1.0 '.$code.' '.$text, TRUE, $code); - } else { - header('HTTP/1.1 '.$code.' '.$text, TRUE, $code); + header(($server_protocol ? $server_protocol : 'HTTP/1.1').' '.$code.' '.$text, TRUE, $code); } } } @@ -524,18 +539,17 @@ if ( ! function_exists('_exception_handler')) { $_error =& load_class('Exceptions', 'core'); - // Should we display the error? We'll get the current error_reporting + // Should we ignore the error? We'll get the current error_reporting // level and add its bits with the severity bits to find out. - // And respect display_errors - if (($severity & error_reporting()) === $severity && (bool) ini_get('display_errors') === TRUE) + if (($severity & error_reporting()) !== $severity) { - $_error->show_php_error($severity, $message, $filepath, $line); + return; } - // Should we log the error? No? We're done... - if (config_item('log_threshold') === 0) + // Should we display the error? + if ((bool) ini_get('display_errors') === TRUE) { - return; + $_error->show_php_error($severity, $message, $filepath, $line); } $_error->log_exception($severity, $message, $filepath, $line); diff --git a/system/core/Config.php b/system/core/Config.php index 2f6a9e085..8250b5b1a 100644 --- a/system/core/Config.php +++ b/system/core/Config.php @@ -1,4 +1,4 @@ -<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed'); +<?php /** * CodeIgniter * @@ -24,9 +24,10 @@ * @since Version 1.0 * @filesource */ +defined('BASEPATH') OR exit('No direct script access allowed'); /** - * CodeIgniter Config Class + * Config Class * * This class contains functions that enable config files to be managed * @@ -41,29 +42,31 @@ class CI_Config { /** * List of all loaded config values * - * @var array + * @var array */ public $config = array(); /** * List of all loaded config files * - * @var array + * @var array */ public $is_loaded = array(); /** * List of paths to search when trying to load a config file. - * This must be public as it's used by the Loader class. * - * @var array + * @used-by CI_Loader + * @var array */ public $_config_paths = array(APPPATH); /** - * Constructor + * Class constructor * - * Sets the $config data from the primary config.php file as a class variable + * Sets the $config data from the primary config.php file as a class variable. + * + * @return void */ public function __construct() { @@ -75,7 +78,7 @@ class CI_Config { { if (isset($_SERVER['HTTP_HOST'])) { - $base_url = ( ! empty($_SERVER['HTTPS']) && strtolower($_SERVER['HTTPS']) !== 'off') ? 'https' : 'http'; + $base_url = is_https() ? 'https' : 'http'; $base_url .= '://'.$_SERVER['HTTP_HOST'] .str_replace(basename($_SERVER['SCRIPT_NAME']), '', $_SERVER['SCRIPT_NAME']); } @@ -93,16 +96,16 @@ class CI_Config { /** * Load Config File * - * @param string the config file name - * @param bool if configuration values should be loaded into their own section - * @param bool true if errors should just return false, false if an error message should be displayed - * @return bool if the file was loaded correctly + * @param string $file Configuration file name + * @param bool $use_sections Whether configuration values should be loaded into their own section + * @param bool $fail_gracefully Whether to just return FALSE or display an error message + * @return bool TRUE if the file was loaded correctly or FALSE on failure */ public function load($file = '', $use_sections = FALSE, $fail_gracefully = FALSE) { $file = ($file === '') ? 'config' : str_replace('.php', '', $file); $found = $loaded = FALSE; - + $check_locations = defined('ENVIRONMENT') ? array(ENVIRONMENT.'/'.$file, $file) : array($file); @@ -183,9 +186,9 @@ class CI_Config { /** * Fetch a config file item * - * @param string the config item name - * @param string the index name - * @return string + * @param string $item Config item name + * @param string $index Index name + * @return string|bool The configuration item or FALSE on failure */ public function item($item, $index = '') { @@ -200,10 +203,10 @@ class CI_Config { // -------------------------------------------------------------------- /** - * Fetch a config file item - adds slash after item (if item is not empty) + * Fetch a config file item with slash appended (if not empty) * - * @param string the config item name - * @return string + * @param string $item Config item name + * @return string|bool The configuration item or FALSE on failure */ public function slash_item($item) { @@ -223,9 +226,12 @@ class CI_Config { /** * Site URL + * * Returns base_url . index_page [. uri_string] * - * @param mixed the URI string or an array of segments + * @uses CI_Config::_uri_string() + * + * @param string|string[] $uri URI string or an array of segments * @return string */ public function site_url($uri = '') @@ -264,9 +270,12 @@ class CI_Config { /** * Base URL + * * Returns base_url [. uri_string] * - * @param string $uri + * @uses CI_Config::_uri_string() + * + * @param string|string[] $uri URI string or an array of segments * @return string */ public function base_url($uri = '') @@ -277,9 +286,12 @@ class CI_Config { // ------------------------------------------------------------- /** - * Build URI string for use in Config::site_url() and Config::base_url() + * Build URI string * - * @param mixed $uri + * @used-by CI_Config::site_url() + * @used-by CI_Config::base_url() + * + * @param string|string[] $uri URI string or an array of segments * @return string */ protected function _uri_string($uri) @@ -318,8 +330,8 @@ class CI_Config { /** * Set a config file item * - * @param string the config item key - * @param string the config item value + * @param string $item Config item key + * @param string $value Config item value * @return void */ public function set_item($item, $value) @@ -327,29 +339,6 @@ class CI_Config { $this->config[$item] = $value; } - // -------------------------------------------------------------------- - - /** - * Assign to Config - * - * This function is called by the front controller (CodeIgniter.php) - * after the Config class is instantiated. It permits config items - * to be assigned or overriden by variables contained in the index.php file - * - * @param array - * @return void - */ - public function _assign_to_config($items = array()) - { - if (is_array($items)) - { - foreach ($items as $key => $val) - { - $this->set_item($key, $val); - } - } - } - } /* End of file Config.php */ diff --git a/system/core/Controller.php b/system/core/Controller.php index 491414807..ee6fec8d5 100644 --- a/system/core/Controller.php +++ b/system/core/Controller.php @@ -1,4 +1,4 @@ -<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed'); +<?php /** * CodeIgniter * @@ -24,9 +24,10 @@ * @since Version 1.0 * @filesource */ +defined('BASEPATH') OR exit('No direct script access allowed'); /** - * CodeIgniter Application Controller Class + * Application Controller Class * * This class object is the super class that every library in * CodeIgniter will be assigned to. @@ -40,14 +41,14 @@ class CI_Controller { /** - * Reference to the global CI instance + * Reference to the CI singleton * * @var object */ private static $instance; /** - * Set up controller properties and methods + * Class constructor * * @return void */ @@ -68,9 +69,12 @@ class CI_Controller { log_message('debug', 'Controller Class Initialized'); } + // -------------------------------------------------------------------- + /** - * Return the CI object + * Get the CI singleton * + * @static * @return object */ public static function &get_instance() diff --git a/system/core/Exceptions.php b/system/core/Exceptions.php index bd9178dbd..ced65ece4 100644 --- a/system/core/Exceptions.php +++ b/system/core/Exceptions.php @@ -1,4 +1,4 @@ -<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed'); +<?php /** * CodeIgniter * @@ -24,6 +24,7 @@ * @since Version 1.0 * @filesource */ +defined('BASEPATH') OR exit('No direct script access allowed'); /** * Exceptions Class @@ -64,7 +65,7 @@ class CI_Exceptions { ); /** - * Initialize execption class + * Class constructor * * @return void */ @@ -79,12 +80,12 @@ class CI_Exceptions { /** * Exception Logger * - * This function logs PHP generated error messages + * Logs PHP generated error messages * - * @param string the error severity - * @param string the error string - * @param string the error filepath - * @param string the error line number + * @param int $severity Log level + * @param string $message Error message + * @param string $filepath File path + * @param int $line Line number * @return void */ public function log_exception($severity, $message, $filepath, $line) @@ -96,11 +97,13 @@ class CI_Exceptions { // -------------------------------------------------------------------- /** - * 404 Page Not Found Handler + * 404 Error Handler * - * @param string the page - * @param bool log error yes/no - * @return string + * @uses CI_Exceptions::show_error() + * + * @param string $page Page URI + * @param bool $log_error Whether to log the error + * @return void */ public function show_404($page = '', $log_error = TRUE) { @@ -122,15 +125,15 @@ class CI_Exceptions { /** * General Error Page * - * This function takes an error message as input - * (either as a string or an array) and displays - * it using the specified template. + * Takes an error message as input (either as a string or an array) + * and displays it using the specified template. + * + * @param string $heading Page heading + * @param string|string[] $message Error message + * @param string $template Template name + * @param int $status_code (default: 500) * - * @param string the heading - * @param string the message - * @param string the template name - * @param int the status code - * @return string + * @return string Error page output */ public function show_error($heading, $message, $template = 'error_general', $status_code = 500) { @@ -154,11 +157,11 @@ class CI_Exceptions { /** * Native PHP error handler * - * @param string the error severity - * @param string the error string - * @param string the error filepath - * @param string the error line number - * @return string + * @param int $severity Error level + * @param string $message Error message + * @param string $filepath File path + * @param int $line Line number + * @return string Error page output */ public function show_php_error($severity, $message, $filepath, $line) { diff --git a/system/core/Hooks.php b/system/core/Hooks.php index afbf4b453..3c28ec9ba 100644 --- a/system/core/Hooks.php +++ b/system/core/Hooks.php @@ -1,4 +1,4 @@ -<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed'); +<?php /** * CodeIgniter * @@ -24,9 +24,10 @@ * @since Version 1.0 * @filesource */ +defined('BASEPATH') OR exit('No direct script access allowed'); /** - * CodeIgniter Hooks Class + * Hooks Class * * Provides a mechanism to extend the base system without hacking. * @@ -41,26 +42,28 @@ class CI_Hooks { /** * Determines whether hooks are enabled * - * @var bool + * @var bool */ - public $enabled = FALSE; + public $enabled = FALSE; /** * List of all hooks set in config/hooks.php * - * @var array + * @var array */ public $hooks = array(); /** + * In progress flag + * * Determines whether hook is in progress, used to prevent infinte loops * - * @var bool + * @var bool */ - public $in_progress = FALSE; + protected $_in_progress = FALSE; /** - * Initialize the Hooks Preferences + * Class constructor * * @return void */ @@ -104,8 +107,10 @@ class CI_Hooks { * * Calls a particular hook. Called by CodeIgniter.php. * - * @param string the hook name - * @return mixed + * @uses CI_Hooks::_run_hook() + * + * @param string $which Hook name + * @return bool TRUE on success or FALSE on failure */ public function call_hook($which = '') { @@ -136,8 +141,8 @@ class CI_Hooks { * * Runs a particular hook * - * @param array the hook details - * @return bool + * @param array $data Hook details + * @return bool TRUE on success or FALSE on failure */ protected function _run_hook($data) { @@ -152,7 +157,7 @@ class CI_Hooks { // If the script being called happens to have the same // hook call within it a loop can happen - if ($this->in_progress === TRUE) + if ($this->_in_progress === TRUE) { return; } @@ -173,44 +178,20 @@ class CI_Hooks { return FALSE; } - // ----------------------------------- - // Set class/function name - // ----------------------------------- - - $class = FALSE; - $function = FALSE; - $params = ''; - - if ( ! empty($data['class'])) - { - $class = $data['class']; - } - - if ( ! empty($data['function'])) - { - $function = $data['function']; - } - - if (isset($data['params'])) - { - $params = $data['params']; - } + // Determine and class and/or function names + $class = empty($data['class']) ? FALSE : $data['class']; + $function = empty($data['function']) ? FALSE : $data['function']; + $params = isset($data['params']) ? $data['params'] : ''; if ($class === FALSE && $function === FALSE) { return FALSE; } - // ----------------------------------- - // Set the in_progress flag - // ----------------------------------- - - $this->in_progress = TRUE; + // Set the _in_progress flag + $this->_in_progress = TRUE; - // ----------------------------------- // Call the requested class and/or function - // ----------------------------------- - if ($class !== FALSE) { if ( ! class_exists($class)) @@ -218,7 +199,7 @@ class CI_Hooks { require($filepath); } - $HOOK = new $class; + $HOOK = new $class(); $HOOK->$function($params); } else @@ -231,7 +212,7 @@ class CI_Hooks { $function($params); } - $this->in_progress = FALSE; + $this->_in_progress = FALSE; return TRUE; } diff --git a/system/core/Input.php b/system/core/Input.php index d7bfed3f8..c0158df99 100644 --- a/system/core/Input.php +++ b/system/core/Input.php @@ -1,4 +1,4 @@ -<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed'); +<?php /** * CodeIgniter * @@ -24,6 +24,7 @@ * @since Version 1.0 * @filesource */ +defined('BASEPATH') OR exit('No direct script access allowed'); /** * Input Class @@ -41,59 +42,68 @@ class CI_Input { /** * IP address of the current user * - * @var string + * @var string */ - public $ip_address = FALSE; + public $ip_address = FALSE; /** - * user agent (web browser) being used by the current user + * User agent strin * - * @var string + * @var string */ - public $user_agent = FALSE; + public $user_agent = FALSE; /** - * If FALSE, then $_GET will be set to an empty array + * Allow GET array flag * - * @var bool + * If set to FALSE, then $_GET will be set to an empty array. + * + * @var bool */ - protected $_allow_get_array = TRUE; + protected $_allow_get_array = TRUE; /** - * If TRUE, then newlines are standardized + * Standartize new lines flag + * + * If set to TRUE, then newlines are standardized. * - * @var bool + * @var bool */ - protected $_standardize_newlines = TRUE; + protected $_standardize_newlines = TRUE; /** - * Determines whether the XSS filter is always active when GET, POST or COOKIE data is encountered - * Set automatically based on config setting + * Enable XSS flag + * + * Determines whether the XSS filter is always active when + * GET, POST or COOKIE data is encountered. + * Set automatically based on config setting. * - * @var bool + * @var bool */ - protected $_enable_xss = FALSE; + protected $_enable_xss = FALSE; /** + * Enable CSRF flag + * * Enables a CSRF cookie token to be set. - * Set automatically based on config setting + * Set automatically based on config setting. * - * @var bool + * @var bool */ - protected $_enable_csrf = FALSE; + protected $_enable_csrf = FALSE; /** * List of all HTTP request headers * * @var array */ - protected $headers = array(); + protected $headers = array(); /** - * Constructor + * Class constructor * - * Sets whether to globally enable the XSS processing - * and whether to allow the $_GET array + * Determines whether to globally enable the XSS processing + * and whether to allow the $_GET array. * * @return void */ @@ -124,12 +134,12 @@ class CI_Input { /** * Fetch from array * - * This is a helper function to retrieve values from global arrays + * Internal method used to retrieve values from global arrays. * - * @param array - * @param string - * @param bool - * @return string + * @param array &$array $_GET, $_POST, $_COOKIE, $_SERVER, etc. + * @param string $index Index for item to be fetched from $array + * @param bool $xss_clean Whether to apply XSS filtering + * @return mixed */ protected function _fetch_from_array(&$array, $index = '', $xss_clean = FALSE) { @@ -151,9 +161,9 @@ class CI_Input { /** * Fetch an item from the GET array * - * @param string - * @param bool - * @return string + * @param string $index Index for item to be fetched from $_GET + * @param bool $xss_clean Whether to apply XSS filtering + * @return mixed */ public function get($index = NULL, $xss_clean = FALSE) { @@ -178,9 +188,9 @@ class CI_Input { /** * Fetch an item from the POST array * - * @param string - * @param bool - * @return string + * @param string $index Index for item to be fetched from $_POST + * @param bool $xss_clean Whether to apply XSS filtering + * @return mixed */ public function post($index = NULL, $xss_clean = FALSE) { @@ -200,15 +210,14 @@ class CI_Input { return $this->_fetch_from_array($_POST, $index, $xss_clean); } - // -------------------------------------------------------------------- /** - * Fetch an item from either the GET array or the POST + * Fetch an item from POST data with fallback to GET * - * @param string The index key - * @param bool XSS cleaning - * @return string + * @param string $index Index for item to be fetched from $_POST or $_GET + * @param bool $xss_clean Whether to apply XSS filtering + * @return mixed */ public function get_post($index = '', $xss_clean = FALSE) { @@ -222,31 +231,45 @@ class CI_Input { /** * Fetch an item from the COOKIE array * - * @param string - * @param bool - * @return string + * @param string $index Index for item to be fetched from $_COOKIE + * @param bool $xss_clean Whether to apply XSS filtering + * @return mixed */ public function cookie($index = '', $xss_clean = FALSE) { return $this->_fetch_from_array($_COOKIE, $index, $xss_clean); } + // -------------------------------------------------------------------- + + /** + * Fetch an item from the SERVER array + * + * @param string $index Index for item to be fetched from $_SERVER + * @param bool $xss_clean Whether to apply XSS filtering + * @return mixed + */ + public function server($index = '', $xss_clean = FALSE) + { + return $this->_fetch_from_array($_SERVER, $index, $xss_clean); + } + // ------------------------------------------------------------------------ /** * Set cookie * - * Accepts seven parameters, or you can submit an associative + * Accepts an arbitrary number of parameters (up to 7) or an associative * array in the first parameter containing all the values. * - * @param mixed - * @param string the value of the cookie - * @param string the number of seconds until expiration - * @param string the cookie domain. Usually: .yourdomain.com - * @param string the cookie path - * @param string the cookie prefix - * @param bool true makes the cookie secure - * @param bool true makes the cookie accessible via http(s) only (no javascript) + * @param string|mixed[] $name Cookie name or an array containing parameters + * @param string $value Cookie value + * @param int $expire Cookie expiration time in seconds + * @param string $domain Cookie domain (e.g.: '.yourdomain.com') + * @param string $path Cookie path (default: '/') + * @param string $prefix Cookie name prefix + * @param bool $secure Whether to only transfer cookies via SSL + * @param bool $httponly Whether to only makes the cookie accessible via HTTP (no javascript) * @return void */ public function set_cookie($name = '', $value = '', $expire = '', $domain = '', $path = '/', $prefix = '', $secure = FALSE, $httponly = FALSE) @@ -303,23 +326,11 @@ class CI_Input { // -------------------------------------------------------------------- /** - * Fetch an item from the SERVER array - * - * @param string - * @param bool - * @return string - */ - public function server($index = '', $xss_clean = FALSE) - { - return $this->_fetch_from_array($_SERVER, $index, $xss_clean); - } - - // -------------------------------------------------------------------- - - /** * Fetch the IP Address * - * @return string + * Determines and validates the visitor's IP address. + * + * @return string IP address */ public function ip_address() { @@ -328,62 +339,117 @@ class CI_Input { return $this->ip_address; } - if (config_item('proxy_ips') != '' && $this->server('HTTP_X_FORWARDED_FOR') && $this->server('REMOTE_ADDR')) + $proxy_ips = config_item('proxy_ips'); + if ( ! empty($proxy_ips) && ! is_array($proxy_ips)) { - $has_ranges = strpos($proxies, '/') !== false; - $proxies = preg_split('/[\s,]/', config_item('proxy_ips'), -1, PREG_SPLIT_NO_EMPTY); - $proxies = is_array($proxies) ? $proxies : array($proxies); - - if ($has_ranges) - { - $long_ip = ip2long($_SERVER['REMOTE_ADDR']); - $bit_32 = 1 << 32; + $proxy_ips = explode(',', str_replace(' ', '', $proxy_ips)); + } + + $this->ip_address = $this->server('REMOTE_ADDR'); - // Go through each of the IP Addresses to check for and - // test against range notation - foreach($proxies as $ip) + if ($proxy_ips) + { + foreach (array('HTTP_X_FORWARDED_FOR', 'HTTP_CLIENT_IP', 'HTTP_X_CLIENT_IP', 'HTTP_X_CLUSTER_CLIENT_IP') as $header) + { + if (($spoof = $this->server($header)) !== NULL) { - list($address, $mask_length) = explode('/', $ip); + // Some proxies typically list the whole chain of IP + // addresses through which the client has reached us. + // e.g. client_ip, proxy_ip1, proxy_ip2, etc. + sscanf($spoof, '%[^,]', $spoof); - // Generate the bitmask for a 32 bit IP Address - $bitmask = $bit_32 - (1 << (32 - (int)$mask_length)); - if (($long_ip & $bitmask) == $address) + if ( ! $this->valid_ip($spoof)) + { + $spoof = NULL; + } + else { - $this->ip_address = $_SERVER['HTTP_X_FORWARDED_FOR']; break; } } - - } else { - $this->ip_address = in_array($_SERVER['REMOTE_ADDR'], $proxies) ? $_SERVER['HTTP_X_FORWARDED_FOR'] : $_SERVER['REMOTE_ADDR']; } - } - elseif ( ! $this->server('HTTP_CLIENT_IP') && $this->server('REMOTE_ADDR')) - { - $this->ip_address = $_SERVER['REMOTE_ADDR']; - } - elseif ($this->server('REMOTE_ADDR') && $this->server('HTTP_CLIENT_IP')) - { - $this->ip_address = $_SERVER['HTTP_CLIENT_IP']; - } - elseif ($this->server('HTTP_CLIENT_IP')) - { - $this->ip_address = $_SERVER['HTTP_CLIENT_IP']; - } - elseif ($this->server('HTTP_X_FORWARDED_FOR')) - { - $this->ip_address = $_SERVER['HTTP_X_FORWARDED_FOR']; - } - if ($this->ip_address === FALSE) - { - return $this->ip_address = '0.0.0.0'; - } + if ($spoof) + { + for ($i = 0, $c = count($proxy_ips); $i < $c; $i++) + { + // Check if we have an IP address or a subnet + if (strpos($proxy_ips[$i], '/') === FALSE) + { + // An IP address (and not a subnet) is specified. + // We can compare right away. + if ($proxy_ips[$i] === $this->ip_address) + { + $this->ip_address = $spoof; + break; + } + + continue; + } - if (strpos($this->ip_address, ',') !== FALSE) - { - $x = explode(',', $this->ip_address); - $this->ip_address = trim(end($x)); + // We have a subnet ... now the heavy lifting begins + isset($separator) OR $separator = $this->valid_ip($this->ip_address, 'ipv6') ? ':' : '.'; + + // If the proxy entry doesn't match the IP protocol - skip it + if (strpos($proxy_ips[$i], $separator) === FALSE) + { + continue; + } + + // Convert the REMOTE_ADDR IP address to binary, if needed + if ( ! isset($ip, $sprintf)) + { + if ($separator === ':') + { + // Make sure we're have the "full" IPv6 format + $ip = explode(':', + str_replace('::', + str_repeat(':', 9 - substr_count($this->ip_address, ':')), + $this->ip_address + ) + ); + + for ($i = 0; $i < 8; $i++) + { + $ip[$i] = intval($ip[$i], 16); + } + + $sprintf = '%016b%016b%016b%016b%016b%016b%016b%016b'; + } + else + { + $ip = explode('.', $this->ip_address); + $sprintf = '%08b%08b%08b%08b'; + } + + $ip = vsprintf($sprintf, $ip); + } + + // Split the netmask length off the network address + sscanf($proxy_ips[$i], '%[^/]/%d', $netaddr, $masklen); + + // Again, an IPv6 address is most likely in a compressed form + if ($separator === ':') + { + $netaddr = explode(':', str_replace('::', str_repeat(':', 9 - substr_count($netaddr, ':')), $netaddr)); + for ($i = 0; $i < 8; $i++) + { + $netaddr[$i] = intval($netaddr[$i], 16); + } + } + else + { + $netaddr = explode('.', $netaddr); + } + + // Convert to binary and finally compare + if (strncmp($ip, vsprintf($sprintf, $netaddr), $masklen) === 0) + { + $this->ip_address = $spoof; + break; + } + } + } } if ( ! $this->valid_ip($this->ip_address)) @@ -399,8 +465,8 @@ class CI_Input { /** * Validate IP Address * - * @param string - * @param string 'ipv4' or 'ipv6' + * @param string $ip IP address + * @param string $which IP protocol: 'ipv4' or 'ipv6' * @return bool */ public function valid_ip($ip, $which = '') @@ -424,9 +490,9 @@ class CI_Input { // -------------------------------------------------------------------- /** - * User Agent + * Fetch User Agent string * - * @return string + * @return string|null User Agent string or NULL if it doesn't exist */ public function user_agent() { @@ -435,7 +501,7 @@ class CI_Input { return $this->user_agent; } - return $this->user_agent = isset($_SERVER['HTTP_USER_AGENT']) ? $_SERVER['HTTP_USER_AGENT'] : FALSE; + return $this->user_agent = isset($_SERVER['HTTP_USER_AGENT']) ? $_SERVER['HTTP_USER_AGENT'] : NULL; } // -------------------------------------------------------------------- @@ -443,11 +509,12 @@ class CI_Input { /** * Sanitize Globals * - * This function does the following: + * Internal method serving for the following purposes: * - * - Unsets $_GET data (if query strings are not enabled) - * - Unsets all globals if register_globals is enabled - * - Standardizes newline characters to \n + * - Unsets $_GET data (if query strings are not enabled) + * - Unsets all globals if register_globals is enabled + * - Cleans POST, COOKIE and SERVER data + * - Standardizes newline characters to PHP_EOL * * @return void */ @@ -475,25 +542,29 @@ class CI_Input { 'IN' ); - // Unset globals for securiy. + // Unset globals for security. // This is effectively the same as register_globals = off - foreach (array($_GET, $_POST, $_COOKIE) as $global) + // PHP 5.4 no longer has the register_globals functionality. + if ( ! is_php('5.4')) { - if (is_array($global)) + foreach (array($_GET, $_POST, $_COOKIE) as $global) { - foreach ($global as $key => $val) + if (is_array($global)) { - if ( ! in_array($key, $protected)) + foreach ($global as $key => $val) { - global $$key; - $$key = NULL; + if ( ! in_array($key, $protected)) + { + global $$key; + $$key = NULL; + } } } - } - elseif ( ! in_array($global, $protected)) - { - global $$global; - $$global = NULL; + elseif ( ! in_array($global, $protected)) + { + global $$global; + $$global = NULL; + } } } @@ -541,7 +612,7 @@ class CI_Input { $_SERVER['PHP_SELF'] = strip_tags($_SERVER['PHP_SELF']); // CSRF Protection check - if ($this->_enable_csrf === TRUE) + if ($this->_enable_csrf === TRUE && ! $this->is_cli_request()) { $this->security->csrf_verify(); } @@ -554,10 +625,10 @@ class CI_Input { /** * Clean Input Data * - * This is a helper function. It escapes data and - * standardizes newline characters to \n + * Internal method that aids in escaping data and + * standardizing newline characters to PHP_EOL. * - * @param string + * @param string|string[] $str Input string(s) * @return string */ protected function _clean_input_data($str) @@ -565,9 +636,9 @@ class CI_Input { if (is_array($str)) { $new_array = array(); - foreach ($str as $key => $val) + foreach (array_keys($str) as $key) { - $new_array[$this->_clean_input_keys($key)] = $this->_clean_input_data($val); + $new_array[$this->_clean_input_keys($key)] = $this->_clean_input_data($str[$key]); } return $new_array; } @@ -611,11 +682,11 @@ class CI_Input { /** * Clean Keys * - * This is a helper function. To prevent malicious users + * Internal method that helps to prevent malicious users * from trying to exploit keys we make sure that keys are * only named with alpha-numeric text and a few other items. * - * @param string + * @param string $str Input string * @return string */ protected function _clean_input_keys($str) @@ -640,15 +711,12 @@ class CI_Input { /** * Request Headers * - * In Apache, you can simply call apache_request_headers(), however for - * people running other webservers the function is undefined. - * - * @param bool XSS cleaning + * @param bool $xss_clean Whether to apply XSS filtering * @return array */ public function request_headers($xss_clean = FALSE) { - // Look at Apache go! + // In Apache, you can simply call apache_request_headers() if (function_exists('apache_request_headers')) { $headers = apache_request_headers(); @@ -685,9 +753,9 @@ class CI_Input { * * Returns the value of a single member of the headers class member * - * @param string array key for $this->headers - * @param bool XSS Clean or not - * @return mixed FALSE on failure, string on success + * @param string $index Header name + * @param bool $xss_clean Whether to apply XSS filtering + * @return string|bool The requested header on success or FALSE on failure */ public function get_request_header($index, $xss_clean = FALSE) { @@ -709,9 +777,9 @@ class CI_Input { // -------------------------------------------------------------------- /** - * Is ajax Request? + * Is AJAX request? * - * Test to see if a request contains the HTTP_X_REQUESTED_WITH header + * Test to see if a request contains the HTTP_X_REQUESTED_WITH header. * * @return bool */ @@ -723,9 +791,9 @@ class CI_Input { // -------------------------------------------------------------------- /** - * Is cli Request? + * Is CLI request? * - * Test to see if a request was made from the command line + * Test to see if a request was made from the command line. * * @return bool */ @@ -739,10 +807,11 @@ class CI_Input { /** * Get Request Method * - * Return the Request Method + * Return the request method * - * @param bool uppercase or lowercase - * @return bool + * @param bool $upper Whether to return in upper or lower case + * (default: FALSE) + * @return string */ public function method($upper = FALSE) { diff --git a/system/core/Lang.php b/system/core/Lang.php index 3001f1b13..896385134 100644 --- a/system/core/Lang.php +++ b/system/core/Lang.php @@ -1,4 +1,4 @@ -<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed'); +<?php /** * CodeIgniter * @@ -24,6 +24,7 @@ * @since Version 1.0 * @filesource */ +defined('BASEPATH') OR exit('No direct script access allowed'); /** * Language Class @@ -39,19 +40,19 @@ class CI_Lang { /** * List of translations * - * @var array + * @var array */ public $language = array(); /** * List of loaded language files * - * @var array + * @var array */ public $is_loaded = array(); /** - * Initialize language class + * Class constructor * * @return void */ @@ -65,12 +66,13 @@ class CI_Lang { /** * Load a language file * - * @param mixed the name of the language file to be loaded - * @param string the language (english, etc.) - * @param bool return loaded array of translations - * @param bool add suffix to $langfile - * @param string alternative path to look for language file - * @return mixed + * @param mixed $langfile Language file name + * @param string $idiom Language name (english, etc.) + * @param bool $return Whether to return the loaded array of translations + * @param bool $add_suffix Whether to add suffix to $langfile + * @param string $alt_path Alternative path to look for the language file + * + * @return void|string[] Array containing translations, if $return is set to TRUE */ public function load($langfile, $idiom = '', $return = FALSE, $add_suffix = TRUE, $alt_path = '') { @@ -83,10 +85,10 @@ class CI_Lang { $langfile .= '.php'; - if ($idiom === '') + if (empty($idiom) OR ! ctype_alpha($idiom)) { $config =& get_config(); - $idiom = ( ! empty($config['language'])) ? $config['language'] : 'english'; + $idiom = empty($config['language']) ? 'english' : $config['language']; } if ($return === FALSE && isset($this->is_loaded[$langfile]) && $this->is_loaded[$langfile] === $idiom) @@ -119,7 +121,6 @@ class CI_Lang { } } - if ( ! isset($lang) OR ! is_array($lang)) { log_message('error', 'Language file contains no data: language/'.$idiom.'/'.$langfile); @@ -146,10 +147,12 @@ class CI_Lang { // -------------------------------------------------------------------- /** - * Fetch a single line of text from the language array + * Language line + * + * Fetches a single line of text from the language array * - * @param string $line the language line - * @return string + * @param string $line Language line key + * @return string Translation */ public function line($line = '') { diff --git a/system/core/Loader.php b/system/core/Loader.php index 0bc6e844a..88fbdb6e1 100644 --- a/system/core/Loader.php +++ b/system/core/Loader.php @@ -1,4 +1,4 @@ -<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed'); +<?php /** * CodeIgniter * @@ -24,11 +24,12 @@ * @since Version 1.0 * @filesource */ +defined('BASEPATH') OR exit('No direct script access allowed'); /** * Loader Class * - * Loads views and files + * Loads framework components. * * @package CodeIgniter * @subpackage Libraries @@ -42,84 +43,84 @@ class CI_Loader { /** * Nesting level of the output buffering mechanism * - * @var int + * @var int */ protected $_ci_ob_level; /** * List of paths to load views from * - * @var array + * @var array */ protected $_ci_view_paths = array(); /** * List of paths to load libraries from * - * @var array + * @var array */ protected $_ci_library_paths = array(); /** * List of paths to load models from * - * @var array + * @var array */ protected $_ci_model_paths = array(); /** * List of paths to load helpers from * - * @var array + * @var array */ protected $_ci_helper_paths = array(); /** * List of loaded base classes * - * @var array + * @var array */ protected $_base_classes = array(); // Set by the controller class /** * List of cached variables * - * @var array + * @var array */ protected $_ci_cached_vars = array(); /** * List of loaded classes * - * @var array + * @var array */ protected $_ci_classes = array(); /** * List of loaded files * - * @var array + * @var array */ protected $_ci_loaded_files = array(); /** * List of loaded models * - * @var array + * @var array */ protected $_ci_models = array(); /** * List of loaded helpers * - * @var array + * @var array */ protected $_ci_helpers = array(); /** * List of class name mappings * - * @var array + * @var array */ protected $_ci_varmap = array( 'unit_test' => 'unit', @@ -127,9 +128,9 @@ class CI_Loader { ); /** - * Constructor + * Class constructor * - * Sets the path to the view files and gets the initial output buffering level + * Sets component load paths, gets the initial output buffering level. * * @return void */ @@ -147,21 +148,18 @@ class CI_Loader { // -------------------------------------------------------------------- /** - * Initialize the Loader + * Initializer * - * This method is called once in CI_Controller. - * - * @return object + * @todo Figure out a way to move this to the constructor + * without breaking *package_path*() methods. + * @uses CI_Loader::_ci_autoloader() + * @used-by CI_Controller::__construct() + * @return void */ public function initialize() { - $this->_ci_classes = array(); - $this->_ci_loaded_files = array(); - $this->_ci_models = array(); $this->_base_classes =& is_loaded(); - $this->_ci_autoloader(); - return $this; } // -------------------------------------------------------------------- @@ -169,14 +167,12 @@ class CI_Loader { /** * Is Loaded * - * A utility function to test if a class is in the self::$_ci_classes array. - * This function returns the object name if the class tested for is loaded, - * and returns FALSE if it isn't. + * A utility method to test if a class is in the self::$_ci_classes array. * - * It is mainly used in the form_helper -> _get_validation_object() + * @used-by Mainly used by Form Helper function _get_validation_object(). * - * @param string class being checked for - * @return mixed class object name on the CI SuperObject or FALSE + * @param string $class Class name to check for + * @return string|bool Class object name if loaded or FALSE */ public function is_loaded($class) { @@ -186,14 +182,14 @@ class CI_Loader { // -------------------------------------------------------------------- /** - * Class Loader + * Library Loader * - * This function lets users load and instantiate classes. - * It is designed to be called from a user's app controllers. + * Loads and instantiates libraries. + * Designed to be called from application controllers. * - * @param string the name of the class - * @param mixed the optional parameters - * @param string an optional object name + * @param string $library Library name + * @param array $params Optional parameters to pass to the library class constructor + * @param string $object_name An optional object name to assign to * @return void */ public function library($library = '', $params = NULL, $object_name = NULL) @@ -210,7 +206,7 @@ class CI_Loader { if ($library === '' OR isset($this->_base_classes[$library])) { - return FALSE; + return; } if ( ! is_null($params) && ! is_array($params)) @@ -226,16 +222,20 @@ class CI_Loader { /** * Model Loader * - * This function lets users load and instantiate models. + * Loads and instantiates libraries. * - * @param string the name of the class - * @param string name for the model - * @param bool database connection + * @param string $model Model name + * @param string $name An optional object name to assign to + * @param bool $db_conn An optional database connection configuration to initialize * @return void */ public function model($model, $name = '', $db_conn = FALSE) { - if (is_array($model)) + if (empty($model)) + { + return; + } + elseif (is_array($model)) { foreach ($model as $class) { @@ -244,11 +244,6 @@ class CI_Loader { return; } - if ($model === '') - { - return; - } - $path = ''; // Is the model in a sub-folder? If so, parse out the filename and path. @@ -318,10 +313,13 @@ class CI_Loader { /** * Database Loader * - * @param string the DB credentials - * @param bool whether to return the DB object - * @param bool whether to enable query builder (this allows us to override the config setting) - * @return object + * @param mixed $params Database configuration options + * @param bool $return Whether to return the database object + * @param bool $query_builder Whether to enable Query Builder + * (overrides the configuration setting) + * + * @return void|object|bool Database object if $return is set to TRUE, + * FALSE on failure, void in any other case */ public function database($params = '', $return = FALSE, $query_builder = NULL) { @@ -329,7 +327,7 @@ class CI_Loader { $CI =& get_instance(); // Do we even need to load the database class? - if (class_exists('CI_DB') && $return === FALSE && $query_builder === NULL && isset($CI->db) && is_object($CI->db)) + if ($return === FALSE && $query_builder === NULL && isset($CI->db) && is_object($CI->db) && ! empty($CI->db->conn_id)) { return FALSE; } @@ -352,9 +350,9 @@ class CI_Loader { // -------------------------------------------------------------------- /** - * Load the Utilities Class + * Load the Database Utilities Class * - * @return string + * @return void */ public function dbutil() { @@ -381,7 +379,7 @@ class CI_Loader { /** * Load the Database Forge Class * - * @return string + * @return void */ public function dbforge() { @@ -402,19 +400,15 @@ class CI_Loader { // -------------------------------------------------------------------- /** - * Load View + * View Loader * - * This function is used to load a "view" file. It has three parameters: + * Loads "view" files. * - * 1. The name of the "view" file to be included. - * 2. An associative array of data to be extracted for use in the view. - * 3. TRUE/FALSE - whether to return the data or load it. In - * some cases it's advantageous to be able to return data so that - * a developer can process it in some way. - * - * @param string - * @param array - * @param bool + * @param string $view View name + * @param array $vars An associative array of data + * to be extracted for use in the view + * @param bool $return Whether to return the view output + * or leave it to the Output class * @return void */ public function view($view, $vars = array(), $return = FALSE) @@ -425,13 +419,11 @@ class CI_Loader { // -------------------------------------------------------------------- /** - * Load File - * - * This is a generic file loader + * Generic File Loader * - * @param string - * @param bool - * @return string + * @param string $path File path + * @param bool $return Whether to return the file output + * @return void|string */ public function file($path, $return = FALSE) { @@ -446,8 +438,10 @@ class CI_Loader { * Once variables are set they become available within * the controller class and its "view" files. * - * @param array - * @param string + * @param array|object|string $vars + * An associative array or object containing values + * to be set, or a value's name if string + * @param string $val Value to set, only used if $vars is a string * @return void */ public function vars($vars = array(), $val = '') @@ -475,8 +469,8 @@ class CI_Loader { * * Check if a variable is set and retrieve it. * - * @param array - * @return void + * @param string $key Variable name + * @return mixed The variable or NULL if not found */ public function get_var($key) { @@ -488,7 +482,7 @@ class CI_Loader { /** * Get Variables * - * Retrieve all loaded variables + * Retrieves all loaded variables. * * @return array */ @@ -500,11 +494,9 @@ class CI_Loader { // -------------------------------------------------------------------- /** - * Load Helper + * Helper Loader * - * This function loads the specified helper file. - * - * @param mixed + * @param string|string[] $helpers Helper name(s) * @return void */ public function helper($helpers = array()) @@ -562,10 +554,11 @@ class CI_Loader { /** * Load Helpers * - * This is simply an alias to the above function in case the - * user has written the plural form of this function. + * An alias for the helper() method in case the developer has + * written the plural form of it. * - * @param array + * @uses CI_Loader::helper() + * @param string|string[] $helpers Helper name(s) * @return void */ public function helpers($helpers = array()) @@ -576,22 +569,21 @@ class CI_Loader { // -------------------------------------------------------------------- /** - * Loads a language file + * Language Loader + * + * Loads language files. * - * @param array - * @param string + * @param string|string[] $files List of language file names to load + * @param string Language name * @return void */ - public function language($file = array(), $lang = '') + public function language($files = array(), $lang = '') { $CI =& get_instance(); - if ( ! is_array($file)) - { - $file = array($file); - } + is_array($files) OR $files = array($files); - foreach ($file as $langfile) + foreach ($files as $langfile) { $CI->lang->load($langfile, $lang); } @@ -600,30 +592,35 @@ class CI_Loader { // -------------------------------------------------------------------- /** - * Loads a config file + * Config Loader * - * @param string - * @param bool - * @param bool - * @return void + * Loads a config file (an alias for CI_Config::load()). + * + * @uses CI_Config::load() + * @param string $file Configuration file name + * @param bool $use_sections Whether configuration values should be loaded into their own section + * @param bool $fail_gracefully Whether to just return FALSE or display an error message + * @return bool TRUE if the file was loaded correctly or FALSE on failure */ public function config($file = '', $use_sections = FALSE, $fail_gracefully = FALSE) { $CI =& get_instance(); - $CI->config->load($file, $use_sections, $fail_gracefully); + return $CI->config->load($file, $use_sections, $fail_gracefully); } // -------------------------------------------------------------------- /** - * Driver + * Driver Loader * - * Loads a driver library + * Loads a driver library. * - * @param mixed the name of the class or array of classes - * @param mixed the optional parameters - * @param string an optional object name - * @return void + * @param string|string[] $library Driver name(s) + * @param array $params Optional parameters to pass to the driver + * @param string $object_name An optional object name to assign to + * + * @return void|object|bool Object or FALSE on failure if $library is a string + * and $object_name is set. void otherwise. */ public function driver($library = '', $params = NULL, $object_name = NULL) { @@ -633,13 +630,7 @@ class CI_Loader { { $this->driver($driver); } - return FALSE; - } - - if ( ! class_exists('CI_Driver_Library')) - { - // we aren't instantiating an object here, that'll be done by the Library itself - require BASEPATH.'libraries/Driver.php'; + return; } if ($library === '') @@ -662,10 +653,16 @@ class CI_Loader { /** * Add Package Path * - * Prepends a parent path to the library, model, helper, and config path arrays + * Prepends a parent path to the library, model, helper and config + * path arrays. + * + * @see CI_Loader::$_ci_library_paths + * @see CI_Loader::$_ci_model_paths + * @see CI_Loader::$_ci_helper_paths + * @see CI_Config::$_config_paths * - * @param string - * @param bool + * @param string $path Path to add + * @param bool $view_cascade (default: TRUE) * @return void */ public function add_package_path($path, $view_cascade = TRUE) @@ -688,14 +685,14 @@ class CI_Loader { /** * Get Package Paths * - * Return a list of all package paths, by default it will ignore BASEPATH. + * Return a list of all package paths. * - * @param string - * @return void + * @param bool $include_base Whether to include BASEPATH (default: TRUE) + * @return array */ public function get_package_paths($include_base = FALSE) { - return $include_base === TRUE ? $this->_ci_library_paths : $this->_ci_model_paths; + return ($include_base === TRUE) ? $this->_ci_library_paths : $this->_ci_model_paths; } // -------------------------------------------------------------------- @@ -703,14 +700,14 @@ class CI_Loader { /** * Remove Package Path * - * Remove a path from the library, model, and helper path arrays if it exists - * If no path is provided, the most recently added path is removed. + * Remove a path from the library, model, helper and/or config + * path arrays if it exists. If no path is provided, the most recently + * added path will be removed removed. * - * @param string - * @param bool + * @param string $path Path to remove * @return void */ - public function remove_package_path($path = '', $remove_config_path = TRUE) + public function remove_package_path($path = '') { $config =& $this->_ci_get_component('config'); @@ -755,13 +752,16 @@ class CI_Loader { // -------------------------------------------------------------------- /** - * Loader + * Internal CI Data Loader + * + * Used to load views and files. * - * This function is used to load views and files. * Variables are prefixed with _ci_ to avoid symbol collision with - * variables made available to view files + * variables made available to view files. * - * @param array + * @used-by CI_Loader::view() + * @used-by CI_Loader::file() + * @param array $_ci_data Data to load * @return void */ protected function _ci_load($_ci_data) @@ -785,11 +785,11 @@ class CI_Loader { $_ci_ext = pathinfo($_ci_view, PATHINFO_EXTENSION); $_ci_file = ($_ci_ext === '') ? $_ci_view.'.php' : $_ci_view; - foreach ($this->_ci_view_paths as $view_file => $cascade) + foreach ($this->_ci_view_paths as $_ci_view_file => $cascade) { - if (file_exists($view_file.$_ci_file)) + if (file_exists($_ci_view_file.$_ci_file)) { - $_ci_path = $view_file.$_ci_file; + $_ci_path = $_ci_view_file.$_ci_file; $file_exists = TRUE; break; } @@ -837,10 +837,10 @@ class CI_Loader { * We buffer the output for two reasons: * 1. Speed. You get a significant speed boost. * 2. So that the final rendered template can be post-processed by - * the output class. Why do we need post processing? For one thing, - * in order to show the elapsed page load time. Unless we can - * intercept the content right before it's sent to the browser and - * then stop the timer it won't be accurate. + * the output class. Why do we need post processing? For one thing, + * in order to show the elapsed page load time. Unless we can + * intercept the content right before it's sent to the browser and + * then stop the timer it won't be accurate. */ ob_start(); @@ -889,13 +889,14 @@ class CI_Loader { // -------------------------------------------------------------------- /** - * Load class + * Internal CI Class Loader * - * This function loads the requested class. + * @used-by CI_Loader::library() + * @uses CI_Loader::_ci_init_class() * - * @param string the item that is being loaded - * @param mixed any additional parameters - * @param string an optional object name + * @param string $class Class name to load + * @param mixed $params Optional parameters to pass to the class constructor + * @param string $object_name Optional object name to assign to * @return void */ protected function _ci_load_class($class, $params = NULL, $object_name = NULL) @@ -915,6 +916,13 @@ class CI_Loader { // Get the filename from the path $class = substr($class, $last_slash); + + // Check for match and driver base class + if (strtolower(trim($subdir, '/')) == strtolower($class) && ! class_exists('CI_Driver_Library')) + { + // We aren't instantiating an object here, just making the base class available + require BASEPATH.'libraries/Driver.php'; + } } // We'll test for both lowercase and capitalized versions of the file name @@ -996,14 +1004,19 @@ class CI_Loader { $this->_ci_loaded_files[] = $filepath; return $this->_ci_init_class($class, '', $params, $object_name); } - } // END FOREACH // One last attempt. Maybe the library is in a subdirectory, but it wasn't specified? if ($subdir === '') { $path = strtolower($class).'/'.$class; - return $this->_ci_load_class($path, $params); + return $this->_ci_load_class($path, $params, $object_name); + } + elseif (ucfirst($subdir) != $subdir) + { + // Lowercase subdir failed - retry capitalized + $path = ucfirst($subdir).$class; + return $this->_ci_load_class($path, $params, $object_name); } // If we got this far we were unable to find the requested class. @@ -1018,12 +1031,17 @@ class CI_Loader { // -------------------------------------------------------------------- /** - * Instantiates a class + * Internal CI Class Instantiator + * + * @used-by CI_Loader::_ci_load_class() * - * @param string - * @param string - * @param bool - * @param string an optional object name + * @param string $class Class name + * @param string $prefix Class name prefix + * @param array|null|bool $config Optional configuration to pass to the class constructor: + * FALSE to skip; + * NULL to search in config paths; + * array containing configuration data + * @param string $object_name Optional object name to assign to * @return void */ protected function _ci_init_class($class, $prefix = '', $config = FALSE, $object_name = NULL) @@ -1125,11 +1143,11 @@ class CI_Loader { // -------------------------------------------------------------------- /** - * Autoloader + * CI Autoloader * - * The config/autoload.php file contains an array that permits sub-systems, - * libraries, and helpers to be loaded automatically. + * Loads component listed in the config/autoload.php file. * + * @used-by CI_Loader::initialize() * @return void */ protected function _ci_autoloader() @@ -1193,6 +1211,15 @@ class CI_Loader { } } + // Autoload drivers + if (isset($autoload['drivers'])) + { + foreach ($autoload['drivers'] as $item) + { + $this->driver($item); + } + } + // Autoload models if (isset($autoload['model'])) { @@ -1203,11 +1230,12 @@ class CI_Loader { // -------------------------------------------------------------------- /** - * Object to Array + * CI Object to Array translator * - * Takes an object as input and converts the class variables to array key/vals + * Takes an object as input and converts the class variables to + * an associative array with key/value pairs. * - * @param object + * @param object $object Object data to translate * @return array */ protected function _ci_object_to_array($object) @@ -1218,9 +1246,11 @@ class CI_Loader { // -------------------------------------------------------------------- /** - * Get a reference to a specific library or model + * CI Component getter + * + * Get a reference to a specific library or model. * - * @param string + * @param string $component Component name * @return bool */ protected function &_ci_get_component($component) @@ -1234,10 +1264,11 @@ class CI_Loader { /** * Prep filename * - * This function preps the name of various items to make loading them more reliable. + * This function prepares filenames of various items to + * make their loading more reliable. * - * @param mixed - * @param string + * @param string|string[] $filename Filename(s) + * @param string $extension Filename extension * @return array */ protected function _ci_prep_filename($filename, $extension) diff --git a/system/core/Model.php b/system/core/Model.php index 9bc9f879f..28fdfbb69 100644 --- a/system/core/Model.php +++ b/system/core/Model.php @@ -1,4 +1,4 @@ -<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed'); +<?php /** * CodeIgniter * @@ -24,9 +24,10 @@ * @since Version 1.0 * @filesource */ +defined('BASEPATH') OR exit('No direct script access allowed'); /** - * CodeIgniter Model Class + * Model Class * * @package CodeIgniter * @subpackage Libraries @@ -37,7 +38,7 @@ class CI_Model { /** - * Initialize CI_Model Class + * Class constructor * * @return void */ @@ -46,13 +47,15 @@ class CI_Model { log_message('debug', 'Model Class Initialized'); } + // -------------------------------------------------------------------- + /** - * __get + * __get magic * * Allows models to access CI's loaded classes using the same * syntax as controllers. * - * @param string + * @param string $key */ public function __get($key) { diff --git a/system/core/Output.php b/system/core/Output.php index 9842f834d..9300df356 100644 --- a/system/core/Output.php +++ b/system/core/Output.php @@ -1,4 +1,4 @@ -<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed'); +<?php /** * CodeIgniter * @@ -24,11 +24,12 @@ * @since Version 1.0 * @filesource */ +defined('BASEPATH') OR exit('No direct script access allowed'); /** * Output Class * - * Responsible for sending final output to browser + * Responsible for sending final output to the browser. * * @package CodeIgniter * @subpackage Libraries @@ -39,70 +40,74 @@ class CI_Output { /** - * Current output string + * Final output string * - * @var string + * @var string */ public $final_output; /** * Cache expiration time * - * @var int + * @var int */ - public $cache_expiration = 0; + public $cache_expiration = 0; /** * List of server headers * - * @var array + * @var array */ public $headers = array(); /** * List of mime types * - * @var array + * @var array */ public $mimes = array(); /** * Mime-type for the current page * - * @var string + * @var string */ - protected $mime_type = 'text/html'; + protected $mime_type = 'text/html'; /** - * Determines whether profiler is enabled + * Enable Profiler flag * - * @var book + * @var bool */ - public $enable_profiler = FALSE; + public $enable_profiler = FALSE; /** - * Determines if output compression is enabled + * zLib output compression flag * - * @var bool + * @var bool */ protected $_zlib_oc = FALSE; /** * List of profiler sections * - * @var array + * @var array */ protected $_profiler_sections = array(); /** - * Whether or not to parse variables like {elapsed_time} and {memory_usage} + * Parse markers flag * - * @var bool + * Whether or not to parse variables like {elapsed_time} and {memory_usage}. + * + * @var bool */ public $parse_exec_vars = TRUE; /** - * Set up Output class + * Class constructor + * + * Determines whether zLib output compression will be used. * * @return void */ @@ -121,7 +126,7 @@ class CI_Output { /** * Get Output * - * Returns the current output string + * Returns the current output string. * * @return string */ @@ -135,10 +140,10 @@ class CI_Output { /** * Set Output * - * Sets the output string + * Sets the output string. * - * @param string - * @return void + * @param string $output Output data + * @return object $this */ public function set_output($output) { @@ -151,14 +156,14 @@ class CI_Output { /** * Append Output * - * Appends data onto the output string + * Appends data onto the output string. * - * @param string - * @return void + * @param string $output Data to append + * @return object $this */ public function append_output($output) { - if ($this->final_output == '') + if (empty($this->final_output)) { $this->final_output = $output; } @@ -175,14 +180,14 @@ class CI_Output { /** * Set Header * - * Lets you set a server header which will be outputted with the final display. + * Lets you set a server header which will be sent with the final output. * - * Note: If a file is cached, headers will not be sent. We need to figure out - * how to permit header data to be saved with the cache data... + * Note: If a file is cached, headers will not be sent. + * @todo We need to figure out how to permit headers to be cached. * - * @param string - * @param bool - * @return void + * @param string $header Header + * @param bool $replace Whether to replace the old header value, if already set + * @return object $this */ public function set_header($header, $replace = TRUE) { @@ -192,7 +197,7 @@ class CI_Output { // We'll just skip content-length in those cases. if ($this->_zlib_oc && strncasecmp($header, 'content-length', 14) === 0) { - return; + return $this; } $this->headers[] = array($header, $replace); @@ -202,10 +207,11 @@ class CI_Output { // -------------------------------------------------------------------- /** - * Set Content Type Header + * Set Content-Type Header * - * @param string extension of the file we're outputting - * @return void + * @param string $mime_type Extension of the file we're outputting + * @param string $charset Character set (default: NULL) + * @return object $this */ public function set_content_type($mime_type, $charset = NULL) { @@ -242,7 +248,7 @@ class CI_Output { // -------------------------------------------------------------------- /** - * Get Current Content Type Header + * Get Current Content-Type Header * * @return string 'text/html', if not already set */ @@ -263,11 +269,13 @@ class CI_Output { /** * Set HTTP Status Header - * moved to Common procedural functions in 1.7.2 * - * @param int the status code - * @param string - * @return void + * As of version 1.7.2, this is an alias for common function + * set_status_header(). + * + * @param int $code Status code (default: 200) + * @param string $text Optional message + * @return object $this */ public function set_status_header($code = 200, $text = '') { @@ -280,8 +288,8 @@ class CI_Output { /** * Enable/disable Profiler * - * @param bool - * @return void + * @param bool $val TRUE to enable or FALSE to disable + * @return object $this */ public function enable_profiler($val = TRUE) { @@ -294,10 +302,11 @@ class CI_Output { /** * Set Profiler Sections * - * Allows override of default / config settings for Profiler section display + * Allows override of default/config settings for + * Profiler section display. * - * @param array - * @return void + * @param array $sections Profiler sections + * @return object $this */ public function set_profiler_sections($sections) { @@ -320,8 +329,8 @@ class CI_Output { /** * Set Cache * - * @param int - * @return void + * @param int $time Cache expiration time in seconds + * @return object $this */ public function cache($time) { @@ -334,16 +343,16 @@ class CI_Output { /** * Display Output * - * All "view" data is automatically put into this variable by the controller class: - * - * $this->final_output + * Processes sends the sends finalized output data to the browser along + * with any server headers and profile data. It also stops benchmark + * timers so the page rendering speed and memory usage can be shown. * - * This function sends the finalized output data to the browser along - * with any server headers and profile data. It also stops the - * benchmark timer so the page rendering speed and memory usage can be shown. + * Note: All "view" data is automatically put into $this->final_output + * by controller class. * - * @param string - * @return mixed + * @uses CI_Output::$final_output + * @param string $output Output data override + * @return void */ public function _display($output = '') { @@ -374,10 +383,9 @@ class CI_Output { $output = $this->minify($output, $this->mime_type); } - // -------------------------------------------------------------------- - // Do we need to write a cache file? Only if the controller does not have its + // Do we need to write a cache file? Only if the controller does not have its // own _output() method and we are not dealing with a cache file, which we // can determine by the existence of the $CI object above if ($this->cache_expiration > 0 && isset($CI) && ! method_exists($CI, '_output')) @@ -430,7 +438,7 @@ class CI_Output { echo $output; log_message('debug', 'Final output sent to browser'); log_message('debug', 'Total execution time: '.$elapsed); - return TRUE; + return; } // -------------------------------------------------------------------- @@ -472,9 +480,9 @@ class CI_Output { // -------------------------------------------------------------------- /** - * Write a Cache File + * Write Cache * - * @param string + * @param string $output Output data to cache * @return void */ public function _write_cache($output) @@ -525,11 +533,14 @@ class CI_Output { // -------------------------------------------------------------------- /** - * Update/serve a cached file + * Update/serve cached output + * + * @uses CI_Config + * @uses CI_URI * - * @param object config class - * @param object uri class - * @return bool + * @param object &$CFG CI_Config class instance + * @param object &$URI CI_URI class instance + * @return bool TRUE on success or FALSE on failure */ public function _display_cache(&$CFG, &$URI) { @@ -552,13 +563,13 @@ class CI_Output { fclose($fp); // Strip out the embedded timestamp - if ( ! preg_match('/\d+TS--->/', $cache, $match)) + if ( ! preg_match('/^(\d+)TS--->/', $cache, $match)) { return FALSE; } $last_modified = filemtime($cache_path); - $expire = str_replace('TS--->', '', $match[0]); + $expire = $match[1]; // Has the file expired? if ($_SERVER['REQUEST_TIME'] >= $expire && is_really_writable($cache_path)) @@ -583,11 +594,13 @@ class CI_Output { // -------------------------------------------------------------------- /** + * Set Cache Header + * * Set the HTTP headers to match the server-side file cache settings * in order to reduce bandwidth. * - * @param int timestamp of when the page was last modified - * @param int timestamp of when should the requested page expire from cache + * @param int $last_modified Timestamp of when the page was last modified + * @param int $expiration Timestamp of when should the requested page expire from cache * @return void */ public function set_cache_header($last_modified, $expiration) @@ -611,11 +624,13 @@ class CI_Output { // -------------------------------------------------------------------- /** - * Reduce excessive size of HTML content. + * Minify * - * @param string - * @param string - * @return string + * Reduce excessive size of HTML/CSS/JavaScript content. + * + * @param string $output Output to minify + * @param string $type Output content MIME type + * @return string Minified output */ public function minify($output, $type = 'text/html') { diff --git a/system/core/Router.php b/system/core/Router.php index 5bc053045..30bf39657 100644 --- a/system/core/Router.php +++ b/system/core/Router.php @@ -1,4 +1,4 @@ -<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed'); +<?php /** * CodeIgniter * @@ -24,6 +24,7 @@ * @since Version 1.0 * @filesource */ +defined('BASEPATH') OR exit('No direct script access allowed'); /** * Router Class @@ -39,56 +40,49 @@ class CI_Router { /** - * Config class + * CI_Config class object * - * @var object + * @var object */ public $config; /** * List of routes * - * @var array + * @var array */ public $routes = array(); /** - * List of error routes - * - * @var array - */ - public $error_routes = array(); - - /** * Current class name * - * @var string + * @var string */ public $class = ''; /** * Current method name * - * @var string + * @var string */ public $method = 'index'; /** * Sub-directory that contains the requested controller class * - * @var string + * @var string */ public $directory = ''; /** * Default controller (and method if specific) * - * @var string + * @var string */ public $default_controller; /** - * Constructor + * Class constructor * * Runs the route mapping function. * @@ -104,9 +98,9 @@ class CI_Router { // -------------------------------------------------------------------- /** - * Set the route mapping + * Set route mapping * - * This function determines what should be served based on the URI request, + * Determines what should be served based on the URI request, * as well as any "routes" that have been set in the routing config file. * * @return void @@ -148,12 +142,12 @@ class CI_Router { include(APPPATH.'config/routes.php'); } - $this->routes = ( ! isset($route) OR ! is_array($route)) ? array() : $route; + $this->routes = (isset($route) && is_array($route)) ? $route : array(); unset($route); // Set the default controller so we can display it in the event // the URI doesn't correlated to a valid controller. - $this->default_controller = empty($this->routes['default_controller']) ? FALSE : strtolower($this->routes['default_controller']); + $this->default_controller = empty($this->routes['default_controller']) ? FALSE : $this->routes['default_controller']; // Were there any query string segments? If so, we'll validate them and bail out since we're done. if (count($segments) > 0) @@ -179,31 +173,27 @@ class CI_Router { // -------------------------------------------------------------------- /** - * Set the default controller + * Set default controller * * @return void */ protected function _set_default_controller() { - if ($this->default_controller === FALSE) + if (empty($this->default_controller)) { show_error('Unable to determine what should be displayed. A default route has not been specified in the routing file.'); } + // Is the method being specified? - if (strpos($this->default_controller, '/') !== FALSE) + if (sscanf($this->default_controller, '%[^/]/%s', $class, $method) !== 2) { - $x = explode('/', $this->default_controller); - $this->set_class($x[0]); - $this->set_method($x[1]); - $this->_set_request($x); - } - else - { - $this->set_class($this->default_controller); - $this->set_method('index'); - $this->_set_request(array($this->default_controller, 'index')); + $method = 'index'; } + $this->set_class($class); + $this->set_method($method); + $this->_set_request(array($class, $method)); + // re-index the routed segments array so it starts with 1 rather than 0 $this->uri->_reindex_segments(); @@ -213,12 +203,12 @@ class CI_Router { // -------------------------------------------------------------------- /** - * Set the Route + * Set request route * - * This function takes an array of URI segments as - * input, and sets the current class/method + * Takes an array of URI segments as input and sets the class/method + * to be called. * - * @param array + * @param array $segments URI segments * @return void */ protected function _set_request($segments = array()) @@ -232,17 +222,8 @@ class CI_Router { $this->set_class($segments[0]); - if (isset($segments[1])) - { - // A standard method request - $this->set_method($segments[1]); - } - else - { - // This lets the "routed" segment array identify that the default - // index method is being used. - $segments[1] = 'index'; - } + isset($segments[1]) OR $segments[1] = 'index'; + $this->set_method($segments[1]); // Update our "routed" segment array to contain the segments. // Note: If there is no custom routing, this array will be @@ -253,11 +234,12 @@ class CI_Router { // -------------------------------------------------------------------- /** - * Validates the supplied segments. - * Attempts to determine the path to the controller. + * Validate request + * + * Attempts validate the URI request and determine the controller path. * - * @param array - * @return array + * @param array $segments URI segments + * @return array URI segments */ protected function _validate_request($segments) { @@ -266,9 +248,13 @@ class CI_Router { return $segments; } + $temp = str_replace('-', '_', $segments[0]); + // Does the requested controller exist in the root folder? - if (file_exists(APPPATH.'controllers/'.$segments[0].'.php')) + if (file_exists(APPPATH.'controllers/'.$temp.'.php')) { + $segments[0] = $temp; + empty($segments[1]) OR $segments[1] = str_replace('-', '_', $segments[1]); return $segments; } @@ -276,22 +262,19 @@ class CI_Router { if (is_dir(APPPATH.'controllers/'.$segments[0])) { // Set the directory and remove it from the segment array - $this->set_directory($segments[0]); - $segments = array_slice($segments, 1); - + $this->set_directory(array_shift($segments)); if (count($segments) > 0) { + $segments[0] = str_replace('-', '_', $segments[0]); + empty($segments[1]) OR $segments[1] = str_replace('-', '_', $segments[1]); + // Does the requested controller exist in the sub-folder? if ( ! file_exists(APPPATH.'controllers/'.$this->fetch_directory().$segments[0].'.php')) { if ( ! empty($this->routes['404_override'])) { - $x = explode('/', $this->routes['404_override']); - $this->set_directory(''); - $this->set_class($x[0]); - $this->set_method(isset($x[1]) ? $x[1] : 'index'); - - return $x; + $this->directory = ''; + return explode('/', $this->routes['404_override'], 2); } else { @@ -302,40 +285,26 @@ class CI_Router { else { // Is the method being specified in the route? - if (strpos($this->default_controller, '/') !== FALSE) - { - $x = explode('/', $this->default_controller); - $this->set_class($x[0]); - $this->set_method($x[1]); - } - else - { - $this->set_class($this->default_controller); - $this->set_method('index'); - } - - // Does the default controller exist in the sub-folder? - if ( ! file_exists(APPPATH.'controllers/'.$this->fetch_directory().$this->default_controller.'.php')) + $segments = explode('/', $this->default_controller); + if ( ! file_exists(APPPATH.'controllers/'.$this->fetch_directory().$segments[0].'.php')) { $this->directory = ''; - return array(); } - } return $segments; } - // If we've gotten this far it means that the URI does not correlate to a valid // controller class. We will now see if there is an override if ( ! empty($this->routes['404_override'])) { - $x = explode('/', $this->routes['404_override']); - $this->set_class($x[0]); - $this->set_method(isset($x[1]) ? $x[1] : 'index'); + if (sscanf($this->routes['404_override'], '%[^/]/%s', $class, $method) !== 2) + { + $method = 'index'; + } - return $x; + return array($class, $method); } // Nothing else to do at this point but show a 404 @@ -347,9 +316,8 @@ class CI_Router { /** * Parse Routes * - * This function matches any routes that may exist in - * the config/routes.php file against the URI to - * determine if the class/method need to be remapped. + * Matches any routes that may exist in the config/routes.php file + * against the URI to determine if the class/method need to be remapped. * * @return void */ @@ -368,13 +336,51 @@ class CI_Router { foreach ($this->routes as $key => $val) { // Convert wild-cards to RegEx - $key = str_replace(array(':any', ':num'), array('.+', '[0-9]+'), $key); + $key = str_replace(array(':any', ':num'), array('[^/]+', '[0-9]+'), $key); // Does the RegEx match? - if (preg_match('#^'.$key.'$#', $uri)) + if (preg_match('#^'.$key.'$#', $uri, $matches)) { - // Do we have a back-reference? - if (strpos($val, '$') !== FALSE && strpos($key, '(') !== FALSE) + // Are we using callbacks to process back-references? + if ( ! is_string($val) && is_callable($val)) + { + // Remove the original string from the matches array. + array_shift($matches); + + // Get the match count. + $match_count = count($matches); + + // Determine how many parameters the callback has. + $reflection = new ReflectionFunction($val); + $param_count = $reflection->getNumberOfParameters(); + + // Are there more parameters than matches? + if ($param_count > $match_count) + { + // Any params without matches will be set to an empty string. + $matches = array_merge($matches, array_fill($match_count, $param_count - $match_count, '')); + + $match_count = $param_count; + } + + // Get the parameters so we can use their default values. + $params = $reflection->getParameters(); + + for ($m = 0; $m < $match_count; $m++) + { + // Is the match empty and does a default value exist? + if (empty($matches[$m]) && $params[$m]->isDefaultValueAvailable()) + { + // Substitute the empty match for the default value. + $matches[$m] = $params[$m]->getDefaultValue(); + } + } + + // Execute the callback using the values in matches as its parameters. + $val = call_user_func_array($val, $matches); + } + // Are we using the default routing method for back-references? + elseif (strpos($val, '$') !== FALSE && strpos($key, '(') !== FALSE) { $val = preg_replace('#^'.$key.'$#', $val, $uri); } @@ -391,9 +397,9 @@ class CI_Router { // -------------------------------------------------------------------- /** - * Set the class name + * Set class name * - * @param string + * @param string $class Class name * @return void */ public function set_class($class) @@ -416,9 +422,9 @@ class CI_Router { // -------------------------------------------------------------------- /** - * Set the method name + * Set method name * - * @param string + * @param string $method Method name * @return void */ public function set_method($method) @@ -441,9 +447,9 @@ class CI_Router { // -------------------------------------------------------------------- /** - * Set the directory name + * Set directory name * - * @param string + * @param string $dir Directory name * @return void */ public function set_directory($dir) @@ -454,7 +460,10 @@ class CI_Router { // -------------------------------------------------------------------- /** - * Fetch the sub-directory (if any) that contains the requested controller class + * Fetch directory + * + * Feches the sub-directory (if any) that contains the requested + * controller class. * * @return string */ @@ -466,9 +475,9 @@ class CI_Router { // -------------------------------------------------------------------- /** - * Set the controller overrides + * Set controller overrides * - * @param array + * @param array $routing Route overrides * @return void */ public function _set_overrides($routing) @@ -490,7 +499,7 @@ class CI_Router { if (isset($routing['function'])) { - $routing['function'] = ($routing['function'] == '') ? 'index' : $routing['function']; + $routing['function'] = empty($routing['function']) ? 'index' : $routing['function']; $this->set_method($routing['function']); } } diff --git a/system/core/Security.php b/system/core/Security.php index b22d2cf19..b8e66c087 100644 --- a/system/core/Security.php +++ b/system/core/Security.php @@ -1,4 +1,4 @@ -<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed'); +<?php /** * CodeIgniter * @@ -24,6 +24,7 @@ * @since Version 1.0 * @filesource */ +defined('BASEPATH') OR exit('No direct script access allowed'); /** * Security Class @@ -37,45 +38,55 @@ class CI_Security { /** - * Random Hash for protecting URLs + * XSS Hash * - * @var string + * Random Hash for protecting URLs. + * + * @var string */ protected $_xss_hash = ''; /** - * Random Hash for Cross Site Request Forgery Protection Cookie + * CSRF Hash + * + * Random hash for Cross Site Request Forgery protection cookie * - * @var string + * @var string */ protected $_csrf_hash = ''; /** - * Expiration time for Cross Site Request Forgery Protection Cookie - * Defaults to two hours (in seconds) + * CSRF Expire time + * + * Expiration time for Cross Site Request Forgery protection cookie. + * Defaults to two hours (in seconds). * - * @var int + * @var int */ protected $_csrf_expire = 7200; /** - * Token name for Cross Site Request Forgery Protection Cookie + * CSRF Token name * - * @var string + * Token name for Cross Site Request Forgery protection cookie. + * + * @var string */ protected $_csrf_token_name = 'ci_csrf_token'; /** - * Cookie name for Cross Site Request Forgery Protection Cookie + * CSRF Cookie name + * + * Cookie name for Cross Site Request Forgery protection cookie. * - * @var string + * @var string */ protected $_csrf_cookie_name = 'ci_csrf_token'; /** * List of never allowed strings * - * @var array + * @var array */ protected $_never_allowed_str = array( 'document.cookie' => '[removed]', @@ -91,9 +102,9 @@ class CI_Security { ); /** - * List of never allowed regex replacement + * List of never allowed regex replacements * - * @var array + * @var array */ protected $_never_allowed_regex = array( 'javascript\s*:', @@ -104,7 +115,7 @@ class CI_Security { ); /** - * Initialize security class + * Class constructor * * @return void */ @@ -138,7 +149,7 @@ class CI_Security { // -------------------------------------------------------------------- /** - * Verify Cross Site Request Forgery Protection + * CSRF Verify * * @return object */ @@ -161,7 +172,7 @@ class CI_Security { } // Do the tokens exist in both the _POST and _COOKIE arrays? - if ( ! isset($_POST[$this->_csrf_token_name]) OR ! isset($_COOKIE[$this->_csrf_cookie_name]) + if ( ! isset($_POST[$this->_csrf_token_name], $_COOKIE[$this->_csrf_cookie_name]) OR $_POST[$this->_csrf_token_name] !== $_COOKIE[$this->_csrf_cookie_name]) // Do the tokens match? { $this->csrf_show_error(); @@ -188,17 +199,17 @@ class CI_Security { // -------------------------------------------------------------------- /** - * Set Cross Site Request Forgery Protection Cookie + * CSRF Set Cookie * - * @return object * @codeCoverageIgnore + * @return object */ public function csrf_set_cookie() { $expire = time() + $this->_csrf_expire; $secure_cookie = (bool) config_item('cookie_secure'); - if ($secure_cookie && (empty($_SERVER['HTTPS']) OR strtolower($_SERVER['HTTPS']) === 'off')) + if ($secure_cookie && ! is_https()) { return FALSE; } @@ -234,9 +245,8 @@ class CI_Security { /** * Get CSRF Hash * - * Getter Method - * - * @return string self::_csrf_hash + * @see CI_Security::$_csrf_hash + * @return string CSRF hash */ public function get_csrf_hash() { @@ -248,9 +258,8 @@ class CI_Security { /** * Get CSRF Token Name * - * Getter Method - * - * @return string self::_csrf_token_name + * @see CI_Security::$_csrf_token_name + * @return string CSRF token name */ public function get_csrf_token_name() { @@ -263,26 +272,26 @@ class CI_Security { * XSS Clean * * Sanitizes data so that Cross Site Scripting Hacks can be - * prevented. This function does a fair amount of work but + * prevented. This method does a fair amount of work but * it is extremely thorough, designed to prevent even the * most obscure XSS attempts. Nothing is ever 100% foolproof, * of course, but I haven't been able to get anything passed * the filter. * - * Note: This function should only be used to deal with data - * upon submission. It's not something that should - * be used for general runtime processing. + * Note: Should only be used to deal with data upon submission. + * It's not something that should be used for general + * runtime processing. * - * This function was based in part on some code and ideas I - * got from Bitflux: http://channel.bitflux.ch/wiki/XSS_Prevention + * @link http://channel.bitflux.ch/wiki/XSS_Prevention + * Based in part on some code and ideas from Bitflux. * - * To help develop this script I used this great list of - * vulnerabilities along with a few other hacks I've - * harvested from examining vulnerabilities in other programs: - * http://ha.ckers.org/xss.html + * @link http://ha.ckers.org/xss.html + * To help develop this script I used this great list of + * vulnerabilities along with a few other hacks I've + * harvested from examining vulnerabilities in other programs. * - * @param mixed string or array - * @param bool + * @param string|string[] $str Input data + * @param bool $is_image Whether the input is an image * @return string */ public function xss_clean($str, $is_image = FALSE) @@ -469,9 +478,12 @@ class CI_Security { // -------------------------------------------------------------------- /** - * Random Hash for protecting URLs + * XSS Hash * - * @return string + * Generates the XSS hash if needed and returns it. + * + * @see CI_Security::$_xss_hash + * @return string XSS hash */ public function xss_hash() { @@ -489,7 +501,7 @@ class CI_Security { /** * HTML Entities Decode * - * This function is a replacement for html_entity_decode() + * A replacement for html_entity_decode() * * The reason we are not using html_entity_decode() by itself is because * while it is not technically correct to leave out the semicolon @@ -497,8 +509,10 @@ class CI_Security { * correctly. html_entity_decode() does not convert entities without * semicolons, so we are left with our own little solution here. Bummer. * - * @param string - * @param string + * @link http://php.net/html-entity-decode + * + * @param string $str Input + * @param string $charset Character set * @return string */ public function entity_decode($str, $charset = NULL) @@ -521,10 +535,10 @@ class CI_Security { // -------------------------------------------------------------------- /** - * Filename Security + * Sanitize Filename * - * @param string - * @param bool + * @param string $str Input file name + * @param bool $relative_path Whether to preserve paths * @return string */ public function sanitize_filename($str, $relative_path = FALSE) @@ -563,7 +577,7 @@ class CI_Security { /** * Strip Image Tags * - * @param string + * @param string $str * @return string */ public function strip_image_tags($str) @@ -576,10 +590,11 @@ class CI_Security { /** * Compact Exploded Words * - * Callback function for xss_clean() to remove whitespace from - * things like j a v a s c r i p t + * Callback method for xss_clean() to remove whitespace from + * things like 'j a v a s c r i p t'. * - * @param array + * @used-by CI_Security::xss_clean() + * @param array $matches * @return string */ protected function _compact_exploded_words($matches) @@ -593,16 +608,22 @@ class CI_Security { * Remove Evil HTML Attributes (like event handlers and style) * * It removes the evil attribute and either: - * - Everything up until a space - * For example, everything between the pipes: + * + * - Everything up until a space. For example, everything between the pipes: + * + * <code> * <a |style=document.write('hello');alert('world');| class=link> - * - Everything inside the quotes - * For example, everything between the pipes: + * </code> + * + * - Everything inside the quotes. For example, everything between the pipes: + * + * <code> * <a |style="document.write('hello'); alert('world');"| class="link"> + * </code> * - * @param string $str The string to check - * @param boolean $is_image TRUE if this is an image - * @return string The string with the evil attributes removed + * @param string $str The string to check + * @param bool $is_image Whether the input is an image + * @return string The string with the evil attributes removed */ protected function _remove_evil_attributes($str, $is_image) { @@ -655,9 +676,10 @@ class CI_Security { /** * Sanitize Naughty HTML * - * Callback function for xss_clean() to remove naughty HTML elements + * Callback method for xss_clean() to remove naughty HTML elements. * - * @param array + * @used-by CI_Security::xss_clean() + * @param array $matches * @return string */ protected function _sanitize_naughty_html($matches) @@ -672,12 +694,14 @@ class CI_Security { /** * JS Link Removal * - * Callback function for xss_clean() to sanitize links + * Callback method for xss_clean() to sanitize links. + * * This limits the PCRE backtracks, making it more performance friendly * and prevents PREG_BACKTRACK_LIMIT_ERROR from being triggered in - * PHP 5.2+ on link-heavy strings + * PHP 5.2+ on link-heavy strings. * - * @param array + * @used-by CI_Security::xss_clean() + * @param array $match * @return string */ protected function _js_link_removal($match) @@ -695,12 +719,14 @@ class CI_Security { /** * JS Image Removal * - * Callback function for xss_clean() to sanitize image tags + * Callback method for xss_clean() to sanitize image tags. + * * This limits the PCRE backtracks, making it more performance friendly * and prevents PREG_BACKTRACK_LIMIT_ERROR from being triggered in - * PHP 5.2+ on image tag heavy strings + * PHP 5.2+ on image tag heavy strings. * - * @param array + * @used-by CI_Security::xss_clean() + * @param array $match * @return string */ protected function _js_img_removal($match) @@ -718,9 +744,8 @@ class CI_Security { /** * Attribute Conversion * - * Used as a callback for XSS Clean - * - * @param array + * @used-by CI_Security::xss_clean() + * @param array $match * @return string */ protected function _convert_attribute($match) @@ -733,9 +758,11 @@ class CI_Security { /** * Filter Attributes * - * Filters tag attributes for consistency and safety + * Filters tag attributes for consistency and safety. * - * @param string + * @used-by CI_Security::_js_img_removal() + * @used-by CI_Security::_js_link_removal() + * @param string $str * @return string */ protected function _filter_attributes($str) @@ -757,9 +784,8 @@ class CI_Security { /** * HTML Entity Decode Callback * - * Used as a callback for XSS Clean - * - * @param array + * @used-by CI_Security::xss_clean() + * @param array $match * @return string */ protected function _decode_entity($match) @@ -772,9 +798,8 @@ class CI_Security { /** * Validate URL entities * - * Called by xss_clean() - * - * @param string + * @used-by CI_Security::xss_clean() + * @param string $str * @return string */ protected function _validate_entities($str) @@ -812,8 +837,7 @@ class CI_Security { /** * Do Never Allowed * - * A utility function for xss_clean() - * + * @used-by CI_Security::xss_clean() * @param string * @return string */ @@ -832,7 +856,7 @@ class CI_Security { // -------------------------------------------------------------------- /** - * Set Cross Site Request Forgery Protection Cookie + * Set CSRF Hash and Cookie * * @return string */ diff --git a/system/core/URI.php b/system/core/URI.php index 6a8b1a5ac..91740254c 100644 --- a/system/core/URI.php +++ b/system/core/URI.php @@ -1,4 +1,4 @@ -<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed'); +<?php /** * CodeIgniter * @@ -24,6 +24,7 @@ * @since Version 1.0 * @filesource */ +defined('BASEPATH') OR exit('No direct script access allowed'); /** * URI Class @@ -39,36 +40,37 @@ class CI_URI { /** - * List of cached uri segments + * List of cached URI segments * - * @var array + * @var array */ public $keyval = array(); /** - * Current uri string + * Current URI string * - * @var string + * @var string */ public $uri_string; /** - * List of uri segments + * List of URI segments * - * @var array + * @var array */ public $segments = array(); /** - * Re-indexed list of uri segments - * Starts at 1 instead of 0 + * Re-indexed list of URI segments * - * @var array + * Starts at 1 instead of 0. + * + * @var array */ public $rsegments = array(); /** - * Constructor + * Class constructor * * Simply globalizes the $RTR object. The front * loads the Router class early on so it's not available @@ -85,10 +87,9 @@ class CI_URI { // -------------------------------------------------------------------- /** - * Get the URI String - * - * Called by CI_Router + * Fetch URI String * + * @used-by CI_Router * @return void */ public function _fetch_uri_string() @@ -98,31 +99,28 @@ class CI_URI { // Is the request coming from the command line? if ($this->_is_cli_request()) { - $this->_set_uri_string($this->_parse_cli_args()); + $this->_set_uri_string($this->_parse_argv()); return; } - // Let's try the REQUEST_URI first, this will work in most situations - if ($uri = $this->_detect_uri()) + // Is there a PATH_INFO variable? This should be the easiest solution. + if (isset($_SERVER['PATH_INFO'])) { - $this->_set_uri_string($uri); + $this->_set_uri_string($_SERVER['PATH_INFO']); return; } - // Is there a PATH_INFO variable? - // Note: some servers seem to have trouble with getenv() so we'll test it two ways - $path = isset($_SERVER['PATH_INFO']) ? $_SERVER['PATH_INFO'] : @getenv('PATH_INFO'); - if (trim($path, '/') !== '' && $path !== '/'.SELF) + // Let's try REQUEST_URI then, this will work in most situations + if (($uri = $this->_parse_request_uri()) !== '') { - $this->_set_uri_string($path); + $this->_set_uri_string($uri); return; } - // No PATH_INFO?... What about QUERY_STRING? - $path = isset($_SERVER['QUERY_STRING']) ? $_SERVER['QUERY_STRING'] : @getenv('QUERY_STRING'); - if (trim($path, '/') !== '') + // No REQUEST_URI either?... What about QUERY_STRING? + if (($uri = $this->_parse_query_string()) !== '') { - $this->_set_uri_string($path); + $this->_set_uri_string($uri); return; } @@ -140,95 +138,86 @@ class CI_URI { $uri = strtoupper($this->config->item('uri_protocol')); - if ($uri === 'REQUEST_URI') + if ($uri === 'CLI') { - $this->_set_uri_string($this->_detect_uri()); + $this->_set_uri_string($this->_parse_argv()); return; } - elseif ($uri === 'CLI') + elseif (method_exists($this, ($method = '_parse_'.strtolower($uri)))) { - $this->_set_uri_string($this->_parse_cli_args()); + $this->_set_uri_string($this->$method()); return; } - $path = isset($_SERVER[$uri]) ? $_SERVER[$uri] : @getenv($uri); - $this->_set_uri_string($path); + $uri = isset($_SERVER[$uri]) ? $_SERVER[$uri] : @getenv($uri); + $this->_set_uri_string($uri); } // -------------------------------------------------------------------- /** - * Set the URI String + * Set URI String * - * @param string + * @param string $str * @return void */ protected function _set_uri_string($str) { - // Filter out control characters - $str = remove_invisible_characters($str, FALSE); - - // If the URI contains only a slash we'll kill it - $this->uri_string = ($str === '/') ? '' : $str; + // Filter out control characters and trim slashes + $this->uri_string = trim(remove_invisible_characters($str, FALSE), '/'); } // -------------------------------------------------------------------- /** - * Detects the URI + * Parse REQUEST_URI * - * This function will detect the URI automatically - * and fix the query string if necessary. + * Will parse REQUEST_URI and automatically detect the URI from it, + * while fixing the query string if necessary. * + * @used-by CI_URI::_fetch_uri_string() * @return string */ - protected function _detect_uri() + protected function _parse_request_uri() { if ( ! isset($_SERVER['REQUEST_URI'], $_SERVER['SCRIPT_NAME'])) { return ''; } - if (strpos($_SERVER['REQUEST_URI'], $_SERVER['SCRIPT_NAME']) === 0) - { - $uri = substr($_SERVER['REQUEST_URI'], strlen($_SERVER['SCRIPT_NAME'])); - } - elseif (strpos($_SERVER['REQUEST_URI'], dirname($_SERVER['SCRIPT_NAME'])) === 0) + $uri = parse_url($_SERVER['REQUEST_URI']); + $query = isset($uri['query']) ? $uri['query'] : ''; + $uri = isset($uri['path']) ? rawurldecode($uri['path']) : ''; + + if (strpos($uri, $_SERVER['SCRIPT_NAME']) === 0) { - $uri = substr($_SERVER['REQUEST_URI'], strlen(dirname($_SERVER['SCRIPT_NAME']))); + $uri = (string) substr($uri, strlen($_SERVER['SCRIPT_NAME'])); } - else + elseif (strpos($uri, dirname($_SERVER['SCRIPT_NAME'])) === 0) { - $uri = $_SERVER['REQUEST_URI']; + $uri = (string) substr($uri, strlen(dirname($_SERVER['SCRIPT_NAME']))); } // This section ensures that even on servers that require the URI to be in the query string (Nginx) a correct // URI is found, and also fixes the QUERY_STRING server var and $_GET array. - if (strpos($uri, '?/') === 0) + if (trim($uri, '/') === '' && strncmp($query, '/', 1) === 0) { - $uri = substr($uri, 2); - } - - $parts = explode('?', $uri, 2); - $uri = $parts[0]; - if (isset($parts[1])) - { - $_SERVER['QUERY_STRING'] = $parts[1]; - parse_str($_SERVER['QUERY_STRING'], $_GET); + $query = explode('?', $query, 2); + $uri = rawurldecode($query[0]); + $_SERVER['QUERY_STRING'] = isset($query[1]) ? $query[1] : ''; } else { - $_SERVER['QUERY_STRING'] = ''; - $_GET = array(); + $_SERVER['QUERY_STRING'] = $query; } - if ($uri === '/' OR empty($uri)) + parse_str($_SERVER['QUERY_STRING'], $_GET); + + if ($uri === '/' OR $uri === '') { return '/'; } - $uri = parse_url('pseudo://hostname/'.$uri, PHP_URL_PATH); - // Do some final cleaning of the URI and return it return str_replace(array('//', '../'), '/', trim($uri, '/')); } @@ -236,10 +225,43 @@ class CI_URI { // -------------------------------------------------------------------- /** - * Is cli Request? + * Parse QUERY_STRING * - * Duplicate of function from the Input class to test to see if a request was made from the command line + * Will parse QUERY_STRING and automatically detect the URI from it. * + * @used-by CI_URI::_fetch_uri_string() + * @return string + */ + protected function _parse_query_string() + { + $uri = isset($_SERVER['QUERY_STRING']) ? $_SERVER['QUERY_STRING'] : @getenv('QUERY_STRING'); + + if (trim($uri, '/') === '') + { + return ''; + } + elseif (strncmp($uri, '/', 1) === 0) + { + $uri = explode('?', $uri, 2); + $_SERVER['QUERY_STRING'] = isset($uri[1]) ? $uri[1] : ''; + $uri = rawurldecode($uri[0]); + } + + parse_str($_SERVER['QUERY_STRING'], $_GET); + + return str_replace(array('//', '../'), '/', trim($uri, '/')); + } + + // -------------------------------------------------------------------- + + /** + * Is CLI Request? + * + * Duplicate of method from the Input class to test to see if + * a request was made from the command line. + * + * @see CI_Input::is_cli_request() + * @used-by CI_URI::_fetch_uri_string() * @return bool */ protected function _is_cli_request() @@ -250,26 +272,27 @@ class CI_URI { // -------------------------------------------------------------------- /** - * Parse cli arguments + * Parse CLI arguments * * Take each command line argument and assume it is a URI segment. * * @return string */ - protected function _parse_cli_args() + protected function _parse_argv() { $args = array_slice($_SERVER['argv'], 1); - return $args ? '/'.implode('/', $args) : ''; + return $args ? implode('/', $args) : ''; } // -------------------------------------------------------------------- /** - * Filter segments for malicious characters + * Filter URI * - * Called by CI_Router + * Filters segments for malicious characters. * - * @param string + * @used-by CI_Router + * @param string $str * @return string */ public function _filter_uri($str) @@ -278,7 +301,7 @@ class CI_URI { { // preg_quote() in PHP 5.3 escapes -, so the str_replace() and addition of - to preg_quote() is to maintain backwards // compatibility as many are unaware of how characters in the permitted_uri_chars will be parsed as a regex pattern - if ( ! preg_match('|^['.str_replace(array('\\-', '\-'), '-', preg_quote($this->config->item('permitted_uri_chars'), '-')).']+$|i', urldecode($str))) + if ( ! preg_match('|^['.str_replace(array('\\-', '\-'), '-', preg_quote($this->config->item('permitted_uri_chars'), '-')).']+$|i', $str)) { show_error('The URI you submitted has disallowed characters.', 400); } @@ -294,10 +317,11 @@ class CI_URI { // -------------------------------------------------------------------- /** - * Remove the suffix from the URL if needed + * Remove URL suffix * - * Called by CI_Router + * Removes the suffix from the URL if needed. * + * @used-by CI_Router * @return void */ public function _remove_url_suffix() @@ -313,11 +337,12 @@ class CI_URI { // -------------------------------------------------------------------- /** - * Explode the URI Segments. The individual segments will - * be stored in the $this->segments array. + * Explode URI segments * - * Called by CI_Router + * The individual segments will be stored in the $this->segments array. * + * @see CI_URI::$segments + * @used-by CI_Router * @return void */ public function _explode_segments() @@ -339,13 +364,12 @@ class CI_URI { /** * Re-index Segments * - * This function re-indexes the $this->segment array so that it - * starts at 1 rather than 0. Doing so makes it simpler to - * use functions like $this->uri->segment(n) since there is - * a 1:1 relationship between the segment array and the actual segments. - * - * Called by CI_Router + * Re-indexes the CI_URI::$segment array so that it starts at 1 rather + * than 0. Doing so makes it simpler to use methods like + * CI_URI::segment(n) since there is a 1:1 relationship between the + * segment array and the actual segments. * + * @used-by CI_Router * @return void */ public function _reindex_segments() @@ -359,13 +383,12 @@ class CI_URI { // -------------------------------------------------------------------- /** - * Fetch a URI Segment + * Fetch URI Segment * - * This function returns the URI segment based on the number provided. - * - * @param int - * @param mixed - * @return string + * @see CI_URI::$segments + * @param int $n Index + * @param mixed $no_result What to return if the segment index is not found + * @return mixed */ public function segment($n, $no_result = NULL) { @@ -375,15 +398,17 @@ class CI_URI { // -------------------------------------------------------------------- /** - * Fetch a URI "routed" Segment + * Fetch URI "routed" Segment * - * This function returns the re-routed URI segment (assuming routing rules are used) - * based on the number provided. If there is no routing this function returns the - * same result as $this->segment() + * Returns the re-routed URI segment (assuming routing rules are used) + * based on the index provided. If there is no routing, will return + * the same result as CI_URI::segment(). * - * @param int - * @param mixed - * @return string + * @see CI_URI::$rsegments + * @see CI_URI::segment() + * @param int $n Index + * @param mixed $no_result What to return if the segment index is not found + * @return mixed */ public function rsegment($n, $no_result = NULL) { @@ -393,23 +418,23 @@ class CI_URI { // -------------------------------------------------------------------- /** - * Generate a key value pair from the URI string + * URI to assoc * - * This function generates and associative array of URI data starting - * at the supplied segment. For example, if this is your URI: + * Generates an associative array of URI data starting at the supplied + * segment index. For example, if this is your URI: * * example.com/user/search/name/joe/location/UK/gender/male * - * You can use this function to generate an array with this prototype: + * You can use this method to generate an array with this prototype: * - * array ( - * name => joe - * location => UK - * gender => male - * ) + * array ( + * name => joe + * location => UK + * gender => male + * ) * - * @param int the starting segment number - * @param array an array of default values + * @param int $n Index (default: 3) + * @param array $default Default values * @return array */ public function uri_to_assoc($n = 3, $default = array()) @@ -420,10 +445,14 @@ class CI_URI { // -------------------------------------------------------------------- /** - * Identical to above only it uses the re-routed segment array + * Routed URI to assoc + * + * Identical to CI_URI::uri_to_assoc(), only it uses the re-routed + * segment array. * - * @param int the starting segment number - * @param array an array of default values + * @see CI_URI::uri_to_assoc() + * @param int $n Index (default: 3) + * @param array $default Default values * @return array */ public function ruri_to_assoc($n = 3, $default = array()) @@ -434,11 +463,15 @@ class CI_URI { // -------------------------------------------------------------------- /** - * Generate a key value pair from the URI string or Re-routed URI string + * Internal URI-to-assoc * - * @param int the starting segment number - * @param array an array of default values - * @param string which array we should use + * Generates a key/value pair from the URI string or re-routed URI string. + * + * @used-by CI_URI::uri_to_assoc() + * @used-by CI_URI::ruri_to_assoc() + * @param int $n Index (default: 3) + * @param array $default Default values + * @param string $which Array name ('segment' or 'rsegment') * @return array */ protected function _uri_to_assoc($n = 3, $default = array(), $which = 'segment') @@ -448,9 +481,11 @@ class CI_URI { return $default; } - if (isset($this->keyval[$n])) + in_array($which, array('segment', 'rsegment'), TRUE) OR $which = 'segment'; + + if (isset($this->keyval[$which], $this->keyval[$which][$n])) { - return $this->keyval[$n]; + return $this->keyval[$which][$n]; } if ($which === 'segment') @@ -474,7 +509,7 @@ class CI_URI { $segments = array_slice($this->$segment_array(), ($n - 1)); $i = 0; $lastval = ''; - $retval = array(); + $retval = array(); foreach ($segments as $seg) { if ($i % 2) @@ -502,17 +537,20 @@ class CI_URI { } // Cache the array for reuse - $this->keyval[$n] = $retval; + isset($this->keyval[$which]) OR $this->keyval[$which] = array(); + $this->keyval[$which][$n] = $retval; return $retval; } // -------------------------------------------------------------------- /** - * Generate a URI string from an associative array + * Assoc to URI * - * @param array an associative array of key/values - * @return array + * Generates a URI string from an associative array. + * + * @param array $array Input array of key/value pairs + * @return string URI string */ public function assoc_to_uri($array) { @@ -529,10 +567,12 @@ class CI_URI { // -------------------------------------------------------------------- /** - * Fetch a URI Segment and add a trailing slash + * Slash segment + * + * Fetches an URI segment with a slash. * - * @param int - * @param string + * @param int $n Index + * @param string $where Where to add the slash ('trailing' or 'leading') * @return string */ public function slash_segment($n, $where = 'trailing') @@ -543,10 +583,12 @@ class CI_URI { // -------------------------------------------------------------------- /** - * Fetch a URI Segment and add a trailing slash + * Slash routed segment * - * @param int - * @param string + * Fetches an URI routed segment with a slash. + * + * @param int $n Index + * @param string $where Where to add the slash ('trailing' or 'leading') * @return string */ public function slash_rsegment($n, $where = 'trailing') @@ -557,11 +599,16 @@ class CI_URI { // -------------------------------------------------------------------- /** - * Fetch a URI Segment and add a trailing slash - helper function + * Internal Slash segment + * + * Fetches an URI Segment and adds a slash to it. * - * @param int - * @param string - * @param string + * @used-by CI_URI::slash_segment() + * @used-by CI_URI::slash_rsegment() + * + * @param int $n Index + * @param string $where Where to add the slash ('trailing' or 'leading') + * @param string $which Array name ('segment' or 'rsegment') * @return string */ protected function _slash_segment($n, $where = 'trailing', $which = 'segment') @@ -585,7 +632,7 @@ class CI_URI { /** * Segment Array * - * @return array + * @return array CI_URI::$segments */ public function segment_array() { @@ -597,7 +644,7 @@ class CI_URI { /** * Routed Segment Array * - * @return array + * @return array CI_URI::$rsegments */ public function rsegment_array() { @@ -631,26 +678,32 @@ class CI_URI { // -------------------------------------------------------------------- /** - * Fetch the entire URI string + * Fetch URI string * - * @return string + * @return string CI_URI::$uri_string */ public function uri_string() { return $this->uri_string; } - // -------------------------------------------------------------------- /** - * Fetch the entire Re-routed URI string + * Fetch Re-routed URI string * * @return string */ public function ruri_string() { - return implode('/', $this->rsegment_array()); + global $RTR; + + if (($dir = $RTR->fetch_directory()) === '/') + { + $dir = ''; + } + + return $dir.implode('/', $this->rsegment_array()); } } diff --git a/system/core/Utf8.php b/system/core/Utf8.php index 0a7ec501c..5bc2dd5c9 100644 --- a/system/core/Utf8.php +++ b/system/core/Utf8.php @@ -1,4 +1,4 @@ -<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed'); +<?php /** * CodeIgniter * @@ -24,6 +24,7 @@ * @since Version 2.0 * @filesource */ +defined('BASEPATH') OR exit('No direct script access allowed'); /** * Utf8 Class @@ -39,9 +40,9 @@ class CI_Utf8 { /** - * Constructor + * Class constructor * - * Determines if UTF-8 support is to be enabled + * Determines if UTF-8 support is to be enabled. * * @return void */ @@ -49,30 +50,30 @@ class CI_Utf8 { { log_message('debug', 'Utf8 Class Initialized'); - global $CFG; + $charset = strtoupper(config_item('charset')); + + // set internal encoding for multibyte string functions if necessary + // and set a flag so we don't have to repeatedly use extension_loaded() + // or function_exists() + if (extension_loaded('mbstring')) + { + define('MB_ENABLED', TRUE); + mb_internal_encoding($charset); + } + else + { + define('MB_ENABLED', FALSE); + } if ( - @preg_match('/./u', 'é') === 1 // PCRE must support UTF-8 - && function_exists('iconv') // iconv must be installed - && (bool) @ini_get('mbstring.func_overload') !== TRUE // Multibyte string function overloading cannot be enabled - && $CFG->item('charset') === 'UTF-8' // Application charset must be UTF-8 + @preg_match('/./u', 'é') === 1 // PCRE must support UTF-8 + && function_exists('iconv') // iconv must be installed + && MB_ENABLED === TRUE // mbstring must be enabled + && $charset === 'UTF-8' // Application charset must be UTF-8 ) { define('UTF8_ENABLED', TRUE); log_message('debug', 'UTF-8 Support Enabled'); - - // set internal encoding for multibyte string functions if necessary - // and set a flag so we don't have to repeatedly use extension_loaded() - // or function_exists() - if (extension_loaded('mbstring')) - { - define('MB_ENABLED', TRUE); - mb_internal_encoding('UTF-8'); - } - else - { - define('MB_ENABLED', FALSE); - } } else { @@ -86,9 +87,11 @@ class CI_Utf8 { /** * Clean UTF-8 strings * - * Ensures strings are UTF-8 + * Ensures strings contain only valid UTF-8 characters. * - * @param string + * @uses CI_Utf8::_is_ascii() Decide whether a conversion is needed + * + * @param string $str String to clean * @return string */ public function clean_string($str) @@ -108,9 +111,9 @@ class CI_Utf8 { * * Removes all ASCII control characters except horizontal tabs, * line feeds, and carriage returns, as all others can cause - * problems in XML + * problems in XML. * - * @param string + * @param string $str String to clean * @return string */ public function safe_ascii_for_xml($str) @@ -123,11 +126,11 @@ class CI_Utf8 { /** * Convert to UTF-8 * - * Attempts to convert a string to UTF-8 + * Attempts to convert a string to UTF-8. * - * @param string - * @param string input encoding - * @return string + * @param string $str Input string + * @param string $encoding Input encoding + * @return string $str encoded in UTF-8 or FALSE on failure */ public function convert_to_utf8($str, $encoding) { @@ -135,7 +138,7 @@ class CI_Utf8 { { return @iconv($encoding, 'UTF-8', $str); } - elseif (function_exists('mb_convert_encoding')) + elseif (MB_ENABLED === TRUE) { return @mb_convert_encoding($str, 'UTF-8', $encoding); } @@ -148,9 +151,9 @@ class CI_Utf8 { /** * Is ASCII? * - * Tests if a string is standard 7-bit ASCII or not + * Tests if a string is standard 7-bit ASCII or not. * - * @param string + * @param string $str String to check * @return bool */ protected function _is_ascii($str) diff --git a/system/database/DB.php b/system/database/DB.php index d751325ce..79e5c7ad2 100644 --- a/system/database/DB.php +++ b/system/database/DB.php @@ -1,4 +1,4 @@ -<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed'); +<?php /** * CodeIgniter * @@ -24,6 +24,7 @@ * @since Version 1.0 * @filesource */ +defined('BASEPATH') OR exit('No direct script access allowed'); /** * Initialize the database @@ -31,8 +32,10 @@ * @category Database * @author EllisLab Dev Team * @link http://codeigniter.com/user_guide/database/ - * @param string - * @param bool Determines if query builder should be used or not + * + * @param string|string[] $params + * @param bool $query_builder_override + * Determines if query builder should be used or not */ function &DB($params = '', $query_builder_override = NULL) { @@ -148,11 +151,22 @@ function &DB($params = '', $query_builder_override = NULL) require_once(BASEPATH.'database/DB_query_builder.php'); if ( ! class_exists('CI_DB')) { + /** + * CI_DB + * + * Acts as an alias for both CI_DB_driver and CI_DB_query_builder. + * + * @see CI_DB_query_builder + * @see CI_DB_driver + */ class CI_DB extends CI_DB_query_builder { } } } elseif ( ! class_exists('CI_DB')) { + /** + * @ignore + */ class CI_DB extends CI_DB_driver { } } diff --git a/system/database/DB_cache.php b/system/database/DB_cache.php index ba9110382..b8f8995fa 100644 --- a/system/database/DB_cache.php +++ b/system/database/DB_cache.php @@ -1,4 +1,4 @@ -<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed'); +<?php /** * CodeIgniter * @@ -24,6 +24,7 @@ * @since Version 1.0 * @filesource */ +defined('BASEPATH') OR exit('No direct script access allowed'); /** * Database Cache Class @@ -34,15 +35,39 @@ */ class CI_DB_Cache { + /** + * CI Singleton + * + * @var object + */ public $CI; - public $db; // allows passing of db object so that multiple database connections and returned db objects can be supported + /** + * Database object + * + * Allows passing of DB object so that multiple database connections + * and returned DB objects can be supported. + * + * @var object + */ + public $db; + + // -------------------------------------------------------------------- + + /** + * Constructor + * + * @param object &$db + * @return void + */ public function __construct(&$db) { // Assign the main CI object to $this->CI and load the file helper since we use it a lot $this->CI =& get_instance(); $this->db =& $db; $this->CI->load->helper('file'); + + $this->check_path(); } // -------------------------------------------------------------------- @@ -50,7 +75,7 @@ class CI_DB_Cache { /** * Set Cache Directory Path * - * @param string the path to the cache directory + * @param string $path Path to the cache directory * @return bool */ public function check_path($path = '') @@ -66,7 +91,9 @@ class CI_DB_Cache { } // Add a trailing slash to the path if needed - $path = preg_replace('/(.+?)\/*$/', '\\1/', $path); + $path = realpath($path) + ? rtrim(realpath($path), DIRECTORY_SEPARATOR).DIRECTORY_SEPARATOR + : rtrim($path, '/').'/'; if ( ! is_dir($path) OR ! is_really_writable($path)) { @@ -84,17 +111,13 @@ class CI_DB_Cache { * Retrieve a cached query * * The URI being requested will become the name of the cache sub-folder. - * An MD5 hash of the SQL statement will become the cache file name + * An MD5 hash of the SQL statement will become the cache file name. * + * @param string $sql * @return string */ public function read($sql) { - if ( ! $this->check_path()) - { - return $this->db->cache_off(); - } - $segment_one = ($this->CI->uri->segment(1) == FALSE) ? 'default' : $this->CI->uri->segment(1); $segment_two = ($this->CI->uri->segment(2) == FALSE) ? 'index' : $this->CI->uri->segment(2); $filepath = $this->db->cachedir.$segment_one.'+'.$segment_two.'/'.md5($sql); @@ -112,15 +135,12 @@ class CI_DB_Cache { /** * Write a query to a cache file * + * @param string $sql + * @param object $object * @return bool */ public function write($sql, $object) { - if ( ! $this->check_path()) - { - return $this->db->cache_off(); - } - $segment_one = ($this->CI->uri->segment(1) == FALSE) ? 'default' : $this->CI->uri->segment(1); $segment_two = ($this->CI->uri->segment(2) == FALSE) ? 'index' : $this->CI->uri->segment(2); $dir_path = $this->db->cachedir.$segment_one.'+'.$segment_two.'/'; @@ -150,7 +170,9 @@ class CI_DB_Cache { /** * Delete cache files within a particular directory * - * @return bool + * @param string $segment_one + * @param string $segment_two + * @return void */ public function delete($segment_one = '', $segment_two = '') { @@ -173,7 +195,7 @@ class CI_DB_Cache { /** * Delete all existing cache files * - * @return bool + * @return void */ public function delete_all() { diff --git a/system/database/DB_driver.php b/system/database/DB_driver.php index d63a1d955..39db16150 100644 --- a/system/database/DB_driver.php +++ b/system/database/DB_driver.php @@ -1,4 +1,4 @@ -<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed'); +<?php /** * CodeIgniter * @@ -24,6 +24,7 @@ * @since Version 1.0 * @filesource */ +defined('BASEPATH') OR exit('No direct script access allowed'); /** * Database Driver Class @@ -40,55 +41,314 @@ */ abstract class CI_DB_driver { + /** + * Data Source Name / Connect string + * + * @var string + */ public $dsn; + + /** + * Username + * + * @var string + */ public $username; + + /** + * Password + * + * @var string + */ public $password; + + /** + * Hostname + * + * @var string + */ public $hostname; + + /** + * Database name + * + * @var string + */ public $database; + + /** + * Database driver + * + * @var string + */ public $dbdriver = 'mysqli'; + + /** + * Sub-driver + * + * @used-by CI_DB_pdo_driver + * @var string + */ public $subdriver; + + /** + * Table prefix + * + * @var string + */ public $dbprefix = ''; + + /** + * Character set + * + * @var string + */ public $char_set = 'utf8'; + + /** + * Collation + * + * @var string + */ public $dbcollat = 'utf8_general_ci'; - public $autoinit = TRUE; // Whether to automatically initialize the DB + + /** + * Auto-init flag + * + * Whether to automatically initialize the DB connection. + * + * @var bool + */ + public $autoinit = TRUE; + + /** + * Encryption flag/data + * + * @var mixed + */ + public $encrypt = FALSE; + + /** + * Swap Prefix + * + * @var string + */ public $swap_pre = ''; + + /** + * Database port + * + * @var int + */ public $port = ''; + + /** + * Persistent connection flag + * + * @var bool + */ public $pconnect = FALSE; + + /** + * Connection ID + * + * @var object|resource + */ public $conn_id = FALSE; + + /** + * Result ID + * + * @var object|resource + */ public $result_id = FALSE; + + /** + * Debug flag + * + * Whether to display error messages. + * + * @var bool + */ public $db_debug = FALSE; + + /** + * Benchmark time + * + * @var int + */ public $benchmark = 0; + + /** + * Executed queries count + * + * @var int + */ public $query_count = 0; + + /** + * Bind marker + * + * Character used to identify values in a prepared statement. + * + * @var string + */ public $bind_marker = '?'; + + /** + * Save queries flag + * + * Whether to keep an in-memory history of queries for debugging purposes. + * + * @var bool + */ public $save_queries = TRUE; + + /** + * Queries list + * + * @see CI_DB_driver::$save_queries + * @var string[] + */ public $queries = array(); + + /** + * Query times + * + * A list of times that queries took to execute. + * + * @var array + */ public $query_times = array(); + + /** + * Data cache + * + * An internal generic value cache. + * + * @var array + */ public $data_cache = array(); + /** + * Transaction enabled flag + * + * @var bool + */ public $trans_enabled = TRUE; + + /** + * Strict transaction mode flag + * + * @var bool + */ public $trans_strict = TRUE; + + /** + * Transaction depth level + * + * @var int + */ protected $_trans_depth = 0; - protected $_trans_status = TRUE; // Used with transactions to determine if a rollback should occur + /** + * Transaction status flag + * + * Used with transactions to determine if a rollback should occur. + * + * @var bool + */ + protected $_trans_status = TRUE; + + /** + * Cache On flag + * + * @var bool + */ public $cache_on = FALSE; + + /** + * Cache directory path + * + * @var bool + */ public $cachedir = ''; + + /** + * Cache auto-delete flag + * + * @var bool + */ public $cache_autodel = FALSE; - public $CACHE; // The cache class object + /** + * DB Cache object + * + * @see CI_DB_cache + * @var object + */ + public $CACHE; + + /** + * Protect identifiers flag + * + * @var bool + */ protected $_protect_identifiers = TRUE; - protected $_reserved_identifiers = array('*'); // Identifiers that should NOT be escaped /** - * The syntax to count rows is slightly different across different - * database engines, so this string appears in each driver and is - * used for the count_all() and count_all_results() functions. + * List of reserved identifiers + * + * Identifiers that must NOT be escaped. + * + * @var string[] + */ + protected $_reserved_identifiers = array('*'); + + /** + * Identifier escape character + * + * @var string + */ + protected $_escape_char = '"'; + + /** + * ESCAPE statement string + * + * @var string + */ + protected $_like_escape_str = " ESCAPE '%s' "; + + /** + * ESCAPE character + * + * @var string + */ + protected $_like_escape_chr = '!'; + + /** + * ORDER BY random keyword + * + * @var string + */ + protected $_random_keyword = ' RAND()'; + + /** + * COUNT string + * + * @used-by CI_DB_driver::count_all() + * @used-by CI_DB_query_builder::count_all_results() + * + * @var string */ protected $_count_string = 'SELECT COUNT(*) AS '; + // -------------------------------------------------------------------- + /** - * Constructor + * Class constructor * - * @param array + * @param array $params * @return void */ public function __construct($params) @@ -305,8 +565,9 @@ abstract class CI_DB_driver { * FALSE upon failure, and if the $db_debug variable is set to TRUE * will raise an error. * - * @param string An SQL query string - * @param array An array of binding data + * @param string $sql + * @param array $binds = FALSE An array of binding data + * @param bool $return_object = NULL * @return mixed */ public function query($sql, $binds = FALSE, $return_object = NULL) @@ -509,6 +770,7 @@ abstract class CI_DB_driver { * If strict mode is disabled, each group is treated autonomously, meaning * a failure of one group will not affect any others * + * @param bool $mode = TRUE * @return void */ public function trans_strict($mode = TRUE) @@ -521,6 +783,7 @@ abstract class CI_DB_driver { /** * Start Transaction * + * @param bool $test_mode = FALSE * @return void */ public function trans_start($test_mode = FALSE) @@ -632,7 +895,7 @@ abstract class CI_DB_driver { // Make sure not to replace a chunk inside a string that happens to match the bind marker if ($c = preg_match_all("/'[^']*'/i", $sql, $matches)) { - $c = preg_match_all('/'.preg_quote($this->bind_marker).'/i', + $c = preg_match_all('/'.preg_quote($this->bind_marker, '/').'/i', str_replace($matches[0], str_replace($this->bind_marker, str_repeat(' ', $ml), $matches[0]), $sql, $c), @@ -644,7 +907,7 @@ abstract class CI_DB_driver { return $sql; } } - elseif (($c = preg_match_all('/'.preg_quote($this->bind_marker).'/i', $sql, $matches, PREG_OFFSET_CAPTURE)) !== $bind_count) + elseif (($c = preg_match_all('/'.preg_quote($this->bind_marker, '/').'/i', $sql, $matches, PREG_OFFSET_CAPTURE)) !== $bind_count) { return $sql; } @@ -669,7 +932,7 @@ abstract class CI_DB_driver { */ public function is_write_type($sql) { - return (bool) preg_match('/^\s*"?(SET|INSERT|UPDATE|DELETE|REPLACE|CREATE|DROP|TRUNCATE|LOAD DATA|COPY|ALTER|RENAME|GRANT|REVOKE|LOCK|UNLOCK|REINDEX)\s+/i', $sql); + return (bool) preg_match('/^\s*"?(SET|INSERT|UPDATE|DELETE|REPLACE|CREATE|DROP|TRUNCATE|LOAD|COPY|ALTER|RENAME|GRANT|REVOKE|LOCK|UNLOCK|REINDEX)\s+/i', $sql); } // -------------------------------------------------------------------- @@ -805,6 +1068,7 @@ abstract class CI_DB_driver { /** * Returns an array of table names * + * @param string $constrain_by_prefix = FALSE * @return array */ public function list_tables($constrain_by_prefix = FALSE) @@ -859,6 +1123,7 @@ abstract class CI_DB_driver { /** * Determine if a particular table exists * + * @param string $table_name * @return bool */ public function table_exists($table_name) @@ -997,13 +1262,13 @@ abstract class CI_DB_driver { if (is_array($this->_escape_char)) { $preg_ec = array( - preg_quote($this->_escape_char[0]), preg_quote($this->_escape_char[1]), + preg_quote($this->_escape_char[0], '/'), preg_quote($this->_escape_char[1], '/'), $this->_escape_char[0], $this->_escape_char[1] ); } else { - $preg_ec[0] = $preg_ec[1] = preg_quote($this->_escape_char); + $preg_ec[0] = $preg_ec[1] = preg_quote($this->_escape_char, '/'); $preg_ec[2] = $preg_ec[3] = $this->_escape_char; } } @@ -1070,43 +1335,19 @@ abstract class CI_DB_driver { */ public function update_string($table, $data, $where) { - if ($where === '') + if (empty($where)) { return FALSE; } + $this->where($where); + $fields = array(); foreach ($data as $key => $val) { $fields[$this->protect_identifiers($key)] = $this->escape($val); } - if ( ! is_array($where)) - { - $dest = array($where); - } - else - { - $dest = array(); - foreach ($where as $key => $val) - { - $prefix = (count($dest) === 0) ? '' : ' AND '; - $key = $this->protect_identifiers($key); - - if ($val !== '') - { - if ( ! $this->_has_operator($key)) - { - $key .= ' ='; - } - - $val = ' '.$this->escape($val); - } - - $dest[] = $prefix.$key.$val; - } - } - return $this->_update($this->protect_identifiers($table, TRUE, NULL, FALSE), $fields, $dest); } @@ -1119,30 +1360,19 @@ abstract class CI_DB_driver { * * @param string the table name * @param array the update data - * @param array the where clause - * @param array the orderby clause - * @param array the limit clause - * @param array the like clause * @return string */ - protected function _update($table, $values, $where, $orderby = array(), $limit = FALSE, $like = array()) + protected function _update($table, $values) { foreach ($values as $key => $val) { $valstr[] = $key.' = '.$val; } - $where = empty($where) ? '' : ' WHERE '.implode(' ', $where); - - if ( ! empty($like)) - { - $where .= ($where === '' ? ' WHERE ' : ' AND ').implode(' ', $like); - } - return 'UPDATE '.$table.' SET '.implode(', ', $valstr) - .$where - .(count($orderby) > 0 ? ' ORDER BY '.implode(', ', $orderby) : '') - .($limit ? ' LIMIT '.$limit : ''); + .$this->_compile_wh('qb_where') + .$this->_compile_order_by() + .($this->qb_limit ? ' LIMIT '.$this->qb_limit : ''); } // -------------------------------------------------------------------- @@ -1155,7 +1385,7 @@ abstract class CI_DB_driver { */ protected function _has_operator($str) { - return (bool) preg_match('/(\s|<|>|!|=|IS NULL|IS NOT NULL|BETWEEN)/i', trim($str)); + return (bool) preg_match('/(<|>|!|=|\sIS NULL|\sIS NOT NULL|\sBETWEEN|\sLIKE|\sIN\s*\(|\s)/i', trim($str)); } // -------------------------------------------------------------------- @@ -1168,8 +1398,30 @@ abstract class CI_DB_driver { */ protected function _get_operator($str) { - return preg_match('/(=|!|<|>| IS NULL| IS NOT NULL| BETWEEN)/i', $str, $match) - ? $match[1] : FALSE; + static $_operators; + + if (empty($_operators)) + { + $_les = ($this->_like_escape_str !== '') + ? '\s+'.preg_quote(trim(sprintf($this->_like_escape_str, $this->_like_escape_chr)), '/') + : ''; + $_operators = array( + '\s*(?:<|>|!)?=\s*', // =, <=, >=, != + '\s*<>?\s*', // <, <> + '\s*>\s*', // > + '\s+IS NULL', // IS NULL + '\s+IS NOT NULL', // IS NOT NULL + '\s+BETWEEN\s+\S+\s+AND\s+\S+', // BETWEEN value AND value + '\s+IN\s*\([^\)]+\)', // IN(list) + '\s+NOT IN\s*\([^\)]+\)', // NOT IN (list) + '\s+LIKE\s+\S+'.$_les, // LIKE 'expr'[ ESCAPE '%s'] + '\s+NOT LIKE\s+\S+'.$_les // NOT LIKE 'expr'[ ESCAPE '%s'] + ); + + } + + return preg_match('/'.implode('|', $_operators).'/i', $str, $match) + ? $match[0] : FALSE; } // -------------------------------------------------------------------- @@ -1177,8 +1429,7 @@ abstract class CI_DB_driver { /** * Enables a native PHP function to be run, using a platform agnostic wrapper. * - * @param string the function name - * @param mixed any parameters needed by the function + * @param string $function Function name * @return mixed */ public function call_function($function) @@ -1242,6 +1493,8 @@ abstract class CI_DB_driver { /** * Delete the cache files associated with a particular URI * + * @param string $segment_one = '' + * @param string $segment_two = '' * @return bool */ public function cache_delete($segment_one = '', $segment_two = '') @@ -1343,7 +1596,7 @@ abstract class CI_DB_driver { } else { - $message = ( ! is_array($error)) ? array(str_replace('%s', $swap, $LANG->line($error))) : $error; + $message = is_array($error) ? $error : array(str_replace('%s', $swap, $LANG->line($error))); } // Find the most likely culprit of the error by going through @@ -1352,7 +1605,13 @@ abstract class CI_DB_driver { $trace = debug_backtrace(); foreach ($trace as $call) { - if (isset($call['file']) && strpos($call['file'], BASEPATH.'database') === FALSE) + // We'll need this on Windows, as APPPATH and BASEPATH will always use forward slashes + if (DIRECTORY_SEPARATOR !== '/') + { + $call['file'] = str_replace('\\', '/', $call['file']); + } + + if (isset($call['file'], $call['class']) && strpos($call['file'], BASEPATH.'database') === FALSE && strpos($call['class'], 'Loader') !== FALSE) { // Found it - use a relative path for safety $message[] = 'Filename: '.str_replace(array(APPPATH, BASEPATH), '', $call['file']); diff --git a/system/database/DB_forge.php b/system/database/DB_forge.php index 91f9d560c..f46237e25 100644 --- a/system/database/DB_forge.php +++ b/system/database/DB_forge.php @@ -1,4 +1,4 @@ -<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed'); +<?php /** * CodeIgniter * @@ -24,6 +24,7 @@ * @since Version 1.0 * @filesource */ +defined('BASEPATH') OR exit('No direct script access allowed'); /** * Database Forge Class @@ -34,17 +35,71 @@ */ abstract class CI_DB_forge { + /** + * Fields data + * + * @var array + */ public $fields = array(); + + /** + * Keys data + * + * @var array + */ public $keys = array(); + + /** + * Primary Keys data + * + * @var array + */ public $primary_keys = array(); - public $db_char_set = ''; - // Platform specific SQL strings + /** + * Database character set + * + * @var string + */ + public $db_char_set = ''; + + // -------------------------------------------------------------------- + + /** + * CREATE DATABASE statement + * + * @var string + */ protected $_create_database = 'CREATE DATABASE %s'; + + /** + * DROP DATABASE statement + * + * @var string + */ protected $_drop_database = 'DROP DATABASE %s'; + + /** + * DROP TABLE statement + * + * @var string + */ protected $_drop_table = 'DROP TABLE IF EXISTS %s'; + + /** + * RENAME TABLE statement + * + * @var string + */ protected $_rename_table = 'ALTER TABLE %s RENAME TO %s'; + // -------------------------------------------------------------------- + + /** + * Constructor + * + * @return void + */ public function __construct() { // Assign the main database object to $this->db @@ -127,7 +182,7 @@ abstract class CI_DB_forge { */ public function add_key($key = '', $primary = FALSE) { - if (is_array($key)) + if ($primary && is_array($key)) { foreach ($key as $one) { @@ -206,7 +261,8 @@ abstract class CI_DB_forge { /** * Create Table * - * @param string the table name + * @param string $table = '' + * @param bool $if_not_exists = FALSE * @return bool */ public function create_table($table = '', $if_not_exists = FALSE) @@ -378,9 +434,8 @@ abstract class CI_DB_forge { /** * Column Modify * - * @param string the table name - * @param string the column name - * @param string the column definition + * @param string $table = '' + * @param string $field = array() column definition * @return bool */ public function modify_column($table = '', $field = array()) diff --git a/system/database/DB_query_builder.php b/system/database/DB_query_builder.php index 479b7f24a..41b30aec3 100644 --- a/system/database/DB_query_builder.php +++ b/system/database/DB_query_builder.php @@ -1,4 +1,4 @@ -<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed'); +<?php /** * CodeIgniter * @@ -24,6 +24,7 @@ * @since Version 1.0 * @filesource */ +defined('BASEPATH') OR exit('No direct script access allowed'); /** * Query Builder Class @@ -39,44 +40,213 @@ abstract class CI_DB_query_builder extends CI_DB_driver { + /** + * Return DELETE SQL flag + * + * @var bool + */ protected $return_delete_sql = FALSE; + + /** + * Reset DELETE data flag + * + * @var bool + */ protected $reset_delete_data = FALSE; + /** + * QB SELECT data + * + * @var array + */ protected $qb_select = array(); + + /** + * QB DISTINCT flag + * + * @var bool + */ protected $qb_distinct = FALSE; + + /** + * QB FROM data + * + * @var array + */ protected $qb_from = array(); + + /** + * QB JOIN data + * + * @var array + */ protected $qb_join = array(); + + /** + * QB WHERE data + * + * @var array + */ protected $qb_where = array(); - protected $qb_like = array(); + + /** + * QB GROUP BY data + * + * @var array + */ protected $qb_groupby = array(); + + /** + * QB HAVING data + * + * @var array + */ protected $qb_having = array(); + + /** + * QB keys + * + * @var array + */ protected $qb_keys = array(); + + /** + * QB LIMIT data + * + * @var int + */ protected $qb_limit = FALSE; + + /** + * QB OFFSET data + * + * @var int + */ protected $qb_offset = FALSE; + + /** + * QB ORDER BY data + * + * @var array + */ protected $qb_orderby = array(); + + /** + * QB data sets + * + * @var array + */ protected $qb_set = array(); - protected $qb_wherein = array(); + + /** + * QB aliased tables list + * + * @var array + */ protected $qb_aliased_tables = array(); - protected $qb_store_array = array(); + + /** + * QB WHERE group started flag + * + * @var bool + */ protected $qb_where_group_started = FALSE; + + /** + * QB WHERE group count + * + * @var int + */ protected $qb_where_group_count = 0; // Query Builder Caching variables + + /** + * QB Caching flag + * + * @var bool + */ protected $qb_caching = FALSE; + + /** + * QB Cache exists list + * + * @var array + */ protected $qb_cache_exists = array(); + + /** + * QB Cache SELECT data + * + * @var array + */ protected $qb_cache_select = array(); + + /** + * QB Cache FROM data + * + * @var array + */ protected $qb_cache_from = array(); + + /** + * QB Cache JOIN data + * + * @var array + */ protected $qb_cache_join = array(); + + /** + * QB Cache WHERE data + * + * @var array + */ protected $qb_cache_where = array(); - protected $qb_cache_like = array(); + + /** + * QB Cache GROUP BY data + * + * @var array + */ protected $qb_cache_groupby = array(); + + /** + * QB Cache HAVING data + * + * @var array + */ protected $qb_cache_having = array(); + + /** + * QB Cache ORDER BY data + * + * @var array + */ protected $qb_cache_orderby = array(); + + /** + * QB Cache data sets + * + * @var array + */ protected $qb_cache_set = array(); + /** + * QB No Escape data + * + * @var array + */ protected $qb_no_escape = array(); + + /** + * QB Cache No Escape data + * + * @var array + */ protected $qb_cache_no_escape = array(); + // -------------------------------------------------------------------- + /** * Select * @@ -184,15 +354,16 @@ abstract class CI_DB_query_builder extends CI_DB_driver { // -------------------------------------------------------------------- /** - * Processing Function for the four functions above: + * SELECT [MAX|MIN|AVG|SUM]() * - * select_max() - * select_min() - * select_avg() - * select_sum() + * @used-by select_max() + * @used-by select_min() + * @used-by select_avg() + * @used-by select_sum() * - * @param string the field - * @param string an alias + * @param string $select Field name + * @param string $alias + * @param string $type * @return object */ protected function _max_min_avg_sum($select = '', $alias = '', $type = 'MAX') @@ -233,7 +404,7 @@ abstract class CI_DB_query_builder extends CI_DB_driver { /** * Determines the alias name based on the table * - * @param string + * @param string $item * @return string */ protected function _create_alias_from_table($item) @@ -254,7 +425,7 @@ abstract class CI_DB_query_builder extends CI_DB_driver { * * Sets a flag which tells the query string compiler to add DISTINCT * - * @param bool + * @param bool $val * @return object */ public function distinct($val = TRUE) @@ -270,7 +441,7 @@ abstract class CI_DB_query_builder extends CI_DB_driver { * * Generates the FROM portion of the query * - * @param mixed can be a string or array + * @param mixed $from can be a string or array * @return object */ public function from($from) @@ -317,7 +488,7 @@ abstract class CI_DB_query_builder extends CI_DB_driver { // -------------------------------------------------------------------- /** - * Join + * JOIN * * Generates the JOIN portion of the query * @@ -405,10 +576,10 @@ abstract class CI_DB_query_builder extends CI_DB_driver { // -------------------------------------------------------------------- /** - * Where + * WHERE * - * Generates the WHERE portion of the query. Separates - * multiple calls with AND + * Generates the WHERE portion of the query. + * Separates multiple calls with 'AND'. * * @param mixed * @param mixed @@ -417,16 +588,16 @@ abstract class CI_DB_query_builder extends CI_DB_driver { */ public function where($key, $value = NULL, $escape = NULL) { - return $this->_where($key, $value, 'AND ', $escape); + return $this->_wh('qb_where', $key, $value, 'AND ', $escape); } // -------------------------------------------------------------------- /** - * OR Where + * OR WHERE * - * Generates the WHERE portion of the query. Separates - * multiple calls with OR + * Generates the WHERE portion of the query. + * Separates multiple calls with 'OR'. * * @param mixed * @param mixed @@ -435,24 +606,30 @@ abstract class CI_DB_query_builder extends CI_DB_driver { */ public function or_where($key, $value = NULL, $escape = NULL) { - return $this->_where($key, $value, 'OR ', $escape); + return $this->_wh('qb_where', $key, $value, 'OR ', $escape); } // -------------------------------------------------------------------- /** - * Where + * WHERE, HAVING * - * Called by where() or or_where() + * @used-by where() + * @used-by or_where() + * @used-by having() + * @used-by or_having() * - * @param mixed - * @param mixed - * @param string - * @param mixed + * @param string $qb_key 'qb_where' or 'qb_having' + * @param mixed $key + * @param mixed $value + * @param string $type + * @param bool $escape * @return object */ - protected function _where($key, $value = NULL, $type = 'AND ', $escape = NULL) + protected function _wh($qb_key, $key, $value = NULL, $type = 'AND ', $escape = NULL) { + $qb_cache_key = ($qb_key === 'qb_having') ? 'qb_cache_having' : 'qb_cache_where'; + if ( ! is_array($key)) { $key = array($key => $value); @@ -463,17 +640,10 @@ abstract class CI_DB_query_builder extends CI_DB_driver { foreach ($key as $k => $v) { - $prefix = (count($this->qb_where) === 0 && count($this->qb_cache_where) === 0) + $prefix = (count($this->$qb_key) === 0 && count($this->$qb_cache_key) === 0) ? $this->_group_get_type('') : $this->_group_get_type($type); - if ($escape === TRUE) - { - $k = (($op = $this->_get_operator($k)) !== FALSE) - ? $this->escape_identifiers(trim(substr($k, 0, strpos($k, $op)))).' '.strstr($k, $op) - : $this->escape_identifiers(trim($k)); - } - if (is_null($v) && ! $this->_has_operator($k)) { // value appears not to have been set, assign the test to IS NULL @@ -484,7 +654,7 @@ abstract class CI_DB_query_builder extends CI_DB_driver { { if ($escape === TRUE) { - $v = ' '.$this->escape($v); + $v = ' '.(is_int($v) ? $v : $this->escape($v)); } if ( ! $this->_has_operator($k)) @@ -493,11 +663,11 @@ abstract class CI_DB_query_builder extends CI_DB_driver { } } - $this->qb_where[] = $prefix.$k.$v; + $this->{$qb_key}[] = array('condition' => $prefix.$k.$v, 'escape' => $escape); if ($this->qb_caching === TRUE) { - $this->qb_cache_where[] = $prefix.$k.$v; - $this->qb_cache_exists[] = 'where'; + $this->{$qb_cache_key}[] = array('condition' => $prefix.$k.$v, 'escape' => $escape); + $this->qb_cache_exists[] = substr($qb_key, 3); } } @@ -508,13 +678,14 @@ abstract class CI_DB_query_builder extends CI_DB_driver { // -------------------------------------------------------------------- /** - * Where_in + * WHERE IN * - * Generates a WHERE field IN ('item', 'item') SQL query joined with - * AND if appropriate + * Generates a WHERE field IN('item', 'item') SQL query, + * joined with 'AND' if appropriate. * - * @param string The field to search - * @param array The values searched on + * @param string $key The field to search + * @param array $values The values searched on + * @param bool $escape * @return object */ public function where_in($key = NULL, $values = NULL, $escape = NULL) @@ -525,13 +696,14 @@ abstract class CI_DB_query_builder extends CI_DB_driver { // -------------------------------------------------------------------- /** - * Where_in_or + * OR WHERE IN * - * Generates a WHERE field IN ('item', 'item') SQL query joined with - * OR if appropriate + * Generates a WHERE field IN('item', 'item') SQL query, + * joined with 'OR' if appropriate. * - * @param string The field to search - * @param array The values searched on + * @param string $key The field to search + * @param array $values The values searched on + * @param bool $escape * @return object */ public function or_where_in($key = NULL, $values = NULL, $escape = NULL) @@ -542,13 +714,14 @@ abstract class CI_DB_query_builder extends CI_DB_driver { // -------------------------------------------------------------------- /** - * Where_not_in + * WHERE NOT IN * - * Generates a WHERE field NOT IN ('item', 'item') SQL query joined - * with AND if appropriate + * Generates a WHERE field NOT IN('item', 'item') SQL query, + * joined with 'AND' if appropriate. * - * @param string The field to search - * @param array The values searched on + * @param string $key The field to search + * @param array $values The values searched on + * @param bool $escape * @return object */ public function where_not_in($key = NULL, $values = NULL, $escape = NULL) @@ -559,13 +732,14 @@ abstract class CI_DB_query_builder extends CI_DB_driver { // -------------------------------------------------------------------- /** - * Where_not_in_or + * OR WHERE NOT IN * - * Generates a WHERE field NOT IN ('item', 'item') SQL query joined - * with OR if appropriate + * Generates a WHERE field NOT IN('item', 'item') SQL query, + * joined with 'OR' if appropriate. * - * @param string The field to search - * @param array The values searched on + * @param string $key The field to search + * @param array $values The values searched on + * @param bool $escape * @return object */ public function or_where_not_in($key = NULL, $values = NULL, $escape = NULL) @@ -576,14 +750,18 @@ abstract class CI_DB_query_builder extends CI_DB_driver { // -------------------------------------------------------------------- /** - * Where_in + * Internal WHERE IN * - * Called by where_in, where_in_or, where_not_in, where_not_in_or + * @used-by where_in() + * @used-by or_where_in() + * @used-by where_not_in() + * @used-by or_where_not_in() * - * @param string The field to search - * @param array The values searched on - * @param bool If the statement would be IN or NOT IN - * @param string + * @param string $key The field to search + * @param array $values The values searched on + * @param bool $not If the statement would be IN or NOT IN + * @param string $type + * @param bool $escape * @return object */ protected function _where_in($key = NULL, $values = NULL, $not = FALSE, $type = 'AND ', $escape = NULL) @@ -602,153 +780,166 @@ abstract class CI_DB_query_builder extends CI_DB_driver { $not = ($not) ? ' NOT' : ''; + $where_in = array(); foreach ($values as $value) { - $this->qb_wherein[] = $this->escape($value); - } - - if ($escape === TRUE) - { - $key = $this->escape_identifiers(trim($key)); + $where_in[] = $this->escape($value); } $prefix = (count($this->qb_where) === 0) ? $this->_group_get_type('') : $this->_group_get_type($type); - $this->qb_where[] = $where_in = $prefix.$key.$not.' IN ('.implode(', ', $this->qb_wherein).') '; + $where_in = array( + 'condition' => $prefix.$key.$not.' IN('.implode(', ', $where_in).')', + 'escape' => $escape + ); + $this->qb_where[] = $where_in; if ($this->qb_caching === TRUE) { $this->qb_cache_where[] = $where_in; $this->qb_cache_exists[] = 'where'; } - // reset the array for multiple calls - $this->qb_wherein = array(); return $this; } // -------------------------------------------------------------------- /** - * Like + * LIKE * - * Generates a %LIKE% portion of the query. Separates - * multiple calls with AND + * Generates a %LIKE% portion of the query. + * Separates multiple calls with 'AND'. * - * @param mixed - * @param mixed + * @param mixed $field + * @param string $match + * @param string $side + * @param bool $escape * @return object */ - public function like($field, $match = '', $side = 'both') + public function like($field, $match = '', $side = 'both', $escape = NULL) { - return $this->_like($field, $match, 'AND ', $side); + return $this->_like($field, $match, 'AND ', $side, '', $escape); } // -------------------------------------------------------------------- /** - * Not Like + * NOT LIKE * - * Generates a NOT LIKE portion of the query. Separates - * multiple calls with AND + * Generates a NOT LIKE portion of the query. + * Separates multiple calls with 'AND'. * - * @param mixed - * @param mixed + * @param mixed $field + * @param string $match + * @param string $side + * @param bool $escape * @return object */ - public function not_like($field, $match = '', $side = 'both') + public function not_like($field, $match = '', $side = 'both', $escape = NULL) { - return $this->_like($field, $match, 'AND ', $side, 'NOT'); + return $this->_like($field, $match, 'AND ', $side, 'NOT', $escape); } // -------------------------------------------------------------------- /** - * OR Like + * OR LIKE * - * Generates a %LIKE% portion of the query. Separates - * multiple calls with OR + * Generates a %LIKE% portion of the query. + * Separates multiple calls with 'OR'. * - * @param mixed - * @param mixed + * @param mixed $field + * @param string $match + * @param string $side + * @param bool $escape * @return object */ - public function or_like($field, $match = '', $side = 'both') + public function or_like($field, $match = '', $side = 'both', $escape = NULL) { - return $this->_like($field, $match, 'OR ', $side); + return $this->_like($field, $match, 'OR ', $side, '', $escape); } // -------------------------------------------------------------------- /** - * OR Not Like + * OR NOT LIKE * - * Generates a NOT LIKE portion of the query. Separates - * multiple calls with OR + * Generates a NOT LIKE portion of the query. + * Separates multiple calls with 'OR'. * - * @param mixed - * @param mixed + * @param mixed $field + * @param string $match + * @param string $side + * @param bool $escape * @return object */ - public function or_not_like($field, $match = '', $side = 'both') + public function or_not_like($field, $match = '', $side = 'both', $escape = NULL) { - return $this->_like($field, $match, 'OR ', $side, 'NOT'); + return $this->_like($field, $match, 'OR ', $side, 'NOT', $escape); } // -------------------------------------------------------------------- /** - * Like + * Internal LIKE * - * Called by like() or orlike() + * @used-by like() + * @used-by or_like() + * @used-by not_like() + * @used-by or_not_like() * - * @param mixed - * @param mixed - * @param string + * @param mixed $field + * @param string $match + * @param string $type + * @param string $side + * @param string $not + * @param bool $escape * @return object */ - protected function _like($field, $match = '', $type = 'AND ', $side = 'both', $not = '') + protected function _like($field, $match = '', $type = 'AND ', $side = 'both', $not = '', $escape = NULL) { if ( ! is_array($field)) { $field = array($field => $match); } + is_bool($escape) OR $escape = $this->_protect_identifiers; + $prefix = (count($this->qb_where) === 0 && count($this->qb_cache_where) === 0) + ? $this->_group_get_type('') : $this->_group_get_type($type); + foreach ($field as $k => $v) { - $k = $this->protect_identifiers($k); - $prefix = (count($this->qb_like) === 0) ? $this->_group_get_type('') : $this->_group_get_type($type); $v = $this->escape_like_str($v); if ($side === 'none') { - $like_statement = "{$prefix} $k $not LIKE '{$v}'"; + $like_statement = "{$prefix} {$k} {$not} LIKE '{$v}'"; } elseif ($side === 'before') { - $like_statement = "{$prefix} $k $not LIKE '%{$v}'"; + $like_statement = "{$prefix} {$k} {$not} LIKE '%{$v}'"; } elseif ($side === 'after') { - $like_statement = "{$prefix} $k $not LIKE '{$v}%'"; + $like_statement = "{$prefix} {$k} {$not} LIKE '{$v}%'"; } else { - $like_statement = "{$prefix} $k $not LIKE '%{$v}%'"; + $like_statement = "{$prefix} {$k} {$not} LIKE '%{$v}%'"; } // some platforms require an escape sequence definition for LIKE wildcards if ($this->_like_escape_str !== '') { - $like_statement = $like_statement.sprintf($this->_like_escape_str, $this->_like_escape_chr); + $like_statement .= sprintf($this->_like_escape_str, $this->_like_escape_chr); } - $this->qb_like[] = $like_statement; + $this->qb_where[] = array('condition' => $like_statement, 'escape' => $escape); if ($this->qb_caching === TRUE) { - $this->qb_cache_like[] = $like_statement; - $this->qb_cache_exists[] = 'like'; + $this->qb_cache_where[] = $like_statement; + $this->qb_cache_exists[] = 'where'; } - } return $this; @@ -759,8 +950,8 @@ abstract class CI_DB_query_builder extends CI_DB_driver { /** * Starts a query group. * - * @param string (Internal use only) - * @param string (Internal use only) + * @param string $not (Internal use only) + * @param string $type (Internal use only) * @return object */ public function group_start($not = '', $type = 'AND ') @@ -769,11 +960,15 @@ abstract class CI_DB_query_builder extends CI_DB_driver { $this->qb_where_group_started = TRUE; $prefix = (count($this->qb_where) === 0 && count($this->qb_cache_where) === 0) ? '' : $type; - $this->qb_where[] = $value = $prefix.$not.str_repeat(' ', ++$this->qb_where_group_count).' ('; + $where = array( + 'condition' => $prefix.$not.str_repeat(' ', ++$this->qb_where_group_count).' (', + 'escape' => FALSE + ); + $this->qb_where[] = $where; if ($this->qb_caching) { - $this->qb_cache_where[] = $value; + $this->qb_cache_where[] = $where; } return $this; @@ -825,11 +1020,15 @@ abstract class CI_DB_query_builder extends CI_DB_driver { public function group_end() { $this->qb_where_group_started = FALSE; - $this->qb_where[] = $value = str_repeat(' ', $this->qb_where_group_count--) . ')'; + $where = array( + 'condition' => str_repeat(' ', $this->qb_where_group_count--).')', + 'escape' => FALSE + ); + $this->qb_where[] = $where; if ($this->qb_caching) { - $this->qb_cache_where[] = $value; + $this->qb_cache_where[] = $where; } return $this; @@ -840,9 +1039,12 @@ abstract class CI_DB_query_builder extends CI_DB_driver { /** * Group_get_type * - * Called by group_start(), _like(), _where() and _where_in() + * @used-by group_start() + * @used-by _like() + * @used-by _wh() + * @used-by _where_in() * - * @param string + * @param string $type * @return string */ protected function _group_get_type($type) @@ -861,14 +1063,19 @@ abstract class CI_DB_query_builder extends CI_DB_driver { /** * GROUP BY * - * @param string + * @param string $by + * @param bool $escape * @return object */ - public function group_by($by) + public function group_by($by, $escape = NULL) { + is_bool($escape) OR $escape = $this->_protect_identifiers; + if (is_string($by)) { - $by = explode(',', $by); + $by = ($escape === TRUE) + ? explode(',', $by) + : array($by); } foreach ($by as $val) @@ -877,8 +1084,9 @@ abstract class CI_DB_query_builder extends CI_DB_driver { if ($val !== '') { - $this->qb_groupby[] = $val = $this->protect_identifiers($val); + $val = array('field' => $val, 'escape' => $escape); + $this->qb_groupby[] = $val; if ($this->qb_caching === TRUE) { $this->qb_cache_groupby[] = $val; @@ -893,142 +1101,87 @@ abstract class CI_DB_query_builder extends CI_DB_driver { // -------------------------------------------------------------------- /** - * Sets the HAVING value + * HAVING * - * Separates multiple calls with AND + * Separates multiple calls with 'AND'. * - * @param string - * @param string - * @param bool + * @param string $key + * @param string $value + * @param bool $escape * @return object */ - public function having($key, $value = '', $escape = NULL) + public function having($key, $value = NULL, $escape = NULL) { - return $this->_having($key, $value, 'AND ', $escape); + return $this->_wh('qb_having', $key, $value, 'AND ', $escape); } // -------------------------------------------------------------------- /** - * Sets the OR HAVING value + * OR HAVING * - * Separates multiple calls with OR + * Separates multiple calls with 'OR'. * - * @param string - * @param string - * @param bool + * @param string $key + * @param string $value + * @param bool $escape * @return object */ - public function or_having($key, $value = '', $escape = NULL) + public function or_having($key, $value = NULL, $escape = NULL) { - return $this->_having($key, $value, 'OR ', $escape); + return $this->_wh('qb_having', $key, $value, 'OR ', $escape); } // -------------------------------------------------------------------- /** - * Sets the HAVING values + * ORDER BY * - * Called by having() or or_having() - * - * @param string - * @param string - * @param string - * @param bool + * @param string $orderby + * @param string $direction ASC or DESC + * @param bool $escape * @return object */ - protected function _having($key, $value = '', $type = 'AND ', $escape = NULL) + public function order_by($orderby, $direction = '', $escape = NULL) { - if ( ! is_array($key)) - { - $key = array($key => $value); - } - - is_bool($escape) OR $escape = $this->_protect_identifiers; + $direction = trim($direction); - foreach ($key as $k => $v) + if (strtolower($direction) === 'random' OR $orderby === $this->_random_keyword) { - $prefix = (count($this->qb_having) === 0) ? '' : $type; - - $k = $this->_has_operator($k) - ? $this->protect_identifiers(substr($k, 0, strpos(rtrim($k), ' ')), FALSE, $escape).strchr(rtrim($k), ' ') - : $this->protect_identifiers($k, FALSE, $escape); - - if ( ! $this->_has_operator($k)) - { - $k .= ' = '; - } - - if ($v !== '') - { - $v = ' '.$this->escape($v); - } - - $this->qb_having[] = $prefix.$k.$v; - if ($this->qb_caching === TRUE) - { - $this->qb_cache_having[] = $prefix.$k.$v; - $this->qb_cache_exists[] = 'having'; - } + // Random ordered results don't need a field name + $orderby = $this->_random_keyword; + $direction = ''; } - - return $this; - } - - // -------------------------------------------------------------------- - - /** - * Sets the ORDER BY value - * - * @param string - * @param string direction: asc or desc - * @param bool enable field name escaping - * @return object - */ - public function order_by($orderby, $direction = '', $escape = NULL) - { - if (strtolower($direction) === 'random') + elseif (empty($orderby)) { - $orderby = ''; // Random results want or don't need a field name - $direction = $this->_random_keyword; + return $this; } - elseif (trim($direction) !== '') + elseif ($direction !== '') { - $direction = in_array(strtoupper(trim($direction)), array('ASC', 'DESC'), TRUE) ? ' '.$direction : ' ASC'; + $direction = in_array(strtoupper(trim($direction)), array('ASC', 'DESC'), TRUE) ? ' '.$direction : ''; } is_bool($escape) OR $escape = $this->_protect_identifiers; - if ($escape === TRUE && strpos($orderby, ',') !== FALSE) + if ($escape === FALSE) { - $temp = array(); - foreach (explode(',', $orderby) as $part) - { - $part = trim($part); - if ( ! in_array($part, $this->qb_aliased_tables)) - { - $part = preg_match('/^(.+)\s+(ASC|DESC)$/i', $part, $matches) - ? $this->protect_identifiers(rtrim($matches[1])).' '.$matches[2] - : $this->protect_identifiers($part); - } - - $temp[] = $part; - } - - $orderby = implode(', ', $temp); + $qb_orderby[] = array('field' => $orderby, 'direction' => $direction, 'escape' => FALSE); } - elseif ($direction !== $this->_random_keyword && $escape === TRUE) + else { - $orderby = preg_match('/^(.+)\s+(ASC|DESC)$/i', $orderby, $matches) - ? $this->protect_identifiers(rtrim($matches[1])).' '.$matches[2] - : $this->protect_identifiers($orderby); + $qb_orderby = array(); + foreach (explode(',', $orderby) as $field) + { + $qb_orderby[] = ($direction === '' && preg_match('/\s+(ASC|DESC)$/i', rtrim($field), $match, PREG_OFFSET_CAPTURE)) + ? array('field' => ltrim(substr($field, 0, $match[0][1])), 'direction' => ' '.$match[1][0], 'escape' => TRUE) + : array('field' => trim($field), 'direction' => $direction, 'escape' => TRUE); + } } - $this->qb_orderby[] = $orderby_statement = $orderby.$direction; - + $this->qb_orderby = array_merge($this->qb_orderby, $qb_orderby); if ($this->qb_caching === TRUE) { - $this->qb_cache_orderby[] = $orderby_statement; + $this->qb_cache_orderby = array_merge($this->qb_cache_orderby, $qb_orderby); $this->qb_cache_exists[] = 'orderby'; } @@ -1038,13 +1191,13 @@ abstract class CI_DB_query_builder extends CI_DB_driver { // -------------------------------------------------------------------- /** - * Sets the LIMIT value + * LIMIT * - * @param int the limit value - * @param int the offset value + * @param int $value LIMIT value + * @param int $offset OFFSET value * @return object */ - public function limit($value, $offset = NULL) + public function limit($value, $offset = FALSE) { is_null($value) OR $this->qb_limit = (int) $value; empty($offset) OR $this->qb_offset = (int) $offset; @@ -1057,7 +1210,7 @@ abstract class CI_DB_query_builder extends CI_DB_driver { /** * Sets the OFFSET value * - * @param int the offset value + * @param int $offset OFFSET value * @return object */ public function offset($offset) @@ -1069,18 +1222,16 @@ abstract class CI_DB_query_builder extends CI_DB_driver { // -------------------------------------------------------------------- /** - * Limit string + * LIMIT string * - * Generates a platform-specific LIMIT clause + * Generates a platform-specific LIMIT clause. * - * @param string the sql query string - * @param int the number of rows to limit the query to - * @param int the offset value + * @param string $sql SQL Query * @return string */ - protected function _limit($sql, $limit, $offset) + protected function _limit($sql) { - return $sql.' LIMIT '.($offset ? $offset.', ' : '').$limit; + return $sql.' LIMIT '.($this->qb_offset ? $this->qb_offset.', ' : '').$this->qb_limit; } // -------------------------------------------------------------------- @@ -1194,7 +1345,9 @@ abstract class CI_DB_query_builder extends CI_DB_driver { $this->from($table); } - $result = $this->query($this->_compile_select($this->_count_string.$this->protect_identifiers('numrows'))); + $result = ($this->qb_distinct === TRUE) + ? $this->query($this->_count_string.$this->protect_identifiers('numrows')."\nFROM (\n".$this->_compile_select()."\n) CI_count_all_results") + : $this->query($this->_compile_select($this->_count_string.$this->protect_identifiers('numrows'))); $this->_reset_select(); if ($result->num_rows() === 0) @@ -1213,9 +1366,10 @@ abstract class CI_DB_query_builder extends CI_DB_driver { * * Allows the where clause, limit and offset to be added directly * - * @param string the where clause - * @param string the limit clause - * @param string the offset clause + * @param string $table + * @param string $where + * @param int $limit + * @param int $offset * @return object */ public function get_where($table = '', $where = NULL, $limit = NULL, $offset = NULL) @@ -1247,9 +1401,9 @@ abstract class CI_DB_query_builder extends CI_DB_driver { * * Compiles batch insert strings and runs the queries * - * @param string the table to retrieve the results from - * @param array an associative array of insert values - * @return object + * @param string $table Table to insert into + * @param array $set An associative array of insert values + * @return int Number of rows inserted or FALSE on failure */ public function insert_batch($table = '', $set = NULL) { @@ -1260,12 +1414,8 @@ abstract class CI_DB_query_builder extends CI_DB_driver { if (count($this->qb_set) === 0) { - if ($this->db_debug) - { - // No valid data array. Folds in cases where keys and values did not match up - return $this->display_error('db_must_use_set'); - } - return FALSE; + // No valid data array. Folds in cases where keys and values did not match up + return ($this->db_debug) ? $this->display_error('db_must_use_set') : FALSE; } if ($table === '') @@ -1279,13 +1429,15 @@ abstract class CI_DB_query_builder extends CI_DB_driver { } // Batch this baby + $affected_rows = 0; for ($i = 0, $total = count($this->qb_set); $i < $total; $i += 100) { $this->query($this->_insert_batch($this->protect_identifiers($table, TRUE, NULL, FALSE), $this->qb_keys, array_slice($this->qb_set, $i, 100))); + $affected_rows += $this->affected_rows(); } $this->_reset_write(); - return TRUE; + return $affected_rows; } // -------------------------------------------------------------------- @@ -1522,19 +1674,18 @@ abstract class CI_DB_query_builder extends CI_DB_driver { // -------------------------------------------------------------------- /** - * From Tables + * FROM tables + * + * Groups tables in FROM clauses if needed, so there is no confusion + * about operator precedence. * - * This public function implicitly groups FROM tables so there is no confusion - * about operator precedence in harmony with SQL standards + * Note: This is only used (and overriden) by MySQL and CUBRID. * - * @param array - * @return string + * @return string */ - protected function _from_tables($tables) + protected function _from_tables() { - is_array($tables) OR $tables = array($tables); - - return (count($tables) === 1) ? $tables[0] : '('.implode(', ', $tables).')'; + return implode(', ', $this->qb_from); } // -------------------------------------------------------------------- @@ -1558,7 +1709,7 @@ abstract class CI_DB_query_builder extends CI_DB_driver { return FALSE; } - $sql = $this->_update($this->protect_identifiers($this->qb_from[0], TRUE, NULL, FALSE), $this->qb_set, $this->qb_where, $this->qb_orderby, $this->qb_limit); + $sql = $this->_update($this->protect_identifiers($this->qb_from[0], TRUE, NULL, FALSE), $this->qb_set); if ($reset === TRUE) { @@ -1571,13 +1722,14 @@ abstract class CI_DB_query_builder extends CI_DB_driver { // -------------------------------------------------------------------- /** - * Update + * UPDATE * - * Compiles an update string and runs the query + * Compiles an update string and runs the query. * - * @param string the table to retrieve the results from - * @param array an associative array of update values - * @param mixed the where clause + * @param string $table + * @param array $set An associative array of update values + * @param mixed $where + * @param int $limit * @return object */ public function update($table = '', $set = NULL, $where = NULL, $limit = NULL) @@ -1605,8 +1757,7 @@ abstract class CI_DB_query_builder extends CI_DB_driver { $this->limit($limit); } - $sql = $this->_update($this->protect_identifiers($this->qb_from[0], TRUE, NULL, FALSE), $this->qb_set, $this->qb_where, $this->qb_orderby, $this->qb_limit, $this->qb_like); - + $sql = $this->_update($this->protect_identifiers($this->qb_from[0], TRUE, NULL, FALSE), $this->qb_set); $this->_reset_write(); return $this->query($sql); } @@ -1652,7 +1803,7 @@ abstract class CI_DB_query_builder extends CI_DB_driver { * @param string the table to retrieve the results from * @param array an associative array of update values * @param string the where key - * @return bool + * @return int number of rows affected or FALSE on failure */ public function update_batch($table = '', $set = NULL, $index = NULL) { @@ -1685,13 +1836,15 @@ abstract class CI_DB_query_builder extends CI_DB_driver { } // Batch this baby + $affected_rows = 0; for ($i = 0, $total = count($this->qb_set); $i < $total; $i += 100) { - $this->query($this->_update_batch($this->protect_identifiers($table, TRUE, NULL, FALSE), array_slice($this->qb_set, $i, 100), $this->protect_identifiers($index), $this->qb_where)); + $this->query($this->_update_batch($this->protect_identifiers($table, TRUE, NULL, FALSE), array_slice($this->qb_set, $i, 100), $this->protect_identifiers($index))); + $affected_rows += $this->affected_rows(); } $this->_reset_write(); - return TRUE; + return $affected_rows; } // -------------------------------------------------------------------- @@ -1852,7 +2005,7 @@ abstract class CI_DB_query_builder extends CI_DB_driver { * @param mixed the where clause * @param mixed the limit clause * @param bool - * @return object + * @return mixed */ public function delete($table = '', $where = '', $limit = NULL, $reset_data = TRUE) { @@ -1872,10 +2025,8 @@ abstract class CI_DB_query_builder extends CI_DB_driver { { foreach ($table as $single_table) { - $this->delete($single_table, $where, $limit, FALSE); + $this->delete($single_table, $where, $limit, $reset_data); } - - $this->_reset_write(); return; } else @@ -1893,12 +2044,12 @@ abstract class CI_DB_query_builder extends CI_DB_driver { $this->limit($limit); } - if (count($this->qb_where) === 0 && count($this->qb_wherein) === 0 && count($this->qb_like) === 0) + if (count($this->qb_where) === 0) { return ($this->db_debug) ? $this->display_error('db_del_must_use_where') : FALSE; } - $sql = $this->_delete($table, $this->qb_where, $this->qb_like, $this->qb_limit); + $sql = $this->_delete($table); if ($reset_data) { $this->_reset_write(); @@ -1915,21 +2066,12 @@ abstract class CI_DB_query_builder extends CI_DB_driver { * Generates a platform-specific delete string from the supplied data * * @param string the table name - * @param array the where clause - * @param array the like clause - * @param string the limit clause * @return string */ - protected function _delete($table, $where = array(), $like = array(), $limit = FALSE) + protected function _delete($table) { - $conditions = array(); - - empty($where) OR $conditions[] = implode(' ', $where); - empty($like) OR $conditions[] = implode(' ', $like); - - return 'DELETE FROM '.$table - .(count($conditions) > 0 ? ' WHERE '.implode(' AND ', $conditions) : '') - .($limit ? ' LIMIT '.(int) $limit : ''); + return 'DELETE FROM '.$table.$this->_compile_wh('qb_where') + .($this->qb_limit ? ' LIMIT '.$this->qb_limit : ''); } // -------------------------------------------------------------------- @@ -2018,8 +2160,9 @@ abstract class CI_DB_query_builder extends CI_DB_driver { * Compile the SELECT statement * * Generates a query string based on which functions were used. - * Should not be called directly. The get() function calls it. + * Should not be called directly. * + * @param bool $select_override * @return string */ protected function _compile_select($select_override = FALSE) @@ -2058,7 +2201,7 @@ abstract class CI_DB_query_builder extends CI_DB_driver { // Write the "FROM" portion of the query if (count($this->qb_from) > 0) { - $sql .= "\nFROM ".$this->_from_tables($this->qb_from); + $sql .= "\nFROM ".$this->_from_tables(); } // Write the "JOIN" portion of the query @@ -2067,50 +2210,156 @@ abstract class CI_DB_query_builder extends CI_DB_driver { $sql .= "\n".implode("\n", $this->qb_join); } - // Write the "WHERE" portion of the query - if (count($this->qb_where) > 0 OR count($this->qb_like) > 0) + $sql .= $this->_compile_wh('qb_where') + .$this->_compile_group_by() + .$this->_compile_wh('qb_having') + .$this->_compile_order_by(); // ORDER BY + + // LIMIT + if ($this->qb_limit) { - $sql .= "\nWHERE "; + return $this->_limit($sql."\n"); } - $sql .= implode("\n", $this->qb_where); + return $sql; + } - // Write the "LIKE" portion of the query - if (count($this->qb_like) > 0) + // -------------------------------------------------------------------- + + /** + * Compile WHERE, HAVING statements + * + * Escapes identifiers in WHERE and HAVING statements at execution time. + * + * Required so that aliases are tracked properly, regardless of wether + * where(), or_where(), having(), or_having are called prior to from(), + * join() and dbprefix is added only if needed. + * + * @param string $qb_key 'qb_where' or 'qb_having' + * @return string SQL statement + */ + protected function _compile_wh($qb_key) + { + if (count($this->$qb_key) > 0) { - if (count($this->qb_where) > 0) + for ($i = 0, $c = count($this->$qb_key); $i < $c; $i++) { - $sql .= "\nAND "; + if ($this->{$qb_key}[$i]['escape'] === FALSE) + { + $this->{$qb_key}[$i] = $this->{$qb_key}[$i]['condition']; + continue; + } + + // Split multiple conditions + $conditions = preg_split( + '/(\s*AND\s+|\s*OR\s+)/i', + $this->{$qb_key}[$i]['condition'], + -1, + PREG_SPLIT_DELIM_CAPTURE | PREG_SPLIT_NO_EMPTY + ); + + for ($ci = 0, $cc = count($conditions); $ci < $cc; $ci++) + { + if (($op = $this->_get_operator($conditions[$ci])) === FALSE + OR ! preg_match('/^(\(?)(.*)('.preg_quote($op, '/').')\s*(.*(?<!\)))?(\)?)$/i', $conditions[$ci], $matches)) + { + continue; + } + + // $matches = array( + // 0 => '(test <= foo)', /* the whole thing */ + // 1 => '(', /* optional */ + // 2 => 'test', /* the field name */ + // 3 => ' <= ', /* $op */ + // 4 => 'foo', /* optional, if $op is e.g. 'IS NULL' */ + // 5 => ')' /* optional */ + // ); + + if ( ! empty($matches[4])) + { + $this->_is_literal($matches[4]) OR $matches[4] = $this->protect_identifiers(trim($matches[4])); + $matches[4] = ' '.$matches[4]; + } + + $conditions[$ci] = $matches[1].$this->protect_identifiers(trim($matches[2])) + .' '.trim($matches[3]).$matches[4].$matches[5]; + } + + $this->{$qb_key}[$i] = implode('', $conditions); } - $sql .= implode("\n", $this->qb_like); + return ($qb_key === 'qb_having' ? "\nHAVING " : "\nWHERE ") + .implode("\n", $this->$qb_key); } - // Write the "GROUP BY" portion of the query + return ''; + } + + // -------------------------------------------------------------------- + + /** + * Compile GROUP BY + * + * Escapes identifiers in GROUP BY statements at execution time. + * + * Required so that aliases are tracked properly, regardless of wether + * group_by() is called prior to from(), join() and dbprefix is added + * only if needed. + * + * @return string SQL statement + */ + protected function _compile_group_by() + { if (count($this->qb_groupby) > 0) { - $sql .= "\nGROUP BY ".implode(', ', $this->qb_groupby); - } + for ($i = 0, $c = count($this->qb_groupby); $i < $c; $i++) + { + $this->qb_groupby[$i] = ($this->qb_groupby[$i]['escape'] === FALSE OR $this->_is_literal($this->qb_groupby[$i]['field'])) + ? $this->qb_groupby[$i]['field'] + : $this->protect_identifiers($this->qb_groupby[$i]['field']); + } - // Write the "HAVING" portion of the query - if (count($this->qb_having) > 0) - { - $sql .= "\nHAVING ".implode("\n", $this->qb_having); + return "\nGROUP BY ".implode(', ', $this->qb_groupby); } - // Write the "ORDER BY" portion of the query - if (count($this->qb_orderby) > 0) + return ''; + } + + // -------------------------------------------------------------------- + + /** + * Compile ORDER BY + * + * Escapes identifiers in ORDER BY statements at execution time. + * + * Required so that aliases are tracked properly, regardless of wether + * order_by() is called prior to from(), join() and dbprefix is added + * only if needed. + * + * @return string SQL statement + */ + protected function _compile_order_by() + { + if (is_array($this->qb_orderby) && count($this->qb_orderby) > 0) { - $sql .= "\nORDER BY ".implode(', ', $this->qb_orderby); - } + for ($i = 0, $c = count($this->qb_orderby); $i < $c; $i++) + { + if ($this->qb_orderby[$i]['escape'] !== FALSE && ! $this->_is_literal($this->qb_orderby[$i]['field'])) + { + $this->qb_orderby[$i]['field'] = $this->protect_identifiers($this->qb_orderby[$i]['field']); + } + + $this->qb_orderby[$i] = $this->qb_orderby[$i]['field'].$this->qb_orderby[$i]['direction']; + } - // Write the "LIMIT" portion of the query - if (is_numeric($this->qb_limit)) + return $this->qb_orderby = "\nORDER BY ".implode(', ', $this->qb_orderby); + } + elseif (is_string($this->qb_orderby)) { - return $this->_limit($sql."\n", $this->qb_limit, $this->qb_offset); + return $this->qb_orderby; } - return $sql; + return ''; } // -------------------------------------------------------------------- @@ -2224,7 +2473,6 @@ abstract class CI_DB_query_builder extends CI_DB_driver { 'qb_cache_from' => array(), 'qb_cache_join' => array(), 'qb_cache_where' => array(), - 'qb_cache_like' => array(), 'qb_cache_groupby' => array(), 'qb_cache_having' => array(), 'qb_cache_orderby' => array(), @@ -2277,6 +2525,36 @@ abstract class CI_DB_query_builder extends CI_DB_driver { // -------------------------------------------------------------------- /** + * Is literal + * + * Determines if a string represents a literal value or a field name + * + * @param string + * @return bool + */ + protected function _is_literal($str) + { + $str = trim($str); + + if (empty($str)) + { + return TRUE; + } + + static $_str; + + if (empty($_str)) + { + $_str = ($this->_escape_char !== '"') + ? array('"', "'") : array("'"); + } + + return (ctype_digit($str) OR in_array($str[0], $_str, TRUE)); + } + + // -------------------------------------------------------------------- + + /** * Reset Query Builder values. * * Publicly-visible method to reset the QB values. @@ -2301,10 +2579,7 @@ abstract class CI_DB_query_builder extends CI_DB_driver { { foreach ($qb_reset_items as $item => $default_value) { - if ( ! in_array($item, $this->qb_store_array)) - { - $this->$item = $default_value; - } + $this->$item = $default_value; } } @@ -2322,11 +2597,9 @@ abstract class CI_DB_query_builder extends CI_DB_driver { 'qb_from' => array(), 'qb_join' => array(), 'qb_where' => array(), - 'qb_like' => array(), 'qb_groupby' => array(), 'qb_having' => array(), 'qb_orderby' => array(), - 'qb_wherein' => array(), 'qb_aliased_tables' => array(), 'qb_no_escape' => array(), 'qb_distinct' => FALSE, @@ -2351,7 +2624,6 @@ abstract class CI_DB_query_builder extends CI_DB_driver { 'qb_set' => array(), 'qb_from' => array(), 'qb_where' => array(), - 'qb_like' => array(), 'qb_orderby' => array(), 'qb_keys' => array(), 'qb_limit' => FALSE diff --git a/system/database/DB_result.php b/system/database/DB_result.php index d44df6c02..9d19075ba 100644 --- a/system/database/DB_result.php +++ b/system/database/DB_result.php @@ -1,4 +1,4 @@ -<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed'); +<?php /** * CodeIgniter * @@ -24,6 +24,7 @@ * @since Version 1.0 * @filesource */ +defined('BASEPATH') OR exit('No direct script access allowed'); /** * Database Result Class @@ -38,19 +39,68 @@ */ class CI_DB_result { + /** + * Connection ID + * + * @var resource|object + */ public $conn_id; + + /** + * Result ID + * + * @var resource|object + */ public $result_id; + + /** + * Result Array + * + * @var array[] + */ public $result_array = array(); + + /** + * Result Object + * + * @var object[] + */ public $result_object = array(); + + /** + * Custom Result Object + * + * @var object[] + */ public $custom_result_object = array(); + + /** + * Current Row index + * + * @var int + */ public $current_row = 0; + + /** + * Number of rows + * + * @var int + */ public $num_rows; + + /** + * Row data + * + * @var array + */ public $row_data; + // -------------------------------------------------------------------- + /** * Constructor * - * @param object + * @param object $driver_object * @return void */ public function __construct(&$driver_object) @@ -89,7 +139,7 @@ class CI_DB_result { /** * Query result. Acts as a wrapper function for the following functions. * - * @param string 'object', 'array' or a custom class name + * @param string $type 'object', 'array' or a custom class name * @return array */ public function result($type = 'object') @@ -113,8 +163,8 @@ class CI_DB_result { /** * Custom query result. * - * @param string A string that represents the type of object you want back - * @return array of objects + * @param string $class_name + * @return array */ public function custom_result_object($class_name) { @@ -249,29 +299,28 @@ class CI_DB_result { // -------------------------------------------------------------------- /** - * Query result. Acts as a wrapper function for the following functions. + * Row + * + * A wrapper method. * - * @param string - * @param string can be "object" or "array" - * @return mixed either a result object or array + * @param mixed $n + * @param string $type 'object' or 'array' + * @return mixed */ public function row($n = 0, $type = 'object') { if ( ! is_numeric($n)) { // We cache the row data for subsequent uses - if ( ! is_array($this->row_data)) - { - $this->row_data = $this->row_array(0); - } + is_array($this->row_data) OR $this->row_data = $this->row_array(0); - // array_key_exists() instead of isset() to allow for MySQL NULL values - if (array_key_exists($n, $this->row_data)) + // array_key_exists() instead of isset() to allow for NULL values + if (empty($this->row_data) OR ! array_key_exists($n, $this->row_data)) { - return $this->row_data[$n]; + return NULL; } - // reset the $n variable if the result was not achieved - $n = 0; + + return $this->row_data[$n]; } if ($type === 'object') return $this->row_object($n); @@ -284,6 +333,8 @@ class CI_DB_result { /** * Assigns an item into a particular column slot * + * @param mixed $key + * @param mixed $value * @return void */ public function set_row($key, $value = NULL) @@ -314,6 +365,8 @@ class CI_DB_result { /** * Returns a single result row - custom object version * + * @param int $n + * @param string $type * @return object */ public function custom_row_object($n, $type) @@ -338,6 +391,7 @@ class CI_DB_result { /** * Returns a single result row - object version * + * @param int $n * @return object */ public function row_object($n = 0) @@ -361,6 +415,7 @@ class CI_DB_result { /** * Returns a single result row - array version * + * @param int $n * @return array */ public function row_array($n = 0) @@ -384,7 +439,8 @@ class CI_DB_result { /** * Returns the "first" row * - * @return object + * @param string $type + * @return mixed */ public function first_row($type = 'object') { @@ -397,7 +453,8 @@ class CI_DB_result { /** * Returns the "last" row * - * @return object + * @param string $type + * @return mixed */ public function last_row($type = 'object') { @@ -410,7 +467,8 @@ class CI_DB_result { /** * Returns the "next" row * - * @return object + * @param string $type + * @return mixed */ public function next_row($type = 'object') { @@ -433,7 +491,8 @@ class CI_DB_result { /** * Returns the "previous" row * - * @return object + * @param string $type + * @return mixed */ public function previous_row($type = 'object') { @@ -455,8 +514,8 @@ class CI_DB_result { /** * Returns an unbuffered row and move pointer to next row * - * @param string 'array', 'object' or a custom class name - * @return mixed either a result object or array + * @param string $type 'array', 'object' or a custom class name + * @return mixed */ public function unbuffered_row($type = 'object') { @@ -475,7 +534,7 @@ class CI_DB_result { // -------------------------------------------------------------------- /** - * The following functions are normally overloaded by the identically named + * The following methods are normally overloaded by the identically named * methods in the platform-specific driver -- except when query caching * is used. When caching is enabled we do not load the other driver. * These functions are primarily here to prevent undefined function errors @@ -483,13 +542,118 @@ class CI_DB_result { * operational due to the unavailability of the database resource IDs with * cached results. */ - public function num_fields() { return 0; } - public function list_fields() { return array(); } - public function field_data() { return array(); } - public function free_result() { $this->result_id = FALSE; } - protected function _data_seek() { return FALSE; } - protected function _fetch_assoc() { return array(); } - protected function _fetch_object() { return array(); } + + // -------------------------------------------------------------------- + + /** + * Number of fields in the result set + * + * Overriden by driver result classes. + * + * @return int + */ + public function num_fields() + { + return 0; + } + + // -------------------------------------------------------------------- + + /** + * Fetch Field Names + * + * Generates an array of column names. + * + * Overriden by driver result classes. + * + * @return array + */ + public function list_fields() + { + return array(); + } + + // -------------------------------------------------------------------- + + /** + * Field data + * + * Generates an array of objects containing field meta-data. + * + * Overriden by driver result classes. + * + * @return array + */ + public function field_data() + { + return array(); + } + + // -------------------------------------------------------------------- + + /** + * Free the result + * + * Overriden by driver result classes. + * + * @return void + */ + public function free_result() + { + $this->result_id = FALSE; + } + + // -------------------------------------------------------------------- + + /** + * Data Seek + * + * Moves the internal pointer to the desired offset. We call + * this internally before fetching results to make sure the + * result set starts at zero. + * + * Overriden by driver result classes. + * + * @param int $n + * @return bool + */ + protected function _data_seek($n = 0) + { + return FALSE; + } + + // -------------------------------------------------------------------- + + /** + * Result - associative array + * + * Returns the result set as an array. + * + * Overriden by driver result classes. + * + * @return array + */ + protected function _fetch_assoc() + { + return array(); + } + + // -------------------------------------------------------------------- + + /** + * Result - object + * + * Returns the result set as an object. + * + * Overriden by driver result classes. + * + * @param string $class_name + * @return object + */ + protected function _fetch_object($class_name = 'stdClass') + { + return array(); + } } diff --git a/system/database/DB_utility.php b/system/database/DB_utility.php index 6a3b40779..f7bef6a2c 100644 --- a/system/database/DB_utility.php +++ b/system/database/DB_utility.php @@ -1,4 +1,4 @@ -<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed'); +<?php /** * CodeIgniter * @@ -24,6 +24,7 @@ * @since Version 1.0 * @filesource */ +defined('BASEPATH') OR exit('No direct script access allowed'); /** * Database Utility Class @@ -34,13 +35,43 @@ */ abstract class CI_DB_utility extends CI_DB_forge { + /** + * Database object + * + * @var object + */ public $db; - // Platform specific SQL strings - // Just setting those defaults to FALSE as they are mostly MySQL-specific + // -------------------------------------------------------------------- + + /** + * List databases statement + * + * @var string + */ + protected $_list_databases = FALSE; + + /** + * OPTIMIZE TABLE statement + * + * @var string + */ protected $_optimize_table = FALSE; + + /** + * REPAIR TABLE statement + * + * @var string + */ protected $_repair_table = FALSE; + // -------------------------------------------------------------------- + + /** + * Class constructor + * + * @return void + */ public function __construct() { // Assign the main database object to $this->db @@ -89,7 +120,7 @@ abstract class CI_DB_utility extends CI_DB_forge { /** * Determine if a particular database exists * - * @param string + * @param string $database_name * @return bool */ public function database_exists($database_name) @@ -102,7 +133,7 @@ abstract class CI_DB_utility extends CI_DB_forge { /** * Optimize Table * - * @param string the table name + * @param string $table_name * @return mixed */ public function optimize_table($table_name) @@ -163,7 +194,7 @@ abstract class CI_DB_utility extends CI_DB_forge { /** * Repair Table * - * @param string the table name + * @param string $table_name * @return mixed */ public function repair_table($table_name) @@ -188,10 +219,10 @@ abstract class CI_DB_utility extends CI_DB_forge { /** * Generate CSV from a query result object * - * @param object The query result object - * @param string The delimiter - comma by default - * @param string The newline character - \n by default - * @param string The enclosure - double quote by default + * @param object $query Query result object + * @param string $delim Delimiter (default: ,) + * @param string $newline Newline character (default: \n) + * @param string $enclosure Enclosure (default: ") * @return string */ public function csv_from_result($query, $delim = ',', $newline = "\n", $enclosure = '"') @@ -228,8 +259,8 @@ abstract class CI_DB_utility extends CI_DB_forge { /** * Generate XML data from a query result object * - * @param object The query result object - * @param array Any preferences + * @param object $query Query result object + * @param array $params Any preferences * @return string */ public function xml_from_result($query, $params = array()) @@ -275,6 +306,7 @@ abstract class CI_DB_utility extends CI_DB_forge { /** * Database Backup * + * @param array $params * @return void */ public function backup($params = array()) @@ -287,8 +319,6 @@ abstract class CI_DB_utility extends CI_DB_forge { $params = array('tables' => $params); } - // ------------------------------------------------------ - // Set up our default preferences $prefs = array( 'tables' => array(), diff --git a/system/database/drivers/cubrid/cubrid_driver.php b/system/database/drivers/cubrid/cubrid_driver.php index a3d0287f5..48b904286 100644 --- a/system/database/drivers/cubrid/cubrid_driver.php +++ b/system/database/drivers/cubrid/cubrid_driver.php @@ -1,4 +1,4 @@ -<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed'); +<?php /** * CodeIgniter * @@ -24,6 +24,7 @@ * @since Version 2.1 * @filesource */ +defined('BASEPATH') OR exit('No direct script access allowed'); /** * CUBRID Database Adapter Class @@ -40,20 +41,37 @@ */ class CI_DB_cubrid_driver extends CI_DB { + /** + * Database driver + * + * @var string + */ public $dbdriver = 'cubrid'; - // The character used for escaping - no need in CUBRID - protected $_escape_char = '`'; + /** + * Auto-commit flag + * + * @var bool + */ + public $auto_commit = TRUE; - // clause and character used for LIKE escape sequences - not used in CUBRID - protected $_like_escape_str = ''; - protected $_like_escape_chr = ''; + // -------------------------------------------------------------------- - protected $_random_keyword = ' RAND()'; // database specific random keyword + /** + * Identifier escape character + * + * @var string + */ + protected $_escape_char = '`'; - // CUBRID-specific properties - public $auto_commit = TRUE; + // -------------------------------------------------------------------- + /** + * Class constructor + * + * @param array $params + * @return void + */ public function __construct($params) { parent::__construct($params); @@ -72,6 +90,8 @@ class CI_DB_cubrid_driver extends CI_DB { } } + // -------------------------------------------------------------------- + /** * Non-persistent database connection * @@ -109,7 +129,7 @@ class CI_DB_cubrid_driver extends CI_DB { * Except for determining if a persistent connection should be used, * the rest of the logic is the same for db_connect() and db_pconnect(). * - * @param bool + * @param bool $persistent * @return resource */ protected function _cubrid_connect($persistent = FALSE) @@ -169,7 +189,7 @@ class CI_DB_cubrid_driver extends CI_DB { /** * Execute the query * - * @param string an SQL query + * @param string $sql an SQL query * @return resource */ protected function _execute($sql) @@ -182,6 +202,7 @@ class CI_DB_cubrid_driver extends CI_DB { /** * Begin Transaction * + * @param bool $test_mode * @return bool */ public function trans_begin($test_mode = FALSE) @@ -260,8 +281,8 @@ class CI_DB_cubrid_driver extends CI_DB { /** * Escape String * - * @param string - * @param bool whether or not the string will be used in a LIKE condition + * @param string $str + * @param bool $like Whether or not the string will be used in a LIKE condition * @return string */ public function escape_str($str, $like = FALSE) @@ -327,7 +348,7 @@ class CI_DB_cubrid_driver extends CI_DB { * * Generates a platform-specific query string so that the table names can be fetched * - * @param bool + * @param bool $prefix_limit * @return string */ protected function _list_tables($prefix_limit = FALSE) @@ -349,7 +370,7 @@ class CI_DB_cubrid_driver extends CI_DB { * * Generates a platform-specific query string so that the column names can be fetched * - * @param string the table name + * @param string $table * @return string */ protected function _list_columns($table = '') @@ -364,7 +385,7 @@ class CI_DB_cubrid_driver extends CI_DB { * * Generates a platform-specific query so that the column data can be retrieved * - * @param string the table name + * @param string $table * @return string */ protected function _field_data($table) @@ -394,12 +415,12 @@ class CI_DB_cubrid_driver extends CI_DB { * * Generates a platform-specific batch update string from the supplied data * - * @param string the table name - * @param array the update data - * @param array the where clause + * @param string $table Table name + * @param array $values Update data + * @param string $index WHERE key * @return string */ - protected function _update_batch($table, $values, $index, $where = NULL) + protected function _update_batch($table, $values, $index) { $ids = array(); foreach ($values as $key => $val) @@ -423,9 +444,29 @@ class CI_DB_cubrid_driver extends CI_DB { .'ELSE '.$k.' END, '; } - return 'UPDATE '.$table.' SET '.substr($cases, 0, -2) - .' WHERE '.(($where !== '' && count($where) > 0) ? implode(' ', $where).' AND ' : '') - .$index.' IN ('.implode(',', $ids).')'; + $this->where($index.' IN('.implode(',', $ids).')', NULL, FALSE); + + return 'UPDATE '.$table.' SET '.substr($cases, 0, -2).$this->_compile_wh('qb_where'); + } + + // -------------------------------------------------------------------- + + /** + * FROM tables + * + * Groups tables in FROM clauses if needed, so there is no confusion + * about operator precedence. + * + * @return string + */ + protected function _from_tables() + { + if ( ! empty($this->qb_join) && count($this->qb_from) > 1) + { + return '('.implode(', ', $this->qb_from).')'; + } + + return implode(', ', $this->qb_from); } // -------------------------------------------------------------------- diff --git a/system/database/drivers/cubrid/cubrid_forge.php b/system/database/drivers/cubrid/cubrid_forge.php index d328aa241..33d502137 100644 --- a/system/database/drivers/cubrid/cubrid_forge.php +++ b/system/database/drivers/cubrid/cubrid_forge.php @@ -1,4 +1,4 @@ -<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed'); +<?php /** * CodeIgniter * @@ -24,6 +24,7 @@ * @since Version 2.1 * @filesource */ +defined('BASEPATH') OR exit('No direct script access allowed'); /** * CUBRID Forge Class @@ -34,13 +35,26 @@ */ class CI_DB_cubrid_forge extends CI_DB_forge { + /** + * CREATE DATABASE statement + * + * @var string + */ protected $_create_database = FALSE; + + // -------------------------------------------------------------------- + + /** + * DROP DATABASE statement + * + * @var string + */ protected $_drop_database = FALSE; /** * Process Fields * - * @param mixed the fields + * @param mixed $fields * @return string */ protected function _process_fields($fields) diff --git a/system/database/drivers/cubrid/cubrid_result.php b/system/database/drivers/cubrid/cubrid_result.php index 4a06a2d39..30aed38d9 100644 --- a/system/database/drivers/cubrid/cubrid_result.php +++ b/system/database/drivers/cubrid/cubrid_result.php @@ -1,4 +1,4 @@ -<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed'); +<?php /** * CodeIgniter * @@ -24,6 +24,7 @@ * @since Version 2.1 * @filesource */ +defined('BASEPATH') OR exit('No direct script access allowed'); /** * CUBRID Result Class @@ -130,8 +131,9 @@ class CI_DB_cubrid_result extends CI_DB_result { * * Moves the internal pointer to the desired offset. We call * this internally before fetching results to make sure the - * result set starts at zero + * result set starts at zero. * + * @param int $n * @return bool */ protected function _data_seek($n = 0) @@ -160,7 +162,7 @@ class CI_DB_cubrid_result extends CI_DB_result { * * Returns the result set as an object * - * @param string + * @param string $class_name * @return object */ protected function _fetch_object($class_name = 'stdClass') diff --git a/system/database/drivers/cubrid/cubrid_utility.php b/system/database/drivers/cubrid/cubrid_utility.php index ea8feb4e2..82d37af3c 100644 --- a/system/database/drivers/cubrid/cubrid_utility.php +++ b/system/database/drivers/cubrid/cubrid_utility.php @@ -1,4 +1,4 @@ -<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed'); +<?php /** * CodeIgniter * @@ -24,6 +24,7 @@ * @since Version 2.1 * @filesource */ +defined('BASEPATH') OR exit('No direct script access allowed'); /** * CUBRID Utility Class diff --git a/system/database/drivers/ibase/ibase_driver.php b/system/database/drivers/ibase/ibase_driver.php index c9027670d..fc1c28f31 100644 --- a/system/database/drivers/ibase/ibase_driver.php +++ b/system/database/drivers/ibase/ibase_driver.php @@ -1,4 +1,4 @@ -<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed'); +<?php /** * CodeIgniter * @@ -24,6 +24,7 @@ * @since Version 3.0 * @filesource */ +defined('BASEPATH') OR exit('No direct script access allowed'); /** * Firebird/Interbase Database Adapter Class @@ -40,19 +41,30 @@ */ class CI_DB_ibase_driver extends CI_DB { + /** + * Database driver + * + * @var string + */ public $dbdriver = 'ibase'; - // The character used to escape with - protected $_escape_char = '"'; + // -------------------------------------------------------------------- - // clause and character used for LIKE escape sequences - protected $_like_escape_str = " ESCAPE '%s' "; - protected $_like_escape_chr = '!'; + /** + * ORDER BY random keyword + * + * @var string + */ + protected $_random_keyword = ' Random()'; - protected $_random_keyword = ' Random()'; // database specific random keyword + /** + * IBase Transaction status flag + * + * @var resource + */ + protected $_ibase_trans; - // Keeps track of the resource for the current transaction - protected $trans; + // -------------------------------------------------------------------- /** * Non-persistent database connection @@ -107,7 +119,7 @@ class CI_DB_ibase_driver extends CI_DB { /** * Execute the query * - * @param string an SQL query + * @param string $sql an SQL query * @return resource */ protected function _execute($sql) @@ -120,6 +132,7 @@ class CI_DB_ibase_driver extends CI_DB { /** * Begin Transaction * + * @param bool $test_mode * @return bool */ public function trans_begin($test_mode = FALSE) @@ -135,7 +148,7 @@ class CI_DB_ibase_driver extends CI_DB { // even if the queries produce a successful result. $this->_trans_failure = ($test_mode === TRUE); - $this->trans = @ibase_trans($this->conn_id); + $this->_ibase_trans = @ibase_trans($this->conn_id); return TRUE; } @@ -155,7 +168,7 @@ class CI_DB_ibase_driver extends CI_DB { return TRUE; } - return @ibase_commit($this->trans); + return @ibase_commit($this->_ibase_trans); } // -------------------------------------------------------------------- @@ -173,7 +186,7 @@ class CI_DB_ibase_driver extends CI_DB { return TRUE; } - return @ibase_rollback($this->trans); + return @ibase_rollback($this->_ibase_trans); } // -------------------------------------------------------------------- @@ -181,8 +194,8 @@ class CI_DB_ibase_driver extends CI_DB { /** * Escape String * - * @param string - * @param bool whether or not the string will be used in a LIKE condition + * @param string $str + * @param bool $like Whether or not the string will be used in a LIKE condition * @return string */ public function escape_str($str, $like = FALSE) @@ -242,7 +255,7 @@ class CI_DB_ibase_driver extends CI_DB { * * Generates a platform-specific query string so that the table names can be fetched * - * @param bool + * @param bool $prefix_limit * @return string */ protected function _list_tables($prefix_limit = FALSE) @@ -265,7 +278,7 @@ class CI_DB_ibase_driver extends CI_DB { * * Generates a platform-specific query string so that the column names can be fetched * - * @param string the table name + * @param string $table * @return string */ protected function _list_columns($table = '') @@ -280,12 +293,15 @@ class CI_DB_ibase_driver extends CI_DB { * * Generates a platform-specific query so that the column data can be retrieved * - * @param string the table name + * @param string $table * @return string */ protected function _field_data($table) { - return $this->_limit('SELECT * FROM '.$this->protect_identifiers($table), 1, NULL); + $this->qb_limit = 1; + $sql = $this->_limit('SELECT * FROM '.$this->protect_identifiers($table)); + $this->qb_limit = 0; + return $sql; } // -------------------------------------------------------------------- @@ -306,51 +322,18 @@ class CI_DB_ibase_driver extends CI_DB { // -------------------------------------------------------------------- /** - * From Tables - * - * This public function implicitly groups FROM tables so there is no confusion - * about operator precedence in harmony with SQL standards - * - * @param array - * @return string - */ - protected function _from_tables($tables) - { - return is_array($tables) ? implode(', ', $tables) : $tables; - } - - // -------------------------------------------------------------------- - - /** * Update statement * * Generates a platform-specific update string from the supplied data * - * @param string the table name - * @param array the update data - * @param array the where clause - * @param array the orderby clause - * @param array the limit clause (ignored) - * @param array the like clause + * @param string $table + * @param array $values * @return string */ - protected function _update($table, $values, $where, $orderby = array(), $limit = FALSE, $like = array()) + protected function _update($table, $values) { - foreach ($values as $key => $val) - { - $valstr[] = $key.' = '.$val; - } - - $where = empty($where) ? '' : ' WHERE '.implode(' ', $where); - - if ( ! empty($like)) - { - $where .= ($where === '' ? ' WHERE ' : ' AND ').implode(' ', $like); - } - - return 'UPDATE '.$table.' SET '.implode(', ', $valstr) - .$where - .(count($orderby) > 0 ? ' ORDER BY '.implode(', ', $orderby) : ''); + $this->qb_limit = FALSE; + return parent::_update($table, $values); } // -------------------------------------------------------------------- @@ -360,10 +343,10 @@ class CI_DB_ibase_driver extends CI_DB { * * Generates a platform-specific truncate string from the supplied data * - * If the database does not support the truncate() command, + * If the database does not support the TRUNCATE statement, * then this method maps to 'DELETE FROM table' * - * @param string the table name + * @param string $table * @return string */ protected function _truncate($table) @@ -378,46 +361,37 @@ class CI_DB_ibase_driver extends CI_DB { * * Generates a platform-specific delete string from the supplied data * - * @param string the table name - * @param array the where clause - * @param array the like clause - * @param string the limit clause (ignored) + * @param string $table * @return string */ - protected function _delete($table, $where = array(), $like = array(), $limit = FALSE) + protected function _delete($table) { - $conditions = array(); - - empty($where) OR $conditions[] = implode(' ', $where); - empty($like) OR $conditions[] = implode(' ', $like); - - return 'DELETE FROM '.$table.(count($conditions) > 0 ? ' WHERE '.implode(' AND ', $conditions) : ''); + $this->qb_limit = FALSE; + return parent::_delete($table); } // -------------------------------------------------------------------- /** - * Limit string + * LIMIT * * Generates a platform-specific LIMIT clause * - * @param string the sql query string - * @param int the number of rows to limit the query to - * @param int the offset value + * @param string $sql SQL Query * @return string */ - protected function _limit($sql, $limit, $offset) + protected function _limit($sql) { // Limit clause depends on if Interbase or Firebird if (stripos($this->version(), 'firebird') !== FALSE) { - $select = 'FIRST '. (int) $limit - .($offset ? ' SKIP '. (int) $offset : ''); + $select = 'FIRST '.$this->qb_limit + .($this->qb_offset ? ' SKIP '.$this->qb_offset : ''); } else { $select = 'ROWS ' - .($offset ? (int) $offset.' TO '.($limit + $offset) : (int) $limit); + .($this->qb_offset ? $this->qb_offset.' TO '.($this->qb_limit + $this->qb_offset) : $this->qb_limit); } return preg_replace('`SELECT`i', 'SELECT '.$select, $sql); diff --git a/system/database/drivers/ibase/ibase_forge.php b/system/database/drivers/ibase/ibase_forge.php index da75eb9c3..7c4d00a23 100644 --- a/system/database/drivers/ibase/ibase_forge.php +++ b/system/database/drivers/ibase/ibase_forge.php @@ -1,4 +1,4 @@ -<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed'); +<?php /** * CodeIgniter * @@ -24,6 +24,7 @@ * @since Version 3.0 * @filesource */ +defined('BASEPATH') OR exit('No direct script access allowed'); /** * Interbase/Firebird Forge Class @@ -34,12 +35,19 @@ */ class CI_DB_ibase_forge extends CI_DB_forge { + /** + * DROP TABLE statement + * + * @var string + */ protected $_drop_table = 'DROP TABLE %s'; + // -------------------------------------------------------------------- + /** * Create database * - * @param string the database name + * @param string $db_name * @return string */ public function create_database($db_name) diff --git a/system/database/drivers/ibase/ibase_result.php b/system/database/drivers/ibase/ibase_result.php index 95e55710b..bbad9d895 100644 --- a/system/database/drivers/ibase/ibase_result.php +++ b/system/database/drivers/ibase/ibase_result.php @@ -1,4 +1,4 @@ -<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed'); +<?php /** * CodeIgniter * @@ -24,6 +24,7 @@ * @since Version 1.0 * @filesource */ +defined('BASEPATH') OR exit('No direct script access allowed'); /** * Interbase/Firebird Result Class @@ -128,7 +129,7 @@ class CI_DB_ibase_result extends CI_DB_result { * * Returns the result set as an object * - * @param string + * @param string $class_name * @return object */ protected function _fetch_object($class_name = 'stdClass') diff --git a/system/database/drivers/ibase/ibase_utility.php b/system/database/drivers/ibase/ibase_utility.php index d0e84a7b2..5eb209ae1 100644 --- a/system/database/drivers/ibase/ibase_utility.php +++ b/system/database/drivers/ibase/ibase_utility.php @@ -1,4 +1,4 @@ -<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed'); +<?php /** * CodeIgniter * @@ -24,6 +24,7 @@ * @since Version 3.0 * @filesource */ +defined('BASEPATH') OR exit('No direct script access allowed'); /** * Interbase/Firebird Utility Class @@ -34,10 +35,8 @@ */ class CI_DB_ibase_utility extends CI_DB_utility { - protected $_list_databases = FALSE; - /** - * Interbase/Firebird Export + * Export * * @param string $filename * @return mixed diff --git a/system/database/drivers/mssql/mssql_driver.php b/system/database/drivers/mssql/mssql_driver.php index 1714704a8..c74f9683b 100644 --- a/system/database/drivers/mssql/mssql_driver.php +++ b/system/database/drivers/mssql/mssql_driver.php @@ -1,4 +1,4 @@ -<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed'); +<?php /** * CodeIgniter * @@ -24,6 +24,7 @@ * @since Version 1.0 * @filesource */ +defined('BASEPATH') OR exit('No direct script access allowed'); /** * MS SQL Database Adapter Class @@ -40,26 +41,40 @@ */ class CI_DB_mssql_driver extends CI_DB { + /** + * Database driver + * + * @var string + */ public $dbdriver = 'mssql'; - // The character used for escaping - protected $_escape_char = '"'; - - // clause and character used for LIKE escape sequences - protected $_like_escape_str = " ESCAPE '%s' "; - protected $_like_escape_chr = '!'; + // -------------------------------------------------------------------- + /** + * ORDER BY random keyword + * + * @var string + */ protected $_random_keyword = ' NEWID()'; - // MSSQL-specific properties + /** + * Quoted identifier flag + * + * Whether to use SQL-92 standard quoted identifier + * (double quotes) or brackets for identifier escaping. + * + * @var bool + */ protected $_quoted_identifier = TRUE; - /* - * Constructor + // -------------------------------------------------------------------- + + /** + * Class constructor * * Appends the port number to the hostname, if needed. * - * @param array + * @param array $params * @return void */ public function __construct($params) @@ -77,7 +92,7 @@ class CI_DB_mssql_driver extends CI_DB { /** * Non-persistent database connection * - * @param bool + * @param bool $persistent * @return resource */ public function db_connect($persistent = FALSE) @@ -117,7 +132,7 @@ class CI_DB_mssql_driver extends CI_DB { /** * Select the database * - * @param string database name + * @param string $database * @return bool */ public function db_select($database = '') @@ -143,7 +158,7 @@ class CI_DB_mssql_driver extends CI_DB { /** * Execute the query * - * @param string an SQL query + * @param string $sql an SQL query * @return mixed resource if rows are returned, bool otherwise */ protected function _execute($sql) @@ -156,6 +171,7 @@ class CI_DB_mssql_driver extends CI_DB { /** * Begin Transaction * + * @param bool $test_mode * @return bool */ public function trans_begin($test_mode = FALSE) @@ -215,8 +231,8 @@ class CI_DB_mssql_driver extends CI_DB { /** * Escape String * - * @param string - * @param bool whether or not the string will be used in a LIKE condition + * @param string $str + * @param bool $like Whether or not the string will be used in a LIKE condition * @return string */ public function escape_str($str, $like = FALSE) @@ -298,7 +314,7 @@ class CI_DB_mssql_driver extends CI_DB { * * Generates a platform-specific query string so that the table names can be fetched * - * @param bool + * @param bool $prefix_limit * @return string */ protected function _list_tables($prefix_limit = FALSE) @@ -323,7 +339,7 @@ class CI_DB_mssql_driver extends CI_DB { * * Generates a platform-specific query string so that the column names can be fetched * - * @param string the table name + * @param string $table * @return string */ protected function _list_columns($table = '') @@ -338,7 +354,7 @@ class CI_DB_mssql_driver extends CI_DB { * * Generates a platform-specific query so that the column data can be retrieved * - * @param string the table name + * @param string $table * @return string */ protected function _field_data($table) @@ -366,49 +382,19 @@ class CI_DB_mssql_driver extends CI_DB { // -------------------------------------------------------------------- /** - * From Tables - * - * This function implicitly groups FROM tables so there is no confusion - * about operator precedence in harmony with SQL standards - * - * @param array - * @return string - */ - protected function _from_tables($tables) - { - return is_array($tables) ? implode(', ', $tables) : $tables; - } - - // -------------------------------------------------------------------- - - /** * Update statement * * Generates a platform-specific update string from the supplied data * - * @param string the table name - * @param array the update data - * @param array the where clause - * @param array the orderby clause (ignored) - * @param array the limit clause (ignored) - * @param array the like clause + * @param string $table + * @param array $values * @return string */ - protected function _update($table, $values, $where, $orderby = array(), $limit = FALSE, $like = array()) + protected function _update($table, $values) { - foreach($values as $key => $val) - { - $valstr[] = $key.' = '.$val; - } - - $where = empty($where) ? '' : ' WHERE '.implode(' ', $where); - - if ( ! empty($like)) - { - $where .= ($where === '' ? ' WHERE ' : ' AND ').implode(' ', $like); - } - - return 'UPDATE '.$table.' SET '.implode(', ', $valstr).' WHERE '.$where; + $this->qb_limit = FALSE; + $this->qb_orderby = array(); + return parent::_update($table, $values); } // -------------------------------------------------------------------- @@ -418,10 +404,10 @@ class CI_DB_mssql_driver extends CI_DB { * * Generates a platform-specific truncate string from the supplied data * - * If the database does not support the truncate() command, + * If the database does not support the TRUNCATE statement, * then this method maps to 'DELETE FROM table' * - * @param string the table name + * @param string $table * @return string */ protected function _truncate($table) @@ -436,61 +422,65 @@ class CI_DB_mssql_driver extends CI_DB { * * Generates a platform-specific delete string from the supplied data * - * @param string the table name - * @param array the where clause - * @param array the like clause - * @param string the limit clause + * @param string $table * @return string */ - protected function _delete($table, $where = array(), $like = array(), $limit = FALSE) + protected function _delete($table) { - $conditions = array(); - - empty($where) OR $conditions[] = implode(' ', $where); - empty($like) OR $conditions[] = implode(' ', $like); - - $conditions = (count($conditions) > 0) ? ' WHERE '.implode(' AND ', $conditions) : ''; + if ($this->qb_limit) + { + return 'WITH ci_delete AS (SELECT TOP '.$this->qb_limit.' * FROM '.$table.$this->_compile_wh('qb_where').') DELETE FROM ci_delete'; + } - return ($limit) - ? 'WITH ci_delete AS (SELECT TOP '.$limit.' * FROM '.$table.$conditions.') DELETE FROM ci_delete' - : 'DELETE FROM '.$table.$conditions; + return parent::_delete($table); } // -------------------------------------------------------------------- /** - * Limit string + * LIMIT * * Generates a platform-specific LIMIT clause * - * @param string the sql query string - * @param int the number of rows to limit the query to - * @param int the offset value + * @param string $sql SQL Query * @return string */ - protected function _limit($sql, $limit, $offset) + protected function _limit($sql) { - // As of SQL Server 2012 (11.0.*) OFFSET is supported - if (version_compare($this->version(), '11', '>=')) - { - return $sql.' OFFSET '.(int) $offset.' ROWS FETCH NEXT '.(int) $limit.' ROWS ONLY'; - } - - $limit = $offset + $limit; + $limit = $this->qb_offset + $this->qb_limit; // As of SQL Server 2005 (9.0.*) ROW_NUMBER() is supported, // however an ORDER BY clause is required for it to work - if (version_compare($this->version(), '9', '>=') && $offset && ! empty($this->qb_orderby)) + if (version_compare($this->version(), '9', '>=') && $this->qb_offset && ! empty($this->qb_orderby)) { - $orderby = 'ORDER BY '.implode(', ', $this->qb_orderby); + $orderby = $this->_compile_order_by(); // We have to strip the ORDER BY clause - $sql = trim(substr($sql, 0, strrpos($sql, 'ORDER BY '.$orderby))); + $sql = trim(substr($sql, 0, strrpos($sql, $orderby))); + + // Get the fields to select from our subquery, so that we can avoid CI_rownum appearing in the actual results + if (count($this->qb_select) === 0) + { + $select = '*'; // Inevitable + } + else + { + // Use only field names and their aliases, everything else is out of our scope. + $select = array(); + $field_regexp = ($this->_quoted_identifier) + ? '("[^\"]+")' : '(\[[^\]]+\])'; + for ($i = 0, $c = count($this->qb_select); $i < $c; $i++) + { + $select[] = preg_match('/(?:\s|\.)'.$field_regexp.'$/i', $this->qb_select[$i], $m) + ? $m[1] : $this->qb_select[$i]; + } + $select = implode(', ', $select); + } - return 'SELECT '.(count($this->qb_select) === 0 ? '*' : implode(', ', $this->qb_select))." FROM (\n" - .preg_replace('/^(SELECT( DISTINCT)?)/i', '\\1 ROW_NUMBER() OVER('.$orderby.') AS '.$this->escape_identifiers('CI_rownum').', ', $sql) - ."\n) ".$this->escape_identifiers('CI_subquery') - ."\nWHERE ".$this->escape_identifiers('CI_rownum').' BETWEEN '.((int) $offset + 1).' AND '.$limit; + return 'SELECT '.$select." FROM (\n\n" + .preg_replace('/^(SELECT( DISTINCT)?)/i', '\\1 ROW_NUMBER() OVER('.trim($orderby).') AS '.$this->escape_identifiers('CI_rownum').', ', $sql) + ."\n\n) ".$this->escape_identifiers('CI_subquery') + ."\nWHERE ".$this->escape_identifiers('CI_rownum').' BETWEEN '.($this->qb_offset + 1).' AND '.$limit; } return preg_replace('/(^\SELECT (DISTINCT)?)/i','\\1 TOP '.$limit.' ', $sql); diff --git a/system/database/drivers/mssql/mssql_forge.php b/system/database/drivers/mssql/mssql_forge.php index 3a3528f7b..1eef648b0 100644 --- a/system/database/drivers/mssql/mssql_forge.php +++ b/system/database/drivers/mssql/mssql_forge.php @@ -1,4 +1,4 @@ -<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed'); +<?php /** * CodeIgniter * @@ -24,6 +24,7 @@ * @since Version 1.0 * @filesource */ +defined('BASEPATH') OR exit('No direct script access allowed'); /** * MS SQL Forge Class @@ -34,8 +35,15 @@ */ class CI_DB_mssql_forge extends CI_DB_forge { + /** + * DROP TABLE statement + * + * @var string + */ protected $_drop_table = 'DROP TABLE %s'; + // -------------------------------------------------------------------- + /** * Create Table * diff --git a/system/database/drivers/mssql/mssql_result.php b/system/database/drivers/mssql/mssql_result.php index aeede3f4b..c74c70abf 100644 --- a/system/database/drivers/mssql/mssql_result.php +++ b/system/database/drivers/mssql/mssql_result.php @@ -1,4 +1,4 @@ -<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed'); +<?php /** * CodeIgniter * @@ -24,6 +24,7 @@ * @since Version 1.0 * @filesource */ +defined('BASEPATH') OR exit('No direct script access allowed'); /** * MSSQL Result Class @@ -131,8 +132,9 @@ class CI_DB_mssql_result extends CI_DB_result { * * Moves the internal pointer to the desired offset. We call * this internally before fetching results to make sure the - * result set starts at zero + * result set starts at zero. * + * @param int $n * @return bool */ protected function _data_seek($n = 0) @@ -161,7 +163,7 @@ class CI_DB_mssql_result extends CI_DB_result { * * Returns the result set as an object * - * @param string + * @param string $class_name * @return object */ protected function _fetch_object($class_name = 'stdClass') diff --git a/system/database/drivers/mssql/mssql_utility.php b/system/database/drivers/mssql/mssql_utility.php index 69fcec5f6..a011d5974 100644 --- a/system/database/drivers/mssql/mssql_utility.php +++ b/system/database/drivers/mssql/mssql_utility.php @@ -1,4 +1,4 @@ -<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed'); +<?php /** * CodeIgniter * @@ -24,6 +24,7 @@ * @since Version 1.0 * @filesource */ +defined('BASEPATH') OR exit('No direct script access allowed'); /** * MS SQL Utility Class @@ -34,13 +35,24 @@ */ class CI_DB_mssql_utility extends CI_DB_utility { + /** + * List databases statement + * + * @var string + */ protected $_list_databases = 'EXEC sp_helpdb'; // Can also be: EXEC sp_databases + + /** + * OPTIMIZE TABLE statement + * + * @var string + */ protected $_optimize_table = 'ALTER INDEX all ON %s REORGANIZE'; /** - * MSSQL Export + * Export * - * @param array Preferences + * @param array $params Preferences * @return bool */ protected function _backup($params = array()) diff --git a/system/database/drivers/mysql/mysql_driver.php b/system/database/drivers/mysql/mysql_driver.php index 29db90408..2457e558c 100644 --- a/system/database/drivers/mysql/mysql_driver.php +++ b/system/database/drivers/mysql/mysql_driver.php @@ -1,4 +1,4 @@ -<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed'); +<?php /** * CodeIgniter * @@ -24,6 +24,7 @@ * @since Version 1.0 * @filesource */ +defined('BASEPATH') OR exit('No direct script access allowed'); /** * MySQL Database Adapter Class @@ -40,28 +41,46 @@ */ class CI_DB_mysql_driver extends CI_DB { + /** + * Database driver + * + * @var string + */ public $dbdriver = 'mysql'; - // The character used for escaping - protected $_escape_char = '`'; - - // clause and character used for LIKE escape sequences - not used in MySQL - protected $_like_escape_str = ''; - protected $_like_escape_chr = '\\'; - - protected $_random_keyword = ' RAND()'; // database specific random keyword + /** + * Compression flag + * + * @var bool + */ + public $compress = FALSE; /** + * DELETE hack flag + * * Whether to use the MySQL "delete hack" which allows the number * of affected rows to be shown. Uses a preg_replace when enabled, * adding a bit more processing to all queries. + * + * @var bool */ public $delete_hack = TRUE; + // -------------------------------------------------------------------- + + /** + * Identifier escape character + * + * @var string + */ + protected $_escape_char = '`'; + + // -------------------------------------------------------------------- + /** - * Constructor + * Class constructor * - * @param array + * @param array $params * @return void */ public function __construct($params) @@ -79,11 +98,21 @@ class CI_DB_mysql_driver extends CI_DB { /** * Non-persistent database connection * + * @param bool $persistent * @return resource */ - public function db_connect() + public function db_connect($persistent = FALSE) { - return @mysql_connect($this->hostname, $this->username, $this->password, TRUE); + $client_flags = ($this->compress === FALSE) ? 0 : MYSQL_CLIENT_COMPRESS; + + if ($this->encrypt === TRUE) + { + $client_flags = $client_flags | MYSQL_CLIENT_SSL; + } + + return ($persistent === TRUE) + ? @mysql_pconnect($this->hostname, $this->username, $this->password, $client_flags) + : @mysql_connect($this->hostname, $this->username, $this->password, TRUE, $client_flags); } // -------------------------------------------------------------------- @@ -95,7 +124,7 @@ class CI_DB_mysql_driver extends CI_DB { */ public function db_pconnect() { - return @mysql_pconnect($this->hostname, $this->username, $this->password); + return $this->db_connect(TRUE); } // -------------------------------------------------------------------- @@ -121,7 +150,7 @@ class CI_DB_mysql_driver extends CI_DB { /** * Select the database * - * @param string database name + * @param string $database * @return bool */ public function db_select($database = '') @@ -145,7 +174,7 @@ class CI_DB_mysql_driver extends CI_DB { /** * Set client character set * - * @param string + * @param string $charset * @return bool */ protected function _db_set_charset($charset) @@ -172,7 +201,7 @@ class CI_DB_mysql_driver extends CI_DB { /** * Execute the query * - * @param string an SQL query + * @param string $sql an SQL query * @return mixed */ protected function _execute($sql) @@ -187,7 +216,7 @@ class CI_DB_mysql_driver extends CI_DB { * * If needed, each database adapter can prep the query string * - * @param string an SQL query + * @param string $sql an SQL query * @return string */ protected function _prep_query($sql) @@ -207,6 +236,7 @@ class CI_DB_mysql_driver extends CI_DB { /** * Begin Transaction * + * @param bool $test_mode * @return bool */ public function trans_begin($test_mode = FALSE) @@ -272,8 +302,8 @@ class CI_DB_mysql_driver extends CI_DB { /** * Escape String * - * @param string - * @param bool whether or not the string will be used in a LIKE condition + * @param string $str + * @param bool $like Whether or not the string will be used in a LIKE condition * @return string */ public function escape_str($str, $like = FALSE) @@ -332,7 +362,7 @@ class CI_DB_mysql_driver extends CI_DB { * * Generates a platform-specific query string so that the table names can be fetched * - * @param bool + * @param bool $prefix_limit * @return string */ protected function _list_tables($prefix_limit = FALSE) @@ -354,7 +384,7 @@ class CI_DB_mysql_driver extends CI_DB { * * Generates a platform-specific query string so that the column names can be fetched * - * @param string the table name + * @param string $table * @return string */ protected function _list_columns($table = '') @@ -367,7 +397,7 @@ class CI_DB_mysql_driver extends CI_DB { /** * Returns an object with field data * - * @param string the table name + * @param string $table * @return object */ public function field_data($table = '') @@ -418,12 +448,12 @@ class CI_DB_mysql_driver extends CI_DB { * * Generates a platform-specific batch update string from the supplied data * - * @param string the table name - * @param array the update data - * @param array the where clause + * @param string $table Table name + * @param array $values Update data + * @param string $index WHERE key * @return string */ - protected function _update_batch($table, $values, $index, $where = NULL) + protected function _update_batch($table, $values, $index) { $ids = array(); foreach ($values as $key => $val) @@ -447,9 +477,29 @@ class CI_DB_mysql_driver extends CI_DB { .'ELSE '.$k.' END, '; } - return 'UPDATE '.$table.' SET '.substr($cases, 0, -2) - .' WHERE '.(($where !== '' && count($where) > 0) ? implode(' ', $where).' AND ' : '') - .$index.' IN('.implode(',', $ids).')'; + $this->where($index.' IN('.implode(',', $ids).')', NULL, FALSE); + + return 'UPDATE '.$table.' SET '.substr($cases, 0, -2).$this->_compile_wh('qb_where'); + } + + // -------------------------------------------------------------------- + + /** + * FROM tables + * + * Groups tables in FROM clauses if needed, so there is no confusion + * about operator precedence. + * + * @return string + */ + protected function _from_tables() + { + if ( ! empty($this->qb_join) && count($this->qb_from) > 1) + { + return '('.implode(', ', $this->qb_from).')'; + } + + return implode(', ', $this->qb_from); } // -------------------------------------------------------------------- diff --git a/system/database/drivers/mysql/mysql_forge.php b/system/database/drivers/mysql/mysql_forge.php index 2ac75bad2..7ce4e8b00 100644 --- a/system/database/drivers/mysql/mysql_forge.php +++ b/system/database/drivers/mysql/mysql_forge.php @@ -1,4 +1,4 @@ -<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed'); +<?php /** * CodeIgniter * @@ -24,6 +24,7 @@ * @since Version 1.0 * @filesource */ +defined('BASEPATH') OR exit('No direct script access allowed'); /** * MySQL Forge Class @@ -34,12 +35,19 @@ */ class CI_DB_mysql_forge extends CI_DB_forge { + /** + * CREATE DATABASE statement + * + * @var string + */ protected $_create_database = 'CREATE DATABASE %s CHARACTER SET %s COLLATE %s'; + // -------------------------------------------------------------------- + /** * Process Fields * - * @param mixed the fields + * @param mixed $fields * @return string */ protected function _process_fields($fields) diff --git a/system/database/drivers/mysql/mysql_result.php b/system/database/drivers/mysql/mysql_result.php index 7fbb65496..4bfa0ae35 100644 --- a/system/database/drivers/mysql/mysql_result.php +++ b/system/database/drivers/mysql/mysql_result.php @@ -1,4 +1,4 @@ -<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed'); +<?php /** * CodeIgniter * @@ -24,6 +24,7 @@ * @since Version 1.0 * @filesource */ +defined('BASEPATH') OR exit('No direct script access allowed'); /** * MySQL Result Class @@ -38,9 +39,9 @@ class CI_DB_mysql_result extends CI_DB_result { /** - * Constructor + * Class constructor * - * @param object + * @param object &$driver_object * @return void */ public function __construct(&$driver_object) @@ -144,8 +145,9 @@ class CI_DB_mysql_result extends CI_DB_result { * * Moves the internal pointer to the desired offset. We call * this internally before fetching results to make sure the - * result set starts at zero + * result set starts at zero. * + * @param int $n * @return bool */ protected function _data_seek($n = 0) @@ -176,7 +178,7 @@ class CI_DB_mysql_result extends CI_DB_result { * * Returns the result set as an object * - * @param string + * @param string $class_name * @return object */ protected function _fetch_object($class_name = 'stdClass') diff --git a/system/database/drivers/mysql/mysql_utility.php b/system/database/drivers/mysql/mysql_utility.php index f0bbc665e..8aa051755 100644 --- a/system/database/drivers/mysql/mysql_utility.php +++ b/system/database/drivers/mysql/mysql_utility.php @@ -1,4 +1,4 @@ -<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed'); +<?php /** * CodeIgniter * @@ -24,6 +24,7 @@ * @since Version 1.0 * @filesource */ +defined('BASEPATH') OR exit('No direct script access allowed'); /** * MySQL Utility Class @@ -34,14 +35,33 @@ */ class CI_DB_mysql_utility extends CI_DB_utility { + /** + * List databases statement + * + * @var string + */ protected $_list_databases = 'SHOW DATABASES'; + + /** + * OPTIMIZE TABLE statement + * + * @var string + */ protected $_optimize_table = 'OPTIMIZE TABLE %s'; + + /** + * REPAIR TABLE statement + * + * @var string + */ protected $_repair_table = 'REPAIR TABLE %s'; + // -------------------------------------------------------------------- + /** - * MySQL Export + * Export * - * @param array Preferences + * @param array $params Preferences * @return mixed */ protected function _backup($params = array()) diff --git a/system/database/drivers/mysqli/mysqli_driver.php b/system/database/drivers/mysqli/mysqli_driver.php index be61aab20..7d2507b40 100644 --- a/system/database/drivers/mysqli/mysqli_driver.php +++ b/system/database/drivers/mysqli/mysqli_driver.php @@ -1,4 +1,4 @@ -<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed'); +<?php /** * CodeIgniter * @@ -24,6 +24,7 @@ * @since Version 1.0 * @filesource */ +defined('BASEPATH') OR exit('No direct script access allowed'); /** * MySQLi Database Adapter Class @@ -40,34 +41,60 @@ */ class CI_DB_mysqli_driver extends CI_DB { + /** + * Database driver + * + * @var string + */ public $dbdriver = 'mysqli'; - // The character used for escaping - protected $_escape_char = '`'; - - // clause and character used for LIKE escape sequences - not used in MySQL - protected $_like_escape_str = ''; - protected $_like_escape_chr = '\\'; - - protected $_random_keyword = ' RAND()'; // database specific random keyword + /** + * Compression flag + * + * @var bool + */ + public $compress = FALSE; /** + * DELETE hack flag + * * Whether to use the MySQL "delete hack" which allows the number * of affected rows to be shown. Uses a preg_replace when enabled, * adding a bit more processing to all queries. + * + * @var bool */ public $delete_hack = TRUE; + // -------------------------------------------------------------------- + + /** + * Identifier escape character + * + * @var string + */ + protected $_escape_char = '`'; + + // -------------------------------------------------------------------- + /** - * Non-persistent database connection + * Database connection * + * @param bool $persistent * @return object + * @todo SSL support */ - public function db_connect() + public function db_connect($persistent = FALSE) { - return empty($this->port) - ? @new mysqli($this->hostname, $this->username, $this->password, $this->database) - : @new mysqli($this->hostname, $this->username, $this->password, $this->database, $this->port); + // Persistent connection support was added in PHP 5.3.0 + $hostname = ($persistent === TRUE && is_php('5.3')) + ? 'p:'.$this->hostname : $this->hostname; + $port = empty($this->port) ? NULL : $this->port; + $client_flags = ($this->compress === TRUE) ? MYSQLI_CLIENT_COMPRESS : 0; + $mysqli = mysqli_init(); + + return @$mysqli->real_connect($hostname, $this->username, $this->password, $this->database, $port, NULL, $client_flags) + ? $mysqli : FALSE; } // -------------------------------------------------------------------- @@ -79,15 +106,7 @@ class CI_DB_mysqli_driver extends CI_DB { */ public function db_pconnect() { - // Persistent connection support was added in PHP 5.3.0 - if ( ! is_php('5.3')) - { - return $this->db_connect(); - } - - return empty($this->port) - ? @new mysqli('p:'.$this->hostname, $this->username, $this->password, $this->database) - : @new mysqli('p:'.$this->hostname, $this->username, $this->password, $this->database, $this->port); + return $this->db_connect(TRUE); } // -------------------------------------------------------------------- @@ -113,7 +132,7 @@ class CI_DB_mysqli_driver extends CI_DB { /** * Select the database * - * @param string database name + * @param string $database * @return bool */ public function db_select($database = '') @@ -137,7 +156,7 @@ class CI_DB_mysqli_driver extends CI_DB { /** * Set client character set * - * @param string + * @param string $charset * @return bool */ protected function _db_set_charset($charset) @@ -164,7 +183,7 @@ class CI_DB_mysqli_driver extends CI_DB { /** * Execute the query * - * @param string an SQL query + * @param string $sql an SQL query * @return mixed */ protected function _execute($sql) @@ -179,7 +198,7 @@ class CI_DB_mysqli_driver extends CI_DB { * * If needed, each database adapter can prep the query string * - * @param string an SQL query + * @param string $sql an SQL query * @return string */ protected function _prep_query($sql) @@ -199,6 +218,7 @@ class CI_DB_mysqli_driver extends CI_DB { /** * Begin Transaction * + * @param bool $test_mode * @return bool */ public function trans_begin($test_mode = FALSE) @@ -264,8 +284,8 @@ class CI_DB_mysqli_driver extends CI_DB { /** * Escape String * - * @param string - * @param bool whether or not the string will be used in a LIKE condition + * @param string $str + * @param bool $like Whether or not the string will be used in a LIKE condition * @return string */ public function escape_str($str, $like = FALSE) @@ -324,7 +344,7 @@ class CI_DB_mysqli_driver extends CI_DB { * * Generates a platform-specific query string so that the table names can be fetched * - * @param bool + * @param bool $prefix_limit * @return string */ protected function _list_tables($prefix_limit = FALSE) @@ -346,7 +366,7 @@ class CI_DB_mysqli_driver extends CI_DB { * * Generates a platform-specific query string so that the column names can be fetched * - * @param string the table name + * @param string $table * @return string */ protected function _list_columns($table = '') @@ -359,7 +379,7 @@ class CI_DB_mysqli_driver extends CI_DB { /** * Returns an object with field data * - * @param string the table name + * @param string $table * @return object */ public function field_data($table = '') @@ -400,6 +420,14 @@ class CI_DB_mysqli_driver extends CI_DB { */ public function error() { + if ( ! empty($this->conn_id->connect_errno)) + { + return array( + 'code' => $this->conn_id->connect_errno, + 'message' => is_php('5.2.9') ? $this->conn_id->connect_error : mysqli_connect_error() + ); + } + return array('code' => $this->conn_id->errno, 'message' => $this->conn_id->error); } @@ -410,12 +438,12 @@ class CI_DB_mysqli_driver extends CI_DB { * * Generates a platform-specific batch update string from the supplied data * - * @param string the table name - * @param array the update data - * @param array the where clause + * @param string $table Table name + * @param array $values Update data + * @param string $index WHERE key * @return string */ - protected function _update_batch($table, $values, $index, $where = NULL) + protected function _update_batch($table, $values, $index) { $ids = array(); foreach ($values as $key => $val) @@ -439,11 +467,29 @@ class CI_DB_mysqli_driver extends CI_DB { .'ELSE '.$k.' END, '; } - $where = ($where !== '' && count($where) > 0) ? implode(' ', $where).' AND ' : ''; + $this->where($index.' IN('.implode(',', $ids).')', NULL, FALSE); + + return 'UPDATE '.$table.' SET '.substr($cases, 0, -2).$this->_compile_wh('qb_where'); + } + + // -------------------------------------------------------------------- + + /** + * FROM tables + * + * Groups tables in FROM clauses if needed, so there is no confusion + * about operator precedence. + * + * @return string + */ + protected function _from_tables() + { + if ( ! empty($this->qb_join) && count($this->qb_from) > 1) + { + return '('.implode(', ', $this->qb_from).')'; + } - return 'UPDATE '.$table.' SET '.substr($cases, 0, -2) - .' WHERE '.(($where !== '' && count($where) > 0) ? implode(' ', $where).' AND ' : '') - .$index.' IN('.implode(',', $ids).')'; + return implode(', ', $this->qb_from); } // -------------------------------------------------------------------- diff --git a/system/database/drivers/mysqli/mysqli_forge.php b/system/database/drivers/mysqli/mysqli_forge.php index b74c775b2..0732dfea5 100644 --- a/system/database/drivers/mysqli/mysqli_forge.php +++ b/system/database/drivers/mysqli/mysqli_forge.php @@ -1,4 +1,4 @@ -<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed'); +<?php /** * CodeIgniter * @@ -24,6 +24,7 @@ * @since Version 1.0 * @filesource */ +defined('BASEPATH') OR exit('No direct script access allowed'); /** * MySQLi Forge Class @@ -34,12 +35,19 @@ */ class CI_DB_mysqli_forge extends CI_DB_forge { + /** + * CREATE DATABASE statement + * + * @var string + */ protected $_create_database = 'CREATE DATABASE %s CHARACTER SET %s COLLATE %s'; + // -------------------------------------------------------------------- + /** * Process Fields * - * @param mixed the fields + * @param mixed $fields * @return string */ protected function _process_fields($fields) diff --git a/system/database/drivers/mysqli/mysqli_result.php b/system/database/drivers/mysqli/mysqli_result.php index c1ec4da76..15e15cd5f 100644 --- a/system/database/drivers/mysqli/mysqli_result.php +++ b/system/database/drivers/mysqli/mysqli_result.php @@ -1,4 +1,4 @@ -<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed'); +<?php /** * CodeIgniter * @@ -24,6 +24,7 @@ * @since Version 1.0 * @filesource */ +defined('BASEPATH') OR exit('No direct script access allowed'); /** * MySQLi Result Class @@ -130,8 +131,9 @@ class CI_DB_mysqli_result extends CI_DB_result { * * Moves the internal pointer to the desired offset. We call * this internally before fetching results to make sure the - * result set starts at zero + * result set starts at zero. * + * @param int $n * @return bool */ protected function _data_seek($n = 0) @@ -160,7 +162,7 @@ class CI_DB_mysqli_result extends CI_DB_result { * * Returns the result set as an object * - * @param string + * @param string $class_name * @return object */ protected function _fetch_object($class_name = 'stdClass') diff --git a/system/database/drivers/mysqli/mysqli_utility.php b/system/database/drivers/mysqli/mysqli_utility.php index 5d2bdbce0..345691e84 100644 --- a/system/database/drivers/mysqli/mysqli_utility.php +++ b/system/database/drivers/mysqli/mysqli_utility.php @@ -1,4 +1,4 @@ -<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed'); +<?php /** * CodeIgniter * @@ -24,6 +24,7 @@ * @since Version 1.0 * @filesource */ +defined('BASEPATH') OR exit('No direct script access allowed'); /** * MySQLi Utility Class @@ -34,14 +35,33 @@ */ class CI_DB_mysqli_utility extends CI_DB_utility { + /** + * List databases statement + * + * @var string + */ protected $_list_databases = 'SHOW DATABASES'; + + /** + * OPTIMIZE TABLE statement + * + * @var string + */ protected $_optimize_table = 'OPTIMIZE TABLE %s'; + + /** + * REPAIR TABLE statement + * + * @var string + */ protected $_repair_table = 'REPAIR TABLE %s'; + // -------------------------------------------------------------------- + /** - * MySQLi Export + * Export * - * @param array Preferences + * @param array $params Preferences * @return mixed */ protected function _backup($params = array()) diff --git a/system/database/drivers/oci8/oci8_driver.php b/system/database/drivers/oci8/oci8_driver.php index 691247fee..38d2395b6 100644 --- a/system/database/drivers/oci8/oci8_driver.php +++ b/system/database/drivers/oci8/oci8_driver.php @@ -1,4 +1,4 @@ -<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed'); +<?php /** * CodeIgniter * @@ -24,6 +24,7 @@ * @since Version 1.0 * @filesource */ +defined('BASEPATH') OR exit('No direct script access allowed'); /** * oci8 Database Adapter Class @@ -49,36 +50,80 @@ */ class CI_DB_oci8_driver extends CI_DB { + /** + * Database driver + * + * @var string + */ public $dbdriver = 'oci8'; - // The character used for excaping - protected $_escape_char = '"'; + /** + * Statement ID + * + * @var resource + */ + public $stmt_id; - // clause and character used for LIKE escape sequences - protected $_like_escape_str = " ESCAPE '%s' "; - protected $_like_escape_chr = '!'; + /** + * Cursor ID + * + * @var resource + */ + public $curs_id; /** - * The syntax to count rows is slightly different across different - * database engines, so this string appears in each driver and is - * used for the count_all() and count_all_results() functions. + * Commit mode flag + * + * @var int */ - protected $_count_string = 'SELECT COUNT(1) AS '; - protected $_random_keyword = ' ASC'; // not currently supported + public $commit_mode = OCI_COMMIT_ON_SUCCESS; + /** + * Limit used flag + * + * If we use LIMIT, we'll add a field that will + * throw off num_fields later. + * + * @var bool + */ + public $limit_used; + + // -------------------------------------------------------------------- + + /** + * List of reserved identifiers + * + * Identifiers that must NOT be escaped. + * + * @var string[] + */ protected $_reserved_identifiers = array('*', 'rownum'); - // Set "auto commit" by default - public $commit_mode = OCI_COMMIT_ON_SUCCESS; + /** + * ORDER BY random keyword + * + * @var string + */ + protected $_random_keyword = ' ASC'; // not currently supported - // need to track statement id and cursor id - public $stmt_id; - public $curs_id; + /** + * COUNT string + * + * @used-by CI_DB_driver::count_all() + * @used-by CI_DB_query_builder::count_all_results() + * + * @var string + */ + protected $_count_string = 'SELECT COUNT(1) AS '; - // if we use a limit, we will add a field that will - // throw off num_fields later - public $limit_used; + // -------------------------------------------------------------------- + /** + * Class constructor + * + * @param array $params + * @return void + */ public function __construct($params) { parent::__construct($params); @@ -205,7 +250,7 @@ class CI_DB_oci8_driver extends CI_DB { /** * Execute the query * - * @param string an SQL query + * @param string $sql an SQL query * @return resource */ protected function _execute($sql) @@ -224,7 +269,7 @@ class CI_DB_oci8_driver extends CI_DB { /** * Generate a statement ID * - * @param string an SQL query + * @param string $sql an SQL query * @return void */ protected function _set_stmt_id($sql) @@ -304,7 +349,7 @@ class CI_DB_oci8_driver extends CI_DB { /** * Bind parameters * - * @param array + * @param array $params * @return void */ protected function _bind_params($params) @@ -333,7 +378,7 @@ class CI_DB_oci8_driver extends CI_DB { /** * Begin Transaction * - * @param bool + * @param bool $test_mode * @return bool */ public function trans_begin($test_mode = FALSE) @@ -406,8 +451,8 @@ class CI_DB_oci8_driver extends CI_DB { /** * Escape String * - * @param string - * @param bool whether or not the string will be used in a LIKE condition + * @param string $str + * @param bool $like Whether or not the string will be used in a LIKE condition * @return string */ public function escape_str($str, $like = FALSE) @@ -467,7 +512,7 @@ class CI_DB_oci8_driver extends CI_DB { * * Generates a platform-specific query string so that the table names can be fetched * - * @param bool + * @param bool $prefix_limit * @return string */ protected function _list_tables($prefix_limit = FALSE) @@ -490,7 +535,7 @@ class CI_DB_oci8_driver extends CI_DB { * * Generates a platform-specific query string so that the column names can be fetched * - * @param string the table name + * @param string $table * @return string */ protected function _list_columns($table = '') @@ -505,7 +550,7 @@ class CI_DB_oci8_driver extends CI_DB { * * Generates a platform-specific query so that the column data can be retrieved * - * @param string the table name + * @param string $table * @return string */ protected function _field_data($table) @@ -547,29 +592,13 @@ class CI_DB_oci8_driver extends CI_DB { // -------------------------------------------------------------------- /** - * From Tables - * - * This function implicitly groups FROM tables so there is no confusion - * about operator precedence in harmony with SQL standards - * - * @param array - * @return string - */ - protected function _from_tables($tables) - { - return is_array($tables) ? implode(', ', $tables) : $tables; - } - - // -------------------------------------------------------------------- - - /** * Insert_batch statement * * Generates a platform-specific insert string from the supplied data * - * @param string the table name - * @param array the insert keys - * @param array the insert values + * @param string $table Table name + * @param array $keys INSERT keys + * @param array $values INSERT values * @return string */ protected function _insert_batch($table, $keys, $values) @@ -592,10 +621,10 @@ class CI_DB_oci8_driver extends CI_DB { * * Generates a platform-specific truncate string from the supplied data * - * If the database does not support the truncate() command, + * If the database does not support the TRUNCATE statement, * then this method maps to 'DELETE FROM table' * - * @param string the table name + * @param string $table * @return string */ protected function _truncate($table) @@ -610,40 +639,35 @@ class CI_DB_oci8_driver extends CI_DB { * * Generates a platform-specific delete string from the supplied data * - * @param string the table name - * @param array the where clause - * @param array the like clause - * @param string the limit clause + * @param string $table * @return string */ - protected function _delete($table, $where = array(), $like = array(), $limit = FALSE) + protected function _delete($table) { - $conditions = array(); - - empty($where) OR $conditions[] = implode(' ', $where); - empty($like) OR $conditions[] = implode(' ', $like); - empty($limit) OR $conditions[] = 'rownum <= '.$limit; + if ($this->qb_limit) + { + $this->where('rownum <= ',$this->qb_limit, FALSE); + $this->qb_limit = FALSE; + } - return 'DELETE FROM '.$table.(count($conditions) > 0 ? ' WHERE '.implode(' AND ', $conditions) : ''); + return parent::_delete($table); } // -------------------------------------------------------------------- /** - * Limit string + * LIMIT * * Generates a platform-specific LIMIT clause * - * @param string the sql query string - * @param int the number of rows to limit the query to - * @param int the offset value + * @param string $sql SQL Query * @return string */ - protected function _limit($sql, $limit, $offset) + protected function _limit($sql) { $this->limit_used = TRUE; - return 'SELECT * FROM (SELECT inner_query.*, rownum rnum FROM ('.$sql.') inner_query WHERE rownum < '.($offset + $limit + 1).')' - .($offset ? ' WHERE rnum >= '.($offset + 1): ''); + return 'SELECT * FROM (SELECT inner_query.*, rownum rnum FROM ('.$sql.') inner_query WHERE rownum < '.($this->qb_offset + $this->qb_limit + 1).')' + .($this->qb_offset ? ' WHERE rnum >= '.($this->qb_offset + 1): ''); } // -------------------------------------------------------------------- diff --git a/system/database/drivers/oci8/oci8_forge.php b/system/database/drivers/oci8/oci8_forge.php index 92e8c02ed..ad578f830 100644 --- a/system/database/drivers/oci8/oci8_forge.php +++ b/system/database/drivers/oci8/oci8_forge.php @@ -1,4 +1,4 @@ -<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed'); +<?php /** * CodeIgniter * @@ -24,6 +24,7 @@ * @since Version 1.0 * @filesource */ +defined('BASEPATH') OR exit('No direct script access allowed'); /** * Oracle Forge Class @@ -34,10 +35,29 @@ */ class CI_DB_oci8_forge extends CI_DB_forge { + /** + * CREATE DATABASE statement + * + * @var string + */ protected $_create_database = FALSE; + + /** + * DROP DATABASE statement + * + * @var string + */ protected $_drop_database = FALSE; + + /** + * DROP TABLE statement + * + * @var string + */ protected $_drop_table = 'DROP TABLE %s'; + // -------------------------------------------------------------------- + /** * Create Table * diff --git a/system/database/drivers/oci8/oci8_result.php b/system/database/drivers/oci8/oci8_result.php index a2b600e6c..7d5bf5172 100644 --- a/system/database/drivers/oci8/oci8_result.php +++ b/system/database/drivers/oci8/oci8_result.php @@ -1,4 +1,4 @@ -<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed'); +<?php /** * CodeIgniter * @@ -24,6 +24,7 @@ * @since Version 1.0 * @filesource */ +defined('BASEPATH') OR exit('No direct script access allowed'); /** * oci8 Result Class @@ -37,15 +38,40 @@ */ class CI_DB_oci8_result extends CI_DB_result { + /** + * Statement ID + * + * @var resource + */ public $stmt_id; + + /** + * Cursor ID + * + * @var resource + */ public $curs_id; + + /** + * Limit used flag + * + * @var bool + */ public $limit_used; + + /** + * Commit mode flag + * + * @var int + */ public $commit_mode; + // -------------------------------------------------------------------- + /** - * Constructor + * Class constructor * - * @param object + * @param object &$driver_object * @return void */ public function __construct(&$driver_object) @@ -157,7 +183,7 @@ class CI_DB_oci8_result extends CI_DB_result { protected function _fetch_assoc() { $id = ($this->curs_id) ? $this->curs_id : $this->stmt_id; - return oci_fetch_assoc($id); + return @oci_fetch_assoc($id); } // -------------------------------------------------------------------- @@ -167,7 +193,7 @@ class CI_DB_oci8_result extends CI_DB_result { * * Returns the result set as an object * - * @param string + * @param string $class_name * @return object */ protected function _fetch_object($class_name = 'stdClass') @@ -211,9 +237,10 @@ class CI_DB_oci8_result extends CI_DB_result { * some point in the future, but it will only work for resetting the * pointer to zero. * + * @param int $n (ignored) * @return bool */ - protected function _data_seek() + protected function _data_seek($n = 0) { /* The PHP manual says that if OCI_NO_AUTO_COMMIT mode * is used, and oci_rollback() and/or oci_commit() are diff --git a/system/database/drivers/oci8/oci8_utility.php b/system/database/drivers/oci8/oci8_utility.php index 0183eda26..e5aae8132 100644 --- a/system/database/drivers/oci8/oci8_utility.php +++ b/system/database/drivers/oci8/oci8_utility.php @@ -1,4 +1,4 @@ -<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed'); +<?php /** * CodeIgniter * @@ -24,6 +24,7 @@ * @since Version 1.0 * @filesource */ +defined('BASEPATH') OR exit('No direct script access allowed'); /** * Oracle Utility Class @@ -34,12 +35,17 @@ */ class CI_DB_oci8_utility extends CI_DB_utility { + /** + * List databases statement + * + * @var string + */ protected $_list_databases = 'SELECT username FROM dba_users'; // Schemas are actual usernames /** - * Oracle Export + * Export * - * @param array Preferences + * @param array $params Preferences * @return mixed */ protected function _backup($params = array()) diff --git a/system/database/drivers/odbc/odbc_driver.php b/system/database/drivers/odbc/odbc_driver.php index 8f0a474b0..88df615e6 100644 --- a/system/database/drivers/odbc/odbc_driver.php +++ b/system/database/drivers/odbc/odbc_driver.php @@ -1,4 +1,4 @@ -<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed'); +<?php /** * CodeIgniter * @@ -24,6 +24,7 @@ * @since Version 1.0 * @filesource */ +defined('BASEPATH') OR exit('No direct script access allowed'); /** * ODBC Database Adapter Class @@ -40,17 +41,46 @@ */ class CI_DB_odbc_driver extends CI_DB { + /** + * Database driver + * + * @var string + */ public $dbdriver = 'odbc'; - // the character used to excape - not necessary for ODBC + /** + * Database schema + * + * @var string + */ + public $schema = 'public'; + + // -------------------------------------------------------------------- + + /** + * Identifier escape character + * + * Must be empty for ODBC. + * + * @var string + */ protected $_escape_char = ''; - // clause and character used for LIKE escape sequences + /** + * ESCAPE statement string + * + * @var string + */ protected $_like_escape_str = " {escape '%s'} "; - protected $_like_escape_chr = '!'; - protected $_random_keyword; + // -------------------------------------------------------------------- + /** + * Class constructor + * + * @param array $params + * @return void + */ public function __construct($params) { parent::__construct($params); @@ -64,6 +94,8 @@ class CI_DB_odbc_driver extends CI_DB { } } + // -------------------------------------------------------------------- + /** * Non-persistent database connection * @@ -91,7 +123,7 @@ class CI_DB_odbc_driver extends CI_DB { /** * Execute the query * - * @param string an SQL query + * @param string $sql an SQL query * @return resource */ protected function _execute($sql) @@ -104,6 +136,7 @@ class CI_DB_odbc_driver extends CI_DB { /** * Begin Transaction * + * @param bool $test_mode * @return bool */ public function trans_begin($test_mode = FALSE) @@ -167,8 +200,8 @@ class CI_DB_odbc_driver extends CI_DB { /** * Escape String * - * @param string - * @param bool whether or not the string will be used in a LIKE condition + * @param string $str + * @param bool $like Whether or not the string will be used in a LIKE condition * @return string */ public function escape_str($str, $like = FALSE) @@ -227,17 +260,17 @@ class CI_DB_odbc_driver extends CI_DB { * * Generates a platform-specific query string so that the table names can be fetched * - * @param bool + * @param bool $prefix_limit * @return string */ protected function _list_tables($prefix_limit = FALSE) { - $sql = 'SHOW TABLES FROM '.$this->database; + $sql = "SELECT table_name FROM information_schema.tables WHERE table_schema = '".$this->schema."'"; if ($prefix_limit !== FALSE && $this->dbprefix !== '') { - //$sql .= " LIKE '".$this->escape_like_str($this->dbprefix)."%' ".sprintf($this->_like_escape_str, $this->_like_escape_chr); - return FALSE; // not currently supported + return $sql." AND table_name LIKE '".$this->escape_like_str($this->dbprefix)."%' " + .sprintf($this->_like_escape_str, $this->_like_escape_chr); } return $sql; @@ -250,7 +283,7 @@ class CI_DB_odbc_driver extends CI_DB { * * Generates a platform-specific query string so that the column names can be fetched * - * @param string the table name + * @param string $table * @return string */ protected function _list_columns($table = '') @@ -265,7 +298,7 @@ class CI_DB_odbc_driver extends CI_DB { * * Generates a platform-specific query so that the column data can be retrieved * - * @param string the table name + * @param string $table * @return string */ protected function _field_data($table) @@ -291,17 +324,19 @@ class CI_DB_odbc_driver extends CI_DB { // -------------------------------------------------------------------- /** - * From Tables + * Update statement * - * This function implicitly groups FROM tables so there is no confusion - * about operator precedence in harmony with SQL standards + * Generates a platform-specific update string from the supplied data * - * @param array + * @param string $table + * @param array $values * @return string - */ - protected function _from_tables($tables) + */ + protected function _update($table, $values) { - return is_array($tables) ? implode(', ', $tables) : $tables; + $this->qb_limit = FALSE; + $this->qb_orderby = array(); + return parent::_update($table, $values); } // -------------------------------------------------------------------- @@ -311,10 +346,10 @@ class CI_DB_odbc_driver extends CI_DB { * * Generates a platform-specific truncate string from the supplied data * - * If the database does not support the truncate() command, + * If the database does not support the TRUNCATE statement, * then this method maps to 'DELETE FROM table' * - * @param string the table name + * @param string $table * @return string */ protected function _truncate($table) @@ -325,6 +360,22 @@ class CI_DB_odbc_driver extends CI_DB { // -------------------------------------------------------------------- /** + * Delete statement + * + * Generates a platform-specific delete string from the supplied data + * + * @param string $table + * @return string + */ + protected function _delete($table) + { + $this->qb_limit = FALSE; + return parent::_delete($table); + } + + // -------------------------------------------------------------------- + + /** * Close DB Connection * * @return void diff --git a/system/database/drivers/odbc/odbc_forge.php b/system/database/drivers/odbc/odbc_forge.php index d17b046ee..699ce996c 100644 --- a/system/database/drivers/odbc/odbc_forge.php +++ b/system/database/drivers/odbc/odbc_forge.php @@ -1,4 +1,4 @@ -<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed'); +<?php /** * CodeIgniter * @@ -24,6 +24,7 @@ * @since Version 1.0 * @filesource */ +defined('BASEPATH') OR exit('No direct script access allowed'); /** * ODBC Forge Class @@ -34,8 +35,15 @@ */ class CI_DB_odbc_forge extends CI_DB_forge { + /** + * DROP TABLE statement + * + * @var string + */ protected $_drop_table = 'DROP TABLE %s'; + // -------------------------------------------------------------------- + /** * Create Table * diff --git a/system/database/drivers/odbc/odbc_result.php b/system/database/drivers/odbc/odbc_result.php index 48dc48dd9..2c50c255b 100644 --- a/system/database/drivers/odbc/odbc_result.php +++ b/system/database/drivers/odbc/odbc_result.php @@ -1,4 +1,4 @@ -<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed'); +<?php /** * CodeIgniter * @@ -24,6 +24,7 @@ * @since Version 1.0 * @filesource */ +defined('BASEPATH') OR exit('No direct script access allowed'); /** * ODBC Result Class @@ -165,7 +166,7 @@ class CI_DB_odbc_result extends CI_DB_result { * * Returns the result set as an object * - * @param string + * @param string $class_name * @return object */ protected function _fetch_object($class_name = 'stdClass') @@ -198,11 +199,11 @@ if ( ! function_exists('odbc_fetch_array')) * Emulates the native odbc_fetch_array() function when * it is not available (odbc_fetch_array() requires unixODBC) * - * @param resource - * @param int + * @param resource &$result + * @param int $rownumber * @return array */ - function odbc_fetch_array(& $result, $rownumber = 1) + function odbc_fetch_array(&$result, $rownumber = 1) { $rs = array(); if ( ! odbc_fetch_into($result, $rs, $rownumber)) @@ -231,11 +232,11 @@ if ( ! function_exists('odbc_fetch_object')) * Emulates the native odbc_fetch_object() function when * it is not available. * - * @param resource - * @param int + * @param resource &$result + * @param int $rownumber * @return object */ - function odbc_fetch_object(& $result, $rownumber = 1) + function odbc_fetch_object(&$result, $rownumber = 1) { $rs = array(); if ( ! odbc_fetch_into($result, $rs, $rownumber)) diff --git a/system/database/drivers/odbc/odbc_utility.php b/system/database/drivers/odbc/odbc_utility.php index 224d48d2b..bfa94f469 100644 --- a/system/database/drivers/odbc/odbc_utility.php +++ b/system/database/drivers/odbc/odbc_utility.php @@ -1,4 +1,4 @@ -<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed'); +<?php /** * CodeIgniter * @@ -24,6 +24,7 @@ * @since Version 1.0 * @filesource */ +defined('BASEPATH') OR exit('No direct script access allowed'); /** * ODBC Utility Class @@ -34,12 +35,10 @@ */ class CI_DB_odbc_utility extends CI_DB_utility { - protected $_list_databases = FALSE; - /** - * ODBC Export + * Export * - * @param array Preferences + * @param array $params Preferences * @return mixed */ protected function _backup($params = array()) diff --git a/system/database/drivers/pdo/pdo_driver.php b/system/database/drivers/pdo/pdo_driver.php index 705b16560..57a3c5c98 100644 --- a/system/database/drivers/pdo/pdo_driver.php +++ b/system/database/drivers/pdo/pdo_driver.php @@ -1,4 +1,4 @@ -<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed'); +<?php /** * CodeIgniter * @@ -24,6 +24,7 @@ * @since Version 2.1.0 * @filesource */ +defined('BASEPATH') OR exit('No direct script access allowed'); /** * PDO Database Adapter Class @@ -40,28 +41,35 @@ */ class CI_DB_pdo_driver extends CI_DB { + /** + * Database driver + * + * @var string + */ public $dbdriver = 'pdo'; - // The character used to escaping - protected $_escape_char = '"'; - - // clause and character used for LIKE escape sequences - protected $_like_escape_str = " ESCAPE '%s' "; - protected $_like_escape_chr = '!'; - - protected $_random_keyword; - + /** + * Transaction enabled flag + * + * @var bool + */ public $trans_enabled = FALSE; - // need to track the PDO options + /** + * PDO Options + * + * @var array + */ public $options = array(); + // -------------------------------------------------------------------- + /** - * Constructor + * Class constructor * - * Validates the DSN string and/or detects the subdriver + * Validates the DSN string and/or detects the subdriver. * - * @param array + * @param array $params * @return void */ public function __construct($params) @@ -107,9 +115,9 @@ class CI_DB_pdo_driver extends CI_DB { // -------------------------------------------------------------------- /** - * Non-persistent database connection + * Database connection * - * @param bool + * @param bool $persistent * @return object */ public function db_connect($persistent = FALSE) @@ -174,7 +182,7 @@ class CI_DB_pdo_driver extends CI_DB { /** * Execute the query * - * @param string an SQL query + * @param string $sql SQL query * @return mixed */ protected function _execute($sql) @@ -187,6 +195,7 @@ class CI_DB_pdo_driver extends CI_DB { /** * Begin Transaction * + * @param bool $test_mode * @return bool */ public function trans_begin($test_mode = FALSE) @@ -246,8 +255,8 @@ class CI_DB_pdo_driver extends CI_DB { /** * Escape String * - * @param string - * @param bool whether or not the string will be used in a LIKE condition + * @param string $str + * @param bool $like Whether or not the string will be used in a LIKE condition * @return string */ public function escape_str($str, $like = FALSE) @@ -299,7 +308,7 @@ class CI_DB_pdo_driver extends CI_DB { /** * Insert ID * - * @param string + * @param string $name * @return int */ public function insert_id($name = NULL) @@ -314,7 +323,7 @@ class CI_DB_pdo_driver extends CI_DB { * * Generates a platform-specific query so that the column data can be retrieved * - * @param string the table name + * @param string $table * @return string */ protected function _field_data($table) @@ -358,16 +367,14 @@ class CI_DB_pdo_driver extends CI_DB { * * Generates a platform-specific batch update string from the supplied data * - * @param string the table name - * @param array the update data - * @param array the where clause + * @param string $table Table name + * @param array $values Update data + * @param string $index WHERE key * @return string */ - protected function _update_batch($table, $values, $index, $where = NULL) + protected function _update_batch($table, $values, $index) { $ids = array(); - $where = ($where !== '' && count($where) >=1) ? implode(' ', $where).' AND ' : ''; - foreach ($values as $key => $val) { $ids[] = $val[$index]; @@ -381,9 +388,7 @@ class CI_DB_pdo_driver extends CI_DB { } } - $sql = 'UPDATE '.$table.' SET '; $cases = ''; - foreach ($final as $k => $v) { $cases .= $k.' = CASE '."\n"; @@ -396,10 +401,9 @@ class CI_DB_pdo_driver extends CI_DB { $cases .= 'ELSE '.$k.' END, '; } - $sql .= substr($cases, 0, -2); - $sql .= ' WHERE '.$where.$index.' IN ('.implode(',', $ids).')'; + $this->where($index.' IN('.implode(',', $ids).')', NULL, FALSE); - return $sql; + return 'UPDATE '.$table.' SET '.substr($cases, 0, -2).$this->_compile_wh('qb_where'); } // -------------------------------------------------------------------- @@ -409,10 +413,10 @@ class CI_DB_pdo_driver extends CI_DB { * * Generates a platform-specific truncate string from the supplied data * - * If the database does not support the truncate() command, + * If the database does not support the TRUNCATE statement, * then this method maps to 'DELETE FROM table' * - * @param string the table name + * @param string $table * @return string */ protected function _truncate($table) @@ -423,4 +427,4 @@ class CI_DB_pdo_driver extends CI_DB { } /* End of file pdo_driver.php */ -/* Location: ./system/database/drivers/pdo/pdo_driver.php */ +/* Location: ./system/database/drivers/pdo/pdo_driver.php */
\ No newline at end of file diff --git a/system/database/drivers/pdo/pdo_forge.php b/system/database/drivers/pdo/pdo_forge.php index 34a6ee44e..e77970cf2 100644 --- a/system/database/drivers/pdo/pdo_forge.php +++ b/system/database/drivers/pdo/pdo_forge.php @@ -1,4 +1,4 @@ -<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed'); +<?php /** * CodeIgniter * @@ -24,6 +24,7 @@ * @since Version 2.1.0 * @filesource */ +defined('BASEPATH') OR exit('No direct script access allowed'); /** * PDO Forge Class @@ -34,8 +35,15 @@ */ class CI_DB_pdo_forge extends CI_DB_forge { + /** + * DROP TABLE statement + * + * @var string + */ protected $_drop_table = 'DROP TABLE %s'; + // -------------------------------------------------------------------- + /** * Create Table * diff --git a/system/database/drivers/pdo/pdo_result.php b/system/database/drivers/pdo/pdo_result.php index 444406986..1de5a47ec 100644 --- a/system/database/drivers/pdo/pdo_result.php +++ b/system/database/drivers/pdo/pdo_result.php @@ -1,4 +1,4 @@ -<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed'); +<?php /** * CodeIgniter * @@ -24,6 +24,7 @@ * @since Version 1.0 * @filesource */ +defined('BASEPATH') OR exit('No direct script access allowed'); /** * PDO Result Class @@ -205,7 +206,7 @@ class CI_DB_pdo_result extends CI_DB_result { * * Returns the result set as an object * - * @param string + * @param string $class_name * @return object */ protected function _fetch_object($class_name = 'stdClass') diff --git a/system/database/drivers/pdo/pdo_utility.php b/system/database/drivers/pdo/pdo_utility.php index 930842118..03b309249 100644 --- a/system/database/drivers/pdo/pdo_utility.php +++ b/system/database/drivers/pdo/pdo_utility.php @@ -1,4 +1,4 @@ -<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed'); +<?php /** * CodeIgniter * @@ -24,6 +24,7 @@ * @since Version 2.1.0 * @filesource */ +defined('BASEPATH') OR exit('No direct script access allowed'); /** * PDO Utility Class @@ -34,12 +35,10 @@ */ class CI_DB_pdo_utility extends CI_DB_utility { - protected $_list_databases = FALSE; - /** - * PDO Export + * Export * - * @param array Preferences + * @param array $params Preferences * @return mixed */ protected function _backup($params = array()) diff --git a/system/database/drivers/pdo/subdrivers/pdo_4d_driver.php b/system/database/drivers/pdo/subdrivers/pdo_4d_driver.php index e287f5c63..6ebd92a9b 100644 --- a/system/database/drivers/pdo/subdrivers/pdo_4d_driver.php +++ b/system/database/drivers/pdo/subdrivers/pdo_4d_driver.php @@ -1,4 +1,4 @@ -<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed'); +<?php /** * CodeIgniter * @@ -24,6 +24,7 @@ * @since Version 3.0.0 * @filesource */ +defined('BASEPATH') OR exit('No direct script access allowed'); /** * PDO 4D Database Adapter Class @@ -40,19 +41,28 @@ */ class CI_DB_pdo_4d_driver extends CI_DB_pdo_driver { + /** + * Sub-driver + * + * @var string + */ public $subdriver = '4d'; - // The character used for escaping + /** + * Identifier escape character + * + * @var string[] + */ protected $_escape_char = array('[', ']'); - protected $_random_keyword = ' RAND()'; + // -------------------------------------------------------------------- /** - * Constructor + * Class constructor * * Builds the DSN if not already set. * - * @param array + * @param array $params * @return void */ public function __construct($params) @@ -80,7 +90,7 @@ class CI_DB_pdo_4d_driver extends CI_DB_pdo_driver { * * Generates a platform-specific query string so that the table names can be fetched * - * @param bool + * @param bool $prefix_limit * @return string */ protected function _list_tables($prefix_limit = FALSE) @@ -103,7 +113,7 @@ class CI_DB_pdo_4d_driver extends CI_DB_pdo_driver { * * Generates a platform-specific query string so that the column names can be fetched * - * @param string the table name + * @param string $table * @return string */ protected function _list_columns($table = '') @@ -119,7 +129,7 @@ class CI_DB_pdo_4d_driver extends CI_DB_pdo_driver { * * Generates a platform-specific query so that the column data can be retrieved * - * @param string the table name + * @param string $table * @return string */ protected function _field_data($table) @@ -130,49 +140,19 @@ class CI_DB_pdo_4d_driver extends CI_DB_pdo_driver { // -------------------------------------------------------------------- /** - * From Tables - * - * This function implicitly groups FROM tables so there is no confusion - * about operator precedence in harmony with SQL standards - * - * @param array - * @return string - */ - protected function _from_tables($tables) - { - return is_array($tables) ? implode(', ', $tables) : $tables; - } - - // -------------------------------------------------------------------- - - /** * Update statement * * Generates a platform-specific update string from the supplied data * - * @param string the table name - * @param array the update data - * @param array the where clause - * @param array the orderby clause (ignored) - * @param array the limit clause (ignored) - * @param array the like clause + * @param string $table + * @param array $values * @return string */ - protected function _update($table, $values, $where, $orderby = array(), $limit = FALSE, $like = array()) + protected function _update($table, $values) { - foreach ($values as $key => $val) - { - $valstr[] = $key.' = '.$val; - } - - $where = empty($where) ? '' : ' WHERE '.implode(' ', $where); - - if ( ! empty($like)) - { - $where .= ($where === '' ? ' WHERE ' : ' AND ').implode(' ', $like); - } - - return 'UPDATE '.$table.' SET '.implode(', ', $valstr).$where; + $this->qb_limit = FALSE; + $this->qb_orderby = array(); + return parent::_update($table, $values); } // -------------------------------------------------------------------- @@ -182,39 +162,28 @@ class CI_DB_pdo_4d_driver extends CI_DB_pdo_driver { * * Generates a platform-specific delete string from the supplied data * - * @param string the table name - * @param array the where clause - * @param array the like clause - * @param string the limit clause (ignored) + * @param string $table * @return string */ - protected function _delete($table, $where = array(), $like = array(), $limit = FALSE) + protected function _delete($table) { - $conditions = array(); - - empty($where) OR $conditions[] = implode(' ', $where); - empty($like) OR $conditions[] = implode(' ', $like); - - $conditions = (count($conditions) > 0) ? ' WHERE '.implode(' AND ', $conditions) : ''; - - return 'DELETE FROM '.$table.$conditions; + $this->qb_limit = FALSE; + return parent::_delete($table); } // -------------------------------------------------------------------- /** - * Limit string + * LIMIT * * Generates a platform-specific LIMIT clause * - * @param string the sql query string - * @param int the number of rows to limit the query to - * @param int the offset value + * @param string $sql SQL Query * @return string */ - protected function _limit($sql, $limit, $offset) + protected function _limit($sql) { - return $sql.' LIMIT '.$limit.($offset ? ' OFFSET '.$offset : ''); + return $sql.' LIMIT '.$this->qb_limit.($this->qb_offset ? ' OFFSET '.$this->qb_offset : ''); } } diff --git a/system/database/drivers/pdo/subdrivers/pdo_cubrid_driver.php b/system/database/drivers/pdo/subdrivers/pdo_cubrid_driver.php index 05eeacfe6..4f762b91c 100644 --- a/system/database/drivers/pdo/subdrivers/pdo_cubrid_driver.php +++ b/system/database/drivers/pdo/subdrivers/pdo_cubrid_driver.php @@ -1,4 +1,4 @@ -<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed'); +<?php /** * CodeIgniter * @@ -24,6 +24,7 @@ * @since Version 3.0.0 * @filesource */ +defined('BASEPATH') OR exit('No direct script access allowed'); /** * PDO CUBRID Database Adapter Class @@ -40,22 +41,28 @@ */ class CI_DB_pdo_cubrid_driver extends CI_DB_pdo_driver { + /** + * Sub-driver + * + * @var string + */ public $subdriver = 'cubrid'; + /** + * Identifier escape character + * + * @var string + */ protected $_escape_char = '`'; - // clause and character used for LIKE escape sequences - not used in CUBRID - protected $_like_escape_str = ''; - protected $_like_escape_chr = '\\'; - - protected $_random_keyword = ' RAND()'; + // -------------------------------------------------------------------- /** - * Constructor + * Class constructor * * Builds the DSN if not already set. * - * @param array + * @param array $params * @return void */ public function __construct($params) @@ -79,7 +86,7 @@ class CI_DB_pdo_cubrid_driver extends CI_DB_pdo_driver { * * Generates a platform-specific query string so that the table names can be fetched * - * @param bool + * @param bool $prefix_limit * @return string */ protected function _list_tables($prefix_limit = FALSE) @@ -101,7 +108,7 @@ class CI_DB_pdo_cubrid_driver extends CI_DB_pdo_driver { * * Generates a platform-specific query string so that the column names can be fetched * - * @param string the table name + * @param string $table * @return string */ protected function _list_columns($table = '') @@ -116,7 +123,7 @@ class CI_DB_pdo_cubrid_driver extends CI_DB_pdo_driver { * * Generates a platform-specific query so that the column data can be retrieved * - * @param string the table name + * @param string $table * @return string */ protected function _field_data($table) @@ -131,12 +138,12 @@ class CI_DB_pdo_cubrid_driver extends CI_DB_pdo_driver { * * Generates a platform-specific batch update string from the supplied data * - * @param string the table name - * @param array the update data - * @param array the where clause + * @param string $table Table name + * @param array $values Update data + * @param string $index WHERE key * @return string */ - protected function _update_batch($table, $values, $index, $where = NULL) + protected function _update_batch($table, $values, $index) { $ids = array(); foreach ($values as $key => $val) @@ -160,9 +167,9 @@ class CI_DB_pdo_cubrid_driver extends CI_DB_pdo_driver { .'ELSE '.$k.' END), '; } - return 'UPDATE '.$table.' SET '.substr($cases, 0, -2) - .' WHERE '.(($where !== '' && count($where) > 0) ? implode(' ', $where).' AND ' : '') - .$index.' IN('.implode(',', $ids).')'; + $this->where($index.' IN('.implode(',', $ids).')', NULL, FALSE); + + return 'UPDATE '.$table.' SET '.substr($cases, 0, -2).$this->_compile_wh('qb_where'); } // -------------------------------------------------------------------- @@ -172,10 +179,10 @@ class CI_DB_pdo_cubrid_driver extends CI_DB_pdo_driver { * * Generates a platform-specific truncate string from the supplied data * - * If the database does not support the truncate() command, + * If the database does not support the TRUNCATE statement, * then this method maps to 'DELETE FROM table' * - * @param string the table name + * @param string $table * @return string */ protected function _truncate($table) @@ -183,6 +190,26 @@ class CI_DB_pdo_cubrid_driver extends CI_DB_pdo_driver { return 'TRUNCATE '.$table; } + // -------------------------------------------------------------------- + + /** + * FROM tables + * + * Groups tables in FROM clauses if needed, so there is no confusion + * about operator precedence. + * + * @return string + */ + protected function _from_tables() + { + if ( ! empty($this->qb_join) && count($this->qb_from) > 1) + { + return '('.implode(', ', $this->qb_from).')'; + } + + return implode(', ', $this->qb_from); + } + } /* End of file pdo_cubrid_driver.php */ diff --git a/system/database/drivers/pdo/subdrivers/pdo_dblib_driver.php b/system/database/drivers/pdo/subdrivers/pdo_dblib_driver.php index 7060c9eb9..6ac32fc16 100644 --- a/system/database/drivers/pdo/subdrivers/pdo_dblib_driver.php +++ b/system/database/drivers/pdo/subdrivers/pdo_dblib_driver.php @@ -1,4 +1,4 @@ -<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed'); +<?php /** * CodeIgniter * @@ -24,6 +24,7 @@ * @since Version 3.0.0 * @filesource */ +defined('BASEPATH') OR exit('No direct script access allowed'); /** * PDO DBLIB Database Adapter Class @@ -40,18 +41,40 @@ */ class CI_DB_pdo_dblib_driver extends CI_DB_pdo_driver { + /** + * Sub-driver + * + * @var string + */ public $subdriver = 'dblib'; + // -------------------------------------------------------------------- + + /** + * ORDER BY random keyword + * + * @var string + */ protected $_random_keyword = ' NEWID()'; + /** + * Quoted identifier flag + * + * Whether to use SQL-92 standard quoted identifier + * (double quotes) or brackets for identifier escaping. + * + * @var bool + */ protected $_quoted_identifier; + // -------------------------------------------------------------------- + /** - * Constructor + * Class constructor * * Builds the DSN if not already set. * - * @param array + * @param array $params * @return void */ public function __construct($params) @@ -85,9 +108,9 @@ class CI_DB_pdo_dblib_driver extends CI_DB_pdo_driver { // -------------------------------------------------------------------- /** - * Non-persistent database connection + * Database connection * - * @param bool + * @param bool $persistent * @return object */ public function db_connect($persistent = FALSE) @@ -115,7 +138,7 @@ class CI_DB_pdo_dblib_driver extends CI_DB_pdo_driver { * * Generates a platform-specific query string so that the table names can be fetched * - * @param bool + * @param bool $prefix_limit * @return string */ protected function _list_tables($prefix_limit = FALSE) @@ -140,7 +163,7 @@ class CI_DB_pdo_dblib_driver extends CI_DB_pdo_driver { * * Generates a platform-specific query string so that the column names can be fetched * - * @param string the table name + * @param string $table * @return string */ protected function _list_columns($table = '') @@ -153,49 +176,19 @@ class CI_DB_pdo_dblib_driver extends CI_DB_pdo_driver { // -------------------------------------------------------------------- /** - * From Tables - * - * This function implicitly groups FROM tables so there is no confusion - * about operator precedence in harmony with SQL standards - * - * @param array - * @return string - */ - protected function _from_tables($tables) - { - return is_array($tables) ? implode(', ', $tables) : $tables; - } - - // -------------------------------------------------------------------- - - /** * Update statement * * Generates a platform-specific update string from the supplied data * - * @param string the table name - * @param array the update data - * @param array the where clause - * @param array the orderby clause (ignored) - * @param array the limit clause (ignored) - * @param array the like clause + * @param string $table + * @param array $values * @return string */ - protected function _update($table, $values, $where, $orderby = array(), $limit = FALSE, $like = array()) + protected function _update($table, $values) { - foreach ($values as $key => $val) - { - $valstr[] = $key.' = '.$val; - } - - $where = empty($where) ? '' : ' WHERE '.implode(' ', $where); - - if ( ! empty($like)) - { - $where .= ($where === '' ? ' WHERE ' : ' AND ').implode(' ', $like); - } - - return 'UPDATE '.$table.' SET '.implode(', ', $valstr).$where; + $this->qb_limit = FALSE; + $this->qb_orderby = array(); + return parent::_update($table, $values); } // -------------------------------------------------------------------- @@ -205,55 +198,65 @@ class CI_DB_pdo_dblib_driver extends CI_DB_pdo_driver { * * Generates a platform-specific delete string from the supplied data * - * @param string the table name - * @param array the where clause - * @param array the like clause - * @param string the limit clause + * @param string $table * @return string */ - protected function _delete($table, $where = array(), $like = array(), $limit = FALSE) + protected function _delete($table) { - $conditions = array(); - - empty($where) OR $conditions[] = implode(' ', $where); - empty($like) OR $conditions[] = implode(' ', $like); - - $conditions = (count($conditions) > 0) ? ' WHERE '.implode(' AND ', $conditions) : ''; + if ($this->qb_limit) + { + return 'WITH ci_delete AS (SELECT TOP '.$this->qb_limit.' * FROM '.$table.$this->_compile_wh('qb_where').') DELETE FROM ci_delete'; + } - return ($limit) - ? 'WITH ci_delete AS (SELECT TOP '.$limit.' * FROM '.$table.$conditions.') DELETE FROM ci_delete' - : 'DELETE FROM '.$table.$conditions; + return parent::_delete($table); } // -------------------------------------------------------------------- /** - * Limit string + * LIMIT * * Generates a platform-specific LIMIT clause * - * @param string the sql query string - * @param int the number of rows to limit the query to - * @param int the offset value + * @param string $sql SQL Query * @return string */ - protected function _limit($sql, $limit, $offset) + protected function _limit($sql) { - $limit = $offset + $limit; + $limit = $this->qb_offset + $this->qb_limit; // As of SQL Server 2005 (9.0.*) ROW_NUMBER() is supported, // however an ORDER BY clause is required for it to work - if (version_compare($this->version(), '9', '>=') && $offset && ! empty($this->qb_orderby)) + if (version_compare($this->version(), '9', '>=') && $this->qb_offset && ! empty($this->qb_orderby)) { - $orderby = 'ORDER BY '.implode(', ', $this->qb_orderby); + $orderby = $this->_compile_order_by(); // We have to strip the ORDER BY clause - $sql = trim(substr($sql, 0, strrpos($sql, 'ORDER BY '.$orderby))); + $sql = trim(substr($sql, 0, strrpos($sql, $orderby))); + + // Get the fields to select from our subquery, so that we can avoid CI_rownum appearing in the actual results + if (count($this->qb_select) === 0) + { + $select = '*'; // Inevitable + } + else + { + // Use only field names and their aliases, everything else is out of our scope. + $select = array(); + $field_regexp = ($this->_quoted_identifier) + ? '("[^\"]+")' : '(\[[^\]]+\])'; + for ($i = 0, $c = count($this->qb_select); $i < $c; $i++) + { + $select[] = preg_match('/(?:\s|\.)'.$field_regexp.'$/i', $this->qb_select[$i], $m) + ? $m[1] : $this->qb_select[$i]; + } + $select = implode(', ', $select); + } - return 'SELECT '.(count($this->qb_select) === 0 ? '*' : implode(', ', $this->qb_select))." FROM (\n" - .preg_replace('/^(SELECT( DISTINCT)?)/i', '\\1 ROW_NUMBER() OVER('.$orderby.') AS '.$this->escape_identifiers('CI_rownum').', ', $sql) - ."\n) ".$this->escape_identifiers('CI_subquery') - ."\nWHERE ".$this->escape_identifiers('CI_rownum').' BETWEEN '.((int) $offset + 1).' AND '.$limit; + return 'SELECT '.$select." FROM (\n\n" + .preg_replace('/^(SELECT( DISTINCT)?)/i', '\\1 ROW_NUMBER() OVER('.trim($orderby).') AS '.$this->escape_identifiers('CI_rownum').', ', $sql) + ."\n\n) ".$this->escape_identifiers('CI_subquery') + ."\nWHERE ".$this->escape_identifiers('CI_rownum').' BETWEEN '.($this->qb_offset + 1).' AND '.$limit; } return preg_replace('/(^\SELECT (DISTINCT)?)/i','\\1 TOP '.$limit.' ', $sql); @@ -262,4 +265,4 @@ class CI_DB_pdo_dblib_driver extends CI_DB_pdo_driver { } /* End of file pdo_dblib_driver.php */ -/* Location: ./system/database/drivers/pdo/subdrivers/pdo_dblib_driver.php */ +/* Location: ./system/database/drivers/pdo/subdrivers/pdo_dblib_driver.php */
\ No newline at end of file diff --git a/system/database/drivers/pdo/subdrivers/pdo_firebird_driver.php b/system/database/drivers/pdo/subdrivers/pdo_firebird_driver.php index c074a9a78..83b9648c1 100644 --- a/system/database/drivers/pdo/subdrivers/pdo_firebird_driver.php +++ b/system/database/drivers/pdo/subdrivers/pdo_firebird_driver.php @@ -1,4 +1,4 @@ -<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed'); +<?php /** * CodeIgniter * @@ -24,6 +24,7 @@ * @since Version 3.0.0 * @filesource */ +defined('BASEPATH') OR exit('No direct script access allowed'); /** * PDO Firebird Database Adapter Class @@ -40,21 +41,30 @@ */ class CI_DB_pdo_firebird_driver extends CI_DB_pdo_driver { + /** + * Sub-driver + * + * @var string + */ public $subdriver = 'firebird'; + // -------------------------------------------------------------------- + /** - * The syntax to count rows is slightly different across different - * database engines, so this string appears in each driver and is - * used for the count_all() and count_all_results() functions. + * ORDER BY random keyword + * + * @var string */ - protected $_random_keyword = ' RANDOM()'; // Currently not supported + protected $_random_keyword = ' RANDOM()'; + + // -------------------------------------------------------------------- /** - * Constructor + * Class constructor * * Builds the DSN if not already set. * - * @param array + * @param array $params * @return void */ public function __construct($params) @@ -90,7 +100,7 @@ class CI_DB_pdo_firebird_driver extends CI_DB_pdo_driver { * * Generates a platform-specific query string so that the table names can be fetched * - * @param bool + * @param bool $prefix_limit * @return string */ protected function _list_tables($prefix_limit = FALSE) @@ -113,7 +123,7 @@ class CI_DB_pdo_firebird_driver extends CI_DB_pdo_driver { * * Generates a platform-specific query string so that the column names can be fetched * - * @param string the table name + * @param string $table * @return string */ protected function _list_columns($table = '') @@ -128,7 +138,7 @@ class CI_DB_pdo_firebird_driver extends CI_DB_pdo_driver { * * Generates a platform-specific query so that the column data can be retrieved * - * @param string the table name + * @param string $table * @return string */ protected function _field_data($table) @@ -139,51 +149,18 @@ class CI_DB_pdo_firebird_driver extends CI_DB_pdo_driver { // -------------------------------------------------------------------- /** - * From Tables - * - * This function implicitly groups FROM tables so there is no confusion - * about operator precedence in harmony with SQL standards - * - * @param array - * @return string - */ - protected function _from_tables($tables) - { - return is_array($tables) ? implode(', ', $tables) : $tables; - } - - // -------------------------------------------------------------------- - - /** * Update statement * * Generates a platform-specific update string from the supplied data * - * @param string the table name - * @param array the update data - * @param array the where clause - * @param array the orderby clause - * @param array the limit clause (ignored) - * @param array the like clause + * @param string $table + * @param array $values * @return string */ - protected function _update($table, $values, $where, $orderby = array(), $limit = FALSE, $like = array()) + protected function _update($table, $values) { - foreach ($values as $key => $val) - { - $valstr[] = $key.' = '.$val; - } - - $where = empty($where) ? '' : ' WHERE '.implode(' ', $where); - - if ( ! empty($like)) - { - $where .= ($where === '' ? ' WHERE ' : ' AND ').implode(' ', $like); - } - - return 'UPDATE '.$table.' SET '.implode(', ', $valstr) - .$where - .(count($orderby) > 0 ? ' ORDER BY '.implode(', ', $orderby) : ''); + $this->qb_limit = FALSE; + return parent::_update($table, $values); } // -------------------------------------------------------------------- @@ -193,10 +170,10 @@ class CI_DB_pdo_firebird_driver extends CI_DB_pdo_driver { * * Generates a platform-specific truncate string from the supplied data * - * If the database does not support the truncate() command, + * If the database does not support the TRUNCATE statement, * then this method maps to 'DELETE FROM table' * - * @param string the table name + * @param string $table * @return string */ protected function _truncate($table) @@ -211,46 +188,37 @@ class CI_DB_pdo_firebird_driver extends CI_DB_pdo_driver { * * Generates a platform-specific delete string from the supplied data * - * @param string the table name - * @param array the where clause - * @param array the like clause - * @param string the limit clause (ignored) + * @param string $table * @return string */ - protected function _delete($table, $where = array(), $like = array(), $limit = FALSE) + protected function _delete($table) { - $conditions = array(); - - empty($where) OR $conditions[] = implode(' ', $where); - empty($like) OR $conditions[] = implode(' ', $like); - - return 'DELETE FROM '.$table.(count($conditions) > 0 ? ' WHERE '.implode(' AND ', $conditions) : ''); + $this->qb_limit = FALSE; + return parent::_delete($table); } // -------------------------------------------------------------------- /** - * Limit string + * LIMIT * * Generates a platform-specific LIMIT clause * - * @param string the sql query string - * @param int the number of rows to limit the query to - * @param int the offset value + * @param string $sql SQL Query * @return string */ - protected function _limit($sql, $limit, $offset) + protected function _limit($sql) { // Limit clause depends on if Interbase or Firebird if (stripos($this->version(), 'firebird') !== FALSE) { - $select = 'FIRST '. (int) $limit - .($offset > 0 ? ' SKIP '. (int) $offset : ''); + $select = 'FIRST '.$this->qb_limit + .($this->qb_offset > 0 ? ' SKIP '.$this->qb_offset : ''); } else { $select = 'ROWS ' - .($offset > 0 ? (int) $offset.' TO '.($limit + $offset) : (int) $limit); + .($this->qb_offset > 0 ? $this->qb_offset.' TO '.($this->qb_limit + $this->qb_offset) : $this->qb_limit); } return preg_replace('`SELECT`i', 'SELECT '.$select, $sql); diff --git a/system/database/drivers/pdo/subdrivers/pdo_ibm_driver.php b/system/database/drivers/pdo/subdrivers/pdo_ibm_driver.php index 832c03c96..d8dbc50c0 100644 --- a/system/database/drivers/pdo/subdrivers/pdo_ibm_driver.php +++ b/system/database/drivers/pdo/subdrivers/pdo_ibm_driver.php @@ -1,4 +1,4 @@ -<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed'); +<?php /** * CodeIgniter * @@ -24,6 +24,7 @@ * @since Version 3.0.0 * @filesource */ +defined('BASEPATH') OR exit('No direct script access allowed'); /** * PDO IBM DB2 Database Adapter Class @@ -40,16 +41,21 @@ */ class CI_DB_pdo_ibm_driver extends CI_DB_pdo_driver { + /** + * Sub-driver + * + * @var string + */ public $subdriver = 'ibm'; - protected $_random_keyword = ' RAND()'; + // -------------------------------------------------------------------- /** - * Constructor + * Class constructor * * Builds the DSN if not already set. * - * @param array + * @param array $params * @return void */ public function __construct($params) @@ -115,7 +121,7 @@ class CI_DB_pdo_ibm_driver extends CI_DB_pdo_driver { * * Generates a platform-specific query string so that the table names can be fetched * - * @param bool + * @param bool $prefix_limit * @return string */ protected function _list_tables($prefix_limit = FALSE) @@ -138,7 +144,7 @@ class CI_DB_pdo_ibm_driver extends CI_DB_pdo_driver { * * Generates a platform-specific query string so that the column names can be fetched * - * @param string the table name + * @param string $table * @return string */ protected function _list_columns($table = '') @@ -154,7 +160,7 @@ class CI_DB_pdo_ibm_driver extends CI_DB_pdo_driver { * * Generates a platform-specific query so that the column data can be retrieved * - * @param string the table name + * @param string $table * @return string */ protected function _field_data($table) @@ -165,49 +171,19 @@ class CI_DB_pdo_ibm_driver extends CI_DB_pdo_driver { // -------------------------------------------------------------------- /** - * From Tables - * - * This function implicitly groups FROM tables so there is no confusion - * about operator precedence in harmony with SQL standards - * - * @param array - * @return string - */ - protected function _from_tables($tables) - { - return is_array($tables) ? implode(', ', $tables) : $tables; - } - - // -------------------------------------------------------------------- - - /** * Update statement * * Generates a platform-specific update string from the supplied data * - * @param string the table name - * @param array the update data - * @param array the where clause - * @param array the orderby clause (ignored) - * @param array the limit clause (ignored) - * @param array the like clause + * @param string $table + * @param array $values * @return string */ - protected function _update($table, $values, $where, $orderby = array(), $limit = FALSE, $like = array()) + protected function _update($table, $values) { - foreach ($values as $key => $val) - { - $valstr[] = $key.' = '.$val; - } - - $where = empty($where) ? '' : ' WHERE '.implode(' ', $where); - - if ( ! empty($like)) - { - $where .= ($where === '' ? ' WHERE ' : ' AND ').implode(' ', $like); - } - - return 'UPDATE '.$table.' SET '.implode(', ', $valstr).$where; + $this->qb_limit = FALSE; + $this->qb_orderby = array(); + return parent::_update($table, $values); } // -------------------------------------------------------------------- @@ -217,42 +193,31 @@ class CI_DB_pdo_ibm_driver extends CI_DB_pdo_driver { * * Generates a platform-specific delete string from the supplied data * - * @param string the table name - * @param array the where clause - * @param array the like clause - * @param string the limit clause (ignored) + * @param string $table * @return string */ - protected function _delete($table, $where = array(), $like = array(), $limit = FALSE) + protected function _delete($table) { - $conditions = array(); - - empty($where) OR $conditions[] = implode(' ', $where); - empty($like) OR $conditions[] = implode(' ', $like); - - $conditions = (count($conditions) > 0) ? ' WHERE '.implode(' AND ', $conditions) : ''; - - return 'DELETE FROM '.$table.$conditions; + $this->qb_limit = FALSE; + return parent::_delete($table); } // -------------------------------------------------------------------- /** - * Limit string + * LIMIT * * Generates a platform-specific LIMIT clause * - * @param string the sql query string - * @param int the number of rows to limit the query to - * @param int the offset value + * @param string $sql SQL Query * @return string */ - protected function _limit($sql, $limit, $offset) + protected function _limit($sql) { - $sql .= ' FETCH FIRST '.($limit + $offset).' ROWS ONLY'; + $sql .= ' FETCH FIRST '.($this->qb_limit + $this->qb_offset).' ROWS ONLY'; - return ($offset) - ? 'SELECT * FROM ('.$sql.') WHERE rownum > '.$offset + return ($this->qb_offset) + ? 'SELECT * FROM ('.$sql.') WHERE rownum > '.$this->qb_offset : $sql; } diff --git a/system/database/drivers/pdo/subdrivers/pdo_informix_driver.php b/system/database/drivers/pdo/subdrivers/pdo_informix_driver.php index a3efc63dc..8998670e1 100644 --- a/system/database/drivers/pdo/subdrivers/pdo_informix_driver.php +++ b/system/database/drivers/pdo/subdrivers/pdo_informix_driver.php @@ -1,4 +1,4 @@ -<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed'); +<?php /** * CodeIgniter * @@ -24,6 +24,7 @@ * @since Version 3.0.0 * @filesource */ +defined('BASEPATH') OR exit('No direct script access allowed'); /** * PDO Informix Database Adapter Class @@ -40,16 +41,21 @@ */ class CI_DB_pdo_informix_driver extends CI_DB_pdo_driver { + /** + * Sub-driver + * + * @var string + */ public $subdriver = 'informix'; - protected $_random_keyword = ' RAND()'; + // -------------------------------------------------------------------- /** - * Constructor + * Class constructor * * Builds the DSN if not already set. * - * @param array + * @param array $params * @return void */ public function __construct($params) @@ -108,7 +114,7 @@ class CI_DB_pdo_informix_driver extends CI_DB_pdo_driver { * * Generates a platform-specific query string so that the table names can be fetched * - * @param bool + * @param bool $prefix_limit * @return string */ protected function _list_tables($prefix_limit = FALSE) @@ -131,7 +137,7 @@ class CI_DB_pdo_informix_driver extends CI_DB_pdo_driver { * * Generates a platform-specific query string so that the column names can be fetched * - * @param string the table name + * @param string $table * @return string */ protected function _list_columns($table = '') @@ -148,7 +154,7 @@ class CI_DB_pdo_informix_driver extends CI_DB_pdo_driver { * * Generates a platform-specific query so that the column data can be retrieved * - * @param string the table name + * @param string $table * @return string */ protected function _field_data($table) @@ -159,49 +165,19 @@ class CI_DB_pdo_informix_driver extends CI_DB_pdo_driver { // -------------------------------------------------------------------- /** - * From Tables - * - * This function implicitly groups FROM tables so there is no confusion - * about operator precedence in harmony with SQL standards - * - * @param array - * @return string - */ - protected function _from_tables($tables) - { - return is_array($tables) ? implode(', ', $tables) : $tables; - } - - // -------------------------------------------------------------------- - - /** * Update statement * * Generates a platform-specific update string from the supplied data * - * @param string the table name - * @param array the update data - * @param array the where clause - * @param array the orderby clause (ignored) - * @param array the limit clause (ignored) - * @param array the like clause + * @param string $table + * @param array $values * @return string */ - protected function _update($table, $values, $where, $orderby = array(), $limit = FALSE, $like = array()) + protected function _update($table, $values) { - foreach ($values as $key => $val) - { - $valstr[] = $key.' = '.$val; - } - - $where = empty($where) ? '' : ' WHERE '.implode(' ', $where); - - if ( ! empty($like)) - { - $where .= ($where === '' ? ' WHERE ' : ' AND ').implode(' ', $like); - } - - return 'UPDATE '.$table.' SET '.implode(', ', $valstr).$where; + $this->qb_limit = FALSE; + $this->qb_orderby = array(); + return parent::_update($table, $values); } // -------------------------------------------------------------------- @@ -211,10 +187,10 @@ class CI_DB_pdo_informix_driver extends CI_DB_pdo_driver { * * Generates a platform-specific truncate string from the supplied data * - * If the database does not support the truncate() command, + * If the database does not support the TRUNCATE statement, * then this method maps to 'DELETE FROM table' * - * @param string the table name + * @param string $table * @return string */ protected function _truncate($table) @@ -229,39 +205,28 @@ class CI_DB_pdo_informix_driver extends CI_DB_pdo_driver { * * Generates a platform-specific delete string from the supplied data * - * @param string the table name - * @param array the where clause - * @param array the like clause - * @param string the limit clause (ignored) + * @param string $table * @return string */ - protected function _delete($table, $where = array(), $like = array(), $limit = FALSE) + protected function _delete($table) { - $conditions = array(); - - empty($where) OR $conditions[] = implode(' ', $where); - empty($like) OR $conditions[] = implode(' ', $like); - - $conditions = (count($conditions) > 0) ? ' WHERE '.implode(' AND ', $conditions) : ''; - - return 'DELETE FROM '.$table.$conditions; + $this->qb_limit = FALSE; + return parent::_delete($table); } // -------------------------------------------------------------------- /** - * Limit string + * LIMIT * * Generates a platform-specific LIMIT clause * - * @param string the sql query string - * @param int the number of rows to limit the query to - * @param int the offset value + * @param string $sql $SQL Query * @return string */ - protected function _limit($sql, $limit, $offset) + protected function _limit($sql) { - $select = 'SELECT '.($offset ? 'SKIP '.$offset : '').'FIRST '.$limit.' '; + $select = 'SELECT '.($this->qb_offset ? 'SKIP '.$this->qb_offset : '').'FIRST '.$this->qb_limit.' '; return preg_replace('/^(SELECT\s)/i', $select, $sql, 1); } diff --git a/system/database/drivers/pdo/subdrivers/pdo_mysql_driver.php b/system/database/drivers/pdo/subdrivers/pdo_mysql_driver.php index 78afe246c..2d076f314 100644 --- a/system/database/drivers/pdo/subdrivers/pdo_mysql_driver.php +++ b/system/database/drivers/pdo/subdrivers/pdo_mysql_driver.php @@ -1,4 +1,4 @@ -<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed'); +<?php /** * CodeIgniter * @@ -24,6 +24,7 @@ * @since Version 3.0.0 * @filesource */ +defined('BASEPATH') OR exit('No direct script access allowed'); /** * PDO MySQL Database Adapter Class @@ -40,22 +41,37 @@ */ class CI_DB_pdo_mysql_driver extends CI_DB_pdo_driver { + /** + * Sub-driver + * + * @var string + */ public $subdriver = 'mysql'; - protected $_escape_char = '`'; + /** + * Compression flag + * + * @var bool + */ + public $compress = FALSE; + + // -------------------------------------------------------------------- - // clause and character used for LIKE escape sequences - not used in MySQL - protected $_like_escape_str = ''; - protected $_like_escape_chr = '\\'; + /** + * Identifier escape character + * + * @var string + */ + protected $_escape_char = '`'; - protected $_random_keyword = ' RAND()'; + // -------------------------------------------------------------------- /** - * Constructor + * Class constructor * * Builds the DSN if not already set. * - * @param array + * @param array $params * @return void */ public function __construct($params) @@ -79,10 +95,11 @@ class CI_DB_pdo_mysql_driver extends CI_DB_pdo_driver { // -------------------------------------------------------------------- /** - * Non-persistent database connection + * Database connection * - * @param bool + * @param bool $persistent * @return object + * @todo SSL support */ public function db_connect($persistent = FALSE) { @@ -97,6 +114,11 @@ class CI_DB_pdo_mysql_driver extends CI_DB_pdo_driver { .(empty($this->dbcollat) ? '' : ' COLLATE '.$this->dbcollat); } + if ($this->compress === TRUE) + { + $this->options[PDO::MYSQL_ATTR_COMPRESS] = TRUE; + } + return parent::db_connect($persistent); } @@ -107,7 +129,7 @@ class CI_DB_pdo_mysql_driver extends CI_DB_pdo_driver { * * Generates a platform-specific query string so that the table names can be fetched * - * @param bool + * @param bool $prefix_limit * @return string */ protected function _list_tables($prefix_limit = FALSE) @@ -129,7 +151,7 @@ class CI_DB_pdo_mysql_driver extends CI_DB_pdo_driver { * * Generates a platform-specific query string so that the column names can be fetched * - * @param string the table name + * @param string $table * @return string */ protected function _list_columns($table = '') @@ -144,7 +166,7 @@ class CI_DB_pdo_mysql_driver extends CI_DB_pdo_driver { * * Generates a platform-specific query so that the column data can be retrieved * - * @param string the table name + * @param string $table * @return string */ protected function _field_data($table) @@ -159,12 +181,12 @@ class CI_DB_pdo_mysql_driver extends CI_DB_pdo_driver { * * Generates a platform-specific batch update string from the supplied data * - * @param string the table name - * @param array the update data - * @param array the where clause + * @param string $table Table name + * @param array $values Update data + * @param string $index UPDATE key * @return string */ - protected function _update_batch($table, $values, $index, $where = NULL) + protected function _update_batch($table, $values, $index) { $ids = array(); foreach ($values as $key => $val) @@ -188,9 +210,9 @@ class CI_DB_pdo_mysql_driver extends CI_DB_pdo_driver { .'ELSE '.$k.' END), '; } - return 'UPDATE '.$table.' SET '.substr($cases, 0, -2) - .' WHERE '.(($where !== '' && count($where) > 0) ? implode(' ', $where).' AND ' : '') - .$index.' IN('.implode(',', $ids).')'; + $this->where($index.' IN('.implode(',', $ids).')', NULL, FALSE); + + return 'UPDATE '.$table.' SET '.substr($cases, 0, -2).$this->_compile_wh('qb_where'); } // -------------------------------------------------------------------- @@ -200,10 +222,10 @@ class CI_DB_pdo_mysql_driver extends CI_DB_pdo_driver { * * Generates a platform-specific truncate string from the supplied data * - * If the database does not support the truncate() command, + * If the database does not support the TRUNCATE statement, * then this method maps to 'DELETE FROM table' * - * @param string the table name + * @param string $table * @return string */ protected function _truncate($table) @@ -211,6 +233,26 @@ class CI_DB_pdo_mysql_driver extends CI_DB_pdo_driver { return 'TRUNCATE '.$table; } + // -------------------------------------------------------------------- + + /** + * FROM tables + * + * Groups tables in FROM clauses if needed, so there is no confusion + * about operator precedence. + * + * @return string + */ + protected function _from_tables() + { + if ( ! empty($this->qb_join) && count($this->qb_from) > 1) + { + return '('.implode(', ', $this->qb_from).')'; + } + + return implode(', ', $this->qb_from); + } + } /* End of file pdo_mysql_driver.php */ diff --git a/system/database/drivers/pdo/subdrivers/pdo_oci_driver.php b/system/database/drivers/pdo/subdrivers/pdo_oci_driver.php index 56ec1bce1..2e28476ba 100644 --- a/system/database/drivers/pdo/subdrivers/pdo_oci_driver.php +++ b/system/database/drivers/pdo/subdrivers/pdo_oci_driver.php @@ -1,4 +1,4 @@ -<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed'); +<?php /** * CodeIgniter * @@ -24,6 +24,7 @@ * @since Version 3.0.0 * @filesource */ +defined('BASEPATH') OR exit('No direct script access allowed'); /** * PDO Oracle Database Adapter Class @@ -40,24 +41,49 @@ */ class CI_DB_pdo_oci_driver extends CI_DB_pdo_driver { + /** + * Sub-driver + * + * @var string + */ public $subdriver = 'oci'; + // -------------------------------------------------------------------- + /** - * The syntax to count rows is slightly different across different - * database engines, so this string appears in each driver and is - * used for the count_all() and count_all_results() functions. + * List of reserved identifiers + * + * Identifiers that must NOT be escaped. + * + * @var string[] + */ + protected $_reserved_identifiers = array('*', 'rownum'); + + /** + * ORDER BY random keyword + * + * @var string */ - protected $_count_string = 'SELECT COUNT(1) AS '; protected $_random_keyword = ' ASC'; // Currently not supported - protected $_reserved_identifiers = array('*', 'rownum'); + /** + * COUNT string + * + * @used-by CI_DB_driver::count_all() + * @used-by CI_DB_query_builder::count_all_results() + * + * @var string + */ + protected $_count_string = 'SELECT COUNT(1) AS '; + + // -------------------------------------------------------------------- /** - * Constructor + * Class constructor * * Builds the DSN if not already set. * - * @param array + * @param array $params * @return void */ public function __construct($params) @@ -97,7 +123,7 @@ class CI_DB_pdo_oci_driver extends CI_DB_pdo_driver { * * Generates a platform-specific query string so that the table names can be fetched * - * @param bool + * @param bool $prefix_limit * @return string */ protected function _list_tables($prefix_limit = FALSE) @@ -120,7 +146,7 @@ class CI_DB_pdo_oci_driver extends CI_DB_pdo_driver { * * Generates a platform-specific query string so that the column names can be fetched * - * @param string the table name + * @param string $table * @return string */ protected function _list_columns($table = '') @@ -135,7 +161,7 @@ class CI_DB_pdo_oci_driver extends CI_DB_pdo_driver { * * Generates a platform-specific query so that the column data can be retrieved * - * @param string the table name + * @param string $table * @return string */ protected function _field_data($table) @@ -146,27 +172,11 @@ class CI_DB_pdo_oci_driver extends CI_DB_pdo_driver { // -------------------------------------------------------------------- /** - * From Tables - * - * This function implicitly groups FROM tables so there is no confusion - * about operator precedence in harmony with SQL standards - * - * @param array - * @return string - */ - protected function _from_tables($tables) - { - return is_array($tables) ? implode(', ', $tables) : $tables; - } - - // -------------------------------------------------------------------- - - /** * Insert_batch statement * - * @param string the table name - * @param array the insert keys - * @param array the insert values + * @param string $table Table name + * @param array $keys INSERT keys + * @param array $values INSERT values * @return string */ protected function _insert_batch($table, $keys, $values) @@ -189,39 +199,34 @@ class CI_DB_pdo_oci_driver extends CI_DB_pdo_driver { * * Generates a platform-specific delete string from the supplied data * - * @param string the table name - * @param array the where clause - * @param array the like clause - * @param string the limit clause + * @param string $table * @return string */ - protected function _delete($table, $where = array(), $like = array(), $limit = FALSE) + protected function _delete($table) { - $conditions = array(); - - empty($where) OR $conditions[] = implode(' ', $where); - empty($like) OR $conditions[] = implode(' ', $like); - empty($limit) OR $conditions[] = 'rownum <= '.$limit; + if ($this->qb_limit) + { + $this->where('rownum <= ',$this->qb_limit, FALSE); + $this->qb_limit = FALSE; + } - return 'DELETE FROM '.$table.(count($conditions) > 0 ? ' WHERE '.implode(' AND ', $conditions) : ''); + return parent::_delete($table); } // -------------------------------------------------------------------- /** - * Limit string + * LIMIT * * Generates a platform-specific LIMIT clause * - * @param string the sql query string - * @param int the number of rows to limit the query to - * @param int the offset value + * @param string $sql SQL Query * @return string */ - protected function _limit($sql, $limit, $offset) + protected function _limit($sql) { - return 'SELECT * FROM (SELECT inner_query.*, rownum rnum FROM ('.$sql.') inner_query WHERE rownum < '.($offset + $limit + 1).')' - .($offset ? ' WHERE rnum >= '.($offset + 1): ''); + return 'SELECT * FROM (SELECT inner_query.*, rownum rnum FROM ('.$sql.') inner_query WHERE rownum < '.($this->qb_offset + $this->qb_limit + 1).')' + .($this->qb_offset ? ' WHERE rnum >= '.($this->qb_offset + 1): ''); } } diff --git a/system/database/drivers/pdo/subdrivers/pdo_odbc_driver.php b/system/database/drivers/pdo/subdrivers/pdo_odbc_driver.php index 392754ff7..f6e0e215a 100644 --- a/system/database/drivers/pdo/subdrivers/pdo_odbc_driver.php +++ b/system/database/drivers/pdo/subdrivers/pdo_odbc_driver.php @@ -1,4 +1,4 @@ -<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed'); +<?php /** * CodeIgniter * @@ -24,6 +24,7 @@ * @since Version 3.0.0 * @filesource */ +defined('BASEPATH') OR exit('No direct script access allowed'); /** * PDO ODBC Database Adapter Class @@ -40,23 +41,46 @@ */ class CI_DB_pdo_odbc_driver extends CI_DB_pdo_driver { + /** + * Sub-driver + * + * @var string + */ public $subdriver = 'odbc'; - // The character used for escaping - not used in ODBC + /** + * Database schema + * + * @var string + */ + public $schema = 'public'; + + // -------------------------------------------------------------------- + + /** + * Identifier escape character + * + * Must be empty for ODBC. + * + * @var string + */ protected $_escape_char = ''; - // clause and character used for LIKE escape sequences - protected $_like_escape_chr = '!'; + /** + * ESCAPE statement string + * + * @var string + */ protected $_like_escape_str = " {escape '%s'} "; - protected $_random_keyword = ' RAND()'; + // -------------------------------------------------------------------- /** - * Constructor + * Class constructor * * Builds the DSN if not already set. * - * @param array + * @param array $params * @return void */ public function __construct($params) @@ -123,12 +147,12 @@ class CI_DB_pdo_odbc_driver extends CI_DB_pdo_driver { * * Generates a platform-specific query string so that the table names can be fetched * - * @param bool + * @param bool $prefix_limit * @return string */ protected function _list_tables($prefix_limit = FALSE) { - $sql = "SELECT table_name FROM information_schema.tables WHERE table_schema = 'public'"; + $sql = "SELECT table_name FROM information_schema.tables WHERE table_schema = '".$this->schema."'"; if ($prefix_limit !== FALSE && $this->dbprefix !== '') { @@ -146,7 +170,7 @@ class CI_DB_pdo_odbc_driver extends CI_DB_pdo_driver { * * Generates a platform-specific query string so that the column names can be fetched * - * @param string the table name + * @param string $table * @return string */ protected function _list_columns($table = '') @@ -157,49 +181,19 @@ class CI_DB_pdo_odbc_driver extends CI_DB_pdo_driver { // -------------------------------------------------------------------- /** - * From Tables - * - * This function implicitly groups FROM tables so there is no confusion - * about operator precedence in harmony with SQL standards - * - * @param array - * @return string - */ - protected function _from_tables($tables) - { - return is_array($tables) ? implode(', ', $tables) : $tables; - } - - // -------------------------------------------------------------------- - - /** * Update statement * * Generates a platform-specific update string from the supplied data * - * @param string the table name - * @param array the update data - * @param array the where clause - * @param array the orderby clause (ignored) - * @param array the limit clause (ignored) - * @param array the like clause + * @param string $table + * @param array $values * @return string */ - protected function _update($table, $values, $where, $orderby = array(), $limit = FALSE, $like = array()) + protected function _update($table, $values) { - foreach ($values as $key => $val) - { - $valstr[] = $key.' = '.$val; - } - - $where = empty($where) ? '' : ' WHERE '.implode(' ', $where); - - if ( ! empty($like)) - { - $where .= ($where === '' ? ' WHERE ' : ' AND ').implode(' ', $like); - } - - return 'UPDATE '.$table.' SET '.implode(', ', $valstr).$where; + $this->qb_limit = FALSE; + $this->qb_orderby = array(); + return parent::_update($table, $values); } // -------------------------------------------------------------------- @@ -209,10 +203,10 @@ class CI_DB_pdo_odbc_driver extends CI_DB_pdo_driver { * * Generates a platform-specific truncate string from the supplied data * - * If the database does not support the truncate() command, + * If the database does not support the TRUNCATE statement, * then this method maps to 'DELETE FROM table' * - * @param string the table name + * @param string $table * @return string */ protected function _truncate($table) @@ -228,38 +222,27 @@ class CI_DB_pdo_odbc_driver extends CI_DB_pdo_driver { * Generates a platform-specific delete string from the supplied data * * @param string the table name - * @param array the where clause - * @param array the like clause - * @param string the limit clause * @return string */ - protected function _delete($table, $where = array(), $like = array(), $limit = FALSE) + protected function _delete($table) { - $conditions = array(); - - empty($where) OR $conditions[] = implode(' ', $where); - empty($like) OR $conditions[] = implode(' ', $like); - - $conditions = (count($conditions) > 0) ? ' WHERE '.implode(' AND ', $conditions) : ''; - - return 'DELETE FROM '.$table.$conditions; + $this->qb_limit = FALSE; + return parent::_delete($table); } // -------------------------------------------------------------------- /** - * Limit string + * LIMIT * * Generates a platform-specific LIMIT clause * - * @param string the sql query string - * @param int the number of rows to limit the query to - * @param int the offset value + * @param string $sql SQL Query * @return string */ - protected function _limit($sql, $limit, $offset) + protected function _limit($sql) { - return preg_replace('/(^\SELECT (DISTINCT)?)/i','\\1 TOP '.$limit.' ', $sql); + return preg_replace('/(^\SELECT (DISTINCT)?)/i','\\1 TOP '.$this->qb_limit.' ', $sql); } } diff --git a/system/database/drivers/pdo/subdrivers/pdo_pgsql_driver.php b/system/database/drivers/pdo/subdrivers/pdo_pgsql_driver.php index 9a476f143..c3f5b7603 100644 --- a/system/database/drivers/pdo/subdrivers/pdo_pgsql_driver.php +++ b/system/database/drivers/pdo/subdrivers/pdo_pgsql_driver.php @@ -1,4 +1,4 @@ -<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed'); +<?php /** * CodeIgniter * @@ -24,6 +24,7 @@ * @since Version 3.0.0 * @filesource */ +defined('BASEPATH') OR exit('No direct script access allowed'); /** * PDO PostgreSQL Database Adapter Class @@ -40,16 +41,37 @@ */ class CI_DB_pdo_pgsql_driver extends CI_DB_pdo_driver { + /** + * Sub-driver + * + * @var string + */ public $subdriver = 'pgsql'; + /** + * Database schema + * + * @var string + */ + public $schema = 'public'; + + // -------------------------------------------------------------------- + + /** + * ORDER BY random keyword + * + * @var string + */ protected $_random_keyword = ' RANDOM()'; + // -------------------------------------------------------------------- + /** - * Constructor + * Class constructor * * Builds the DSN if not already set. * - * @param array + * @param array $params * @return void */ public function __construct($params) @@ -70,7 +92,7 @@ class CI_DB_pdo_pgsql_driver extends CI_DB_pdo_driver { /** * Insert ID * - * @param string + * @param string $name * @return int */ public function insert_id($name = NULL) @@ -92,12 +114,12 @@ class CI_DB_pdo_pgsql_driver extends CI_DB_pdo_driver { * * Generates a platform-specific query string so that the table names can be fetched * - * @param bool + * @param bool $prefix_limit * @return string */ protected function _list_tables($prefix_limit = FALSE) { - $sql = 'SELECT "table_name" FROM "information_schema"."tables" WHERE "table_schema" = \'public\''; + $sql = 'SELECT "table_name" FROM "information_schema"."tables" WHERE "table_schema" = \''.$this->schema."'"; if ($prefix_limit === TRUE && $this->dbprefix !== '') { @@ -116,7 +138,7 @@ class CI_DB_pdo_pgsql_driver extends CI_DB_pdo_driver { * * Generates a platform-specific query string so that the column names can be fetched * - * @param string the table name + * @param string $table * @return string */ protected function _list_columns($table = '') @@ -131,7 +153,7 @@ class CI_DB_pdo_pgsql_driver extends CI_DB_pdo_driver { * * Generates a platform-specific query so that the column data can be retrieved * - * @param string the table name + * @param string $table * @return string */ protected function _field_data($table) @@ -142,49 +164,19 @@ class CI_DB_pdo_pgsql_driver extends CI_DB_pdo_driver { // -------------------------------------------------------------------- /** - * From Tables - * - * This function implicitly groups FROM tables so there is no confusion - * about operator precedence in harmony with SQL standards - * - * @param array - * @return string - */ - protected function _from_tables($tables) - { - return is_array($tables) ? implode(', ', $tables) : $tables; - } - - // -------------------------------------------------------------------- - - /** * Update statement * * Generates a platform-specific update string from the supplied data * - * @param string the table name - * @param array the update data - * @param array the where clause - * @param array the orderby clause (ignored) - * @param array the limit clause (ignored) - * @param array the like clause + * @param string $table + * @param array $values * @return string */ - protected function _update($table, $values, $where, $orderby = array(), $limit = FALSE, $like = array()) + protected function _update($table, $values) { - foreach ($values as $key => $val) - { - $valstr[] = $key.' = '.$val; - } - - $where = empty($where) ? '' : ' WHERE '.implode(' ', $where); - - if ( ! empty($like)) - { - $where .= ($where === '' ? ' WHERE ' : ' AND ').implode(' ', $like); - } - - return 'UPDATE '.$table.' SET '.implode(', ', $valstr).$where; + $this->qb_limit = FALSE; + $this->qb_orderby = array(); + return parent::_update($table, $values); } // -------------------------------------------------------------------- @@ -194,12 +186,12 @@ class CI_DB_pdo_pgsql_driver extends CI_DB_pdo_driver { * * Generates a platform-specific batch update string from the supplied data * - * @param string the table name - * @param array the update data - * @param array the where clause + * @param string $table Table name + * @param array $values Update data + * @param string $index WHERE key * @return string */ - protected function _update_batch($table, $values, $index, $where = NULL) + protected function _update_batch($table, $values, $index) { $ids = array(); foreach ($values as $key => $val) @@ -218,14 +210,14 @@ class CI_DB_pdo_pgsql_driver extends CI_DB_pdo_driver { $cases = ''; foreach ($final as $k => $v) { - $cases .= $k.' = (CASE '.$k."\n" + $cases .= $k.' = (CASE '.$index."\n" .implode("\n", $v)."\n" .'ELSE '.$k.' END), '; } - return 'UPDATE '.$table.' SET '.substr($cases, 0, -2) - .' WHERE '.(($where !== '' && count($where) > 0) ? implode(' ', $where).' AND ' : '') - .$index.' IN('.implode(',', $ids).')'; + $this->where($index.' IN('.implode(',', $ids).')', NULL, FALSE); + + return 'UPDATE '.$table.' SET '.substr($cases, 0, -2).$this->_compile_wh('qb_where'); } // -------------------------------------------------------------------- @@ -235,53 +227,48 @@ class CI_DB_pdo_pgsql_driver extends CI_DB_pdo_driver { * * Generates a platform-specific delete string from the supplied data * - * @param string the table name - * @param array the where clause - * @param array the like clause - * @param string the limit clause (ignored) + * @param string $table * @return string */ - protected function _delete($table, $where = array(), $like = array(), $limit = FALSE) + protected function _delete($table) { - $conditions = array(); - - empty($where) OR $conditions[] = implode(' ', $where); - empty($like) OR $conditions[] = implode(' ', $like); - - return 'DELETE FROM '.$table.(count($conditions) > 0 ? ' WHERE '.implode(' AND ', $conditions) : ''); + $this->qb_limit = FALSE; + return parent::_delete($table); } // -------------------------------------------------------------------- /** - * Limit string + * LIMIT * * Generates a platform-specific LIMIT clause * - * @param string the sql query string - * @param int the number of rows to limit the query to - * @param int the offset value + * @param string $sql SQL Query * @return string */ - protected function _limit($sql, $limit, $offset) + protected function _limit($sql) { - return $sql.' LIMIT '.$limit.($offset ? ' OFFSET '.$offset : ''); + return $sql.' LIMIT '.$this->qb_limit.($this->qb_offset ? ' OFFSET '.$this->qb_offset : ''); } // -------------------------------------------------------------------- /** - * Where + * WHERE, HAVING * - * Called by where() or or_where() + * Called by where(), or_where(), having(), or_having() * + * @param string 'qb_where' or 'qb_having' * @param mixed * @param mixed * @param string + * @param bool * @return object */ - protected function _where($key, $value = NULL, $type = 'AND ', $escape = NULL) + protected function _wh($qb_key, $key, $value = NULL, $type = 'AND ', $escape = NULL) { + $qb_cache_key = ($qb_key === 'qb_having') ? 'qb_cache_having' : 'qb_cache_where'; + if ( ! is_array($key)) { $key = array($key => $value); @@ -292,14 +279,10 @@ class CI_DB_pdo_pgsql_driver extends CI_DB_pdo_driver { foreach ($key as $k => $v) { - $prefix = (count($this->qb_where) === 0 && count($this->qb_cache_where) === 0) + $prefix = (count($this->$qb_key) === 0 && count($this->$qb_cache_key) === 0) ? $this->_group_get_type('') : $this->_group_get_type($type); - $k = (($op = $this->_get_operator($k)) !== FALSE) - ? $this->protect_identifiers(substr($k, 0, strpos($k, $op)), FALSE, $escape).strstr($k, $op) - : $this->protect_identifiers($k, FALSE, $escape); - if (is_null($v) && ! $this->_has_operator($k)) { // value appears not to have been set, assign the test to IS NULL @@ -308,13 +291,13 @@ class CI_DB_pdo_pgsql_driver extends CI_DB_pdo_driver { if ( ! is_null($v)) { - if ($escape === TRUE) + if (is_bool($v)) { - $v = ' '.$this->escape($v); + $v = ' '.($v ? 'TRUE' : 'FALSE'); } - elseif (is_bool($v)) + elseif ($escape === TRUE) { - $v = ($v ? ' TRUE' : ' FALSE'); + $v = ' '.(is_int($v) ? $v : $this->escape($v)); } if ( ! $this->_has_operator($k)) @@ -323,11 +306,11 @@ class CI_DB_pdo_pgsql_driver extends CI_DB_pdo_driver { } } - $this->qb_where[] = $prefix.$k.$v; + $this->{$qb_key}[] = array('condition' => $prefix.$k.$v, 'escape' => $escape); if ($this->qb_caching === TRUE) { - $this->qb_cache_where[] = $prefix.$k.$v; - $this->qb_cache_exists[] = 'where'; + $this->{$qb_cache_key}[] = array('condition' => $prefix.$k.$v, 'escape' => $escape); + $this->qb_cache_exists[] = substr($qb_key, 3); } } diff --git a/system/database/drivers/pdo/subdrivers/pdo_sqlite_driver.php b/system/database/drivers/pdo/subdrivers/pdo_sqlite_driver.php index bf0363f63..b24b13e76 100644 --- a/system/database/drivers/pdo/subdrivers/pdo_sqlite_driver.php +++ b/system/database/drivers/pdo/subdrivers/pdo_sqlite_driver.php @@ -1,4 +1,4 @@ -<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed'); +<?php /** * CodeIgniter * @@ -24,6 +24,7 @@ * @since Version 3.0.0 * @filesource */ +defined('BASEPATH') OR exit('No direct script access allowed'); /** * PDO SQLite Database Adapter Class @@ -40,21 +41,30 @@ */ class CI_DB_pdo_sqlite_driver extends CI_DB_pdo_driver { + /** + * Sub-driver + * + * @var string + */ public $subdriver = 'sqlite'; + // -------------------------------------------------------------------- + /** - * The syntax to count rows is slightly different across different - * database engines, so this string appears in each driver and is - * used for the count_all() and count_all_results() functions. + * ORDER BY random keyword + * + * @var string */ - protected $_random_keyword = ' RANDOM()'; // Currently not supported + protected $_random_keyword = ' RANDOM()'; + + // -------------------------------------------------------------------- /** - * Constructor + * Class constructor * * Builds the DSN if not already set. * - * @param array + * @param array $params * @return void */ public function __construct($params) @@ -81,7 +91,7 @@ class CI_DB_pdo_sqlite_driver extends CI_DB_pdo_driver { * * Generates a platform-specific query string so that the table names can be fetched * - * @param bool + * @param bool $prefix_limit * @return string */ protected function _list_tables($prefix_limit = FALSE) @@ -104,7 +114,7 @@ class CI_DB_pdo_sqlite_driver extends CI_DB_pdo_driver { * * Generates a platform-specific query string so that the column names can be fetched * - * @param string the table name + * @param string $table * @return string */ protected function _list_columns($table = '') @@ -120,7 +130,7 @@ class CI_DB_pdo_sqlite_driver extends CI_DB_pdo_driver { * * Generates a platform-specific query so that the column data can be retrieved * - * @param string the table name + * @param string $table * @return string */ protected function _field_data($table) @@ -133,9 +143,9 @@ class CI_DB_pdo_sqlite_driver extends CI_DB_pdo_driver { /** * Replace statement * - * @param string the table name - * @param array the insert keys - * @param array the insert values + * @param string $table Table name + * @param array $keys INSERT keys + * @param array $values INSERT values * @return string */ protected function _replace($table, $keys, $values) @@ -150,10 +160,10 @@ class CI_DB_pdo_sqlite_driver extends CI_DB_pdo_driver { * * Generates a platform-specific truncate string from the supplied data * - * If the database does not support the truncate() command, + * If the database does not support the TRUNCATE statement, * then this method maps to 'DELETE FROM table' * - * @param string the table name + * @param string $table * @return string */ protected function _truncate($table) diff --git a/system/database/drivers/pdo/subdrivers/pdo_sqlsrv_driver.php b/system/database/drivers/pdo/subdrivers/pdo_sqlsrv_driver.php index f125b8f50..b8c60c6b2 100644 --- a/system/database/drivers/pdo/subdrivers/pdo_sqlsrv_driver.php +++ b/system/database/drivers/pdo/subdrivers/pdo_sqlsrv_driver.php @@ -1,4 +1,4 @@ -<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed'); +<?php /** * CodeIgniter * @@ -24,6 +24,7 @@ * @since Version 3.0.0 * @filesource */ +defined('BASEPATH') OR exit('No direct script access allowed'); /** * PDO SQLSRV Database Adapter Class @@ -40,18 +41,40 @@ */ class CI_DB_pdo_sqlsrv_driver extends CI_DB_pdo_driver { + /** + * Sub-driver + * + * @var string + */ public $subdriver = 'sqlsrv'; + // -------------------------------------------------------------------- + + /** + * ORDER BY random keyword + * + * @var string + */ protected $_random_keyword = ' NEWID()'; + /** + * Quoted identifier flag + * + * Whether to use SQL-92 standard quoted identifier + * (double quotes) or brackets for identifier escaping. + * + * @var bool + */ protected $_quoted_identifier; + // -------------------------------------------------------------------- + /** - * Constructor + * Class constructor * * Builds the DSN if not already set. * - * @param array + * @param array $params * @return void */ public function __construct($params) @@ -78,9 +101,9 @@ class CI_DB_pdo_sqlsrv_driver extends CI_DB_pdo_driver { $this->dsn .= ';ConnectionPooling='.$this->ConnectionPooling; } - if (isset($this->Encrypt)) + if ($this->encrypt === TRUE) { - $this->dsn .= ';Encrypt='.$this->Encrypt; + $this->dsn .= ';Encrypt=1'; } if (isset($this->TraceOn)) @@ -109,9 +132,9 @@ class CI_DB_pdo_sqlsrv_driver extends CI_DB_pdo_driver { // -------------------------------------------------------------------- /** - * Non-persistent database connection + * Database connection * - * @param bool + * @param bool $persistent * @return object */ public function db_connect($persistent = FALSE) @@ -144,7 +167,7 @@ class CI_DB_pdo_sqlsrv_driver extends CI_DB_pdo_driver { * * Generates a platform-specific query string so that the table names can be fetched * - * @param bool + * @param bool $prefix_limit * @return string */ protected function _list_tables($prefix_limit = FALSE) @@ -169,7 +192,7 @@ class CI_DB_pdo_sqlsrv_driver extends CI_DB_pdo_driver { * * Generates a platform-specific query string so that the column names can be fetched * - * @param string the table name + * @param string $table * @return string */ protected function _list_columns($table = '') @@ -182,49 +205,19 @@ class CI_DB_pdo_sqlsrv_driver extends CI_DB_pdo_driver { // -------------------------------------------------------------------- /** - * From Tables - * - * This function implicitly groups FROM tables so there is no confusion - * about operator precedence in harmony with SQL standards - * - * @param array - * @return string - */ - protected function _from_tables($tables) - { - return is_array($tables) ? implode(', ', $tables) : $tables; - } - - // -------------------------------------------------------------------- - - /** * Update statement * * Generates a platform-specific update string from the supplied data * - * @param string the table name - * @param array the update data - * @param array the where clause - * @param array the orderby clause (ignored) - * @param array the limit clause (ignored) - * @param array the like clause + * @param string $table + * @param array $values * @return string */ - protected function _update($table, $values, $where, $orderby = array(), $limit = FALSE, $like = array()) + protected function _update($table, $values) { - foreach ($values as $key => $val) - { - $valstr[] = $key.' = '.$val; - } - - $where = empty($where) ? '' : ' WHERE '.implode(' ', $where); - - if ( ! empty($like)) - { - $where .= ($where === '' ? ' WHERE ' : ' AND ').implode(' ', $like); - } - - return 'UPDATE '.$table.' SET '.implode(', ', $valstr).$where; + $this->qb_limit = FALSE; + $this->qb_orderby = array(); + return parent::_update($table, $values); } // -------------------------------------------------------------------- @@ -234,60 +227,70 @@ class CI_DB_pdo_sqlsrv_driver extends CI_DB_pdo_driver { * * Generates a platform-specific delete string from the supplied data * - * @param string the table name - * @param array the where clause - * @param array the like clause - * @param string the limit clause + * @param string $table * @return string */ - protected function _delete($table, $where = array(), $like = array(), $limit = FALSE) + protected function _delete($table) { - $conditions = array(); - - empty($where) OR $conditions[] = implode(' ', $where); - empty($like) OR $conditions[] = implode(' ', $like); - - $conditions = (count($conditions) > 0) ? ' WHERE '.implode(' AND ', $conditions) : ''; + if ($this->qb_limit) + { + return 'WITH ci_delete AS (SELECT TOP '.$this->qb_limit.' * FROM '.$table.$this->_compile_wh('qb_where').') DELETE FROM ci_delete'; + } - return ($limit) - ? 'WITH ci_delete AS (SELECT TOP '.$limit.' * FROM '.$table.$conditions.') DELETE FROM ci_delete' - : 'DELETE FROM '.$table.$conditions; + return parent::_delete($table); } // -------------------------------------------------------------------- /** - * Limit string + * LIMIT * * Generates a platform-specific LIMIT clause * - * @param string the sql query string - * @param int the number of rows to limit the query to - * @param int the offset value + * @param string $sql SQL Query * @return string */ - protected function _limit($sql, $limit, $offset) + protected function _limit($sql) { // As of SQL Server 2012 (11.0.*) OFFSET is supported if (version_compare($this->version(), '11', '>=')) { - return $sql.' OFFSET '.(int) $offset.' ROWS FETCH NEXT '.(int) $limit.' ROWS ONLY'; + return $sql.' OFFSET '.(int) $this->qb_offset.' ROWS FETCH NEXT '.$this->qb_limit.' ROWS ONLY'; } - $limit = $offset + $limit; + $limit = $this->qb_offset + $this->qb_limit; // An ORDER BY clause is required for ROW_NUMBER() to work - if ($offset && ! empty($this->qb_orderby)) + if ($this->qb_offset && ! empty($this->qb_orderby)) { - $orderby = 'ORDER BY '.implode(', ', $this->qb_orderby); + $orderby = $this->_compile_order_by(); // We have to strip the ORDER BY clause - $sql = trim(substr($sql, 0, strrpos($sql, 'ORDER BY '.$orderby))); + $sql = trim(substr($sql, 0, strrpos($sql, $orderby))); + + // Get the fields to select from our subquery, so that we can avoid CI_rownum appearing in the actual results + if (count($this->qb_select) === 0) + { + $select = '*'; // Inevitable + } + else + { + // Use only field names and their aliases, everything else is out of our scope. + $select = array(); + $field_regexp = ($this->_quoted_identifier) + ? '("[^\"]+")' : '(\[[^\]]+\])'; + for ($i = 0, $c = count($this->qb_select); $i < $c; $i++) + { + $select[] = preg_match('/(?:\s|\.)'.$field_regexp.'$/i', $this->qb_select[$i], $m) + ? $m[1] : $this->qb_select[$i]; + } + $select = implode(', ', $select); + } - return 'SELECT '.(count($this->qb_select) === 0 ? '*' : implode(', ', $this->qb_select))." FROM (\n" - .preg_replace('/^(SELECT( DISTINCT)?)/i', '\\1 ROW_NUMBER() OVER('.$orderby.') AS '.$this->escape_identifiers('CI_rownum').', ', $sql) - ."\n) ".$this->escape_identifiers('CI_subquery') - ."\nWHERE ".$this->escape_identifiers('CI_rownum').' BETWEEN '.((int) $offset + 1).' AND '.$limit; + return 'SELECT '.$select." FROM (\n\n" + .preg_replace('/^(SELECT( DISTINCT)?)/i', '\\1 ROW_NUMBER() OVER('.trim($orderby).') AS '.$this->escape_identifiers('CI_rownum').', ', $sql) + ."\n\n) ".$this->escape_identifiers('CI_subquery') + ."\nWHERE ".$this->escape_identifiers('CI_rownum').' BETWEEN '.($this->qb_offset + 1).' AND '.$limit; } return preg_replace('/(^\SELECT (DISTINCT)?)/i','\\1 TOP '.$limit.' ', $sql); @@ -296,4 +299,4 @@ class CI_DB_pdo_sqlsrv_driver extends CI_DB_pdo_driver { } /* End of file pdo_sqlsrv_driver.php */ -/* Location: ./system/database/drivers/pdo/subdrivers/pdo_sqlsrv_driver.php */ +/* Location: ./system/database/drivers/pdo/subdrivers/pdo_sqlsrv_driver.php */
\ No newline at end of file diff --git a/system/database/drivers/postgre/postgre_driver.php b/system/database/drivers/postgre/postgre_driver.php index 8c11c477b..028dc1996 100644 --- a/system/database/drivers/postgre/postgre_driver.php +++ b/system/database/drivers/postgre/postgre_driver.php @@ -1,4 +1,4 @@ -<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed'); +<?php /** * CodeIgniter * @@ -24,6 +24,7 @@ * @since Version 1.0 * @filesource */ +defined('BASEPATH') OR exit('No direct script access allowed'); /** * Postgre Database Adapter Class @@ -40,21 +41,37 @@ */ class CI_DB_postgre_driver extends CI_DB { + /** + * Database driver + * + * @var string + */ public $dbdriver = 'postgre'; - protected $_escape_char = '"'; + /** + * Database schema + * + * @var string + */ + public $schema = 'public'; - // clause and character used for LIKE escape sequences - protected $_like_escape_str = " ESCAPE '%s' "; - protected $_like_escape_chr = '!'; + // -------------------------------------------------------------------- + /** + * ORDER BY random keyword + * + * @var string + */ protected $_random_keyword = ' RANDOM()'; // database specific random keyword + // -------------------------------------------------------------------- + /** - * Constructor + * Class constructor * * Creates a DSN string to be used for db_connect() and db_pconnect() * + * @param array $params * @return void */ public function __construct($params) @@ -166,7 +183,7 @@ class CI_DB_postgre_driver extends CI_DB { /** * Set client character set * - * @param string + * @param string $charset * @return bool */ protected function _db_set_charset($charset) @@ -208,7 +225,7 @@ class CI_DB_postgre_driver extends CI_DB { /** * Execute the query * - * @param string an SQL query + * @param string $sql an SQL query * @return resource */ protected function _execute($sql) @@ -221,7 +238,7 @@ class CI_DB_postgre_driver extends CI_DB { /** * Begin Transaction * - * @param bool + * @param bool $test_mode * @return bool */ public function trans_begin($test_mode = FALSE) @@ -281,8 +298,8 @@ class CI_DB_postgre_driver extends CI_DB { /** * Escape String * - * @param string - * @param bool whether or not the string will be used in a LIKE condition + * @param string $str + * @param bool $like Whether or not the string will be used in a LIKE condition * @return string */ public function escape_str($str, $like = FALSE) @@ -318,7 +335,7 @@ class CI_DB_postgre_driver extends CI_DB { * Escapes data based on type * Sets boolean and null types * - * @param string + * @param string $str * @return mixed */ public function escape($str) @@ -396,12 +413,12 @@ class CI_DB_postgre_driver extends CI_DB { * * Generates a platform-specific query string so that the table names can be fetched * - * @param bool + * @param bool $prefix_limit * @return string */ protected function _list_tables($prefix_limit = FALSE) { - $sql = 'SELECT "table_name" FROM "information_schema"."tables" WHERE "table_schema" = \'public\''; + $sql = 'SELECT "table_name" FROM "information_schema"."tables" WHERE "table_schema" = \''.$this->schema."'"; if ($prefix_limit !== FALSE && $this->dbprefix !== '') { @@ -420,7 +437,7 @@ class CI_DB_postgre_driver extends CI_DB { * * Generates a platform-specific query string so that the column names can be fetched * - * @param string the table name + * @param string $table * @return string */ protected function _list_columns($table = '') @@ -435,7 +452,7 @@ class CI_DB_postgre_driver extends CI_DB { * * Generates a platform-specific query so that the column data can be retrieved * - * @param string the table name + * @param string $table * @return string */ protected function _field_data($table) @@ -461,49 +478,19 @@ class CI_DB_postgre_driver extends CI_DB { // -------------------------------------------------------------------- /** - * From Tables - * - * This function implicitly groups FROM tables so there is no confusion - * about operator precedence in harmony with SQL standards - * - * @param array - * @return string - */ - protected function _from_tables($tables) - { - return is_array($tables) ? implode(', ', $tables) : $tables; - } - - // -------------------------------------------------------------------- - - /** * Update statement * * Generates a platform-specific update string from the supplied data * - * @param string the table name - * @param array the update data - * @param array the where clause - * @param array the orderby clause (ignored) - * @param array the limit clause (ignored) - * @param array the like clause + * @param string $table + * @param array $values * @return string */ - protected function _update($table, $values, $where, $orderby = array(), $limit = FALSE, $like = array()) + protected function _update($table, $values) { - foreach ($values as $key => $val) - { - $valstr[] = $key.' = '.$val; - } - - $where = empty($where) ? '' : ' WHERE '.implode(' ', $where); - - if ( ! empty($like)) - { - $where .= ($where === '' ? ' WHERE ' : ' AND ').implode(' ', $like); - } - - return 'UPDATE '.$table.' SET '.implode(', ', $valstr).$where; + $this->qb_limit = FALSE; + $this->qb_orderby = array(); + return parent::_update($table, $values); } // -------------------------------------------------------------------- @@ -513,12 +500,12 @@ class CI_DB_postgre_driver extends CI_DB { * * Generates a platform-specific batch update string from the supplied data * - * @param string the table name - * @param array the update data - * @param array the where clause + * @param string $table Table name + * @param array $values Update data + * @param string $index WHERE key * @return string */ - protected function _update_batch($table, $values, $index, $where = NULL) + protected function _update_batch($table, $values, $index) { $ids = array(); foreach ($values as $key => $val) @@ -542,9 +529,9 @@ class CI_DB_postgre_driver extends CI_DB { .'ELSE '.$k.' END), '; } - return 'UPDATE '.$table.' SET '.substr($cases, 0, -2) - .' WHERE '.(($where !== '' && count($where) > 0) ? implode(' ', $where).' AND ' : '') - .$index.' IN('.implode(',', $ids).')'; + $this->where($index.' IN('.implode(',', $ids).')', NULL, FALSE); + + return 'UPDATE '.$table.' SET '.substr($cases, 0, -2).$this->_compile_wh('qb_where'); } // -------------------------------------------------------------------- @@ -554,54 +541,48 @@ class CI_DB_postgre_driver extends CI_DB { * * Generates a platform-specific delete string from the supplied data * - * @param string the table name - * @param array the where clause - * @param array the like clause - * @param string the limit clause (ignored) + * @param string $table * @return string */ - protected function _delete($table, $where = array(), $like = array(), $limit = FALSE) + protected function _delete($table) { - $conditions = array(); - - empty($where) OR $conditions[] = implode(' ', $where); - empty($like) OR $conditions[] = implode(' ', $like); - - return 'DELETE FROM '.$table.(count($conditions) > 0 ? ' WHERE '.implode(' AND ', $conditions) : ''); + $this->qb_limit = FALSE; + return parent::_delete($table); } // -------------------------------------------------------------------- /** - * Limit string + * LIMIT * * Generates a platform-specific LIMIT clause * - * @param string the sql query string - * @param int the number of rows to limit the query to - * @param int the offset value + * @param string $sql SQL Query * @return string */ - protected function _limit($sql, $limit, $offset) + protected function _limit($sql) { - return $sql.' LIMIT '.$limit.($offset ? ' OFFSET '.$offset : ''); + return $sql.' LIMIT '.$this->qb_limit.($this->qb_offset ? ' OFFSET '.$this->qb_offset : ''); } // -------------------------------------------------------------------- /** - * Where + * WHERE, HAVING * - * Called by where() or or_where() + * Called by where(), or_where(), having(), or_having() * + * @param string 'qb_where' or 'qb_having' * @param mixed * @param mixed * @param string - * @param mixed + * @param bool * @return object */ - protected function _where($key, $value = NULL, $type = 'AND ', $escape = NULL) + protected function _wh($qb_key, $key, $value = NULL, $type = 'AND ', $escape = NULL) { + $qb_cache_key = ($qb_key === 'qb_having') ? 'qb_cache_having' : 'qb_cache_where'; + if ( ! is_array($key)) { $key = array($key => $value); @@ -612,17 +593,10 @@ class CI_DB_postgre_driver extends CI_DB { foreach ($key as $k => $v) { - $prefix = (count($this->qb_where) === 0 && count($this->qb_cache_where) === 0) + $prefix = (count($this->$qb_key) === 0 && count($this->$qb_cache_key) === 0) ? $this->_group_get_type('') : $this->_group_get_type($type); - if ($escape === TRUE) - { - $k = (($op = $this->_get_operator($k)) !== FALSE) - ? $this->escape_identifiers(trim(substr($k, 0, strpos($k, $op)))).' '.strstr($k, $op) - : $this->escape_identifiers(trim($k)); - } - if (is_null($v) && ! $this->_has_operator($k)) { // value appears not to have been set, assign the test to IS NULL @@ -631,13 +605,13 @@ class CI_DB_postgre_driver extends CI_DB { if ( ! is_null($v)) { - if ($escape === TRUE) + if (is_bool($v)) { - $v = ' '.$this->escape($v); + $v = ' '.($v ? 'TRUE' : 'FALSE'); } - elseif (is_bool($v)) + elseif ($escape === TRUE) { - $v = ($v ? ' TRUE' : ' FALSE'); + $v = ' '.(is_int($v) ? $v : $this->escape($v)); } if ( ! $this->_has_operator($k)) @@ -646,11 +620,11 @@ class CI_DB_postgre_driver extends CI_DB { } } - $this->qb_where[] = $prefix.$k.$v; + $this->{$qb_key}[] = array('condition' => $prefix.$k.$v, 'escape' => $escape); if ($this->qb_caching === TRUE) { - $this->qb_cache_where[] = $prefix.$k.$v; - $this->qb_cache_exists[] = 'where'; + $this->{$qb_cache_key}[] = array('condition' => $prefix.$k.$v, 'escape' => $escape); + $this->qb_cache_exists[] = substr($qb_key, 3); } } diff --git a/system/database/drivers/postgre/postgre_forge.php b/system/database/drivers/postgre/postgre_forge.php index c434e9510..b08fa5177 100644 --- a/system/database/drivers/postgre/postgre_forge.php +++ b/system/database/drivers/postgre/postgre_forge.php @@ -1,4 +1,4 @@ -<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed'); +<?php /** * CodeIgniter * @@ -24,6 +24,7 @@ * @since Version 1.0 * @filesource */ +defined('BASEPATH') OR exit('No direct script access allowed'); /** * Postgre Forge Class @@ -34,12 +35,20 @@ */ class CI_DB_postgre_forge extends CI_DB_forge { + /** + * DROP TABLE statement + * + * @var string + */ protected $_drop_table = 'DROP TABLE IF EXISTS %s CASCADE'; + // -------------------------------------------------------------------- + /** * Process Fields * - * @param mixed the fields + * @param mixed $fields + * @param array $primary_keys * @return string */ protected function _process_fields($fields, $primary_keys = array()) @@ -190,13 +199,10 @@ class CI_DB_postgre_forge extends CI_DB_forge { * Generates a platform-specific query so that a table can be altered * Called by add_column(), drop_column(), and column_alter(), * - * @param string the ALTER type (ADD, DROP, CHANGE) - * @param string the column name - * @param string the table name - * @param string the column definition - * @param string the default value - * @param bool should 'NOT NULL' be added - * @param string the field after which we should add the new field + * @param string $alter_type the ALTER type (ADD, DROP, CHANGE) + * @param string $table the table name + * @param string $fields the column definition + * @param string $after_field * @return string */ protected function _alter_table($alter_type, $table, $fields, $after_field = '') diff --git a/system/database/drivers/postgre/postgre_result.php b/system/database/drivers/postgre/postgre_result.php index eb9d647e7..3f73f84c7 100644 --- a/system/database/drivers/postgre/postgre_result.php +++ b/system/database/drivers/postgre/postgre_result.php @@ -1,4 +1,4 @@ -<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed'); +<?php /** * CodeIgniter * @@ -24,6 +24,7 @@ * @since Version 1.0 * @filesource */ +defined('BASEPATH') OR exit('No direct script access allowed'); /** * Postgres Result Class @@ -129,8 +130,9 @@ class CI_DB_postgre_result extends CI_DB_result { * * Moves the internal pointer to the desired offset. We call * this internally before fetching results to make sure the - * result set starts at zero + * result set starts at zero. * + * @param int $n * @return bool */ protected function _data_seek($n = 0) @@ -159,7 +161,7 @@ class CI_DB_postgre_result extends CI_DB_result { * * Returns the result set as an object * - * @param string + * @param string $class_name * @return object */ protected function _fetch_object($class_name = 'stdClass') diff --git a/system/database/drivers/postgre/postgre_utility.php b/system/database/drivers/postgre/postgre_utility.php index c95e6df0c..bae1c6704 100644 --- a/system/database/drivers/postgre/postgre_utility.php +++ b/system/database/drivers/postgre/postgre_utility.php @@ -1,4 +1,4 @@ -<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed'); +<?php /** * CodeIgniter * @@ -24,6 +24,7 @@ * @since Version 1.0 * @filesource */ +defined('BASEPATH') OR exit('No direct script access allowed'); /** * Postgre Utility Class @@ -34,13 +35,26 @@ */ class CI_DB_postgre_utility extends CI_DB_utility { + /** + * List databases statement + * + * @var string + */ protected $_list_databases = 'SELECT datname FROM pg_database'; + + /** + * OPTIMIZE TABLE statement + * + * @var string + */ protected $_optimize_table = 'REINDEX TABLE %s'; + // -------------------------------------------------------------------- + /** - * Postgre Export + * Export * - * @param array Preferences + * @param array $params Preferences * @return mixed */ protected function _backup($params = array()) diff --git a/system/database/drivers/sqlite/sqlite_driver.php b/system/database/drivers/sqlite/sqlite_driver.php index 19824dbbf..85411735c 100644 --- a/system/database/drivers/sqlite/sqlite_driver.php +++ b/system/database/drivers/sqlite/sqlite_driver.php @@ -1,4 +1,4 @@ -<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed'); +<?php /** * CodeIgniter * @@ -24,6 +24,7 @@ * @since Version 1.0 * @filesource */ +defined('BASEPATH') OR exit('No direct script access allowed'); /** * SQLite Database Adapter Class @@ -40,17 +41,24 @@ */ class CI_DB_sqlite_driver extends CI_DB { + /** + * Database driver + * + * @var string + */ public $dbdriver = 'sqlite'; - // The character used to escape with - not needed for SQLite - protected $_escape_char = '"'; - - // clause and character used for LIKE escape sequences - protected $_like_escape_str = " ESCAPE '%s' "; - protected $_like_escape_chr = '!'; + // -------------------------------------------------------------------- + /** + * ORDER BY random keyword + * + * @var string + */ protected $_random_keyword = ' Random()'; // database specific random keyword + // -------------------------------------------------------------------- + /** * Non-persistent database connection * @@ -116,7 +124,7 @@ class CI_DB_sqlite_driver extends CI_DB { /** * Execute the query * - * @param string an SQL query + * @param string $sql an SQL query * @return resource */ protected function _execute($sql) @@ -131,6 +139,7 @@ class CI_DB_sqlite_driver extends CI_DB { /** * Begin Transaction * + * @param bool $test_mode * @return bool */ public function trans_begin($test_mode = FALSE) @@ -193,8 +202,8 @@ class CI_DB_sqlite_driver extends CI_DB { /** * Escape String * - * @param string - * @param bool whether or not the string will be used in a LIKE condition + * @param string $str + * @param bool $like Whether or not the string will be used in a LIKE condition * @return string */ public function escape_str($str, $like = FALSE) @@ -253,7 +262,7 @@ class CI_DB_sqlite_driver extends CI_DB { * * Generates a platform-specific query string so that the table names can be fetched * - * @param bool + * @param bool $prefix_limit * @return string */ protected function _list_tables($prefix_limit = FALSE) @@ -275,7 +284,7 @@ class CI_DB_sqlite_driver extends CI_DB { * * Generates a platform-specific query string so that the column names can be fetched * - * @param string the table name + * @param string $table * @return bool */ protected function _list_columns($table = '') @@ -291,7 +300,7 @@ class CI_DB_sqlite_driver extends CI_DB { * * Generates a platform-specific query so that the column data can be retrieved * - * @param string the table name + * @param string $table * @return string */ protected function _field_data($table) @@ -323,9 +332,9 @@ class CI_DB_sqlite_driver extends CI_DB { * * Generates a platform-specific replace string from the supplied data * - * @param string the table name - * @param array the insert keys - * @param array the insert values + * @param string $table Table name + * @param array $keys INSERT keys + * @param array $values INSERT values * @return string */ protected function _replace($table, $keys, $values) @@ -340,10 +349,10 @@ class CI_DB_sqlite_driver extends CI_DB { * * Generates a platform-specific truncate string from the supplied data * - * If the database does not support the truncate() command, + * If the database does not support the TRUNCATE statement, * then this function maps to 'DELETE FROM table' * - * @param string the table name + * @param string $table * @return string */ protected function _truncate($table) diff --git a/system/database/drivers/sqlite/sqlite_forge.php b/system/database/drivers/sqlite/sqlite_forge.php index e02e327f3..5650af7be 100644 --- a/system/database/drivers/sqlite/sqlite_forge.php +++ b/system/database/drivers/sqlite/sqlite_forge.php @@ -1,4 +1,4 @@ -<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed'); +<?php /** * CodeIgniter * @@ -24,6 +24,7 @@ * @since Version 1.0 * @filesource */ +defined('BASEPATH') OR exit('No direct script access allowed'); /** * SQLite Forge Class diff --git a/system/database/drivers/sqlite/sqlite_result.php b/system/database/drivers/sqlite/sqlite_result.php index eef9787a1..0e6335f73 100644 --- a/system/database/drivers/sqlite/sqlite_result.php +++ b/system/database/drivers/sqlite/sqlite_result.php @@ -1,4 +1,4 @@ -<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed'); +<?php /** * CodeIgniter * @@ -24,6 +24,7 @@ * @since Version 1.0 * @filesource */ +defined('BASEPATH') OR exit('No direct script access allowed'); /** * SQLite Result Class @@ -113,8 +114,9 @@ class CI_DB_sqlite_result extends CI_DB_result { * * Moves the internal pointer to the desired offset. We call * this internally before fetching results to make sure the - * result set starts at zero + * result set starts at zero. * + * @param int $n * @return bool */ protected function _data_seek($n = 0) @@ -143,7 +145,7 @@ class CI_DB_sqlite_result extends CI_DB_result { * * Returns the result set as an object * - * @param string + * @param string $class_name * @return object */ protected function _fetch_object($class_name = 'stdClass') diff --git a/system/database/drivers/sqlite/sqlite_utility.php b/system/database/drivers/sqlite/sqlite_utility.php index 1bcb42d9f..2fd5c85f6 100644 --- a/system/database/drivers/sqlite/sqlite_utility.php +++ b/system/database/drivers/sqlite/sqlite_utility.php @@ -1,4 +1,4 @@ -<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed'); +<?php /** * CodeIgniter * @@ -24,6 +24,7 @@ * @since Version 1.0 * @filesource */ +defined('BASEPATH') OR exit('No direct script access allowed'); /** * SQLite Utility Class @@ -34,12 +35,10 @@ */ class CI_DB_sqlite_utility extends CI_DB_utility { - protected $_list_databases = FALSE; - /** - * SQLite Export + * Export * - * @param array Preferences + * @param array $params Preferences * @return mixed */ protected function _backup($params = array()) diff --git a/system/database/drivers/sqlite3/sqlite3_driver.php b/system/database/drivers/sqlite3/sqlite3_driver.php index cc35d319f..9a2c1eefc 100644 --- a/system/database/drivers/sqlite3/sqlite3_driver.php +++ b/system/database/drivers/sqlite3/sqlite3_driver.php @@ -1,4 +1,4 @@ -<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed'); +<?php /** * CodeIgniter * @@ -24,6 +24,7 @@ * @since Version 1.0 * @filesource */ +defined('BASEPATH') OR exit('No direct script access allowed'); /** * SQLite3 Database Adapter Class @@ -41,17 +42,24 @@ */ class CI_DB_sqlite3_driver extends CI_DB { + /** + * Database driver + * + * @var string + */ public $dbdriver = 'sqlite3'; - // The character used for escaping - protected $_escape_char = '"'; - - // clause and character used for LIKE escape sequences - protected $_like_escape_str = ' ESCAPE \'%s\' '; - protected $_like_escape_chr = '!'; + // -------------------------------------------------------------------- + /** + * ORDER BY random keyword + * + * @var string + */ protected $_random_keyword = ' RANDOM()'; + // -------------------------------------------------------------------- + /** * Non-persistent database connection * @@ -107,13 +115,12 @@ class CI_DB_sqlite3_driver extends CI_DB { /** * Execute the query * - * @param string an SQL query + * @todo Implement use of SQLite3::querySingle(), if needed + * @param string $sql * @return mixed SQLite3Result object or bool */ protected function _execute($sql) { - // TODO: Implement use of SQLite3::querySingle(), if needed - return $this->is_write_type($sql) ? $this->conn_id->exec($sql) : $this->conn_id->query($sql); @@ -124,6 +131,7 @@ class CI_DB_sqlite3_driver extends CI_DB { /** * Begin Transaction * + * @param bool $test_mode * @return bool */ public function trans_begin($test_mode = FALSE) @@ -183,8 +191,8 @@ class CI_DB_sqlite3_driver extends CI_DB { /** * Escape String * - * @param string - * @param bool whether or not the string will be used in a LIKE condition + * @param string $str + * @param bool $like Whether or not the string will be used in a LIKE condition * @return string */ public function escape_str($str, $like = FALSE) @@ -243,7 +251,7 @@ class CI_DB_sqlite3_driver extends CI_DB { * * Generates a platform-specific query string so that the table names can be fetched * - * @param bool + * @param bool $prefix_limit * @return string */ protected function _list_tables($prefix_limit = FALSE) @@ -261,7 +269,7 @@ class CI_DB_sqlite3_driver extends CI_DB { * * Generates a platform-specific query string so that the column names can be fetched * - * @param string the table name + * @param string $table * @return string */ protected function _list_columns($table = '') @@ -277,7 +285,7 @@ class CI_DB_sqlite3_driver extends CI_DB { * * Generates a platform-specific query so that the column data can be retrieved * - * @param string the table name + * @param string $table * @return string */ protected function _field_data($table) @@ -288,25 +296,16 @@ class CI_DB_sqlite3_driver extends CI_DB { // -------------------------------------------------------------------- /** - * The error message string + * Error * - * @return string - */ - protected function _error_message() - { - return $this->conn_id->lastErrorMsg(); - } - - // -------------------------------------------------------------------- - - /** - * The error message number + * Returns an array containing code and message of the last + * database error that has occured. * - * @return int + * @return array */ - protected function _error_number() + public function error() { - return $this->conn_id->lastErrorCode(); + return array('code' => $this->conn_id->lastErrorCode(), 'message' => $this->conn_id->lastErrorMsg()); } // -------------------------------------------------------------------- @@ -316,9 +315,9 @@ class CI_DB_sqlite3_driver extends CI_DB { * * Generates a platform-specific replace string from the supplied data * - * @param string the table name - * @param array the insert keys - * @param array the insert values + * @param string $table Table name + * @param array $keys INSERT keys + * @param array $values INSERT values * @return string */ protected function _replace($table, $keys, $values) @@ -333,10 +332,10 @@ class CI_DB_sqlite3_driver extends CI_DB { * * Generates a platform-specific truncate string from the supplied data * - * If the database does not support the truncate() command, then, + * If the database does not support the TRUNCATE statement, * then this method maps to 'DELETE FROM table' * - * @param string the table name + * @param string $table * @return string */ protected function _truncate($table) diff --git a/system/database/drivers/sqlite3/sqlite3_forge.php b/system/database/drivers/sqlite3/sqlite3_forge.php index f9ae5bcce..e1dd3fa91 100644 --- a/system/database/drivers/sqlite3/sqlite3_forge.php +++ b/system/database/drivers/sqlite3/sqlite3_forge.php @@ -1,4 +1,4 @@ -<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed'); +<?php /** * CodeIgniter * @@ -24,6 +24,7 @@ * @since Version 1.0 * @filesource */ +defined('BASEPATH') OR exit('No direct script access allowed'); /** * SQLite3 Forge Class diff --git a/system/database/drivers/sqlite3/sqlite3_result.php b/system/database/drivers/sqlite3/sqlite3_result.php index 117fb3ce8..153e3480a 100644 --- a/system/database/drivers/sqlite3/sqlite3_result.php +++ b/system/database/drivers/sqlite3/sqlite3_result.php @@ -1,4 +1,4 @@ -<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed'); +<?php /** * CodeIgniter * @@ -24,6 +24,7 @@ * @since Version 1.0 * @filesource */ +defined('BASEPATH') OR exit('No direct script access allowed'); /** * SQLite3 Result Class @@ -37,9 +38,6 @@ */ class CI_DB_sqlite3_result extends CI_DB_result { - // num_fields() might be called multiple times, so we'll use this one to cache it's result - protected $_num_fields; - /** * Number of fields in the result set * @@ -47,9 +45,7 @@ class CI_DB_sqlite3_result extends CI_DB_result { */ public function num_fields() { - return ( ! is_int($this->_num_fields)) - ? $this->_num_fields = $this->result_id->numColumns() - : $this->_num_fields; + return $this->result_id->numColumns(); } // -------------------------------------------------------------------- @@ -134,7 +130,7 @@ class CI_DB_sqlite3_result extends CI_DB_result { * * Returns the result set as an object * - * @param string + * @param string $class_name * @return object */ protected function _fetch_object($class_name = 'stdClass') @@ -165,8 +161,9 @@ class CI_DB_sqlite3_result extends CI_DB_result { * * Moves the internal pointer to the desired offset. We call * this internally before fetching results to make sure the - * result set starts at zero + * result set starts at zero. * + * @param int $n (ignored) * @return array */ protected function _data_seek($n = 0) diff --git a/system/database/drivers/sqlite3/sqlite3_utility.php b/system/database/drivers/sqlite3/sqlite3_utility.php index f58c3d168..6f276ebcc 100644 --- a/system/database/drivers/sqlite3/sqlite3_utility.php +++ b/system/database/drivers/sqlite3/sqlite3_utility.php @@ -1,4 +1,4 @@ -<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed'); +<?php /** * CodeIgniter * @@ -24,6 +24,7 @@ * @since Version 1.0 * @filesource */ +defined('BASEPATH') OR exit('No direct script access allowed'); /** * SQLite3 Utility Class @@ -34,12 +35,10 @@ */ class CI_DB_sqlite3_utility extends CI_DB_utility { - protected $_list_databases = FALSE; - /** - * SQLite Export + * Export * - * @param array Preferences + * @param array $params Preferences * @return mixed */ protected function _backup($params = array()) diff --git a/system/database/drivers/sqlsrv/sqlsrv_driver.php b/system/database/drivers/sqlsrv/sqlsrv_driver.php index bda450e88..de3d87312 100644 --- a/system/database/drivers/sqlsrv/sqlsrv_driver.php +++ b/system/database/drivers/sqlsrv/sqlsrv_driver.php @@ -1,4 +1,4 @@ -<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed'); +<?php /** * CodeIgniter * @@ -24,6 +24,7 @@ * @since Version 2.0.3 * @filesource */ +defined('BASEPATH') OR exit('No direct script access allowed'); /** * SQLSRV Database Adapter Class @@ -40,36 +41,52 @@ */ class CI_DB_sqlsrv_driver extends CI_DB { + /** + * Database driver + * + * @var string + */ public $dbdriver = 'sqlsrv'; - // The character used for escaping - protected $_escape_char = '"'; - - // clause and character used for LIKE escape sequences - protected $_like_escape_str = " ESCAPE '%s' "; - protected $_like_escape_chr = '!'; + // -------------------------------------------------------------------- + /** + * ORDER BY random keyword + * + * @var string + */ protected $_random_keyword = ' NEWID()'; - // SQLSRV-specific properties + /** + * Quoted identifier flag + * + * Whether to use SQL-92 standard quoted identifier + * (double quotes) or brackets for identifier escaping. + * + * @var bool + */ protected $_quoted_identifier = TRUE; + // -------------------------------------------------------------------- + /** - * Non-persistent database connection + * Database connection * + * @param bool $pooling * @return resource */ public function db_connect($pooling = FALSE) { - // Check for a UTF-8 charset being passed as CI's default 'utf8'. - $character_set = (0 === strcasecmp('utf8', $this->char_set)) ? 'UTF-8' : $this->char_set; + $charset = in_array(strtolower($this->char_set), array('utf-8', 'utf8'), TRUE) + ? 'UTF-8' : SQLSRV_ENC_CHAR; $connection = array( 'UID' => empty($this->username) ? '' : $this->username, 'PWD' => empty($this->password) ? '' : $this->password, 'Database' => $this->database, - 'ConnectionPooling' => $pooling ? 1 : 0, - 'CharacterSet' => $character_set, + 'ConnectionPooling' => ($pooling === TRUE) ? 1 : 0, + 'CharacterSet' => $charset, + 'Encrypt' => ($this->encrypt === TRUE) ? 1 : 0, 'ReturnDatesAsStrings' => 1 ); @@ -108,7 +125,7 @@ class CI_DB_sqlsrv_driver extends CI_DB { /** * Select the database * - * @param string database name + * @param string $database * @return bool */ public function db_select($database = '') @@ -132,7 +149,7 @@ class CI_DB_sqlsrv_driver extends CI_DB { /** * Execute the query * - * @param string an SQL query + * @param string $sql an SQL query * @return resource */ protected function _execute($sql) @@ -147,6 +164,7 @@ class CI_DB_sqlsrv_driver extends CI_DB { /** * Begin Transaction * + * @param bool $test_mode * @return bool */ public function trans_begin($test_mode = FALSE) @@ -206,8 +224,8 @@ class CI_DB_sqlsrv_driver extends CI_DB { /** * Escape String * - * @param string - * @param bool whether or not the string will be used in a LIKE condition + * @param string $str + * @param bool $like Whether or not the string will be used in a LIKE condition * @return string */ public function escape_str($str, $like = FALSE) @@ -274,7 +292,7 @@ class CI_DB_sqlsrv_driver extends CI_DB { * Generates a platform-specific query string so that the table names can be fetched * * @param bool - * @return string + * @return string $prefix_limit */ protected function _list_tables($prefix_limit = FALSE) { @@ -298,7 +316,7 @@ class CI_DB_sqlsrv_driver extends CI_DB { * * Generates a platform-specific query string so that the column names can be fetched * - * @param string the table name + * @param string $table * @return string */ protected function _list_columns($table = '') @@ -313,7 +331,7 @@ class CI_DB_sqlsrv_driver extends CI_DB { * * Generates a platform-specific query so that the column data can be retrieved * - * @param string the table name + * @param string $table * @return string */ protected function _field_data($table) @@ -362,49 +380,19 @@ class CI_DB_sqlsrv_driver extends CI_DB { // -------------------------------------------------------------------- /** - * From Tables - * - * This function implicitly groups FROM tables so there is no confusion - * about operator precedence in harmony with SQL standards - * - * @param array - * @return string - */ - protected function _from_tables($tables) - { - return is_array($tables) ? implode(', ', $tables) : $tables; - } - - // -------------------------------------------------------------------- - - /** * Update statement * * Generates a platform-specific update string from the supplied data * - * @param string the table name - * @param array the update data - * @param array the where clause - * @param array the orderby clause (ignored) - * @param array the limit clause (ignored) - * @param array the like clause + * @param string $table + * @param array $values * @return string */ - protected function _update($table, $values, $where, $orderby = array(), $limit = FALSE, $like = array()) + protected function _update($table, $values) { - foreach ($values as $key => $val) - { - $valstr[] = $key.' = '.$val; - } - - $where = empty($where) ? '' : ' WHERE '.implode(' ', $where); - - if ( ! empty($like)) - { - $where .= ($where === '' ? ' WHERE ' : ' AND ').implode(' ', $like); - } - - return 'UPDATE '.$table.' SET '.implode(', ', $valstr).$where; + $this->qb_limit = FALSE; + $this->qb_orderby = array(); + return parent::_update($table, $values); } // -------------------------------------------------------------------- @@ -414,10 +402,10 @@ class CI_DB_sqlsrv_driver extends CI_DB { * * Generates a platform-specific truncate string from the supplied data * - * If the database does not support the truncate() command, + * If the database does not support the TRUNCATE statement, * then this method maps to 'DELETE FROM table' * - * @param string the table name + * @param string $table * @return string */ protected function _truncate($table) @@ -432,60 +420,70 @@ class CI_DB_sqlsrv_driver extends CI_DB { * * Generates a platform-specific delete string from the supplied data * - * @param string the table name - * @param array the where clause - * @param array the like clause - * @param string the limit clause + * @param string $table * @return string */ - protected function _delete($table, $where = array(), $like = array(), $limit = FALSE) + protected function _delete($table) { - $conditions = array(); - - empty($where) OR $conditions[] = implode(' ', $where); - empty($like) OR $conditions[] = implode(' ', $like); - - $conditions = (count($conditions) > 0) ? ' WHERE '.implode(' AND ', $conditions) : ''; + if ($this->qb_limit) + { + return 'WITH ci_delete AS (SELECT TOP '.$this->qb_limit.' * FROM '.$table.$this->_compile_wh('qb_where').') DELETE FROM ci_delete'; + } - return ($limit) - ? 'WITH ci_delete AS (SELECT TOP '.$limit.' * FROM '.$table.$conditions.') DELETE FROM ci_delete' - : 'DELETE FROM '.$table.$conditions; + return parent::_delete($table); } // -------------------------------------------------------------------- /** - * Limit string + * LIMIT * * Generates a platform-specific LIMIT clause * - * @param string the sql query string - * @param int the number of rows to limit the query to - * @param int the offset value + * @param string $sql SQL Query * @return string */ - protected function _limit($sql, $limit, $offset) + protected function _limit($sql) { // As of SQL Server 2012 (11.0.*) OFFSET is supported if (version_compare($this->version(), '11', '>=')) { - return $sql.' OFFSET '.(int) $offset.' ROWS FETCH NEXT '.(int) $limit.' ROWS ONLY'; + return $sql.' OFFSET '.(int) $this->qb_offset.' ROWS FETCH NEXT '.$this->qb_limit.' ROWS ONLY'; } - $limit = $offset + $limit; + $limit = $this->qb_offset + $this->qb_limit; // An ORDER BY clause is required for ROW_NUMBER() to work - if ($offset && ! empty($this->qb_orderby)) + if ($this->qb_offset && ! empty($this->qb_orderby)) { - $orderby = 'ORDER BY '.implode(', ', $this->qb_orderby); + $orderby = $this->_compile_order_by(); // We have to strip the ORDER BY clause - $sql = trim(substr($sql, 0, strrpos($sql, 'ORDER BY '.$orderby))); - - return 'SELECT '.(count($this->qb_select) === 0 ? '*' : implode(', ', $this->qb_select))." FROM (\n" - .preg_replace('/^(SELECT( DISTINCT)?)/i', '\\1 ROW_NUMBER() OVER('.$orderby.') AS '.$this->escape_identifiers('CI_rownum').', ', $sql) - ."\n) ".$this->escape_identifiers('CI_subquery') - ."\nWHERE ".$this->escape_identifiers('CI_rownum').' BETWEEN '.((int) $offset + 1).' AND '.$limit; + $sql = trim(substr($sql, 0, strrpos($sql, $orderby))); + + // Get the fields to select from our subquery, so that we can avoid CI_rownum appearing in the actual results + if (count($this->qb_select) === 0) + { + $select = '*'; // Inevitable + } + else + { + // Use only field names and their aliases, everything else is out of our scope. + $select = array(); + $field_regexp = ($this->_quoted_identifier) + ? '("[^\"]+")' : '(\[[^\]]+\])'; + for ($i = 0, $c = count($this->qb_select); $i < $c; $i++) + { + $select[] = preg_match('/(?:\s|\.)'.$field_regexp.'$/i', $this->qb_select[$i], $m) + ? $m[1] : $this->qb_select[$i]; + } + $select = implode(', ', $select); + } + + return 'SELECT '.$select." FROM (\n\n" + .preg_replace('/^(SELECT( DISTINCT)?)/i', '\\1 ROW_NUMBER() OVER('.trim($orderby).') AS '.$this->escape_identifiers('CI_rownum').', ', $sql) + ."\n\n) ".$this->escape_identifiers('CI_subquery') + ."\nWHERE ".$this->escape_identifiers('CI_rownum').' BETWEEN '.($this->qb_offset + 1).' AND '.$limit; } return preg_replace('/(^\SELECT (DISTINCT)?)/i','\\1 TOP '.$limit.' ', $sql); diff --git a/system/database/drivers/sqlsrv/sqlsrv_forge.php b/system/database/drivers/sqlsrv/sqlsrv_forge.php index ccdb36929..8155565c0 100644 --- a/system/database/drivers/sqlsrv/sqlsrv_forge.php +++ b/system/database/drivers/sqlsrv/sqlsrv_forge.php @@ -1,4 +1,4 @@ -<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed'); +<?php /** * CodeIgniter * @@ -24,6 +24,7 @@ * @since Version 2.0.3 * @filesource */ +defined('BASEPATH') OR exit('No direct script access allowed'); /** * SQLSRV Forge Class @@ -34,8 +35,15 @@ */ class CI_DB_sqlsrv_forge extends CI_DB_forge { + /** + * DROP TABLE statement + * + * @var string + */ protected $_drop_table = 'DROP TABLE %s'; + // -------------------------------------------------------------------- + /** * Create Table * diff --git a/system/database/drivers/sqlsrv/sqlsrv_result.php b/system/database/drivers/sqlsrv/sqlsrv_result.php index fb7a68647..6d24cc995 100644 --- a/system/database/drivers/sqlsrv/sqlsrv_result.php +++ b/system/database/drivers/sqlsrv/sqlsrv_result.php @@ -1,4 +1,4 @@ -<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed'); +<?php /** * CodeIgniter * @@ -24,6 +24,7 @@ * @since Version 1.0 * @filesource */ +defined('BASEPATH') OR exit('No direct script access allowed'); /** * SQLSRV Result Class @@ -145,7 +146,7 @@ class CI_DB_sqlsrv_result extends CI_DB_result { * * Returns the result set as an object * - * @param string + * @param string $class_name * @return object */ protected function _fetch_object($class_name = 'stdClass') diff --git a/system/database/drivers/sqlsrv/sqlsrv_utility.php b/system/database/drivers/sqlsrv/sqlsrv_utility.php index d518cc15a..315090049 100644 --- a/system/database/drivers/sqlsrv/sqlsrv_utility.php +++ b/system/database/drivers/sqlsrv/sqlsrv_utility.php @@ -1,4 +1,4 @@ -<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed'); +<?php /** * CodeIgniter * @@ -24,6 +24,7 @@ * @since Version 2.0.3 * @filesource */ +defined('BASEPATH') OR exit('No direct script access allowed'); /** * SQLSRV Utility Class @@ -34,13 +35,26 @@ */ class CI_DB_sqlsrv_utility extends CI_DB_utility { + /** + * List databases statement + * + * @var string + */ protected $_list_databases = 'EXEC sp_helpdb'; // Can also be: EXEC sp_databases + + /** + * OPTIMIZE TABLE statement + * + * @var string + */ protected $_optimize_table = 'ALTER INDEX all ON %s REORGANIZE'; + // -------------------------------------------------------------------- + /** - * SQLSRV Export + * Export * - * @param array Preferences + * @param array $params Preferences * @return bool */ protected function _backup($params = array()) diff --git a/system/helpers/array_helper.php b/system/helpers/array_helper.php index ed2fe3c4a..0e66e4b77 100644 --- a/system/helpers/array_helper.php +++ b/system/helpers/array_helper.php @@ -1,4 +1,4 @@ -<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed'); +<?php /** * CodeIgniter * @@ -24,6 +24,7 @@ * @since Version 1.0 * @filesource */ +defined('BASEPATH') OR exit('No direct script access allowed'); /** * CodeIgniter Array Helpers diff --git a/system/helpers/captcha_helper.php b/system/helpers/captcha_helper.php index a4383c9d3..e9b167fa9 100644 --- a/system/helpers/captcha_helper.php +++ b/system/helpers/captcha_helper.php @@ -1,4 +1,4 @@ -<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed'); +<?php /** * CodeIgniter * @@ -24,6 +24,7 @@ * @since Version 1.0 * @filesource */ +defined('BASEPATH') OR exit('No direct script access allowed'); /** * CodeIgniter CAPTCHA Helper @@ -80,8 +81,7 @@ if ( ! function_exists('create_captcha')) $current_dir = @opendir($img_path); while ($filename = @readdir($current_dir)) { - if ($filename !== '.' && $filename !== '..' && $filename !== 'index.html' - && (str_replace('.jpg', '', $filename) + $expiration) < $now) + if (substr($filename, -4) === '.jpg' && (str_replace('.jpg', '', $filename) + $expiration) < $now) { @unlink($img_path.$filename); } diff --git a/system/helpers/cookie_helper.php b/system/helpers/cookie_helper.php index f396c76b0..02841409d 100644 --- a/system/helpers/cookie_helper.php +++ b/system/helpers/cookie_helper.php @@ -1,4 +1,4 @@ -<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed'); +<?php /** * CodeIgniter * @@ -24,6 +24,7 @@ * @since Version 1.0 * @filesource */ +defined('BASEPATH') OR exit('No direct script access allowed'); /** * CodeIgniter Cookie Helpers diff --git a/system/helpers/date_helper.php b/system/helpers/date_helper.php index a792f09a2..0fa400d7e 100644 --- a/system/helpers/date_helper.php +++ b/system/helpers/date_helper.php @@ -1,4 +1,4 @@ -<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed'); +<?php /** * CodeIgniter * @@ -24,6 +24,7 @@ * @since Version 1.0 * @filesource */ +defined('BASEPATH') OR exit('No direct script access allowed'); /** * CodeIgniter Date Helpers @@ -119,19 +120,16 @@ if ( ! function_exists('standard_date')) * * As of PHP 5.2, the DateTime extension provides constants that * serve for the exact same purpose and are used with date(). - * Due to that, this function is DEPRECATED and should be removed - * in CodeIgniter 3.1+. * - * Here are two examples of how you should replace it: + * @todo Remove in version 3.1+. + * @deprecated 3.0.0 Use PHP's native date() instead. + * @link http://www.php.net/manual/en/class.datetime.php#datetime.constants.types * - * date(DATE_RFC822, now()); // default - * date(DATE_W3C, $time); // a different format and time + * @example date(DATE_RFC822, now()); // default + * @example date(DATE_W3C, $time); // a different format and time * - * Reference: http://www.php.net/manual/en/class.datetime.php#datetime.constants.types - * - * @deprecated - * @param string the chosen format - * @param int Unix timestamp + * @param string $fmt = 'DATE_RFC822' the chosen format + * @param int $time = NULL Unix timestamp * @return string */ function standard_date($fmt = 'DATE_RFC822', $time = NULL) @@ -452,20 +450,13 @@ if ( ! function_exists('human_to_unix')) return FALSE; } - $split = explode(' ', $datestr); - - list($year, $month, $day) = explode('-', $split[0]); - - $ex = explode(':', $split['1']); + sscanf($datestr, '%d-%d-%d %s %s', $year, $month, $day, $time, $ampm); + sscanf($time, '%d:%d:%d', $hour, $min, $sec); + isset($sec) OR $sec = 0; - $hour = (int) $ex[0]; - $min = (int) $ex[1]; - $sec = ( ! empty($ex[2]) && preg_match('/[0-9]{1,2}/', $ex[2])) - ? (int) $ex[2] : 0; - - if (isset($split[2])) + if (isset($ampm)) { - $ampm = strtolower($split[2]); + $ampm = strtolower($ampm); if ($ampm[0] === 'p' && $hour < 12) { @@ -657,5 +648,136 @@ if ( ! function_exists('timezones')) } } +// ------------------------------------------------------------------------ + +if ( ! function_exists('date_range')) +{ + /** + * Date range + * + * Returns a list of dates within a specified period. + * + * @param int unix_start UNIX timestamp of period start date + * @param int unix_end|days UNIX timestamp of period end date + * or interval in days. + * @param mixed is_unix Specifies whether the second parameter + * is a UNIX timestamp or a day interval + * - TRUE or 'unix' for a timestamp + * - FALSE or 'days' for an interval + * @param string date_format Output date format, same as in date() + * @return array + */ + function date_range($unix_start = '', $mixed = '', $is_unix = TRUE, $format = 'Y-m-d') + { + if ($unix_start == '' OR $mixed == '' OR $format == '') + { + return FALSE; + } + + $is_unix = ! ( ! $is_unix OR $is_unix === 'days'); + + // Validate input and try strtotime() on invalid timestamps/intervals, just in case + if ( ( ! preg_match('/^[0-9]+$/', $unix_start) && ($unix_start = @strtotime($unix_time)) === FALSE) + OR ( ! preg_match('/^[0-9]+$/', $mixed) && ($is_unix === FALSE OR ($mixed = @strtotime($mixed)) === FALSE)) + OR ($is_unix === TRUE && $mixed < $unix_start)) + { + return FALSE; + } + + if ($is_unix && ($unix_start == $mixed OR date($format, $unix_start) === date($format, $mixed))) + { + return array($start_date); + } + + $range = array(); + + /* NOTE: Even though the DateTime object has many useful features, it appears that + * it doesn't always handle properly timezones, when timestamps are passed + * directly to its constructor. Neither of the following gave proper results: + * + * new DateTime('<timestamp>') + * new DateTime('<timestamp>', '<timezone>') + * + * --- available in PHP 5.3: + * + * DateTime::createFromFormat('<format>', '<timestamp>') + * DateTime::createFromFormat('<format>', '<timestamp>', '<timezone') + * + * ... so we'll have to set the timestamp after the object is instantiated. + * Furthermore, in PHP 5.3 we can use DateTime::setTimestamp() to do that and + * given that we have UNIX timestamps - we should use it. + */ + $from = new DateTime(); + + if (is_php('5.3')) + { + $from->setTimestamp($unix_start); + if ($is_unix) + { + $arg = new DateTime(); + $arg->setTimestamp($mixed); + } + else + { + $arg = (int) $mixed; + } + + $period = new DatePeriod($from, new DateInterval('P1D'), $arg); + foreach ($period as $date) + { + $range[] = $date->format($format); + } + + /* If a period end date was passed to the DatePeriod constructor, it might not + * be in our results. Not sure if this is a bug or it's just possible because + * the end date might actually be less than 24 hours away from the previously + * generated DateTime object, but either way - we have to append it manually. + */ + if ( ! is_int($arg) && $range[count($range) - 1] !== $arg->format($format)) + { + $range[] = $arg->format($format); + } + + return $range; + } + + $from->setDate(date('Y', $unix_start), date('n', $unix_start), date('j', $unix_start)); + $from->setTime(date('G', $unix_start), date('i', $unix_start), date('s', $unix_start)); + if ($is_unix) + { + $arg = new DateTime(); + $arg->setDate(date('Y', $mixed), date('n', $mixed), date('j', $mixed)); + $arg->setTime(date('G', $mixed), date('i', $mixed), date('s', $mixed)); + } + else + { + $arg = (int) $mixed; + } + $range[] = $from->format($format); + + if (is_int($arg)) // Day intervals + { + do + { + $from->modify('+1 day'); + $range[] = $from->format($format); + } + while (--$arg > 0); + } + else // end date UNIX timestamp + { + for ($from->modify('+1 day'), $end_check = $arg->format('Ymd'); $from->format('Ymd') < $end_check; $from->modify('+1 day')) + { + $range[] = $from->format($format); + } + + // Our loop only appended dates prior to our end date + $range[] = $arg->format($format); + } + + return $range; + } +} + /* End of file date_helper.php */ /* Location: ./system/helpers/date_helper.php */
\ No newline at end of file diff --git a/system/helpers/directory_helper.php b/system/helpers/directory_helper.php index e7d3b5e8a..7223a2911 100644 --- a/system/helpers/directory_helper.php +++ b/system/helpers/directory_helper.php @@ -1,4 +1,4 @@ -<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed'); +<?php /** * CodeIgniter * @@ -24,6 +24,7 @@ * @since Version 1.0 * @filesource */ +defined('BASEPATH') OR exit('No direct script access allowed'); /** * CodeIgniter Directory Helpers @@ -62,7 +63,7 @@ if ( ! function_exists('directory_map')) while (FALSE !== ($file = readdir($fp))) { // Remove '.', '..', and hidden files [optional] - if ( ! trim($file, '.') OR ($hidden === FALSE && $file[0] === '.')) + if ($file === '.' OR $file === '..' OR ($hidden === FALSE && $file[0] === '.')) { continue; } diff --git a/system/helpers/download_helper.php b/system/helpers/download_helper.php index 0232adfe4..8fe66e222 100644 --- a/system/helpers/download_helper.php +++ b/system/helpers/download_helper.php @@ -1,4 +1,4 @@ -<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed'); +<?php /** * CodeIgniter * @@ -24,6 +24,7 @@ * @since Version 1.0 * @filesource */ +defined('BASEPATH') OR exit('No direct script access allowed'); /** * CodeIgniter Download Helpers @@ -110,14 +111,11 @@ if ( ! function_exists('force_download')) // Internet Explorer-specific headers if (isset($_SERVER['HTTP_USER_AGENT']) && strpos($_SERVER['HTTP_USER_AGENT'], 'MSIE') !== FALSE) { - header('Cache-Control: must-revalidate, post-check=0, pre-check=0'); - header('Pragma: public'); - } - else - { - header('Pragma: no-cache'); + header('Cache-Control: no-cache, no-store, must-revalidate'); } + header('Pragma: no-cache'); + exit($data); } } diff --git a/system/helpers/email_helper.php b/system/helpers/email_helper.php index 2a63b36c9..6f5d17255 100644 --- a/system/helpers/email_helper.php +++ b/system/helpers/email_helper.php @@ -1,4 +1,4 @@ -<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed'); +<?php /** * CodeIgniter * @@ -24,6 +24,7 @@ * @since Version 1.0 * @filesource */ +defined('BASEPATH') OR exit('No direct script access allowed'); /** * CodeIgniter Email Helpers diff --git a/system/helpers/file_helper.php b/system/helpers/file_helper.php index e68bb7f7a..6383007ba 100644 --- a/system/helpers/file_helper.php +++ b/system/helpers/file_helper.php @@ -1,4 +1,4 @@ -<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed'); +<?php /** * CodeIgniter * @@ -24,6 +24,7 @@ * @since Version 1.0 * @filesource */ +defined('BASEPATH') OR exit('No direct script access allowed'); /** * CodeIgniter File Helpers @@ -44,12 +45,10 @@ if ( ! function_exists('read_file')) * * Opens the file specfied in the path and returns it as a string. * - * This function is DEPRECATED and should be removed in - * CodeIgniter 3.1+. Use file_get_contents() instead. - * - * @deprecated - * @param string path to file - * @return string + * @todo Remove in version 3.1+. + * @deprecated 3.0.0 It is now just an alias for PHP's native file_get_contents(). + * @param string $file Path to file + * @return string File contents */ function read_file($file) { @@ -109,7 +108,7 @@ if ( ! function_exists('delete_files')) function delete_files($path, $del_dir = FALSE, $level = 0, $htdocs = FALSE) { // Trim the trailing slash - $path = rtrim($path, DIRECTORY_SEPARATOR); + $path = rtrim($path, '/\\'); if ( ! $current_dir = @opendir($path)) { diff --git a/system/helpers/form_helper.php b/system/helpers/form_helper.php index 1bccac35c..e7bea92cc 100644 --- a/system/helpers/form_helper.php +++ b/system/helpers/form_helper.php @@ -1,4 +1,4 @@ -<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed'); +<?php /** * CodeIgniter * @@ -22,7 +22,9 @@ * @license http://opensource.org/licenses/OSL-3.0 Open Software License (OSL 3.0) * @link http://codeigniter.com * @since Version 1.0 + * @filesource */ +defined('BASEPATH') OR exit('No direct script access allowed'); /** * CodeIgniter Form Helpers @@ -124,9 +126,9 @@ if ( ! function_exists('form_hidden')) * Generates hidden fields. You can pass a simple key/value string or * an associative array with multiple values. * - * @param mixed - * @param string - * @param bool + * @param mixed $name Field name + * @param string $value Field value + * @param bool $recursing * @return string */ function form_hidden($name, $value = '', $recursing = FALSE) @@ -149,7 +151,7 @@ if ( ! function_exists('form_hidden')) if ( ! is_array($value)) { - $form .= '<input type="hidden" name="'.$name.'" value="'.form_prep($value, $name)."\" />\n"; + $form .= '<input type="hidden" name="'.$name.'" value="'.form_prep($value)."\" />\n"; } else { @@ -243,9 +245,9 @@ if ( ! function_exists('form_textarea')) /** * Textarea field * - * @param mixed - * @param string - * @param string + * @param mixed $data + * @param string $value + * @param string $extra * @return string */ function form_textarea($data = '', $value = '', $extra = '') @@ -263,7 +265,7 @@ if ( ! function_exists('form_textarea')) } $name = is_array($data) ? $data['name'] : $data; - return '<textarea '._parse_form_attributes($data, $defaults).$extra.'>'.form_prep($val, $name)."</textarea>\n"; + return '<textarea '._parse_form_attributes($data, $defaults).$extra.'>'.form_prep($val, TRUE)."</textarea>\n"; } } @@ -298,10 +300,10 @@ if ( ! function_exists('form_dropdown')) /** * Drop-down Menu * - * @param string - * @param array - * @param string - * @param string + * @param mixed $name + * @param mixed $options + * @param mixed $selected + * @param mixed $extra * @return string */ function form_dropdown($name = '', $options = array(), $selected = array(), $extra = '') @@ -316,10 +318,7 @@ if ( ! function_exists('form_dropdown')) return form_dropdown($name['name'], $name['options'], $name['selected'], $name['extra']); } - if ( ! is_array($selected)) - { - $selected = array($selected); - } + is_array($selected) OR $selected = array($selected); // If no selected state was submitted we will attempt to set it automatically if (count($selected) === 0 && isset($_POST[$name])) @@ -352,14 +351,17 @@ if ( ! function_exists('form_dropdown')) foreach ($val as $optgroup_key => $optgroup_val) { $sel = in_array($optgroup_key, $selected) ? ' selected="selected"' : ''; - $form .= '<option value="'.$optgroup_key.'"'.$sel.'>'.(string) $optgroup_val."</option>\n"; + $form .= '<option value="'.form_prep($optgroup_key).'"'.$sel.'>' + .(string) $optgroup_val."</option>\n"; } $form .= "</optgroup>\n"; } else { - $form .= '<option value="'.$key.'"'.(in_array($key, $selected) ? ' selected="selected"' : '').'>'.(string) $val."</option>\n"; + $form .= '<option value="'.form_prep($key).'"' + .(in_array($key, $selected) ? ' selected="selected"' : '').'>' + .(string) $val."</option>\n"; } } @@ -600,45 +602,28 @@ if ( ! function_exists('form_prep')) * * Formats text so that it can be safely placed in a form field in the event it has HTML tags. * - * @param string - * @param string - * @return string + * @param string|string[] $str Value to escape + * @param bool $is_textarea Whether we're escaping for a textarea element + * @return string|string[] Escaped values */ - function form_prep($str = '', $field_name = '') + function form_prep($str = '', $is_textarea = FALSE) { - static $prepped_fields = array(); - - // if the field name is an array we do this recursively if (is_array($str)) { - foreach ($str as $key => $val) + foreach (array_keys($str) as $key) { - $str[$key] = form_prep($val); + $str[$key] = form_prep($str[$key], $is_textarea); } return $str; } - if ($str === '') - { - return ''; - } - - // we've already prepped a field with this name - // @todo need to figure out a way to namespace this so - // that we know the *exact* field and not just one with - // the same name - if (isset($prepped_fields[$field_name])) - { - return $str; - } - - if ($field_name !== '') + if ($is_textarea === TRUE) { - $prepped_fields[$field_name] = $field_name; + return str_replace(array('<', '>'), array('<', '>'), stripslashes($str)); } - return html_escape($str); + return str_replace(array("'", '"'), array(''', '"'), stripslashes($str)); } } @@ -653,23 +638,21 @@ if ( ! function_exists('set_value')) * re-populate an input field or textarea. If Form Validation * is active it retrieves the info from the validation class * - * @param string - * @param string - * @return mixed + * @param string $field Field name + * @param string $default Default value + * @param bool $is_textarea Whether the field is a textarea element + * @return string */ - function set_value($field = '', $default = '') + function set_value($field = '', $default = '', $is_textarea = FALSE) { if (FALSE === ($OBJ =& _get_validation_object())) { - if ( ! isset($_POST[$field])) - { - return $default; - } - - return form_prep($_POST[$field], $field); + return isset($_POST[$field]) + ? form_prep($_POST[$field], $is_textarea) + : form_prep($default, $is_textarea); } - return form_prep($OBJ->set_value($field, $default), $field); + return form_prep($OBJ->set_value($field, $default), $is_textarea); } } @@ -890,8 +873,8 @@ if ( ! function_exists('_parse_form_attributes')) * * Helper function used by some of the form helpers * - * @param array - * @param array + * @param array $attributes List of attributes + * @param array $default Default values * @return string */ function _parse_form_attributes($attributes, $default) @@ -919,7 +902,11 @@ if ( ! function_exists('_parse_form_attributes')) { if ($key === 'value') { - $val = form_prep($val, $default['name']); + $val = form_prep($val); + } + elseif ($key === 'name' && ! strlen($default['name'])) + { + continue; } $att .= $key.'="'.$val.'" '; diff --git a/system/helpers/html_helper.php b/system/helpers/html_helper.php index 2372e8174..404392f06 100644 --- a/system/helpers/html_helper.php +++ b/system/helpers/html_helper.php @@ -1,4 +1,4 @@ -<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed'); +<?php /** * CodeIgniter * @@ -24,6 +24,7 @@ * @since Version 1.0 * @filesource */ +defined('BASEPATH') OR exit('No direct script access allowed'); /** * CodeIgniter HTML Helpers diff --git a/system/helpers/inflector_helper.php b/system/helpers/inflector_helper.php index 647d840e4..6f1086a00 100644 --- a/system/helpers/inflector_helper.php +++ b/system/helpers/inflector_helper.php @@ -1,4 +1,4 @@ -<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed'); +<?php /** * CodeIgniter * @@ -24,6 +24,7 @@ * @since Version 1.0 * @filesource */ +defined('BASEPATH') OR exit('No direct script access allowed'); /** * CodeIgniter Inflector Helpers diff --git a/system/helpers/language_helper.php b/system/helpers/language_helper.php index bd567ed79..658be6de7 100644 --- a/system/helpers/language_helper.php +++ b/system/helpers/language_helper.php @@ -1,4 +1,4 @@ -<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed'); +<?php /** * CodeIgniter * @@ -24,6 +24,7 @@ * @since Version 1.0 * @filesource */ +defined('BASEPATH') OR exit('No direct script access allowed'); /** * CodeIgniter Language Helpers diff --git a/system/helpers/number_helper.php b/system/helpers/number_helper.php index e49f2f7a0..b93096543 100644 --- a/system/helpers/number_helper.php +++ b/system/helpers/number_helper.php @@ -1,4 +1,4 @@ -<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed'); +<?php /** * CodeIgniter * @@ -24,6 +24,7 @@ * @since Version 1.0 * @filesource */ +defined('BASEPATH') OR exit('No direct script access allowed'); /** * CodeIgniter Number Helpers diff --git a/system/helpers/path_helper.php b/system/helpers/path_helper.php index 166fef065..5a798b118 100644 --- a/system/helpers/path_helper.php +++ b/system/helpers/path_helper.php @@ -1,4 +1,4 @@ -<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed'); +<?php /** * CodeIgniter * @@ -24,6 +24,7 @@ * @since Version 1.0 * @filesource */ +defined('BASEPATH') OR exit('No direct script access allowed'); /** * CodeIgniter Path Helpers diff --git a/system/helpers/security_helper.php b/system/helpers/security_helper.php index 5ecc960bc..898a49c80 100644 --- a/system/helpers/security_helper.php +++ b/system/helpers/security_helper.php @@ -1,4 +1,4 @@ -<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed'); +<?php /** * CodeIgniter * @@ -24,6 +24,7 @@ * @since Version 1.0 * @filesource */ +defined('BASEPATH') OR exit('No direct script access allowed'); /** * CodeIgniter Security Helpers @@ -77,12 +78,10 @@ if ( ! function_exists('do_hash')) /** * Hash encode a string * - * This function is DEPRECATED and should be removed in - * CodeIgniter 3.1+. Use hash() instead. - * - * @deprecated - * @param string - * @param string + * @todo Remove in version 3.1+. + * @deprecated 3.0.0 Use PHP's native hash() instead. + * @param string $str + * @param string $type = 'sha1' * @return string */ function do_hash($str, $type = 'sha1') diff --git a/system/helpers/smiley_helper.php b/system/helpers/smiley_helper.php index b6b2afcf4..6ae8937ee 100644 --- a/system/helpers/smiley_helper.php +++ b/system/helpers/smiley_helper.php @@ -1,4 +1,4 @@ -<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed'); +<?php /** * CodeIgniter * @@ -24,6 +24,7 @@ * @since Version 1.0 * @filesource */ +defined('BASEPATH') OR exit('No direct script access allowed'); /** * CodeIgniter Smiley Helpers diff --git a/system/helpers/string_helper.php b/system/helpers/string_helper.php index 4eee2a262..c895d5767 100644 --- a/system/helpers/string_helper.php +++ b/system/helpers/string_helper.php @@ -1,4 +1,4 @@ -<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed'); +<?php /** * CodeIgniter * @@ -24,6 +24,7 @@ * @since Version 1.0 * @filesource */ +defined('BASEPATH') OR exit('No direct script access allowed'); /** * CodeIgniter String Helpers @@ -276,8 +277,11 @@ if ( ! function_exists('repeater')) /** * Repeater function * - * @param string - * @param int number of repeats + * @todo Remove in version 3.1+. + * @deprecated 3.0.0 This is just an alias for PHP's native str_repeat() + * + * @param string $data String to repeat + * @param int $num Number of repeats * @return string */ function repeater($data, $num = 1) diff --git a/system/helpers/text_helper.php b/system/helpers/text_helper.php index 8a1f01b51..cce659231 100644 --- a/system/helpers/text_helper.php +++ b/system/helpers/text_helper.php @@ -1,4 +1,4 @@ -<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed'); +<?php /** * CodeIgniter * @@ -24,6 +24,7 @@ * @since Version 1.0 * @filesource */ +defined('BASEPATH') OR exit('No direct script access allowed'); /** * CodeIgniter Text Helpers @@ -89,7 +90,8 @@ if ( ! function_exists('character_limiter')) return $str; } - $str = preg_replace('/\s+/', ' ', str_replace(array("\r\n", "\r", "\n"), ' ', $str)); + // a bit complicated, but faster than preg_replace with \s+ + $str = preg_replace('/ {2,}/', ' ', str_replace(array("\r", "\n", "\t", "\x0B", "\x0C"), ' ', $str)); if (strlen($str) <= $n) { @@ -117,18 +119,15 @@ if ( ! function_exists('ascii_to_entities')) /** * High ASCII to Entities * - * Converts High ascii text and MS Word special characters to character entities + * Converts high ASCII text and MS Word special characters to character entities * - * @param string + * @param string $str * @return string */ function ascii_to_entities($str) { - $count = 1; - $out = ''; - $temp = array(); - - for ($i = 0, $s = strlen($str); $i < $s; $i++) + $out = ''; + for ($i = 0, $s = strlen($str), $count = 1, $temp = array(); $i < $s; $i++) { $ordinal = ord($str[$i]); @@ -389,19 +388,19 @@ if ( ! function_exists('convert_accented_characters')) // ------------------------------------------------------------------------ -/** - * Word Wrap - * - * Wraps text at the specified character. Maintains the integrity of words. - * Anything placed between {unwrap}{/unwrap} will not be word wrapped, nor - * will URLs. - * - * @param string the text string - * @param int the number of characters to wrap at - * @return string - */ if ( ! function_exists('word_wrap')) { + /** + * Word Wrap + * + * Wraps text at the specified character. Maintains the integrity of words. + * Anything placed between {unwrap}{/unwrap} will not be word wrapped, nor + * will URLs. + * + * @param string $str the text string + * @param int $charlim = 76 the number of characters to wrap at + * @return string + */ function word_wrap($str, $charlim = 76) { // Set the character limit diff --git a/system/helpers/typography_helper.php b/system/helpers/typography_helper.php index 9dbba0679..48f1f1147 100644 --- a/system/helpers/typography_helper.php +++ b/system/helpers/typography_helper.php @@ -1,4 +1,4 @@ -<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed'); +<?php /** * CodeIgniter * @@ -24,6 +24,7 @@ * @since Version 1.0 * @filesource */ +defined('BASEPATH') OR exit('No direct script access allowed'); /** * CodeIgniter Typography Helpers @@ -60,9 +61,8 @@ if ( ! function_exists('auto_typography')) /** * Auto Typography Wrapper Function * - * @param string - * @param bool whether to allow javascript event handlers - * @param bool whether to reduce multiple instances of double newlines to two + * @param string $str + * @param bool $reduce_linebreaks = FALSE whether to reduce multiple instances of double newlines to two * @return string */ function auto_typography($str, $reduce_linebreaks = FALSE) diff --git a/system/helpers/url_helper.php b/system/helpers/url_helper.php index 57208c948..8e9cb7b03 100644 --- a/system/helpers/url_helper.php +++ b/system/helpers/url_helper.php @@ -1,4 +1,4 @@ -<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed'); +<?php /** * CodeIgniter * @@ -24,6 +24,7 @@ * @since Version 1.0 * @filesource */ +defined('BASEPATH') OR exit('No direct script access allowed'); /** * CodeIgniter URL Helpers @@ -388,40 +389,43 @@ if ( ! function_exists('auto_link')) for ($i = 0, $c = count($matches[0]); $i < $c; $i++) { - if (preg_match('|\.$|', $matches[6][$i])) + if (preg_match('/(\.|\,)$/i', $matches[6][$i], $m)) { - $period = '.'; + $punct = $m[1]; $matches[6][$i] = substr($matches[6][$i], 0, -1); } else { - $period = ''; + $punct = ''; } $str = str_replace($matches[0][$i], $matches[1][$i].'<a href="http'.$matches[4][$i].'://' .$matches[5][$i].$matches[6][$i].'"'.$pop.'>http' .$matches[4][$i].'://'.$matches[5][$i] - .$matches[6][$i].'</a>'.$period, + .$matches[6][$i].'</a>'.$punct, $str); } } - if ($type !== 'url' && preg_match_all('/([a-zA-Z0-9_\.\-\+]+)@([a-zA-Z0-9\-]+)\.([a-zA-Z0-9\-\.]*)/i', $str, $matches)) + if ($type !== 'url' && preg_match_all('/([a-zA-Z0-9_\.\-\+]+)@([a-zA-Z0-9\-]+)\.([a-zA-Z0-9\-\.]+)/i', $str, $matches)) { for ($i = 0, $c = count($matches); $i < $c; $i++) { - if (preg_match('|\.$|', $matches[3][$i])) + if (preg_match('/(\.|\,)$/i', $matches[3][$i], $m)) { - $period = '.'; + $punct = $m[1]; $matches[3][$i] = substr($matches[3][$i], 0, -1); } else { - $period = ''; + $punct = ''; } - $str = str_replace($matches[0][$i], safe_mailto($matches[1][$i].'@'.$matches[2][$i].'.'.$matches[3][$i]).$period, $str); + if (filter_var(($m = $matches[1][$i].'@'.$matches[2][$i].'.'.$matches[3][$i]), FILTER_VALIDATE_EMAIL) !== FALSE) + { + $str = str_replace($matches[0][$i], safe_mailto($m).$punct, $str); + } } } @@ -486,7 +490,7 @@ if ( ! function_exists('url_title')) $separator = '_'; } - $q_separator = preg_quote($separator); + $q_separator = preg_quote($separator, '#'); $trans = array( '&.+?;' => '', @@ -534,7 +538,7 @@ if ( ! function_exists('redirect')) } // IIS environment likely? Use 'refresh' for better compatibility - if (DIRECTORY_SEPARATOR !== '/' && $method === 'auto') + if ($method === 'auto' && isset($_SERVER['SERVER_SOFTWARE']) && strpos($_SERVER['SERVER_SOFTWARE'], 'Microsoft-IIS') !== FALSE) { $method = 'refresh'; } diff --git a/system/helpers/xml_helper.php b/system/helpers/xml_helper.php index 1431777d2..c3dfdcddb 100644 --- a/system/helpers/xml_helper.php +++ b/system/helpers/xml_helper.php @@ -1,4 +1,4 @@ -<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed'); +<?php /** * CodeIgniter * @@ -24,6 +24,7 @@ * @since Version 1.0 * @filesource */ +defined('BASEPATH') OR exit('No direct script access allowed'); /** * CodeIgniter XML Helpers diff --git a/system/language/english/calendar_lang.php b/system/language/english/calendar_lang.php index a70a564e8..288eb91d8 100644 --- a/system/language/english/calendar_lang.php +++ b/system/language/english/calendar_lang.php @@ -24,6 +24,7 @@ * @since Version 1.0 * @filesource */ +defined('BASEPATH') OR exit('No direct script access allowed'); $lang['cal_su'] = 'Su'; $lang['cal_mo'] = 'Mo'; diff --git a/system/language/english/date_lang.php b/system/language/english/date_lang.php index 229d33d2e..db1e9e0ff 100644 --- a/system/language/english/date_lang.php +++ b/system/language/english/date_lang.php @@ -24,21 +24,22 @@ * @since Version 1.0 * @filesource */ +defined('BASEPATH') OR exit('No direct script access allowed'); -$lang['date_year'] = "Year"; -$lang['date_years'] = "Years"; -$lang['date_month'] = "Month"; -$lang['date_months'] = "Months"; -$lang['date_week'] = "Week"; -$lang['date_weeks'] = "Weeks"; -$lang['date_day'] = "Day"; -$lang['date_days'] = "Days"; -$lang['date_hour'] = "Hour"; -$lang['date_hours'] = "Hours"; -$lang['date_minute'] = "Minute"; -$lang['date_minutes'] = "Minutes"; -$lang['date_second'] = "Second"; -$lang['date_seconds'] = "Seconds"; +$lang['date_year'] = 'Year'; +$lang['date_years'] = 'Years'; +$lang['date_month'] = 'Month'; +$lang['date_months'] = 'Months'; +$lang['date_week'] = 'Week'; +$lang['date_weeks'] = 'Weeks'; +$lang['date_day'] = 'Day'; +$lang['date_days'] = 'Days'; +$lang['date_hour'] = 'Hour'; +$lang['date_hours'] = 'Hours'; +$lang['date_minute'] = 'Minute'; +$lang['date_minutes'] = 'Minutes'; +$lang['date_second'] = 'Second'; +$lang['date_seconds'] = 'Seconds'; $lang['UM12'] = '(UTC -12:00) Baker/Howland Island'; $lang['UM11'] = '(UTC -11:00) Niue'; diff --git a/system/language/english/db_lang.php b/system/language/english/db_lang.php index 479cbb167..180bd4a0e 100644 --- a/system/language/english/db_lang.php +++ b/system/language/english/db_lang.php @@ -24,6 +24,7 @@ * @since Version 1.0 * @filesource */ +defined('BASEPATH') OR exit('No direct script access allowed'); $lang['db_invalid_connection_str'] = 'Unable to determine the database settings based on the connection string you submitted.'; $lang['db_unable_to_connect'] = 'Unable to connect to your database server using the provided settings.'; diff --git a/system/language/english/email_lang.php b/system/language/english/email_lang.php index 0de9aa27e..646a49647 100644 --- a/system/language/english/email_lang.php +++ b/system/language/english/email_lang.php @@ -24,6 +24,7 @@ * @since Version 1.0 * @filesource */ +defined('BASEPATH') OR exit('No direct script access allowed'); $lang['email_must_be_array'] = 'The email validation method must be passed an array.'; $lang['email_invalid_address'] = 'Invalid email address: %s'; diff --git a/system/language/english/form_validation_lang.php b/system/language/english/form_validation_lang.php index 021776161..52ca21f92 100644 --- a/system/language/english/form_validation_lang.php +++ b/system/language/english/form_validation_lang.php @@ -24,6 +24,7 @@ * @since Version 1.0 * @filesource */ +defined('BASEPATH') OR exit('No direct script access allowed'); $lang['required'] = 'The %s field is required.'; $lang['isset'] = 'The %s field must have a value.'; @@ -42,9 +43,10 @@ $lang['is_numeric'] = 'The %s field must contain only numeric characters.'; $lang['integer'] = 'The %s field must contain an integer.'; $lang['regex_match'] = 'The %s field is not in the correct format.'; $lang['matches'] = 'The %s field does not match the %s field.'; +$lang['differs'] = 'The %s field must differ from the %s field.'; $lang['is_unique'] = 'The %s field must contain a unique value.'; -$lang['is_natural'] = 'The %s field must contain only positive numbers.'; -$lang['is_natural_no_zero'] = 'The %s field must contain a number greater than zero.'; +$lang['is_natural'] = 'The %s field must only contain digits.'; +$lang['is_natural_no_zero'] = 'The %s field must only contain digits and must be greater than zero.'; $lang['decimal'] = 'The %s field must contain a decimal number.'; $lang['less_than'] = 'The %s field must contain a number less than %s.'; $lang['less_than_equal_to'] = 'The %s field must contain a number less than or equal to %s.'; diff --git a/system/language/english/ftp_lang.php b/system/language/english/ftp_lang.php index 24923c8d8..090a88c28 100644 --- a/system/language/english/ftp_lang.php +++ b/system/language/english/ftp_lang.php @@ -24,6 +24,7 @@ * @since Version 1.0 * @filesource */ +defined('BASEPATH') OR exit('No direct script access allowed'); $lang['ftp_no_connection'] = 'Unable to locate a valid connection ID. Please make sure you are connected before peforming any file routines.'; $lang['ftp_unable_to_connect'] = 'Unable to connect to your FTP server using the supplied hostname.'; diff --git a/system/language/english/imglib_lang.php b/system/language/english/imglib_lang.php index d755437f2..296c4af68 100644 --- a/system/language/english/imglib_lang.php +++ b/system/language/english/imglib_lang.php @@ -24,6 +24,7 @@ * @since Version 1.0 * @filesource */ +defined('BASEPATH') OR exit('No direct script access allowed'); $lang['imglib_source_image_required'] = 'You must specify a source image in your preferences.'; $lang['imglib_gd_required'] = 'The GD image library is required for this feature.'; diff --git a/system/language/english/migration_lang.php b/system/language/english/migration_lang.php index 5753c00bf..714a1e304 100644 --- a/system/language/english/migration_lang.php +++ b/system/language/english/migration_lang.php @@ -24,6 +24,7 @@ * @since Version 3.0 * @filesource */ +defined('BASEPATH') OR exit('No direct script access allowed'); $lang['migration_none_found'] = 'No migrations were found.'; $lang['migration_not_found'] = 'No migration could be found with the version number: %d.'; @@ -33,6 +34,5 @@ $lang['migration_missing_up_method'] = 'The migration class "%s" is missing an " $lang['migration_missing_down_method'] = 'The migration class "%s" is missing a "down" method.'; $lang['migration_invalid_filename'] = 'Migration "%s" has an invalid filename.'; - /* End of file migration_lang.php */ /* Location: ./system/language/english/migration_lang.php */
\ No newline at end of file diff --git a/system/language/english/number_lang.php b/system/language/english/number_lang.php index 429c64738..019013a49 100644 --- a/system/language/english/number_lang.php +++ b/system/language/english/number_lang.php @@ -24,6 +24,7 @@ * @since Version 1.0 * @filesource */ +defined('BASEPATH') OR exit('No direct script access allowed'); $lang['terabyte_abbr'] = 'TB'; $lang['gigabyte_abbr'] = 'GB'; diff --git a/system/language/english/profiler_lang.php b/system/language/english/profiler_lang.php index 112527faa..6ffcd9349 100644 --- a/system/language/english/profiler_lang.php +++ b/system/language/english/profiler_lang.php @@ -24,6 +24,7 @@ * @since Version 1.0 * @filesource */ +defined('BASEPATH') OR exit('No direct script access allowed'); $lang['profiler_database'] = 'DATABASE'; $lang['profiler_controller_info'] = 'CLASS/METHOD'; diff --git a/system/language/english/unit_test_lang.php b/system/language/english/unit_test_lang.php index 146ec25b4..ed452615f 100644 --- a/system/language/english/unit_test_lang.php +++ b/system/language/english/unit_test_lang.php @@ -24,6 +24,7 @@ * @since Version 1.0 * @filesource */ +defined('BASEPATH') OR exit('No direct script access allowed'); $lang['ut_test_name'] = 'Test Name'; $lang['ut_test_datatype'] = 'Test Datatype'; diff --git a/system/language/english/upload_lang.php b/system/language/english/upload_lang.php index d70e7f20f..88f9ac372 100644 --- a/system/language/english/upload_lang.php +++ b/system/language/english/upload_lang.php @@ -24,6 +24,7 @@ * @since Version 1.0 * @filesource */ +defined('BASEPATH') OR exit('No direct script access allowed'); $lang['upload_userfile_not_set'] = 'Unable to find a post variable called userfile.'; $lang['upload_file_exceeds_limit'] = 'The uploaded file exceeds the maximum allowed size in your PHP configuration file.'; diff --git a/system/libraries/Cache/Cache.php b/system/libraries/Cache/Cache.php index 4395cf411..e76fdc557 100644 --- a/system/libraries/Cache/Cache.php +++ b/system/libraries/Cache/Cache.php @@ -1,4 +1,4 @@ -<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed'); +<?php /** * CodeIgniter * @@ -18,12 +18,13 @@ * * @package CodeIgniter * @author EllisLab Dev Team - * @copyright Copyright (c) 2006 - 2012 EllisLab, Inc. + * @copyright Copyright (c) 2008 - 2012, EllisLab, Inc. (http://ellislab.com/) * @license http://opensource.org/licenses/OSL-3.0 Open Software License (OSL 3.0) * @link http://codeigniter.com * @since Version 2.0 * @filesource */ +defined('BASEPATH') OR exit('No direct script access allowed'); /** * CodeIgniter Caching Class @@ -41,7 +42,7 @@ class CI_Cache extends CI_Driver_Library { * * @var array */ - protected $valid_drivers = array( + protected $valid_drivers = array( 'cache_apc', 'cache_dummy', 'cache_file', @@ -67,16 +68,23 @@ class CI_Cache extends CI_Driver_Library { /** * Fallback driver * - * @param string + * @var string */ protected $_backup_driver = 'dummy'; /** + * Cache key prefix + * + * @var string + */ + public $key_prefix = ''; + + /** * Constructor * * Initialize class properties based on the configuration array. * - * @param array + * @param array $config = array() * @return void */ public function __construct($config = array()) @@ -96,12 +104,11 @@ class CI_Cache extends CI_Driver_Library { } } - if (isset($config['backup'])) + isset($config['key_prefix']) && $this->key_prefix = $config['key_prefix']; + + if (isset($config['backup']) && in_array('cache_'.$config['backup'], $this->valid_drivers)) { - if (in_array('cache_'.$config['backup'], $this->valid_drivers)) - { - $this->_backup_driver = $config['backup']; - } + $this->_backup_driver = $config['backup']; } // If the specified adapter isn't available, check the backup. @@ -129,12 +136,12 @@ class CI_Cache extends CI_Driver_Library { * Look for a value in the cache. If it exists, return the data * if not, return FALSE * - * @param string - * @return mixed value that is stored/FALSE on failure + * @param string $id + * @return mixed value matching $id or FALSE on failure */ public function get($id) { - return $this->{$this->_adapter}->get($id); + return $this->{$this->_adapter}->get($this->key_prefix.$id); } // ------------------------------------------------------------------------ @@ -142,14 +149,14 @@ class CI_Cache extends CI_Driver_Library { /** * Cache Save * - * @param string Unique Key - * @param mixed Data to store - * @param int Length of time (in seconds) to cache the data - * @return bool true on success/false on failure + * @param string $id Cache ID + * @param mixed $data Data to store + * @param int $ttl = 60 Cache TTL (in seconds) + * @return bool TRUE on success, FALSE on failure */ public function save($id, $data, $ttl = 60) { - return $this->{$this->_adapter}->save($id, $data, $ttl); + return $this->{$this->_adapter}->save($this->key_prefix.$id, $data, $ttl); } // ------------------------------------------------------------------------ @@ -157,12 +164,12 @@ class CI_Cache extends CI_Driver_Library { /** * Delete from Cache * - * @param mixed unique identifier of the item in the cache - * @return bool true on success/false on failure + * @param string $id Cache ID + * @return bool TRUE on success, FALSE on failure */ public function delete($id) { - return $this->{$this->_adapter}->delete($id); + return $this->{$this->_adapter}->delete($this->key_prefix.$id); } // ------------------------------------------------------------------------ @@ -170,7 +177,7 @@ class CI_Cache extends CI_Driver_Library { /** * Clean the cache * - * @return bool false on failure/true on success + * @return bool TRUE on success, FALSE on failure */ public function clean() { @@ -182,8 +189,8 @@ class CI_Cache extends CI_Driver_Library { /** * Cache Info * - * @param string user/filehits - * @return mixed array on success, false on failure + * @param string $type = 'user' user/filehits + * @return mixed array containing cache info on success OR FALSE on failure */ public function cache_info($type = 'user') { @@ -195,12 +202,12 @@ class CI_Cache extends CI_Driver_Library { /** * Get Cache Metadata * - * @param mixed key to get cache metadata on - * @return mixed return value from child method + * @param string $id key to get cache metadata on + * @return mixed cache item metadata */ public function get_metadata($id) { - return $this->{$this->_adapter}->get_metadata($id); + return $this->{$this->_adapter}->get_metadata($this->key_prefix.$id); } // ------------------------------------------------------------------------ @@ -208,7 +215,7 @@ class CI_Cache extends CI_Driver_Library { /** * Is the requested driver supported in this environment? * - * @param string The driver to test. + * @param string $driver The driver to test * @return array */ public function is_supported($driver) diff --git a/system/libraries/Cache/drivers/Cache_apc.php b/system/libraries/Cache/drivers/Cache_apc.php index c85034f95..46e633463 100644 --- a/system/libraries/Cache/drivers/Cache_apc.php +++ b/system/libraries/Cache/drivers/Cache_apc.php @@ -1,4 +1,4 @@ -<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed'); +<?php /** * CodeIgniter * @@ -18,12 +18,13 @@ * * @package CodeIgniter * @author EllisLab Dev Team - * @copyright Copyright (c) 2006 - 2012 EllisLab, Inc. + * @copyright Copyright (c) 2008 - 2012, EllisLab, Inc. (http://ellislab.com/) * @license http://opensource.org/licenses/OSL-3.0 Open Software License (OSL 3.0) * @link http://codeigniter.com * @since Version 2.0 * @filesource */ +defined('BASEPATH') OR exit('No direct script access allowed'); /** * CodeIgniter APC Caching Class diff --git a/system/libraries/Cache/drivers/Cache_dummy.php b/system/libraries/Cache/drivers/Cache_dummy.php index 3f2b4b956..a3bdc3c80 100644 --- a/system/libraries/Cache/drivers/Cache_dummy.php +++ b/system/libraries/Cache/drivers/Cache_dummy.php @@ -1,4 +1,4 @@ -<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed'); +<?php /** * CodeIgniter * @@ -18,12 +18,13 @@ * * @package CodeIgniter * @author EllisLab Dev Team - * @copyright Copyright (c) 2006 - 2012 EllisLab, Inc. + * @copyright Copyright (c) 2008 - 2012, EllisLab, Inc. (http://ellislab.com/) * @license http://opensource.org/licenses/OSL-3.0 Open Software License (OSL 3.0) * @link http://codeigniter.com * @since Version 2.0 * @filesource */ +defined('BASEPATH') OR exit('No direct script access allowed'); /** * CodeIgniter Dummy Caching Class diff --git a/system/libraries/Cache/drivers/Cache_file.php b/system/libraries/Cache/drivers/Cache_file.php index 37d77c268..5d370380e 100644 --- a/system/libraries/Cache/drivers/Cache_file.php +++ b/system/libraries/Cache/drivers/Cache_file.php @@ -1,4 +1,4 @@ -<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed'); +<?php /** * CodeIgniter * @@ -18,12 +18,13 @@ * * @package CodeIgniter * @author EllisLab Dev Team - * @copyright Copyright (c) 2006 - 2012 EllisLab, Inc. + * @copyright Copyright (c) 2008 - 2012, EllisLab, Inc. (http://ellislab.com/) * @license http://opensource.org/licenses/OSL-3.0 Open Software License (OSL 3.0) * @link http://codeigniter.com * @since Version 2.0 * @filesource */ +defined('BASEPATH') OR exit('No direct script access allowed'); /** * CodeIgniter File Caching Class diff --git a/system/libraries/Cache/drivers/Cache_memcached.php b/system/libraries/Cache/drivers/Cache_memcached.php index bf90f6197..fae002347 100644 --- a/system/libraries/Cache/drivers/Cache_memcached.php +++ b/system/libraries/Cache/drivers/Cache_memcached.php @@ -1,4 +1,4 @@ -<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed'); +<?php /** * CodeIgniter * @@ -18,12 +18,13 @@ * * @package CodeIgniter * @author EllisLab Dev Team - * @copyright Copyright (c) 2006 - 2012 EllisLab, Inc. + * @copyright Copyright (c) 2008 - 2012, EllisLab, Inc. (http://ellislab.com/) * @license http://opensource.org/licenses/OSL-3.0 Open Software License (OSL 3.0) * @link http://codeigniter.com * @since Version 2.0 * @filesource */ +defined('BASEPATH') OR exit('No direct script access allowed'); /** * CodeIgniter Memcached Caching Class diff --git a/system/libraries/Cache/drivers/Cache_redis.php b/system/libraries/Cache/drivers/Cache_redis.php index e4a26b5f0..60033344b 100644 --- a/system/libraries/Cache/drivers/Cache_redis.php +++ b/system/libraries/Cache/drivers/Cache_redis.php @@ -1,4 +1,4 @@ -<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed'); +<?php /** * CodeIgniter * @@ -18,12 +18,13 @@ * * @package CodeIgniter * @author EllisLab Dev Team - * @copyright Copyright (c) 2006 - 2012 EllisLab, Inc. + * @copyright Copyright (c) 2008 - 2012, EllisLab, Inc. (http://ellislab.com/) * @license http://opensource.org/licenses/OSL-3.0 Open Software License (OSL 3.0) * @link http://codeigniter.com * @since Version 3.0 * @filesource */ +defined('BASEPATH') OR exit('No direct script access allowed'); /** * CodeIgniter Redis Caching Class diff --git a/system/libraries/Cache/drivers/Cache_wincache.php b/system/libraries/Cache/drivers/Cache_wincache.php index 89e9f77c8..383b3afdd 100644 --- a/system/libraries/Cache/drivers/Cache_wincache.php +++ b/system/libraries/Cache/drivers/Cache_wincache.php @@ -1,4 +1,4 @@ -<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed'); +<?php /** * CodeIgniter * @@ -18,12 +18,13 @@ * * @package CodeIgniter * @author EllisLab Dev Team - * @copyright Copyright (c) 2006 - 2012 EllisLab, Inc. + * @copyright Copyright (c) 2008 - 2012, EllisLab, Inc. (http://ellislab.com/) * @license http://opensource.org/licenses/OSL-3.0 Open Software License (OSL 3.0) * @link http://codeigniter.com * @since Version 3.0 * @filesource */ +defined('BASEPATH') OR exit('No direct script access allowed'); /** * CodeIgniter Wincache Caching Class diff --git a/system/libraries/Calendar.php b/system/libraries/Calendar.php index a49f171b9..caa496a5e 100644 --- a/system/libraries/Calendar.php +++ b/system/libraries/Calendar.php @@ -1,4 +1,4 @@ -<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed'); +<?php /** * CodeIgniter * @@ -24,6 +24,7 @@ * @since Version 1.0 * @filesource */ +defined('BASEPATH') OR exit('No direct script access allowed'); /** * CodeIgniter Calendar Class @@ -95,11 +96,13 @@ class CI_Calendar { public $next_prev_url = ''; /** - * Constructor + * Class constructor * - * Loads the calendar language file and sets the default time reference + * Loads the calendar language file and sets the default time reference. * - * @param array + * @uses CI_Lang::$is_loaded + * + * @param array $config Calendar options * @return void */ public function __construct($config = array()) diff --git a/system/libraries/Cart.php b/system/libraries/Cart.php index c442f88da..035a6a42b 100644 --- a/system/libraries/Cart.php +++ b/system/libraries/Cart.php @@ -1,4 +1,4 @@ -<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed'); +<?php /** * CodeIgniter * @@ -24,6 +24,7 @@ * @since Version 1.0 * @filesource */ +defined('BASEPATH') OR exit('No direct script access allowed'); /** * Shopping Cart Class @@ -193,7 +194,7 @@ class CI_Cart { $items['qty'] = (float) $items['qty']; // If the quantity is zero or blank there's nothing for us to do - if ( ! is_numeric($items['qty']) OR $items['qty'] == 0) + if ($items['qty'] == 0) { return FALSE; } @@ -224,15 +225,6 @@ class CI_Cart { // Prep the price. Remove leading zeros and anything that isn't a number or decimal point. $items['price'] = (float) $items['price']; - // Is the price a valid number? - if ( ! is_numeric($items['price'])) - { - log_message('error', 'An invalid price was submitted for product ID: '.$items['id']); - return FALSE; - } - - // -------------------------------------------------------------------- - // We now need to create a unique identifier for the item being inserted into the cart. // Every time something is added to the cart it is stored in the master cart array. // Each row in the cart array, however, must have a unique index that identifies not only @@ -350,12 +342,6 @@ class CI_Cart { // Prep the quantity $items['qty'] = (float) $items['qty']; - // Is the quantity a number? - if ( ! is_numeric($items['qty'])) - { - return FALSE; - } - // Is the quantity zero? If so we will remove the item from the cart. // If the quantity is greater than zero we are updating if ($items['qty'] == 0) @@ -480,17 +466,34 @@ class CI_Cart { // -------------------------------------------------------------------- /** + * Get cart item + * + * Returns the details of a specific item in the cart + * + * @param string $row_id + * @return array + */ + public function get_item($row_id) + { + return (in_array($row_id, array('total_items', 'cart_total'), TRUE) OR ! isset($this->_cart_contents[$row_id])) + ? FALSE + : $this->_cart_contents[$row_id]; + } + + // -------------------------------------------------------------------- + + /** * Has options * * Returns TRUE if the rowid passed to this function correlates to an item * that has options associated with it. * - * @param mixed + * @param string $row_id = '' * @return bool */ - public function has_options($rowid = '') + public function has_options($row_id = '') { - return (isset($this->_cart_contents[$rowid]['options']) && count($this->_cart_contents[$rowid]['options']) !== 0); + return (isset($this->_cart_contents[$row_id]['options']) && count($this->_cart_contents[$row_id]['options']) !== 0); } // -------------------------------------------------------------------- @@ -500,12 +503,12 @@ class CI_Cart { * * Returns the an array of options, for a particular product row ID * - * @param int + * @param string $row_id = '' * @return array */ - public function product_options($rowid = '') + public function product_options($row_id = '') { - return isset($this->_cart_contents[$rowid]['options']) ? $this->_cart_contents[$rowid]['options'] : array(); + return isset($this->_cart_contents[$row_id]['options']) ? $this->_cart_contents[$row_id]['options'] : array(); } // -------------------------------------------------------------------- diff --git a/system/libraries/Driver.php b/system/libraries/Driver.php index d67ee2549..621d22631 100644 --- a/system/libraries/Driver.php +++ b/system/libraries/Driver.php @@ -1,4 +1,4 @@ -<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed'); +<?php /** * CodeIgniter * @@ -24,6 +24,7 @@ * @since Version 1.0 * @filesource */ +defined('BASEPATH') OR exit('No direct script access allowed'); /** * CodeIgniter Driver Library Class @@ -54,14 +55,30 @@ class CI_Driver_Library { protected $lib_name; /** + * Get magic method + * * The first time a child is used it won't exist, so we instantiate it * subsequents calls will go straight to the proper child. * - * @param mixed $child - * @return mixed + * @param string Child class name + * @return object Child class */ public function __get($child) { + // Try to load the driver + return $this->load_driver($child); + } + + /** + * Load driver + * + * Separate load_driver call to support explicit driver load by library or user + * + * @param string Child class name + * @return object Child class + */ + public function load_driver($child) + { if ( ! isset($this->lib_name)) { $this->lib_name = get_class($this); @@ -156,7 +173,8 @@ class CI_Driver { /** * Array of methods and properties for the parent class(es) * - * @var array + * @static + * @var array */ protected static $_reflections = array(); diff --git a/system/libraries/Email.php b/system/libraries/Email.php index 8fd7a79e7..f3718ae7e 100644 --- a/system/libraries/Email.php +++ b/system/libraries/Email.php @@ -1,4 +1,4 @@ -<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed'); +<?php /** * CodeIgniter * @@ -24,6 +24,7 @@ * @since Version 1.0 * @filesource */ +defined('BASEPATH') OR exit('No direct script access allowed'); /** * CodeIgniter Email Class @@ -38,66 +39,352 @@ */ class CI_Email { + /** + * Used as the User-Agent and X-Mailer headers' value. + * + * @var string + */ public $useragent = 'CodeIgniter'; + + /** + * Path to the Sendmail binary. + * + * @var string + */ public $mailpath = '/usr/sbin/sendmail'; // Sendmail path + + /** + * Which method to use for sending e-mails. + * + * @var string 'mail', 'sendmail' or 'smtp' + */ public $protocol = 'mail'; // mail/sendmail/smtp - public $smtp_host = ''; // SMTP Server. Example: mail.earthlink.net - public $smtp_user = ''; // SMTP Username - public $smtp_pass = ''; // SMTP Password - public $smtp_port = 25; // SMTP Port - public $smtp_timeout = 5; // SMTP Timeout in seconds - public $smtp_crypto = ''; // SMTP Encryption. Can be null, tls or ssl. - public $wordwrap = TRUE; // TRUE/FALSE Turns word-wrap on/off - public $wrapchars = 76; // Number of characters to wrap at. - public $mailtype = 'text'; // text/html Defines email formatting - public $charset = 'utf-8'; // Default char set: iso-8859-1 or us-ascii + + /** + * STMP Server host + * + * @var string + */ + public $smtp_host = ''; + + /** + * SMTP Username + * + * @var string + */ + public $smtp_user = ''; + + /** + * SMTP Password + * + * @var string + */ + public $smtp_pass = ''; + + /** + * SMTP Server port + * + * @var int + */ + public $smtp_port = 25; + + /** + * SMTP connection timeout in seconds + * + * @var int + */ + public $smtp_timeout = 5; + + /** + * SMTP Encryption + * + * @var string NULL, 'tls' or 'ssl' + */ + public $smtp_crypto = NULL; + + /** + * Whether to apply word-wrapping to the message body. + * + * @var bool + */ + public $wordwrap = TRUE; + + /** + * Number of characters to wrap at. + * + * @see CI_Email::$wordwrap + * @var int + */ + public $wrapchars = 76; + + /** + * Message format. + * + * @var string 'text' or 'html' + */ + public $mailtype = 'text'; + + /** + * Character set (default: utf-8) + * + * @var string + */ + public $charset = 'utf-8'; + + /** + * Multipart message + * + * @var string 'mixed' (in the body) or 'related' (separate) + */ public $multipart = 'mixed'; // "mixed" (in the body) or "related" (separate) - public $alt_message = ''; // Alternative message for HTML emails - public $validate = FALSE; // TRUE/FALSE. Enables email validation + + /** + * Alternative message (for HTML messages only) + * + * @var string + */ + public $alt_message = ''; + + /** + * Whether to validate e-mail addresses. + * + * @var bool + */ + public $validate = FALSE; + + /** + * X-Priority header value. + * + * @var int 1-5 + */ public $priority = 3; // Default priority (1 - 5) + + /** + * Newline character sequence. + * Use "\r\n" to comply with RFC 822. + * + * @link http://www.ietf.org/rfc/rfc822.txt + * @var string "\r\n" or "\n" + */ public $newline = "\n"; // Default newline. "\r\n" or "\n" (Use "\r\n" to comply with RFC 822) - public $crlf = "\n"; // The RFC 2045 compliant CRLF for quoted-printable is "\r\n". Apparently some servers, - // even on the receiving end think they need to muck with CRLFs, so using "\n", while - // distasteful, is the only thing that seems to work for all environments. - public $dsn = FALSE; // Delivery Status Notification - public $send_multipart = TRUE; // TRUE/FALSE - Yahoo does not like multipart alternative, so this is an override. Set to FALSE for Yahoo. - public $bcc_batch_mode = FALSE; // TRUE/FALSE - Turns on/off Bcc batch feature - public $bcc_batch_size = 200; // If bcc_batch_mode = TRUE, sets max number of Bccs in each batch + /** + * CRLF character sequence + * + * RFC 2045 specifies that for 'quoted-printable' encoding, + * "\r\n" must be used. However, it appears that some servers + * (even on the receiving end) don't handle it properly and + * switching to "\n", while improper, is the only solution + * that seems to work for all environments. + * + * @link http://www.ietf.org/rfc/rfc822.txt + * @var string + */ + public $crlf = "\n"; + + /** + * Whether to use Delivery Status Notification. + * + * @var bool + */ + public $dsn = FALSE; + + /** + * Whether to send multipart alternatives. + * Yahoo! doesn't seem to like these. + * + * @var bool + */ + public $send_multipart = TRUE; + + /** + * Whether to send messages to BCC recipients in batches. + * + * @var bool + */ + public $bcc_batch_mode = FALSE; + + /** + * BCC Batch max number size. + * + * @see CI_Email::$bcc_batch_mode + * @var int + */ + public $bcc_batch_size = 200; + + // -------------------------------------------------------------------- + + /** + * Whether PHP is running in safe mode. Initialized by the class constructor. + * + * @var bool + */ protected $_safe_mode = FALSE; + + /** + * Subject header + * + * @var string + */ protected $_subject = ''; + + /** + * Message body + * + * @var string + */ protected $_body = ''; + + /** + * Final message body to be sent. + * + * @var string + */ protected $_finalbody = ''; + + /** + * multipart/alternative boundary + * + * @var string + */ protected $_alt_boundary = ''; + + /** + * Attachment boundary + * + * @var string + */ protected $_atc_boundary = ''; + + /** + * Final headers to send + * + * @var string + */ protected $_header_str = ''; + + /** + * SMTP Connection socket placeholder + * + * @var resource + */ protected $_smtp_connect = ''; + + /** + * Mail encoding + * + * @var string '8bit' or '7bit' + */ protected $_encoding = '8bit'; - protected $_IP = FALSE; + + /** + * Whether to perform SMTP authentication + * + * @var bool + */ protected $_smtp_auth = FALSE; + + /** + * Whether to send a Reply-To header + * + * @var bool + */ protected $_replyto_flag = FALSE; + + /** + * Debug messages + * + * @see CI_Email::print_debugger() + * @var string + */ protected $_debug_msg = array(); + + /** + * Recipients + * + * @var string[] + */ protected $_recipients = array(); + + /** + * CC Recipients + * + * @var string[] + */ protected $_cc_array = array(); + + /** + * BCC Recipients + * + * @var string[] + */ protected $_bcc_array = array(); + + /** + * Message headers + * + * @var string[] + */ protected $_headers = array(); - protected $_attach_name = array(); - protected $_attach_type = array(); - protected $_attach_disp = array(); + + /** + * Attachment data + * + * @var array + */ + protected $_attachments = array(); + + /** + * Valid $protocol values + * + * @see CI_Email::$protocol + * @var string[] + */ protected $_protocols = array('mail', 'sendmail', 'smtp'); - protected $_base_charsets = array('us-ascii', 'iso-2022-'); // 7-bit charsets (excluding language suffix) + + /** + * Base charsets + * + * Character sets valid for 7-bit encoding, + * excluding language suffix. + * + * @var string[] + */ + protected $_base_charsets = array('us-ascii', 'iso-2022-'); + + /** + * Bit depths + * + * Valid mail encodings + * + * @see CI_Email::$_encoding + * @var string[] + */ protected $_bit_depths = array('7bit', '8bit'); + + /** + * $priority translations + * + * Actual values to send with the X-Priority header + * + * @var string[] + */ protected $_priorities = array('1 (Highest)', '2 (High)', '3 (Normal)', '4 (Low)', '5 (Lowest)'); + // -------------------------------------------------------------------- + /** * Constructor - Sets Email Preferences * * The constructor can be passed an array of config values * + * @param array $config = array() * @return void */ public function __construct($config = array()) { + $this->charset = config_item('charset'); + if (count($config) > 0) { $this->initialize($config); @@ -108,6 +395,8 @@ class CI_Email { $this->_safe_mode = (bool) @ini_get('safe_mode'); } + $this->charset = strtoupper($this->charset); + log_message('debug', 'Email Class Initialized'); } @@ -171,9 +460,7 @@ class CI_Email { if ($clear_attachments !== FALSE) { - $this->_attach_name = array(); - $this->_attach_type = array(); - $this->_attach_disp = array(); + $this->_attachments = array(); } return $this; @@ -184,11 +471,12 @@ class CI_Email { /** * Set FROM * - * @param string - * @param string + * @param string $from + * @param string $name + * @param string $return_path = NULL Return-Path * @return object */ - public function from($from, $name = '') + public function from($from, $name = '', $return_path = NULL) { if (preg_match('/\<(.*)\>/', $from, $match)) { @@ -198,6 +486,10 @@ class CI_Email { if ($this->validate) { $this->validate_email($this->_str_to_array($from)); + if ($return_path) + { + $this->validate_email($this->_str_to_array($return_path)); + } } // prepare the display name @@ -211,12 +503,14 @@ class CI_Email { } else { - $name = $this->_prep_q_encoding($name, TRUE); + $name = $this->_prep_q_encoding($name); } } $this->set_header('From', $name.' <'.$from.'>'); - $this->set_header('Return-Path', '<'.$from.'>'); + + isset($return_path) OR $return_path = $from; + $this->set_header('Return-Path', '<'.$return_path.'>'); return $this; } @@ -281,16 +575,7 @@ class CI_Email { $this->set_header('To', implode(', ', $to)); } - switch ($this->_get_protocol()) - { - case 'smtp': - $this->_recipients = $to; - break; - case 'sendmail': - case 'mail': - $this->_recipients = implode(', ', $to); - break; - } + $this->_recipients = $to; return $this; } @@ -404,14 +689,20 @@ class CI_Email { /** * Assign file attachments * - * @param string + * @param string $filename + * @param string $disposition = 'attachment' + * @param string $newname = NULL + * @param string $mime = '' * @return object */ public function attach($filename, $disposition = '', $newname = NULL, $mime = '') { - $this->_attach_name[] = array($filename, $newname); - $this->_attach_disp[] = empty($disposition) ? 'attachment' : $disposition; // Can also be 'inline' Not sure if it matters - $this->_attach_type[] = $mime; + $this->_attachments[] = array( + 'name' => array($filename, $newname), + 'disposition' => empty($disposition) ? 'attachment' : $disposition, // Can also be 'inline' Not sure if it matters + 'type' => $mime + ); + return $this; } @@ -629,9 +920,9 @@ class CI_Email { { if ($this->mailtype === 'html') { - return (count($this->_attach_name) === 0) ? 'html' : 'html-attach'; + return (count($this->_attachments) === 0) ? 'html' : 'html-attach'; } - elseif ($this->mailtype === 'text' && count($this->_attach_name) > 0) + elseif ($this->mailtype === 'text' && count($this->_attachments) > 0) { return 'plain-attach'; } @@ -741,8 +1032,8 @@ class CI_Email { /** * Build alternative plain text message * - * This public function provides the raw message for use - * in plain-text headers of HTML-formatted emails. + * Provides the raw message for use in plain-text headers of + * HTML-formatted emails. * If the user hasn't specified his own alternative message * it creates one by stripping the HTML * @@ -750,9 +1041,11 @@ class CI_Email { */ protected function _get_alt_message() { - if ($this->alt_message !== '') + if ( ! empty($this->alt_message)) { - return $this->word_wrap($this->alt_message, '76'); + return ($this->wordwrap) + ? $this->word_wrap($this->alt_message, 76) + : $this->alt_message; } $body = preg_match('/\<body.*?\>(.*)\<\/body\>/si', $this->_body, $match) ? $match[1] : $this->_body; @@ -763,7 +1056,12 @@ class CI_Email { $body = str_replace(str_repeat("\n", $i), "\n\n", $body); } - return $this->word_wrap($body, 76); + // Reduce multiple spaces + $body = preg_replace('| +|', ' ', $body); + + return ($this->wordwrap) + ? $this->word_wrap($body, 76) + : $body; } // -------------------------------------------------------------------- @@ -772,26 +1070,26 @@ class CI_Email { * Word Wrap * * @param string - * @param int + * @param int line-length limit * @return string */ - public function word_wrap($str, $charlim = '') + public function word_wrap($str, $charlim = NULL) { - // Se the character limit - if ($charlim === '') + // Set the character limit, if not already present + if (empty($charlim)) { - $charlim = ($this->wrapchars === '') ? 76 : $this->wrapchars; + $charlim = empty($this->wrapchars) ? 76 : $this->wrapchars; } - // Reduce multiple spaces - $str = preg_replace('| +|', ' ', $str); - // Standardize newlines if (strpos($str, "\r") !== FALSE) { $str = str_replace(array("\r\n", "\r"), "\n", $str); } + // Reduce multiple spaces at end of line + $str = preg_replace('| +\n|', "\n", $str); + // If the current word is surrounded by {unwrap} tags we'll // strip the entire chunk and replace it with a marker. $unwrap = array(); @@ -971,7 +1269,6 @@ class CI_Email { $this->_finalbody = $body.$this->_prep_quoted_printable($this->_body).$this->newline.$this->newline; - if ($this->_get_protocol() === 'mail') { $this->_header_str .= $hdr; @@ -981,7 +1278,6 @@ class CI_Email { $this->_finalbody = $hdr.$this->_finalbody; } - if ($this->send_multipart !== FALSE) { $this->_finalbody .= '--'.$this->_alt_boundary.'--'; @@ -1036,14 +1332,15 @@ class CI_Email { } $attachment = array(); - for ($i = 0, $c = count($this->_attach_name), $z = 0; $i < $c; $i++) + for ($i = 0, $c = count($this->_attachments), $z = 0; $i < $c; $i++) { - $filename = $this->_attach_name[$i][0]; - $basename = is_null($this->_attach_name[$i][1]) ? basename($filename) : $this->_attach_name[$i][1]; - $ctype = $this->_attach_type[$i]; + $filename = $this->_attachments[$i]['name'][0]; + $basename = is_null($this->_attachments[$i]['name'][1]) + ? basename($filename) : $this->_attachments[$i]['name'][1]; + $ctype = $this->_attachments[$i]['type']; $file_content = ''; - if ($this->_attach_type[$i] === '') + if ($ctype === '') { if ( ! file_exists($filename)) { @@ -1065,13 +1362,13 @@ class CI_Email { } else { - $file_content =& $this->_attach_content[$i]; + $file_content =& $this->_attachments[$i]['name'][0]; } $attachment[$z++] = '--'.$this->_atc_boundary.$this->newline .'Content-type: '.$ctype.'; ' .'name="'.$basename.'"'.$this->newline - .'Content-Disposition: '.$this->_attach_disp[$i].';'.$this->newline + .'Content-Disposition: '.$this->_attachments[$i]['disposition'].';'.$this->newline .'Content-Transfer-Encoding: base64'.$this->newline; $attachment[$z++] = chunk_split(base64_encode($file_content)); @@ -1091,17 +1388,28 @@ class CI_Email { * Refer to RFC 2045 http://www.ietf.org/rfc/rfc2045.txt * * @param string - * @param int * @return string */ - protected function _prep_quoted_printable($str, $charlim = '') + protected function _prep_quoted_printable($str) { - // Set the character limit - // Don't allow over 76, as that will make servers and MUAs barf - // all over quoted-printable data - if ($charlim === '' OR $charlim > 76) + // We are intentionally wrapping so mail servers will encode characters + // properly and MUAs will behave, so {unwrap} must go! + $str = str_replace(array('{unwrap}', '{/unwrap}'), '', $str); + + // RFC 2045 specifies CRLF as "\r\n". + // However, many developers choose to override that and violate + // the RFC rules due to (apparently) a bug in MS Exchange, + // which only works with "\n". + if ($this->crlf === "\r\n") { - $charlim = 76; + if (is_php('5.3')) + { + return quoted_printable_encode($str); + } + elseif (function_exists('imap_8bit')) + { + return imap_8bit($str); + } } // Reduce multiple spaces & remove nulls @@ -1113,10 +1421,6 @@ class CI_Email { $str = str_replace(array("\r\n", "\r"), "\n", $str); } - // We are intentionally wrapping so mail servers will encode characters - // properly and MUAs will behave, so {unwrap} must go! - $str = str_replace(array('{unwrap}', '{/unwrap}'), '', $str); - $escape = '='; $output = ''; @@ -1146,7 +1450,7 @@ class CI_Email { // If we're at the character limit, add the line to the output, // reset our temp variable, and keep on chuggin' - if ((strlen($temp) + strlen($char)) >= $charlim) + if ((strlen($temp) + strlen($char)) >= 76) { $output .= $temp.$escape.$this->crlf; $temp = ''; @@ -1169,66 +1473,75 @@ class CI_Email { /** * Prep Q Encoding * - * Performs "Q Encoding" on a string for use in email headers. It's related - * but not identical to quoted-printable, so it has its own method + * Performs "Q Encoding" on a string for use in email headers. + * It's related but not identical to quoted-printable, so it has its + * own method. * * @param string - * @param bool set to TRUE for processing From: headers * @return string */ - protected function _prep_q_encoding($str, $from = FALSE) + protected function _prep_q_encoding($str) { - $str = str_replace(array("\r", "\n"), array('', ''), $str); - - // Line length must not exceed 76 characters, so we adjust for - // a space, 7 extra characters =??Q??=, and the charset that we will add to each line - $limit = 75 - 7 - strlen($this->charset); + $str = str_replace(array("\r", "\n"), '', $str); - // these special characters must be converted too - $convert = array('_', '=', '?'); - - if ($from === TRUE) + if ($this->charset === 'UTF-8') { - $convert[] = ','; - $convert[] = ';'; + if (MB_ENABLED === TRUE) + { + return mb_encode_mimeheader($str, $this->charset, 'Q', $this->crlf); + } + elseif (extension_loaded('iconv')) + { + $output = @iconv_mime_encode('', $str, + array( + 'scheme' => 'Q', + 'line-length' => 76, + 'input-charset' => $this->charset, + 'output-charset' => $this->charset, + 'line-break-chars' => $this->crlf + ) + ); + + // There are reports that iconv_mime_encode() might fail and return FALSE + if ($output !== FALSE) + { + // iconv_mime_encode() will always put a header field name. + // We've passed it an empty one, but it still prepends our + // encoded string with ': ', so we need to strip it. + return substr($output, 2); + } + + $chars = iconv_strlen($str, 'UTF-8'); + } } - $output = ''; - $temp = ''; + // We might already have this set for UTF-8 + isset($chars) OR $chars = strlen($str); - for ($i = 0, $length = strlen($str); $i < $length; $i++) + $output = '=?'.$this->charset.'?Q?'; + for ($i = 0, $length = strlen($output), $iconv = extension_loaded('iconv'); $i < $chars; $i++) { - // Grab the next character - $char = $str[$i]; - $ascii = ord($char); - - // convert ALL non-printable ASCII characters and our specials - if ($ascii < 32 OR $ascii > 126 OR in_array($char, $convert)) - { - $char = '='.dechex($ascii); - } + $chr = ($this->charset === 'UTF-8' && $iconv === TRUE) + ? '='.implode('=', str_split(strtoupper(bin2hex(iconv_substr($str, $i, 1, $this->charset))), 2)) + : '='.strtoupper(bin2hex($str[$i])); - // handle regular spaces a bit more compactly than =20 - if ($ascii === 32) + // RFC 2045 sets a limit of 76 characters per line. + // We'll append ?= to the end of each line though. + if ($length + ($l = strlen($chr)) > 74) { - $char = '_'; + $output .= '?='.$this->crlf // EOL + .' =?'.$this->charset.'?Q?'.$chr; // New line + $length = 6 + strlen($this->charset) + $l; // Reset the length for the new line } - - // If we're at the character limit, add the line to the output, - // reset our temp variable, and keep on chuggin' - if ((strlen($temp) + strlen($char)) >= $limit) + else { - $output .= $temp.$this->crlf; - $temp = ''; + $output .= $chr; + $length += $l; } - - // Add the character to our temporary line - $temp .= $char; } - // wrap each line with the shebang, charset, and transfer encoding - // the preceding space on successive lines is required for header "folding" - return trim(preg_replace('/^(.*)$/m', ' =?'.$this->charset.'?Q?$1?=', $output.$temp)); + // End the header + return $output.'?='; } // -------------------------------------------------------------------- @@ -1236,6 +1549,7 @@ class CI_Email { /** * Send Email * + * @param bool $auto_clear = TRUE * @return bool */ public function send($auto_clear = TRUE) @@ -1348,6 +1662,7 @@ class CI_Email { /** * Strip line-breaks via callback * + * @param string $matches * @return string */ protected function _remove_nl_callback($matches) @@ -1391,6 +1706,11 @@ class CI_Email { */ protected function _send_with_mail() { + if (is_array($this->_recipients)) + { + $this->_recipients = implode(', ', $this->_recipients); + } + if ($this->_safe_mode === TRUE) { return mail($this->_recipients, $this->_subject, $this->_finalbody, $this->_header_str); @@ -1399,7 +1719,7 @@ class CI_Email { { // most documentation of sendmail using the "-f" flag lacks a space after it, however // we've encountered servers that seem to require it to be in place. - return mail($this->_recipients, $this->_subject, $this->_finalbody, $this->_header_str, '-f '.$this->clean_email($this->_headers['From'])); + return mail($this->_recipients, $this->_subject, $this->_finalbody, $this->_header_str, '-f '.$this->clean_email($this->_headers['Return-Path'])); } } @@ -1412,7 +1732,7 @@ class CI_Email { */ protected function _send_with_sendmail() { - $fp = @popen($this->mailpath.' -oi -f '.$this->clean_email($this->_headers['From']).' -t', 'w'); + $fp = @popen($this->mailpath.' -oi -f '.$this->clean_email($this->_headers['From']).' -t'.' -r '.$this->clean_email($this->_headers['Return-Path']), 'w'); if ($fp === FALSE OR $fp === NULL) { @@ -1510,7 +1830,6 @@ class CI_Email { /** * SMTP Connect * - * @param string * @return string */ protected function _smtp_connect() @@ -1630,7 +1949,7 @@ class CI_Email { // -------------------------------------------------------------------- /** - * SMTP Authenticate + * SMTP Authenticate * * @return bool */ @@ -1685,11 +2004,12 @@ class CI_Email { /** * Send SMTP data * + * @param string $data * @return bool */ protected function _send_data($data) { - if ( ! fwrite($this->_smtp_connect, $data . $this->newline)) + if ( ! fwrite($this->_smtp_connect, $data.$this->newline)) { $this->_set_error_message('lang:email_smtp_data_failure', $data); return FALSE; @@ -1737,47 +2057,6 @@ class CI_Email { // -------------------------------------------------------------------- /** - * Get IP - * - * @return string - */ - protected function _get_ip() - { - if ($this->_IP !== FALSE) - { - return $this->_IP; - } - - $cip = ( ! empty($_SERVER['HTTP_CLIENT_IP'])) ? $_SERVER['HTTP_CLIENT_IP'] : FALSE; - $rip = ( ! empty($_SERVER['REMOTE_ADDR'])) ? $_SERVER['REMOTE_ADDR'] : FALSE; - if ($cip) $this->_IP = $cip; - elseif ($rip) $this->_IP = $rip; - else - { - $fip = ( ! empty($_SERVER['HTTP_X_FORWARDED_FOR'])) ? $_SERVER['HTTP_X_FORWARDED_FOR'] : FALSE; - if ($fip) - { - $this->_IP = $fip; - } - } - - if (strpos($this->_IP, ',') !== FALSE) - { - $x = explode(',', $this->_IP); - $this->_IP = end($x); - } - - if ( ! preg_match('/^[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}$/', $this->_IP)) - { - $this->_IP = '0.0.0.0'; - } - - return $this->_IP; - } - - // -------------------------------------------------------------------- - - /** * Get Debug Message * * @return string @@ -1802,7 +2081,8 @@ class CI_Email { /** * Set Message * - * @param string + * @param string $msg + * @param string $val = '' * @return void */ protected function _set_error_message($msg, $val = '') diff --git a/system/libraries/Encrypt.php b/system/libraries/Encrypt.php index 8ffd93aea..cdb0a6452 100644 --- a/system/libraries/Encrypt.php +++ b/system/libraries/Encrypt.php @@ -1,4 +1,4 @@ -<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed'); +<?php /** * CodeIgniter * @@ -24,6 +24,7 @@ * @since Version 1.0 * @filesource */ +defined('BASEPATH') OR exit('No direct script access allowed'); /** * CodeIgniter Encryption Class @@ -165,7 +166,7 @@ class CI_Encrypt { */ public function decode($string, $key = '') { - if (preg_match('/[^a-zA-Z0-9\/\+=]/', $string)) + if (preg_match('/[^a-zA-Z0-9\/\+=]/', $string) OR base64_encode(base64_decode($string)) !== $string) { return FALSE; } @@ -484,7 +485,7 @@ class CI_Encrypt { */ public function set_hash($type = 'sha1') { - $this->_hash_type = ($type !== 'sha1' && $type !== 'md5') ? 'sha1' : $type; + $this->_hash_type = in_array($type, hash_algos()) ? $type : 'sha1'; } // -------------------------------------------------------------------- @@ -497,7 +498,7 @@ class CI_Encrypt { */ public function hash($str) { - return ($this->_hash_type === 'sha1') ? sha1($str) : md5($str); + return hash($this->_hash_type, $str); } } diff --git a/system/libraries/Form_validation.php b/system/libraries/Form_validation.php index b490a34ca..e50eee4f2 100644 --- a/system/libraries/Form_validation.php +++ b/system/libraries/Form_validation.php @@ -1,4 +1,4 @@ -<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed'); +<?php /** * CodeIgniter * @@ -24,6 +24,7 @@ * @since Version 1.0 * @filesource */ +defined('BASEPATH') OR exit('No direct script access allowed'); /** * Form Validation Class @@ -134,12 +135,6 @@ class CI_Form_validation { // Automatically load the form helper $this->CI->load->helper('form'); - // Set the character encoding in MB. - if (MB_ENABLED === TRUE) - { - mb_internal_encoding($this->CI->config->item('charset')); - } - log_message('debug', 'Form Validation Class Initialized'); } @@ -445,11 +440,10 @@ class CI_Form_validation { // Load the language file containing error messages $this->CI->lang->load('form_validation'); - // Cycle through the rules for each field, match the - // corresponding $_POST item and test for errors + // Cycle through the rules for each field and match the corresponding $validation_data item foreach ($this->_field_data as $field => $row) { - // Fetch the data from the corresponding $_POST or validation array and cache it in the _field_data array. + // Fetch the data from the validation_data array item and cache it in the _field_data array. // Depending on whether the field name is an array or a string will determine where we get it from. if ($row['is_array'] === TRUE) { @@ -459,7 +453,13 @@ class CI_Form_validation { { $this->_field_data[$field]['postdata'] = $validation_array[$field]; } + } + // Execute validation rules + // Note: A second foreach (for now) is required in order to avoid false-positives + // for rules like 'matches', which correlate to other validation fields. + foreach ($this->_field_data as $field => $row) + { // Don't try to validate if we have no rules set if (empty($row['rules'])) { @@ -963,15 +963,29 @@ class CI_Form_validation { /** * Match one field to another * - * @param string - * @param string field + * @param string $str string to compare against + * @param string $field * @return bool */ public function matches($str, $field) { - $validation_array = empty($this->validation_data) ? $_POST : $this->validation_data; + return isset($this->_field_data[$field], $this->_field_data[$field]['postdata']) + ? ($str === $this->_field_data[$field]['postdata']) + : FALSE; + } - return isset($validation_array[$field]) ? ($str === $validation_array[$field]) : FALSE; + // -------------------------------------------------------------------- + + /** + * Differs from another field + * + * @param string + * @param string field + * @return bool + */ + public function differs($str, $field) + { + return ! (isset($this->_field_data[$field]) && $this->_field_data[$field]['postdata'] === $str); } // -------------------------------------------------------------------- @@ -1315,6 +1329,11 @@ class CI_Form_validation { */ public function prep_for_form($data = '') { + if ($this->_safe_form_data === FALSE OR empty($data)) + { + return $data; + } + if (is_array($data)) { foreach ($data as $key => $val) @@ -1325,11 +1344,6 @@ class CI_Form_validation { return $data; } - if ($this->_safe_form_data === FALSE OR $data === '') - { - return $data; - } - return str_replace(array("'", '"', '<', '>'), array(''', '"', '<', '>'), stripslashes($data)); } diff --git a/system/libraries/Ftp.php b/system/libraries/Ftp.php index 76f5e151a..60c03b5ad 100644 --- a/system/libraries/Ftp.php +++ b/system/libraries/Ftp.php @@ -1,4 +1,4 @@ -<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed'); +<?php /** * CodeIgniter * @@ -24,6 +24,7 @@ * @since Version 1.0 * @filesource */ +defined('BASEPATH') OR exit('No direct script access allowed'); /** * FTP Class @@ -36,14 +37,65 @@ */ class CI_FTP { + /** + * FTP Server hostname + * + * @var string + */ public $hostname = ''; + + /** + * FTP Username + * + * @var string + */ public $username = ''; + + /** + * FTP Password + * + * @var string + */ public $password = ''; + + /** + * FTP Server port + * + * @var int + */ public $port = 21; + + /** + * Passive mode flag + * + * @var bool + */ public $passive = TRUE; + + /** + * Debug flag + * + * Specifies whether to display error messages. + * + * @var bool + */ public $debug = FALSE; + + /** + * Connection + * + * @var resource + */ public $conn_id = FALSE; + // -------------------------------------------------------------------- + + /** + * Constructor + * + * @param array $config + * @return void + */ public function __construct($config = array()) { if (count($config) > 0) @@ -59,7 +111,7 @@ class CI_FTP { /** * Initialize preferences * - * @param array + * @param array $config * @return void */ public function initialize($config = array()) @@ -81,7 +133,7 @@ class CI_FTP { /** * FTP Connect * - * @param array the connection values + * @param array $config Connection values * @return bool */ public function connect($config = array()) @@ -161,8 +213,8 @@ class CI_FTP { * so we do it by trying to change to a particular directory. * Internally, this parameter is only used by the "mirror" function below. * - * @param string - * @param bool + * @param string $path + * @param bool $supress_debug * @return bool */ public function changedir($path = '', $supress_debug = FALSE) @@ -191,8 +243,8 @@ class CI_FTP { /** * Create a directory * - * @param string - * @param int + * @param string $path + * @param int $permissions * @return bool */ public function mkdir($path = '', $permissions = NULL) @@ -227,10 +279,10 @@ class CI_FTP { /** * Upload a file to the server * - * @param string - * @param string - * @param string - * @param int + * @param string $locpath + * @param string $rempath + * @param string $mode + * @param int $permissions * @return bool */ public function upload($locpath, $rempath, $mode = 'auto', $permissions = NULL) @@ -281,9 +333,9 @@ class CI_FTP { /** * Download a file from a remote server to the local server * - * @param string - * @param string - * @param string + * @param string $rempath + * @param string $locpath + * @param string $mode * @return bool */ public function download($rempath, $locpath, $mode = 'auto') @@ -322,9 +374,9 @@ class CI_FTP { /** * Rename (or move) a file * - * @param string - * @param string - * @param bool + * @param string $old_file + * @param string $new_file + * @param bool $move * @return bool */ public function rename($old_file, $new_file, $move = FALSE) @@ -353,8 +405,8 @@ class CI_FTP { /** * Move a file * - * @param string - * @param string + * @param string $old_file + * @param string $new_file * @return bool */ public function move($old_file, $new_file) @@ -367,7 +419,7 @@ class CI_FTP { /** * Rename (or move) a file * - * @param string + * @param string $filepath * @return bool */ public function delete_file($filepath) @@ -397,7 +449,7 @@ class CI_FTP { * Delete a folder and recursively delete everything (including sub-folders) * containted within it. * - * @param string + * @param string $filepath * @return bool */ public function delete_dir($filepath) @@ -444,8 +496,8 @@ class CI_FTP { /** * Set file permissions * - * @param string the file path - * @param int the permissions + * @param string $path File path + * @param int $perm Permissions * @return bool */ public function chmod($path, $perm) @@ -474,6 +526,7 @@ class CI_FTP { /** * FTP List files in the specified directory * + * @param string $path * @return array */ public function list_files($path = '.') @@ -496,8 +549,8 @@ class CI_FTP { * Whatever the directory structure of the original file path will be * recreated on the server. * - * @param string path to source with trailing slash - * @param string path to destination - include the base folder with trailing slash + * @param string $locpath Path to source with trailing slash + * @param string $rempath Path to destination - include the base folder with trailing slash * @return bool */ public function mirror($locpath, $rempath) @@ -543,7 +596,7 @@ class CI_FTP { /** * Extract the file extension * - * @param string + * @param string $filename * @return string */ protected function _getext($filename) @@ -562,7 +615,7 @@ class CI_FTP { /** * Set the upload type * - * @param string + * @param string $ext Filename extension * @return string */ protected function _settype($ext) @@ -609,7 +662,7 @@ class CI_FTP { /** * Display error message * - * @param string + * @param string $line * @return void */ protected function _error($line) diff --git a/system/libraries/Image_lib.php b/system/libraries/Image_lib.php index 899b995d4..3b453be47 100644 --- a/system/libraries/Image_lib.php +++ b/system/libraries/Image_lib.php @@ -1,4 +1,4 @@ -<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed'); +<?php /** * CodeIgniter * @@ -24,6 +24,7 @@ * @since Version 1.0 * @filesource */ +defined('BASEPATH') OR exit('No direct script access allowed'); /** * Image Manipulation class @@ -1320,6 +1321,13 @@ class CI_Image_lib { imagestring($src_img, $this->wm_font_size, $x_shad, $y_shad, $this->wm_text, $drp_color); imagestring($src_img, $this->wm_font_size, $x_axis, $y_axis, $this->wm_text, $txt_color); } + + // We can preserve transparency for PNG images + if ($this->image_type === 3) + { + imagealphablending($src_img, FALSE); + imagesavealpha($src_img, TRUE); + } } // Output the final image diff --git a/system/libraries/Javascript.php b/system/libraries/Javascript.php index 5c8b09217..9a15cddaa 100644 --- a/system/libraries/Javascript.php +++ b/system/libraries/Javascript.php @@ -1,4 +1,4 @@ -<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed'); +<?php /** * CodeIgniter * @@ -24,6 +24,7 @@ * @since Version 1.0 * @filesource */ +defined('BASEPATH') OR exit('No direct script access allowed'); /** * Javascript Class @@ -36,8 +37,21 @@ */ class CI_Javascript { + /** + * JavaScript location + * + * @var string + */ protected $_javascript_location = 'js'; + // -------------------------------------------------------------------- + + /** + * Constructor + * + * @param array $params + * @return void + */ public function __construct($params = array()) { $defaults = array('js_library_driver' => 'jquery', 'autoload' => TRUE); @@ -312,8 +326,7 @@ class CI_Javascript { * * Outputs a javascript library mouseup event * - * @param string The element to attach the event to - * @param string The code to execute + * @param string $js Code to execute * @return string */ public function ready($js) @@ -394,9 +407,10 @@ class CI_Javascript { * * Outputs a javascript library animate event * - * @param string - element - * @param string - One of 'slow', 'normal', 'fast', or time in milliseconds - * @param string - Javascript callback function + * @param string $element = 'this' + * @param array $params = array() + * @param mixed $speed 'slow', 'normal', 'fast', or time in milliseconds + * @param string $extra * @return string */ public function animate($element = 'this', $params = array(), $speed = '', $extra = '') @@ -546,10 +560,11 @@ class CI_Javascript { * * Outputs a javascript library toggle class event * - * @param string - element + * @param string $element = 'this' + * @param string $class = '' * @return string */ - public function toggleClass($element = 'this', $class='') + public function toggleClass($element = 'this', $class = '') { return $this->js->_toggleClass($element, $class); } @@ -579,7 +594,8 @@ class CI_Javascript { * * gather together all script needing to be output * - * @param string The element to attach the event to + * @param string $view_var + * @param bool $script_tags * @return string */ public function compile($view_var = 'script_foot', $script_tags = TRUE) @@ -587,6 +603,8 @@ class CI_Javascript { $this->js->_compile($view_var, $script_tags); } + // -------------------------------------------------------------------- + /** * Clear Compile * @@ -606,7 +624,8 @@ class CI_Javascript { * * Outputs a <script> tag with the source as an external js file * - * @param string The element to attach the event to + * @param string $external_file + * @param bool $relative * @return string */ public function external($external_file = '', $relative = FALSE) @@ -799,7 +818,8 @@ class CI_Javascript { * * Ensures a standard json value and escapes values * - * @param mixed + * @param mixed $result + * @param bool $is_key = FALSE * @return string */ protected function _prep_args($result, $is_key = FALSE) diff --git a/system/libraries/Log.php b/system/libraries/Log.php index baac80121..e66270840 100644 --- a/system/libraries/Log.php +++ b/system/libraries/Log.php @@ -1,4 +1,4 @@ -<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed'); +<?php /** * CodeIgniter * @@ -24,6 +24,7 @@ * @since Version 1.0 * @filesource */ +defined('BASEPATH') OR exit('No direct script access allowed'); /** * Logging Class @@ -151,7 +152,7 @@ class CI_Log { if ( ! file_exists($filepath)) { $newfile = TRUE; - $message .= '<'."?php if ( ! defined('BASEPATH')) exit('No direct script access allowed'); ?".">\n\n"; + $message .= '<'."?php defined('BASEPATH') OR exit('No direct script access allowed'); ?".">\n\n"; } if ( ! $fp = @fopen($filepath, FOPEN_WRITE_CREATE)) diff --git a/system/libraries/Migration.php b/system/libraries/Migration.php index 5d637d44a..06f2f562c 100644 --- a/system/libraries/Migration.php +++ b/system/libraries/Migration.php @@ -1,4 +1,4 @@ -<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed'); +<?php /** * CodeIgniter * @@ -24,6 +24,7 @@ * @since Version 3.0 * @filesource */ +defined('BASEPATH') OR exit('No direct script access allowed'); /** * Migration Class diff --git a/system/libraries/Pagination.php b/system/libraries/Pagination.php index 5573f6407..ae8dba072 100644 --- a/system/libraries/Pagination.php +++ b/system/libraries/Pagination.php @@ -1,4 +1,4 @@ -<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed'); +<?php /** * CodeIgniter * @@ -24,6 +24,7 @@ * @since Version 1.0 * @filesource */ +defined('BASEPATH') OR exit('No direct script access allowed'); /** * Pagination Class @@ -36,46 +37,269 @@ */ class CI_Pagination { - protected $base_url = ''; // The page we are linking to - protected $prefix = ''; // A custom prefix added to the path. - protected $suffix = ''; // A custom suffix added to the path. - protected $total_rows = 0; // Total number of items (database results) - protected $per_page = 10; // Max number of items you want shown per page - protected $num_links = 2; // Number of "digit" links to show before/after the currently viewed page - protected $cur_page = 0; // The current page being viewed - protected $use_page_numbers = FALSE; // Use page number for segment instead of offset - protected $first_link = '‹ First'; - protected $next_link = '>'; - protected $prev_link = '<'; - protected $last_link = 'Last ›'; - protected $uri_segment = 3; - protected $full_tag_open = ''; - protected $full_tag_close = ''; - protected $first_tag_open = ''; - protected $first_tag_close = ' '; - protected $last_tag_open = ' '; - protected $last_tag_close = ''; - protected $first_url = ''; // Alternative URL for the First Page. - protected $cur_tag_open = ' <strong>'; - protected $cur_tag_close = '</strong>'; - protected $next_tag_open = ' '; - protected $next_tag_close = ' '; - protected $prev_tag_open = ' '; - protected $prev_tag_close = ''; - protected $num_tag_open = ' '; - protected $num_tag_close = ''; + /** + * Base URL + * + * The page that we're linking to + * + * @var string + */ + protected $base_url = ''; + + /** + * Prefix + * + * @var string + */ + protected $prefix = ''; + + /** + * Suffix + * + * @var string + */ + protected $suffix = ''; + + /** + * Total number of items + * + * @var int + */ + protected $total_rows = 0; + + /** + * Items per page + * + * @var int + */ + protected $per_page = 10; + + /** + * Number of links to show + * + * Relates to "digit" type links shown before/after + * the currently viewed page. + * + * @var int + */ + protected $num_links = 2; + + /** + * Current page + * + * @var int + */ + protected $cur_page = 0; + + /** + * Use page numbers flag + * + * Whether to use actual page numbers instead of an offset + * + * @var bool + */ + protected $use_page_numbers = FALSE; + + /** + * First link + * + * @var string + */ + protected $first_link = '‹ First'; + + /** + * Next link + * + * @var string + */ + protected $next_link = '>'; + + /** + * Previous link + * + * @var string + */ + protected $prev_link = '<'; + + /** + * Last link + * + * @var string + */ + protected $last_link = 'Last ›'; + + /** + * URI Segment + * + * @var int + */ + protected $uri_segment = 3; + + /** + * Full tag open + * + * @var string + */ + protected $full_tag_open = ''; + + /** + * Full tag close + * + * @var string + */ + protected $full_tag_close = ''; + + /** + * First tag open + * + * @var string + */ + protected $first_tag_open = ''; + + /** + * First tag close + * + * @var string + */ + protected $first_tag_close = ''; + + /** + * Last tag open + * + * @var string + */ + protected $last_tag_open = ''; + + /** + * Last tag close + * + * @var string + */ + protected $last_tag_close = ''; + + /** + * First URL + * + * An alternative URL for the first page + * + * @var string + */ + protected $first_url = ''; + + /** + * Current tag open + * + * @var string + */ + protected $cur_tag_open = '<strong>'; + + /** + * Current tag close + * + * @var string + */ + protected $cur_tag_close = '</strong>'; + + /** + * Next tag open + * + * @var string + */ + protected $next_tag_open = ''; + + /** + * Next tag close + * + * @var string + */ + protected $next_tag_close = ''; + + /** + * Previous tag open + * + * @var string + */ + protected $prev_tag_open = ''; + + /** + * Previous tag close + * + * @var string + */ + protected $prev_tag_close = ''; + + /** + * Number tag open + * + * @var string + */ + protected $num_tag_open = ''; + + /** + * Number tag close + * + * @var string + */ + protected $num_tag_close = ''; + + /** + * Page query string flag + * + * @var bool + */ protected $page_query_string = FALSE; - protected $query_string_segment = 'per_page'; - protected $display_pages = TRUE; - protected $_attributes = ''; - protected $_link_types = array(); + + /** + * Query string segment + * + * @var string + */ + protected $query_string_segment = 'per_page'; + + /** + * Display pages flag + * + * @var bool + */ + protected $display_pages = TRUE; + + /** + * Attributes + * + * @var string + */ + protected $_attributes = ''; + + /** + * Link types + * + * "rel" attribute + * + * @see CI_Pagination::_attr_rel() + * @var array + */ + protected $_link_types = array(); + + /** + * Reuse query string flag + * + * @var bool + */ protected $reuse_query_string = FALSE; - protected $data_page_attr = 'data-ci-pagination-page'; + + /** + * Data page attribute + * + * @var string + */ + protected $data_page_attr = 'data-ci-pagination-page'; + + // -------------------------------------------------------------------- /** * Constructor * - * @param array initialization parameters + * @param array $params Initialization parameters * @return void */ public function __construct($params = array()) @@ -89,7 +313,7 @@ class CI_Pagination { /** * Initialize Preferences * - * @param array initialization parameters + * @param array $params Initialization parameters * @return void */ public function initialize($params = array()) @@ -157,7 +381,7 @@ class CI_Pagination { // See if we are using a prefix or suffix on links if ($this->prefix !== '' OR $this->suffix !== '') { - $this->cur_page = (int) str_replace(array($this->prefix, $this->suffix), '', $CI->uri->segment($this->uri_segment)); + $this->cur_page = (int) str_replace(array($this->prefix, $this->suffix), '', $CI->uri->rsegment($this->uri_segment)); } if ($CI->config->item('enable_query_strings') === TRUE OR $this->page_query_string === TRUE) @@ -169,7 +393,7 @@ class CI_Pagination { } elseif ( ! $this->cur_page && $CI->uri->segment($this->uri_segment) !== $base_page) { - $this->cur_page = (int) $CI->uri->segment($this->uri_segment); + $this->cur_page = (int) $CI->uri->rsegment($this->uri_segment); } // Set current page to 1 if it's not valid or if using page numbers instead of offset @@ -215,7 +439,8 @@ class CI_Pagination { // string. If post, add a trailing slash to the base URL if needed if ($CI->config->item('enable_query_strings') === TRUE OR $this->page_query_string === TRUE) { - $this->base_url = rtrim($this->base_url).'&'.$this->query_string_segment.'='; + $segment = (strpos($this->base_url, '?')) ? '&' : '?'; + $this->base_url = rtrim($this->base_url).$segment.$this->query_string_segment.'='; } else { @@ -351,7 +576,7 @@ class CI_Pagination { /** * Parse attributes * - * @param array + * @param array $attributes * @return void */ protected function _parse_attributes($attributes) @@ -375,7 +600,7 @@ class CI_Pagination { * Add "rel" attribute * * @link http://www.w3.org/TR/html5/links.html#linkTypes - * @param string + * @param string $type * @return string */ protected function _attr_rel($type) diff --git a/system/libraries/Parser.php b/system/libraries/Parser.php index b64c78254..d29eede02 100644 --- a/system/libraries/Parser.php +++ b/system/libraries/Parser.php @@ -1,4 +1,4 @@ -<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed'); +<?php /** * CodeIgniter * @@ -24,6 +24,7 @@ * @since Version 1.0 * @filesource */ +defined('BASEPATH') OR exit('No direct script access allowed'); /** * Parser Class diff --git a/system/libraries/Profiler.php b/system/libraries/Profiler.php index 1e961f6df..7d7069b95 100644 --- a/system/libraries/Profiler.php +++ b/system/libraries/Profiler.php @@ -1,4 +1,4 @@ -<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed'); +<?php /** * CodeIgniter * @@ -24,6 +24,7 @@ * @since Version 1.0 * @filesource */ +defined('BASEPATH') OR exit('No direct script access allowed'); /** * CodeIgniter Profiler Class diff --git a/system/libraries/Session.php b/system/libraries/Session.php deleted file mode 100644 index af38dc366..000000000 --- a/system/libraries/Session.php +++ /dev/null @@ -1,955 +0,0 @@ -<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed'); -/** - * CodeIgniter - * - * An open source application development framework for PHP 5.2.4 or newer - * - * NOTICE OF LICENSE - * - * Licensed under the Open Software License version 3.0 - * - * This source file is subject to the Open Software License (OSL 3.0) that is - * bundled with this package in the files license.txt / license.rst. It is - * also available through the world wide web at this URL: - * http://opensource.org/licenses/OSL-3.0 - * If you did not receive a copy of the license and are unable to obtain it - * through the world wide web, please send an email to - * licensing@ellislab.com so we can send you a copy immediately. - * - * @package CodeIgniter - * @author EllisLab Dev Team - * @copyright Copyright (c) 2008 - 2012, EllisLab, Inc. (http://ellislab.com/) - * @license http://opensource.org/licenses/OSL-3.0 Open Software License (OSL 3.0) - * @link http://codeigniter.com - * @since Version 1.0 - * @filesource - */ - -/** - * Session Class - * - * @package CodeIgniter - * @subpackage Libraries - * @category Sessions - * @author EllisLab Dev Team - * @link http://codeigniter.com/user_guide/libraries/sessions.html - */ -class CI_Session { - - /** - * Whether to encrypt the session cookie - * - * @var bool - */ - public $sess_encrypt_cookie = FALSE; - - /** - * Whether to use to the database for session storage - * - * @var bool - */ - public $sess_use_database = FALSE; - - /** - * Name of the database table in which to store sessions - * - * @var string - */ - public $sess_table_name = ''; - - /** - * Length of time (in seconds) for sessions to expire - * - * @var int - */ - public $sess_expiration = 7200; - - /** - * Whether to kill session on close of browser window - * - * @var bool - */ - public $sess_expire_on_close = FALSE; - - /** - * Whether to match session on ip address - * - * @var bool - */ - public $sess_match_ip = FALSE; - - /** - * Whether to match session on user-agent - * - * @var bool - */ - public $sess_match_useragent = TRUE; - - /** - * Name of session cookie - * - * @var string - */ - public $sess_cookie_name = 'ci_session'; - - /** - * Session cookie prefix - * - * @var string - */ - public $cookie_prefix = ''; - - /** - * Session cookie path - * - * @var string - */ - public $cookie_path = ''; - - /** - * Session cookie domain - * - * @var string - */ - public $cookie_domain = ''; - - /** - * Whether to set the cookie only on HTTPS connections - * - * @var bool - */ - public $cookie_secure = FALSE; - - /** - * Whether cookie should be allowed only to be sent by the server - * - * @var bool - */ - public $cookie_httponly = FALSE; - - /** - * Interval at which to update session - * - * @var int - */ - public $sess_time_to_update = 300; - - /** - * Key with which to encrypt the session cookie - * - * @var string - */ - public $encryption_key = ''; - - /** - * String to indicate flash data cookies - * - * @var string - */ - public $flashdata_key = 'flash'; - - /** - * Timezone to use for the current time - * - * @var string - */ - public $time_reference = 'local'; - - - /** - * Session data - * - * @var array - */ - public $userdata = array(); - - /** - * Reference to CodeIgniter instance - * - * @var object - */ - public $CI; - - /** - * Current time - * - * @var int - */ - public $now; - - /** - * Session Constructor - * - * The constructor runs the session routines automatically - * whenever the class is instantiated. - * - * @param array - * @return void - */ - public function __construct($params = array()) - { - log_message('debug', 'Session Class Initialized'); - - // Set the super object to a local variable for use throughout the class - $this->CI =& get_instance(); - - // Set all the session preferences, which can either be set - // manually via the $params array above or via the config file - foreach (array('sess_encrypt_cookie', 'sess_use_database', 'sess_table_name', 'sess_expiration', 'sess_expire_on_close', 'sess_match_ip', 'sess_match_useragent', 'sess_cookie_name', 'cookie_path', 'cookie_domain', 'cookie_secure', 'cookie_httponly', 'sess_time_to_update', 'time_reference', 'cookie_prefix', 'encryption_key') as $key) - { - $this->$key = isset($params[$key]) ? $params[$key] : $this->CI->config->item($key); - } - - if ($this->encryption_key === '') - { - show_error('In order to use the Session class you are required to set an encryption key in your config file.'); - } - - // Load the string helper so we can use the strip_slashes() function - $this->CI->load->helper('string'); - - // Do we need encryption? If so, load the encryption class - if ($this->sess_encrypt_cookie === TRUE) - { - $this->CI->load->library('encrypt'); - } - - // Are we using a database? If so, load it - if ($this->sess_use_database === TRUE && $this->sess_table_name !== '') - { - $this->CI->load->database(); - } - - // Set the "now" time. Can either be GMT or server time, based on the - // config prefs. We use this to set the "last activity" time - $this->now = $this->_get_time(); - - // Set the session length. If the session expiration is - // set to zero we'll set the expiration two years from now. - if ($this->sess_expiration === 0) - { - $this->sess_expiration = (60*60*24*365*2); - } - - // Set the cookie name - $this->sess_cookie_name = $this->cookie_prefix.$this->sess_cookie_name; - - // Run the Session routine. If a session doesn't exist we'll - // create a new one. If it does, we'll update it. - if ( ! $this->sess_read()) - { - $this->sess_create(); - } - else - { - $this->sess_update(); - } - - // Delete 'old' flashdata (from last request) - $this->_flashdata_sweep(); - - // Mark all new flashdata as old (data will be deleted before next request) - $this->_flashdata_mark(); - - // Delete expired sessions if necessary - $this->_sess_gc(); - - log_message('debug', 'Session routines successfully run'); - } - - // -------------------------------------------------------------------- - - /** - * Fetch the current session data if it exists - * - * @return bool - */ - public function sess_read() - { - // Fetch the cookie - $session = $this->CI->input->cookie($this->sess_cookie_name); - - // No cookie? Goodbye cruel world!... - if ($session === NULL) - { - log_message('debug', 'A session cookie was not found.'); - return FALSE; - } - - // Decrypt the cookie data - if ($this->sess_encrypt_cookie === TRUE) - { - $session = $this->CI->encrypt->decode($session); - } - else - { - // encryption was not used, so we need to check the md5 hash - $hash = substr($session, strlen($session)-32); // get last 32 chars - $session = substr($session, 0, strlen($session)-32); - - // Does the md5 hash match? This is to prevent manipulation of session data in userspace - if ($hash !== md5($session.$this->encryption_key)) - { - log_message('error', 'The session cookie data did not match what was expected. This could be a possible hacking attempt.'); - $this->sess_destroy(); - return FALSE; - } - } - - // Unserialize the session array - $session = $this->_unserialize($session); - - // Is the session data we unserialized an array with the correct format? - if ( ! is_array($session) OR ! isset($session['session_id'], $session['ip_address'], $session['user_agent'], $session['last_activity'])) - { - $this->sess_destroy(); - return FALSE; - } - - // Is the session current? - if (($session['last_activity'] + $this->sess_expiration) < $this->now) - { - $this->sess_destroy(); - return FALSE; - } - - // Does the IP match? - if ($this->sess_match_ip === TRUE && $session['ip_address'] !== $this->CI->input->ip_address()) - { - $this->sess_destroy(); - return FALSE; - } - - // Does the User Agent Match? - if ($this->sess_match_useragent === TRUE && trim($session['user_agent']) !== trim(substr($this->CI->input->user_agent(), 0, 120))) - { - $this->sess_destroy(); - return FALSE; - } - - // Is there a corresponding session in the DB? - if ($this->sess_use_database === TRUE) - { - $this->CI->db->where('session_id', $session['session_id']); - - if ($this->sess_match_ip === TRUE) - { - $this->CI->db->where('ip_address', $session['ip_address']); - } - - if ($this->sess_match_useragent === TRUE) - { - $this->CI->db->where('user_agent', $session['user_agent']); - } - - $query = $this->CI->db->limit(1)->get($this->sess_table_name); - - // No result? Kill it! - if ($query->num_rows() === 0) - { - $this->sess_destroy(); - return FALSE; - } - - // Is there custom data? If so, add it to the main session array - $row = $query->row(); - if ( ! empty($row->user_data)) - { - $custom_data = $this->_unserialize($row->user_data); - - if (is_array($custom_data)) - { - foreach ($custom_data as $key => $val) - { - $session[$key] = $val; - } - } - } - } - - // Session is valid! - $this->userdata = $session; - unset($session); - - return TRUE; - } - - // -------------------------------------------------------------------- - - /** - * Write the session data - * - * @return void - */ - public function sess_write() - { - // Are we saving custom data to the DB? If not, all we do is update the cookie - if ($this->sess_use_database === FALSE) - { - $this->_set_cookie(); - return; - } - - // set the custom userdata, the session data we will set in a second - $custom_userdata = $this->userdata; - $cookie_userdata = array(); - - // Before continuing, we need to determine if there is any custom data to deal with. - // Let's determine this by removing the default indexes to see if there's anything left in the array - // and set the session data while we're at it - foreach (array('session_id','ip_address','user_agent','last_activity') as $val) - { - unset($custom_userdata[$val]); - $cookie_userdata[$val] = $this->userdata[$val]; - } - - // Did we find any custom data? If not, we turn the empty array into a string - // since there's no reason to serialize and store an empty array in the DB - if (count($custom_userdata) === 0) - { - $custom_userdata = ''; - } - else - { - // Serialize the custom data array so we can store it - $custom_userdata = $this->_serialize($custom_userdata); - } - - // Run the update query - $this->CI->db->where('session_id', $this->userdata['session_id']); - $this->CI->db->update($this->sess_table_name, array('last_activity' => $this->userdata['last_activity'], 'user_data' => $custom_userdata)); - - // Write the cookie. Notice that we manually pass the cookie data array to the - // _set_cookie() function. Normally that function will store $this->userdata, but - // in this case that array contains custom data, which we do not want in the cookie. - $this->_set_cookie($cookie_userdata); - } - - // -------------------------------------------------------------------- - - /** - * Create a new session - * - * @return void - */ - public function sess_create() - { - $sessid = ''; - do - { - $sessid .= mt_rand(0, mt_getrandmax()); - } - while (strlen($sessid) < 32); - - // To make the session ID even more secure we'll combine it with the user's IP - $sessid .= $this->CI->input->ip_address(); - - $this->userdata = array( - 'session_id' => md5(uniqid($sessid, TRUE)), - 'ip_address' => $this->CI->input->ip_address(), - 'user_agent' => substr($this->CI->input->user_agent(), 0, 120), - 'last_activity' => $this->now, - 'user_data' => '' - ); - - // Save the data to the DB if needed - if ($this->sess_use_database === TRUE) - { - $this->CI->db->query($this->CI->db->insert_string($this->sess_table_name, $this->userdata)); - } - - // Write the cookie - $this->_set_cookie(); - } - - // -------------------------------------------------------------------- - - /** - * Update an existing session - * - * @return void - */ - public function sess_update() - { - // We only update the session every five minutes by default - if (($this->userdata['last_activity'] + $this->sess_time_to_update) >= $this->now) - { - return; - } - - // _set_cookie() will handle this for us if we aren't using database sessions - // by pushing all userdata to the cookie. - $cookie_data = NULL; - - /* Changing the session ID during an AJAX call causes problems, - * so we'll only update our last_activity - */ - if ($this->CI->input->is_ajax_request()) - { - $this->userdata['last_activity'] = $this->now; - - // Update the session ID and last_activity field in the DB if needed - if ($this->sess_use_database === TRUE) - { - // set cookie explicitly to only have our session data - $cookie_data = array(); - foreach (array('session_id','ip_address','user_agent','last_activity') as $val) - { - $cookie_data[$val] = $this->userdata[$val]; - } - - $this->CI->db->query($this->CI->db->update_string($this->sess_table_name, - array('last_activity' => $this->userdata['last_activity']), - array('session_id' => $this->userdata['session_id']))); - } - - return $this->_set_cookie($cookie_data); - } - - // Save the old session id so we know which record to - // update in the database if we need it - $old_sessid = $this->userdata['session_id']; - $new_sessid = ''; - do - { - $new_sessid .= mt_rand(0, mt_getrandmax()); - } - while (strlen($new_sessid) < 32); - - // To make the session ID even more secure we'll combine it with the user's IP - $new_sessid .= $this->CI->input->ip_address(); - - // Turn it into a hash and update the session data array - $this->userdata['session_id'] = $new_sessid = md5(uniqid($new_sessid, TRUE)); - $this->userdata['last_activity'] = $this->now; - - // Update the session ID and last_activity field in the DB if needed - if ($this->sess_use_database === TRUE) - { - // set cookie explicitly to only have our session data - $cookie_data = array(); - foreach (array('session_id','ip_address','user_agent','last_activity') as $val) - { - $cookie_data[$val] = $this->userdata[$val]; - } - - $this->CI->db->query($this->CI->db->update_string($this->sess_table_name, array('last_activity' => $this->now, 'session_id' => $new_sessid), array('session_id' => $old_sessid))); - } - - // Write the cookie - $this->_set_cookie($cookie_data); - } - - // -------------------------------------------------------------------- - - /** - * Destroy the current session - * - * @return void - */ - public function sess_destroy() - { - // Kill the session DB row - if ($this->sess_use_database === TRUE && isset($this->userdata['session_id'])) - { - $this->CI->db->where('session_id', $this->userdata['session_id']); - $this->CI->db->delete($this->sess_table_name); - } - - // Kill the cookie - setcookie( - $this->sess_cookie_name, - addslashes(serialize(array())), - ($this->now - 31500000), - $this->cookie_path, - $this->cookie_domain, - 0 - ); - - // Kill session data - $this->userdata = array(); - } - - // -------------------------------------------------------------------- - - /** - * Fetch a specific item from the session array - * - * @param string - * @return string - */ - public function userdata($item) - { - return isset($this->userdata[$item]) ? $this->userdata[$item] : NULL; - } - - // -------------------------------------------------------------------- - - /** - * Fetch all session data - * - * @return array - */ - public function all_userdata() - { - return $this->userdata; - } - - // -------------------------------------------------------------------------- - - /** - * Fetch all flashdata - * - * @return array - */ - public function all_flashdata() - { - $out = array(); - - // loop through all userdata - foreach ($this->all_userdata() as $key => $val) - { - // if it contains flashdata, add it - if (strpos($key, 'flash:old:') !== FALSE) - { - $out[$key] = $val; - } - } - return $out; - } - - // -------------------------------------------------------------------- - - /** - * Add or change data in the "userdata" array - * - * @param mixed - * @param string - * @return void - */ - public function set_userdata($newdata = array(), $newval = '') - { - if (is_string($newdata)) - { - $newdata = array($newdata => $newval); - } - - if (count($newdata) > 0) - { - foreach ($newdata as $key => $val) - { - $this->userdata[$key] = $val; - } - } - - $this->sess_write(); - } - - // -------------------------------------------------------------------- - - /** - * Delete a session variable from the "userdata" array - * - * @param array - * @return void - */ - public function unset_userdata($newdata = array()) - { - if (is_string($newdata)) - { - $newdata = array($newdata => ''); - } - - if (count($newdata) > 0) - { - foreach ($newdata as $key => $val) - { - unset($this->userdata[$key]); - } - } - - $this->sess_write(); - } - - // ------------------------------------------------------------------------ - - /** - * Add or change flashdata, only available - * until the next request - * - * @param mixed - * @param string - * @return void - */ - public function set_flashdata($newdata = array(), $newval = '') - { - if (is_string($newdata)) - { - $newdata = array($newdata => $newval); - } - - if (count($newdata) > 0) - { - foreach ($newdata as $key => $val) - { - $this->set_userdata($this->flashdata_key.':new:'.$key, $val); - } - } - } - - // ------------------------------------------------------------------------ - - /** - * Keeps existing flashdata available to next request. - * - * @param string - * @return void - */ - public function keep_flashdata($key) - { - // 'old' flashdata gets removed. Here we mark all - // flashdata as 'new' to preserve it from _flashdata_sweep() - // Note the function will return NULL if the $key - // provided cannot be found - $value = $this->userdata($this->flashdata_key.':old:'.$key); - - $this->set_userdata($this->flashdata_key.':new:'.$key, $value); - } - - // ------------------------------------------------------------------------ - - /** - * Fetch a specific flashdata item from the session array - * - * @param string - * @return string - */ - public function flashdata($key) - { - return $this->userdata($this->flashdata_key.':old:'.$key); - } - - // ------------------------------------------------------------------------ - - /** - * Identifies flashdata as 'old' for removal - * when _flashdata_sweep() runs. - * - * @return void - */ - protected function _flashdata_mark() - { - $userdata = $this->all_userdata(); - foreach ($userdata as $name => $value) - { - $parts = explode(':new:', $name); - if (is_array($parts) && count($parts) === 2) - { - $this->set_userdata($this->flashdata_key.':old:'.$parts[1], $value); - $this->unset_userdata($name); - } - } - } - - // ------------------------------------------------------------------------ - - /** - * Removes all flashdata marked as 'old' - * - * @return void - */ - protected function _flashdata_sweep() - { - $userdata = $this->all_userdata(); - foreach ($userdata as $key => $value) - { - if (strpos($key, ':old:')) - { - $this->unset_userdata($key); - } - } - - } - - // -------------------------------------------------------------------- - - /** - * Get the "now" time - * - * @return string - */ - protected function _get_time() - { - if ($this->time_reference === 'local' OR $this->time_reference === date_default_timezone_get()) - { - return time(); - } - - $datetime = new DateTime('now', new DateTimeZone($this->time_reference)); - sscanf($datetime->format('j-n-Y G:i:s'), '%d-%d-%d %d:%d:%d', $day, $month, $year, $hour, $minute, $second); - - return mktime($hour, $minute, $second, $month, $day, $year); - } - - // -------------------------------------------------------------------- - - /** - * Write the session cookie - * - * @param mixed - * @return void - */ - protected function _set_cookie($cookie_data = NULL) - { - if (is_null($cookie_data)) - { - $cookie_data = $this->userdata; - } - - // Serialize the userdata for the cookie - $cookie_data = $this->_serialize($cookie_data); - - if ($this->sess_encrypt_cookie === TRUE) - { - $cookie_data = $this->CI->encrypt->encode($cookie_data); - } - else - { - // if encryption is not used, we provide an md5 hash to prevent userside tampering - $cookie_data = $cookie_data.md5($cookie_data.$this->encryption_key); - } - - $expire = ($this->sess_expire_on_close === TRUE) ? 0 : $this->sess_expiration + time(); - - // Set the cookie - setcookie( - $this->sess_cookie_name, - $cookie_data, - $expire, - $this->cookie_path, - $this->cookie_domain, - $this->cookie_secure, - $this->cookie_httponly - ); - } - - // -------------------------------------------------------------------- - - /** - * Serialize an array - * - * This function first converts any slashes found in the array to a temporary - * marker, so when it gets unserialized the slashes will be preserved - * - * @param array - * @return string - */ - protected function _serialize($data) - { - if (is_array($data)) - { - array_walk_recursive($data, array(&$this, '_escape_slashes')); - } - elseif (is_string($data)) - { - $data = str_replace('\\', '{{slash}}', $data); - } - return serialize($data); - } - - /** - * Escape slashes - * - * This function converts any slashes found into a temporary marker - * - * @param string - * @param string - * @return void - */ - protected function _escape_slashes(&$val, $key) - { - if (is_string($val)) - { - $val = str_replace('\\', '{{slash}}', $val); - } - } - - // -------------------------------------------------------------------- - - /** - * Unserialize - * - * This function unserializes a data string, then converts any - * temporary slash markers back to actual slashes - * - * @param array - * @return string - */ - protected function _unserialize($data) - { - $data = @unserialize(strip_slashes(trim($data))); - - if (is_array($data)) - { - array_walk_recursive($data, array(&$this, '_unescape_slashes')); - return $data; - } - - return is_string($data) ? str_replace('{{slash}}', '\\', $data) : $data; - } - - // -------------------------------------------------------------------- - - /** - * Unescape slashes - * - * This function converts any slash markers back into actual slashes - * - * @param string - * @param string - * @return void - */ - protected function _unescape_slashes(&$val, $key) - { - if (is_string($val)) - { - $val= str_replace('{{slash}}', '\\', $val); - } - } - - // -------------------------------------------------------------------- - - /** - * Garbage collection - * - * This deletes expired session rows from database - * if the probability percentage is met - * - * @return void - */ - protected function _sess_gc() - { - if ($this->sess_use_database !== TRUE) - { - return; - } - - $probability = ini_get('session.gc_probability'); - $divisor = ini_get('session.gc_divisor'); - - srand(time()); - if ((mt_rand(0, $divisor) / $divisor) < $probability) - { - $expire = $this->now - $this->sess_expiration; - - $this->CI->db->where('last_activity < '.$expire); - $this->CI->db->delete($this->sess_table_name); - - log_message('debug', 'Session garbage collection performed.'); - } - } - -} - -/* End of file Session.php */ -/* Location: ./system/libraries/Session.php */
\ No newline at end of file diff --git a/system/libraries/Session/Session.php b/system/libraries/Session/Session.php new file mode 100755 index 000000000..96e65f154 --- /dev/null +++ b/system/libraries/Session/Session.php @@ -0,0 +1,744 @@ +<?php +/** + * CodeIgniter + * + * An open source application development framework for PHP 5.2.4 or newer + * + * NOTICE OF LICENSE + * + * Licensed under the Open Software License version 3.0 + * + * This source file is subject to the Open Software License (OSL 3.0) that is + * bundled with this package in the files license.txt / license.rst. It is + * also available through the world wide web at this URL: + * http://opensource.org/licenses/OSL-3.0 + * If you did not receive a copy of the license and are unable to obtain it + * through the world wide web, please send an email to + * licensing@ellislab.com so we can send you a copy immediately. + * + * @package CodeIgniter + * @author EllisLab Dev Team + * @copyright Copyright (c) 2008 - 2012, EllisLab, Inc. (http://ellislab.com/) + * @license http://opensource.org/licenses/OSL-3.0 Open Software License (OSL 3.0) + * @link http://codeigniter.com + * @since Version 2.0 + * @filesource + */ +defined('BASEPATH') OR exit('No direct script access allowed'); + +/** + * CodeIgniter Session Class + * + * The user interface defined by EllisLabs, now with puggable drivers to manage different storage mechanisms. + * By default, the cookie session driver will load, but the 'sess_driver' config/param item (see above) can be + * used to specify the 'native' driver, or any other you might create. + * Once loaded, this driver setup is a drop-in replacement for the former CI_Session library, taking its place as the + * 'session' member of the global controller framework (e.g.: $CI->session or $this->session). + * In keeping with the CI_Driver methodology, multiple drivers may be loaded, although this might be a bit confusing. + * The CI_Session library class keeps track of the most recently loaded driver as "current" to call for driver methods. + * Ideally, one driver is loaded and all calls go directly through the main library interface. However, any methods + * called through the specific driver will switch the "current" driver to itself before invoking the library method + * (which will then call back into the driver for low-level operations). So, alternation between two drivers can be + * achieved by specifying which driver to use for each call (e.g.: $this->session->native->set_userdata('foo', 'bar'); + * $this->session->cookie->userdata('foo'); $this->session->native->unset_userdata('foo');). Notice in the previous + * example that the _native_ userdata value 'foo' would be set to 'bar', which would NOT be returned by the call for + * the _cookie_ userdata 'foo', nor would the _cookie_ value be unset by the call to unset the _native_ 'foo' value. + * + * @package CodeIgniter + * @subpackage Libraries + * @category Sessions + * @author EllisLab Dev Team + * @link http://codeigniter.com/user_guide/libraries/sessions.html + */ +class CI_Session extends CI_Driver_Library { + + /** + * Initialization parameters + * + * @var array + */ + public $params = array(); + + /** + * Current driver in use + * + * @var string + */ + protected $current = NULL; + + /** + * User data + * + * @var array + */ + protected $userdata = array(); + + // ------------------------------------------------------------------------ + + const FLASHDATA_KEY = 'flash'; + const FLASHDATA_NEW = ':new:'; + const FLASHDATA_OLD = ':old:'; + const FLASHDATA_EXP = ':exp:'; + const EXPIRATION_KEY = '__expirations'; + const TEMP_EXP_DEF = 300; + + // ------------------------------------------------------------------------ + + /** + * CI_Session constructor + * + * The constructor loads the configured driver ('sess_driver' in config.php or as a parameter), running + * routines in its constructor, and manages flashdata aging. + * + * @param array Configuration parameters + * @return void + */ + public function __construct(array $params = array()) + { + $CI =& get_instance(); + + // No sessions under CLI + if ($CI->input->is_cli_request()) + { + return; + } + + log_message('debug', 'CI_Session Class Initialized'); + + // Get valid drivers list + $this->valid_drivers = array( + 'Session_native', + 'Session_cookie' + ); + $key = 'sess_valid_drivers'; + $drivers = isset($params[$key]) ? $params[$key] : $CI->config->item($key); + if ($drivers) + { + is_array($drivers) OR $drivers = array($drivers); + + // Add driver names to valid list + foreach ($drivers as $driver) + { + if ( ! in_array(strtolower($driver), array_map('strtolower', $this->valid_drivers))) + { + $this->valid_drivers[] = $driver; + } + } + } + + // Get driver to load + $key = 'sess_driver'; + $driver = isset($params[$key]) ? $params[$key] : $CI->config->item($key); + if ( ! $driver) + { + $driver = 'cookie'; + } + + if ( ! in_array('session_'.strtolower($driver), array_map('strtolower', $this->valid_drivers))) + { + $this->valid_drivers[] = 'Session_'.$driver; + } + + // Save a copy of parameters in case drivers need access + $this->params = $params; + + // Load driver and get array reference + $this->load_driver($driver); + + // Delete 'old' flashdata (from last request) + $this->_flashdata_sweep(); + + // Mark all new flashdata as old (data will be deleted before next request) + $this->_flashdata_mark(); + + // Delete expired tempdata + $this->_tempdata_sweep(); + + log_message('debug', 'CI_Session routines successfully run'); + } + + // ------------------------------------------------------------------------ + + /** + * Loads session storage driver + * + * @param string Driver classname + * @return object Loaded driver object + */ + public function load_driver($driver) + { + // Save reference to most recently loaded driver as library default and sync userdata + $this->current = parent::load_driver($driver); + $this->userdata =& $this->current->get_userdata(); + return $this->current; + } + + // ------------------------------------------------------------------------ + + /** + * Select default session storage driver + * + * @param string Driver classname + * @return void + */ + public function select_driver($driver) + { + // Validate driver name + $lowername = strtolower(str_replace('CI_', '', $driver)); + if (in_array($lowername, array_map('strtolower', $this->valid_drivers))) + { + // See if driver is loaded + $child = str_replace($this->lib_name.'_', '', $driver); + if (isset($this->$child)) + { + // See if driver is already current + if ($this->$child !== $this->current) + { + // Make driver current and sync userdata + $this->current = $this->$child; + $this->userdata =& $this->current->get_userdata(); + } + } + else + { + // Load new driver + $this->load_driver($child); + } + } + } + + // ------------------------------------------------------------------------ + + /** + * Destroy the current session + * + * @return void + */ + public function sess_destroy() + { + // Just call destroy on driver + $this->current->sess_destroy(); + } + + // ------------------------------------------------------------------------ + + /** + * Regenerate the current session + * + * @param bool Destroy session data flag (default: false) + * @return void + */ + public function sess_regenerate($destroy = FALSE) + { + // Call regenerate on driver and resync userdata + $this->current->sess_regenerate($destroy); + $this->userdata =& $this->current->get_userdata(); + } + + // ------------------------------------------------------------------------ + + /** + * Fetch a specific item from the session array + * + * @param string Item key + * @return string Item value or NULL if not found + */ + public function userdata($item) + { + return isset($this->userdata[$item]) ? $this->userdata[$item] : NULL; + } + + // ------------------------------------------------------------------------ + + /** + * Fetch all session data + * + * @return array User data array + */ + public function all_userdata() + { + return isset($this->userdata) ? $this->userdata : NULL; + } + + // ------------------------------------------------------------------------ + + /** + * Fetch all flashdata + * + * @return array Flash data array + */ + public function all_flashdata() + { + $out = array(); + + // loop through all userdata + foreach ($this->all_userdata() as $key => $val) + { + // if it contains flashdata, add it + if (strpos($key, self::FLASHDATA_KEY.self::FLASHDATA_OLD) !== FALSE) + { + $key = str_replace(self::FLASHDATA_KEY.self::FLASHDATA_OLD, '', $key); + $out[$key] = $val; + } + } + return $out; + } + + // ------------------------------------------------------------------------ + + /** + * Add or change data in the "userdata" array + * + * @param mixed Item name or array of items + * @param string Item value or empty string + * @return void + */ + public function set_userdata($newdata = array(), $newval = '') + { + // Wrap params as array if singular + if (is_string($newdata)) + { + $newdata = array($newdata => $newval); + } + + // Set each name/value pair + if (count($newdata) > 0) + { + foreach ($newdata as $key => $val) + { + $this->userdata[$key] = $val; + } + } + + // Tell driver data changed + $this->current->sess_save(); + } + + // ------------------------------------------------------------------------ + + /** + * Delete a session variable from the "userdata" array + * + * @param mixed Item name or array of item names + * @return void + */ + public function unset_userdata($newdata = array()) + { + // Wrap single name as array + if (is_string($newdata)) + { + $newdata = array($newdata => ''); + } + + // Unset each item name + if (count($newdata) > 0) + { + foreach (array_keys($newdata) as $key) + { + unset($this->userdata[$key]); + } + } + + // Tell driver data changed + $this->current->sess_save(); + } + + // ------------------------------------------------------------------------ + + /** + * Determine if an item exists + * + * @param string Item name + * @return bool + */ + public function has_userdata($item) + { + return isset($this->userdata[$item]); + } + + // ------------------------------------------------------------------------ + + /** + * Add or change flashdata, only available until the next request + * + * @param mixed Item name or array of items + * @param string Item value or empty string + * @return void + */ + public function set_flashdata($newdata = array(), $newval = '') + { + // Wrap item as array if singular + if (is_string($newdata)) + { + $newdata = array($newdata => $newval); + } + + // Prepend each key name and set value + if (count($newdata) > 0) + { + foreach ($newdata as $key => $val) + { + $flashdata_key = self::FLASHDATA_KEY.self::FLASHDATA_NEW.$key; + $this->set_userdata($flashdata_key, $val); + } + } + } + + // ------------------------------------------------------------------------ + + /** + * Keeps existing flashdata available to next request. + * + * @param string Item key + * @return void + */ + public function keep_flashdata($key) + { + // 'old' flashdata gets removed. Here we mark all flashdata as 'new' to preserve it from _flashdata_sweep() + // Note the function will return NULL if the $key provided cannot be found + $old_flashdata_key = self::FLASHDATA_KEY.self::FLASHDATA_OLD.$key; + $value = $this->userdata($old_flashdata_key); + + $new_flashdata_key = self::FLASHDATA_KEY.self::FLASHDATA_NEW.$key; + $this->set_userdata($new_flashdata_key, $value); + } + + // ------------------------------------------------------------------------ + + /** + * Fetch a specific flashdata item from the session array + * + * @param string Item key + * @return string + */ + public function flashdata($key) + { + // Prepend key and retrieve value + $flashdata_key = self::FLASHDATA_KEY.self::FLASHDATA_OLD.$key; + return $this->userdata($flashdata_key); + } + + // ------------------------------------------------------------------------ + + /** + * Add or change tempdata, only available until expiration + * + * @param mixed Item name or array of items + * @param string Item value or empty string + * @param int Item lifetime in seconds or 0 for default + * @return void + */ + public function set_tempdata($newdata = array(), $newval = '', $expire = 0) + { + // Set expiration time + $expire = time() + ($expire ? $expire : self::TEMP_EXP_DEF); + + // Wrap item as array if singular + if (is_string($newdata)) + { + $newdata = array($newdata => $newval); + } + + // Get or create expiration list + $expirations = $this->userdata(self::EXPIRATION_KEY); + if ( ! $expirations) + { + $expirations = array(); + } + + // Prepend each key name and set value + if (count($newdata) > 0) + { + foreach ($newdata as $key => $val) + { + $tempdata_key = self::FLASHDATA_KEY.self::FLASHDATA_EXP.$key; + $expirations[$tempdata_key] = $expire; + $this->set_userdata($tempdata_key, $val); + } + } + + // Update expiration list + $this->set_userdata(self::EXPIRATION_KEY, $expirations); + } + + // ------------------------------------------------------------------------ + + /** + * Delete a temporary session variable from the "userdata" array + * + * @param mixed Item name or array of item names + * @return void + */ + public function unset_tempdata($newdata = array()) + { + // Get expirations list + $expirations = $this->userdata(self::EXPIRATION_KEY); + if (empty($expirations)) + { + // Nothing to do + return; + } + + // Wrap single name as array + if (is_string($newdata)) + { + $newdata = array($newdata => ''); + } + + // Prepend each item name and unset + if (count($newdata) > 0) + { + foreach (array_keys($newdata) as $key) + { + $tempdata_key = self::FLASHDATA_KEY.self::FLASHDATA_EXP.$key; + unset($expirations[$tempdata_key]); + $this->unset_userdata($tempdata_key); + } + } + + // Update expiration list + $this->set_userdata(self::EXPIRATION_KEY, $expirations); + } + + // ------------------------------------------------------------------------ + + /** + * Fetch a specific tempdata item from the session array + * + * @param string Item key + * @return string + */ + public function tempdata($key) + { + // Prepend key and return value + $tempdata_key = self::FLASHDATA_KEY.self::FLASHDATA_EXP.$key; + return $this->userdata($tempdata_key); + } + + // ------------------------------------------------------------------------ + + /** + * Identifies flashdata as 'old' for removal + * when _flashdata_sweep() runs. + * + * @return void + */ + protected function _flashdata_mark() + { + foreach ($this->all_userdata() as $name => $value) + { + $parts = explode(self::FLASHDATA_NEW, $name); + if (count($parts) === 2) + { + $new_name = self::FLASHDATA_KEY.self::FLASHDATA_OLD.$parts[1]; + $this->set_userdata($new_name, $value); + $this->unset_userdata($name); + } + } + } + + // ------------------------------------------------------------------------ + + /** + * Removes all flashdata marked as 'old' + * + * @return void + */ + protected function _flashdata_sweep() + { + $userdata = $this->all_userdata(); + foreach (array_keys($userdata) as $key) + { + if (strpos($key, self::FLASHDATA_OLD)) + { + $this->unset_userdata($key); + } + } + } + + // ------------------------------------------------------------------------ + + /** + * Removes all expired tempdata + * + * @return void + */ + protected function _tempdata_sweep() + { + // Get expirations list + $expirations = $this->userdata(self::EXPIRATION_KEY); + if (empty($expirations)) + { + // Nothing to do + return; + } + + // Unset expired elements + $now = time(); + $userdata = $this->all_userdata(); + foreach (array_keys($userdata) as $key) + { + if (strpos($key, self::FLASHDATA_EXP) && $expirations[$key] < $now) + { + unset($expirations[$key]); + $this->unset_userdata($key); + } + } + + // Update expiration list + $this->set_userdata(self::EXPIRATION_KEY, $expirations); + } + +} + +// ------------------------------------------------------------------------ + +/** + * CI_Session_driver Class + * + * Extend this class to make a new CI_Session driver. + * A CI_Session driver basically manages an array of name/value pairs with some sort of storage mechanism. + * To make a new driver, derive from (extend) CI_Session_driver. Overload the initialize method and read or create + * session data. Then implement a save handler to write changed data to storage (sess_save), a destroy handler + * to remove deleted data (sess_destroy), and an access handler to expose the data (get_userdata). + * Put your driver in the libraries/Session/drivers folder anywhere in the loader paths. This includes the + * application directory, the system directory, or any path you add with $CI->load->add_package_path(). + * Your driver must be named CI_Session_<name>, and your filename must be Session_<name>.php, + * preferably also capitalized. (e.g.: CI_Session_foo in libraries/Session/drivers/Session_foo.php) + * Then specify the driver by setting 'sess_driver' in your config file or as a parameter when loading the CI_Session + * object. (e.g.: $config['sess_driver'] = 'foo'; OR $CI->load->driver('session', array('sess_driver' => 'foo')); ) + * Already provided are the Native driver, which manages the native PHP $_SESSION array, and + * the Cookie driver, which manages the data in a browser cookie, with optional extra storage in a database table. + * + * @package CodeIgniter + * @subpackage Libraries + * @category Sessions + * @author EllisLab Dev Team + */ +abstract class CI_Session_driver extends CI_Driver { + + /** + * CI Singleton + * + * @see get_instance() + * @var object + */ + protected $CI; + + // ------------------------------------------------------------------------ + + /** + * Constructor + * + * Gets the CI singleton, so that individual drivers + * don't have to do it separately. + * + * @return void + */ + public function __construct() + { + $this->CI =& get_instance(); + } + + // ------------------------------------------------------------------------ + + /** + * Decorate + * + * Decorates the child with the parent driver lib's methods and properties + * + * @param object Parent library object + * @return void + */ + public function decorate($parent) + { + // Call base class decorate first + parent::decorate($parent); + + // Call initialize method now that driver has access to $this->_parent + $this->initialize(); + } + + // ------------------------------------------------------------------------ + + /** + * __call magic method + * + * Handles access to the parent driver library's methods + * + * @param string Library method name + * @param array Method arguments (default: none) + * @return mixed + */ + public function __call($method, $args = array()) + { + // Make sure the parent library uses this driver + $this->_parent->select_driver(get_class($this)); + return parent::__call($method, $args); + } + + // ------------------------------------------------------------------------ + + /** + * Initialize driver + * + * @return void + */ + protected function initialize() + { + // Overload this method to implement initialization + } + + // ------------------------------------------------------------------------ + + /** + * Save the session data + * + * Data in the array has changed - perform any storage synchronization + * necessary. The child class MUST implement this abstract method! + * + * @return void + */ + abstract public function sess_save(); + + // ------------------------------------------------------------------------ + + /** + * Destroy the current session + * + * Clean up storage for this session - it has been terminated. + * The child class MUST implement this abstract method! + * + * @return void + */ + abstract public function sess_destroy(); + + // ------------------------------------------------------------------------ + + /** + * Regenerate the current session + * + * Regenerate the session ID. + * The child class MUST implement this abstract method! + * + * @param bool Destroy session data flag (default: false) + * @return void + */ + abstract public function sess_regenerate($destroy = FALSE); + + // ------------------------------------------------------------------------ + + /** + * Get a reference to user data array + * + * Give array access to the main CI_Session object. + * The child class MUST implement this abstract method! + * + * @return array Reference to userdata + */ + abstract public function &get_userdata(); + +} + +/* End of file Session.php */ +/* Location: ./system/libraries/Session/Session.php */
\ No newline at end of file diff --git a/system/libraries/Session/drivers/Session_cookie.php b/system/libraries/Session/drivers/Session_cookie.php new file mode 100755 index 000000000..3c4848265 --- /dev/null +++ b/system/libraries/Session/drivers/Session_cookie.php @@ -0,0 +1,845 @@ +<?php +/** + * CodeIgniter + * + * An open source application development framework for PHP 5.2.4 or newer + * + * NOTICE OF LICENSE + * + * Licensed under the Open Software License version 3.0 + * + * This source file is subject to the Open Software License (OSL 3.0) that is + * bundled with this package in the files license.txt / license.rst. It is + * also available through the world wide web at this URL: + * http://opensource.org/licenses/OSL-3.0 + * If you did not receive a copy of the license and are unable to obtain it + * through the world wide web, please send an email to + * licensing@ellislab.com so we can send you a copy immediately. + * + * @package CodeIgniter + * @author EllisLab Dev Team + * @copyright Copyright (c) 2008 - 2012, EllisLab, Inc. (http://ellislab.com/) + * @license http://opensource.org/licenses/OSL-3.0 Open Software License (OSL 3.0) + * @link http://codeigniter.com + * @since Version 1.0 + * @filesource + */ +defined('BASEPATH') OR exit('No direct script access allowed'); + +/** + * Cookie-based session management driver + * + * This is the classic CI_Session functionality, as written by EllisLab, abstracted out to a driver. + * + * @package CodeIgniter + * @subpackage Libraries + * @category Sessions + * @author EllisLab Dev Team + * @link http://codeigniter.com/user_guide/libraries/sessions.html + */ +class CI_Session_cookie extends CI_Session_driver { + + /** + * Whether to encrypt the session cookie + * + * @var bool + */ + public $sess_encrypt_cookie = FALSE; + + /** + * Whether to use to the database for session storage + * + * @var bool + */ + public $sess_use_database = FALSE; + + /** + * Name of the database table in which to store sessions + * + * @var string + */ + public $sess_table_name = ''; + + /** + * Length of time (in seconds) for sessions to expire + * + * @var int + */ + public $sess_expiration = 7200; + + /** + * Whether to kill session on close of browser window + * + * @var bool + */ + public $sess_expire_on_close = FALSE; + + /** + * Whether to match session on ip address + * + * @var bool + */ + public $sess_match_ip = FALSE; + + /** + * Whether to match session on user-agent + * + * @var bool + */ + public $sess_match_useragent = TRUE; + + /** + * Name of session cookie + * + * @var string + */ + public $sess_cookie_name = 'ci_session'; + + /** + * Session cookie prefix + * + * @var string + */ + public $cookie_prefix = ''; + + /** + * Session cookie path + * + * @var string + */ + public $cookie_path = ''; + + /** + * Session cookie domain + * + * @var string + */ + public $cookie_domain = ''; + + /** + * Whether to set the cookie only on HTTPS connections + * + * @var bool + */ + public $cookie_secure = FALSE; + + /** + * Whether cookie should be allowed only to be sent by the server + * + * @var bool + */ + public $cookie_httponly = FALSE; + + /** + * Interval at which to update session + * + * @var int + */ + public $sess_time_to_update = 300; + + /** + * Key with which to encrypt the session cookie + * + * @var string + */ + public $encryption_key = ''; + + /** + * Timezone to use for the current time + * + * @var string + */ + public $time_reference = 'local'; + + /** + * Session data + * + * @var array + */ + public $userdata = array(); + + /** + * Current time + * + * @var int + */ + public $now; + + /** + * Default userdata keys + * + * @var array + */ + protected $defaults = array( + 'session_id' => NULL, + 'ip_address' => NULL, + 'user_agent' => NULL, + 'last_activity' => NULL + ); + + /** + * Data needs DB update flag + * + * @var bool + */ + protected $data_dirty = FALSE; + + /** + * Initialize session driver object + * + * @return void + */ + protected function initialize() + { + // Set all the session preferences, which can either be set + // manually via the $params array or via the config file + $prefs = array( + 'sess_encrypt_cookie', + 'sess_use_database', + 'sess_table_name', + 'sess_expiration', + 'sess_expire_on_close', + 'sess_match_ip', + 'sess_match_useragent', + 'sess_cookie_name', + 'cookie_path', + 'cookie_domain', + 'cookie_secure', + 'cookie_httponly', + 'sess_time_to_update', + 'time_reference', + 'cookie_prefix', + 'encryption_key' + ); + + foreach ($prefs as $key) + { + $this->$key = isset($this->_parent->params[$key]) + ? $this->_parent->params[$key] + : $this->CI->config->item($key); + } + + if ($this->encryption_key === '') + { + show_error('In order to use the Cookie Session driver you are required to set an encryption key in your config file.'); + } + + // Do we need encryption? If so, load the encryption class + if ($this->sess_encrypt_cookie === TRUE) + { + $this->CI->load->library('encrypt'); + } + + // Check for database + if ($this->sess_use_database === TRUE && $this->sess_table_name !== '') + { + // Load database driver + $this->CI->load->database(); + + // Register shutdown function + register_shutdown_function(array($this, '_update_db')); + } + + // Set the "now" time. Can either be GMT or server time, based on the config prefs. + // We use this to set the "last activity" time + $this->now = $this->_get_time(); + + // Set the session length. If the session expiration is + // set to zero we'll set the expiration two years from now. + if ($this->sess_expiration === 0) + { + $this->sess_expiration = (60*60*24*365*2); + } + + // Set the cookie name + $this->sess_cookie_name = $this->cookie_prefix.$this->sess_cookie_name; + + // Run the Session routine. If a session doesn't exist we'll + // create a new one. If it does, we'll update it. + if ( ! $this->_sess_read()) + { + $this->_sess_create(); + } + else + { + $this->_sess_update(); + } + + // Delete expired sessions if necessary + $this->_sess_gc(); + } + + // ------------------------------------------------------------------------ + + /** + * Write the session data + * + * @return void + */ + public function sess_save() + { + // Check for database + if ($this->sess_use_database === TRUE) + { + // Mark custom data as dirty so we know to update the DB + $this->data_dirty = TRUE; + } + + // Write the cookie + $this->_set_cookie(); + } + + // ------------------------------------------------------------------------ + + /** + * Destroy the current session + * + * @return void + */ + public function sess_destroy() + { + // Kill the session DB row + if ($this->sess_use_database === TRUE && isset($this->userdata['session_id'])) + { + $this->CI->db->delete($this->sess_table_name, array('session_id' => $this->userdata['session_id'])); + $this->data_dirty = FALSE; + } + + // Kill the cookie + $this->_setcookie($this->sess_cookie_name, '', ($this->now - 31500000), + $this->cookie_path, $this->cookie_domain, 0); + + // Kill session data + $this->userdata = array(); + } + + // ------------------------------------------------------------------------ + + /** + * Regenerate the current session + * + * Regenerate the session id + * + * @param bool Destroy session data flag (default: false) + * @return void + */ + public function sess_regenerate($destroy = FALSE) + { + // Check destroy flag + if ($destroy) + { + // Destroy old session and create new one + $this->sess_destroy(); + $this->_sess_create(); + } + else + { + // Just force an update to recreate the id + $this->_sess_update(TRUE); + } + } + + // ------------------------------------------------------------------------ + + /** + * Get a reference to user data array + * + * @return array Reference to userdata + */ + public function &get_userdata() + { + return $this->userdata; + } + + // ------------------------------------------------------------------------ + + /** + * Fetch the current session data if it exists + * + * @return bool + */ + protected function _sess_read() + { + // Fetch the cookie + $session = $this->CI->input->cookie($this->sess_cookie_name); + + // No cookie? Goodbye cruel world!... + if ($session === NULL) + { + log_message('debug', 'A session cookie was not found.'); + return FALSE; + } + + $len = strlen($session) - 40; + + if ($len < 0) + { + log_message('debug', 'The session cookie was not signed.'); + return FALSE; + } + + // Check cookie authentication + $hmac = substr($session, $len); + $session = substr($session, 0, $len); + + if ($hmac !== hash_hmac('sha1', $session, $this->encryption_key)) + { + log_message('error', 'The session cookie data did not match what was expected.'); + $this->sess_destroy(); + return FALSE; + } + + // Check for encryption + if ($this->sess_encrypt_cookie === TRUE) + { + // Decrypt the cookie data + $session = $this->CI->encrypt->decode($session); + } + + // Unserialize the session array + $session = $this->_unserialize($session); + + // Is the session data we unserialized an array with the correct format? + if ( ! is_array($session) OR ! isset($session['session_id'], $session['ip_address'], $session['user_agent'], $session['last_activity'])) + { + $this->sess_destroy(); + return FALSE; + } + + // Is the session current? + if (($session['last_activity'] + $this->sess_expiration) < $this->now OR $session['last_activity'] > $this->now) + { + $this->sess_destroy(); + return FALSE; + } + + // Does the IP match? + if ($this->sess_match_ip === TRUE && $session['ip_address'] !== $this->CI->input->ip_address()) + { + $this->sess_destroy(); + return FALSE; + } + + // Does the User Agent Match? + if ($this->sess_match_useragent === TRUE && + trim($session['user_agent']) !== trim(substr($this->CI->input->user_agent(), 0, 120))) + { + $this->sess_destroy(); + return FALSE; + } + + // Is there a corresponding session in the DB? + if ($this->sess_use_database === TRUE) + { + $this->CI->db->where('session_id', $session['session_id']); + + if ($this->sess_match_ip === TRUE) + { + $this->CI->db->where('ip_address', $session['ip_address']); + } + + if ($this->sess_match_useragent === TRUE) + { + $this->CI->db->where('user_agent', $session['user_agent']); + } + + // Is caching in effect? Turn it off + $db_cache = $this->CI->db->cache_on; + $this->CI->db->cache_off(); + + $query = $this->CI->db->limit(1)->get($this->sess_table_name); + + // Was caching in effect? + if ($db_cache) + { + // Turn it back on + $this->CI->db->cache_on(); + } + + // No result? Kill it! + if ($query->num_rows() === 0) + { + $this->sess_destroy(); + return FALSE; + } + + // Is there custom data? If so, add it to the main session array + $row = $query->row(); + if ( ! empty($row->user_data)) + { + $custom_data = $this->_unserialize($row->user_data); + + if (is_array($custom_data)) + { + $session = $session + $custom_data; + } + } + } + + // Session is valid! + $this->userdata = $session; + return TRUE; + } + + // ------------------------------------------------------------------------ + + /** + * Create a new session + * + * @return void + */ + protected function _sess_create() + { + // Initialize userdata + $this->userdata = array( + 'session_id' => $this->_make_sess_id(), + 'ip_address' => $this->CI->input->ip_address(), + 'user_agent' => substr($this->CI->input->user_agent(), 0, 120), + 'last_activity' => $this->now, + ); + + // Check for database + if ($this->sess_use_database === TRUE) + { + // Add empty user_data field and save the data to the DB + $this->CI->db->set('user_data', '')->insert($this->sess_table_name, $this->userdata); + } + + // Write the cookie + $this->_set_cookie(); + } + + // ------------------------------------------------------------------------ + + /** + * Update an existing session + * + * @param bool Force update flag (default: false) + * @return void + */ + protected function _sess_update($force = FALSE) + { + // We only update the session every five minutes by default (unless forced) + if ( ! $force && ($this->userdata['last_activity'] + $this->sess_time_to_update) >= $this->now) + { + return; + } + + // Update last activity to now + $this->userdata['last_activity'] = $this->now; + + // Save the old session id so we know which DB record to update + $old_sessid = $this->userdata['session_id']; + + // Changing the session ID during an AJAX call causes problems + if ( ! $this->CI->input->is_ajax_request()) + { + // Get new id + $this->userdata['session_id'] = $this->_make_sess_id(); + } + + // Check for database + if ($this->sess_use_database === TRUE) + { + $this->CI->db->where('session_id', $old_sessid); + + if ($this->sess_match_ip === TRUE) + { + $this->CI->db->where('ip_address', $this->CI->input->ip_address()); + } + + if ($this->sess_match_useragent === TRUE) + { + $this->CI->db->where('user_agent', trim(substr($this->CI->input->user_agent(), 0, 120))); + } + + // Update the session ID and last_activity field in the DB + $this->CI->db->update($this->sess_table_name, + array( + 'last_activity' => $this->now, + 'session_id' => $this->userdata['session_id'] + ) + ); + } + + // Write the cookie + $this->_set_cookie(); + } + + // ------------------------------------------------------------------------ + + /** + * Update database with current data + * + * This gets called from the shutdown function and also + * registered with PHP to run at the end of the request + * so it's guaranteed to update even when a fatal error + * occurs. The first call makes the update and clears the + * dirty flag so it won't happen twice. + * + * @return void + */ + public function _update_db() + { + // Check for database and dirty flag and unsaved + if ($this->sess_use_database === TRUE && $this->data_dirty === TRUE) + { + // Set up activity and data fields to be set + // If we don't find custom data, user_data will remain an empty string + $set = array( + 'last_activity' => $this->userdata['last_activity'], + 'user_data' => '' + ); + + // Get the custom userdata, leaving out the defaults + // (which get stored in the cookie) + $userdata = array_diff_key($this->userdata, $this->defaults); + + // Did we find any custom data? + if ( ! empty($userdata)) + { + // Serialize the custom data array so we can store it + $set['user_data'] = $this->_serialize($userdata); + } + + // Run the update query + // Any time we change the session id, it gets updated immediately, + // so our where clause below is always safe + $this->CI->db->where('session_id', $this->userdata['session_id']); + + if ($this->sess_match_ip === TRUE) + { + $this->CI->db->where('ip_address', $this->CI->input->ip_address()); + } + + if ($this->sess_match_useragent === TRUE) + { + $this->CI->db->where('user_agent', trim(substr($this->CI->input->user_agent(), 0, 120))); + } + + $this->CI->db->update($this->sess_table_name, $set); + + // Clear dirty flag to prevent double updates + $this->data_dirty = FALSE; + + log_message('debug', 'CI_Session Data Saved To DB'); + } + } + + // ------------------------------------------------------------------------ + + /** + * Generate a new session id + * + * @return string Hashed session id + */ + protected function _make_sess_id() + { + $new_sessid = ''; + do + { + $new_sessid .= mt_rand(0, mt_getrandmax()); + } + while (strlen($new_sessid) < 32); + + // To make the session ID even more secure we'll combine it with the user's IP + $new_sessid .= $this->CI->input->ip_address(); + + // Turn it into a hash and return + return md5(uniqid($new_sessid, TRUE)); + } + + // ------------------------------------------------------------------------ + + /** + * Get the "now" time + * + * @return int Time + */ + protected function _get_time() + { + if ($this->time_reference === 'local' OR $this->time_reference === date_default_timezone_get()) + { + return time(); + } + + $datetime = new DateTime('now', new DateTimeZone($this->time_reference)); + sscanf($datetime->format('j-n-Y G:i:s'), '%d-%d-%d %d:%d:%d', $day, $month, $year, $hour, $minute, $second); + + return mktime($hour, $minute, $second, $month, $day, $year); + } + + // ------------------------------------------------------------------------ + + /** + * Write the session cookie + * + * @return void + */ + protected function _set_cookie() + { + // Get userdata (only defaults if database) + $cookie_data = ($this->sess_use_database === TRUE) + ? array_intersect_key($this->userdata, $this->defaults) + : $this->userdata; + + // Serialize the userdata for the cookie + $cookie_data = $this->_serialize($cookie_data); + + if ($this->sess_encrypt_cookie === TRUE) + { + $cookie_data = $this->CI->encrypt->encode($cookie_data); + } + + // Require message authentication + $cookie_data .= hash_hmac('sha1', $cookie_data, $this->encryption_key); + + $expire = ($this->sess_expire_on_close === TRUE) ? 0 : $this->sess_expiration + time(); + + // Set the cookie + $this->_setcookie($this->sess_cookie_name, $cookie_data, $expire, $this->cookie_path, $this->cookie_domain, + $this->cookie_secure, $this->cookie_httponly); + } + + // ------------------------------------------------------------------------ + + /** + * Set a cookie with the system + * + * This abstraction of the setcookie call allows overriding for unit testing + * + * @param string Cookie name + * @param string Cookie value + * @param int Expiration time + * @param string Cookie path + * @param string Cookie domain + * @param bool Secure connection flag + * @param bool HTTP protocol only flag + * @return void + */ + protected function _setcookie($name, $value = '', $expire = 0, $path = '', $domain = '', $secure = FALSE, $httponly = FALSE) + { + setcookie($name, $value, $expire, $path, $domain, $secure, $httponly); + } + + // ------------------------------------------------------------------------ + + /** + * Serialize an array + * + * This function first converts any slashes found in the array to a temporary + * marker, so when it gets unserialized the slashes will be preserved + * + * @param mixed Data to serialize + * @return string Serialized data + */ + protected function _serialize($data) + { + if (is_array($data)) + { + array_walk_recursive($data, array(&$this, '_escape_slashes')); + } + elseif (is_string($data)) + { + $data = str_replace('\\', '{{slash}}', $data); + } + + return serialize($data); + } + + // ------------------------------------------------------------------------ + + /** + * Escape slashes + * + * This function converts any slashes found into a temporary marker + * + * @param string Value + * @param string Key + * @return void + */ + protected function _escape_slashes(&$val, $key) + { + if (is_string($val)) + { + $val = str_replace('\\', '{{slash}}', $val); + } + } + + // ------------------------------------------------------------------------ + + /** + * Unserialize + * + * This function unserializes a data string, then converts any + * temporary slash markers back to actual slashes + * + * @param mixed Data to unserialize + * @return mixed Unserialized data + */ + protected function _unserialize($data) + { + $data = @unserialize(trim($data)); + + if (is_array($data)) + { + array_walk_recursive($data, array(&$this, '_unescape_slashes')); + return $data; + } + + return is_string($data) ? str_replace('{{slash}}', '\\', $data) : $data; + } + + // ------------------------------------------------------------------------ + + /** + * Unescape slashes + * + * This function converts any slash markers back into actual slashes + * + * @param string Value + * @param string Key + * @return void + */ + protected function _unescape_slashes(&$val, $key) + { + if (is_string($val)) + { + $val= str_replace('{{slash}}', '\\', $val); + } + } + + // ------------------------------------------------------------------------ + + /** + * Garbage collection + * + * This deletes expired session rows from database + * if the probability percentage is met + * + * @return void + */ + protected function _sess_gc() + { + if ($this->sess_use_database !== TRUE) + { + return; + } + + $probability = ini_get('session.gc_probability'); + $divisor = ini_get('session.gc_divisor'); + + srand(time()); + if ((mt_rand(0, $divisor) / $divisor) < $probability) + { + $expire = $this->now - $this->sess_expiration; + $this->CI->db->delete($this->sess_table_name, 'last_activity < '.$expire); + + log_message('debug', 'Session garbage collection performed.'); + } + } + +} + +/* End of file Session_cookie.php */ +/* Location: ./system/libraries/Session/drivers/Session_cookie.php */
\ No newline at end of file diff --git a/system/libraries/Session/drivers/Session_native.php b/system/libraries/Session/drivers/Session_native.php new file mode 100755 index 000000000..3e700ad5d --- /dev/null +++ b/system/libraries/Session/drivers/Session_native.php @@ -0,0 +1,242 @@ +<?php +/** + * CodeIgniter + * + * An open source application development framework for PHP 5.2.4 or newer + * + * NOTICE OF LICENSE + * + * Licensed under the Open Software License version 3.0 + * + * This source file is subject to the Open Software License (OSL 3.0) that is + * bundled with this package in the files license.txt / license.rst. It is + * also available through the world wide web at this URL: + * http://opensource.org/licenses/OSL-3.0 + * If you did not receive a copy of the license and are unable to obtain it + * through the world wide web, please send an email to + * licensing@ellislab.com so we can send you a copy immediately. + * + * @package CodeIgniter + * @author EllisLab Dev Team + * @copyright Copyright (c) 2008 - 2012, EllisLab, Inc. (http://ellislab.com/) + * @license http://opensource.org/licenses/OSL-3.0 Open Software License (OSL 3.0) + * @link http://codeigniter.com + * @since Version 1.0 + * @filesource + */ +defined('BASEPATH') OR exit('No direct script access allowed'); + +/** + * Native PHP session management driver + * + * This is the driver that uses the native PHP $_SESSION array through the Session driver library. + * + * @package CodeIgniter + * @subpackage Libraries + * @category Sessions + * @author EllisLab Dev Team + */ +class CI_Session_native extends CI_Session_driver { + + /** + * Initialize session driver object + * + * @return void + */ + protected function initialize() + { + // Get config parameters + $config = array(); + $prefs = array( + 'sess_cookie_name', + 'sess_expire_on_close', + 'sess_expiration', + 'sess_match_ip', + 'sess_match_useragent', + 'sess_time_to_update', + 'cookie_prefix', + 'cookie_path', + 'cookie_domain', + 'cookie_secure', + 'cookie_httponly' + ); + + foreach ($prefs as $key) + { + $config[$key] = isset($this->_parent->params[$key]) + ? $this->_parent->params[$key] + : $this->CI->config->item($key); + } + + // Set session name, if specified + if ($config['sess_cookie_name']) + { + // Differentiate name from cookie driver with '_id' suffix + $name = $config['sess_cookie_name'].'_id'; + if ($config['cookie_prefix']) + { + // Prepend cookie prefix + $name = $config['cookie_prefix'].$name; + } + session_name($name); + } + + // Set expiration, path, and domain + $expire = 7200; + $path = '/'; + $domain = ''; + $secure = (bool) $config['cookie_secure']; + $http_only = (bool) $config['cookie_httponly']; + + if ($config['sess_expiration'] !== FALSE) + { + // Default to 2 years if expiration is "0" + $expire = ($config['sess_expiration'] == 0) ? (60*60*24*365*2) : $config['sess_expiration']; + } + + if ($config['cookie_path']) + { + // Use specified path + $path = $config['cookie_path']; + } + + if ($config['cookie_domain']) + { + // Use specified domain + $domain = $config['cookie_domain']; + } + + session_set_cookie_params($config['sess_expire_on_close'] ? 0 : $expire, $path, $domain, $secure, $http_only); + + // Start session + session_start(); + + // Check session expiration, ip, and agent + $now = time(); + $destroy = FALSE; + if (isset($_SESSION['last_activity']) && (($_SESSION['last_activity'] + $expire) < $now OR $_SESSION['last_activity'] > $now)) + { + // Expired - destroy + $destroy = TRUE; + } + elseif ($config['sess_match_ip'] === TRUE && isset($_SESSION['ip_address']) + && $_SESSION['ip_address'] !== $this->CI->input->ip_address()) + { + // IP doesn't match - destroy + $destroy = TRUE; + } + elseif ($config['sess_match_useragent'] === TRUE && isset($_SESSION['user_agent']) + && $_SESSION['user_agent'] !== trim(substr($this->CI->input->user_agent(), 0, 50))) + { + // Agent doesn't match - destroy + $destroy = TRUE; + } + + // Destroy expired or invalid session + if ($destroy) + { + // Clear old session and start new + $this->sess_destroy(); + session_start(); + } + + // Check for update time + if ($config['sess_time_to_update'] && isset($_SESSION['last_activity']) + && ($_SESSION['last_activity'] + $config['sess_time_to_update']) < $now) + { + // Changing the session ID amidst a series of AJAX calls causes problems + if( ! $this->CI->input->is_ajax_request()) + { + // Regenerate ID, but don't destroy session + $this->sess_regenerate(FALSE); + } + } + + // Set activity time + $_SESSION['last_activity'] = $now; + + // Set matching values as required + if ($config['sess_match_ip'] === TRUE && ! isset($_SESSION['ip_address'])) + { + // Store user IP address + $_SESSION['ip_address'] = $this->CI->input->ip_address(); + } + + if ($config['sess_match_useragent'] === TRUE && ! isset($_SESSION['user_agent'])) + { + // Store user agent string + $_SESSION['user_agent'] = trim(substr($this->CI->input->user_agent(), 0, 50)); + } + + // Make session ID available + $_SESSION['session_id'] = session_id(); + } + + // ------------------------------------------------------------------------ + + /** + * Save the session data + * + * @return void + */ + public function sess_save() + { + // Nothing to do - changes to $_SESSION are automatically saved + } + + // ------------------------------------------------------------------------ + + /** + * Destroy the current session + * + * @return void + */ + public function sess_destroy() + { + // Cleanup session + $_SESSION = array(); + $name = session_name(); + if (isset($_COOKIE[$name])) + { + // Clear session cookie + $params = session_get_cookie_params(); + setcookie($name, '', time() - 42000, $params['path'], $params['domain'], $params['secure'], $params['httponly']); + unset($_COOKIE[$name]); + } + session_destroy(); + } + + // ------------------------------------------------------------------------ + + /** + * Regenerate the current session + * + * Regenerate the session id + * + * @param bool Destroy session data flag (default: FALSE) + * @return void + */ + public function sess_regenerate($destroy = FALSE) + { + // Just regenerate id, passing destroy flag + session_regenerate_id($destroy); + $_SESSION['session_id'] = session_id(); + } + + // ------------------------------------------------------------------------ + + /** + * Get a reference to user data array + * + * @return array Reference to userdata + */ + public function &get_userdata() + { + // Just return reference to $_SESSION + return $_SESSION; + } + +} + +/* End of file Session_native.php */ +/* Location: ./system/libraries/Session/drivers/Session_native.php */
\ No newline at end of file diff --git a/system/libraries/Table.php b/system/libraries/Table.php index 0f8404d85..886fb6581 100644 --- a/system/libraries/Table.php +++ b/system/libraries/Table.php @@ -1,4 +1,4 @@ -<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed'); +<?php /** * CodeIgniter * @@ -24,6 +24,7 @@ * @since Version 1.3.1 * @filesource */ +defined('BASEPATH') OR exit('No direct script access allowed'); /** * HTML Table Generating Class diff --git a/system/libraries/Trackback.php b/system/libraries/Trackback.php index 9a680dc2a..c923a6220 100644 --- a/system/libraries/Trackback.php +++ b/system/libraries/Trackback.php @@ -1,4 +1,4 @@ -<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed'); +<?php /** * CodeIgniter * @@ -24,6 +24,7 @@ * @since Version 1.0 * @filesource */ +defined('BASEPATH') OR exit('No direct script access allowed'); /** * Trackback Class @@ -38,13 +39,51 @@ */ class CI_Trackback { - public $time_format = 'local'; + /** + * Character set + * + * @var string + */ public $charset = 'UTF-8'; - public $data = array('url' => '', 'title' => '', 'excerpt' => '', 'blog_name' => '', 'charset' => ''); + + /** + * Trackback data + * + * @var array + */ + public $data = array('url' => '', 'title' => '', 'excerpt' => '', 'blog_name' => '', 'charset' => ''); + + /** + * Convert ASCII flag + * + * Whether to convert high-ASCII and MS Word + * characters to HTML entities. + * + * @var bool + */ public $convert_ascii = TRUE; - public $response = ''; - public $error_msg = array(); + /** + * Response + * + * @var string + */ + public $response = ''; + + /** + * Error messages list + * + * @var string[] + */ + public $error_msg = array(); + + // -------------------------------------------------------------------- + + /** + * Constructor + * + * @return void + */ public function __construct() { log_message('debug', 'Trackback Class Initialized'); diff --git a/system/libraries/Typography.php b/system/libraries/Typography.php index a50934f2c..d83bf519b 100644 --- a/system/libraries/Typography.php +++ b/system/libraries/Typography.php @@ -1,4 +1,4 @@ -<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed'); +<?php /** * CodeIgniter * @@ -24,6 +24,7 @@ * @since Version 1.0 * @filesource */ +defined('BASEPATH') OR exit('No direct script access allowed'); /** * Typography Class diff --git a/system/libraries/Unit_test.php b/system/libraries/Unit_test.php index 70ad8dc41..842b4aebd 100644 --- a/system/libraries/Unit_test.php +++ b/system/libraries/Unit_test.php @@ -1,4 +1,4 @@ -<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed'); +<?php /** * CodeIgniter * @@ -24,6 +24,7 @@ * @since Version 1.3.1 * @filesource */ +defined('BASEPATH') OR exit('No direct script access allowed'); /** * Unit Testing Class @@ -38,13 +39,57 @@ */ class CI_Unit_test { - public $active = TRUE; - public $results = array(); - public $strict = FALSE; - protected $_template = NULL; - protected $_template_rows = NULL; + /** + * Active flag + * + * @var bool + */ + public $active = TRUE; + + /** + * Test results + * + * @var array + */ + public $results = array(); + + /** + * Strict comparison flag + * + * Whether to use === or == when comparing + * + * @var bool + */ + public $strict = FALSE; + + /** + * Template + * + * @var string + */ + protected $_template = NULL; + + /** + * Template rows + * + * @var string + */ + protected $_template_rows = NULL; + + /** + * List of visible test items + * + * @var array + */ protected $_test_items_visible = array(); + // -------------------------------------------------------------------- + + /** + * Constructor + * + * @return void + */ public function __construct() { // These are the default items visible when a test is run. @@ -86,9 +131,10 @@ class CI_Unit_test { * * Runs the supplied tests * - * @param mixed - * @param mixed - * @param string + * @param mixed $test + * @param mixed $expected + * @param string $test_name + * @param string $notes * @return string */ public function run($test, $expected = TRUE, $test_name = 'undefined', $notes = '') @@ -106,13 +152,13 @@ class CI_Unit_test { } else { - $result = ($this->strict === TRUE) ? ($test === $expected) : ($test === $expected); + $result = ($this->strict === TRUE) ? ($test === $expected) : ($test == $expected); $extype = gettype($expected); } $back = $this->_backtrace(); - $report[] = array ( + $report = array ( 'test_name' => $test_name, 'test_datatype' => gettype($test), 'res_datatype' => $extype, @@ -124,7 +170,7 @@ class CI_Unit_test { $this->results[] = $report; - return $this->report($this->result($report)); + return $this->report($this->result(array($report))); } // -------------------------------------------------------------------- @@ -134,6 +180,7 @@ class CI_Unit_test { * * Displays a table with the test data * + * @param array $result * @return string */ public function report($result = array()) @@ -213,6 +260,7 @@ class CI_Unit_test { * * Returns the raw result data * + * @param array $results * @return array */ public function result($results = array()) @@ -236,25 +284,11 @@ class CI_Unit_test { continue; } - if (is_array($val)) + if (FALSE !== ($line = $CI->lang->line(strtolower('ut_'.$val)))) { - foreach ($val as $k => $v) - { - if (FALSE !== ($line = $CI->lang->line(strtolower('ut_'.$v)))) - { - $v = $line; - } - $temp[$CI->lang->line('ut_'.$k)] = $v; - } - } - else - { - if (FALSE !== ($line = $CI->lang->line(strtolower('ut_'.$val)))) - { - $val = $line; - } - $temp[$CI->lang->line('ut_'.$key)] = $val; + $val = $line; } + $temp[$CI->lang->line('ut_'.$key)] = $val; } $retval[] = $temp; @@ -340,18 +374,26 @@ class CI_Unit_test { } /** - * Helper functions to test boolean true/false + * Helper function to test boolean TRUE * + * @param mixed $test * @return bool */ function is_true($test) { return ($test === TRUE); } + +/** + * Helper function to test boolean FALSE + * + * @param mixed $test + * @return bool + */ function is_false($test) { return ($test === FALSE); } /* End of file Unit_test.php */ -/* Location: ./system/libraries/Unit_test.php */
\ No newline at end of file +/* Location: ./system/libraries/Unit_test.php */ diff --git a/system/libraries/Upload.php b/system/libraries/Upload.php index d381440cd..013644963 100644 --- a/system/libraries/Upload.php +++ b/system/libraries/Upload.php @@ -1,4 +1,4 @@ -<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed'); +<?php /** * CodeIgniter * @@ -24,6 +24,7 @@ * @since Version 1.0 * @filesource */ +defined('BASEPATH') OR exit('No direct script access allowed'); /** * File Uploading Class @@ -36,40 +37,210 @@ */ class CI_Upload { + /** + * Maximum file size + * + * @var int + */ public $max_size = 0; + + /** + * Maximum image width + * + * @var int + */ public $max_width = 0; + + /** + * Maximum image height + * + * @var int + */ public $max_height = 0; + + /** + * Maximum filename length + * + * @var int + */ public $max_filename = 0; + + /** + * Maximum duplicate filename increment ID + * + * @var int + */ public $max_filename_increment = 100; + + /** + * Allowed file types + * + * @var string + */ public $allowed_types = ''; + + /** + * Temporary filename + * + * @var string + */ public $file_temp = ''; + + /** + * Filename + * + * @var string + */ public $file_name = ''; + + /** + * Original filename + * + * @var string + */ public $orig_name = ''; + + /** + * File type + * + * @var string + */ public $file_type = ''; - public $file_size = ''; + + /** + * File size + * + * @var int + */ + public $file_size = NULL; + + /** + * Filename extension + * + * @var string + */ public $file_ext = ''; + + /** + * Upload path + * + * @var string + */ public $upload_path = ''; + + /** + * Overwrite flag + * + * @var bool + */ public $overwrite = FALSE; + + /** + * Obfuscate filename flag + * + * @var bool + */ public $encrypt_name = FALSE; + + /** + * Is image flag + * + * @var bool + */ public $is_image = FALSE; - public $image_width = ''; - public $image_height = ''; + + /** + * Image width + * + * @var int + */ + public $image_width = NULL; + + /** + * Image height + * + * @var int + */ + public $image_height = NULL; + + /** + * Image type + * + * @var string + */ public $image_type = ''; + + /** + * Image size string + * + * @var string + */ public $image_size_str = ''; + + /** + * Error messages list + * + * @var array + */ public $error_msg = array(); + + /** + * MIME types list + * + * @var array + */ public $mimes = array(); + + /** + * Remove spaces flag + * + * @var bool + */ public $remove_spaces = TRUE; + + /** + * MIME detection flag + * + * @var bool + */ public $detect_mime = TRUE; + + /** + * XSS filter flag + * + * @var bool + */ public $xss_clean = FALSE; + + /** + * Temporary filename prefix + * + * @var string + */ public $temp_prefix = 'temp_file_'; + + /** + * Filename sent by the client + * + * @var bool + */ public $client_name = ''; + // -------------------------------------------------------------------- + + /** + * Filename override + * + * @var string + */ protected $_file_name_override = ''; + // -------------------------------------------------------------------- + /** * Constructor * - * @param array + * @param array $props * @return void */ public function __construct($props = array()) @@ -89,7 +260,7 @@ class CI_Upload { /** * Initialize preferences * - * @param array + * @param array $config * @return void */ public function initialize($config = array()) @@ -105,14 +276,14 @@ class CI_Upload { 'file_name' => '', 'orig_name' => '', 'file_type' => '', - 'file_size' => '', + 'file_size' => NULL, 'file_ext' => '', 'upload_path' => '', 'overwrite' => FALSE, 'encrypt_name' => FALSE, 'is_image' => FALSE, - 'image_width' => '', - 'image_height' => '', + 'image_width' => NULL, + 'image_height' => NULL, 'image_type' => '', 'image_size_str' => '', 'error_msg' => array(), @@ -154,6 +325,7 @@ class CI_Upload { /** * Perform the file upload * + * @param string $field * @return bool */ public function do_upload($field = 'userfile') @@ -355,7 +527,7 @@ class CI_Upload { * Returns an associative array containing all of the information * related to the upload, allowing the developer easy access in one array. * - * @param string + * @param string $index * @return mixed */ public function data($index = NULL) @@ -390,7 +562,7 @@ class CI_Upload { /** * Set Upload Path * - * @param string + * @param string $path * @return void */ public function set_upload_path($path) @@ -408,8 +580,8 @@ class CI_Upload { * existence of a file with the same name. If found, it will append a * number to the end of the filename to avoid overwriting a pre-existing file. * - * @param string - * @param string + * @param string $path + * @param string $filename * @return string */ public function set_filename($path, $filename) @@ -453,7 +625,7 @@ class CI_Upload { /** * Set Maximum File Size * - * @param int + * @param int $n * @return void */ public function set_max_filesize($n) @@ -466,7 +638,7 @@ class CI_Upload { /** * Set Maximum File Name Length * - * @param int + * @param int $n * @return void */ public function set_max_filename($n) @@ -479,7 +651,7 @@ class CI_Upload { /** * Set Maximum Image Width * - * @param int + * @param int $n * @return void */ public function set_max_width($n) @@ -492,7 +664,7 @@ class CI_Upload { /** * Set Maximum Image Height * - * @param int + * @param int $n * @return void */ public function set_max_height($n) @@ -505,7 +677,7 @@ class CI_Upload { /** * Set Allowed File Types * - * @param string + * @param string $types * @return void */ public function set_allowed_types($types) @@ -525,7 +697,7 @@ class CI_Upload { * * Uses GD to determine the width/height/type of image * - * @param string + * @param string $path * @return void */ public function set_image_properties($path = '') @@ -557,7 +729,7 @@ class CI_Upload { * Enables the XSS flag so that the file that was uploaded * will be run through the XSS filter. * - * @param bool + * @param bool $flag * @return void */ public function set_xss_clean($flag = FALSE) @@ -599,7 +771,7 @@ class CI_Upload { /** * Verify that the filetype is allowed * - * @param bool + * @param bool $ignore_mime * @return bool */ public function is_allowed_filetype($ignore_mime = FALSE) @@ -736,7 +908,7 @@ class CI_Upload { /** * Extract the file extension * - * @param string + * @param string $filename * @return string */ public function get_extension($filename) @@ -750,7 +922,7 @@ class CI_Upload { /** * Clean the file name for security * - * @param string + * @param string $filename * @return string */ public function clean_file_name($filename) @@ -790,7 +962,8 @@ class CI_Upload { /** * Limit the File Name Length * - * @param string + * @param string $filename + * @param int $length * @return string */ public function limit_filename_length($filename, $length) @@ -883,7 +1056,7 @@ class CI_Upload { /** * Set an error message * - * @param string + * @param string $msg * @return void */ public function set_error($msg) @@ -913,8 +1086,8 @@ class CI_Upload { /** * Display the error message * - * @param string - * @param string + * @param string $open + * @param string $close * @return string */ public function display_errors($open = '<p>', $close = '</p>') @@ -930,7 +1103,7 @@ class CI_Upload { * This is a list of mime types. We use it to validate * the "allowed types" set by the developer * - * @param string + * @param string $mime * @return string */ public function mimes_types($mime) @@ -943,10 +1116,12 @@ class CI_Upload { /** * Prep Filename * - * Prevents possible script execution from Apache's handling of files multiple extensions - * http://httpd.apache.org/docs/1.3/mod/mod_mime.html#multipleext + * Prevents possible script execution from Apache's handling + * of files' multiple extensions. + * + * @link http://httpd.apache.org/docs/1.3/mod/mod_mime.html#multipleext * - * @param string + * @param string $filename * @return string */ protected function _prep_filename($filename) @@ -983,7 +1158,7 @@ class CI_Upload { * Detects the (actual) MIME type of the uploaded file, if possible. * The input array is expected to be $_FILES[$field] * - * @param array + * @param array $file * @return void */ protected function _file_mime_type($file) diff --git a/system/libraries/User_agent.php b/system/libraries/User_agent.php index ff596f04b..e920578d9 100644 --- a/system/libraries/User_agent.php +++ b/system/libraries/User_agent.php @@ -1,4 +1,4 @@ -<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed'); +<?php /** * CodeIgniter * @@ -24,6 +24,7 @@ * @since Version 1.0 * @filesource */ +defined('BASEPATH') OR exit('No direct script access allowed'); /** * User Agent Class @@ -466,7 +467,13 @@ class CI_User_agent { */ public function is_referral() { - return ! empty($_SERVER['HTTP_REFERER']); + if (empty($_SERVER['HTTP_REFERER'])) + { + return FALSE; + } + + $referer = parse_url($_SERVER['HTTP_REFERER']); + return ! (empty($referer['host']) && strpos(config_item('base_url'), $referer['host']) !== FALSE); } // -------------------------------------------------------------------- diff --git a/system/libraries/Xmlrpc.php b/system/libraries/Xmlrpc.php index cbb91c40a..3ef823e29 100644..100755 --- a/system/libraries/Xmlrpc.php +++ b/system/libraries/Xmlrpc.php @@ -1,4 +1,4 @@ -<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed'); +<?php /** * CodeIgniter * @@ -24,6 +24,14 @@ * @since Version 1.0 * @filesource */ +defined('BASEPATH') OR exit('No direct script access allowed'); + +if ( ! function_exists('xml_parser_create')) +{ + show_error('Your PHP installation does not support XML'); +} + +// ------------------------------------------------------------------------ /** * XML-RPC request handler class @@ -34,56 +42,212 @@ * @author EllisLab Dev Team * @link http://codeigniter.com/user_guide/libraries/xmlrpc.html */ - -if ( ! function_exists('xml_parser_create')) -{ - show_error('Your PHP installation does not support XML'); -} - -// ------------------------------------------------------------------------ - class CI_Xmlrpc { - public $debug = FALSE; // Debugging on or off + /** + * Debug flag + * + * @var bool + */ + public $debug = FALSE; + + /** + * I4 data type + * + * @var string + */ public $xmlrpcI4 = 'i4'; + + /** + * Integer data type + * + * @var string + */ public $xmlrpcInt = 'int'; + + /** + * Boolean data type + * + * @var string + */ public $xmlrpcBoolean = 'boolean'; + + /** + * Double data type + * + * @var string + */ public $xmlrpcDouble = 'double'; + + /** + * String data type + * + * @var string + */ public $xmlrpcString = 'string'; + + /** + * DateTime format + * + * @var string + */ public $xmlrpcDateTime = 'dateTime.iso8601'; + + /** + * Base64 data type + * + * @var string + */ public $xmlrpcBase64 = 'base64'; + + /** + * Array data type + * + * @var string + */ public $xmlrpcArray = 'array'; + + /** + * Struct data type + * + * @var string + */ public $xmlrpcStruct = 'struct'; + /** + * Data types list + * + * @var array + */ public $xmlrpcTypes = array(); + + /** + * Valid parents list + * + * @var array + */ public $valid_parents = array(); - public $xmlrpcerr = array(); // Response numbers - public $xmlrpcstr = array(); // Response strings + /** + * Response error numbers list + * + * @var array + */ + public $xmlrpcerr = array(); + + /** + * Response error messages list + * + * @var string[] + */ + public $xmlrpcstr = array(); + + /** + * Encoding charset + * + * @var string + */ public $xmlrpc_defencoding = 'UTF-8'; + + /** + * XML-RPC client name + * + * @var string + */ public $xmlrpcName = 'XML-RPC for CodeIgniter'; + + /** + * XML-RPC version + * + * @var string + */ public $xmlrpcVersion = '1.1'; - public $xmlrpcerruser = 800; // Start of user errors - public $xmlrpcerrxml = 100; // Start of XML Parse errors - public $xmlrpc_backslash = ''; // formulate backslashes for escaping regexp + /** + * Start of user errors + * + * @var int + */ + public $xmlrpcerruser = 800; + + /** + * Start of XML parse errors + * + * @var int + */ + public $xmlrpcerrxml = 100; + + /** + * Backslash replacement value + * + * @var string + */ + public $xmlrpc_backslash = ''; + + /** + * XML-RPC Client object + * + * @var object + */ public $client; + + /** + * XML-RPC Method name + * + * @var string + */ public $method; + + /** + * XML-RPC Data + * + * @var array + */ public $data; + + /** + * XML-RPC Message + * + * @var string + */ public $message = ''; - public $error = ''; // Error string for request + + /** + * Request error message + * + * @var string + */ + public $error = ''; + + /** + * XML-RPC result object + * + * @var object + */ public $result; + + /** + * XML-RPC Reponse + * + * @var array + */ public $response = array(); // Response from remote server + /** + * XSS Filter flag + * + * @var bool + */ public $xss_clean = TRUE; + // -------------------------------------------------------------------- /** * Constructor * * Initializes property default values * - * @param array + * @param array $config * @return void */ public function __construct($config = array()) @@ -148,7 +312,7 @@ class CI_Xmlrpc { /** * Initialize * - * @param array + * @param array $config * @return void */ public function initialize($config = array()) @@ -170,8 +334,10 @@ class CI_Xmlrpc { /** * Parse server URL * - * @param string url - * @param int port + * @param string $url + * @param int $port + * @param string $proxy + * @param int $proxy_port * @return void */ public function server($url, $port = 80, $proxy = FALSE, $proxy_port = 8080) @@ -198,7 +364,7 @@ class CI_Xmlrpc { /** * Set Timeout * - * @param int seconds + * @param int $seconds * @return void */ public function timeout($seconds = 5) @@ -214,7 +380,7 @@ class CI_Xmlrpc { /** * Set Methods * - * @param string method name + * @param string $function Method name * @return void */ public function method($function) @@ -227,7 +393,7 @@ class CI_Xmlrpc { /** * Take Array of Data and Create Objects * - * @param array + * @param array $incoming * @return void */ public function request($incoming) @@ -251,7 +417,7 @@ class CI_Xmlrpc { /** * Set Debug * - * @param bool + * @param bool $flag * @return void */ public function set_debug($flag = TRUE) @@ -264,7 +430,7 @@ class CI_Xmlrpc { /** * Values Parsing * - * @param mixed + * @param mixed $value * @return object */ public function values_parsing($value) @@ -347,8 +513,8 @@ class CI_Xmlrpc { /** * Sends an Error Message for Server Request * - * @param int - * @param string + * @param int $number + * @param string $message * @return object */ public function send_error_message($number, $message) @@ -361,7 +527,7 @@ class CI_Xmlrpc { /** * Send Response for Server Request * - * @param array + * @param array $response * @return object */ public function send_response($response) @@ -382,22 +548,79 @@ class CI_Xmlrpc { */ class XML_RPC_Client extends CI_Xmlrpc { + /** + * Path + * + * @var string + */ public $path = ''; + + /** + * Server hostname + * + * @var string + */ public $server = ''; + + /** + * Server port + * + * @var int + */ public $port = 80; + + /** + * Proxy hostname + * + * @var string + */ public $proxy = FALSE; + + /** + * Proxy port + * + * @var int + */ public $proxy_port = 8080; + + /** + * Error number + * + * @var string + */ public $errno = ''; + + /** + * Error message + * + * @var string + */ public $errstring = ''; + + /** + * Timeout in seconds + * + * @var int + */ public $timeout = 5; + + /** + * No Multicall flag + * + * @var bool + */ public $no_multicall = FALSE; + // -------------------------------------------------------------------- + /** * Constructor * - * @param string - * @param object - * @param int + * @param string $path + * @param object $server + * @param int $port + * @param string $proxy + * @param int $proxy_port * @return void */ public function __construct($path, $server, $port = 80, $proxy = FALSE, $proxy_port = 8080) @@ -416,7 +639,7 @@ class XML_RPC_Client extends CI_Xmlrpc /** * Send message * - * @param mixed + * @param mixed $msg * @return object */ public function send($msg) @@ -435,7 +658,7 @@ class XML_RPC_Client extends CI_Xmlrpc /** * Send payload * - * @param object + * @param object $msg * @return object */ public function sendPayload($msg) @@ -495,18 +718,50 @@ class XML_RPC_Client extends CI_Xmlrpc */ class XML_RPC_Response { + + /** + * Value + * + * @var mixed + */ public $val = 0; + + /** + * Error number + * + * @var int + */ public $errno = 0; + + /** + * Error message + * + * @var string + */ public $errstr = ''; + + /** + * Headers list + * + * @var array + */ public $headers = array(); + + /** + * XSS Filter flag + * + * @var bool + */ public $xss_clean = TRUE; + // -------------------------------------------------------------------- + /** * Constructor * - * @param mixed - * @param int - * @param string + * @param mixed $val + * @param int $code + * @param string $fstr * @return void */ public function __construct($val, $code = 0, $fstr = '') @@ -712,16 +967,42 @@ class XML_RPC_Response */ class XML_RPC_Message extends CI_Xmlrpc { + + /** + * Payload + * + * @var string + */ public $payload; + + /** + * Method name + * + * @var string + */ public $method_name; + + /** + * Parameter list + * + * @var array + */ public $params = array(); + + /** + * XH? + * + * @var array + */ public $xh = array(); + // -------------------------------------------------------------------- + /** * Constructor * - * @param string method name - * @param array + * @param string $method + * @param array $pars * @return void */ public function __construct($method, $pars = FALSE) @@ -1299,14 +1580,27 @@ class XML_RPC_Message extends CI_Xmlrpc */ class XML_RPC_Values extends CI_Xmlrpc { + /** + * Value data + * + * @var array + */ public $me = array(); + + /** + * Value type + * + * @var int + */ public $mytype = 0; + // -------------------------------------------------------------------- + /** * Constructor * - * @param mixed - * @param string + * @param mixed $val + * @param string $type * @return void */ public function __construct($val = -1, $type = '') @@ -1317,15 +1611,15 @@ class XML_RPC_Values extends CI_Xmlrpc { $type = $type === '' ? 'string' : $type; - if ($this->xmlrpcTypes[$type] === 1) + if ($this->xmlrpcTypes[$type] == 1) { $this->addScalar($val,$type); } - elseif ($this->xmlrpcTypes[$type] === 2) + elseif ($this->xmlrpcTypes[$type] == 2) { $this->addArray($val); } - elseif ($this->xmlrpcTypes[$type] === 3) + elseif ($this->xmlrpcTypes[$type] == 3) { $this->addStruct($val); } @@ -1351,7 +1645,7 @@ class XML_RPC_Values extends CI_Xmlrpc return 0; } - if ($typeof !== 1) + if ($typeof != 1) { echo '<strong>XML_RPC_Values</strong>: not a scalar type (${typeof})<br />'; return 0; @@ -1359,7 +1653,7 @@ class XML_RPC_Values extends CI_Xmlrpc if ($type === $this->xmlrpcBoolean) { - $val = (int) (strcasecmp($val,'true') === 0 OR $val === 1 OR ($val === TRUE && strcasecmp($val, 'false'))); + $val = (int) (strcasecmp($val, 'true') === 0 OR $val === 1 OR ($val === TRUE && strcasecmp($val, 'false'))); } if ($this->mytype === 2) diff --git a/system/libraries/Xmlrpcs.php b/system/libraries/Xmlrpcs.php index 5d01d374d..3c3337bf2 100644 --- a/system/libraries/Xmlrpcs.php +++ b/system/libraries/Xmlrpcs.php @@ -1,4 +1,4 @@ -<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed'); +<?php /** * CodeIgniter * @@ -24,6 +24,7 @@ * @since Version 1.0 * @filesource */ +defined('BASEPATH') OR exit('No direct script access allowed'); if ( ! function_exists('xml_parser_create')) { diff --git a/system/libraries/Zip.php b/system/libraries/Zip.php index 5c4c257f8..9ecd0de9f 100644 --- a/system/libraries/Zip.php +++ b/system/libraries/Zip.php @@ -1,4 +1,4 @@ -<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed'); +<?php /** * CodeIgniter * @@ -24,6 +24,7 @@ * @since Version 1.0 * @filesource */ +defined('BASEPATH') OR exit('No direct script access allowed'); /** * Zip Compression Class diff --git a/system/libraries/javascript/Jquery.php b/system/libraries/javascript/Jquery.php index 44c16b578..2bf47957f 100644 --- a/system/libraries/javascript/Jquery.php +++ b/system/libraries/javascript/Jquery.php @@ -1,4 +1,4 @@ -<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed'); +<?php /** * CodeIgniter * @@ -24,6 +24,7 @@ * @since Version 1.0 * @filesource */ +defined('BASEPATH') OR exit('No direct script access allowed'); /** * Jquery Class @@ -34,17 +35,65 @@ * @author EllisLab Dev Team * @link http://codeigniter.com/user_guide/libraries/javascript.html */ - class CI_Jquery extends CI_Javascript { + /** + * JavaScript directory location + * + * @var string + */ protected $_javascript_folder = 'js'; + + /** + * JQuery code for load + * + * @var array + */ public $jquery_code_for_load = array(); + + /** + * JQuery code for compile + * + * @var array + */ public $jquery_code_for_compile = array(); + + /** + * JQuery corner active flag + * + * @var bool + */ public $jquery_corner_active = FALSE; + + /** + * JQuery table sorter active flag + * + * @var bool + */ public $jquery_table_sorter_active = FALSE; + + /** + * JQuery table sorder pager active + * + * @var bool + */ public $jquery_table_sorter_pager_active = FALSE; + + /** + * JQuery AJAX image + * + * @var string + */ public $jquery_ajax_img = ''; + // -------------------------------------------------------------------- + + /** + * Constructor + * + * @param array $params + * @return void + */ public function __construct($params) { $this->CI =& get_instance(); @@ -101,15 +150,12 @@ class CI_Jquery extends CI_Javascript { * * @param string The element to attach the event to * @param string The code to execute - * @param boolean whether or not to return false + * @param bool whether or not to return false * @return string */ protected function _click($element = 'this', $js = '', $ret_false = TRUE) { - if ( ! is_array($js)) - { - $js = array($js); - } + is_array($js) OR $js = array($js); if ($ret_false) { @@ -307,11 +353,10 @@ class CI_Jquery extends CI_Javascript { * * Outputs script directly * - * @param string The element to attach the event to - * @param string The code to execute - * @return string + * @param array $array_js = array() + * @return void */ - protected function _output($array_js = '') + protected function _output($array_js = array()) { if ( ! is_array($array_js)) { @@ -381,10 +426,11 @@ class CI_Jquery extends CI_Javascript { * * Outputs a jQuery addClass event * - * @param string - element + * @param string $element + * @param string $class * @return string */ - protected function _addClass($element = 'this', $class='') + protected function _addClass($element = 'this', $class = '') { $element = $this->_prep_element($element); return '$('.$element.').addClass("'.$class.'");'; @@ -397,9 +443,10 @@ class CI_Jquery extends CI_Javascript { * * Outputs a jQuery animate event * - * @param string - element - * @param string - One of 'slow', 'normal', 'fast', or time in milliseconds - * @param string - Javascript callback function + * @param string $element + * @param array $params + * @param string $speed 'slow', 'normal', 'fast', or time in milliseconds + * @param string $extra * @return string */ protected function _animate($element = 'this', $params = array(), $speed = '', $extra = '') @@ -511,10 +558,11 @@ class CI_Jquery extends CI_Javascript { * * Outputs a jQuery remove class event * - * @param string - element + * @param string $element + * @param string $class * @return string */ - protected function _removeClass($element = 'this', $class='') + protected function _removeClass($element = 'this', $class = '') { $element = $this->_prep_element($element); return '$('.$element.').removeClass("'.$class.'");'; @@ -618,10 +666,11 @@ class CI_Jquery extends CI_Javascript { * * Outputs a jQuery toggle class event * - * @param string - element + * @param string $element + * @param string $class * @return string */ - protected function _toggleClass($element = 'this', $class='') + protected function _toggleClass($element = 'this', $class = '') { $element = $this->_prep_element($element); return '$('.$element.').toggleClass("'.$class.'");'; @@ -695,7 +744,6 @@ class CI_Jquery extends CI_Javascript { return $updater."\t\t$($container).load('$controller'$request_options);"; } - // -------------------------------------------------------------------- // Pre-written handy stuff // -------------------------------------------------------------------- @@ -703,14 +751,15 @@ class CI_Jquery extends CI_Javascript { /** * Zebra tables * - * @param string table name - * @param string plugin location + * @param string $class + * @param string $odd + * @param string $hover * @return string */ protected function _zebraTables($class = '', $odd = 'odd', $hover = '') { $class = ($class !== '') ? '.'.$class : ''; - $zebra = "\t\$(\"table{$class} tbody tr:nth-child(even)\").addClass(\"{$odd}\");"; + $zebra = "\t\$(\"table{$class} tbody tr:nth-child(even)\").addClass(\"{$odd}\");"; $this->jquery_code_for_compile[] = $zebra; @@ -729,9 +778,9 @@ class CI_Jquery extends CI_Javascript { /** * Corner Plugin * - * http://www.malsup.com/jquery/corner/ - * - * @param string target + * @link http://www.malsup.com/jquery/corner/ + * @param string $element + * @param string $corner_style * @return string */ public function corner($element = '', $corner_style = '') @@ -750,10 +799,12 @@ class CI_Jquery extends CI_Javascript { // -------------------------------------------------------------------- /** - * modal window + * Modal window * * Load a thickbox modal window * + * @param string $src + * @param bool $relative * @return void */ public function modal($src, $relative = FALSE) @@ -768,6 +819,8 @@ class CI_Jquery extends CI_Javascript { * * Load an Effect library * + * @param string $src + * @param bool $relative * @return void */ public function effect($src, $relative = FALSE) @@ -782,6 +835,8 @@ class CI_Jquery extends CI_Javascript { * * Load a plugin library * + * @param string $src + * @param bool $relative * @return void */ public function plugin($src, $relative = FALSE) @@ -796,12 +851,15 @@ class CI_Jquery extends CI_Javascript { * * Load a user interface library * + * @param string $src + * @param bool $relative * @return void */ public function ui($src, $relative = FALSE) { $this->jquery_code_for_load[] = $this->external($src, $relative); } + // -------------------------------------------------------------------- /** @@ -809,11 +867,12 @@ class CI_Jquery extends CI_Javascript { * * Creates a jQuery sortable * - * @return void + * @param string $element + * @param array $options + * @return string */ public function sortable($element, $options = array()) { - if (count($options) > 0) { $sort_options = array(); @@ -880,7 +939,9 @@ class CI_Jquery extends CI_Javascript { * As events are specified, they are stored in an array * This funciton compiles them all for output on a page * - * @return string + * @param string $view_var + * @param bool $script_tags + * @return void */ protected function _compile($view_var = 'script_foot', $script_tags = TRUE) { @@ -902,7 +963,6 @@ class CI_Jquery extends CI_Javascript { $output = ($script_tags === FALSE) ? $script : $this->inline($script); $this->CI->load->vars(array($view_var => $output)); - } // -------------------------------------------------------------------- @@ -926,14 +986,12 @@ class CI_Jquery extends CI_Javascript { * * A wrapper for writing document.ready() * - * @return string + * @param array $js + * @return void */ protected function _document_ready($js) { - if ( ! is_array($js)) - { - $js = array($js); - } + is_array($js) OR $js = array($js); foreach ($js as $script) { @@ -948,7 +1006,8 @@ class CI_Jquery extends CI_Javascript { * * Outputs the script tag that loads the jquery.js file into an HTML document * - * @param string + * @param string $library_src + * @param bool $relative * @return string */ public function script($library_src = '', $relative = FALSE) |