Permalink
Please sign in to comment.
Showing
with
14,926 additions
and 0 deletions.
- +255 −0 README/Cache/Cache.php
- +210 −0 README/Cache/drivers/Cache_apc.php
- +172 −0 README/Cache/drivers/Cache_dummy.php
- +286 −0 README/Cache/drivers/Cache_file.php
- +289 −0 README/Cache/drivers/Cache_memcached.php
- +320 −0 README/Cache/drivers/Cache_redis.php
- +206 −0 README/Cache/drivers/Cache_wincache.php
- +11 −0 README/Cache/drivers/index.html
- +11 −0 README/Cache/index.html
- +546 −0 README/Calendar.php
- +567 −0 README/Cart.php
- +342 −0 README/Driver.php
- +2,314 −0 README/Email.php
- +480 −0 README/Encrypt.php
- +926 −0 README/Encryption.php
- +1,595 −0 README/Form_validation.php
- +667 −0 README/Ftp.php
- +1,825 −0 README/Image_lib.php
- +856 −0 README/Javascript.php
- +1,076 −0 README/Javascript/Jquery.php
- +11 −0 README/Javascript/index.html
- +446 −0 README/Migration.php
- +697 −0 README/Pagination.php
- +248 −0 README/Parser.php
- +570 −0 README/Profiler.php
255
README/Cache/Cache.php
@@ -0,0 +1,255 @@ | ||
+<?php | ||
+/** | ||
+ * CodeIgniter | ||
+ * | ||
+ * An open source application development framework for PHP | ||
+ * | ||
+ * This content is released under the MIT License (MIT) | ||
+ * | ||
+ * Copyright (c) 2014 - 2015, British Columbia Institute of Technology | ||
+ * | ||
+ * Permission is hereby granted, free of charge, to any person obtaining a copy | ||
+ * of this software and associated documentation files (the "Software"), to deal | ||
+ * in the Software without restriction, including without limitation the rights | ||
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | ||
+ * copies of the Software, and to permit persons to whom the Software is | ||
+ * furnished to do so, subject to the following conditions: | ||
+ * | ||
+ * The above copyright notice and this permission notice shall be included in | ||
+ * all copies or substantial portions of the Software. | ||
+ * | ||
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | ||
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | ||
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN | ||
+ * THE SOFTWARE. | ||
+ * | ||
+ * @package CodeIgniter | ||
+ * @author EllisLab Dev Team | ||
+ * @copyright Copyright (c) 2008 - 2014, EllisLab, Inc. (http://ellislab.com/) | ||
+ * @copyright Copyright (c) 2014 - 2015, British Columbia Institute of Technology (http://bcit.ca/) | ||
+ * @license http://opensource.org/licenses/MIT MIT License | ||
+ * @link http://codeigniter.com | ||
+ * @since Version 2.0.0 | ||
+ * @filesource | ||
+ */ | ||
+defined('BASEPATH') OR exit('No direct script access allowed'); | ||
+ | ||
+/** | ||
+ * CodeIgniter Caching Class | ||
+ * | ||
+ * @package CodeIgniter | ||
+ * @subpackage Libraries | ||
+ * @category Core | ||
+ * @author EllisLab Dev Team | ||
+ * @link | ||
+ */ | ||
+class CI_Cache extends CI_Driver_Library { | ||
+ | ||
+ /** | ||
+ * Valid cache drivers | ||
+ * | ||
+ * @var array | ||
+ */ | ||
+ protected $valid_drivers = array( | ||
+ 'apc', | ||
+ 'dummy', | ||
+ 'file', | ||
+ 'memcached', | ||
+ 'redis', | ||
+ 'wincache' | ||
+ ); | ||
+ | ||
+ /** | ||
+ * Path of cache files (if file-based cache) | ||
+ * | ||
+ * @var string | ||
+ */ | ||
+ protected $_cache_path = NULL; | ||
+ | ||
+ /** | ||
+ * Reference to the driver | ||
+ * | ||
+ * @var mixed | ||
+ */ | ||
+ protected $_adapter = 'dummy'; | ||
+ | ||
+ /** | ||
+ * Fallback driver | ||
+ * | ||
+ * @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 $config = array() | ||
+ * @return void | ||
+ */ | ||
+ public function __construct($config = array()) | ||
+ { | ||
+ isset($config['adapter']) && $this->_adapter = $config['adapter']; | ||
+ isset($config['backup']) && $this->_backup_driver = $config['backup']; | ||
+ isset($config['key_prefix']) && $this->key_prefix = $config['key_prefix']; | ||
+ | ||
+ // If the specified adapter isn't available, check the backup. | ||
+ if ( ! $this->is_supported($this->_adapter)) | ||
+ { | ||
+ if ( ! $this->is_supported($this->_backup_driver)) | ||
+ { | ||
+ // Backup isn't supported either. Default to 'Dummy' driver. | ||
+ log_message('error', 'Cache adapter "'.$this->_adapter.'" and backup "'.$this->_backup_driver.'" are both unavailable. Cache is now using "Dummy" adapter.'); | ||
+ $this->_adapter = 'dummy'; | ||
+ } | ||
+ else | ||
+ { | ||
+ // Backup is supported. Set it to primary. | ||
+ log_message('debug', 'Cache adapter "'.$this->_adapter.'" is unavailable. Falling back to "'.$this->_backup_driver.'" backup adapter.'); | ||
+ $this->_adapter = $this->_backup_driver; | ||
+ } | ||
+ } | ||
+ } | ||
+ | ||
+ // ------------------------------------------------------------------------ | ||
+ | ||
+ /** | ||
+ * Get | ||
+ * | ||
+ * Look for a value in the cache. If it exists, return the data | ||
+ * if not, return FALSE | ||
+ * | ||
+ * @param string $id | ||
+ * @return mixed value matching $id or FALSE on failure | ||
+ */ | ||
+ public function get($id) | ||
+ { | ||
+ return $this->{$this->_adapter}->get($this->key_prefix.$id); | ||
+ } | ||
+ | ||
+ // ------------------------------------------------------------------------ | ||
+ | ||
+ /** | ||
+ * Cache Save | ||
+ * | ||
+ * @param string $id Cache ID | ||
+ * @param mixed $data Data to store | ||
+ * @param int $ttl Cache TTL (in seconds) | ||
+ * @param bool $raw Whether to store the raw value | ||
+ * @return bool TRUE on success, FALSE on failure | ||
+ */ | ||
+ public function save($id, $data, $ttl = 60, $raw = FALSE) | ||
+ { | ||
+ return $this->{$this->_adapter}->save($this->key_prefix.$id, $data, $ttl, $raw); | ||
+ } | ||
+ | ||
+ // ------------------------------------------------------------------------ | ||
+ | ||
+ /** | ||
+ * Delete from Cache | ||
+ * | ||
+ * @param string $id Cache ID | ||
+ * @return bool TRUE on success, FALSE on failure | ||
+ */ | ||
+ public function delete($id) | ||
+ { | ||
+ return $this->{$this->_adapter}->delete($this->key_prefix.$id); | ||
+ } | ||
+ | ||
+ // ------------------------------------------------------------------------ | ||
+ | ||
+ /** | ||
+ * Increment a raw value | ||
+ * | ||
+ * @param string $id Cache ID | ||
+ * @param int $offset Step/value to add | ||
+ * @return mixed New value on success or FALSE on failure | ||
+ */ | ||
+ public function increment($id, $offset = 1) | ||
+ { | ||
+ return $this->{$this->_adapter}->increment($this->key_prefix.$id, $offset); | ||
+ } | ||
+ | ||
+ // ------------------------------------------------------------------------ | ||
+ | ||
+ /** | ||
+ * Decrement a raw value | ||
+ * | ||
+ * @param string $id Cache ID | ||
+ * @param int $offset Step/value to reduce by | ||
+ * @return mixed New value on success or FALSE on failure | ||
+ */ | ||
+ public function decrement($id, $offset = 1) | ||
+ { | ||
+ return $this->{$this->_adapter}->decrement($this->key_prefix.$id, $offset); | ||
+ } | ||
+ | ||
+ // ------------------------------------------------------------------------ | ||
+ | ||
+ /** | ||
+ * Clean the cache | ||
+ * | ||
+ * @return bool TRUE on success, FALSE on failure | ||
+ */ | ||
+ public function clean() | ||
+ { | ||
+ return $this->{$this->_adapter}->clean(); | ||
+ } | ||
+ | ||
+ // ------------------------------------------------------------------------ | ||
+ | ||
+ /** | ||
+ * Cache Info | ||
+ * | ||
+ * @param string $type = 'user' user/filehits | ||
+ * @return mixed array containing cache info on success OR FALSE on failure | ||
+ */ | ||
+ public function cache_info($type = 'user') | ||
+ { | ||
+ return $this->{$this->_adapter}->cache_info($type); | ||
+ } | ||
+ | ||
+ // ------------------------------------------------------------------------ | ||
+ | ||
+ /** | ||
+ * Get Cache Metadata | ||
+ * | ||
+ * @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($this->key_prefix.$id); | ||
+ } | ||
+ | ||
+ // ------------------------------------------------------------------------ | ||
+ | ||
+ /** | ||
+ * Is the requested driver supported in this environment? | ||
+ * | ||
+ * @param string $driver The driver to test | ||
+ * @return array | ||
+ */ | ||
+ public function is_supported($driver) | ||
+ { | ||
+ static $support; | ||
+ | ||
+ if ( ! isset($support, $support[$driver])) | ||
+ { | ||
+ $support[$driver] = $this->{$driver}->is_supported(); | ||
+ } | ||
+ | ||
+ return $support[$driver]; | ||
+ } | ||
+} |
210
README/Cache/drivers/Cache_apc.php
@@ -0,0 +1,210 @@ | ||
+<?php | ||
+/** | ||
+ * CodeIgniter | ||
+ * | ||
+ * An open source application development framework for PHP | ||
+ * | ||
+ * This content is released under the MIT License (MIT) | ||
+ * | ||
+ * Copyright (c) 2014 - 2015, British Columbia Institute of Technology | ||
+ * | ||
+ * Permission is hereby granted, free of charge, to any person obtaining a copy | ||
+ * of this software and associated documentation files (the "Software"), to deal | ||
+ * in the Software without restriction, including without limitation the rights | ||
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | ||
+ * copies of the Software, and to permit persons to whom the Software is | ||
+ * furnished to do so, subject to the following conditions: | ||
+ * | ||
+ * The above copyright notice and this permission notice shall be included in | ||
+ * all copies or substantial portions of the Software. | ||
+ * | ||
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | ||
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | ||
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN | ||
+ * THE SOFTWARE. | ||
+ * | ||
+ * @package CodeIgniter | ||
+ * @author EllisLab Dev Team | ||
+ * @copyright Copyright (c) 2008 - 2014, EllisLab, Inc. (http://ellislab.com/) | ||
+ * @copyright Copyright (c) 2014 - 2015, British Columbia Institute of Technology (http://bcit.ca/) | ||
+ * @license http://opensource.org/licenses/MIT MIT License | ||
+ * @link http://codeigniter.com | ||
+ * @since Version 2.0.0 | ||
+ * @filesource | ||
+ */ | ||
+defined('BASEPATH') OR exit('No direct script access allowed'); | ||
+ | ||
+/** | ||
+ * CodeIgniter APC Caching Class | ||
+ * | ||
+ * @package CodeIgniter | ||
+ * @subpackage Libraries | ||
+ * @category Core | ||
+ * @author EllisLab Dev Team | ||
+ * @link | ||
+ */ | ||
+class CI_Cache_apc extends CI_Driver { | ||
+ | ||
+ /** | ||
+ * Get | ||
+ * | ||
+ * 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 | ||
+ */ | ||
+ public function get($id) | ||
+ { | ||
+ $success = FALSE; | ||
+ $data = apc_fetch($id, $success); | ||
+ | ||
+ if ($success === TRUE) | ||
+ { | ||
+ return is_array($data) | ||
+ ? unserialize($data[0]) | ||
+ : $data; | ||
+ } | ||
+ | ||
+ return FALSE; | ||
+ } | ||
+ | ||
+ // ------------------------------------------------------------------------ | ||
+ | ||
+ /** | ||
+ * Cache Save | ||
+ * | ||
+ * @param string $id Cache ID | ||
+ * @param mixed $data Data to store | ||
+ * @param int $ttol Length of time (in seconds) to cache the data | ||
+ * @param bool $raw Whether to store the raw value | ||
+ * @return bool TRUE on success, FALSE on failure | ||
+ */ | ||
+ public function save($id, $data, $ttl = 60, $raw = FALSE) | ||
+ { | ||
+ $ttl = (int) $ttl; | ||
+ | ||
+ return apc_store( | ||
+ $id, | ||
+ ($raw === TRUE ? $data : array(serialize($data), time(), $ttl)), | ||
+ $ttl | ||
+ ); | ||
+ } | ||
+ | ||
+ // ------------------------------------------------------------------------ | ||
+ | ||
+ /** | ||
+ * Delete from Cache | ||
+ * | ||
+ * @param mixed unique identifier of the item in the cache | ||
+ * @return bool true on success/false on failure | ||
+ */ | ||
+ public function delete($id) | ||
+ { | ||
+ return apc_delete($id); | ||
+ } | ||
+ | ||
+ // ------------------------------------------------------------------------ | ||
+ | ||
+ /** | ||
+ * Increment a raw value | ||
+ * | ||
+ * @param string $id Cache ID | ||
+ * @param int $offset Step/value to add | ||
+ * @return mixed New value on success or FALSE on failure | ||
+ */ | ||
+ public function increment($id, $offset = 1) | ||
+ { | ||
+ return apc_inc($id, $offset); | ||
+ } | ||
+ | ||
+ // ------------------------------------------------------------------------ | ||
+ | ||
+ /** | ||
+ * Decrement a raw value | ||
+ * | ||
+ * @param string $id Cache ID | ||
+ * @param int $offset Step/value to reduce by | ||
+ * @return mixed New value on success or FALSE on failure | ||
+ */ | ||
+ public function decrement($id, $offset = 1) | ||
+ { | ||
+ return apc_dec($id, $offset); | ||
+ } | ||
+ | ||
+ // ------------------------------------------------------------------------ | ||
+ | ||
+ /** | ||
+ * Clean the cache | ||
+ * | ||
+ * @return bool false on failure/true on success | ||
+ */ | ||
+ public function clean() | ||
+ { | ||
+ return apc_clear_cache('user'); | ||
+ } | ||
+ | ||
+ // ------------------------------------------------------------------------ | ||
+ | ||
+ /** | ||
+ * Cache Info | ||
+ * | ||
+ * @param string user/filehits | ||
+ * @return mixed array on success, false on failure | ||
+ */ | ||
+ public function cache_info($type = NULL) | ||
+ { | ||
+ return apc_cache_info($type); | ||
+ } | ||
+ | ||
+ // ------------------------------------------------------------------------ | ||
+ | ||
+ /** | ||
+ * Get Cache Metadata | ||
+ * | ||
+ * @param mixed key to get cache metadata on | ||
+ * @return mixed array on success/false on failure | ||
+ */ | ||
+ public function get_metadata($id) | ||
+ { | ||
+ $success = FALSE; | ||
+ $stored = apc_fetch($id, $success); | ||
+ | ||
+ if ($success === FALSE OR count($stored) !== 3) | ||
+ { | ||
+ return FALSE; | ||
+ } | ||
+ | ||
+ list($data, $time, $ttl) = $stored; | ||
+ | ||
+ return array( | ||
+ 'expire' => $time + $ttl, | ||
+ 'mtime' => $time, | ||
+ 'data' => unserialize($data) | ||
+ ); | ||
+ } | ||
+ | ||
+ // ------------------------------------------------------------------------ | ||
+ | ||
+ /** | ||
+ * is_supported() | ||
+ * | ||
+ * Check to see if APC is available on this system, bail if it isn't. | ||
+ * | ||
+ * @return bool | ||
+ */ | ||
+ public function is_supported() | ||
+ { | ||
+ if ( ! extension_loaded('apc') OR ! ini_get('apc.enabled')) | ||
+ { | ||
+ log_message('debug', 'The APC PHP extension must be loaded to use APC Cache.'); | ||
+ return FALSE; | ||
+ } | ||
+ | ||
+ return TRUE; | ||
+ } | ||
+ | ||
+} |
172
README/Cache/drivers/Cache_dummy.php
@@ -0,0 +1,172 @@ | ||
+<?php | ||
+/** | ||
+ * CodeIgniter | ||
+ * | ||
+ * An open source application development framework for PHP | ||
+ * | ||
+ * This content is released under the MIT License (MIT) | ||
+ * | ||
+ * Copyright (c) 2014 - 2015, British Columbia Institute of Technology | ||
+ * | ||
+ * Permission is hereby granted, free of charge, to any person obtaining a copy | ||
+ * of this software and associated documentation files (the "Software"), to deal | ||
+ * in the Software without restriction, including without limitation the rights | ||
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | ||
+ * copies of the Software, and to permit persons to whom the Software is | ||
+ * furnished to do so, subject to the following conditions: | ||
+ * | ||
+ * The above copyright notice and this permission notice shall be included in | ||
+ * all copies or substantial portions of the Software. | ||
+ * | ||
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | ||
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | ||
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN | ||
+ * THE SOFTWARE. | ||
+ * | ||
+ * @package CodeIgniter | ||
+ * @author EllisLab Dev Team | ||
+ * @copyright Copyright (c) 2008 - 2014, EllisLab, Inc. (http://ellislab.com/) | ||
+ * @copyright Copyright (c) 2014 - 2015, British Columbia Institute of Technology (http://bcit.ca/) | ||
+ * @license http://opensource.org/licenses/MIT MIT License | ||
+ * @link http://codeigniter.com | ||
+ * @since Version 2.0 | ||
+ * @filesource | ||
+ */ | ||
+defined('BASEPATH') OR exit('No direct script access allowed'); | ||
+ | ||
+/** | ||
+ * CodeIgniter Dummy Caching Class | ||
+ * | ||
+ * @package CodeIgniter | ||
+ * @subpackage Libraries | ||
+ * @category Core | ||
+ * @author EllisLab Dev Team | ||
+ * @link | ||
+ */ | ||
+class CI_Cache_dummy extends CI_Driver { | ||
+ | ||
+ /** | ||
+ * Get | ||
+ * | ||
+ * Since this is the dummy class, it's always going to return FALSE. | ||
+ * | ||
+ * @param string | ||
+ * @return bool FALSE | ||
+ */ | ||
+ public function get($id) | ||
+ { | ||
+ return FALSE; | ||
+ } | ||
+ | ||
+ // ------------------------------------------------------------------------ | ||
+ | ||
+ /** | ||
+ * Cache Save | ||
+ * | ||
+ * @param string Unique Key | ||
+ * @param mixed Data to store | ||
+ * @param int Length of time (in seconds) to cache the data | ||
+ * @param bool Whether to store the raw value | ||
+ * @return bool TRUE, Simulating success | ||
+ */ | ||
+ public function save($id, $data, $ttl = 60, $raw = FALSE) | ||
+ { | ||
+ return TRUE; | ||
+ } | ||
+ | ||
+ // ------------------------------------------------------------------------ | ||
+ | ||
+ /** | ||
+ * Delete from Cache | ||
+ * | ||
+ * @param mixed unique identifier of the item in the cache | ||
+ * @return bool TRUE, simulating success | ||
+ */ | ||
+ public function delete($id) | ||
+ { | ||
+ return TRUE; | ||
+ } | ||
+ | ||
+ // ------------------------------------------------------------------------ | ||
+ | ||
+ /** | ||
+ * Increment a raw value | ||
+ * | ||
+ * @param string $id Cache ID | ||
+ * @param int $offset Step/value to add | ||
+ * @return mixed New value on success or FALSE on failure | ||
+ */ | ||
+ public function increment($id, $offset = 1) | ||
+ { | ||
+ return TRUE; | ||
+ } | ||
+ | ||
+ // ------------------------------------------------------------------------ | ||
+ | ||
+ /** | ||
+ * Decrement a raw value | ||
+ * | ||
+ * @param string $id Cache ID | ||
+ * @param int $offset Step/value to reduce by | ||
+ * @return mixed New value on success or FALSE on failure | ||
+ */ | ||
+ public function decrement($id, $offset = 1) | ||
+ { | ||
+ return TRUE; | ||
+ } | ||
+ | ||
+ // ------------------------------------------------------------------------ | ||
+ | ||
+ /** | ||
+ * Clean the cache | ||
+ * | ||
+ * @return bool TRUE, simulating success | ||
+ */ | ||
+ public function clean() | ||
+ { | ||
+ return TRUE; | ||
+ } | ||
+ | ||
+ // ------------------------------------------------------------------------ | ||
+ | ||
+ /** | ||
+ * Cache Info | ||
+ * | ||
+ * @param string user/filehits | ||
+ * @return bool FALSE | ||
+ */ | ||
+ public function cache_info($type = NULL) | ||
+ { | ||
+ return FALSE; | ||
+ } | ||
+ | ||
+ // ------------------------------------------------------------------------ | ||
+ | ||
+ /** | ||
+ * Get Cache Metadata | ||
+ * | ||
+ * @param mixed key to get cache metadata on | ||
+ * @return bool FALSE | ||
+ */ | ||
+ public function get_metadata($id) | ||
+ { | ||
+ return FALSE; | ||
+ } | ||
+ | ||
+ // ------------------------------------------------------------------------ | ||
+ | ||
+ /** | ||
+ * Is this caching driver supported on the system? | ||
+ * Of course this one is. | ||
+ * | ||
+ * @return bool TRUE | ||
+ */ | ||
+ public function is_supported() | ||
+ { | ||
+ return TRUE; | ||
+ } | ||
+ | ||
+} |
286
README/Cache/drivers/Cache_file.php
@@ -0,0 +1,286 @@ | ||
+<?php | ||
+/** | ||
+ * CodeIgniter | ||
+ * | ||
+ * An open source application development framework for PHP | ||
+ * | ||
+ * This content is released under the MIT License (MIT) | ||
+ * | ||
+ * Copyright (c) 2014 - 2015, British Columbia Institute of Technology | ||
+ * | ||
+ * Permission is hereby granted, free of charge, to any person obtaining a copy | ||
+ * of this software and associated documentation files (the "Software"), to deal | ||
+ * in the Software without restriction, including without limitation the rights | ||
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | ||
+ * copies of the Software, and to permit persons to whom the Software is | ||
+ * furnished to do so, subject to the following conditions: | ||
+ * | ||
+ * The above copyright notice and this permission notice shall be included in | ||
+ * all copies or substantial portions of the Software. | ||
+ * | ||
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | ||
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | ||
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN | ||
+ * THE SOFTWARE. | ||
+ * | ||
+ * @package CodeIgniter | ||
+ * @author EllisLab Dev Team | ||
+ * @copyright Copyright (c) 2008 - 2014, EllisLab, Inc. (http://ellislab.com/) | ||
+ * @copyright Copyright (c) 2014 - 2015, British Columbia Institute of Technology (http://bcit.ca/) | ||
+ * @license http://opensource.org/licenses/MIT MIT License | ||
+ * @link http://codeigniter.com | ||
+ * @since Version 2.0 | ||
+ * @filesource | ||
+ */ | ||
+defined('BASEPATH') OR exit('No direct script access allowed'); | ||
+ | ||
+/** | ||
+ * CodeIgniter File Caching Class | ||
+ * | ||
+ * @package CodeIgniter | ||
+ * @subpackage Libraries | ||
+ * @category Core | ||
+ * @author EllisLab Dev Team | ||
+ * @link | ||
+ */ | ||
+class CI_Cache_file extends CI_Driver { | ||
+ | ||
+ /** | ||
+ * Directory in which to save cache files | ||
+ * | ||
+ * @var string | ||
+ */ | ||
+ protected $_cache_path; | ||
+ | ||
+ /** | ||
+ * Initialize file-based cache | ||
+ * | ||
+ * @return void | ||
+ */ | ||
+ public function __construct() | ||
+ { | ||
+ $CI =& get_instance(); | ||
+ $CI->load->helper('file'); | ||
+ $path = $CI->config->item('cache_path'); | ||
+ $this->_cache_path = ($path === '') ? APPPATH.'cache/' : $path; | ||
+ } | ||
+ | ||
+ // ------------------------------------------------------------------------ | ||
+ | ||
+ /** | ||
+ * Fetch from cache | ||
+ * | ||
+ * @param string $id Cache ID | ||
+ * @return mixed Data on success, FALSE on failure | ||
+ */ | ||
+ public function get($id) | ||
+ { | ||
+ $data = $this->_get($id); | ||
+ return is_array($data) ? $data['data'] : FALSE; | ||
+ } | ||
+ | ||
+ // ------------------------------------------------------------------------ | ||
+ | ||
+ /** | ||
+ * Save into cache | ||
+ * | ||
+ * @param string $id Cache ID | ||
+ * @param mixed $data Data to store | ||
+ * @param int $ttl Time to live in seconds | ||
+ * @param bool $raw Whether to store the raw value (unused) | ||
+ * @return bool TRUE on success, FALSE on failure | ||
+ */ | ||
+ public function save($id, $data, $ttl = 60, $raw = FALSE) | ||
+ { | ||
+ $contents = array( | ||
+ 'time' => time(), | ||
+ 'ttl' => $ttl, | ||
+ 'data' => $data | ||
+ ); | ||
+ | ||
+ if (write_file($this->_cache_path.$id, serialize($contents))) | ||
+ { | ||
+ chmod($this->_cache_path.$id, 0640); | ||
+ return TRUE; | ||
+ } | ||
+ | ||
+ return FALSE; | ||
+ } | ||
+ | ||
+ // ------------------------------------------------------------------------ | ||
+ | ||
+ /** | ||
+ * Delete from Cache | ||
+ * | ||
+ * @param mixed unique identifier of item in cache | ||
+ * @return bool true on success/false on failure | ||
+ */ | ||
+ public function delete($id) | ||
+ { | ||
+ return file_exists($this->_cache_path.$id) ? unlink($this->_cache_path.$id) : FALSE; | ||
+ } | ||
+ | ||
+ // ------------------------------------------------------------------------ | ||
+ | ||
+ /** | ||
+ * Increment a raw value | ||
+ * | ||
+ * @param string $id Cache ID | ||
+ * @param int $offset Step/value to add | ||
+ * @return New value on success, FALSE on failure | ||
+ */ | ||
+ public function increment($id, $offset = 1) | ||
+ { | ||
+ $data = $this->_get($id); | ||
+ | ||
+ if ($data === FALSE) | ||
+ { | ||
+ $data = array('data' => 0, 'ttl' => 60); | ||
+ } | ||
+ elseif ( ! is_int($data['data'])) | ||
+ { | ||
+ return FALSE; | ||
+ } | ||
+ | ||
+ $new_value = $data['data'] + $offset; | ||
+ return $this->save($id, $new_value, $data['ttl']) | ||
+ ? $new_value | ||
+ : FALSE; | ||
+ } | ||
+ | ||
+ // ------------------------------------------------------------------------ | ||
+ | ||
+ /** | ||
+ * Decrement a raw value | ||
+ * | ||
+ * @param string $id Cache ID | ||
+ * @param int $offset Step/value to reduce by | ||
+ * @return New value on success, FALSE on failure | ||
+ */ | ||
+ public function decrement($id, $offset = 1) | ||
+ { | ||
+ $data = $this->_get($id); | ||
+ | ||
+ if ($data === FALSE) | ||
+ { | ||
+ $data = array('data' => 0, 'ttl' => 60); | ||
+ } | ||
+ elseif ( ! is_int($data['data'])) | ||
+ { | ||
+ return FALSE; | ||
+ } | ||
+ | ||
+ $new_value = $data['data'] - $offset; | ||
+ return $this->save($id, $new_value, $data['ttl']) | ||
+ ? $new_value | ||
+ : FALSE; | ||
+ } | ||
+ | ||
+ // ------------------------------------------------------------------------ | ||
+ | ||
+ /** | ||
+ * Clean the Cache | ||
+ * | ||
+ * @return bool false on failure/true on success | ||
+ */ | ||
+ public function clean() | ||
+ { | ||
+ return delete_files($this->_cache_path, FALSE, TRUE); | ||
+ } | ||
+ | ||
+ // ------------------------------------------------------------------------ | ||
+ | ||
+ /** | ||
+ * Cache Info | ||
+ * | ||
+ * Not supported by file-based caching | ||
+ * | ||
+ * @param string user/filehits | ||
+ * @return mixed FALSE | ||
+ */ | ||
+ public function cache_info($type = NULL) | ||
+ { | ||
+ return get_dir_file_info($this->_cache_path); | ||
+ } | ||
+ | ||
+ // ------------------------------------------------------------------------ | ||
+ | ||
+ /** | ||
+ * Get Cache Metadata | ||
+ * | ||
+ * @param mixed key to get cache metadata on | ||
+ * @return mixed FALSE on failure, array on success. | ||
+ */ | ||
+ public function get_metadata($id) | ||
+ { | ||
+ if ( ! file_exists($this->_cache_path.$id)) | ||
+ { | ||
+ return FALSE; | ||
+ } | ||
+ | ||
+ $data = unserialize(file_get_contents($this->_cache_path.$id)); | ||
+ | ||
+ if (is_array($data)) | ||
+ { | ||
+ $mtime = filemtime($this->_cache_path.$id); | ||
+ | ||
+ if ( ! isset($data['ttl'])) | ||
+ { | ||
+ return FALSE; | ||
+ } | ||
+ | ||
+ return array( | ||
+ 'expire' => $mtime + $data['ttl'], | ||
+ 'mtime' => $mtime | ||
+ ); | ||
+ } | ||
+ | ||
+ return FALSE; | ||
+ } | ||
+ | ||
+ // ------------------------------------------------------------------------ | ||
+ | ||
+ /** | ||
+ * Is supported | ||
+ * | ||
+ * In the file driver, check to see that the cache directory is indeed writable | ||
+ * | ||
+ * @return bool | ||
+ */ | ||
+ public function is_supported() | ||
+ { | ||
+ return is_really_writable($this->_cache_path); | ||
+ } | ||
+ | ||
+ // ------------------------------------------------------------------------ | ||
+ | ||
+ /** | ||
+ * Get all data | ||
+ * | ||
+ * Internal method to get all the relevant data about a cache item | ||
+ * | ||
+ * @param string $id Cache ID | ||
+ * @return mixed Data array on success or FALSE on failure | ||
+ */ | ||
+ protected function _get($id) | ||
+ { | ||
+ if ( ! is_file($this->_cache_path.$id)) | ||
+ { | ||
+ return FALSE; | ||
+ } | ||
+ | ||
+ $data = unserialize(file_get_contents($this->_cache_path.$id)); | ||
+ | ||
+ if ($data['ttl'] > 0 && time() > $data['time'] + $data['ttl']) | ||
+ { | ||
+ unlink($this->_cache_path.$id); | ||
+ return FALSE; | ||
+ } | ||
+ | ||
+ return $data; | ||
+ } | ||
+ | ||
+} |
289
README/Cache/drivers/Cache_memcached.php
@@ -0,0 +1,289 @@ | ||
+<?php | ||
+/** | ||
+ * CodeIgniter | ||
+ * | ||
+ * An open source application development framework for PHP | ||
+ * | ||
+ * This content is released under the MIT License (MIT) | ||
+ * | ||
+ * Copyright (c) 2014 - 2015, British Columbia Institute of Technology | ||
+ * | ||
+ * Permission is hereby granted, free of charge, to any person obtaining a copy | ||
+ * of this software and associated documentation files (the "Software"), to deal | ||
+ * in the Software without restriction, including without limitation the rights | ||
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | ||
+ * copies of the Software, and to permit persons to whom the Software is | ||
+ * furnished to do so, subject to the following conditions: | ||
+ * | ||
+ * The above copyright notice and this permission notice shall be included in | ||
+ * all copies or substantial portions of the Software. | ||
+ * | ||
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | ||
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | ||
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN | ||
+ * THE SOFTWARE. | ||
+ * | ||
+ * @package CodeIgniter | ||
+ * @author EllisLab Dev Team | ||
+ * @copyright Copyright (c) 2008 - 2014, EllisLab, Inc. (http://ellislab.com/) | ||
+ * @copyright Copyright (c) 2014 - 2015, British Columbia Institute of Technology (http://bcit.ca/) | ||
+ * @license http://opensource.org/licenses/MIT MIT License | ||
+ * @link http://codeigniter.com | ||
+ * @since Version 2.0 | ||
+ * @filesource | ||
+ */ | ||
+defined('BASEPATH') OR exit('No direct script access allowed'); | ||
+ | ||
+/** | ||
+ * CodeIgniter Memcached Caching Class | ||
+ * | ||
+ * @package CodeIgniter | ||
+ * @subpackage Libraries | ||
+ * @category Core | ||
+ * @author EllisLab Dev Team | ||
+ * @link | ||
+ */ | ||
+class CI_Cache_memcached extends CI_Driver { | ||
+ | ||
+ /** | ||
+ * Holds the memcached object | ||
+ * | ||
+ * @var object | ||
+ */ | ||
+ protected $_memcached; | ||
+ | ||
+ /** | ||
+ * Memcached configuration | ||
+ * | ||
+ * @var array | ||
+ */ | ||
+ protected $_memcache_conf = array( | ||
+ 'default' => array( | ||
+ 'host' => '127.0.0.1', | ||
+ 'port' => 11211, | ||
+ 'weight' => 1 | ||
+ ) | ||
+ ); | ||
+ | ||
+ // ------------------------------------------------------------------------ | ||
+ | ||
+ /** | ||
+ * Class constructor | ||
+ * | ||
+ * Setup Memcache(d) | ||
+ * | ||
+ * @return void | ||
+ */ | ||
+ public function __construct() | ||
+ { | ||
+ // Try to load memcached server info from the config file. | ||
+ $CI =& get_instance(); | ||
+ $defaults = $this->_memcache_conf['default']; | ||
+ | ||
+ if ($CI->config->load('memcached', TRUE, TRUE)) | ||
+ { | ||
+ if (is_array($CI->config->config['memcached'])) | ||
+ { | ||
+ $this->_memcache_conf = array(); | ||
+ | ||
+ foreach ($CI->config->config['memcached'] as $name => $conf) | ||
+ { | ||
+ $this->_memcache_conf[$name] = $conf; | ||
+ } | ||
+ } | ||
+ } | ||
+ | ||
+ if (class_exists('Memcached', FALSE)) | ||
+ { | ||
+ $this->_memcached = new Memcached(); | ||
+ } | ||
+ elseif (class_exists('Memcache', FALSE)) | ||
+ { | ||
+ $this->_memcached = new Memcache(); | ||
+ } | ||
+ else | ||
+ { | ||
+ log_message('error', 'Cache: Failed to create Memcache(d) object; extension not loaded?'); | ||
+ } | ||
+ | ||
+ foreach ($this->_memcache_conf as $cache_server) | ||
+ { | ||
+ isset($cache_server['hostname']) OR $cache_server['hostname'] = $defaults['host']; | ||
+ isset($cache_server['port']) OR $cache_server['port'] = $defaults['port']; | ||
+ isset($cache_server['weight']) OR $cache_server['weight'] = $defaults['weight']; | ||
+ | ||
+ if (get_class($this->_memcached) === 'Memcache') | ||
+ { | ||
+ // Third parameter is persistance and defaults to TRUE. | ||
+ $this->_memcached->addServer( | ||
+ $cache_server['hostname'], | ||
+ $cache_server['port'], | ||
+ TRUE, | ||
+ $cache_server['weight'] | ||
+ ); | ||
+ } | ||
+ else | ||
+ { | ||
+ $this->_memcached->addServer( | ||
+ $cache_server['hostname'], | ||
+ $cache_server['port'], | ||
+ $cache_server['weight'] | ||
+ ); | ||
+ } | ||
+ } | ||
+ } | ||
+ | ||
+ // ------------------------------------------------------------------------ | ||
+ | ||
+ /** | ||
+ * Fetch from cache | ||
+ * | ||
+ * @param string $id Cache ID | ||
+ * @return mixed Data on success, FALSE on failure | ||
+ */ | ||
+ public function get($id) | ||
+ { | ||
+ $data = $this->_memcached->get($id); | ||
+ | ||
+ return is_array($data) ? $data[0] : $data; | ||
+ } | ||
+ | ||
+ // ------------------------------------------------------------------------ | ||
+ | ||
+ /** | ||
+ * Save | ||
+ * | ||
+ * @param string $id Cache ID | ||
+ * @param mixed $data Data being cached | ||
+ * @param int $ttl Time to live | ||
+ * @param bool $raw Whether to store the raw value | ||
+ * @return bool TRUE on success, FALSE on failure | ||
+ */ | ||
+ public function save($id, $data, $ttl = 60, $raw = FALSE) | ||
+ { | ||
+ if ($raw !== TRUE) | ||
+ { | ||
+ $data = array($data, time(), $ttl); | ||
+ } | ||
+ | ||
+ if (get_class($this->_memcached) === 'Memcached') | ||
+ { | ||
+ return $this->_memcached->set($id, $data, $ttl); | ||
+ } | ||
+ elseif (get_class($this->_memcached) === 'Memcache') | ||
+ { | ||
+ return $this->_memcached->set($id, $data, 0, $ttl); | ||
+ } | ||
+ | ||
+ return FALSE; | ||
+ } | ||
+ | ||
+ // ------------------------------------------------------------------------ | ||
+ | ||
+ /** | ||
+ * Delete from Cache | ||
+ * | ||
+ * @param mixed key to be deleted. | ||
+ * @return bool true on success, false on failure | ||
+ */ | ||
+ public function delete($id) | ||
+ { | ||
+ return $this->_memcached->delete($id); | ||
+ } | ||
+ | ||
+ // ------------------------------------------------------------------------ | ||
+ | ||
+ /** | ||
+ * Increment a raw value | ||
+ * | ||
+ * @param string $id Cache ID | ||
+ * @param int $offset Step/value to add | ||
+ * @return mixed New value on success or FALSE on failure | ||
+ */ | ||
+ public function increment($id, $offset = 1) | ||
+ { | ||
+ return $this->_memcached->increment($id, $offset); | ||
+ } | ||
+ | ||
+ // ------------------------------------------------------------------------ | ||
+ | ||
+ /** | ||
+ * Decrement a raw value | ||
+ * | ||
+ * @param string $id Cache ID | ||
+ * @param int $offset Step/value to reduce by | ||
+ * @return mixed New value on success or FALSE on failure | ||
+ */ | ||
+ public function decrement($id, $offset = 1) | ||
+ { | ||
+ return $this->_memcached->decrement($id, $offset); | ||
+ } | ||
+ | ||
+ // ------------------------------------------------------------------------ | ||
+ | ||
+ /** | ||
+ * Clean the Cache | ||
+ * | ||
+ * @return bool false on failure/true on success | ||
+ */ | ||
+ public function clean() | ||
+ { | ||
+ return $this->_memcached->flush(); | ||
+ } | ||
+ | ||
+ // ------------------------------------------------------------------------ | ||
+ | ||
+ /** | ||
+ * Cache Info | ||
+ * | ||
+ * @return mixed array on success, false on failure | ||
+ */ | ||
+ public function cache_info() | ||
+ { | ||
+ return $this->_memcached->getStats(); | ||
+ } | ||
+ | ||
+ // ------------------------------------------------------------------------ | ||
+ | ||
+ /** | ||
+ * Get Cache Metadata | ||
+ * | ||
+ * @param mixed key to get cache metadata on | ||
+ * @return mixed FALSE on failure, array on success. | ||
+ */ | ||
+ public function get_metadata($id) | ||
+ { | ||
+ $stored = $this->_memcached->get($id); | ||
+ | ||
+ if (count($stored) !== 3) | ||
+ { | ||
+ return FALSE; | ||
+ } | ||
+ | ||
+ list($data, $time, $ttl) = $stored; | ||
+ | ||
+ return array( | ||
+ 'expire' => $time + $ttl, | ||
+ 'mtime' => $time, | ||
+ 'data' => $data | ||
+ ); | ||
+ } | ||
+ | ||
+ // ------------------------------------------------------------------------ | ||
+ | ||
+ /** | ||
+ * Is supported | ||
+ * | ||
+ * Returns FALSE if memcached is not supported on the system. | ||
+ * If it is, we setup the memcached object & return TRUE | ||
+ * | ||
+ * @return bool | ||
+ */ | ||
+ public function is_supported() | ||
+ { | ||
+ return (extension_loaded('memcached') OR extension_loaded('memcache')); | ||
+ } | ||
+} |
320
README/Cache/drivers/Cache_redis.php
@@ -0,0 +1,320 @@ | ||
+<?php | ||
+/** | ||
+ * CodeIgniter | ||
+ * | ||
+ * An open source application development framework for PHP | ||
+ * | ||
+ * This content is released under the MIT License (MIT) | ||
+ * | ||
+ * Copyright (c) 2014 - 2015, British Columbia Institute of Technology | ||
+ * | ||
+ * Permission is hereby granted, free of charge, to any person obtaining a copy | ||
+ * of this software and associated documentation files (the "Software"), to deal | ||
+ * in the Software without restriction, including without limitation the rights | ||
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | ||
+ * copies of the Software, and to permit persons to whom the Software is | ||
+ * furnished to do so, subject to the following conditions: | ||
+ * | ||
+ * The above copyright notice and this permission notice shall be included in | ||
+ * all copies or substantial portions of the Software. | ||
+ * | ||
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | ||
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | ||
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN | ||
+ * THE SOFTWARE. | ||
+ * | ||
+ * @package CodeIgniter | ||
+ * @author EllisLab Dev Team | ||
+ * @copyright Copyright (c) 2008 - 2014, EllisLab, Inc. (http://ellislab.com/) | ||
+ * @copyright Copyright (c) 2014 - 2015, British Columbia Institute of Technology (http://bcit.ca/) | ||
+ * @license http://opensource.org/licenses/MIT MIT License | ||
+ * @link http://codeigniter.com | ||
+ * @since Version 3.0.0 | ||
+ * @filesource | ||
+ */ | ||
+defined('BASEPATH') OR exit('No direct script access allowed'); | ||
+ | ||
+/** | ||
+ * CodeIgniter Redis Caching Class | ||
+ * | ||
+ * @package CodeIgniter | ||
+ * @subpackage Libraries | ||
+ * @category Core | ||
+ * @author Anton Lindqvist <anton@qvister.se> | ||
+ * @link | ||
+ */ | ||
+class CI_Cache_redis extends CI_Driver | ||
+{ | ||
+ /** | ||
+ * Default config | ||
+ * | ||
+ * @static | ||
+ * @var array | ||
+ */ | ||
+ protected static $_default_config = array( | ||
+ 'socket_type' => 'tcp', | ||
+ 'host' => '127.0.0.1', | ||
+ 'password' => NULL, | ||
+ 'port' => 6379, | ||
+ 'timeout' => 0 | ||
+ ); | ||
+ | ||
+ /** | ||
+ * Redis connection | ||
+ * | ||
+ * @var Redis | ||
+ */ | ||
+ protected $_redis; | ||
+ | ||
+ /** | ||
+ * An internal cache for storing keys of serialized values. | ||
+ * | ||
+ * @var array | ||
+ */ | ||
+ protected $_serialized = array(); | ||
+ | ||
+ // ------------------------------------------------------------------------ | ||
+ | ||
+ /** | ||
+ * Class constructor | ||
+ * | ||
+ * Setup Redis | ||
+ * | ||
+ * Loads Redis config file if present. Will halt execution | ||
+ * if a Redis connection can't be established. | ||
+ * | ||
+ * @return void | ||
+ * @see Redis::connect() | ||
+ */ | ||
+ public function __construct() | ||
+ { | ||
+ $config = array(); | ||
+ $CI =& get_instance(); | ||
+ | ||
+ if ($CI->config->load('redis', TRUE, TRUE)) | ||
+ { | ||
+ $config = $CI->config->item('redis'); | ||
+ } | ||
+ | ||
+ $config = array_merge(self::$_default_config, $config); | ||
+ $this->_redis = new Redis(); | ||
+ | ||
+ try | ||
+ { | ||
+ if ($config['socket_type'] === 'unix') | ||
+ { | ||
+ $success = $this->_redis->connect($config['socket']); | ||
+ } | ||
+ else // tcp socket | ||
+ { | ||
+ $success = $this->_redis->connect($config['host'], $config['port'], $config['timeout']); | ||
+ } | ||
+ | ||
+ if ( ! $success) | ||
+ { | ||
+ log_message('error', 'Cache: Redis connection failed. Check your configuration.'); | ||
+ } | ||
+ | ||
+ if (isset($config['password']) && ! $this->_redis->auth($config['password'])) | ||
+ { | ||
+ log_message('error', 'Cache: Redis authentication failed.'); | ||
+ } | ||
+ } | ||
+ catch (RedisException $e) | ||
+ { | ||
+ log_message('error', 'Cache: Redis connection refused ('.$e->getMessage().')'); | ||
+ } | ||
+ | ||
+ // Initialize the index of serialized values. | ||
+ $serialized = $this->_redis->sMembers('_ci_redis_serialized'); | ||
+ empty($serialized) OR $this->_serialized = array_flip($serialized); | ||
+ } | ||
+ | ||
+ // ------------------------------------------------------------------------ | ||
+ | ||
+ /** | ||
+ * Get cache | ||
+ * | ||
+ * @param string Cache ID | ||
+ * @return mixed | ||
+ */ | ||
+ public function get($key) | ||
+ { | ||
+ $value = $this->_redis->get($key); | ||
+ | ||
+ if ($value !== FALSE && isset($this->_serialized[$key])) | ||
+ { | ||
+ return unserialize($value); | ||
+ } | ||
+ | ||
+ return $value; | ||
+ } | ||
+ | ||
+ // ------------------------------------------------------------------------ | ||
+ | ||
+ /** | ||
+ * Save cache | ||
+ * | ||
+ * @param string $id Cache ID | ||
+ * @param mixed $data Data to save | ||
+ * @param int $ttl Time to live in seconds | ||
+ * @param bool $raw Whether to store the raw value (unused) | ||
+ * @return bool TRUE on success, FALSE on failure | ||
+ */ | ||
+ public function save($id, $data, $ttl = 60, $raw = FALSE) | ||
+ { | ||
+ if (is_array($data) OR is_object($data)) | ||
+ { | ||
+ if ( ! $this->_redis->sIsMember('_ci_redis_serialized', $id) && ! $this->_redis->sAdd('_ci_redis_serialized', $id)) | ||
+ { | ||
+ return FALSE; | ||
+ } | ||
+ | ||
+ isset($this->_serialized[$id]) OR $this->_serialized[$id] = TRUE; | ||
+ $data = serialize($data); | ||
+ } | ||
+ elseif (isset($this->_serialized[$id])) | ||
+ { | ||
+ $this->_serialized[$id] = NULL; | ||
+ $this->_redis->sRemove('_ci_redis_serialized', $id); | ||
+ } | ||
+ | ||
+ return $this->_redis->set($id, $data, $ttl); | ||
+ } | ||
+ | ||
+ // ------------------------------------------------------------------------ | ||
+ | ||
+ /** | ||
+ * Delete from cache | ||
+ * | ||
+ * @param string Cache key | ||
+ * @return bool | ||
+ */ | ||
+ public function delete($key) | ||
+ { | ||
+ if ($this->_redis->delete($key) !== 1) | ||
+ { | ||
+ return FALSE; | ||
+ } | ||
+ | ||
+ if (isset($this->_serialized[$key])) | ||
+ { | ||
+ $this->_serialized[$key] = NULL; | ||
+ $this->_redis->sRemove('_ci_redis_serialized', $key); | ||
+ } | ||
+ | ||
+ return TRUE; | ||
+ } | ||
+ | ||
+ // ------------------------------------------------------------------------ | ||
+ | ||
+ /** | ||
+ * Increment a raw value | ||
+ * | ||
+ * @param string $id Cache ID | ||
+ * @param int $offset Step/value to add | ||
+ * @return mixed New value on success or FALSE on failure | ||
+ */ | ||
+ public function increment($id, $offset = 1) | ||
+ { | ||
+ return $this->_redis->incr($id, $offset); | ||
+ } | ||
+ | ||
+ // ------------------------------------------------------------------------ | ||
+ | ||
+ /** | ||
+ * Decrement a raw value | ||
+ * | ||
+ * @param string $id Cache ID | ||
+ * @param int $offset Step/value to reduce by | ||
+ * @return mixed New value on success or FALSE on failure | ||
+ */ | ||
+ public function decrement($id, $offset = 1) | ||
+ { | ||
+ return $this->_redis->decr($id, $offset); | ||
+ } | ||
+ | ||
+ // ------------------------------------------------------------------------ | ||
+ | ||
+ /** | ||
+ * Clean cache | ||
+ * | ||
+ * @return bool | ||
+ * @see Redis::flushDB() | ||
+ */ | ||
+ public function clean() | ||
+ { | ||
+ return $this->_redis->flushDB(); | ||
+ } | ||
+ | ||
+ // ------------------------------------------------------------------------ | ||
+ | ||
+ /** | ||
+ * Get cache driver info | ||
+ * | ||
+ * @param string Not supported in Redis. | ||
+ * Only included in order to offer a | ||
+ * consistent cache API. | ||
+ * @return array | ||
+ * @see Redis::info() | ||
+ */ | ||
+ public function cache_info($type = NULL) | ||
+ { | ||
+ return $this->_redis->info(); | ||
+ } | ||
+ | ||
+ // ------------------------------------------------------------------------ | ||
+ | ||
+ /** | ||
+ * Get cache metadata | ||
+ * | ||
+ * @param string Cache key | ||
+ * @return array | ||
+ */ | ||
+ public function get_metadata($key) | ||
+ { | ||
+ $value = $this->get($key); | ||
+ | ||
+ if ($value !== FALSE) | ||
+ { | ||
+ return array( | ||
+ 'expire' => time() + $this->_redis->ttl($key), | ||
+ 'data' => $value | ||
+ ); | ||
+ } | ||
+ | ||
+ return FALSE; | ||
+ } | ||
+ | ||
+ // ------------------------------------------------------------------------ | ||
+ | ||
+ /** | ||
+ * Check if Redis driver is supported | ||
+ * | ||
+ * @return bool | ||
+ */ | ||
+ public function is_supported() | ||
+ { | ||
+ return extension_loaded('redis'); | ||
+ } | ||
+ | ||
+ // ------------------------------------------------------------------------ | ||
+ | ||
+ /** | ||
+ * Class destructor | ||
+ * | ||
+ * Closes the connection to Redis if present. | ||
+ * | ||
+ * @return void | ||
+ */ | ||
+ public function __destruct() | ||
+ { | ||
+ if ($this->_redis) | ||
+ { | ||
+ $this->_redis->close(); | ||
+ } | ||
+ } | ||
+} |
206
README/Cache/drivers/Cache_wincache.php
@@ -0,0 +1,206 @@ | ||
+<?php | ||
+/** | ||
+ * CodeIgniter | ||
+ * | ||
+ * An open source application development framework for PHP | ||
+ * | ||
+ * This content is released under the MIT License (MIT) | ||
+ * | ||
+ * Copyright (c) 2014 - 2015, British Columbia Institute of Technology | ||
+ * | ||
+ * Permission is hereby granted, free of charge, to any person obtaining a copy | ||
+ * of this software and associated documentation files (the "Software"), to deal | ||
+ * in the Software without restriction, including without limitation the rights | ||
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | ||
+ * copies of the Software, and to permit persons to whom the Software is | ||
+ * furnished to do so, subject to the following conditions: | ||
+ * | ||
+ * The above copyright notice and this permission notice shall be included in | ||
+ * all copies or substantial portions of the Software. | ||
+ * | ||
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | ||
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | ||
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN | ||
+ * THE SOFTWARE. | ||
+ * | ||
+ * @package CodeIgniter | ||
+ * @author EllisLab Dev Team | ||
+ * @copyright Copyright (c) 2008 - 2014, EllisLab, Inc. (http://ellislab.com/) | ||
+ * @copyright Copyright (c) 2014 - 2015, British Columbia Institute of Technology (http://bcit.ca/) | ||
+ * @license http://opensource.org/licenses/MIT MIT License | ||
+ * @link http://codeigniter.com | ||
+ * @since Version 3.0.0 | ||
+ * @filesource | ||
+ */ | ||
+defined('BASEPATH') OR exit('No direct script access allowed'); | ||
+ | ||
+/** | ||
+ * CodeIgniter Wincache Caching Class | ||
+ * | ||
+ * Read more about Wincache functions here: | ||
+ * http://www.php.net/manual/en/ref.wincache.php | ||
+ * | ||
+ * @package CodeIgniter | ||
+ * @subpackage Libraries | ||
+ * @category Core | ||
+ * @author Mike Murkovic | ||
+ * @link | ||
+ */ | ||
+class CI_Cache_wincache extends CI_Driver { | ||
+ | ||
+ /** | ||
+ * Get | ||
+ * | ||
+ * Look for a value in the cache. If it exists, return the data, | ||
+ * if not, return FALSE | ||
+ * | ||
+ * @param string $id Cache Ide | ||
+ * @return mixed Value that is stored/FALSE on failure | ||
+ */ | ||
+ public function get($id) | ||
+ { | ||
+ $success = FALSE; | ||
+ $data = wincache_ucache_get($id, $success); | ||
+ | ||
+ // Success returned by reference from wincache_ucache_get() | ||
+ return ($success) ? $data : FALSE; | ||
+ } | ||
+ | ||
+ // ------------------------------------------------------------------------ | ||
+ | ||
+ /** | ||
+ * Cache Save | ||
+ * | ||
+ * @param string $id Cache ID | ||
+ * @param mixed $data Data to store | ||
+ * @param int $ttl Time to live (in seconds) | ||
+ * @param bool $raw Whether to store the raw value (unused) | ||
+ * @return bool true on success/false on failure | ||
+ */ | ||
+ public function save($id, $data, $ttl = 60, $raw = FALSE) | ||
+ { | ||
+ return wincache_ucache_set($id, $data, $ttl); | ||
+ } | ||
+ | ||
+ // ------------------------------------------------------------------------ | ||
+ | ||
+ /** | ||
+ * Delete from Cache | ||
+ * | ||
+ * @param mixed unique identifier of the item in the cache | ||
+ * @return bool true on success/false on failure | ||
+ */ | ||
+ public function delete($id) | ||
+ { | ||
+ return wincache_ucache_delete($id); | ||
+ } | ||
+ | ||
+ // ------------------------------------------------------------------------ | ||
+ | ||
+ /** | ||
+ * Increment a raw value | ||
+ * | ||
+ * @param string $id Cache ID | ||
+ * @param int $offset Step/value to add | ||
+ * @return mixed New value on success or FALSE on failure | ||
+ */ | ||
+ public function increment($id, $offset = 1) | ||
+ { | ||
+ $success = FALSE; | ||
+ $value = wincache_ucache_inc($id, $offset, $success); | ||
+ | ||
+ return ($success === TRUE) ? $value : FALSE; | ||
+ } | ||
+ | ||
+ // ------------------------------------------------------------------------ | ||
+ | ||
+ /** | ||
+ * Decrement a raw value | ||
+ * | ||
+ * @param string $id Cache ID | ||
+ * @param int $offset Step/value to reduce by | ||
+ * @return mixed New value on success or FALSE on failure | ||
+ */ | ||
+ public function decrement($id, $offset = 1) | ||
+ { | ||
+ $success = FALSE; | ||
+ $value = wincache_ucache_dec($id, $offset, $success); | ||
+ | ||
+ return ($success === TRUE) ? $value : FALSE; | ||
+ } | ||
+ | ||
+ // ------------------------------------------------------------------------ | ||
+ | ||
+ /** | ||
+ * Clean the cache | ||
+ * | ||
+ * @return bool false on failure/true on success | ||
+ */ | ||
+ public function clean() | ||
+ { | ||
+ return wincache_ucache_clear(); | ||
+ } | ||
+ | ||
+ // ------------------------------------------------------------------------ | ||
+ | ||
+ /** | ||
+ * Cache Info | ||
+ * | ||
+ * @return mixed array on success, false on failure | ||
+ */ | ||
+ public function cache_info() | ||
+ { | ||
+ return wincache_ucache_info(TRUE); | ||
+ } | ||
+ | ||
+ // ------------------------------------------------------------------------ | ||
+ | ||
+ /** | ||
+ * Get Cache Metadata | ||
+ * | ||
+ * @param mixed key to get cache metadata on | ||
+ * @return mixed array on success/false on failure | ||
+ */ | ||
+ public function get_metadata($id) | ||
+ { | ||
+ if ($stored = wincache_ucache_info(FALSE, $id)) | ||
+ { | ||
+ $age = $stored['ucache_entries'][1]['age_seconds']; | ||
+ $ttl = $stored['ucache_entries'][1]['ttl_seconds']; | ||
+ $hitcount = $stored['ucache_entries'][1]['hitcount']; | ||
+ | ||
+ return array( | ||
+ 'expire' => $ttl - $age, | ||
+ 'hitcount' => $hitcount, | ||
+ 'age' => $age, | ||
+ 'ttl' => $ttl | ||
+ ); | ||
+ } | ||
+ | ||
+ return FALSE; | ||
+ } | ||
+ | ||
+ // ------------------------------------------------------------------------ | ||
+ | ||
+ /** | ||
+ * is_supported() | ||
+ * | ||
+ * Check to see if WinCache is available on this system, bail if it isn't. | ||
+ * | ||
+ * @return bool | ||
+ */ | ||
+ public function is_supported() | ||
+ { | ||
+ if ( ! extension_loaded('wincache') OR ! ini_get('wincache.ucenabled')) | ||
+ { | ||
+ log_message('debug', 'The Wincache PHP extension must be loaded to use Wincache Cache.'); | ||
+ return FALSE; | ||
+ } | ||
+ | ||
+ return TRUE; | ||
+ } | ||
+ | ||
+} |
11
README/Cache/drivers/index.html
@@ -0,0 +1,11 @@ | ||
+<!DOCTYPE html> | ||
+<html> | ||
+<head> | ||
+ <title>403 Forbidden</title> | ||
+</head> | ||
+<body> | ||
+ | ||
+<p>Directory access is forbidden.</p> | ||
+ | ||
+</body> | ||
+</html> |
11
README/Cache/index.html
@@ -0,0 +1,11 @@ | ||
+<!DOCTYPE html> | ||
+<html> | ||
+<head> | ||
+ <title>403 Forbidden</title> | ||
+</head> | ||
+<body> | ||
+ | ||
+<p>Directory access is forbidden.</p> | ||
+ | ||
+</body> | ||
+</html> |
546
README/Calendar.php
@@ -0,0 +1,546 @@ | ||
+<?php | ||
+/** | ||
+ * CodeIgniter | ||
+ * | ||
+ * An open source application development framework for PHP | ||
+ * | ||
+ * This content is released under the MIT License (MIT) | ||
+ * | ||
+ * Copyright (c) 2014 - 2015, British Columbia Institute of Technology | ||
+ * | ||
+ * Permission is hereby granted, free of charge, to any person obtaining a copy | ||
+ * of this software and associated documentation files (the "Software"), to deal | ||
+ * in the Software without restriction, including without limitation the rights | ||
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | ||
+ * copies of the Software, and to permit persons to whom the Software is | ||
+ * furnished to do so, subject to the following conditions: | ||
+ * | ||
+ * The above copyright notice and this permission notice shall be included in | ||
+ * all copies or substantial portions of the Software. | ||
+ * | ||
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | ||
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | ||
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN | ||
+ * THE SOFTWARE. | ||
+ * | ||
+ * @package CodeIgniter | ||
+ * @author EllisLab Dev Team | ||
+ * @copyright Copyright (c) 2008 - 2014, EllisLab, Inc. (http://ellislab.com/) | ||
+ * @copyright Copyright (c) 2014 - 2015, British Columbia Institute of Technology (http://bcit.ca/) | ||
+ * @license http://opensource.org/licenses/MIT MIT License | ||
+ * @link http://codeigniter.com | ||
+ * @since Version 1.0.0 | ||
+ * @filesource | ||
+ */ | ||
+defined('BASEPATH') OR exit('No direct script access allowed'); | ||
+ | ||
+/** | ||
+ * CodeIgniter Calendar Class | ||
+ * | ||
+ * This class enables the creation of calendars | ||
+ * | ||
+ * @package CodeIgniter | ||
+ * @subpackage Libraries | ||
+ * @category Libraries | ||
+ * @author EllisLab Dev Team | ||
+ * @link http://codeigniter.com/user_guide/libraries/calendar.html | ||
+ */ | ||
+class CI_Calendar { | ||
+ | ||
+ /** | ||
+ * Calendar layout template | ||
+ * | ||
+ * @var mixed | ||
+ */ | ||
+ public $template = ''; | ||
+ | ||
+ /** | ||
+ * Replacements array for template | ||
+ * | ||
+ * @var array | ||
+ */ | ||
+ public $replacements = array(); | ||
+ | ||
+ /** | ||
+ * Day of the week to start the calendar on | ||
+ * | ||
+ * @var string | ||
+ */ | ||
+ public $start_day = 'sunday'; | ||
+ | ||
+ /** | ||
+ * How to display months | ||
+ * | ||
+ * @var string | ||
+ */ | ||
+ public $month_type = 'long'; | ||
+ | ||
+ /** | ||
+ * How to display names of days | ||
+ * | ||
+ * @var string | ||
+ */ | ||
+ public $day_type = 'abr'; | ||
+ | ||
+ /** | ||
+ * Whether to show next/prev month links | ||
+ * | ||
+ * @var bool | ||
+ */ | ||
+ public $show_next_prev = FALSE; | ||
+ | ||
+ /** | ||
+ * Url base to use for next/prev month links | ||
+ * | ||
+ * @var bool | ||
+ */ | ||
+ public $next_prev_url = ''; | ||
+ | ||
+ /** | ||
+ * Show days of other months | ||
+ * | ||
+ * @var bool | ||
+ */ | ||
+ public $show_other_days = FALSE; | ||
+ | ||
+ // -------------------------------------------------------------------- | ||
+ | ||
+ /** | ||
+ * CI Singleton | ||
+ * | ||
+ * @var object | ||
+ */ | ||
+ protected $CI; | ||
+ | ||
+ // -------------------------------------------------------------------- | ||
+ | ||
+ /** | ||
+ * Class constructor | ||
+ * | ||
+ * Loads the calendar language file and sets the default time reference. | ||
+ * | ||
+ * @uses CI_Lang::$is_loaded | ||
+ * | ||
+ * @param array $config Calendar options | ||
+ * @return void | ||
+ */ | ||
+ public function __construct($config = array()) | ||
+ { | ||
+ $this->CI =& get_instance(); | ||
+ $this->CI->lang->load('calendar'); | ||
+ | ||
+ empty($config) OR $this->initialize($config); | ||
+ | ||
+ log_message('info', 'Calendar Class Initialized'); | ||
+ } | ||
+ | ||
+ // -------------------------------------------------------------------- | ||
+ | ||
+ /** | ||
+ * Initialize the user preferences | ||
+ * | ||
+ * Accepts an associative array as input, containing display preferences | ||
+ * | ||
+ * @param array config preferences | ||
+ * @return CI_Calendar | ||
+ */ | ||
+ public function initialize($config = array()) | ||
+ { | ||
+ foreach ($config as $key => $val) | ||
+ { | ||
+ if (isset($this->$key)) | ||
+ { | ||
+ $this->$key = $val; | ||
+ } | ||
+ } | ||
+ | ||
+ // Set the next_prev_url to the controller if required but not defined | ||
+ if ($this->show_next_prev === TRUE && empty($this->next_prev_url)) | ||
+ { | ||
+ $this->next_prev_url = $this->CI->config->site_url($this->CI->router->class.'/'.$this->CI->router->method); | ||
+ } | ||
+ | ||
+ return $this; | ||
+ } | ||
+ | ||
+ // -------------------------------------------------------------------- | ||
+ | ||
+ /** | ||
+ * Generate the calendar | ||
+ * | ||
+ * @param int the year | ||
+ * @param int the month | ||
+ * @param array the data to be shown in the calendar cells | ||
+ * @return string | ||
+ */ | ||
+ public function generate($year = '', $month = '', $data = array()) | ||
+ { | ||
+ $local_time = time(); | ||
+ | ||
+ // Set and validate the supplied month/year | ||
+ if (empty($year)) | ||
+ { | ||
+ $year = date('Y', $local_time); | ||
+ } | ||
+ elseif (strlen($year) === 1) | ||
+ { | ||
+ $year = '200'.$year; | ||
+ } | ||
+ elseif (strlen($year) === 2) | ||
+ { | ||
+ $year = '20'.$year; | ||
+ } | ||
+ | ||
+ if (empty($month)) | ||
+ { | ||
+ $month = date('m', $local_time); | ||
+ } | ||
+ elseif (strlen($month) === 1) | ||
+ { | ||
+ $month = '0'.$month; | ||
+ } | ||
+ | ||
+ $adjusted_date = $this->adjust_date($month, $year); | ||
+ | ||
+ $month = $adjusted_date['month']; | ||
+ $year = $adjusted_date['year']; | ||
+ | ||
+ // Determine the total days in the month | ||
+ $total_days = $this->get_total_days($month, $year); | ||
+ | ||
+ // Set the starting day of the week | ||
+ $start_days = array('sunday' => 0, 'monday' => 1, 'tuesday' => 2, 'wednesday' => 3, 'thursday' => 4, 'friday' => 5, 'saturday' => 6); | ||
+ $start_day = isset($start_days[$this->start_day]) ? $start_days[$this->start_day] : 0; | ||
+ | ||
+ // Set the starting day number | ||
+ $local_date = mktime(12, 0, 0, $month, 1, $year); | ||
+ $date = getdate($local_date); | ||
+ $day = $start_day + 1 - $date['wday']; | ||
+ | ||
+ while ($day > 1) | ||
+ { | ||
+ $day -= 7; | ||
+ } | ||
+ | ||
+ // Set the current month/year/day | ||
+ // We use this to determine the "today" date | ||
+ $cur_year = date('Y', $local_time); | ||
+ $cur_month = date('m', $local_time); | ||
+ $cur_day = date('j', $local_time); | ||
+ | ||
+ $is_current_month = ($cur_year == $year && $cur_month == $month); | ||
+ | ||
+ // Generate the template data array | ||
+ $this->parse_template(); | ||
+ | ||
+ // Begin building the calendar output | ||
+ $out = $this->replacements['table_open']."\n\n".$this->replacements['heading_row_start']."\n"; | ||
+ | ||
+ // "previous" month link | ||
+ if ($this->show_next_prev === TRUE) | ||
+ { | ||
+ // Add a trailing slash to the URL if needed | ||
+ $this->next_prev_url = preg_replace('/(.+?)\/*$/', '\\1/', $this->next_prev_url); | ||
+ | ||
+ $adjusted_date = $this->adjust_date($month - 1, $year); | ||
+ $out .= str_replace('{previous_url}', $this->next_prev_url.$adjusted_date['year'].'/'.$adjusted_date['month'], $this->replacements['heading_previous_cell'])."\n"; | ||
+ } | ||
+ | ||
+ // Heading containing the month/year | ||
+ $colspan = ($this->show_next_prev === TRUE) ? 5 : 7; | ||
+ | ||
+ $this->replacements['heading_title_cell'] = str_replace('{colspan}', $colspan, | ||
+ str_replace('{heading}', $this->get_month_name($month).' '.$year, $this->replacements['heading_title_cell'])); | ||
+ | ||
+ $out .= $this->replacements['heading_title_cell']."\n"; | ||
+ | ||
+ // "next" month link | ||
+ if ($this->show_next_prev === TRUE) | ||
+ { | ||
+ $adjusted_date = $this->adjust_date($month + 1, $year); | ||
+ $out .= str_replace('{next_url}', $this->next_prev_url.$adjusted_date['year'].'/'.$adjusted_date['month'], $this->replacements['heading_next_cell']); | ||
+ } | ||
+ | ||
+ $out .= "\n".$this->replacements['heading_row_end']."\n\n" | ||
+ // Write the cells containing the days of the week | ||
+ .$this->replacements['week_row_start']."\n"; | ||
+ | ||
+ $day_names = $this->get_day_names(); | ||
+ | ||
+ for ($i = 0; $i < 7; $i ++) | ||
+ { | ||
+ $out .= str_replace('{week_day}', $day_names[($start_day + $i) %7], $this->replacements['week_day_cell']); | ||
+ } | ||
+ | ||
+ $out .= "\n".$this->replacements['week_row_end']."\n"; | ||
+ | ||
+ // Build the main body of the calendar | ||
+ while ($day <= $total_days) | ||
+ { | ||
+ $out .= "\n".$this->replacements['cal_row_start']."\n"; | ||
+ | ||
+ for ($i = 0; $i < 7; $i++) | ||
+ { | ||
+ if ($day > 0 && $day <= $total_days) | ||
+ { | ||
+ $out .= ($is_current_month === TRUE && $day == $cur_day) ? $this->replacements['cal_cell_start_today'] : $this->replacements['cal_cell_start']; | ||
+ | ||
+ if (isset($data[$day])) | ||
+ { | ||
+ // Cells with content | ||
+ $temp = ($is_current_month === TRUE && $day == $cur_day) ? | ||
+ $this->replacements['cal_cell_content_today'] : $this->replacements['cal_cell_content']; | ||
+ $out .= str_replace(array('{content}', '{day}'), array($data[$day], $day), $temp); | ||
+ } | ||
+ else | ||
+ { | ||
+ // Cells with no content | ||
+ $temp = ($is_current_month === TRUE && $day == $cur_day) ? | ||
+ $this->replacements['cal_cell_no_content_today'] : $this->replacements['cal_cell_no_content']; | ||
+ $out .= str_replace('{day}', $day, $temp); | ||
+ } | ||
+ | ||
+ $out .= ($is_current_month === TRUE && $day == $cur_day) ? $this->replacements['cal_cell_end_today'] : $this->replacements['cal_cell_end']; | ||
+ } | ||
+ elseif ($this->show_other_days === TRUE) | ||
+ { | ||
+ $out .= $this->replacements['cal_cell_start_other']; | ||
+ | ||
+ if ($day <= 0) | ||
+ { | ||
+ // Day of previous month | ||
+ $prev_month = $this->adjust_date($month - 1, $year); | ||
+ $prev_month_days = $this->get_total_days($prev_month['month'], $prev_month['year']); | ||
+ $out .= str_replace('{day}', $prev_month_days + $day, $this->replacements['cal_cell_other']); | ||
+ } | ||
+ else | ||
+ { | ||
+ // Day of next month | ||
+ $out .= str_replace('{day}', $day - $total_days, $this->replacements['cal_cell_other']); | ||
+ } | ||
+ | ||
+ $out .= $this->replacements['cal_cell_end_other']; | ||
+ } | ||
+ else | ||
+ { | ||
+ // Blank cells | ||
+ $out .= $this->replacements['cal_cell_start'].$this->replacements['cal_cell_blank'].$this->replacements['cal_cell_end']; | ||
+ } | ||
+ | ||
+ $day++; | ||
+ } | ||
+ | ||
+ $out .= "\n".$this->replacements['cal_row_end']."\n"; | ||
+ } | ||
+ | ||
+ return $out .= "\n".$this->replacements['table_close']; | ||
+ } | ||
+ | ||
+ // -------------------------------------------------------------------- | ||
+ | ||
+ /** | ||
+ * Get Month Name | ||
+ * | ||
+ * Generates a textual month name based on the numeric | ||
+ * month provided. | ||
+ * | ||
+ * @param int the month | ||
+ * @return string | ||
+ */ | ||
+ public function get_month_name($month) | ||
+ { | ||
+ if ($this->month_type === 'short') | ||
+ { | ||
+ $month_names = array('01' => 'cal_jan', '02' => 'cal_feb', '03' => 'cal_mar', '04' => 'cal_apr', '05' => 'cal_may', '06' => 'cal_jun', '07' => 'cal_jul', '08' => 'cal_aug', '09' => 'cal_sep', '10' => 'cal_oct', '11' => 'cal_nov', '12' => 'cal_dec'); | ||
+ } | ||
+ else | ||
+ { | ||
+ $month_names = array('01' => 'cal_january', '02' => 'cal_february', '03' => 'cal_march', '04' => 'cal_april', '05' => 'cal_mayl', '06' => 'cal_june', '07' => 'cal_july', '08' => 'cal_august', '09' => 'cal_september', '10' => 'cal_october', '11' => 'cal_november', '12' => 'cal_december'); | ||
+ } | ||
+ | ||
+ return ($this->CI->lang->line($month_names[$month]) === FALSE) | ||
+ ? ucfirst(substr($month_names[$month], 4)) | ||
+ : $this->CI->lang->line($month_names[$month]); | ||
+ } | ||
+ | ||
+ // -------------------------------------------------------------------- | ||
+ | ||
+ /** | ||
+ * Get Day Names | ||
+ * | ||
+ * Returns an array of day names (Sunday, Monday, etc.) based | ||
+ * on the type. Options: long, short, abr | ||
+ * | ||
+ * @param string | ||
+ * @return array | ||
+ */ | ||
+ public function get_day_names($day_type = '') | ||
+ { | ||
+ if ($day_type !== '') | ||
+ { | ||
+ $this->day_type = $day_type; | ||
+ } | ||
+ | ||
+ if ($this->day_type === 'long') | ||
+ { | ||
+ $day_names = array('sunday', 'monday', 'tuesday', 'wednesday', 'thursday', 'friday', 'saturday'); | ||
+ } | ||
+ elseif ($this->day_type === 'short') | ||
+ { | ||
+ $day_names = array('sun', 'mon', 'tue', 'wed', 'thu', 'fri', 'sat'); | ||
+ } | ||
+ else | ||
+ { | ||
+ $day_names = array('su', 'mo', 'tu', 'we', 'th', 'fr', 'sa'); | ||
+ } | ||
+ | ||
+ $days = array(); | ||
+ for ($i = 0, $c = count($day_names); $i < $c; $i++) | ||
+ { | ||
+ $days[] = ($this->CI->lang->line('cal_'.$day_names[$i]) === FALSE) ? ucfirst($day_names[$i]) : $this->CI->lang->line('cal_'.$day_names[$i]); | ||
+ } | ||
+ | ||
+ return $days; | ||
+ } | ||
+ | ||
+ // -------------------------------------------------------------------- | ||
+ | ||
+ /** | ||
+ * Adjust Date | ||
+ * | ||
+ * This function makes sure that we have a valid month/year. | ||
+ * For example, if you submit 13 as the month, the year will | ||
+ * increment and the month will become January. | ||
+ * | ||
+ * @param int the month | ||
+ * @param int the year | ||
+ * @return array | ||
+ */ | ||
+ public function adjust_date($month, $year) | ||
+ { | ||
+ $date = array(); | ||
+ | ||
+ $date['month'] = $month; | ||
+ $date['year'] = $year; | ||
+ | ||
+ while ($date['month'] > 12) | ||
+ { | ||
+ $date['month'] -= 12; | ||
+ $date['year']++; | ||
+ } | ||
+ | ||
+ while ($date['month'] <= 0) | ||
+ { | ||
+ $date['month'] += 12; | ||
+ $date['year']--; | ||
+ } | ||
+ | ||
+ if (strlen($date['month']) === 1) | ||
+ { | ||
+ $date['month'] = '0'.$date['month']; | ||
+ } | ||
+ | ||
+ return $date; | ||
+ } | ||
+ | ||
+ // -------------------------------------------------------------------- | ||
+ | ||
+ /** | ||
+ * Total days in a given month | ||
+ * | ||
+ * @param int the month | ||
+ * @param int the year | ||
+ * @return int | ||
+ */ | ||
+ public function get_total_days($month, $year) | ||
+ { | ||
+ $this->CI->load->helper('date'); | ||
+ return days_in_month($month, $year); | ||
+ } | ||
+ | ||
+ // -------------------------------------------------------------------- | ||
+ | ||
+ /** | ||
+ * Set Default Template Data | ||
+ * | ||
+ * This is used in the event that the user has not created their own template | ||
+ * | ||
+ * @return array | ||
+ */ | ||
+ public function default_template() | ||
+ { | ||
+ return array( | ||
+ 'table_open' => '<table border="0" cellpadding="4" cellspacing="0">', | ||
+ 'heading_row_start' => '<tr>', | ||
+ 'heading_previous_cell' => '<th><a href="{previous_url}"><<</a></th>', | ||
+ 'heading_title_cell' => '<th colspan="{colspan}">{heading}</th>', | ||
+ 'heading_next_cell' => '<th><a href="{next_url}">>></a></th>', | ||
+ 'heading_row_end' => '</tr>', | ||
+ 'week_row_start' => '<tr>', | ||
+ 'week_day_cell' => '<td>{week_day}</td>', | ||
+ 'week_row_end' => '</tr>', | ||
+ 'cal_row_start' => '<tr>', | ||
+ 'cal_cell_start' => '<td>', | ||
+ 'cal_cell_start_today' => '<td>', | ||
+ 'cal_cell_start_other' => '<td style="color: #666;">', | ||
+ 'cal_cell_content' => '<a href="{content}">{day}</a>', | ||
+ 'cal_cell_content_today' => '<a href="{content}"><strong>{day}</strong></a>', | ||
+ 'cal_cell_no_content' => '{day}', | ||
+ 'cal_cell_no_content_today' => '<strong>{day}</strong>', | ||
+ 'cal_cell_blank' => ' ', | ||
+ 'cal_cell_other' => '{day}', | ||
+ 'cal_cell_end' => '</td>', | ||
+ 'cal_cell_end_today' => '</td>', | ||
+ 'cal_cell_end_other' => '</td>', | ||
+ 'cal_row_end' => '</tr>', | ||
+ 'table_close' => '</table>' | ||
+ ); | ||
+ } | ||
+ | ||
+ // -------------------------------------------------------------------- | ||
+ | ||
+ /** | ||
+ * Parse Template | ||
+ * | ||
+ * Harvests the data within the template {pseudo-variables} | ||
+ * used to display the calendar | ||
+ * | ||
+ * @return CI_Calendar | ||
+ */ | ||
+ public function parse_template() | ||
+ { | ||
+ $this->replacements = $this->default_template(); | ||
+ | ||
+ if (empty($this->template)) | ||
+ { | ||
+ return $this; | ||
+ } | ||
+ | ||
+ if (is_string($this->template)) | ||
+ { | ||
+ $today = array('cal_cell_start_today', 'cal_cell_content_today', 'cal_cell_no_content_today', 'cal_cell_end_today'); | ||
+ | ||
+ foreach (array('table_open', 'table_close', 'heading_row_start', 'heading_previous_cell', 'heading_title_cell', 'heading_next_cell', 'heading_row_end', 'week_row_start', 'week_day_cell', 'week_row_end', 'cal_row_start', 'cal_cell_start', 'cal_cell_content', 'cal_cell_no_content', 'cal_cell_blank', 'cal_cell_end', 'cal_row_end', 'cal_cell_start_today', 'cal_cell_content_today', 'cal_cell_no_content_today', 'cal_cell_end_today', 'cal_cell_start_other', 'cal_cell_other', 'cal_cell_end_other') as $val) | ||
+ { | ||
+ if (preg_match('/\{'.$val.'\}(.*?)\{\/'.$val.'\}/si', $this->template, $match)) | ||
+ { | ||
+ $this->replacements[$val] = $match[1]; | ||
+ } | ||
+ elseif (in_array($val, $today, TRUE)) | ||
+ { | ||
+ $this->replacements[$val] = $this->replacements[substr($val, 0, -6)]; | ||
+ } | ||
+ } | ||
+ } | ||
+ elseif (is_array($this->template)) | ||
+ { | ||
+ $this->replacements = array_merge($this->replacements, $this->template); | ||
+ } | ||
+ | ||
+ return $this; | ||
+ } | ||
+ | ||
+} |
567
README/Cart.php
@@ -0,0 +1,567 @@ | ||
+<?php | ||
+/** | ||
+ * CodeIgniter | ||
+ * | ||
+ * An open source application development framework for PHP | ||
+ * | ||
+ * This content is released under the MIT License (MIT) | ||
+ * | ||
+ * Copyright (c) 2014 - 2015, British Columbia Institute of Technology | ||
+ * | ||
+ * Permission is hereby granted, free of charge, to any person obtaining a copy | ||
+ * of this software and associated documentation files (the "Software"), to deal | ||
+ * in the Software without restriction, including without limitation the rights | ||
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | ||
+ * copies of the Software, and to permit persons to whom the Software is | ||
+ * furnished to do so, subject to the following conditions: | ||
+ * | ||
+ * The above copyright notice and this permission notice shall be included in | ||
+ * all copies or substantial portions of the Software. | ||
+ * | ||
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | ||
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | ||
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN | ||
+ * THE SOFTWARE. | ||
+ * | ||
+ * @package CodeIgniter | ||
+ * @author EllisLab Dev Team | ||
+ * @copyright Copyright (c) 2008 - 2014, EllisLab, Inc. (http://ellislab.com/) | ||
+ * @copyright Copyright (c) 2014 - 2015, British Columbia Institute of Technology (http://bcit.ca/) | ||
+ * @license http://opensource.org/licenses/MIT MIT License | ||
+ * @link http://codeigniter.com | ||
+ * @since Version 1.0.0 | ||
+ * @filesource | ||
+ */ | ||
+defined('BASEPATH') OR exit('No direct script access allowed'); | ||
+ | ||
+/** | ||
+ * Shopping Cart Class | ||
+ * | ||
+ * @package CodeIgniter | ||
+ * @subpackage Libraries | ||
+ * @category Shopping Cart | ||
+ * @author EllisLab Dev Team | ||
+ * @link http://codeigniter.com/user_guide/libraries/cart.html | ||
+ * @deprecated 3.0.0 This class is too specific for CI. | ||
+ */ | ||
+class CI_Cart { | ||
+ | ||
+ /** | ||
+ * These are the regular expression rules that we use to validate the product ID and product name | ||
+ * alpha-numeric, dashes, underscores, or periods | ||
+ * | ||
+ * @var string | ||
+ */ | ||
+ public $product_id_rules = '\.a-z0-9_-'; | ||
+ | ||
+ /** | ||
+ * These are the regular expression rules that we use to validate the product ID and product name | ||
+ * alpha-numeric, dashes, underscores, colons or periods | ||
+ * | ||
+ * @var string | ||
+ */ | ||
+ public $product_name_rules = '\w \-\.\:'; | ||
+ | ||
+ /** | ||
+ * only allow safe product names | ||
+ * | ||
+ * @var bool | ||
+ */ | ||
+ public $product_name_safe = TRUE; | ||
+ | ||
+ // -------------------------------------------------------------------------- | ||
+ | ||
+ /** | ||
+ * Reference to CodeIgniter instance | ||
+ * | ||
+ * @var object | ||
+ */ | ||
+ protected $CI; | ||
+ | ||
+ /** | ||
+ * Contents of the cart | ||
+ * | ||
+ * @var array | ||
+ */ | ||
+ protected $_cart_contents = array(); | ||
+ | ||
+ /** | ||
+ * Shopping Class Constructor | ||
+ * | ||
+ * The constructor loads the Session class, used to store the shopping cart contents. | ||
+ * | ||
+ * @param array | ||
+ * @return void | ||
+ */ | ||
+ public function __construct($params = array()) | ||
+ { | ||
+ // Set the super object to a local variable for use later | ||
+ $this->CI =& get_instance(); | ||
+ | ||
+ // Are any config settings being passed manually? If so, set them | ||
+ $config = is_array($params) ? $params : array(); | ||
+ | ||
+ // Load the Sessions class | ||
+ $this->CI->load->driver('session', $config); | ||
+ | ||
+ // Grab the shopping cart array from the session table | ||
+ $this->_cart_contents = $this->CI->session->userdata('cart_contents'); | ||
+ if ($this->_cart_contents === NULL) | ||
+ { | ||
+ // No cart exists so we'll set some base values | ||
+ $this->_cart_contents = array('cart_total' => 0, 'total_items' => 0); | ||
+ } | ||
+ | ||
+ log_message('info', 'Cart Class Initialized'); | ||
+ } | ||
+ | ||
+ // -------------------------------------------------------------------- | ||
+ | ||
+ /** | ||
+ * Insert items into the cart and save it to the session table | ||
+ * | ||
+ * @param array | ||
+ * @return bool | ||
+ */ | ||
+ public function insert($items = array()) | ||
+ { | ||
+ // Was any cart data passed? No? Bah... | ||
+ if ( ! is_array($items) OR count($items) === 0) | ||
+ { | ||
+ log_message('error', 'The insert method must be passed an array containing data.'); | ||
+ return FALSE; | ||
+ } | ||
+ | ||
+ // You can either insert a single product using a one-dimensional array, | ||
+ // or multiple products using a multi-dimensional one. The way we | ||
+ // determine the array type is by looking for a required array key named "id" | ||
+ // at the top level. If it's not found, we will assume it's a multi-dimensional array. | ||
+ | ||
+ $save_cart = FALSE; | ||
+ if (isset($items['id'])) | ||
+ { | ||
+ if (($rowid = $this->_insert($items))) | ||
+ { | ||
+ $save_cart = TRUE; | ||
+ } | ||
+ } | ||
+ else | ||
+ { | ||
+ foreach ($items as $val) | ||
+ { | ||
+ if (is_array($val) && isset($val['id'])) | ||
+ { | ||
+ if ($this->_insert($val)) | ||
+ { | ||
+ $save_cart = TRUE; | ||
+ } | ||
+ } | ||
+ } | ||
+ } | ||
+ | ||
+ // Save the cart data if the insert was successful | ||
+ if ($save_cart === TRUE) | ||
+ { | ||
+ $this->_save_cart(); | ||
+ return isset($rowid) ? $rowid : TRUE; | ||
+ } | ||
+ | ||
+ return FALSE; | ||
+ } | ||
+ | ||
+ // -------------------------------------------------------------------- | ||
+ | ||
+ /** | ||
+ * Insert | ||
+ * | ||
+ * @param array | ||
+ * @return bool | ||
+ */ | ||
+ protected function _insert($items = array()) | ||
+ { | ||
+ // Was any cart data passed? No? Bah... | ||
+ if ( ! is_array($items) OR count($items) === 0) | ||
+ { | ||
+ log_message('error', 'The insert method must be passed an array containing data.'); | ||
+ return FALSE; | ||
+ } | ||
+ | ||
+ // -------------------------------------------------------------------- | ||
+ | ||
+ // Does the $items array contain an id, quantity, price, and name? These are required | ||
+ if ( ! isset($items['id'], $items['qty'], $items['price'], $items['name'])) | ||
+ { | ||
+ log_message('error', 'The cart array must contain a product ID, quantity, price, and name.'); | ||
+ return FALSE; | ||
+ } | ||
+ | ||
+ // -------------------------------------------------------------------- | ||
+ | ||
+ // Prep the quantity. It can only be a number. Duh... also trim any leading zeros | ||
+ $items['qty'] = (float) $items['qty']; | ||
+ | ||
+ // If the quantity is zero or blank there's nothing for us to do | ||
+ if ($items['qty'] == 0) | ||
+ { | ||
+ return FALSE; | ||
+ } | ||
+ | ||
+ // -------------------------------------------------------------------- | ||
+ | ||
+ // Validate the product ID. It can only be alpha-numeric, dashes, underscores or periods | ||
+ // Not totally sure we should impose this rule, but it seems prudent to standardize IDs. | ||
+ // Note: These can be user-specified by setting the $this->product_id_rules variable. | ||
+ if ( ! preg_match('/^['.$this->product_id_rules.']+$/i', $items['id'])) | ||
+ { | ||
+ log_message('error', 'Invalid product ID. The product ID can only contain alpha-numeric characters, dashes, and underscores'); | ||
+ return FALSE; | ||
+ } | ||
+ | ||
+ // -------------------------------------------------------------------- | ||
+ | ||
+ // Validate the product name. It can only be alpha-numeric, dashes, underscores, colons or periods. | ||
+ // Note: These can be user-specified by setting the $this->product_name_rules variable. | ||
+ if ($this->product_name_safe && ! preg_match('/^['.$this->product_name_rules.']+$/i'.(UTF8_ENABLED ? 'u' : ''), $items['name'])) | ||
+ { | ||
+ log_message('error', 'An invalid name was submitted as the product name: '.$items['name'].' The name can only contain alpha-numeric characters, dashes, underscores, colons, and spaces'); | ||
+ return FALSE; | ||
+ } | ||
+ | ||
+ // -------------------------------------------------------------------- | ||
+ | ||
+ // Prep the price. Remove leading zeros and anything that isn't a number or decimal point. | ||
+ $items['price'] = (float) $items['price']; | ||
+ | ||
+ // 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 | ||
+ // a particular product, but makes it possible to store identical products with different options. | ||
+ // For example, what if someone buys two identical t-shirts (same product ID), but in | ||
+ // different sizes? The product ID (and other attributes, like the name) will be identical for | ||
+ // both sizes because it's the same shirt. The only difference will be the size. | ||
+ // Internally, we need to treat identical submissions, but with different options, as a unique product. | ||
+ // Our solution is to convert the options array to a string and MD5 it along with the product ID. | ||
+ // This becomes the unique "row ID" | ||
+ if (isset($items['options']) && count($items['options']) > 0) | ||
+ { | ||
+ $rowid = md5($items['id'].serialize($items['options'])); | ||
+ } | ||
+ else | ||
+ { | ||
+ // No options were submitted so we simply MD5 the product ID. | ||
+ // Technically, we don't need to MD5 the ID in this case, but it makes | ||
+ // sense to standardize the format of array indexes for both conditions | ||
+ $rowid = md5($items['id']); | ||
+ } | ||
+ | ||
+ // -------------------------------------------------------------------- | ||
+ | ||
+ // Now that we have our unique "row ID", we'll add our cart items to the master array | ||
+ // grab quantity if it's already there and add it on | ||
+ $old_quantity = isset($this->_cart_contents[$rowid]['qty']) ? (int) $this->_cart_contents[$rowid]['qty'] : 0; | ||
+ | ||
+ // Re-create the entry, just to make sure our index contains only the data from this submission | ||
+ $items['rowid'] = $rowid; | ||
+ $items['qty'] += $old_quantity; | ||
+ $this->_cart_contents[$rowid] = $items; | ||
+ | ||
+ return $rowid; | ||
+ } | ||
+ | ||
+ // -------------------------------------------------------------------- | ||
+ | ||
+ /** | ||
+ * Update the cart | ||
+ * | ||
+ * This function permits the quantity of a given item to be changed. | ||
+ * Typically it is called from the "view cart" page if a user makes | ||
+ * changes to the quantity before checkout. That array must contain the | ||
+ * product ID and quantity for each item. | ||
+ * | ||
+ * @param array | ||
+ * @return bool | ||
+ */ | ||
+ public function update($items = array()) | ||
+ { | ||
+ // Was any cart data passed? | ||
+ if ( ! is_array($items) OR count($items) === 0) | ||
+ { | ||
+ return FALSE; | ||
+ } | ||
+ | ||
+ // You can either update a single product using a one-dimensional array, | ||
+ // or multiple products using a multi-dimensional one. The way we | ||
+ // determine the array type is by looking for a required array key named "rowid". | ||
+ // If it's not found we assume it's a multi-dimensional array | ||
+ $save_cart = FALSE; | ||
+ if (isset($items['rowid'])) | ||
+ { | ||
+ if ($this->_update($items) === TRUE) | ||
+ { | ||
+ $save_cart = TRUE; | ||
+ } | ||
+ } | ||
+ else | ||
+ { | ||
+ foreach ($items as $val) | ||
+ { | ||
+ if (is_array($val) && isset($val['rowid'])) | ||
+ { | ||
+ if ($this->_update($val) === TRUE) | ||
+ { | ||
+ $save_cart = TRUE; | ||
+ } | ||
+ } | ||
+ } | ||
+ } | ||
+ | ||
+ // Save the cart data if the insert was successful | ||
+ if ($save_cart === TRUE) | ||
+ { | ||
+ $this->_save_cart(); | ||
+ return TRUE; | ||
+ } | ||
+ | ||
+ return FALSE; | ||
+ } | ||
+ | ||
+ // -------------------------------------------------------------------- | ||
+ | ||
+ /** | ||
+ * Update the cart | ||
+ * | ||
+ * This function permits changing item properties. | ||
+ * Typically it is called from the "view cart" page if a user makes | ||
+ * changes to the quantity before checkout. That array must contain the | ||
+ * rowid and quantity for each item. | ||
+ * | ||
+ * @param array | ||
+ * @return bool | ||
+ */ | ||
+ protected function _update($items = array()) | ||
+ { | ||
+ // Without these array indexes there is nothing we can do | ||
+ if ( ! isset($items['rowid'], $this->_cart_contents[$items['rowid']])) | ||
+ { | ||
+ return FALSE; | ||
+ } | ||
+ | ||
+ // Prep the quantity | ||
+ if (isset($items['qty'])) | ||
+ { | ||
+ $items['qty'] = (float) $items['qty']; | ||
+ // 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) | ||
+ { | ||
+ unset($this->_cart_contents[$items['rowid']]); | ||
+ return TRUE; | ||
+ } | ||
+ } | ||
+ | ||
+ // find updatable keys | ||
+ $keys = array_intersect(array_keys($this->_cart_contents[$items['rowid']]), array_keys($items)); | ||
+ // if a price was passed, make sure it contains valid data | ||
+ if (isset($items['price'])) | ||
+ { | ||
+ $items['price'] = (float) $items['price']; | ||
+ } | ||
+ | ||
+ // product id & name shouldn't be changed | ||
+ foreach (array_diff($keys, array('id', 'name')) as $key) | ||
+ { | ||
+ $this->_cart_contents[$items['rowid']][$key] = $items[$key]; | ||
+ } | ||
+ | ||
+ return TRUE; | ||
+ } | ||
+ | ||
+ // -------------------------------------------------------------------- | ||
+ | ||
+ /** | ||
+ * Save the cart array to the session DB | ||
+ * | ||
+ * @return bool | ||
+ */ | ||
+ protected function _save_cart() | ||
+ { | ||
+ // Let's add up the individual prices and set the cart sub-total | ||
+ $this->_cart_contents['total_items'] = $this->_cart_contents['cart_total'] = 0; | ||
+ foreach ($this->_cart_contents as $key => $val) | ||
+ { | ||
+ // We make sure the array contains the proper indexes | ||
+ if ( ! is_array($val) OR ! isset($val['price'], $val['qty'])) | ||
+ { | ||
+ continue; | ||
+ } | ||
+ | ||
+ $this->_cart_contents['cart_total'] += ($val['price'] * $val['qty']); | ||
+ $this->_cart_contents['total_items'] += $val['qty']; | ||
+ $this->_cart_contents[$key]['subtotal'] = ($this->_cart_contents[$key]['price'] * $this->_cart_contents[$key]['qty']); | ||
+ } | ||
+ | ||
+ // Is our cart empty? If so we delete it from the session | ||
+ if (count($this->_cart_contents) <= 2) | ||
+ { | ||
+ $this->CI->session->unset_userdata('cart_contents'); | ||
+ | ||
+ // Nothing more to do... coffee time! | ||
+ return FALSE; | ||
+ } | ||
+ | ||
+ // If we made it this far it means that our cart has data. | ||
+ // Let's pass it to the Session class so it can be stored | ||
+ $this->CI->session->set_userdata(array('cart_contents' => $this->_cart_contents)); | ||
+ | ||
+ // Woot! | ||
+ return TRUE; | ||
+ } | ||
+ | ||
+ // -------------------------------------------------------------------- | ||
+ | ||
+ /** | ||
+ * Cart Total | ||
+ * | ||
+ * @return int | ||
+ */ | ||
+ public function total() | ||
+ { | ||
+ return $this->_cart_contents['cart_total']; | ||
+ } | ||
+ | ||
+ // -------------------------------------------------------------------- | ||
+ | ||
+ /** | ||
+ * Remove Item | ||
+ * | ||
+ * Removes an item from the cart | ||
+ * | ||
+ * @param int | ||
+ * @return bool | ||
+ */ | ||
+ public function remove($rowid) | ||
+ { | ||
+ // unset & save | ||
+ unset($this->_cart_contents[$rowid]); | ||
+ $this->_save_cart(); | ||
+ return TRUE; | ||
+ } | ||
+ | ||
+ // -------------------------------------------------------------------- | ||
+ | ||
+ /** | ||
+ * Total Items | ||
+ * | ||
+ * Returns the total item count | ||
+ * | ||
+ * @return int | ||
+ */ | ||
+ public function total_items() | ||
+ { | ||
+ return $this->_cart_contents['total_items']; | ||
+ } | ||
+ | ||
+ // -------------------------------------------------------------------- | ||
+ | ||
+ /** | ||
+ * Cart Contents | ||
+ * | ||
+ * Returns the entire cart array | ||
+ * | ||
+ * @param bool | ||
+ * @return array | ||
+ */ | ||
+ public function contents($newest_first = FALSE) | ||
+ { | ||
+ // do we want the newest first? | ||
+ $cart = ($newest_first) ? array_reverse($this->_cart_contents) : $this->_cart_contents; | ||
+ | ||
+ // Remove these so they don't create a problem when showing the cart table | ||
+ unset($cart['total_items']); | ||
+ unset($cart['cart_total']); | ||
+ | ||
+ return $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 string $row_id = '' | ||
+ * @return bool | ||
+ */ | ||
+ public function has_options($row_id = '') | ||
+ { | ||
+ return (isset($this->_cart_contents[$row_id]['options']) && count($this->_cart_contents[$row_id]['options']) !== 0); | ||
+ } | ||
+ | ||
+ // -------------------------------------------------------------------- | ||
+ | ||
+ /** | ||
+ * Product options | ||
+ * | ||
+ * Returns the an array of options, for a particular product row ID | ||
+ * | ||
+ * @param string $row_id = '' | ||
+ * @return array | ||
+ */ | ||
+ public function product_options($row_id = '') | ||
+ { | ||
+ return isset($this->_cart_contents[$row_id]['options']) ? $this->_cart_contents[$row_id]['options'] : array(); | ||
+ } | ||
+ | ||
+ // -------------------------------------------------------------------- | ||
+ | ||
+ /** | ||
+ * Format Number | ||
+ * | ||
+ * Returns the supplied number with commas and a decimal point. | ||
+ * | ||
+ * @param float | ||
+ * @return string | ||
+ */ | ||
+ public function format_number($n = '') | ||
+ { | ||
+ return ($n === '') ? '' : number_format( (float) $n, 2, '.', ','); | ||
+ } | ||
+ | ||
+ // -------------------------------------------------------------------- | ||
+ | ||
+ /** | ||
+ * Destroy the cart | ||
+ * | ||
+ * Empties the cart and kills the session | ||
+ * | ||
+ * @return void | ||
+ */ | ||
+ public function destroy() | ||
+ { | ||
+ $this->_cart_contents = array('cart_total' => 0, 'total_items' => 0); | ||
+ $this->CI->session->unset_userdata('cart_contents'); | ||
+ } | ||
+ | ||
+} |
342
README/Driver.php
@@ -0,0 +1,342 @@ | ||
+<?php | ||
+/** | ||
+ * CodeIgniter | ||
+ * | ||
+ * An open source application development framework for PHP | ||
+ * | ||
+ * This content is released under the MIT License (MIT) | ||
+ * | ||
+ * Copyright (c) 2014 - 2015, British Columbia Institute of Technology | ||
+ * | ||
+ * Permission is hereby granted, free of charge, to any person obtaining a copy | ||
+ * of this software and associated documentation files (the "Software"), to deal | ||
+ * in the Software without restriction, including without limitation the rights | ||
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | ||
+ * copies of the Software, and to permit persons to whom the Software is | ||
+ * furnished to do so, subject to the following conditions: | ||
+ * | ||
+ * The above copyright notice and this permission notice shall be included in | ||
+ * all copies or substantial portions of the Software. | ||
+ * | ||
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | ||
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | ||
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN | ||
+ * THE SOFTWARE. | ||
+ * | ||
+ * @package CodeIgniter | ||
+ * @author EllisLab Dev Team | ||
+ * @copyright Copyright (c) 2008 - 2014, EllisLab, Inc. (http://ellislab.com/) | ||
+ * @copyright Copyright (c) 2014 - 2015, British Columbia Institute of Technology (http://bcit.ca/) | ||
+ * @license http://opensource.org/licenses/MIT MIT License | ||
+ * @link http://codeigniter.com | ||
+ * @since Version 1.0.0 | ||
+ * @filesource | ||
+ */ | ||
+defined('BASEPATH') OR exit('No direct script access allowed'); | ||
+ | ||
+/** | ||
+ * CodeIgniter Driver Library Class | ||
+ * | ||
+ * This class enables you to create "Driver" libraries that add runtime ability | ||
+ * to extend the capabilities of a class via additional driver objects | ||
+ * | ||
+ * @package CodeIgniter | ||
+ * @subpackage Libraries | ||
+ * @category Libraries | ||
+ * @author EllisLab Dev Team | ||
+ * @link | ||
+ */ | ||
+class CI_Driver_Library { | ||
+ | ||
+ /** | ||
+ * Array of drivers that are available to use with the driver class | ||
+ * | ||
+ * @var array | ||
+ */ | ||
+ protected $valid_drivers = array(); | ||
+ | ||
+ /** | ||
+ * Name of the current class - usually the driver class | ||
+ * | ||
+ * @var string | ||
+ */ | ||
+ 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 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 Driver name (w/o parent prefix) | ||
+ * @return object Child class | ||
+ */ | ||
+ public function load_driver($child) | ||
+ { | ||
+ // Get CodeIgniter instance and subclass prefix | ||
+ $prefix = config_item('subclass_prefix'); | ||
+ | ||
+ if ( ! isset($this->lib_name)) | ||
+ { | ||
+ // Get library name without any prefix | ||
+ $this->lib_name = str_replace(array('CI_', $prefix), '', get_class($this)); | ||
+ } | ||
+ | ||
+ // The child will be prefixed with the parent lib | ||
+ $child_name = $this->lib_name.'_'.$child; | ||
+ | ||
+ // See if requested child is a valid driver | ||
+ if ( ! in_array($child, $this->valid_drivers)) | ||
+ { | ||
+ // The requested driver isn't valid! | ||
+ $msg = 'Invalid driver requested: '.$child_name; | ||
+ log_message('error', $msg); | ||
+ show_error($msg); | ||
+ } | ||
+ | ||
+ // Get package paths and filename case variations to search | ||
+ $CI = get_instance(); | ||
+ $paths = $CI->load->get_package_paths(TRUE); | ||
+ | ||
+ // Is there an extension? | ||
+ $class_name = $prefix.$child_name; | ||
+ $found = class_exists($class_name, FALSE); | ||
+ if ( ! $found) | ||
+ { | ||
+ // Check for subclass file | ||
+ foreach ($paths as $path) | ||
+ { | ||
+ // Does the file exist? | ||
+ $file = $path.'libraries/'.$this->lib_name.'/drivers/'.$prefix.$child_name.'.php'; | ||
+ if (file_exists($file)) | ||
+ { | ||
+ // Yes - require base class from BASEPATH | ||
+ $basepath = BASEPATH.'libraries/'.$this->lib_name.'/drivers/'.$child_name.'.php'; | ||
+ if ( ! file_exists($basepath)) | ||
+ { | ||
+ $msg = 'Unable to load the requested class: CI_'.$child_name; | ||
+ log_message('error', $msg); | ||
+ show_error($msg); | ||
+ } | ||
+ | ||
+ // Include both sources and mark found | ||
+ include_once($basepath); | ||
+ include_once($file); | ||
+ $found = TRUE; | ||
+ break; | ||
+ } | ||
+ } | ||
+ } | ||
+ | ||
+ // Do we need to search for the class? | ||
+ if ( ! $found) | ||
+ { | ||
+ // Use standard class name | ||
+ $class_name = 'CI_'.$child_name; | ||
+ if ( ! class_exists($class_name, FALSE)) | ||
+ { | ||
+ // Check package paths | ||
+ foreach ($paths as $path) | ||
+ { | ||
+ // Does the file exist? | ||
+ $file = $path.'libraries/'.$this->lib_name.'/drivers/'.$child_name.'.php'; | ||
+ if (file_exists($file)) | ||
+ { | ||
+ // Include source | ||
+ include_once($file); | ||
+ break; | ||
+ } | ||
+ } | ||
+ } | ||
+ } | ||
+ | ||
+ // Did we finally find the class? | ||
+ if ( ! class_exists($class_name, FALSE)) | ||
+ { | ||
+ if (class_exists($child_name, FALSE)) | ||
+ { | ||
+ $class_name = $child_name; | ||
+ } | ||
+ else | ||
+ { | ||
+ $msg = 'Unable to load the requested driver: '.$class_name; | ||
+ log_message('error', $msg); | ||
+ show_error($msg); | ||
+ } | ||
+ } | ||
+ | ||
+ // Instantiate, decorate and add child | ||
+ $obj = new $class_name(); | ||
+ $obj->decorate($this); | ||
+ $this->$child = $obj; | ||
+ return $this->$child; | ||
+ } | ||
+ | ||
+} | ||
+ | ||
+// -------------------------------------------------------------------------- | ||
+ | ||
+/** | ||
+ * CodeIgniter Driver Class | ||
+ * | ||
+ * This class enables you to create drivers for a Library based on the Driver Library. | ||
+ * It handles the drivers' access to the parent library | ||
+ * | ||
+ * @package CodeIgniter | ||
+ * @subpackage Libraries | ||
+ * @category Libraries | ||
+ * @author EllisLab Dev Team | ||
+ * @link | ||
+ */ | ||
+class CI_Driver { | ||
+ | ||
+ /** | ||
+ * Instance of the parent class | ||
+ * | ||
+ * @var object | ||
+ */ | ||
+ protected $_parent; | ||
+ | ||
+ /** | ||
+ * List of methods in the parent class | ||
+ * | ||
+ * @var array | ||
+ */ | ||
+ protected $_methods = array(); | ||
+ | ||
+ /** | ||
+ * List of properties in the parent class | ||
+ * | ||
+ * @var array | ||
+ */ | ||
+ protected $_properties = array(); | ||
+ | ||
+ /** | ||
+ * Array of methods and properties for the parent class(es) | ||
+ * | ||
+ * @static | ||
+ * @var array | ||
+ */ | ||
+ protected static $_reflections = array(); | ||
+ | ||
+ /** | ||
+ * Decorate | ||
+ * | ||
+ * Decorates the child with the parent driver lib's methods and properties | ||
+ * | ||
+ * @param object | ||
+ * @return void | ||
+ */ | ||
+ public function decorate($parent) | ||
+ { | ||
+ $this->_parent = $parent; | ||
+ | ||
+ // Lock down attributes to what is defined in the class | ||
+ // and speed up references in magic methods | ||
+ | ||
+ $class_name = get_class($parent); | ||
+ | ||
+ if ( ! isset(self::$_reflections[$class_name])) | ||
+ { | ||
+ $r = new ReflectionObject($parent); | ||
+ | ||
+ foreach ($r->getMethods() as $method) | ||
+ { | ||
+ if ($method->isPublic()) | ||
+ { | ||
+ $this->_methods[] = $method->getName(); | ||
+ } | ||
+ } | ||
+ | ||
+ foreach ($r->getProperties() as $prop) | ||
+ { | ||
+ if ($prop->isPublic()) | ||
+ { | ||
+ $this->_properties[] = $prop->getName(); | ||
+ } | ||
+ } | ||
+ | ||
+ self::$_reflections[$class_name] = array($this->_methods, $this->_properties); | ||
+ } | ||
+ else | ||
+ { | ||
+ list($this->_methods, $this->_properties) = self::$_reflections[$class_name]; | ||
+ } | ||
+ } | ||
+ | ||
+ // -------------------------------------------------------------------- | ||
+ | ||
+ /** | ||
+ * __call magic method | ||
+ * | ||
+ * Handles access to the parent driver library's methods | ||
+ * | ||
+ * @param string | ||
+ * @param array | ||
+ * @return mixed | ||
+ */ | ||
+ public function __call($method, $args = array()) | ||
+ { | ||
+ if (in_array($method, $this->_methods)) | ||
+ { | ||
+ return call_user_func_array(array($this->_parent, $method), $args); | ||
+ } | ||
+ | ||
+ throw new BadMethodCallException('No such method: '.$method.'()'); | ||
+ } | ||
+ | ||
+ // -------------------------------------------------------------------- | ||
+ | ||
+ /** | ||
+ * __get magic method | ||
+ * | ||
+ * Handles reading of the parent driver library's properties | ||
+ * | ||
+ * @param string | ||
+ * @return mixed | ||
+ */ | ||
+ public function __get($var) | ||
+ { | ||
+ if (in_array($var, $this->_properties)) | ||
+ { | ||
+ return $this->_parent->$var; | ||
+ } | ||
+ } | ||
+ | ||
+ // -------------------------------------------------------------------- | ||
+ | ||
+ /** | ||
+ * __set magic method | ||
+ * | ||
+ * Handles writing to the parent driver library's properties | ||
+ * | ||
+ * @param string | ||
+ * @param array | ||
+ * @return mixed | ||
+ */ | ||
+ public function __set($var, $val) | ||
+ { | ||
+ if (in_array($var, $this->_properties)) | ||
+ { | ||
+ $this->_parent->$var = $val; | ||
+ } | ||
+ } | ||
+ | ||
+} |
2,314
README/Email.php
2,314 additions,
0 deletions
not shown because the diff is too large. Please use a local Git client to view these changes.
480
README/Encrypt.php
@@ -0,0 +1,480 @@ | ||
+<?php | ||
+/** | ||
+ * CodeIgniter | ||
+ * | ||
+ * An open source application development framework for PHP | ||
+ * | ||
+ * This content is released under the MIT License (MIT) | ||
+ * | ||
+ * Copyright (c) 2014 - 2015, British Columbia Institute of Technology | ||
+ * | ||
+ * Permission is hereby granted, free of charge, to any person obtaining a copy | ||
+ * of this software and associated documentation files (the "Software"), to deal | ||
+ * in the Software without restriction, including without limitation the rights | ||
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | ||
+ * copies of the Software, and to permit persons to whom the Software is | ||
+ * furnished to do so, subject to the following conditions: | ||
+ * | ||
+ * The above copyright notice and this permission notice shall be included in | ||
+ * all copies or substantial portions of the Software. | ||
+ * | ||
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | ||
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | ||
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN | ||
+ * THE SOFTWARE. | ||
+ * | ||
+ * @package CodeIgniter | ||
+ * @author EllisLab Dev Team | ||
+ * @copyright Copyright (c) 2008 - 2014, EllisLab, Inc. (http://ellislab.com/) | ||
+ * @copyright Copyright (c) 2014 - 2015, British Columbia Institute of Technology (http://bcit.ca/) | ||
+ * @license http://opensource.org/licenses/MIT MIT License | ||
+ * @link http://codeigniter.com | ||
+ * @since Version 1.0.0 | ||
+ * @filesource | ||
+ */ | ||
+defined('BASEPATH') OR exit('No direct script access allowed'); | ||
+ | ||
+/** | ||
+ * CodeIgniter Encryption Class | ||
+ * | ||
+ * Provides two-way keyed encoding using Mcrypt | ||
+ * | ||
+ * @package CodeIgniter | ||
+ * @subpackage Libraries | ||
+ * @category Libraries | ||
+ * @author EllisLab Dev Team | ||
+ * @link http://codeigniter.com/user_guide/libraries/encryption.html | ||
+ */ | ||
+class CI_Encrypt { | ||
+ | ||
+ /** | ||
+ * Reference to the user's encryption key | ||
+ * | ||
+ * @var string | ||
+ */ | ||
+ public $encryption_key = ''; | ||
+ | ||
+ /** | ||
+ * Type of hash operation | ||
+ * | ||
+ * @var string | ||
+ */ | ||
+ protected $_hash_type = 'sha1'; | ||
+ | ||
+ /** | ||
+ * Flag for the existence of mcrypt | ||
+ * | ||
+ * @var bool | ||
+ */ | ||
+ protected $_mcrypt_exists = FALSE; | ||
+ | ||
+ /** | ||
+ * Current cipher to be used with mcrypt | ||
+ * | ||
+ * @var string | ||
+ */ | ||
+ protected $_mcrypt_cipher; | ||
+ | ||
+ /** | ||
+ * Method for encrypting/decrypting data | ||
+ * | ||
+ * @var int | ||
+ */ | ||
+ protected $_mcrypt_mode; | ||
+ | ||
+ /** | ||
+ * Initialize Encryption class | ||
+ * | ||
+ * @return void | ||
+ */ | ||
+ public function __construct() | ||
+ { | ||
+ if (($this->_mcrypt_exists = function_exists('mcrypt_encrypt')) === FALSE) | ||
+ { | ||
+ show_error('The Encrypt library requires the Mcrypt extension.'); | ||
+ } | ||
+ | ||
+ log_message('info', 'Encrypt Class Initialized'); | ||
+ } | ||
+ | ||
+ // -------------------------------------------------------------------- | ||
+ | ||
+ /** | ||
+ * Fetch the encryption key | ||
+ * | ||
+ * Returns it as MD5 in order to have an exact-length 128 bit key. | ||
+ * Mcrypt is sensitive to keys that are not the correct length | ||
+ * | ||
+ * @param string | ||
+ * @return string | ||
+ */ | ||
+ public function get_key($key = '') | ||
+ { | ||
+ if ($key === '') | ||
+ { | ||
+ if ($this->encryption_key !== '') | ||
+ { | ||
+ return $this->encryption_key; | ||
+ } | ||
+ | ||
+ $key = config_item('encryption_key'); | ||
+ | ||
+ if ( ! strlen($key)) | ||
+ { | ||
+ show_error('In order to use the encryption class requires that you set an encryption key in your config file.'); | ||
+ } | ||
+ } | ||
+ | ||
+ return md5($key); | ||
+ } | ||
+ | ||
+ // -------------------------------------------------------------------- | ||
+ | ||
+ /** | ||
+ * Set the encryption key | ||
+ * | ||
+ * @param string | ||
+ * @return CI_Encrypt | ||
+ */ | ||
+ public function set_key($key = '') | ||
+ { | ||
+ $this->encryption_key = $key; | ||
+ return $this; | ||
+ } | ||
+ | ||
+ // -------------------------------------------------------------------- | ||
+ | ||
+ /** | ||
+ * Encode | ||
+ * | ||
+ * Encodes the message string using bitwise XOR encoding. | ||
+ * The key is combined with a random hash, and then it | ||
+ * too gets converted using XOR. The whole thing is then run | ||
+ * through mcrypt using the randomized key. The end result | ||
+ * is a double-encrypted message string that is randomized | ||
+ * with each call to this function, even if the supplied | ||
+ * message and key are the same. | ||
+ * | ||
+ * @param string the string to encode | ||
+ * @param string the key | ||
+ * @return string | ||
+ */ | ||
+ public function encode($string, $key = '') | ||
+ { | ||
+ return base64_encode($this->mcrypt_encode($string, $this->get_key($key))); | ||
+ } | ||
+ | ||
+ // -------------------------------------------------------------------- | ||
+ | ||
+ /** | ||
+ * Decode | ||
+ * | ||
+ * Reverses the above process | ||
+ * | ||
+ * @param string | ||
+ * @param string | ||
+ * @return string | ||
+ */ | ||
+ public function decode($string, $key = '') | ||
+ { | ||
+ if (preg_match('/[^a-zA-Z0-9\/\+=]/', $string) OR base64_encode(base64_decode($string)) !== $string) | ||
+ { | ||
+ return FALSE; | ||
+ } | ||
+ | ||
+ return $this->mcrypt_decode(base64_decode($string), $this->get_key($key)); | ||
+ } | ||
+ | ||
+ // -------------------------------------------------------------------- | ||
+ | ||
+ /** | ||
+ * Encode from Legacy | ||
+ * | ||
+ * Takes an encoded string from the original Encryption class algorithms and | ||
+ * returns a newly encoded string using the improved method added in 2.0.0 | ||
+ * This allows for backwards compatibility and a method to transition to the | ||
+ * new encryption algorithms. | ||
+ * | ||
+ * For more details, see http://codeigniter.com/user_guide/installation/upgrade_200.html#encryption | ||
+ * | ||
+ * @param string | ||
+ * @param int (mcrypt mode constant) | ||
+ * @param string | ||
+ * @return string | ||
+ */ | ||
+ public function encode_from_legacy($string, $legacy_mode = MCRYPT_MODE_ECB, $key = '') | ||
+ { | ||
+ if (preg_match('/[^a-zA-Z0-9\/\+=]/', $string)) | ||
+ { | ||
+ return FALSE; | ||
+ } | ||
+ | ||
+ // decode it first | ||
+ // set mode temporarily to what it was when string was encoded with the legacy | ||
+ // algorithm - typically MCRYPT_MODE_ECB | ||
+ $current_mode = $this->_get_mode(); | ||
+ $this->set_mode($legacy_mode); | ||
+ | ||
+ $key = $this->get_key($key); | ||
+ $dec = base64_decode($string); | ||
+ if (($dec = $this->mcrypt_decode($dec, $key)) === FALSE) | ||
+ { | ||
+ $this->set_mode($current_mode); | ||
+ return FALSE; | ||
+ } | ||
+ | ||
+ $dec = $this->_xor_decode($dec, $key); | ||
+ | ||
+ // set the mcrypt mode back to what it should be, typically MCRYPT_MODE_CBC | ||
+ $this->set_mode($current_mode); | ||
+ | ||
+ // and re-encode | ||
+ return base64_encode($this->mcrypt_encode($dec, $key)); | ||
+ } | ||
+ | ||
+ // -------------------------------------------------------------------- | ||
+ | ||
+ /** | ||
+ * XOR Decode | ||
+ * | ||
+ * Takes an encoded string and key as input and generates the | ||
+ * plain-text original message | ||
+ * | ||
+ * @param string | ||
+ * @param string | ||
+ * @return string | ||
+ */ | ||
+ protected function _xor_decode($string, $key) | ||
+ { | ||
+ $string = $this->_xor_merge($string, $key); | ||
+ | ||
+ $dec = ''; | ||
+ for ($i = 0, $l = strlen($string); $i < $l; $i++) | ||
+ { | ||
+ $dec .= ($string[$i++] ^ $string[$i]); | ||
+ } | ||
+ | ||
+ return $dec; | ||
+ } | ||
+ | ||
+ // -------------------------------------------------------------------- | ||
+ | ||
+ /** | ||
+ * XOR key + string Combiner | ||
+ * | ||
+ * Takes a string and key as input and computes the difference using XOR | ||
+ * | ||
+ * @param string | ||
+ * @param string | ||
+ * @return string | ||
+ */ | ||
+ protected function _xor_merge($string, $key) | ||
+ { | ||
+ $hash = $this->hash($key); | ||
+ $str = ''; | ||
+ for ($i = 0, $ls = strlen($string), $lh = strlen($hash); $i < $ls; $i++) | ||
+ { | ||
+ $str .= $string[$i] ^ $hash[($i % $lh)]; | ||
+ } | ||
+ | ||
+ return $str; | ||
+ } | ||
+ | ||
+ // -------------------------------------------------------------------- | ||
+ | ||
+ /** | ||
+ * Encrypt using Mcrypt | ||
+ * | ||
+ * @param string | ||
+ * @param string | ||
+ * @return string | ||
+ */ | ||
+ public function mcrypt_encode($data, $key) | ||
+ { | ||
+ $init_size = mcrypt_get_iv_size($this->_get_cipher(), $this->_get_mode()); | ||
+ $init_vect = mcrypt_create_iv($init_size, MCRYPT_RAND); | ||
+ return $this->_add_cipher_noise($init_vect.mcrypt_encrypt($this->_get_cipher(), $key, $data, $this->_get_mode(), $init_vect), $key); | ||
+ } | ||
+ | ||
+ // -------------------------------------------------------------------- | ||
+ | ||
+ /** | ||
+ * Decrypt using Mcrypt | ||
+ * | ||
+ * @param string | ||
+ * @param string | ||
+ * @return string | ||
+ */ | ||
+ public function mcrypt_decode($data, $key) | ||
+ { | ||
+ $data = $this->_remove_cipher_noise($data, $key); | ||
+ $init_size = mcrypt_get_iv_size($this->_get_cipher(), $this->_get_mode()); | ||
+ | ||
+ if ($init_size > strlen($data)) | ||
+ { | ||
+ return FALSE; | ||
+ } | ||
+ | ||
+ $init_vect = substr($data, 0, $init_size); | ||
+ $data = substr($data, $init_size); | ||
+ return rtrim(mcrypt_decrypt($this->_get_cipher(), $key, $data, $this->_get_mode(), $init_vect), "\0"); | ||
+ } | ||
+ | ||
+ // -------------------------------------------------------------------- | ||
+ | ||
+ /** | ||
+ * Adds permuted noise to the IV + encrypted data to protect | ||
+ * against Man-in-the-middle attacks on CBC mode ciphers | ||
+ * http://www.ciphersbyritter.com/GLOSSARY.HTM#IV | ||
+ * | ||
+ * @param string | ||
+ * @param string | ||
+ * @return string | ||
+ */ | ||
+ protected function _add_cipher_noise($data, $key) | ||
+ { | ||
+ $key = $this->hash($key); | ||
+ $str = ''; | ||
+ | ||
+ for ($i = 0, $j = 0, $ld = strlen($data), $lk = strlen($key); $i < $ld; ++$i, ++$j) | ||
+ { | ||
+ if ($j >= $lk) | ||
+ { | ||
+ $j = 0; | ||
+ } | ||
+ | ||
+ $str .= chr((ord($data[$i]) + ord($key[$j])) % 256); | ||
+ } | ||
+ | ||
+ return $str; | ||
+ } | ||
+ | ||
+ // -------------------------------------------------------------------- | ||
+ | ||
+ /** | ||
+ * Removes permuted noise from the IV + encrypted data, reversing | ||
+ * _add_cipher_noise() | ||
+ * | ||
+ * Function description | ||
+ * | ||
+ * @param string $data | ||
+ * @param string $key | ||
+ * @return string | ||
+ */ | ||
+ protected function _remove_cipher_noise($data, $key) | ||
+ { | ||
+ $key = $this->hash($key); | ||
+ $str = ''; | ||
+ | ||
+ for ($i = 0, $j = 0, $ld = strlen($data), $lk = strlen($key); $i < $ld; ++$i, ++$j) | ||
+ { | ||
+ if ($j >= $lk) | ||
+ { | ||
+ $j = 0; | ||
+ } | ||
+ | ||
+ $temp = ord($data[$i]) - ord($key[$j]); | ||
+ | ||
+ if ($temp < 0) | ||
+ { | ||
+ $temp += 256; | ||
+ } | ||
+ | ||
+ $str .= chr($temp); | ||
+ } | ||
+ | ||
+ return $str; | ||
+ } | ||
+ | ||
+ // -------------------------------------------------------------------- | ||
+ | ||
+ /** | ||
+ * Set the Mcrypt Cipher | ||
+ * | ||
+ * @param int | ||
+ * @return CI_Encrypt | ||
+ */ | ||
+ public function set_cipher($cipher) | ||
+ { | ||
+ $this->_mcrypt_cipher = $cipher; | ||
+ return $this; | ||
+ } | ||
+ | ||
+ // -------------------------------------------------------------------- | ||
+ | ||
+ /** | ||
+ * Set the Mcrypt Mode | ||
+ * | ||
+ * @param int | ||
+ * @return CI_Encrypt | ||
+ */ | ||
+ public function set_mode($mode) | ||
+ { | ||
+ $this->_mcrypt_mode = $mode; | ||
+ return $this; | ||
+ } | ||
+ | ||
+ // -------------------------------------------------------------------- | ||
+ | ||
+ /** | ||
+ * Get Mcrypt cipher Value | ||
+ * | ||
+ * @return int | ||
+ */ | ||
+ protected function _get_cipher() | ||
+ { | ||
+ if ($this->_mcrypt_cipher === NULL) | ||
+ { | ||
+ return $this->_mcrypt_cipher = MCRYPT_RIJNDAEL_256; | ||
+ } | ||
+ | ||
+ return $this->_mcrypt_cipher; | ||
+ } | ||
+ | ||
+ // -------------------------------------------------------------------- | ||
+ | ||
+ /** | ||
+ * Get Mcrypt Mode Value | ||
+ * | ||
+ * @return int | ||
+ */ | ||
+ protected function _get_mode() | ||
+ { | ||
+ if ($this->_mcrypt_mode === NULL) | ||
+ { | ||
+ return $this->_mcrypt_mode = MCRYPT_MODE_CBC; | ||
+ } | ||
+ | ||
+ return $this->_mcrypt_mode; | ||
+ } | ||
+ | ||
+ // -------------------------------------------------------------------- | ||
+ | ||
+ /** | ||
+ * Set the Hash type | ||
+ * | ||
+ * @param string | ||
+ * @return void | ||
+ */ | ||
+ public function set_hash($type = 'sha1') | ||
+ { | ||
+ $this->_hash_type = in_array($type, hash_algos()) ? $type : 'sha1'; | ||
+ } | ||
+ | ||
+ // -------------------------------------------------------------------- | ||
+ | ||
+ /** | ||
+ * Hash encode a string | ||
+ * | ||
+ * @param string | ||
+ * @return string | ||
+ */ | ||
+ public function hash($str) | ||
+ { | ||
+ return hash($this->_hash_type, $str); | ||
+ } | ||
+ | ||
+} |
926
README/Encryption.php
@@ -0,0 +1,926 @@ | ||
+<?php | ||
+/** | ||
+ * CodeIgniter | ||
+ * | ||
+ * An open source application development framework for PHP | ||
+ * | ||
+ * This content is released under the MIT License (MIT) | ||
+ * | ||
+ * Copyright (c) 2014 - 2015, British Columbia Institute of Technology | ||
+ * | ||
+ * Permission is hereby granted, free of charge, to any person obtaining a copy | ||
+ * of this software and associated documentation files (the "Software"), to deal | ||
+ * in the Software without restriction, including without limitation the rights | ||
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | ||
+ * copies of the Software, and to permit persons to whom the Software is | ||
+ * furnished to do so, subject to the following conditions: | ||
+ * | ||
+ * The above copyright notice and this permission notice shall be included in | ||
+ * all copies or substantial portions of the Software. | ||
+ * | ||
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | ||
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | ||
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN | ||
+ * THE SOFTWARE. | ||
+ * | ||
+ * @package CodeIgniter | ||
+ * @author EllisLab Dev Team | ||
+ * @copyright Copyright (c) 2008 - 2014, EllisLab, Inc. (http://ellislab.com/) | ||
+ * @copyright Copyright (c) 2014 - 2015, British Columbia Institute of Technology (http://bcit.ca/) | ||
+ * @license http://opensource.org/licenses/MIT MIT License | ||
+ * @link http://codeigniter.com | ||
+ * @since Version 3.0.0 | ||
+ * @filesource | ||
+ */ | ||
+defined('BASEPATH') OR exit('No direct script access allowed'); | ||
+ | ||
+/** | ||
+ * CodeIgniter Encryption Class | ||
+ * | ||
+ * Provides two-way keyed encryption via PHP's MCrypt and/or OpenSSL extensions. | ||
+ * | ||
+ * @package CodeIgniter | ||
+ * @subpackage Libraries | ||
+ * @category Libraries | ||
+ * @author Andrey Andreev | ||
+ * @link http://codeigniter.com/user_guide/libraries/encryption.html | ||
+ */ | ||
+class CI_Encryption { | ||
+ | ||
+ /** | ||
+ * Encryption cipher | ||
+ * | ||
+ * @var string | ||
+ */ | ||
+ protected $_cipher = 'aes-128'; | ||
+ | ||
+ /** | ||
+ * Cipher mode | ||
+ * | ||
+ * @var string | ||
+ */ | ||
+ protected $_mode = 'cbc'; | ||
+ | ||
+ /** | ||
+ * Cipher handle | ||
+ * | ||
+ * @var mixed | ||
+ */ | ||
+ protected $_handle; | ||
+ | ||
+ /** | ||
+ * Encryption key | ||
+ * | ||
+ * @var string | ||
+ */ | ||
+ protected $_key; | ||
+ | ||
+ /** | ||
+ * PHP extension to be used | ||
+ * | ||
+ * @var string | ||
+ */ | ||
+ protected $_driver; | ||
+ | ||
+ /** | ||
+ * List of usable drivers (PHP extensions) | ||
+ * | ||
+ * @var array | ||
+ */ | ||
+ protected $_drivers = array(); | ||
+ | ||
+ /** | ||
+ * List of available modes | ||
+ * | ||
+ * @var array | ||
+ */ | ||
+ protected $_modes = array( | ||
+ 'mcrypt' => array( | ||
+ 'cbc' => 'cbc', | ||
+ 'ecb' => 'ecb', | ||
+ 'ofb' => 'nofb', | ||
+ 'ofb8' => 'ofb', | ||
+ 'cfb' => 'ncfb', | ||
+ 'cfb8' => 'cfb', | ||
+ 'ctr' => 'ctr', | ||
+ 'stream' => 'stream' | ||
+ ), | ||
+ 'openssl' => array( | ||
+ 'cbc' => 'cbc', | ||
+ 'ecb' => 'ecb', | ||
+ 'ofb' => 'ofb', | ||
+ 'cfb' => 'cfb', | ||
+ 'cfb8' => 'cfb8', | ||
+ 'ctr' => 'ctr', | ||
+ 'stream' => '', | ||
+ 'xts' => 'xts' | ||
+ ) | ||
+ ); | ||
+ | ||
+ /** | ||
+ * List of supported HMAC algorithms | ||
+ * | ||
+ * name => digest size pairs | ||
+ * | ||
+ * @var array | ||
+ */ | ||
+ protected $_digests = array( | ||
+ 'sha224' => 28, | ||
+ 'sha256' => 32, | ||
+ 'sha384' => 48, | ||
+ 'sha512' => 64 | ||
+ ); | ||
+ | ||
+ /** | ||
+ * mbstring.func_override flag | ||
+ * | ||
+ * @var bool | ||
+ */ | ||
+ protected static $func_override; | ||
+ | ||
+ // -------------------------------------------------------------------- | ||
+ | ||
+ /** | ||
+ * Class constructor | ||
+ * | ||
+ * @param array $params Configuration parameters | ||
+ * @return void | ||
+ */ | ||
+ public function __construct(array $params = array()) | ||
+ { | ||
+ $this->_drivers = array( | ||
+ 'mcrypt' => defined('MCRYPT_DEV_URANDOM'), | ||
+ // While OpenSSL is available for PHP 5.3.0, an IV parameter | ||
+ // for the encrypt/decrypt functions is only available since 5.3.3 | ||
+ 'openssl' => (is_php('5.3.3') && extension_loaded('openssl')) | ||
+ ); | ||
+ | ||
+ if ( ! $this->_drivers['mcrypt'] && ! $this->_drivers['openssl']) | ||
+ { | ||
+ show_error('Encryption: Unable to find an available encryption driver.'); | ||
+ } | ||
+ | ||
+ isset(self::$func_override) OR self::$func_override = (extension_loaded('mbstring') && ini_get('mbstring.func_override')); | ||
+ $this->initialize($params); | ||
+ | ||
+ if ( ! isset($this->_key) && self::strlen($key = config_item('encryption_key')) > 0) | ||
+ { | ||
+ $this->_key = $key; | ||
+ } | ||
+ | ||
+ log_message('info', 'Encryption Class Initialized'); | ||
+ } | ||
+ | ||
+ // -------------------------------------------------------------------- | ||
+ | ||
+ /** | ||
+ * Initialize | ||
+ * | ||
+ * @param array $params Configuration parameters | ||
+ * @return CI_Encryption | ||
+ */ | ||
+ public function initialize(array $params) | ||
+ { | ||
+ if ( ! empty($params['driver'])) | ||
+ { | ||
+ if (isset($this->_drivers[$params['driver']])) | ||
+ { | ||
+ if ($this->_drivers[$params['driver']]) | ||
+ { | ||
+ $this->_driver = $params['driver']; | ||
+ } | ||
+ else | ||
+ { | ||
+ log_message('error', "Encryption: Driver '".$params['driver']."' is not available."); | ||
+ } | ||
+ } | ||
+ else | ||
+ { | ||
+ log_message('error', "Encryption: Unknown driver '".$params['driver']."' cannot be configured."); | ||
+ } | ||
+ } | ||
+ | ||
+ if (empty($this->_driver)) | ||
+ { | ||
+ $this->_driver = ($this->_drivers['openssl'] === TRUE) | ||
+ ? 'openssl' | ||
+ : 'mcrypt'; | ||
+ | ||
+ log_message('debug', "Encryption: Auto-configured driver '".$this->_driver."'."); | ||
+ } | ||
+ | ||
+ empty($params['cipher']) && $params['cipher'] = $this->_cipher; | ||
+ empty($params['key']) OR $this->_key = $params['key']; | ||
+ $this->{'_'.$this->_driver.'_initialize'}($params); | ||
+ return $this; | ||
+ } | ||
+ | ||
+ // -------------------------------------------------------------------- | ||
+ | ||
+ /** | ||
+ * Initialize MCrypt | ||
+ * | ||
+ * @param array $params Configuration parameters | ||
+ * @return void | ||
+ */ | ||
+ protected function _mcrypt_initialize($params) | ||
+ { | ||
+ if ( ! empty($params['cipher'])) | ||
+ { | ||
+ $params['cipher'] = strtolower($params['cipher']); | ||
+ $this->_cipher_alias($params['cipher']); | ||
+ | ||
+ if ( ! in_array($params['cipher'], mcrypt_list_algorithms(), TRUE)) | ||
+ { | ||
+ log_message('error', 'Encryption: MCrypt cipher '.strtoupper($params['cipher']).' is not available.'); | ||
+ } | ||
+ else | ||
+ { | ||
+ $this->_cipher = $params['cipher']; | ||
+ } | ||
+ } | ||
+ | ||
+ if ( ! empty($params['mode'])) | ||
+ { | ||
+ $params['mode'] = strtolower($params['mode']); | ||
+ if ( ! isset($this->_modes['mcrypt'][$params['mode']])) | ||
+ { | ||
+ log_message('error', 'Encryption: MCrypt mode '.strtoupper($params['mode']).' is not available.'); | ||
+ } | ||
+ else | ||
+ { | ||
+ $this->_mode = $this->_modes['mcrypt'][$params['mode']]; | ||
+ } | ||
+ } | ||
+ | ||
+ if (isset($this->_cipher, $this->_mode)) | ||
+ { | ||
+ if (is_resource($this->_handle) | ||
+ && (strtolower(mcrypt_enc_get_algorithms_name($this->_handle)) !== $this->_cipher | ||
+ OR strtolower(mcrypt_enc_get_modes_name($this->_handle)) !== $this->_mode) | ||
+ ) | ||
+ { | ||
+ mcrypt_module_close($this->_handle); | ||
+ } | ||
+ | ||
+ if ($this->_handle = mcrypt_module_open($this->_cipher, '', $this->_mode, '')) | ||
+ { | ||
+ log_message('info', 'Encryption: MCrypt cipher '.strtoupper($this->_cipher).' initialized in '.strtoupper($this->_mode).' mode.'); | ||
+ } | ||
+ else | ||
+ { | ||
+ log_message('error', 'Encryption: Unable to initialize MCrypt with cipher '.strtoupper($this->_cipher).' in '.strtoupper($this->_mode).' mode.'); | ||
+ } | ||
+ } | ||
+ } | ||
+ | ||
+ // -------------------------------------------------------------------- | ||
+ | ||
+ /** | ||
+ * Initialize OpenSSL | ||
+ * | ||
+ * @param array $params Configuration parameters | ||
+ * @return void | ||
+ */ | ||
+ protected function _openssl_initialize($params) | ||
+ { | ||
+ if ( ! empty($params['cipher'])) | ||
+ { | ||
+ $params['cipher'] = strtolower($params['cipher']); | ||
+ $this->_cipher_alias($params['cipher']); | ||
+ $this->_cipher = $params['cipher']; | ||
+ } | ||
+ | ||
+ if ( ! empty($params['mode'])) | ||
+ { | ||
+ $params['mode'] = strtolower($params['mode']); | ||
+ if ( ! isset($this->_modes['openssl'][$params['mode']])) | ||
+ { | ||
+ log_message('error', 'Encryption: OpenSSL mode '.strtoupper($params['mode']).' is not available.'); | ||
+ } | ||
+ else | ||
+ { | ||
+ $this->_mode = $this->_modes['openssl'][$params['mode']]; | ||
+ } | ||
+ } | ||
+ | ||
+ if (isset($this->_cipher, $this->_mode)) | ||
+ { | ||
+ // This is mostly for the stream mode, which doesn't get suffixed in OpenSSL | ||
+ $handle = empty($this->_mode) | ||
+ ? $this->_cipher | ||
+ : $this->_cipher.'-'.$this->_mode; | ||
+ | ||
+ if ( ! in_array($handle, openssl_get_cipher_methods(), TRUE)) | ||
+ { | ||
+ $this->_handle = NULL; | ||
+ log_message('error', 'Encryption: Unable to initialize OpenSSL with method '.strtoupper($handle).'.'); | ||
+ } | ||
+ else | ||
+ { | ||
+ $this->_handle = $handle; | ||
+ log_message('info', 'Encryption: OpenSSL initialized with method '.strtoupper($handle).'.'); | ||
+ } | ||
+ } | ||
+ } | ||
+ | ||
+ // -------------------------------------------------------------------- | ||
+ | ||
+ /** | ||
+ * Create a random key | ||
+ * | ||
+ * @param int $length Output length | ||
+ * @return string | ||
+ */ | ||
+ public function create_key($length) | ||
+ { | ||
+ return ($this->_driver === 'mcrypt') | ||
+ ? mcrypt_create_iv($length, MCRYPT_DEV_URANDOM) | ||
+ : openssl_random_pseudo_bytes($length); | ||
+ } | ||
+ | ||
+ // -------------------------------------------------------------------- | ||
+ | ||
+ /** | ||
+ * Encrypt | ||
+ * | ||
+ * @param string $data Input data | ||
+ * @param array $params Input parameters | ||
+ * @return string | ||
+ */ | ||
+ public function encrypt($data, array $params = NULL) | ||
+ { | ||
+ if (($params = $this->_get_params($params)) === FALSE) | ||
+ { | ||
+ return FALSE; | ||
+ } | ||
+ | ||
+ isset($params['key']) OR $params['key'] = $this->hkdf($this->_key, 'sha512', NULL, self::strlen($this->_key), 'encryption'); | ||
+ | ||
+ if (($data = $this->{'_'.$this->_driver.'_encrypt'}($data, $params)) === FALSE) | ||
+ { | ||
+ return FALSE; | ||
+ } | ||
+ | ||
+ $params['base64'] && $data = base64_encode($data); | ||
+ | ||
+ if (isset($params['hmac_digest'])) | ||
+ { | ||
+ isset($params['hmac_key']) OR $params['hmac_key'] = $this->hkdf($this->_key, 'sha512', NULL, NULL, 'authentication'); | ||
+ return hash_hmac($params['hmac_digest'], $data, $params['hmac_key'], ! $params['base64']).$data; | ||
+ } | ||
+ | ||
+ return $data; | ||
+ } | ||
+ | ||
+ // -------------------------------------------------------------------- | ||
+ | ||
+ /** | ||
+ * Encrypt via MCrypt | ||
+ * | ||
+ * @param string $data Input data | ||
+ * @param array $params Input parameters | ||
+ * @return string | ||
+ */ | ||
+ protected function _mcrypt_encrypt($data, $params) | ||
+ { | ||
+ if ( ! is_resource($params['handle'])) | ||
+ { | ||
+ return FALSE; | ||
+ } | ||
+ | ||
+ // The greater-than-1 comparison is mostly a work-around for a bug, | ||
+ // where 1 is returned for ARCFour instead of 0. | ||
+ $iv = (($iv_size = mcrypt_enc_get_iv_size($params['handle'])) > 1) | ||
+ ? mcrypt_create_iv($iv_size, MCRYPT_DEV_URANDOM) | ||
+ : NULL; | ||
+ | ||
+ if (mcrypt_generic_init($params['handle'], $params['key'], $iv) < 0) | ||
+ { | ||
+ if ($params['handle'] !== $this->_handle) | ||
+ { | ||
+ mcrypt_module_close($params['handle']); | ||
+ } | ||
+ | ||
+ return FALSE; | ||
+ } | ||
+ | ||
+ // Use PKCS#7 padding in order to ensure compatibility with OpenSSL | ||
+ // and other implementations outside of PHP. | ||
+ if (in_array(strtolower(mcrypt_enc_get_modes_name($params['handle'])), array('cbc', 'ecb'), TRUE)) | ||
+ { | ||
+ $block_size = mcrypt_enc_get_block_size($params['handle']); | ||
+ $pad = $block_size - (self::strlen($data) % $block_size); | ||
+ $data .= str_repeat(chr($pad), $pad); | ||
+ } | ||
+ | ||
+ // Work-around for yet another strange behavior in MCrypt. | ||
+ // | ||
+ // When encrypting in ECB mode, the IV is ignored. Yet | ||
+ // mcrypt_enc_get_iv_size() returns a value larger than 0 | ||
+ // even if ECB is used AND mcrypt_generic_init() complains | ||
+ // if you don't pass an IV with length equal to the said | ||
+ // return value. | ||
+ // | ||
+ // This probably would've been fine (even though still wasteful), | ||
+ // but OpenSSL isn't that dumb and we need to make the process | ||
+ // portable, so ... | ||
+ $data = (mcrypt_enc_get_modes_name($params['handle']) !== 'ECB') | ||
+ ? $iv.mcrypt_generic($params['handle'], $data) | ||
+ : mcrypt_generic($params['handle'], $data); | ||
+ | ||
+ mcrypt_generic_deinit($params['handle']); | ||
+ if ($params['handle'] !== $this->_handle) | ||
+ { | ||
+ mcrypt_module_close($params['handle']); | ||
+ } | ||
+ | ||
+ return $data; | ||
+ } | ||
+ | ||
+ // -------------------------------------------------------------------- | ||
+ | ||
+ /** | ||
+ * Encrypt via OpenSSL | ||
+ * | ||
+ * @param string $data Input data | ||
+ * @param array $params Input parameters | ||
+ * @return string | ||
+ */ | ||
+ protected function _openssl_encrypt($data, $params) | ||
+ { | ||
+ if (empty($params['handle'])) | ||
+ { | ||
+ return FALSE; | ||
+ } | ||
+ | ||
+ $iv = ($iv_size = openssl_cipher_iv_length($params['handle'])) | ||
+ ? openssl_random_pseudo_bytes($iv_size) | ||
+ : NULL; | ||
+ | ||
+ $data = openssl_encrypt( | ||
+ $data, | ||
+ $params['handle'], | ||
+ $params['key'], | ||
+ 1, // DO NOT TOUCH! | ||
+ $iv | ||
+ ); | ||
+ | ||
+ if ($data === FALSE) | ||
+ { | ||
+ return FALSE; | ||
+ } | ||
+ | ||
+ return $iv.$data; | ||
+ } | ||
+ | ||
+ // -------------------------------------------------------------------- | ||
+ | ||
+ /** | ||
+ * Decrypt | ||
+ * | ||
+ * @param string $data Encrypted data | ||
+ * @param array $params Input parameters | ||
+ * @return string | ||
+ */ | ||
+ public function decrypt($data, array $params = NULL) | ||
+ { | ||
+ if (($params = $this->_get_params($params)) === FALSE) | ||
+ { | ||
+ return FALSE; | ||
+ } | ||
+ | ||
+ if (isset($params['hmac_digest'])) | ||
+ { | ||
+ // This might look illogical, but it is done during encryption as well ... | ||
+ // The 'base64' value is effectively an inverted "raw data" parameter | ||
+ $digest_size = ($params['base64']) | ||
+ ? $this->_digests[$params['hmac_digest']] * 2 | ||
+ : $this->_digests[$params['hmac_digest']]; | ||
+ | ||
+ if (self::strlen($data) <= $digest_size) | ||
+ { | ||
+ return FALSE; | ||
+ } | ||
+ | ||
+ $hmac_input = self::substr($data, 0, $digest_size); | ||
+ $data = self::substr($data, $digest_size); | ||
+ | ||
+ isset($params['hmac_key']) OR $params['hmac_key'] = $this->hkdf($this->_key, 'sha512', NULL, NULL, 'authentication'); | ||
+ $hmac_check = hash_hmac($params['hmac_digest'], $data, $params['hmac_key'], ! $params['base64']); | ||
+ | ||
+ // Time-attack-safe comparison | ||
+ $diff = 0; | ||
+ for ($i = 0; $i < $digest_size; $i++) | ||
+ { | ||
+ $diff |= ord($hmac_input[$i]) ^ ord($hmac_check[$i]); | ||
+ } | ||
+ | ||
+ if ($diff !== 0) | ||
+ { | ||
+ return FALSE; | ||
+ } | ||
+ } | ||
+ | ||
+ if ($params['base64']) | ||
+ { | ||
+ $data = base64_decode($data); | ||
+ } | ||
+ | ||
+ isset($params['key']) OR $params['key'] = $this->hkdf($this->_key, 'sha512', NULL, self::strlen($this->_key), 'encryption'); | ||
+ | ||
+ return $this->{'_'.$this->_driver.'_decrypt'}($data, $params); | ||
+ } | ||
+ | ||
+ // -------------------------------------------------------------------- | ||
+ | ||
+ /** | ||
+ * Decrypt via MCrypt | ||
+ * | ||
+ * @param string $data Encrypted data | ||
+ * @param array $params Input parameters | ||
+ * @return string | ||
+ */ | ||
+ protected function _mcrypt_decrypt($data, $params) | ||
+ { | ||
+ if ( ! is_resource($params['handle'])) | ||
+ { | ||
+ return FALSE; | ||
+ } | ||
+ | ||
+ // The greater-than-1 comparison is mostly a work-around for a bug, | ||
+ // where 1 is returned for ARCFour instead of 0. | ||
+ if (($iv_size = mcrypt_enc_get_iv_size($params['handle'])) > 1) | ||
+ { | ||
+ if (mcrypt_enc_get_modes_name($params['handle']) !== 'ECB') | ||
+ { | ||
+ $iv = self::substr($data, 0, $iv_size); | ||
+ $data = self::substr($data, $iv_size); | ||
+ } | ||
+ else | ||
+ { | ||
+ // MCrypt is dumb and this is ignored, only size matters | ||
+ $iv = str_repeat("\x0", $iv_size); | ||
+ } | ||
+ } | ||
+ else | ||
+ { | ||
+ $iv = NULL; | ||
+ } | ||
+ | ||
+ if (mcrypt_generic_init($params['handle'], $params['key'], $iv) < 0) | ||
+ { | ||
+ if ($params['handle'] !== $this->_handle) | ||
+ { | ||
+ mcrypt_module_close($params['handle']); | ||
+ } | ||
+ | ||
+ return FALSE; | ||
+ } | ||
+ | ||
+ $data = mdecrypt_generic($params['handle'], $data); | ||
+ // Remove PKCS#7 padding, if necessary | ||
+ if (in_array(strtolower(mcrypt_enc_get_modes_name($params['handle'])), array('cbc', 'ecb'), TRUE)) | ||
+ { | ||
+ $data = self::substr($data, 0, -ord($data[self::strlen($data)-1])); | ||
+ } | ||
+ | ||
+ mcrypt_generic_deinit($params['handle']); | ||
+ if ($params['handle'] !== $this->_handle) | ||
+ { | ||
+ mcrypt_module_close($params['handle']); | ||
+ } | ||
+ | ||
+ return $data; | ||
+ } | ||
+ | ||
+ // -------------------------------------------------------------------- | ||
+ | ||
+ /** | ||
+ * Decrypt via OpenSSL | ||
+ * | ||
+ * @param string $data Encrypted data | ||
+ * @param array $params Input parameters | ||
+ * @return string | ||
+ */ | ||
+ protected function _openssl_decrypt($data, $params) | ||
+ { | ||
+ if ($iv_size = openssl_cipher_iv_length($params['handle'])) | ||
+ { | ||
+ $iv = self::substr($data, 0, $iv_size); | ||
+ $data = self::substr($data, $iv_size); | ||
+ } | ||
+ else | ||
+ { | ||
+ $iv = NULL; | ||
+ } | ||
+ | ||
+ return empty($params['handle']) | ||
+ ? FALSE | ||
+ : openssl_decrypt( | ||
+ $data, | ||
+ $params['handle'], | ||
+ $params['key'], | ||
+ 1, // DO NOT TOUCH! | ||
+ $iv | ||
+ ); | ||
+ } | ||
+ | ||
+ // -------------------------------------------------------------------- | ||
+ | ||
+ /** | ||
+ * Get params | ||
+ * | ||
+ * @param array $params Input parameters | ||
+ * @return array | ||
+ */ | ||
+ protected function _get_params($params) | ||
+ { | ||
+ if (empty($params)) | ||
+ { | ||
+ return isset($this->_cipher, $this->_mode, $this->_key, $this->_handle) | ||
+ ? array( | ||
+ 'handle' => $this->_handle, | ||
+ 'cipher' => $this->_cipher, | ||
+ 'mode' => $this->_mode, | ||
+ 'key' => NULL, | ||
+ 'base64' => TRUE, | ||
+ 'hmac_digest' => 'sha512', | ||
+ 'hmac_key' => NULL | ||
+ ) | ||
+ : FALSE; | ||
+ } | ||
+ elseif ( ! isset($params['cipher'], $params['mode'], $params['key'])) | ||
+ { | ||
+ return FALSE; | ||
+ } | ||
+ | ||
+ if (isset($params['mode'])) | ||
+ { | ||
+ $params['mode'] = strtolower($params['mode']); | ||
+ if ( ! isset($this->_modes[$this->_driver][$params['mode']])) | ||
+ { | ||
+ return FALSE; | ||
+ } | ||
+ else | ||
+ { | ||
+ $params['mode'] = $this->_modes[$this->_driver][$params['mode']]; | ||
+ } | ||
+ } | ||
+ | ||
+ if (isset($params['hmac']) && $params['hmac'] === FALSE) | ||
+ { | ||
+ $params['hmac_digest'] = $params['hmac_key'] = NULL; | ||
+ } | ||
+ else | ||
+ { | ||
+ if ( ! isset($params['hmac_key'])) | ||
+ { | ||
+ return FALSE; | ||
+ } | ||
+ elseif (isset($params['hmac_digest'])) | ||
+ { | ||
+ $params['hmac_digest'] = strtolower($params['hmac_digest']); | ||
+ if ( ! isset($this->_digests[$params['hmac_digest']])) | ||
+ { | ||
+ return FALSE; | ||
+ } | ||
+ } | ||
+ else | ||
+ { | ||
+ $params['hmac_digest'] = 'sha512'; | ||
+ } | ||
+ } | ||
+ | ||
+ $params = array( | ||
+ 'handle' => NULL, | ||
+ 'cipher' => $params['cipher'], | ||
+ 'mode' => $params['mode'], | ||
+ 'key' => $params['key'], | ||
+ 'base64' => isset($params['raw_data']) ? ! $params['raw_data'] : FALSE, | ||
+ 'hmac_digest' => $params['hmac_digest'], | ||
+ 'hmac_key' => $params['hmac_key'] | ||
+ ); | ||
+ | ||
+ $this->_cipher_alias($params['cipher']); | ||
+ $params['handle'] = ($params['cipher'] !== $this->_cipher OR $params['mode'] !== $this->_mode) | ||
+ ? $this->{'_'.$this->_driver.'_get_handle'}($params['cipher'], $params['mode']) | ||
+ : $this->_handle; | ||
+ | ||
+ return $params; | ||
+ } | ||
+ | ||
+ // -------------------------------------------------------------------- | ||
+ | ||
+ /** | ||
+ * Get MCrypt handle | ||
+ * | ||
+ * @param string $cipher Cipher name | ||
+ * @param string $mode Encryption mode | ||
+ * @return resource | ||
+ */ | ||
+ protected function _mcrypt_get_handle($cipher, $mode) | ||
+ { | ||
+ return mcrypt_module_open($cipher, '', $mode, ''); | ||
+ } | ||
+ | ||
+ // -------------------------------------------------------------------- | ||
+ | ||
+ /** | ||
+ * Get OpenSSL handle | ||
+ * | ||
+ * @param string $cipher Cipher name | ||
+ * @param string $mode Encryption mode | ||
+ * @return string | ||
+ */ | ||
+ protected function _openssl_get_handle($cipher, $mode) | ||
+ { | ||
+ // OpenSSL methods aren't suffixed with '-stream' for this mode | ||
+ return ($mode === 'stream') | ||
+ ? $cipher | ||
+ : $cipher.'-'.$mode; | ||
+ } | ||
+ | ||
+ // -------------------------------------------------------------------- | ||
+ | ||
+ /** | ||
+ * Cipher alias | ||
+ * | ||
+ * Tries to translate cipher names between MCrypt and OpenSSL's "dialects". | ||
+ * | ||
+ * @param string $cipher Cipher name | ||
+ * @return void | ||
+ */ | ||
+ protected function _cipher_alias(&$cipher) | ||
+ { | ||
+ static $dictionary; | ||
+ | ||
+ if (empty($dictionary)) | ||
+ { | ||
+ $dictionary = array( | ||
+ 'mcrypt' => array( | ||
+ 'aes-128' => 'rijndael-128', | ||
+ 'aes-192' => 'rijndael-128', | ||
+ 'aes-256' => 'rijndael-128', | ||
+ 'des3-ede3' => 'tripledes', | ||
+ 'bf' => 'blowfish', | ||
+ 'cast5' => 'cast-128', | ||
+ 'rc4' => 'arcfour', | ||
+ 'rc4-40' => 'arcfour' | ||
+ ), | ||
+ 'openssl' => array( | ||
+ 'rijndael-128' => 'aes-128', | ||
+ 'tripledes' => 'des-ede3', | ||
+ 'blowfish' => 'bf', | ||
+ 'cast-128' => 'cast5', | ||
+ 'arcfour' => 'rc4-40', | ||
+ 'rc4' => 'rc4-40' | ||
+ ) | ||
+ ); | ||
+ | ||
+ // Notes: | ||
+ // | ||
+ // - Rijndael-128 is, at the same time all three of AES-128, | ||
+ // AES-192 and AES-256. The only difference between them is | ||
+ // the key size. Rijndael-192, Rijndael-256 on the other hand | ||
+ // also have different block sizes and are NOT AES-compatible. | ||
+ // | ||
+ // - Blowfish is said to be supporting key sizes between | ||
+ // 4 and 56 bytes, but it appears that between MCrypt and | ||
+ // OpenSSL, only those of 16 and more bytes are compatible. | ||
+ // Also, don't know what MCrypt's 'blowfish-compat' is. | ||
+ // | ||
+ // - CAST-128/CAST5 produces a longer cipher when encrypted via | ||
+ // OpenSSL, but (strangely enough) can be decrypted by either | ||
+ // extension anyway. | ||
+ // Also, it appears that OpenSSL uses 16 rounds regardless of | ||
+ // the key size, while RFC2144 says that for key sizes lower | ||
+ // than 11 bytes, only 12 rounds should be used. This makes | ||
+ // it portable only with keys of between 11 and 16 bytes. | ||
+ // | ||
+ // - RC4 (ARCFour) has a strange implementation under OpenSSL. | ||
+ // Its 'rc4-40' cipher method seems to work flawlessly, yet | ||
+ // there's another one, 'rc4' that only works with a 16-byte key. | ||
+ // | ||
+ // - DES is compatible, but doesn't need an alias. | ||
+ // | ||
+ // Other seemingly matching ciphers between MCrypt, OpenSSL: | ||
+ // | ||
+ // - RC2 is NOT compatible and only an obscure forum post | ||
+ // confirms that it is MCrypt's fault. | ||
+ } | ||
+ | ||
+ if (isset($dictionary[$this->_driver][$cipher])) | ||
+ { | ||
+ $cipher = $dictionary[$this->_driver][$cipher]; | ||
+ } | ||
+ } | ||
+ | ||
+ // -------------------------------------------------------------------- | ||
+ | ||
+ /** | ||
+ * HKDF | ||
+ * | ||
+ * @link https://tools.ietf.org/rfc/rfc5869.txt | ||
+ * @param $key Input key | ||
+ * @param $digest A SHA-2 hashing algorithm | ||
+ * @param $salt Optional salt | ||
+ * @param $length Output length (defaults to the selected digest size) | ||
+ * @param $info Optional context/application-specific info | ||
+ * @return string A pseudo-random key | ||
+ */ | ||
+ public function hkdf($key, $digest = 'sha512', $salt = NULL, $length = NULL, $info = '') | ||
+ { | ||
+ if ( ! isset($this->_digests[$digest])) | ||
+ { | ||
+ return FALSE; | ||
+ } | ||
+ | ||
+ if (empty($length) OR ! is_int($length)) | ||
+ { | ||
+ $length = $this->_digests[$digest]; | ||
+ } | ||
+ elseif ($length > (255 * $this->_digests[$digest])) | ||
+ { | ||
+ return FALSE; | ||
+ } | ||
+ | ||
+ self::strlen($salt) OR $salt = str_repeat("\0", $this->_digests[$digest]); | ||
+ | ||
+ $prk = hash_hmac($digest, $key, $salt, TRUE); | ||
+ $key = ''; | ||
+ for ($key_block = '', $block_index = 1; self::strlen($key) < $length; $block_index++) | ||
+ { | ||
+ $key_block = hash_hmac($digest, $key_block.$info.chr($block_index), $prk, TRUE); | ||
+ $key .= $key_block; | ||
+ } | ||
+ | ||
+ return self::substr($key, 0, $length); | ||
+ } | ||
+ | ||
+ // -------------------------------------------------------------------- | ||
+ | ||
+ /** | ||
+ * __get() magic | ||
+ * | ||
+ * @param string $key Property name | ||
+ * @return mixed | ||
+ */ | ||
+ public function __get($key) | ||
+ { | ||
+ // Because aliases | ||
+ if ($key === 'mode') | ||
+ { | ||
+ return array_search($this->_mode, $this->_modes[$this->_driver], TRUE); | ||
+ } | ||
+ elseif (in_array($key, array('cipher', 'driver', 'drivers', 'digests'), TRUE)) | ||
+ { | ||
+ return $this->{'_'.$key}; | ||
+ } | ||
+ | ||
+ return NULL; | ||
+ } | ||
+ | ||
+ // -------------------------------------------------------------------- | ||
+ | ||
+ /** | ||
+ * Byte-safe strlen() | ||
+ * | ||
+ * @param string $str | ||
+ * @return integer | ||
+ */ | ||
+ protected static function strlen($str) | ||
+ { | ||
+ return (self::$func_override) | ||
+ ? mb_strlen($str, '8bit') | ||
+ : strlen($str); | ||
+ } | ||
+ | ||
+ // -------------------------------------------------------------------- | ||
+ | ||
+ /** | ||
+ * Byte-safe substr() | ||
+ * | ||
+ * @param string $str | ||
+ * @param int $start | ||
+ * @param int $length | ||
+ * @return string | ||
+ */ | ||
+ protected static function substr($str, $start, $length = NULL) | ||
+ { | ||
+ if (self::$func_override) | ||
+ { | ||
+ // mb_substr($str, $start, null, '8bit') returns an empty | ||
+ // string on PHP 5.3 | ||
+ isset($length) OR $length = ($start >= 0 ? self::strlen($str) - $start : -$start); | ||
+ return mb_substr($str, $start, $length, '8bit'); | ||
+ } | ||
+ | ||
+ return isset($length) | ||
+ ? substr($str, $start, $length) | ||
+ : substr($str, $start); | ||
+ } | ||
+} |
1,595
README/Form_validation.php
1,595 additions,
0 deletions
not shown because the diff is too large. Please use a local Git client to view these changes.
667
README/Ftp.php
@@ -0,0 +1,667 @@ | ||
+<?php | ||
+/** | ||
+ * CodeIgniter | ||
+ * | ||
+ * An open source application development framework for PHP | ||
+ * | ||
+ * This content is released under the MIT License (MIT) | ||
+ * | ||
+ * Copyright (c) 2014 - 2015, British Columbia Institute of Technology | ||
+ * | ||
+ * Permission is hereby granted, free of charge, to any person obtaining a copy | ||
+ * of this software and associated documentation files (the "Software"), to deal | ||
+ * in the Software without restriction, including without limitation the rights | ||
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | ||
+ * copies of the Software, and to permit persons to whom the Software is | ||
+ * furnished to do so, subject to the following conditions: | ||
+ * | ||
+ * The above copyright notice and this permission notice shall be included in | ||
+ * all copies or substantial portions of the Software. | ||
+ * | ||
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | ||
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | ||
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN | ||
+ * THE SOFTWARE. | ||
+ * | ||
+ * @package CodeIgniter | ||
+ * @author EllisLab Dev Team | ||
+ * @copyright Copyright (c) 2008 - 2014, EllisLab, Inc. (http://ellislab.com/) | ||
+ * @copyright Copyright (c) 2014 - 2015, British Columbia Institute of Technology (http://bcit.ca/) | ||
+ * @license http://opensource.org/licenses/MIT MIT License | ||
+ * @link http://codeigniter.com | ||
+ * @since Version 1.0.0 | ||
+ * @filesource | ||
+ */ | ||
+defined('BASEPATH') OR exit('No direct script access allowed'); | ||
+ | ||
+/** | ||
+ * FTP Class | ||
+ * | ||
+ * @package CodeIgniter | ||
+ * @subpackage Libraries | ||
+ * @category Libraries | ||
+ * @author EllisLab Dev Team | ||
+ * @link http://codeigniter.com/user_guide/libraries/ftp.html | ||
+ */ | ||
+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 ID | ||
+ * | ||
+ * @var resource | ||
+ */ | ||
+ protected $conn_id; | ||
+ | ||
+ // -------------------------------------------------------------------- | ||
+ | ||
+ /** | ||
+ * Constructor | ||
+ * | ||
+ * @param array $config | ||
+ * @return void | ||
+ */ | ||
+ public function __construct($config = array()) | ||
+ { | ||
+ empty($config) OR $this->initialize($config); | ||
+ log_message('info', 'FTP Class Initialized'); | ||
+ } | ||
+ | ||
+ // -------------------------------------------------------------------- | ||
+ | ||
+ /** | ||
+ * Initialize preferences | ||
+ * | ||
+ * @param array $config | ||
+ * @return void | ||
+ */ | ||
+ public function initialize($config = array()) | ||
+ { | ||
+ foreach ($config as $key => $val) | ||
+ { | ||
+ if (isset($this->$key)) | ||
+ { | ||
+ $this->$key = $val; | ||
+ } | ||
+ } | ||
+ | ||
+ // Prep the hostname | ||
+ $this->hostname = preg_replace('|.+?://|', '', $this->hostname); | ||
+ } | ||
+ | ||
+ // -------------------------------------------------------------------- | ||
+ | ||
+ /** | ||
+ * FTP Connect | ||
+ * | ||
+ * @param array $config Connection values | ||
+ * @return bool | ||
+ */ | ||
+ public function connect($config = array()) | ||
+ { | ||
+ if (count($config) > 0) | ||
+ { | ||
+ $this->initialize($config); | ||
+ } | ||
+ | ||
+ if (FALSE === ($this->conn_id = @ftp_connect($this->hostname, $this->port))) | ||
+ { | ||
+ if ($this->debug === TRUE) | ||
+ { | ||
+ $this->_error('ftp_unable_to_connect'); | ||
+ } | ||
+ | ||
+ return FALSE; | ||
+ } | ||
+ | ||
+ if ( ! $this->_login()) | ||
+ { | ||
+ if ($this->debug === TRUE) | ||
+ { | ||
+ $this->_error('ftp_unable_to_login'); | ||
+ } | ||
+ | ||
+ return FALSE; | ||
+ } | ||
+ | ||
+ // Set passive mode if needed | ||
+ if ($this->passive === TRUE) | ||
+ { | ||
+ ftp_pasv($this->conn_id, TRUE); | ||
+ } | ||
+ | ||
+ return TRUE; | ||
+ } | ||
+ | ||
+ // -------------------------------------------------------------------- | ||
+ | ||
+ /** | ||
+ * FTP Login | ||
+ * | ||
+ * @return bool | ||
+ */ | ||
+ protected function _login() | ||
+ { | ||
+ return @ftp_login($this->conn_id, $this->username, $this->password); | ||
+ } | ||
+ | ||
+ // -------------------------------------------------------------------- | ||
+ | ||
+ /** | ||
+ * Validates the connection ID | ||
+ * | ||
+ * @return bool | ||
+ */ | ||
+ protected function _is_conn() | ||
+ { | ||
+ if ( ! is_resource($this->conn_id)) | ||
+ { | ||
+ if ($this->debug === TRUE) | ||
+ { | ||
+ $this->_error('ftp_no_connection'); | ||
+ } | ||
+ | ||
+ return FALSE; | ||
+ } | ||
+ | ||
+ return TRUE; | ||
+ } | ||
+ | ||
+ // -------------------------------------------------------------------- | ||
+ | ||
+ /** | ||
+ * Change directory | ||
+ * | ||
+ * The second parameter lets us momentarily turn off debugging so that | ||
+ * this function can be used to test for the existence of a folder | ||
+ * without throwing an error. There's no FTP equivalent to is_dir() | ||
+ * 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 $path | ||
+ * @param bool $suppress_debug | ||
+ * @return bool | ||
+ */ | ||
+ public function changedir($path, $suppress_debug = FALSE) | ||
+ { | ||
+ if ( ! $this->_is_conn()) | ||
+ { | ||
+ return FALSE; | ||
+ } | ||
+ | ||
+ $result = @ftp_chdir($this->conn_id, $path); | ||
+ | ||
+ if ($result === FALSE) | ||
+ { | ||
+ if ($this->debug === TRUE && $suppress_debug === FALSE) | ||
+ { | ||
+ $this->_error('ftp_unable_to_changedir'); | ||
+ } | ||
+ | ||
+ return FALSE; | ||
+ } | ||
+ | ||
+ return TRUE; | ||
+ } | ||
+ | ||
+ // -------------------------------------------------------------------- | ||
+ | ||
+ /** | ||
+ * Create a directory | ||
+ * | ||
+ * @param string $path | ||
+ * @param int $permissions | ||
+ * @return bool | ||
+ */ | ||
+ public function mkdir($path, $permissions = NULL) | ||
+ { | ||
+ if ($path === '' OR ! $this->_is_conn()) | ||
+ { | ||
+ return FALSE; | ||
+ } | ||
+ | ||
+ $result = @ftp_mkdir($this->conn_id, $path); | ||
+ | ||
+ if ($result === FALSE) | ||
+ { | ||
+ if ($this->debug === TRUE) | ||
+ { | ||
+ $this->_error('ftp_unable_to_mkdir'); | ||
+ } | ||
+ | ||
+ return FALSE; | ||
+ } | ||
+ | ||
+ // Set file permissions if needed | ||
+ if ($permissions !== NULL) | ||
+ { | ||
+ $this->chmod($path, (int) $permissions); | ||
+ } | ||
+ | ||
+ return TRUE; | ||
+ } | ||
+ | ||
+ // -------------------------------------------------------------------- | ||
+ | ||
+ /** | ||
+ * Upload a file to the server | ||
+ * | ||
+ * @param string $locpath | ||
+ * @param string $rempath | ||
+ * @param string $mode | ||
+ * @param int $permissions | ||
+ * @return bool | ||
+ */ | ||
+ public function upload($locpath, $rempath, $mode = 'auto', $permissions = NULL) | ||
+ { | ||
+ if ( ! $this->_is_conn()) | ||
+ { | ||
+ return FALSE; | ||
+ } | ||
+ | ||
+ if ( ! file_exists($locpath)) | ||
+ { | ||
+ $this->_error('ftp_no_source_file'); | ||
+ return FALSE; | ||
+ } | ||
+ | ||
+ // Set the mode if not specified | ||
+ if ($mode === 'auto') | ||
+ { | ||
+ // Get the file extension so we can set the upload type | ||
+ $ext = $this->_getext($locpath); | ||
+ $mode = $this->_settype($ext); | ||
+ } | ||
+ | ||
+ $mode = ($mode === 'ascii') ? FTP_ASCII : FTP_BINARY; | ||
+ | ||
+ $result = @ftp_put($this->conn_id, $rempath, $locpath, $mode); | ||
+ | ||
+ if ($result === FALSE) | ||
+ { | ||
+ if ($this->debug === TRUE) | ||
+ { | ||
+ $this->_error('ftp_unable_to_upload'); | ||
+ } | ||
+ | ||
+ return FALSE; | ||
+ } | ||
+ | ||
+ // Set file permissions if needed | ||
+ if ($permissions !== NULL) | ||
+ { | ||
+ $this->chmod($rempath, (int) $permissions); | ||
+ } | ||
+ | ||
+ return TRUE; | ||
+ } | ||
+ | ||
+ // -------------------------------------------------------------------- | ||
+ | ||
+ /** | ||
+ * Download a file from a remote server to the local server | ||
+ * | ||
+ * @param string $rempath | ||
+ * @param string $locpath | ||
+ * @param string $mode | ||
+ * @return bool | ||
+ */ | ||
+ public function download($rempath, $locpath, $mode = 'auto') | ||
+ { | ||
+ if ( ! $this->_is_conn()) | ||
+ { | ||
+ return FALSE; | ||
+ } | ||
+ | ||
+ // Set the mode if not specified | ||
+ if ($mode === 'auto') | ||
+ { | ||
+ // Get the file extension so we can set the upload type | ||
+ $ext = $this->_getext($rempath); | ||
+ $mode = $this->_settype($ext); | ||
+ } | ||
+ | ||
+ $mode = ($mode === 'ascii') ? FTP_ASCII : FTP_BINARY; | ||
+ | ||
+ $result = @ftp_get($this->conn_id, $locpath, $rempath, $mode); | ||
+ | ||
+ if ($result === FALSE) | ||
+ { | ||
+ if ($this->debug === TRUE) | ||
+ { | ||
+ $this->_error('ftp_unable_to_download'); | ||
+ } | ||
+ | ||
+ return FALSE; | ||
+ } | ||
+ | ||
+ return TRUE; | ||
+ } | ||
+ | ||
+ // -------------------------------------------------------------------- | ||
+ | ||
+ /** | ||
+ * Rename (or move) a file | ||
+ * | ||
+ * @param string $old_file | ||
+ * @param string $new_file | ||
+ * @param bool $move | ||
+ * @return bool | ||
+ */ | ||
+ public function rename($old_file, $new_file, $move = FALSE) | ||
+ { | ||
+ if ( ! $this->_is_conn()) | ||
+ { | ||
+ return FALSE; | ||
+ } | ||
+ | ||
+ $result = @ftp_rename($this->conn_id, $old_file, $new_file); | ||
+ | ||
+ if ($result === FALSE) | ||
+ { | ||
+ if ($this->debug === TRUE) | ||
+ { | ||
+ $this->_error('ftp_unable_to_'.($move === FALSE ? 'rename' : 'move')); | ||
+ } | ||
+ | ||
+ return FALSE; | ||
+ } | ||
+ | ||
+ return TRUE; | ||
+ } | ||
+ | ||
+ // -------------------------------------------------------------------- | ||
+ | ||
+ /** | ||
+ * Move a file | ||
+ * | ||
+ * @param string $old_file | ||
+ * @param string $new_file | ||
+ * @return bool | ||
+ */ | ||
+ public function move($old_file, $new_file) | ||
+ { | ||
+ return $this->rename($old_file, $new_file, TRUE); | ||
+ } | ||
+ | ||
+ // -------------------------------------------------------------------- | ||
+ | ||
+ /** | ||
+ * Rename (or move) a file | ||
+ * | ||
+ * @param string $filepath | ||
+ * @return bool | ||
+ */ | ||
+ public function delete_file($filepath) | ||
+ { | ||
+ if ( ! $this->_is_conn()) | ||
+ { | ||
+ return FALSE; | ||
+ } | ||
+ | ||
+ $result = @ftp_delete($this->conn_id, $filepath); | ||
+ | ||
+ if ($result === FALSE) | ||
+ { | ||
+ if ($this->debug === TRUE) | ||
+ { | ||
+ $this->_error('ftp_unable_to_delete'); | ||
+ } | ||
+ | ||
+ return FALSE; | ||
+ } | ||
+ | ||
+ return TRUE; | ||
+ } | ||
+ | ||
+ // -------------------------------------------------------------------- | ||
+ | ||
+ /** | ||
+ * Delete a folder and recursively delete everything (including sub-folders) | ||
+ * contained within it. | ||
+ * | ||
+ * @param string $filepath | ||
+ * @return bool | ||
+ */ | ||
+ public function delete_dir($filepath) | ||
+ { | ||
+ if ( ! $this->_is_conn()) | ||
+ { | ||
+ return FALSE; | ||
+ } | ||
+ | ||
+ // Add a trailing slash to the file path if needed | ||
+ $filepath = preg_replace('/(.+?)\/*$/', '\\1/', $filepath); | ||
+ | ||
+ $list = $this->list_files($filepath); | ||
+ if ( ! empty($list)) | ||
+ { | ||
+ for ($i = 0, $c = count($list); $i < $c; $i++) | ||
+ { | ||
+ // If we can't delete the item it's probaly a directory, | ||
+ // so we'll recursively call delete_dir() | ||
+ if ( ! preg_match('#/\.\.?$#', $list[$i]) && ! @ftp_delete($this->conn_id, $list[$i])) | ||
+ { | ||
+ $this->delete_dir($filepath.$list[$i]); | ||
+ } | ||
+ } | ||
+ } | ||
+ | ||
+ if (@ftp_rmdir($this->conn_id, $filepath) === FALSE) | ||
+ { | ||
+ if ($this->debug === TRUE) | ||
+ { | ||
+ $this->_error('ftp_unable_to_delete'); | ||
+ } | ||
+ | ||
+ return FALSE; | ||
+ } | ||
+ | ||
+ return TRUE; | ||
+ } | ||
+ | ||
+ // -------------------------------------------------------------------- | ||
+ | ||
+ /** | ||
+ * Set file permissions | ||
+ * | ||
+ * @param string $path File path | ||
+ * @param int $perm Permissions | ||
+ * @return bool | ||
+ */ | ||
+ public function chmod($path, $perm) | ||
+ { | ||
+ if ( ! $this->_is_conn()) | ||
+ { | ||
+ return FALSE; | ||
+ } | ||
+ | ||
+ if (@ftp_chmod($this->conn_id, $perm, $path) === FALSE) | ||
+ { | ||
+ if ($this->debug === TRUE) | ||
+ { | ||
+ $this->_error('ftp_unable_to_chmod'); | ||
+ } | ||
+ | ||
+ return FALSE; | ||
+ } | ||
+ | ||
+ return TRUE; | ||
+ } | ||
+ | ||
+ // -------------------------------------------------------------------- | ||
+ | ||
+ /** | ||
+ * FTP List files in the specified directory | ||
+ * | ||
+ * @param string $path | ||
+ * @return array | ||
+ */ | ||
+ public function list_files($path = '.') | ||
+ { | ||
+ return $this->_is_conn() | ||
+ ? ftp_nlist($this->conn_id, $path) | ||
+ : FALSE; | ||
+ } | ||
+ | ||
+ // ------------------------------------------------------------------------ | ||
+ | ||
+ /** | ||
+ * Read a directory and recreate it remotely | ||
+ * | ||
+ * This function recursively reads a folder and everything it contains | ||
+ * (including sub-folders) and creates a mirror via FTP based on it. | ||
+ * Whatever the directory structure of the original file path will be | ||
+ * recreated on the server. | ||
+ * | ||
+ * @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) | ||
+ { | ||
+ if ( ! $this->_is_conn()) | ||
+ { | ||
+ return FALSE; | ||
+ } | ||
+ | ||
+ // Open the local file path | ||
+ if ($fp = @opendir($locpath)) | ||
+ { | ||
+ // Attempt to open the remote file path and try to create it, if it doesn't exist | ||
+ if ( ! $this->changedir($rempath, TRUE) && ( ! $this->mkdir($rempath) OR ! $this->changedir($rempath))) | ||
+ { | ||
+ return FALSE; | ||
+ } | ||
+ | ||
+ // Recursively read the local directory | ||
+ while (FALSE !== ($file = readdir($fp))) | ||
+ { | ||
+ if (is_dir($locpath.$file) && $file[0] !== '.') | ||
+ { | ||
+ $this->mirror($locpath.$file.'/', $rempath.$file.'/'); | ||
+ } | ||
+ elseif ($file[0] !== '.') | ||
+ { | ||
+ // Get the file extension so we can se the upload type | ||
+ $ext = $this->_getext($file); | ||
+ $mode = $this->_settype($ext); | ||
+ | ||
+ $this->upload($locpath.$file, $rempath.$file, $mode); | ||
+ } | ||
+ } | ||
+ | ||
+ return TRUE; | ||
+ } | ||
+ | ||
+ return FALSE; | ||
+ } | ||
+ | ||
+ // -------------------------------------------------------------------- | ||
+ | ||
+ /** | ||
+ * Extract the file extension | ||
+ * | ||
+ * @param string $filename | ||
+ * @return string | ||
+ */ | ||
+ protected function _getext($filename) | ||
+ { | ||
+ return (($dot = strrpos($filename, '.')) === FALSE) | ||
+ ? 'txt' | ||
+ : substr($filename, $dot + 1); | ||
+ } | ||
+ | ||
+ // -------------------------------------------------------------------- | ||
+ | ||
+ /** | ||
+ * Set the upload type | ||
+ * | ||
+ * @param string $ext Filename extension | ||
+ * @return string | ||
+ */ | ||
+ protected function _settype($ext) | ||
+ { | ||
+ return in_array($ext, array('txt', 'text', 'php', 'phps', 'php4', 'js', 'css', 'htm', 'html', 'phtml', 'shtml', 'log', 'xml'), TRUE) | ||
+ ? 'ascii' | ||
+ : 'binary'; | ||
+ } | ||
+ | ||
+ // ------------------------------------------------------------------------ | ||
+ | ||
+ /** | ||
+ * Close the connection | ||
+ * | ||
+ * @return bool | ||
+ */ | ||
+ public function close() | ||
+ { | ||
+ return $this->_is_conn() | ||
+ ? @ftp_close($this->conn_id) | ||
+ : FALSE; | ||
+ } | ||
+ | ||
+ // ------------------------------------------------------------------------ | ||
+ | ||
+ /** | ||
+ * Display error message | ||
+ * | ||
+ * @param string $line | ||
+ * @return void | ||
+ */ | ||
+ protected function _error($line) | ||
+ { | ||
+ $CI =& get_instance(); | ||
+ $CI->lang->load('ftp'); | ||
+ show_error($CI->lang->line($line)); | ||
+ } | ||
+ | ||
+} |
1,825
README/Image_lib.php
1,825 additions,
0 deletions
not shown because the diff is too large. Please use a local Git client to view these changes.
856
README/Javascript.php
@@ -0,0 +1,856 @@ | ||
+<?php | ||
+/** | ||
+ * CodeIgniter | ||
+ * | ||
+ * An open source application development framework for PHP | ||
+ * | ||
+ * This content is released under the MIT License (MIT) | ||
+ * | ||
+ * Copyright (c) 2014 - 2015, British Columbia Institute of Technology | ||
+ * | ||
+ * Permission is hereby granted, free of charge, to any person obtaining a copy | ||
+ * of this software and associated documentation files (the "Software"), to deal | ||
+ * in the Software without restriction, including without limitation the rights | ||
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | ||
+ * copies of the Software, and to permit persons to whom the Software is | ||
+ * furnished to do so, subject to the following conditions: | ||
+ * | ||
+ * The above copyright notice and this permission notice shall be included in | ||
+ * all copies or substantial portions of the Software. | ||
+ * | ||
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | ||
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | ||
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN | ||
+ * THE SOFTWARE. | ||
+ * | ||
+ * @package CodeIgniter | ||
+ * @author EllisLab Dev Team | ||
+ * @copyright Copyright (c) 2008 - 2014, EllisLab, Inc. (http://ellislab.com/) | ||
+ * @copyright Copyright (c) 2014 - 2015, British Columbia Institute of Technology (http://bcit.ca/) | ||
+ * @license http://opensource.org/licenses/MIT MIT License | ||
+ * @link http://codeigniter.com | ||
+ * @since Version 1.0.0 | ||
+ * @filesource | ||
+ */ | ||
+defined('BASEPATH') OR exit('No direct script access allowed'); | ||
+ | ||
+/** | ||
+ * Javascript Class | ||
+ * | ||
+ * @package CodeIgniter | ||
+ * @subpackage Libraries | ||
+ * @category Javascript | ||
+ * @author EllisLab Dev Team | ||
+ * @link http://codeigniter.com/user_guide/libraries/javascript.html | ||
+ * @deprecated 3.0.0 This was never a good idea in the first place. | ||
+ */ | ||
+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); | ||
+ | ||
+ foreach ($defaults as $key => $val) | ||
+ { | ||
+ if (isset($params[$key]) && $params[$key] !== '') | ||
+ { | ||
+ $defaults[$key] = $params[$key]; | ||
+ } | ||
+ } | ||
+ | ||
+ extract($defaults); | ||
+ | ||
+ $this->CI =& get_instance(); | ||
+ | ||
+ // load the requested js library | ||
+ $this->CI->load->library('Javascript/'.$js_library_driver, array('autoload' => $autoload)); | ||
+ // make js to refer to current library | ||
+ $this->js =& $this->CI->$js_library_driver; | ||
+ | ||
+ log_message('info', 'Javascript Class Initialized and loaded. Driver used: '.$js_library_driver); | ||
+ } | ||
+ | ||
+ // -------------------------------------------------------------------- | ||
+ // Event Code | ||
+ // -------------------------------------------------------------------- | ||
+ | ||
+ /** | ||
+ * Blur | ||
+ * | ||
+ * Outputs a javascript library blur event | ||
+ * | ||
+ * @param string The element to attach the event to | ||
+ * @param string The code to execute | ||
+ * @return string | ||
+ */ | ||
+ public function blur($element = 'this', $js = '') | ||
+ { | ||
+ return $this->js->_blur($element, $js); | ||
+ } | ||
+ | ||
+ // -------------------------------------------------------------------- | ||
+ | ||
+ /** | ||
+ * Change | ||
+ * | ||
+ * Outputs a javascript library change event | ||
+ * | ||
+ * @param string The element to attach the event to | ||
+ * @param string The code to execute | ||
+ * @return string | ||
+ */ | ||
+ public function change($element = 'this', $js = '') | ||
+ { | ||
+ return $this->js->_change($element, $js); | ||
+ } | ||
+ | ||
+ // -------------------------------------------------------------------- | ||
+ | ||
+ /** | ||
+ * Click | ||
+ * | ||
+ * Outputs a javascript library click event | ||
+ * | ||
+ * @param string The element to attach the event to | ||
+ * @param string The code to execute | ||
+ * @param bool whether or not to return false | ||
+ * @return string | ||
+ */ | ||
+ public function click($element = 'this', $js = '', $ret_false = TRUE) | ||
+ { | ||
+ return $this->js->_click($element, $js, $ret_false); | ||
+ } | ||
+ | ||
+ // -------------------------------------------------------------------- | ||
+ | ||
+ /** | ||
+ * Double Click | ||
+ * | ||
+ * Outputs a javascript library dblclick event | ||
+ * | ||
+ * @param string The element to attach the event to | ||
+ * @param string The code to execute | ||
+ * @return string | ||
+ */ | ||
+ public function dblclick($element = 'this', $js = '') | ||
+ { | ||
+ return $this->js->_dblclick($element, $js); | ||
+ } | ||
+ | ||
+ // -------------------------------------------------------------------- | ||
+ | ||
+ /** | ||
+ * Error | ||
+ * | ||
+ * Outputs a javascript library error event | ||
+ * | ||
+ * @param string The element to attach the event to | ||
+ * @param string The code to execute | ||
+ * @return string | ||
+ */ | ||
+ public function error($element = 'this', $js = '') | ||
+ { | ||
+ return $this->js->_error($element, $js); | ||
+ } | ||
+ | ||
+ // -------------------------------------------------------------------- | ||
+ | ||
+ /** | ||
+ * Focus | ||
+ * | ||
+ * Outputs a javascript library focus event | ||
+ * | ||
+ * @param string The element to attach the event to | ||
+ * @param string The code to execute | ||
+ * @return string | ||
+ */ | ||
+ public function focus($element = 'this', $js = '') | ||
+ { | ||
+ return $this->js->_focus($element, $js); | ||
+ } | ||
+ | ||
+ // -------------------------------------------------------------------- | ||
+ | ||
+ /** | ||
+ * Hover | ||
+ * | ||
+ * Outputs a javascript library hover event | ||
+ * | ||
+ * @param string - element | ||
+ * @param string - Javascript code for mouse over | ||
+ * @param string - Javascript code for mouse out | ||
+ * @return string | ||
+ */ | ||
+ public function hover($element = 'this', $over = '', $out = '') | ||
+ { | ||
+ return $this->js->_hover($element, $over, $out); | ||
+ } | ||
+ | ||
+ // -------------------------------------------------------------------- | ||
+ | ||
+ /** | ||
+ * Keydown | ||
+ * | ||
+ * Outputs a javascript library keydown event | ||
+ * | ||
+ * @param string The element to attach the event to | ||
+ * @param string The code to execute | ||
+ * @return string | ||
+ */ | ||
+ public function keydown($element = 'this', $js = '') | ||
+ { | ||
+ return $this->js->_keydown($element, $js); | ||
+ } | ||
+ | ||
+ // -------------------------------------------------------------------- | ||
+ | ||
+ /** | ||
+ * Keyup | ||
+ * | ||
+ * Outputs a javascript library keydown event | ||
+ * | ||
+ * @param string The element to attach the event to | ||
+ * @param string The code to execute | ||
+ * @return string | ||
+ */ | ||
+ public function keyup($element = 'this', $js = '') | ||
+ { | ||
+ return $this->js->_keyup($element, $js); | ||
+ } | ||
+ | ||
+ // -------------------------------------------------------------------- | ||
+ | ||
+ /** | ||
+ * Load | ||
+ * | ||
+ * Outputs a javascript library load event | ||
+ * | ||
+ * @param string The element to attach the event to | ||
+ * @param string The code to execute | ||
+ * @return string | ||
+ */ | ||
+ public function load($element = 'this', $js = '') | ||
+ { | ||
+ return $this->js->_load($element, $js); | ||
+ } | ||
+ | ||
+ // -------------------------------------------------------------------- | ||
+ | ||
+ /** | ||
+ * Mousedown | ||
+ * | ||
+ * Outputs a javascript library mousedown event | ||
+ * | ||
+ * @param string The element to attach the event to | ||
+ * @param string The code to execute | ||
+ * @return string | ||
+ */ | ||
+ public function mousedown($element = 'this', $js = '') | ||
+ { | ||
+ return $this->js->_mousedown($element, $js); | ||
+ } | ||
+ | ||
+ // -------------------------------------------------------------------- | ||
+ | ||
+ /** | ||
+ * Mouse Out | ||
+ * | ||
+ * Outputs a javascript library mouseout event | ||
+ * | ||
+ * @param string The element to attach the event to | ||
+ * @param string The code to execute | ||
+ * @return string | ||
+ */ | ||
+ public function mouseout($element = 'this', $js = '') | ||
+ { | ||
+ return $this->js->_mouseout($element, $js); | ||
+ } | ||
+ | ||
+ // -------------------------------------------------------------------- | ||
+ | ||
+ /** | ||
+ * Mouse Over | ||
+ * | ||
+ * Outputs a javascript library mouseover event | ||
+ * | ||
+ * @param string The element to attach the event to | ||
+ * @param string The code to execute | ||
+ * @return string | ||
+ */ | ||
+ public function mouseover($element = 'this', $js = '') | ||
+ { | ||
+ return $this->js->_mouseover($element, $js); | ||
+ } | ||
+ | ||
+ // -------------------------------------------------------------------- | ||
+ | ||
+ /** | ||
+ * Mouseup | ||
+ * | ||
+ * Outputs a javascript library mouseup event | ||
+ * | ||
+ * @param string The element to attach the event to | ||
+ * @param string The code to execute | ||
+ * @return string | ||
+ */ | ||
+ public function mouseup($element = 'this', $js = '') | ||
+ { | ||
+ return $this->js->_mouseup($element, $js); | ||
+ } | ||
+ | ||
+ // -------------------------------------------------------------------- | ||
+ | ||
+ /** | ||
+ * Output | ||
+ * | ||
+ * Outputs the called javascript to the screen | ||
+ * | ||
+ * @param string The code to output | ||
+ * @return string | ||
+ */ | ||
+ public function output($js) | ||
+ { | ||
+ return $this->js->_output($js); | ||
+ } | ||
+ | ||
+ // -------------------------------------------------------------------- | ||
+ | ||
+ /** | ||
+ * Ready | ||
+ * | ||
+ * Outputs a javascript library mouseup event | ||
+ * | ||
+ * @param string $js Code to execute | ||
+ * @return string | ||
+ */ | ||
+ public function ready($js) | ||
+ { | ||
+ return $this->js->_document_ready($js); | ||
+ } | ||
+ | ||
+ // -------------------------------------------------------------------- | ||
+ | ||
+ /** | ||
+ * Resize | ||
+ * | ||
+ * Outputs a javascript library resize event | ||
+ * | ||
+ * @param string The element to attach the event to | ||
+ * @param string The code to execute | ||
+ * @return string | ||
+ */ | ||
+ public function resize($element = 'this', $js = '') | ||
+ { | ||
+ return $this->js->_resize($element, $js); | ||
+ } | ||
+ | ||
+ // -------------------------------------------------------------------- | ||
+ | ||
+ /** | ||
+ * Scroll | ||
+ * | ||
+ * Outputs a javascript library scroll event | ||
+ * | ||
+ * @param string The element to attach the event to | ||
+ * @param string The code to execute | ||
+ * @return string | ||
+ */ | ||
+ public function scroll($element = 'this', $js = '') | ||
+ { | ||
+ return $this->js->_scroll($element, $js); | ||
+ } | ||
+ | ||
+ // -------------------------------------------------------------------- | ||
+ | ||
+ /** | ||
+ * Unload | ||
+ * | ||
+ * Outputs a javascript library unload event | ||
+ * | ||
+ * @param string The element to attach the event to | ||
+ * @param string The code to execute | ||
+ * @return string | ||
+ */ | ||
+ public function unload($element = 'this', $js = '') | ||
+ { | ||
+ return $this->js->_unload($element, $js); | ||
+ } | ||
+ | ||
+ // -------------------------------------------------------------------- | ||
+ // Effects | ||
+ // -------------------------------------------------------------------- | ||
+ | ||
+ /** | ||
+ * Add Class | ||
+ * | ||
+ * Outputs a javascript library addClass event | ||
+ * | ||
+ * @param string - element | ||
+ * @param string - Class to add | ||
+ * @return string | ||
+ */ | ||
+ public function addClass($element = 'this', $class = '') | ||
+ { | ||
+ return $this->js->_addClass($element, $class); | ||
+ } | ||
+ | ||
+ // -------------------------------------------------------------------- | ||
+ | ||
+ /** | ||
+ * Animate | ||
+ * | ||
+ * Outputs a javascript library animate event | ||
+ * | ||
+ * @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 = '') | ||
+ { | ||
+ return $this->js->_animate($element, $params, $speed, $extra); | ||
+ } | ||
+ | ||
+ // -------------------------------------------------------------------- | ||
+ | ||
+ /** | ||
+ * Fade In | ||
+ * | ||
+ * Outputs a javascript library hide event | ||
+ * | ||
+ * @param string - element | ||
+ * @param string - One of 'slow', 'normal', 'fast', or time in milliseconds | ||
+ * @param string - Javascript callback function | ||
+ * @return string | ||
+ */ | ||
+ public function fadeIn($element = 'this', $speed = '', $callback = '') | ||
+ { | ||
+ return $this->js->_fadeIn($element, $speed, $callback); | ||
+ } | ||
+ | ||
+ // -------------------------------------------------------------------- | ||
+ | ||
+ /** | ||
+ * Fade Out | ||
+ * | ||
+ * Outputs a javascript library hide event | ||
+ * | ||
+ * @param string - element | ||
+ * @param string - One of 'slow', 'normal', 'fast', or time in milliseconds | ||
+ * @param string - Javascript callback function | ||
+ * @return string | ||
+ */ | ||
+ public function fadeOut($element = 'this', $speed = '', $callback = '') | ||
+ { | ||
+ return $this->js->_fadeOut($element, $speed, $callback); | ||
+ } | ||
+ // -------------------------------------------------------------------- | ||
+ | ||
+ /** | ||
+ * Slide Up | ||
+ * | ||
+ * Outputs a javascript library slideUp event | ||
+ * | ||
+ * @param string - element | ||
+ * @param string - One of 'slow', 'normal', 'fast', or time in milliseconds | ||
+ * @param string - Javascript callback function | ||
+ * @return string | ||
+ */ | ||
+ public function slideUp($element = 'this', $speed = '', $callback = '') | ||
+ { | ||
+ return $this->js->_slideUp($element, $speed, $callback); | ||
+ | ||
+ } | ||
+ | ||
+ // -------------------------------------------------------------------- | ||
+ | ||
+ /** | ||
+ * Remove Class | ||
+ * | ||
+ * Outputs a javascript library removeClass event | ||
+ * | ||
+ * @param string - element | ||
+ * @param string - Class to add | ||
+ * @return string | ||
+ */ | ||
+ public function removeClass($element = 'this', $class = '') | ||
+ { | ||
+ return $this->js->_removeClass($element, $class); | ||
+ } | ||
+ | ||
+ // -------------------------------------------------------------------- | ||
+ | ||
+ /** | ||
+ * Slide Down | ||
+ * | ||
+ * Outputs a javascript library slideDown event | ||
+ * | ||
+ * @param string - element | ||
+ * @param string - One of 'slow', 'normal', 'fast', or time in milliseconds | ||
+ * @param string - Javascript callback function | ||
+ * @return string | ||
+ */ | ||
+ public function slideDown($element = 'this', $speed = '', $callback = '') | ||
+ { | ||
+ return $this->js->_slideDown($element, $speed, $callback); | ||
+ } | ||
+ | ||
+ // -------------------------------------------------------------------- | ||
+ | ||
+ /** | ||
+ * Slide Toggle | ||
+ * | ||
+ * Outputs a javascript library slideToggle event | ||
+ * | ||
+ * @param string - element | ||
+ * @param string - One of 'slow', 'normal', 'fast', or time in milliseconds | ||
+ * @param string - Javascript callback function | ||
+ * @return string | ||
+ */ | ||
+ public function slideToggle($element = 'this', $speed = '', $callback = '') | ||
+ { | ||
+ return $this->js->_slideToggle($element, $speed, $callback); | ||
+ | ||
+ } | ||
+ | ||
+ // -------------------------------------------------------------------- | ||
+ | ||
+ /** | ||
+ * Hide | ||
+ * | ||
+ * Outputs a javascript library hide action | ||
+ * | ||
+ * @param string - element | ||
+ * @param string - One of 'slow', 'normal', 'fast', or time in milliseconds | ||
+ * @param string - Javascript callback function | ||
+ * @return string | ||
+ */ | ||
+ public function hide($element = 'this', $speed = '', $callback = '') | ||
+ { | ||
+ return $this->js->_hide($element, $speed, $callback); | ||
+ } | ||
+ | ||
+ // -------------------------------------------------------------------- | ||
+ | ||
+ /** | ||
+ * Toggle | ||
+ * | ||
+ * Outputs a javascript library toggle event | ||
+ * | ||
+ * @param string - element | ||
+ * @return string | ||
+ */ | ||
+ public function toggle($element = 'this') | ||
+ { | ||
+ return $this->js->_toggle($element); | ||
+ | ||
+ } | ||
+ | ||
+ // -------------------------------------------------------------------- | ||
+ | ||
+ /** | ||
+ * Toggle Class | ||
+ * | ||
+ * Outputs a javascript library toggle class event | ||
+ * | ||
+ * @param string $element = 'this' | ||
+ * @param string $class = '' | ||
+ * @return string | ||
+ */ | ||
+ public function toggleClass($element = 'this', $class = '') | ||
+ { | ||
+ return $this->js->_toggleClass($element, $class); | ||
+ } | ||
+ | ||
+ // -------------------------------------------------------------------- | ||
+ | ||
+ /** | ||
+ * Show | ||
+ * | ||
+ * Outputs a javascript library show event | ||
+ * | ||
+ * @param string - element | ||
+ * @param string - One of 'slow', 'normal', 'fast', or time in milliseconds | ||
+ * @param string - Javascript callback function | ||
+ * @return string | ||
+ */ | ||
+ public function show($element = 'this', $speed = '', $callback = '') | ||
+ { | ||
+ return $this->js->_show($element, $speed, $callback); | ||
+ } | ||
+ | ||
+ // -------------------------------------------------------------------- | ||
+ | ||
+ /** | ||
+ * Compile | ||
+ * | ||
+ * gather together all script needing to be output | ||
+ * | ||
+ * @param string $view_var | ||
+ * @param bool $script_tags | ||
+ * @return string | ||
+ */ | ||
+ public function compile($view_var = 'script_foot', $script_tags = TRUE) | ||
+ { | ||
+ $this->js->_compile($view_var, $script_tags); | ||
+ } | ||
+ | ||
+ // -------------------------------------------------------------------- | ||
+ | ||
+ /** | ||
+ * Clear Compile | ||
+ * | ||
+ * Clears any previous javascript collected for output | ||
+ * | ||
+ * @return void | ||
+ */ | ||
+ public function clear_compile() | ||
+ { | ||
+ $this->js->_clear_compile(); | ||
+ } | ||
+ | ||
+ // -------------------------------------------------------------------- | ||
+ | ||
+ /** | ||
+ * External | ||
+ * | ||
+ * Outputs a <script> tag with the source as an external js file | ||
+ * | ||
+ * @param string $external_file | ||
+ * @param bool $relative | ||
+ * @return string | ||
+ */ | ||
+ public function external($external_file = '', $relative = FALSE) | ||
+ { | ||
+ if ($external_file !== '') | ||
+ { | ||
+ $this->_javascript_location = $external_file; | ||
+ } | ||
+ elseif ($this->CI->config->item('javascript_location') !== '') | ||
+ { | ||
+ $this->_javascript_location = $this->CI->config->item('javascript_location'); | ||
+ } | ||
+ | ||
+ if ($relative === TRUE OR strpos($external_file, 'http://') === 0 OR strpos($external_file, 'https://') === 0) | ||
+ { | ||
+ $str = $this->_open_script($external_file); | ||
+ } | ||
+ elseif (strpos($this->_javascript_location, 'http://') !== FALSE) | ||
+ { | ||
+ $str = $this->_open_script($this->_javascript_location.$external_file); | ||
+ } | ||
+ else | ||
+ { | ||
+ $str = $this->_open_script($this->CI->config->slash_item('base_url').$this->_javascript_location.$external_file); | ||
+ } | ||
+ | ||
+ return $str.$this->_close_script(); | ||
+ } | ||
+ | ||
+ // -------------------------------------------------------------------- | ||
+ | ||
+ /** | ||
+ * Inline | ||
+ * | ||
+ * Outputs a <script> tag | ||
+ * | ||
+ * @param string The element to attach the event to | ||
+ * @param bool If a CDATA section should be added | ||
+ * @return string | ||
+ */ | ||
+ public function inline($script, $cdata = TRUE) | ||
+ { | ||
+ return $this->_open_script() | ||
+ . ($cdata ? "\n// <![CDATA[\n".$script."\n// ]]>\n" : "\n".$script."\n") | ||
+ . $this->_close_script(); | ||
+ } | ||
+ | ||
+ // -------------------------------------------------------------------- | ||
+ | ||
+ /** | ||
+ * Open Script | ||
+ * | ||
+ * Outputs an opening <script> | ||
+ * | ||
+ * @param string | ||
+ * @return string | ||
+ */ | ||
+ protected function _open_script($src = '') | ||
+ { | ||
+ return '<script type="text/javascript" charset="'.strtolower($this->CI->config->item('charset')).'"' | ||
+ .($src === '' ? '>' : ' src="'.$src.'">'); | ||
+ } | ||
+ | ||
+ // -------------------------------------------------------------------- | ||
+ | ||
+ /** | ||
+ * Close Script | ||
+ * | ||
+ * Outputs an closing </script> | ||
+ * | ||
+ * @param string | ||
+ * @return string | ||
+ */ | ||
+ protected function _close_script($extra = "\n") | ||
+ { | ||
+ return '</script>'.$extra; | ||
+ } | ||
+ | ||
+ // -------------------------------------------------------------------- | ||
+ // AJAX-Y STUFF - still a testbed | ||
+ // -------------------------------------------------------------------- | ||
+ | ||
+ /** | ||
+ * Update | ||
+ * | ||
+ * Outputs a javascript library slideDown event | ||
+ * | ||
+ * @param string - element | ||
+ * @param string - One of 'slow', 'normal', 'fast', or time in milliseconds | ||
+ * @param string - Javascript callback function | ||
+ * @return string | ||
+ */ | ||
+ public function update($element = 'this', $speed = '', $callback = '') | ||
+ { | ||
+ return $this->js->_updater($element, $speed, $callback); | ||
+ } | ||
+ | ||
+ // -------------------------------------------------------------------- | ||
+ | ||
+ /** | ||
+ * Generate JSON | ||
+ * | ||
+ * Can be passed a database result or associative array and returns a JSON formatted string | ||
+ * | ||
+ * @param mixed result set or array | ||
+ * @param bool match array types (defaults to objects) | ||
+ * @return string a json formatted string | ||
+ */ | ||
+ public function generate_json($result = NULL, $match_array_type = FALSE) | ||
+ { | ||
+ // JSON data can optionally be passed to this function | ||
+ // either as a database result object or an array, or a user supplied array | ||
+ if ($result !== NULL) | ||
+ { | ||
+ if (is_object($result)) | ||
+ { | ||
+ $json_result = is_callable(array($result, 'result_array')) ? $result->result_array() : (array) $result; | ||
+ } | ||
+ elseif (is_array($result)) | ||
+ { | ||
+ $json_result = $result; | ||
+ } | ||
+ else | ||
+ { | ||
+ return $this->_prep_args($result); | ||
+ } | ||
+ } | ||
+ else | ||
+ { | ||
+ return 'null'; | ||
+ } | ||
+ | ||
+ $json = array(); | ||
+ $_is_assoc = TRUE; | ||
+ | ||
+ if ( ! is_array($json_result) && empty($json_result)) | ||
+ { | ||
+ show_error('Generate JSON Failed - Illegal key, value pair.'); | ||
+ } | ||
+ elseif ($match_array_type) | ||
+ { | ||
+ $_is_assoc = $this->_is_associative_array($json_result); | ||
+ } | ||
+ | ||
+ foreach ($json_result as $k => $v) | ||
+ { | ||
+ if ($_is_assoc) | ||
+ { | ||
+ $json[] = $this->_prep_args($k, TRUE).':'.$this->generate_json($v, $match_array_type); | ||
+ } | ||
+ else | ||
+ { | ||
+ $json[] = $this->generate_json($v, $match_array_type); | ||
+ } | ||
+ } | ||
+ | ||
+ $json = implode(',', $json); | ||
+ | ||
+ return $_is_assoc ? '{'.$json.'}' : '['.$json.']'; | ||
+ | ||
+ } | ||
+ | ||
+ // -------------------------------------------------------------------- | ||
+ | ||
+ /** | ||
+ * Is associative array | ||
+ * | ||
+ * Checks for an associative array | ||
+ * | ||
+ * @param array | ||
+ * @return bool | ||
+ */ | ||
+ protected function _is_associative_array($arr) | ||
+ { | ||
+ foreach (array_keys($arr) as $key => $val) | ||
+ { | ||
+ if ($key !== $val) | ||
+ { | ||
+ return TRUE; | ||
+ } | ||
+ } | ||
+ | ||
+ return FALSE; | ||
+ } | ||
+ | ||
+ // -------------------------------------------------------------------- | ||
+ | ||
+ /** | ||
+ * Prep Args | ||
+ * | ||
+ * Ensures a standard json value and escapes values | ||
+ * | ||
+ * @param mixed $result | ||
+ * @param bool $is_key = FALSE | ||
+ * @return string | ||
+ */ | ||
+ protected function _prep_args($result, $is_key = FALSE) | ||
+ { | ||
+ if ($result === NULL) | ||
+ { | ||
+ return 'null'; | ||
+ } | ||
+ elseif (is_bool($result)) | ||
+ { | ||
+ return ($result === TRUE) ? 'true' : 'false'; | ||
+ } | ||
+ elseif (is_string($result) OR $is_key) | ||
+ { | ||
+ return '"'.str_replace(array('\\', "\t", "\n", "\r", '"', '/'), array('\\\\', '\\t', '\\n', "\\r", '\"', '\/'), $result).'"'; | ||
+ } | ||
+ elseif (is_scalar($result)) | ||
+ { | ||
+ return $result; | ||
+ } | ||
+ } | ||
+ | ||
+} |
1,076
README/Javascript/Jquery.php
@@ -0,0 +1,1076 @@ | ||
+<?php | ||
+/** | ||
+ * CodeIgniter | ||
+ * | ||
+ * An open source application development framework for PHP | ||
+ * | ||
+ * This content is released under the MIT License (MIT) | ||
+ * | ||
+ * Copyright (c) 2014 - 2015, British Columbia Institute of Technology | ||
+ * | ||
+ * Permission is hereby granted, free of charge, to any person obtaining a copy | ||
+ * of this software and associated documentation files (the "Software"), to deal | ||
+ * in the Software without restriction, including without limitation the rights | ||
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | ||
+ * copies of the Software, and to permit persons to whom the Software is | ||
+ * furnished to do so, subject to the following conditions: | ||
+ * | ||
+ * The above copyright notice and this permission notice shall be included in | ||
+ * all copies or substantial portions of the Software. | ||
+ * | ||
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | ||
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | ||
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN | ||
+ * THE SOFTWARE. | ||
+ * | ||
+ * @package CodeIgniter | ||
+ * @author EllisLab Dev Team | ||
+ * @copyright Copyright (c) 2008 - 2014, EllisLab, Inc. (http://ellislab.com/) | ||
+ * @copyright Copyright (c) 2014 - 2015, British Columbia Institute of Technology (http://bcit.ca/) | ||
+ * @license http://opensource.org/licenses/MIT MIT License | ||
+ * @link http://codeigniter.com | ||
+ * @since Version 1.0.0 | ||
+ * @filesource | ||
+ */ | ||
+defined('BASEPATH') OR exit('No direct script access allowed'); | ||
+ | ||
+/** | ||
+ * Jquery Class | ||
+ * | ||
+ * @package CodeIgniter | ||
+ * @subpackage Libraries | ||
+ * @category Loader | ||
+ * @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 sorter 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(); | ||
+ extract($params); | ||
+ | ||
+ if ($autoload === TRUE) | ||
+ { | ||
+ $this->script(); | ||
+ } | ||
+ | ||
+ log_message('info', 'Jquery Class Initialized'); | ||
+ } | ||
+ | ||
+ // -------------------------------------------------------------------- | ||
+ // Event Code | ||
+ // -------------------------------------------------------------------- | ||
+ | ||
+ /** | ||
+ * Blur | ||
+ * | ||
+ * Outputs a jQuery blur event | ||
+ * | ||
+ * @param string The element to attach the event to | ||
+ * @param string The code to execute | ||
+ * @return string | ||
+ */ | ||
+ protected function _blur($element = 'this', $js = '') | ||
+ { | ||
+ return $this->_add_event($element, $js, 'blur'); | ||
+ } | ||
+ | ||
+ // -------------------------------------------------------------------- | ||
+ | ||
+ /** | ||
+ * Change | ||
+ * | ||
+ * Outputs a jQuery change event | ||
+ * | ||
+ * @param string The element to attach the event to | ||
+ * @param string The code to execute | ||
+ * @return string | ||
+ */ | ||
+ protected function _change($element = 'this', $js = '') | ||
+ { | ||
+ return $this->_add_event($element, $js, 'change'); | ||
+ } | ||
+ | ||
+ // -------------------------------------------------------------------- | ||
+ | ||
+ /** | ||
+ * Click | ||
+ * | ||
+ * Outputs a jQuery click event | ||
+ * | ||
+ * @param string The element to attach the event to | ||
+ * @param string The code to execute | ||
+ * @param bool whether or not to return false | ||
+ * @return string | ||
+ */ | ||
+ protected function _click($element = 'this', $js = '', $ret_false = TRUE) | ||
+ { | ||
+ is_array($js) OR $js = array($js); | ||
+ | ||
+ if ($ret_false) | ||
+ { | ||
+ $js[] = 'return false;'; | ||
+ } | ||
+ | ||
+ return $this->_add_event($element, $js, 'click'); | ||
+ } | ||
+ | ||
+ // -------------------------------------------------------------------- | ||
+ | ||
+ /** | ||
+ * Double Click | ||
+ * | ||
+ * Outputs a jQuery dblclick event | ||
+ * | ||
+ * @param string The element to attach the event to | ||
+ * @param string The code to execute | ||
+ * @return string | ||
+ */ | ||
+ protected function _dblclick($element = 'this', $js = '') | ||
+ { | ||
+ return $this->_add_event($element, $js, 'dblclick'); | ||
+ } | ||
+ | ||
+ // -------------------------------------------------------------------- | ||
+ | ||
+ /** | ||
+ * Error | ||
+ * | ||
+ * Outputs a jQuery error event | ||
+ * | ||
+ * @param string The element to attach the event to | ||
+ * @param string The code to execute | ||
+ * @return string | ||
+ */ | ||
+ protected function _error($element = 'this', $js = '') | ||
+ { | ||
+ return $this->_add_event($element, $js, 'error'); | ||
+ } | ||
+ | ||
+ // -------------------------------------------------------------------- | ||
+ | ||
+ /** | ||
+ * Focus | ||
+ * | ||
+ * Outputs a jQuery focus event | ||
+ * | ||
+ * @param string The element to attach the event to | ||
+ * @param string The code to execute | ||
+ * @return string | ||
+ */ | ||
+ protected function _focus($element = 'this', $js = '') | ||
+ { | ||
+ return $this->_add_event($element, $js, 'focus'); | ||
+ } | ||
+ | ||
+ // -------------------------------------------------------------------- | ||
+ | ||
+ /** | ||
+ * Hover | ||
+ * | ||
+ * Outputs a jQuery hover event | ||
+ * | ||
+ * @param string - element | ||
+ * @param string - Javascript code for mouse over | ||
+ * @param string - Javascript code for mouse out | ||
+ * @return string | ||
+ */ | ||
+ protected function _hover($element = 'this', $over = '', $out = '') | ||
+ { | ||
+ $event = "\n\t$(".$this->_prep_element($element).").hover(\n\t\tfunction()\n\t\t{\n\t\t\t{$over}\n\t\t}, \n\t\tfunction()\n\t\t{\n\t\t\t{$out}\n\t\t});\n"; | ||
+ | ||
+ $this->jquery_code_for_compile[] = $event; | ||
+ | ||
+ return $event; | ||
+ } | ||
+ | ||
+ // -------------------------------------------------------------------- | ||
+ | ||
+ /** | ||
+ * Keydown | ||
+ * | ||
+ * Outputs a jQuery keydown event | ||
+ * | ||
+ * @param string The element to attach the event to | ||
+ * @param string The code to execute | ||
+ * @return string | ||
+ */ | ||
+ protected function _keydown($element = 'this', $js = '') | ||
+ { | ||
+ return $this->_add_event($element, $js, 'keydown'); | ||
+ } | ||
+ | ||
+ // -------------------------------------------------------------------- | ||
+ | ||
+ /** | ||
+ * Keyup | ||
+ * | ||
+ * Outputs a jQuery keydown event | ||
+ * | ||
+ * @param string The element to attach the event to | ||
+ * @param string The code to execute | ||
+ * @return string | ||
+ */ | ||
+ protected function _keyup($element = 'this', $js = '') | ||
+ { | ||
+ return $this->_add_event($element, $js, 'keyup'); | ||
+ } | ||
+ | ||
+ // -------------------------------------------------------------------- | ||
+ | ||
+ /** | ||
+ * Load | ||
+ * | ||
+ * Outputs a jQuery load event | ||
+ * | ||
+ * @param string The element to attach the event to | ||
+ * @param string The code to execute | ||
+ * @return string | ||
+ */ | ||
+ protected function _load($element = 'this', $js = '') | ||
+ { | ||
+ return $this->_add_event($element, $js, 'load'); | ||
+ } | ||
+ | ||
+ // -------------------------------------------------------------------- | ||
+ | ||
+ /** | ||
+ * Mousedown | ||
+ * | ||
+ * Outputs a jQuery mousedown event | ||
+ * | ||
+ * @param string The element to attach the event to | ||
+ * @param string The code to execute | ||
+ * @return string | ||
+ */ | ||
+ protected function _mousedown($element = 'this', $js = '') | ||
+ { | ||
+ return $this->_add_event($element, $js, 'mousedown'); | ||
+ } | ||
+ | ||
+ // -------------------------------------------------------------------- | ||
+ | ||
+ /** | ||
+ * Mouse Out | ||
+ * | ||
+ * Outputs a jQuery mouseout event | ||
+ * | ||
+ * @param string The element to attach the event to | ||
+ * @param string The code to execute | ||
+ * @return string | ||
+ */ | ||
+ protected function _mouseout($element = 'this', $js = '') | ||
+ { | ||
+ return $this->_add_event($element, $js, 'mouseout'); | ||
+ } | ||
+ | ||
+ // -------------------------------------------------------------------- | ||
+ | ||
+ /** | ||
+ * Mouse Over | ||
+ * | ||
+ * Outputs a jQuery mouseover event | ||
+ * | ||
+ * @param string The element to attach the event to | ||
+ * @param string The code to execute | ||
+ * @return string | ||
+ */ | ||
+ protected function _mouseover($element = 'this', $js = '') | ||
+ { | ||
+ return $this->_add_event($element, $js, 'mouseover'); | ||
+ } | ||
+ | ||
+ // -------------------------------------------------------------------- | ||
+ | ||
+ /** | ||
+ * Mouseup | ||
+ * | ||
+ * Outputs a jQuery mouseup event | ||
+ * | ||
+ * @param string The element to attach the event to | ||
+ * @param string The code to execute | ||
+ * @return string | ||
+ */ | ||
+ protected function _mouseup($element = 'this', $js = '') | ||
+ { | ||
+ return $this->_add_event($element, $js, 'mouseup'); | ||
+ } | ||
+ | ||
+ // -------------------------------------------------------------------- | ||
+ | ||
+ /** | ||
+ * Output | ||
+ * | ||
+ * Outputs script directly | ||
+ * | ||
+ * @param array $array_js = array() | ||
+ * @return void | ||
+ */ | ||
+ protected function _output($array_js = array()) | ||
+ { | ||
+ if ( ! is_array($array_js)) | ||
+ { | ||
+ $array_js = array($array_js); | ||
+ } | ||
+ | ||
+ foreach ($array_js as $js) | ||
+ { | ||
+ $this->jquery_code_for_compile[] = "\t".$js."\n"; | ||
+ } | ||
+ } | ||
+ | ||
+ // -------------------------------------------------------------------- | ||
+ | ||
+ /** | ||
+ * Resize | ||
+ * | ||
+ * Outputs a jQuery resize event | ||
+ * | ||
+ * @param string The element to attach the event to | ||
+ * @param string The code to execute | ||
+ * @return string | ||
+ */ | ||
+ protected function _resize($element = 'this', $js = '') | ||
+ { | ||
+ return $this->_add_event($element, $js, 'resize'); | ||
+ } | ||
+ | ||
+ // -------------------------------------------------------------------- | ||
+ | ||
+ /** | ||
+ * Scroll | ||
+ * | ||
+ * Outputs a jQuery scroll event | ||
+ * | ||
+ * @param string The element to attach the event to | ||
+ * @param string The code to execute | ||
+ * @return string | ||
+ */ | ||
+ protected function _scroll($element = 'this', $js = '') | ||
+ { | ||
+ return $this->_add_event($element, $js, 'scroll'); | ||
+ } | ||
+ | ||
+ // -------------------------------------------------------------------- | ||
+ | ||
+ /** | ||
+ * Unload | ||
+ * | ||
+ * Outputs a jQuery unload event | ||
+ * | ||
+ * @param string The element to attach the event to | ||
+ * @param string The code to execute | ||
+ * @return string | ||
+ */ | ||
+ protected function _unload($element = 'this', $js = '') | ||
+ { | ||
+ return $this->_add_event($element, $js, 'unload'); | ||
+ } | ||
+ | ||
+ // -------------------------------------------------------------------- | ||
+ // Effects | ||
+ // -------------------------------------------------------------------- | ||
+ | ||
+ /** | ||
+ * Add Class | ||
+ * | ||
+ * Outputs a jQuery addClass event | ||
+ * | ||
+ * @param string $element | ||
+ * @param string $class | ||
+ * @return string | ||
+ */ | ||
+ protected function _addClass($element = 'this', $class = '') | ||
+ { | ||
+ $element = $this->_prep_element($element); | ||
+ return '$('.$element.').addClass("'.$class.'");'; | ||
+ } | ||
+ | ||
+ // -------------------------------------------------------------------- | ||
+ | ||
+ /** | ||
+ * Animate | ||
+ * | ||
+ * Outputs a jQuery animate event | ||
+ * | ||
+ * @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 = '') | ||
+ { | ||
+ $element = $this->_prep_element($element); | ||
+ $speed = $this->_validate_speed($speed); | ||
+ | ||
+ $animations = "\t\t\t"; | ||
+ | ||
+ foreach ($params as $param => $value) | ||
+ { | ||
+ $animations .= $param.": '".$value."', "; | ||
+ } | ||
+ | ||
+ $animations = substr($animations, 0, -2); // remove the last ", " | ||
+ | ||
+ if ($speed !== '') | ||
+ { | ||
+ $speed = ', '.$speed; | ||
+ } | ||
+ | ||
+ if ($extra !== '') | ||
+ { | ||
+ $extra = ', '.$extra; | ||
+ } | ||
+ | ||
+ return "$({$element}).animate({\n$animations\n\t\t}".$speed.$extra.');'; | ||
+ } | ||
+ | ||
+ // -------------------------------------------------------------------- | ||
+ | ||
+ /** | ||
+ * Fade In | ||
+ * | ||
+ * Outputs a jQuery hide event | ||
+ * | ||
+ * @param string - element | ||
+ * @param string - One of 'slow', 'normal', 'fast', or time in milliseconds | ||
+ * @param string - Javascript callback function | ||
+ * @return string | ||
+ */ | ||
+ protected function _fadeIn($element = 'this', $speed = '', $callback = '') | ||
+ { | ||
+ $element = $this->_prep_element($element); | ||
+ $speed = $this->_validate_speed($speed); | ||
+ | ||
+ if ($callback !== '') | ||
+ { | ||
+ $callback = ", function(){\n{$callback}\n}"; | ||
+ } | ||
+ | ||
+ return "$({$element}).fadeIn({$speed}{$callback});"; | ||
+ } | ||
+ | ||
+ // -------------------------------------------------------------------- | ||
+ | ||
+ /** | ||
+ * Fade Out | ||
+ * | ||
+ * Outputs a jQuery hide event | ||
+ * | ||
+ * @param string - element | ||
+ * @param string - One of 'slow', 'normal', 'fast', or time in milliseconds | ||
+ * @param string - Javascript callback function | ||
+ * @return string | ||
+ */ | ||
+ protected function _fadeOut($element = 'this', $speed = '', $callback = '') | ||
+ { | ||
+ $element = $this->_prep_element($element); | ||
+ $speed = $this->_validate_speed($speed); | ||
+ | ||
+ if ($callback !== '') | ||
+ { | ||
+ $callback = ", function(){\n{$callback}\n}"; | ||
+ } | ||
+ | ||
+ return '$('.$element.').fadeOut('.$speed.$callback.');'; | ||
+ } | ||
+ | ||
+ // -------------------------------------------------------------------- | ||
+ | ||
+ /** | ||
+ * Hide | ||
+ * | ||
+ * Outputs a jQuery hide action | ||
+ * | ||
+ * @param string - element | ||
+ * @param string - One of 'slow', 'normal', 'fast', or time in milliseconds | ||
+ * @param string - Javascript callback function | ||
+ * @return string | ||
+ */ | ||
+ protected function _hide($element = 'this', $speed = '', $callback = '') | ||
+ { | ||
+ $element = $this->_prep_element($element); | ||
+ $speed = $this->_validate_speed($speed); | ||
+ | ||
+ if ($callback !== '') | ||
+ { | ||
+ $callback = ", function(){\n{$callback}\n}"; | ||
+ } | ||
+ | ||
+ return "$({$element}).hide({$speed}{$callback});"; | ||
+ } | ||
+ | ||
+ // -------------------------------------------------------------------- | ||
+ | ||
+ /** | ||
+ * Remove Class | ||
+ * | ||
+ * Outputs a jQuery remove class event | ||
+ * | ||
+ * @param string $element | ||
+ * @param string $class | ||
+ * @return string | ||
+ */ | ||
+ protected function _removeClass($element = 'this', $class = '') | ||
+ { | ||
+ $element = $this->_prep_element($element); | ||
+ return '$('.$element.').removeClass("'.$class.'");'; | ||
+ } | ||
+ | ||
+ // -------------------------------------------------------------------- | ||
+ | ||
+ /** | ||
+ * Slide Up | ||
+ * | ||
+ * Outputs a jQuery slideUp event | ||
+ * | ||
+ * @param string - element | ||
+ * @param string - One of 'slow', 'normal', 'fast', or time in milliseconds | ||
+ * @param string - Javascript callback function | ||
+ * @return string | ||
+ */ | ||
+ protected function _slideUp($element = 'this', $speed = '', $callback = '') | ||
+ { | ||
+ $element = $this->_prep_element($element); | ||
+ $speed = $this->_validate_speed($speed); | ||
+ | ||
+ if ($callback !== '') | ||
+ { | ||
+ $callback = ", function(){\n{$callback}\n}"; | ||
+ } | ||
+ | ||
+ return '$('.$element.').slideUp('.$speed.$callback.');'; | ||
+ } | ||
+ | ||
+ // -------------------------------------------------------------------- | ||
+ | ||
+ /** | ||
+ * Slide Down | ||
+ * | ||
+ * Outputs a jQuery slideDown event | ||
+ * | ||
+ * @param string - element | ||
+ * @param string - One of 'slow', 'normal', 'fast', or time in milliseconds | ||
+ * @param string - Javascript callback function | ||
+ * @return string | ||
+ */ | ||
+ protected function _slideDown($element = 'this', $speed = '', $callback = '') | ||
+ { | ||
+ $element = $this->_prep_element($element); | ||
+ $speed = $this->_validate_speed($speed); | ||
+ | ||
+ if ($callback !== '') | ||
+ { | ||
+ $callback = ", function(){\n{$callback}\n}"; | ||
+ } | ||
+ | ||
+ return '$('.$element.').slideDown('.$speed.$callback.');'; | ||
+ } | ||
+ | ||
+ // -------------------------------------------------------------------- | ||
+ | ||
+ /** | ||
+ * Slide Toggle | ||
+ * | ||
+ * Outputs a jQuery slideToggle event | ||
+ * | ||
+ * @param string - element | ||
+ * @param string - One of 'slow', 'normal', 'fast', or time in milliseconds | ||
+ * @param string - Javascript callback function | ||
+ * @return string | ||
+ */ | ||
+ protected function _slideToggle($element = 'this', $speed = '', $callback = '') | ||
+ { | ||
+ $element = $this->_prep_element($element); | ||
+ $speed = $this->_validate_speed($speed); | ||
+ | ||
+ if ($callback !== '') | ||
+ { | ||
+ $callback = ", function(){\n{$callback}\n}"; | ||
+ } | ||
+ | ||
+ return '$('.$element.').slideToggle('.$speed.$callback.');'; | ||
+ } | ||
+ | ||
+ // -------------------------------------------------------------------- | ||
+ | ||
+ /** | ||
+ * Toggle | ||
+ * | ||
+ * Outputs a jQuery toggle event | ||
+ * | ||
+ * @param string - element | ||
+ * @return string | ||
+ */ | ||
+ protected function _toggle($element = 'this') | ||
+ { | ||
+ $element = $this->_prep_element($element); | ||
+ return '$('.$element.').toggle();'; | ||
+ } | ||
+ | ||
+ // -------------------------------------------------------------------- | ||
+ | ||
+ /** | ||
+ * Toggle Class | ||
+ * | ||
+ * Outputs a jQuery toggle class event | ||
+ * | ||
+ * @param string $element | ||
+ * @param string $class | ||
+ * @return string | ||
+ */ | ||
+ protected function _toggleClass($element = 'this', $class = '') | ||
+ { | ||
+ $element = $this->_prep_element($element); | ||
+ return '$('.$element.').toggleClass("'.$class.'");'; | ||
+ } | ||
+ | ||
+ // -------------------------------------------------------------------- | ||
+ | ||
+ /** | ||
+ * Show | ||
+ * | ||
+ * Outputs a jQuery show event | ||
+ * | ||
+ * @param string - element | ||
+ * @param string - One of 'slow', 'normal', 'fast', or time in milliseconds | ||
+ * @param string - Javascript callback function | ||
+ * @return string | ||
+ */ | ||
+ protected function _show($element = 'this', $speed = '', $callback = '') | ||
+ { | ||
+ $element = $this->_prep_element($element); | ||
+ $speed = $this->_validate_speed($speed); | ||
+ | ||
+ if ($callback !== '') | ||
+ { | ||
+ $callback = ", function(){\n{$callback}\n}"; | ||
+ } | ||
+ | ||
+ return '$('.$element.').show('.$speed.$callback.');'; | ||
+ } | ||
+ | ||
+ // -------------------------------------------------------------------- | ||
+ | ||
+ /** | ||
+ * Updater | ||
+ * | ||
+ * An Ajax call that populates the designated DOM node with | ||
+ * returned content | ||
+ * | ||
+ * @param string The element to attach the event to | ||
+ * @param string the controller to run the call against | ||
+ * @param string optional parameters | ||
+ * @return string | ||
+ */ | ||
+ | ||
+ protected function _updater($container = 'this', $controller = '', $options = '') | ||
+ { | ||
+ $container = $this->_prep_element($container); | ||
+ $controller = (strpos('://', $controller) === FALSE) ? $controller : $this->CI->config->site_url($controller); | ||
+ | ||
+ // ajaxStart and ajaxStop are better choices here... but this is a stop gap | ||
+ if ($this->CI->config->item('javascript_ajax_img') === '') | ||
+ { | ||
+ $loading_notifier = 'Loading...'; | ||
+ } | ||
+ else | ||
+ { | ||
+ $loading_notifier = '<img src="'.$this->CI->config->slash_item('base_url').$this->CI->config->item('javascript_ajax_img').'" alt="Loading" />'; | ||
+ } | ||
+ | ||
+ $updater = '$('.$container.").empty();\n" // anything that was in... get it out | ||
+ ."\t\t$(".$container.').prepend("'.$loading_notifier."\");\n"; // to replace with an image | ||
+ | ||
+ $request_options = ''; | ||
+ if ($options !== '') | ||
+ { | ||
+ $request_options .= ', {' | ||
+ .(is_array($options) ? "'".implode("', '", $options)."'" : "'".str_replace(':', "':'", $options)."'") | ||
+ .'}'; | ||
+ } | ||
+ | ||
+ return $updater."\t\t$($container).load('$controller'$request_options);"; | ||
+ } | ||
+ | ||
+ // -------------------------------------------------------------------- | ||
+ // Pre-written handy stuff | ||
+ // -------------------------------------------------------------------- | ||
+ | ||
+ /** | ||
+ * Zebra tables | ||
+ * | ||
+ * @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}\");"; | ||
+ | ||
+ $this->jquery_code_for_compile[] = $zebra; | ||
+ | ||
+ if ($hover !== '') | ||
+ { | ||
+ $hover = $this->hover("table{$class} tbody tr", "$(this).addClass('hover');", "$(this).removeClass('hover');"); | ||
+ } | ||
+ | ||
+ return $zebra; | ||
+ } | ||
+ | ||
+ // -------------------------------------------------------------------- | ||
+ // Plugins | ||
+ // -------------------------------------------------------------------- | ||
+ | ||
+ /** | ||
+ * Corner Plugin | ||
+ * | ||
+ * @link http://www.malsup.com/jquery/corner/ | ||
+ * @param string $element | ||
+ * @param string $corner_style | ||
+ * @return string | ||
+ */ | ||
+ public function corner($element = '', $corner_style = '') | ||
+ { | ||
+ // may want to make this configurable down the road | ||
+ $corner_location = '/plugins/jquery.corner.js'; | ||
+ | ||
+ if ($corner_style !== '') | ||
+ { | ||
+ $corner_style = '"'.$corner_style.'"'; | ||
+ } | ||
+ | ||
+ return '$('.$this->_prep_element($element).').corner('.$corner_style.');'; | ||
+ } | ||
+ | ||
+ // -------------------------------------------------------------------- | ||
+ | ||
+ /** | ||
+ * Modal window | ||
+ * | ||
+ * Load a thickbox modal window | ||
+ * | ||
+ * @param string $src | ||
+ * @param bool $relative | ||
+ * @return void | ||
+ */ | ||
+ public function modal($src, $relative = FALSE) | ||
+ { | ||
+ $this->jquery_code_for_load[] = $this->external($src, $relative); | ||
+ } | ||
+ | ||
+ // -------------------------------------------------------------------- | ||
+ | ||
+ /** | ||
+ * Effect | ||
+ * | ||
+ * Load an Effect library | ||
+ * | ||
+ * @param string $src | ||
+ * @param bool $relative | ||
+ * @return void | ||
+ */ | ||
+ public function effect($src, $relative = FALSE) | ||
+ { | ||
+ $this->jquery_code_for_load[] = $this->external($src, $relative); | ||
+ } | ||
+ | ||
+ // -------------------------------------------------------------------- | ||
+ | ||
+ /** | ||
+ * Plugin | ||
+ * | ||
+ * Load a plugin library | ||
+ * | ||
+ * @param string $src | ||
+ * @param bool $relative | ||
+ * @return void | ||
+ */ | ||
+ public function plugin($src, $relative = FALSE) | ||
+ { | ||
+ $this->jquery_code_for_load[] = $this->external($src, $relative); | ||
+ } | ||
+ | ||
+ // -------------------------------------------------------------------- | ||
+ | ||
+ /** | ||
+ * UI | ||
+ * | ||
+ * 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); | ||
+ } | ||
+ | ||
+ // -------------------------------------------------------------------- | ||
+ | ||
+ /** | ||
+ * Sortable | ||
+ * | ||
+ * Creates a jQuery sortable | ||
+ * | ||
+ * @param string $element | ||
+ * @param array $options | ||
+ * @return string | ||
+ */ | ||
+ public function sortable($element, $options = array()) | ||
+ { | ||
+ if (count($options) > 0) | ||
+ { | ||
+ $sort_options = array(); | ||
+ foreach ($options as $k=>$v) | ||
+ { | ||
+ $sort_options[] = "\n\t\t".$k.': '.$v; | ||
+ } | ||
+ $sort_options = implode(',', $sort_options); | ||
+ } | ||
+ else | ||
+ { | ||
+ $sort_options = ''; | ||
+ } | ||
+ | ||
+ return '$('.$this->_prep_element($element).').sortable({'.$sort_options."\n\t});"; | ||
+ } | ||
+ | ||
+ // -------------------------------------------------------------------- | ||
+ | ||
+ /** | ||
+ * Table Sorter Plugin | ||
+ * | ||
+ * @param string table name | ||
+ * @param string plugin location | ||
+ * @return string | ||
+ */ | ||
+ public function tablesorter($table = '', $options = '') | ||
+ { | ||
+ $this->jquery_code_for_compile[] = "\t$(".$this->_prep_element($table).').tablesorter('.$options.");\n"; | ||
+ } | ||
+ | ||
+ // -------------------------------------------------------------------- | ||
+ // Class functions | ||
+ // -------------------------------------------------------------------- | ||
+ | ||
+ /** | ||
+ * Add Event | ||
+ * | ||
+ * Constructs the syntax for an event, and adds to into the array for compilation | ||
+ * | ||
+ * @param string The element to attach the event to | ||
+ * @param string The code to execute | ||
+ * @param string The event to pass | ||
+ * @return string | ||
+ */ | ||
+ protected function _add_event($element, $js, $event) | ||
+ { | ||
+ if (is_array($js)) | ||
+ { | ||
+ $js = implode("\n\t\t", $js); | ||
+ } | ||
+ | ||
+ $event = "\n\t$(".$this->_prep_element($element).').'.$event."(function(){\n\t\t{$js}\n\t});\n"; | ||
+ $this->jquery_code_for_compile[] = $event; | ||
+ return $event; | ||
+ } | ||
+ | ||
+ // -------------------------------------------------------------------- | ||
+ | ||
+ /** | ||
+ * Compile | ||
+ * | ||
+ * As events are specified, they are stored in an array | ||
+ * This function compiles them all for output on a page | ||
+ * | ||
+ * @param string $view_var | ||
+ * @param bool $script_tags | ||
+ * @return void | ||
+ */ | ||
+ protected function _compile($view_var = 'script_foot', $script_tags = TRUE) | ||
+ { | ||
+ // External references | ||
+ $external_scripts = implode('', $this->jquery_code_for_load); | ||
+ $this->CI->load->vars(array('library_src' => $external_scripts)); | ||
+ | ||
+ if (count($this->jquery_code_for_compile) === 0) | ||
+ { | ||
+ // no inline references, let's just return | ||
+ return; | ||
+ } | ||
+ | ||
+ // Inline references | ||
+ $script = '$(document).ready(function() {'."\n" | ||
+ .implode('', $this->jquery_code_for_compile) | ||
+ .'});'; | ||
+ | ||
+ $output = ($script_tags === FALSE) ? $script : $this->inline($script); | ||
+ | ||
+ $this->CI->load->vars(array($view_var => $output)); | ||
+ } | ||
+ | ||
+ // -------------------------------------------------------------------- | ||
+ | ||
+ /** | ||
+ * Clear Compile | ||
+ * | ||
+ * Clears the array of script events collected for output | ||
+ * | ||
+ * @return void | ||
+ */ | ||
+ protected function _clear_compile() | ||
+ { | ||
+ $this->jquery_code_for_compile = array(); | ||
+ } | ||
+ | ||
+ // -------------------------------------------------------------------- | ||
+ | ||
+ /** | ||
+ * Document Ready | ||
+ * | ||
+ * A wrapper for writing document.ready() | ||
+ * | ||
+ * @param array $js | ||
+ * @return void | ||
+ */ | ||
+ protected function _document_ready($js) | ||
+ { | ||
+ is_array($js) OR $js = array($js); | ||
+ | ||
+ foreach ($js as $script) | ||
+ { | ||
+ $this->jquery_code_for_compile[] = $script; | ||
+ } | ||
+ } | ||
+ | ||
+ // -------------------------------------------------------------------- | ||
+ | ||
+ /** | ||
+ * Script Tag | ||
+ * | ||
+ * Outputs the script tag that loads the jquery.js file into an HTML document | ||
+ * | ||
+ * @param string $library_src | ||
+ * @param bool $relative | ||
+ * @return string | ||
+ */ | ||
+ public function script($library_src = '', $relative = FALSE) | ||
+ { | ||
+ $library_src = $this->external($library_src, $relative); | ||
+ $this->jquery_code_for_load[] = $library_src; | ||
+ return $library_src; | ||
+ } | ||
+ | ||
+ // -------------------------------------------------------------------- | ||
+ | ||
+ /** | ||
+ * Prep Element | ||
+ * | ||
+ * Puts HTML element in quotes for use in jQuery code | ||
+ * unless the supplied element is the Javascript 'this' | ||
+ * object, in which case no quotes are added | ||
+ * | ||
+ * @param string | ||
+ * @return string | ||
+ */ | ||
+ protected function _prep_element($element) | ||
+ { | ||
+ if ($element !== 'this') | ||
+ { | ||
+ $element = '"'.$element.'"'; | ||
+ } | ||
+ | ||
+ return $element; | ||
+ } | ||
+ | ||
+ // -------------------------------------------------------------------- | ||
+ | ||
+ /** | ||
+ * Validate Speed | ||
+ * | ||
+ * Ensures the speed parameter is valid for jQuery | ||
+ * | ||
+ * @param string | ||
+ * @return string | ||
+ */ | ||
+ protected function _validate_speed($speed) | ||
+ { | ||
+ if (in_array($speed, array('slow', 'normal', 'fast'))) | ||
+ { | ||
+ return '"'.$speed.'"'; | ||
+ } | ||
+ elseif (preg_match('/[^0-9]/', $speed)) | ||
+ { | ||
+ return ''; | ||
+ } | ||
+ | ||
+ return $speed; | ||
+ } | ||
+ | ||
+} |
11
README/Javascript/index.html
@@ -0,0 +1,11 @@ | ||
+<!DOCTYPE html> | ||
+<html> | ||
+<head> | ||
+ <title>403 Forbidden</title> | ||
+</head> | ||
+<body> | ||
+ | ||
+<p>Directory access is forbidden.</p> | ||
+ | ||
+</body> | ||
+</html> |
446
README/Migration.php
@@ -0,0 +1,446 @@ | ||
+<?php | ||
+/** | ||
+ * CodeIgniter | ||
+ * | ||
+ * An open source application development framework for PHP | ||
+ * | ||
+ * This content is released under the MIT License (MIT) | ||
+ * | ||
+ * Copyright (c) 2014 - 2015, British Columbia Institute of Technology | ||
+ * | ||
+ * Permission is hereby granted, free of charge, to any person obtaining a copy | ||
+ * of this software and associated documentation files (the "Software"), to deal | ||
+ * in the Software without restriction, including without limitation the rights | ||
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | ||
+ * copies of the Software, and to permit persons to whom the Software is | ||
+ * furnished to do so, subject to the following conditions: | ||
+ * | ||
+ * The above copyright notice and this permission notice shall be included in | ||
+ * all copies or substantial portions of the Software. | ||
+ * | ||
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | ||
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | ||
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN | ||
+ * THE SOFTWARE. | ||
+ * | ||
+ * @package CodeIgniter | ||
+ * @author EllisLab Dev Team | ||
+ * @copyright Copyright (c) 2008 - 2014, EllisLab, Inc. (http://ellislab.com/) | ||
+ * @copyright Copyright (c) 2014 - 2015, British Columbia Institute of Technology (http://bcit.ca/) | ||
+ * @license http://opensource.org/licenses/MIT MIT License | ||
+ * @link http://codeigniter.com | ||
+ * @since Version 3.0.0 | ||
+ * @filesource | ||
+ */ | ||
+defined('BASEPATH') OR exit('No direct script access allowed'); | ||
+ | ||
+/** | ||
+ * Migration Class | ||
+ * | ||
+ * All migrations should implement this, forces up() and down() and gives | ||
+ * access to the CI super-global. | ||
+ * | ||
+ * @package CodeIgniter | ||
+ * @subpackage Libraries | ||
+ * @category Libraries | ||
+ * @author Reactor Engineers | ||
+ * @link | ||
+ */ | ||
+class CI_Migration { | ||
+ | ||
+ /** | ||
+ * Whether the library is enabled | ||
+ * | ||
+ * @var bool | ||
+ */ | ||
+ protected $_migration_enabled = FALSE; | ||
+ | ||
+ /** | ||
+ * Migration numbering type | ||
+ * | ||
+ * @var bool | ||
+ */ | ||
+ protected $_migration_type = 'sequential'; | ||
+ | ||
+ /** | ||
+ * Path to migration classes | ||
+ * | ||
+ * @var string | ||
+ */ | ||
+ protected $_migration_path = NULL; | ||
+ | ||
+ /** | ||
+ * Current migration version | ||
+ * | ||
+ * @var mixed | ||
+ */ | ||
+ protected $_migration_version = 0; | ||
+ | ||
+ /** | ||
+ * Database table with migration info | ||
+ * | ||
+ * @var string | ||
+ */ | ||
+ protected $_migration_table = 'migrations'; | ||
+ | ||
+ /** | ||
+ * Whether to automatically run migrations | ||
+ * | ||
+ * @var bool | ||
+ */ | ||
+ protected $_migration_auto_latest = FALSE; | ||
+ | ||
+ /** | ||
+ * Migration basename regex | ||
+ * | ||
+ * @var bool | ||
+ */ | ||
+ protected $_migration_regex = NULL; | ||
+ | ||
+ /** | ||
+ * Error message | ||
+ * | ||
+ * @var string | ||
+ */ | ||
+ protected $_error_string = ''; | ||
+ | ||
+ /** | ||
+ * Initialize Migration Class | ||
+ * | ||
+ * @param array $config | ||
+ * @return void | ||
+ */ | ||
+ public function __construct($config = array()) | ||
+ { | ||
+ // Only run this constructor on main library load | ||
+ if ( ! in_array(get_class($this), array('CI_Migration', config_item('subclass_prefix').'Migration'), TRUE)) | ||
+ { | ||
+ return; | ||
+ } | ||
+ | ||
+ foreach ($config as $key => $val) | ||
+ { | ||
+ $this->{'_'.$key} = $val; | ||
+ } | ||
+ | ||
+ log_message('info', 'Migrations Class Initialized'); | ||
+ | ||
+ // Are they trying to use migrations while it is disabled? | ||
+ if ($this->_migration_enabled !== TRUE) | ||
+ { | ||
+ show_error('Migrations has been loaded but is disabled or set up incorrectly.'); | ||
+ } | ||
+ | ||
+ // If not set, set it | ||
+ $this->_migration_path !== '' OR $this->_migration_path = APPPATH.'migrations/'; | ||
+ | ||
+ // Add trailing slash if not set | ||
+ $this->_migration_path = rtrim($this->_migration_path, '/').'/'; | ||
+ | ||
+ // Load migration language | ||
+ $this->lang->load('migration'); | ||
+ | ||
+ // They'll probably be using dbforge | ||
+ $this->load->dbforge(); | ||
+ | ||
+ // Make sure the migration table name was set. | ||
+ if (empty($this->_migration_table)) | ||
+ { | ||
+ show_error('Migrations configuration file (migration.php) must have "migration_table" set.'); | ||
+ } | ||
+ | ||
+ // Migration basename regex | ||
+ $this->_migration_regex = ($this->_migration_type === 'timestamp') | ||
+ ? '/^\d{14}_(\w+)$/' | ||
+ : '/^\d{3}_(\w+)$/'; | ||
+ | ||
+ // Make sure a valid migration numbering type was set. | ||
+ if ( ! in_array($this->_migration_type, array('sequential', 'timestamp'))) | ||
+ { | ||
+ show_error('An invalid migration numbering type was specified: '.$this->_migration_type); | ||
+ } | ||
+ | ||
+ // If the migrations table is missing, make it | ||
+ if ( ! $this->db->table_exists($this->_migration_table)) | ||
+ { | ||
+ $this->dbforge->add_field(array( | ||
+ 'version' => array('type' => 'BIGINT', 'constraint' => 20), | ||
+ )); | ||
+ | ||
+ $this->dbforge->create_table($this->_migration_table, TRUE); | ||
+ | ||
+ $this->db->insert($this->_migration_table, array('version' => 0)); | ||
+ } | ||
+ | ||
+ // Do we auto migrate to the latest migration? | ||
+ if ($this->_migration_auto_latest === TRUE && ! $this->latest()) | ||
+ { | ||
+ show_error($this->error_string()); | ||
+ } | ||
+ } | ||
+ | ||
+ // -------------------------------------------------------------------- | ||
+ | ||
+ /** | ||
+ * Migrate to a schema version | ||
+ * | ||
+ * Calls each migration step required to get to the schema version of | ||
+ * choice | ||
+ * | ||
+ * @param string $target_version Target schema version | ||
+ * @return mixed TRUE if no migrations are found, current version string on success, FALSE on failure | ||
+ */ | ||
+ public function version($target_version) | ||
+ { | ||
+ // Note: We use strings, so that timestamp versions work on 32-bit systems | ||
+ $current_version = $this->_get_version(); | ||
+ | ||
+ if ($this->_migration_type === 'sequential') | ||
+ { | ||
+ $target_version = sprintf('%03d', $target_version); | ||
+ } | ||
+ else | ||
+ { | ||
+ $target_version = (string) $target_version; | ||
+ } | ||
+ | ||
+ $migrations = $this->find_migrations(); | ||
+ | ||
+ if ($target_version > 0 && ! isset($migrations[$target_version])) | ||
+ { | ||
+ $this->_error_string = sprintf($this->lang->line('migration_not_found'), $target_version); | ||
+ return FALSE; | ||
+ } | ||
+ | ||
+ if ($target_version > $current_version) | ||
+ { | ||
+ // Moving Up | ||
+ $method = 'up'; | ||
+ } | ||
+ else | ||
+ { | ||
+ // Moving Down, apply in reverse order | ||
+ $method = 'down'; | ||
+ krsort($migrations); | ||
+ } | ||
+ | ||
+ if (empty($migrations)) | ||
+ { | ||
+ return TRUE; | ||
+ } | ||
+ | ||
+ $previous = FALSE; | ||
+ | ||
+ // Validate all available migrations, and run the ones within our target range | ||
+ foreach ($migrations as $number => $file) | ||
+ { | ||
+ // Check for sequence gaps | ||
+ if ($this->_migration_type === 'sequential' && $previous !== FALSE && abs($number - $previous) > 1) | ||
+ { | ||
+ $this->_error_string = sprintf($this->lang->line('migration_sequence_gap'), $number); | ||
+ return FALSE; | ||
+ } | ||
+ | ||
+ include_once($file); | ||
+ $class = 'Migration_'.ucfirst(strtolower($this->_get_migration_name(basename($file, '.php')))); | ||
+ | ||
+ // Validate the migration file structure | ||
+ if ( ! class_exists($class, FALSE)) | ||
+ { | ||
+ $this->_error_string = sprintf($this->lang->line('migration_class_doesnt_exist'), $class); | ||
+ return FALSE; | ||
+ } | ||
+ | ||
+ $previous = $number; | ||
+ | ||
+ // Run migrations that are inside the target range | ||
+ if ( | ||
+ ($method === 'up' && $number > $current_version && $number <= $target_version) OR | ||
+ ($method === 'down' && $number <= $current_version && $number > $target_version) | ||
+ ) | ||
+ { | ||
+ $instance = new $class(); | ||
+ if ( ! is_callable(array($instance, $method))) | ||
+ { | ||
+ $this->_error_string = sprintf($this->lang->line('migration_missing_'.$method.'_method'), $class); | ||
+ return FALSE; | ||
+ } | ||
+ | ||
+ log_message('debug', 'Migrating '.$method.' from version '.$current_version.' to version '.$number); | ||
+ call_user_func(array($instance, $method)); | ||
+ $current_version = $number; | ||
+ $this->_update_version($current_version); | ||
+ } | ||
+ } | ||
+ | ||
+ // This is necessary when moving down, since the the last migration applied | ||
+ // will be the down() method for the next migration up from the target | ||
+ if ($current_version <> $target_version) | ||
+ { | ||
+ $current_version = $target_version; | ||
+ $this->_update_version($current_version); | ||
+ } | ||
+ | ||
+ log_message('debug', 'Finished migrating to '.$current_version); | ||
+ | ||
+ return $current_version; | ||
+ } | ||
+ | ||
+ // -------------------------------------------------------------------- | ||
+ | ||
+ /** | ||
+ * Sets the schema to the latest migration | ||
+ * | ||
+ * @return mixed Current version string on success, FALSE on failure | ||
+ */ | ||
+ public function latest() | ||
+ { | ||
+ $migrations = $this->find_migrations(); | ||
+ | ||
+ if (empty($migrations)) | ||
+ { | ||
+ $this->_error_string = $this->lang->line('migration_none_found'); | ||
+ return FALSE; | ||
+ } | ||
+ | ||
+ $last_migration = basename(end($migrations)); | ||
+ | ||
+ // Calculate the last migration step from existing migration | ||
+ // filenames and proceed to the standard version migration | ||
+ return $this->version($this->_get_migration_number($last_migration)); | ||
+ } | ||
+ | ||
+ // -------------------------------------------------------------------- | ||
+ | ||
+ /** | ||
+ * Sets the schema to the migration version set in config | ||
+ * | ||
+ * @return mixed TRUE if no migrations are found, current version string on success, FALSE on failure | ||
+ */ | ||
+ public function current() | ||
+ { | ||
+ return $this->version($this->_migration_version); | ||
+ } | ||
+ | ||
+ // -------------------------------------------------------------------- | ||
+ | ||
+ /** | ||
+ * Error string | ||
+ * | ||
+ * @return string Error message returned as a string | ||
+ */ | ||
+ public function error_string() | ||
+ { | ||
+ return $this->_error_string; | ||
+ } | ||
+ | ||
+ // -------------------------------------------------------------------- | ||
+ | ||
+ /** | ||
+ * Retrieves list of available migration scripts | ||
+ * | ||
+ * @return array list of migration file paths sorted by version | ||
+ */ | ||
+ public function find_migrations() | ||
+ { | ||
+ $migrations = array(); | ||
+ | ||
+ // Load all *_*.php files in the migrations path | ||
+ foreach (glob($this->_migration_path.'*_*.php') as $file) | ||
+ { | ||
+ $name = basename($file, '.php'); | ||
+ | ||
+ // Filter out non-migration files | ||
+ if (preg_match($this->_migration_regex, $name)) | ||
+ { | ||
+ $number = $this->_get_migration_number($name); | ||
+ | ||
+ // There cannot be duplicate migration numbers | ||
+ if (isset($migrations[$number])) | ||
+ { | ||
+ $this->_error_string = sprintf($this->lang->line('migration_multiple_version'), $number); | ||
+ show_error($this->_error_string); | ||
+ } | ||
+ | ||
+ $migrations[$number] = $file; | ||
+ } | ||
+ } | ||
+ | ||
+ ksort($migrations); | ||
+ return $migrations; | ||
+ } | ||
+ | ||
+ // -------------------------------------------------------------------- | ||
+ | ||
+ /** | ||
+ * Extracts the migration number from a filename | ||
+ * | ||
+ * @param string $migration | ||
+ * @return string Numeric portion of a migration filename | ||
+ */ | ||
+ protected function _get_migration_number($migration) | ||
+ { | ||
+ return sscanf($migration, '%[0-9]+', $number) | ||
+ ? $number : '0'; | ||
+ } | ||
+ | ||
+ // -------------------------------------------------------------------- | ||
+ | ||
+ /** | ||
+ * Extracts the migration class name from a filename | ||
+ * | ||
+ * @param string $migration | ||
+ * @return string text portion of a migration filename | ||
+ */ | ||
+ protected function _get_migration_name($migration) | ||
+ { | ||
+ $parts = explode('_', $migration); | ||
+ array_shift($parts); | ||
+ return implode('_', $parts); | ||
+ } | ||
+ | ||
+ // -------------------------------------------------------------------- | ||
+ | ||
+ /** | ||
+ * Retrieves current schema version | ||
+ * | ||
+ * @return string Current migration version | ||
+ */ | ||
+ protected function _get_version() | ||
+ { | ||
+ $row = $this->db->select('version')->get($this->_migration_table)->row(); | ||
+ return $row ? $row->version : '0'; | ||
+ } | ||
+ | ||
+ // -------------------------------------------------------------------- | ||
+ | ||
+ /** | ||
+ * Stores the current schema version | ||
+ * | ||
+ * @param string $migration Migration reached | ||
+ * @return void | ||
+ */ | ||
+ protected function _update_version($migration) | ||
+ { | ||
+ $this->db->update($this->_migration_table, array( | ||
+ 'version' => $migration | ||
+ )); | ||
+ } | ||
+ | ||
+ // -------------------------------------------------------------------- | ||
+ | ||
+ /** | ||
+ * Enable the use of CI super-global | ||
+ * | ||
+ * @param string $var | ||
+ * @return mixed | ||
+ */ | ||
+ public function __get($var) | ||
+ { | ||
+ return get_instance()->$var; | ||
+ } | ||
+ | ||
+} |
697
README/Pagination.php
@@ -0,0 +1,697 @@ | ||
+<?php | ||
+/** | ||
+ * CodeIgniter | ||
+ * | ||
+ * An open source application development framework for PHP | ||
+ * | ||
+ * This content is released under the MIT License (MIT) | ||
+ * | ||
+ * Copyright (c) 2014 - 2015, British Columbia Institute of Technology | ||
+ * | ||
+ * Permission is hereby granted, free of charge, to any person obtaining a copy | ||
+ * of this software and associated documentation files (the "Software"), to deal | ||
+ * in the Software without restriction, including without limitation the rights | ||
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | ||
+ * copies of the Software, and to permit persons to whom the Software is | ||
+ * furnished to do so, subject to the following conditions: | ||
+ * | ||
+ * The above copyright notice and this permission notice shall be included in | ||
+ * all copies or substantial portions of the Software. | ||
+ * | ||
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | ||
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | ||
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN | ||
+ * THE SOFTWARE. | ||
+ * | ||
+ * @package CodeIgniter | ||
+ * @author EllisLab Dev Team | ||
+ * @copyright Copyright (c) 2008 - 2014, EllisLab, Inc. (http://ellislab.com/) | ||
+ * @copyright Copyright (c) 2014 - 2015, British Columbia Institute of Technology (http://bcit.ca/) | ||
+ * @license http://opensource.org/licenses/MIT MIT License | ||
+ * @link http://codeigniter.com | ||
+ * @since Version 1.0.0 | ||
+ * @filesource | ||
+ */ | ||
+defined('BASEPATH') OR exit('No direct script access allowed'); | ||
+ | ||
+/** | ||
+ * Pagination Class | ||
+ * | ||
+ * @package CodeIgniter | ||
+ * @subpackage Libraries | ||
+ * @category Pagination | ||
+ * @author EllisLab Dev Team | ||
+ * @link http://codeigniter.com/user_guide/libraries/pagination.html | ||
+ */ | ||
+class CI_Pagination { | ||
+ | ||
+ /** | ||
+ * 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; | ||
+ | ||
+ /** | ||
+ * Number of links to show | ||
+ * | ||
+ * Relates to "digit" type links shown before/after | ||
+ * the currently viewed page. | ||
+ * | ||
+ * @var int | ||
+ */ | ||
+ protected $num_links = 2; | ||
+ | ||
+ /** | ||
+ * Items per page | ||
+ * | ||
+ * @var int | ||
+ */ | ||
+ public $per_page = 10; | ||
+ | ||
+ /** | ||
+ * Current page | ||
+ * | ||
+ * @var int | ||
+ */ | ||
+ public $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 = 0; | ||
+ | ||
+ /** | ||
+ * 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; | ||
+ | ||
+ /** | ||
+ * 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; | ||
+ | ||
+ /** | ||
+ * Use global URL suffix flag | ||
+ * | ||
+ * @var bool | ||
+ */ | ||
+ protected $use_global_url_suffix = FALSE; | ||
+ | ||
+ /** | ||
+ * Data page attribute | ||
+ * | ||
+ * @var string | ||
+ */ | ||
+ protected $data_page_attr = 'data-ci-pagination-page'; | ||
+ | ||
+ /** | ||
+ * CI Singleton | ||
+ * | ||
+ * @var object | ||
+ */ | ||
+ protected $CI; | ||
+ | ||
+ // -------------------------------------------------------------------- | ||
+ | ||
+ /** | ||
+ * Constructor | ||
+ * | ||
+ * @param array $params Initialization parameters | ||
+ * @return void | ||
+ */ | ||
+ public function __construct($params = array()) | ||
+ { | ||
+ $this->CI =& get_instance(); | ||
+ $this->CI->load->language('pagination'); | ||
+ foreach (array('first_link', 'next_link', 'prev_link', 'last_link') as $key) | ||
+ { | ||
+ if (($val = $this->CI->lang->line('pagination_'.$key)) !== FALSE) | ||
+ { | ||
+ $this->$key = $val; | ||
+ } | ||
+ } | ||
+ | ||
+ $this->initialize($params); | ||
+ log_message('info', 'Pagination Class Initialized'); | ||
+ } | ||
+ | ||
+ // -------------------------------------------------------------------- | ||
+ | ||
+ /** | ||
+ * Initialize Preferences | ||
+ * | ||
+ * @param array $params Initialization parameters | ||
+ * @return CI_Pagination | ||
+ */ | ||
+ public function initialize(array $params = array()) | ||
+ { | ||
+ isset($params['attributes']) OR $params['attributes'] = array(); | ||
+ if (is_array($params['attributes'])) | ||
+ { | ||
+ $this->_parse_attributes($params['attributes']); | ||
+ unset($params['attributes']); | ||
+ } | ||
+ | ||
+ // Deprecated legacy support for the anchor_class option | ||
+ // Should be removed in CI 3.1+ | ||
+ if (isset($params['anchor_class'])) | ||
+ { | ||
+ empty($params['anchor_class']) OR $attributes['class'] = $params['anchor_class']; | ||
+ unset($params['anchor_class']); | ||
+ } | ||
+ | ||
+ foreach ($params as $key => $val) | ||
+ { | ||
+ if (property_exists($this, $key)) | ||
+ { | ||
+ $this->$key = $val; | ||
+ } | ||
+ } | ||
+ | ||
+ if ($this->CI->config->item('enable_query_strings') === TRUE) | ||
+ { | ||
+ $this->page_query_string = TRUE; | ||
+ } | ||
+ | ||
+ if ($this->use_global_url_suffix === TRUE) | ||
+ { | ||
+ $this->suffix = $this->CI->config->item('url_suffix'); | ||
+ } | ||
+ | ||
+ return $this; | ||
+ } | ||
+ | ||
+ // -------------------------------------------------------------------- | ||
+ | ||
+ /** | ||
+ * Generate the pagination links | ||
+ * | ||
+ * @return string | ||
+ */ | ||
+ public function create_links() | ||
+ { | ||
+ // If our item count or per-page total is zero there is no need to continue. | ||
+ // Note: DO NOT change the operator to === here! | ||
+ if ($this->total_rows == 0 OR $this->per_page == 0) | ||
+ { | ||
+ return ''; | ||
+ } | ||
+ | ||
+ // Calculate the total number of pages | ||
+ $num_pages = (int) ceil($this->total_rows / $this->per_page); | ||
+ | ||
+ // Is there only one page? Hm... nothing more to do here then. | ||
+ if ($num_pages === 1) | ||
+ { | ||
+ return ''; | ||
+ } | ||
+ | ||
+ // Check the user defined number of links. | ||
+ $this->num_links = (int) $this->num_links; | ||
+ | ||
+ if ($this->num_links < 0) | ||
+ { | ||
+ show_error('Your number of links must be a non-negative number.'); | ||
+ } | ||
+ | ||
+ // Keep any existing query string items. | ||
+ // Note: Has nothing to do with any other query string option. | ||
+ if ($this->reuse_query_string === TRUE) | ||
+ { | ||
+ $get = $this->CI->input->get(); | ||
+ | ||
+ // Unset the controll, method, old-school routing options | ||
+ unset($get['c'], $get['m'], $get[$this->query_string_segment]); | ||
+ } | ||
+ else | ||
+ { | ||
+ $get = array(); | ||
+ } | ||
+ | ||
+ // Put together our base and first URLs. | ||
+ // Note: DO NOT append to the properties as that would break successive calls | ||
+ $base_url = trim($this->base_url); | ||
+ $first_url = $this->first_url; | ||
+ | ||
+ $query_string = ''; | ||
+ $query_string_sep = (strpos($base_url, '?') === FALSE) ? '?' : '&'; | ||
+ | ||
+ // Are we using query strings? | ||
+ if ($this->page_query_string === TRUE) | ||
+ { | ||
+ // If a custom first_url hasn't been specified, we'll create one from | ||
+ // the base_url, but without the page item. | ||
+ if ($first_url === '') | ||
+ { | ||
+ $first_url = $base_url; | ||
+ | ||
+ // If we saved any GET items earlier, make sure they're appended. | ||
+ if ( ! empty($get)) | ||
+ { | ||
+ $first_url .= $query_string_sep.http_build_query($get); | ||
+ } | ||
+ } | ||
+ | ||
+ // Add the page segment to the end of the query string, where the | ||
+ // page number will be appended. | ||
+ $base_url .= $query_string_sep.http_build_query(array_merge($get, array($this->query_string_segment => ''))); | ||
+ } | ||
+ else | ||
+ { | ||
+ // Standard segment mode. | ||
+ // Generate our saved query string to append later after the page number. | ||
+ if ( ! empty($get)) | ||
+ { | ||
+ $query_string = $query_string_sep.http_build_query($get); | ||
+ $this->suffix .= $query_string; | ||
+ } | ||
+ | ||
+ // Does the base_url have the query string in it? | ||
+ // If we're supposed to save it, remove it so we can append it later. | ||
+ if ($this->reuse_query_string === TRUE && ($base_query_pos = strpos($base_url, '?')) !== FALSE) | ||
+ { | ||
+ $base_url = substr($base_url, 0, $base_query_pos); | ||
+ } | ||
+ | ||
+ if ($first_url === '') | ||
+ { | ||
+ $first_url = $base_url.$query_string; | ||
+ } | ||
+ | ||
+ $base_url = rtrim($base_url, '/').'/'; | ||
+ } | ||
+ | ||
+ // Determine the current page number. | ||
+ $base_page = ($this->use_page_numbers) ? 1 : 0; | ||
+ | ||
+ // Are we using query strings? | ||
+ if ($this->page_query_string === TRUE) | ||
+ { | ||
+ $this->cur_page = $this->CI->input->get($this->query_string_segment); | ||
+ } | ||
+ else | ||
+ { | ||
+ // Default to the last segment number if one hasn't been defined. | ||
+ if ($this->uri_segment === 0) | ||
+ { | ||
+ $this->uri_segment = count($this->CI->uri->segment_array()); | ||
+ } | ||
+ | ||
+ $this->cur_page = $this->CI->uri->segment($this->uri_segment); | ||
+ | ||
+ // Remove any specified prefix/suffix from the segment. | ||
+ if ($this->prefix !== '' OR $this->suffix !== '') | ||
+ { | ||
+ $this->cur_page = str_replace(array($this->prefix, $this->suffix), '', $this->cur_page); | ||
+ } | ||
+ } | ||
+ | ||
+ // If something isn't quite right, back to the default base page. | ||
+ if ( ! ctype_digit($this->cur_page) OR ($this->use_page_numbers && (int) $this->cur_page === 0)) | ||
+ { | ||
+ $this->cur_page = $base_page; | ||
+ } | ||
+ else | ||
+ { | ||
+ // Make sure we're using integers for comparisons later. | ||
+ $this->cur_page = (int) $this->cur_page; | ||
+ } | ||
+ | ||
+ // Is the page number beyond the result range? | ||
+ // If so, we show the last page. | ||
+ if ($this->use_page_numbers) | ||
+ { | ||
+ if ($this->cur_page > $num_pages) | ||
+ { | ||
+ $this->cur_page = $num_pages; | ||
+ } | ||
+ } | ||
+ elseif ($this->cur_page > $this->total_rows) | ||
+ { | ||
+ $this->cur_page = ($num_pages - 1) * $this->per_page; | ||
+ } | ||
+ | ||
+ $uri_page_number = $this->cur_page; | ||
+ | ||
+ // If we're using offset instead of page numbers, convert it | ||
+ // to a page number, so we can generate the surrounding number links. | ||
+ if ( ! $this->use_page_numbers) | ||
+ { | ||
+ $this->cur_page = (int) floor(($this->cur_page/$this->per_page) + 1); | ||
+ } | ||
+ | ||
+ // Calculate the start and end numbers. These determine | ||
+ // which number to start and end the digit links with. | ||
+ $start = (($this->cur_page - $this->num_links) > 0) ? $this->cur_page - ($this->num_links - 1) : 1; | ||
+ $end = (($this->cur_page + $this->num_links) < $num_pages) ? $this->cur_page + $this->num_links : $num_pages; | ||
+ | ||
+ // And here we go... | ||
+ $output = ''; | ||
+ | ||
+ // Render the "First" link. | ||
+ if ($this->first_link !== FALSE && $this->cur_page > ($this->num_links + 1 + ! $this->num_links)) | ||
+ { | ||
+ // Take the general parameters, and squeeze this pagination-page attr in for JS frameworks. | ||
+ $attributes = sprintf('%s %s="%d"', $this->_attributes, $this->data_page_attr, 1); | ||
+ | ||
+ $output .= $this->first_tag_open.'<a href="'.$first_url.'"'.$attributes.$this->_attr_rel('start').'>' | ||
+ .$this->first_link.'</a>'.$this->first_tag_close; | ||
+ } | ||
+ | ||
+ // Render the "Previous" link. | ||
+ if ($this->prev_link !== FALSE && $this->cur_page !== 1) | ||
+ { | ||
+ $i = ($this->use_page_numbers) ? $uri_page_number - 1 : $uri_page_number - $this->per_page; | ||
+ | ||
+ $attributes = sprintf('%s %s="%d"', $this->_attributes, $this->data_page_attr, ($this->cur_page - 1)); | ||
+ | ||
+ if ($i === $base_page) | ||
+ { | ||
+ // First page | ||
+ $output .= $this->prev_tag_open.'<a href="'.$first_url.'"'.$attributes.$this->_attr_rel('prev').'>' | ||
+ .$this->prev_link.'</a>'.$this->prev_tag_close; | ||
+ } | ||
+ else | ||
+ { | ||
+ $append = $this->prefix.$i.$this->suffix; | ||
+ $output .= $this->prev_tag_open.'<a href="'.$base_url.$append.'"'.$attributes.$this->_attr_rel('prev').'>' | ||
+ .$this->prev_link.'</a>'.$this->prev_tag_close; | ||
+ } | ||
+ | ||
+ } | ||
+ | ||
+ // Render the pages | ||
+ if ($this->display_pages !== FALSE) | ||
+ { | ||
+ // Write the digit links | ||
+ for ($loop = $start - 1; $loop <= $end; $loop++) | ||
+ { | ||
+ $i = ($this->use_page_numbers) ? $loop : ($loop * $this->per_page) - $this->per_page; | ||
+ | ||
+ $attributes = sprintf('%s %s="%d"', $this->_attributes, $this->data_page_attr, $loop); | ||
+ | ||
+ if ($i >= $base_page) | ||
+ { | ||
+ if ($this->cur_page === $loop) | ||
+ { | ||
+ // Current page | ||
+ $output .= $this->cur_tag_open.$loop.$this->cur_tag_close; | ||
+ } | ||
+ elseif ($i === $base_page) | ||
+ { | ||
+ // First page | ||
+ $output .= $this->num_tag_open.'<a href="'.$first_url.'"'.$attributes.$this->_attr_rel('start').'>' | ||
+ .$loop.'</a>'.$this->num_tag_close; | ||
+ } | ||
+ else | ||
+ { | ||
+ $append = $this->prefix.$i.$this->suffix; | ||
+ $output .= $this->num_tag_open.'<a href="'.$base_url.$append.'"'.$attributes.'>' | ||
+ .$loop.'</a>'.$this->num_tag_close; | ||
+ } | ||
+ } | ||
+ } | ||
+ } | ||
+ | ||
+ // Render the "next" link | ||
+ if ($this->next_link !== FALSE && $this->cur_page < $num_pages) | ||
+ { | ||
+ $i = ($this->use_page_numbers) ? $this->cur_page + 1 : $this->cur_page * $this->per_page; | ||
+ | ||
+ $attributes = sprintf('%s %s="%d"', $this->_attributes, $this->data_page_attr, $this->cur_page + 1); | ||
+ | ||
+ $output .= $this->next_tag_open.'<a href="'.$base_url.$this->prefix.$i.$this->suffix.'"'.$attributes | ||
+ .$this->_attr_rel('next').'>'.$this->next_link.'</a>'.$this->next_tag_close; | ||
+ } | ||
+ | ||
+ // Render the "Last" link | ||
+ if ($this->last_link !== FALSE && ($this->cur_page + $this->num_links + ! $this->num_links) < $num_pages) | ||
+ { | ||
+ $i = ($this->use_page_numbers) ? $num_pages : ($num_pages * $this->per_page) - $this->per_page; | ||
+ | ||
+ $attributes = sprintf('%s %s="%d"', $this->_attributes, $this->data_page_attr, $num_pages); | ||
+ | ||
+ $output .= $this->last_tag_open.'<a href="'.$base_url.$this->prefix.$i.$this->suffix.'"'.$attributes.'>' | ||
+ .$this->last_link.'</a>'.$this->last_tag_close; | ||
+ } | ||
+ | ||
+ // Kill double slashes. Note: Sometimes we can end up with a double slash | ||
+ // in the penultimate link so we'll kill all double slashes. | ||
+ $output = preg_replace('#([^:"])//+#', '\\1/', $output); | ||
+ | ||
+ // Add the wrapper HTML if exists | ||
+ return $this->full_tag_open.$output.$this->full_tag_close; | ||
+ } | ||
+ | ||
+ // -------------------------------------------------------------------- | ||
+ | ||
+ /** | ||
+ * Parse attributes | ||
+ * | ||
+ * @param array $attributes | ||
+ * @return void | ||
+ */ | ||
+ protected function _parse_attributes($attributes) | ||
+ { | ||
+ isset($attributes['rel']) OR $attributes['rel'] = TRUE; | ||
+ $this->_link_types = ($attributes['rel']) | ||
+ ? array('start' => 'start', 'prev' => 'prev', 'next' => 'next') | ||
+ : array(); | ||
+ unset($attributes['rel']); | ||
+ | ||
+ $this->_attributes = ''; | ||
+ foreach ($attributes as $key => $value) | ||
+ { | ||
+ $this->_attributes .= ' '.$key.'="'.$value.'"'; | ||
+ } | ||
+ } | ||
+ | ||
+ // -------------------------------------------------------------------- | ||
+ | ||
+ /** | ||
+ * Add "rel" attribute | ||
+ * | ||
+ * @link http://www.w3.org/TR/html5/links.html#linkTypes | ||
+ * @param string $type | ||
+ * @return string | ||
+ */ | ||
+ protected function _attr_rel($type) | ||
+ { | ||
+ if (isset($this->_link_types[$type])) | ||
+ { | ||
+ unset($this->_link_types[$type]); | ||
+ return ' rel="'.$type.'"'; | ||
+ } | ||
+ | ||
+ return ''; | ||
+ } | ||
+ | ||
+} |
248
README/Parser.php
@@ -0,0 +1,248 @@ | ||
+<?php | ||
+/** | ||
+ * CodeIgniter | ||
+ * | ||
+ * An open source application development framework for PHP | ||
+ * | ||
+ * This content is released under the MIT License (MIT) | ||
+ * | ||
+ * Copyright (c) 2014 - 2015, British Columbia Institute of Technology | ||
+ * | ||
+ * Permission is hereby granted, free of charge, to any person obtaining a copy | ||
+ * of this software and associated documentation files (the "Software"), to deal | ||
+ * in the Software without restriction, including without limitation the rights | ||
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | ||
+ * copies of the Software, and to permit persons to whom the Software is | ||
+ * furnished to do so, subject to the following conditions: | ||
+ * | ||
+ * The above copyright notice and this permission notice shall be included in | ||
+ * all copies or substantial portions of the Software. | ||
+ * | ||
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | ||
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | ||
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN | ||
+ * THE SOFTWARE. | ||
+ * | ||
+ * @package CodeIgniter | ||
+ * @author EllisLab Dev Team | ||
+ * @copyright Copyright (c) 2008 - 2014, EllisLab, Inc. (http://ellislab.com/) | ||
+ * @copyright Copyright (c) 2014 - 2015, British Columbia Institute of Technology (http://bcit.ca/) | ||
+ * @license http://opensource.org/licenses/MIT MIT License | ||
+ * @link http://codeigniter.com | ||
+ * @since Version 1.0.0 | ||
+ * @filesource | ||
+ */ | ||
+defined('BASEPATH') OR exit('No direct script access allowed'); | ||
+ | ||
+/** | ||
+ * Parser Class | ||
+ * | ||
+ * @package CodeIgniter | ||
+ * @subpackage Libraries | ||
+ * @category Parser | ||
+ * @author EllisLab Dev Team | ||
+ * @link http://codeigniter.com/user_guide/libraries/parser.html | ||
+ */ | ||
+class CI_Parser { | ||
+ | ||
+ /** | ||
+ * Left delimiter character for pseudo vars | ||
+ * | ||
+ * @var string | ||
+ */ | ||
+ public $l_delim = '{'; | ||
+ | ||
+ /** | ||
+ * Right delimiter character for pseudo vars | ||
+ * | ||
+ * @var string | ||
+ */ | ||
+ public $r_delim = '}'; | ||
+ | ||
+ /** | ||
+ * Reference to CodeIgniter instance | ||
+ * | ||
+ * @var object | ||
+ */ | ||
+ protected $CI; | ||
+ | ||
+ // -------------------------------------------------------------------- | ||
+ | ||
+ /** | ||
+ * Class constructor | ||
+ * | ||
+ * @return void | ||
+ */ | ||
+ public function __construct() | ||
+ { | ||
+ $this->CI =& get_instance(); | ||
+ log_message('info', 'Parser Class Initialized'); | ||
+ } | ||
+ | ||
+ // -------------------------------------------------------------------- | ||
+ | ||
+ /** | ||
+ * Parse a template | ||
+ * | ||
+ * Parses pseudo-variables contained in the specified template view, | ||
+ * replacing them with the data in the second param | ||
+ * | ||
+ * @param string | ||
+ * @param array | ||
+ * @param bool | ||
+ * @return string | ||
+ */ | ||
+ public function parse($template, $data, $return = FALSE) | ||
+ { | ||
+ $template = $this->CI->load->view($template, $data, TRUE); | ||
+ | ||
+ return $this->_parse($template, $data, $return); | ||
+ } | ||
+ | ||
+ // -------------------------------------------------------------------- | ||
+ | ||
+ /** | ||
+ * Parse a String | ||
+ * | ||
+ * Parses pseudo-variables contained in the specified string, | ||
+ * replacing them with the data in the second param | ||
+ * | ||
+ * @param string | ||
+ * @param array | ||
+ * @param bool | ||
+ * @return string | ||
+ */ | ||
+ public function parse_string($template, $data, $return = FALSE) | ||
+ { | ||
+ return $this->_parse($template, $data, $return); | ||
+ } | ||
+ | ||
+ // -------------------------------------------------------------------- | ||
+ | ||
+ /** | ||
+ * Parse a template | ||
+ * | ||
+ * Parses pseudo-variables contained in the specified template, | ||
+ * replacing them with the data in the second param | ||
+ * | ||
+ * @param string | ||
+ * @param array | ||
+ * @param bool | ||
+ * @return string | ||
+ */ | ||
+ protected function _parse($template, $data, $return = FALSE) | ||
+ { | ||
+ if ($template === '') | ||
+ { | ||
+ return FALSE; | ||
+ } | ||
+ | ||
+ $replace = array(); | ||
+ foreach ($data as $key => $val) | ||
+ { | ||
+ $replace = array_merge( | ||
+ $replace, | ||
+ is_array($val) | ||
+ ? $this->_parse_pair($key, $val, $template) | ||
+ : $this->_parse_single($key, (string) $val, $template) | ||
+ ); | ||
+ } | ||
+ | ||
+ unset($data); | ||
+ $template = strtr($template, $replace); | ||
+ | ||
+ if ($return === FALSE) | ||
+ { | ||
+ $this->CI->output->append_output($template); | ||
+ } | ||
+ | ||
+ return $template; | ||
+ } | ||
+ | ||
+ // -------------------------------------------------------------------- | ||
+ | ||
+ /** | ||
+ * Set the left/right variable delimiters | ||
+ * | ||
+ * @param string | ||
+ * @param string | ||
+ * @return void | ||
+ */ | ||
+ public function set_delimiters($l = '{', $r = '}') | ||
+ { | ||
+ $this->l_delim = $l; | ||
+ $this->r_delim = $r; | ||
+ } | ||
+ | ||
+ // -------------------------------------------------------------------- | ||
+ | ||
+ /** | ||
+ * Parse a single key/value | ||
+ * | ||
+ * @param string | ||
+ * @param string | ||
+ * @param string | ||
+ * @return string | ||
+ */ | ||
+ protected function _parse_single($key, $val, $string) | ||
+ { | ||
+ return array($this->l_delim.$key.$this->r_delim => (string) $val); | ||
+ } | ||
+ | ||
+ // -------------------------------------------------------------------- | ||
+ | ||
+ /** | ||
+ * Parse a tag pair | ||
+ * | ||
+ * Parses tag pairs: {some_tag} string... {/some_tag} | ||
+ * | ||
+ * @param string | ||
+ * @param array | ||
+ * @param string | ||
+ * @return string | ||
+ */ | ||
+ protected function _parse_pair($variable, $data, $string) | ||
+ { | ||
+ $replace = array(); | ||
+ preg_match_all( | ||
+ '#'.preg_quote($this->l_delim.$variable.$this->r_delim).'(.+?)'.preg_quote($this->l_delim.'/'.$variable.$this->r_delim).'#s', | ||
+ $string, | ||
+ $matches, | ||
+ PREG_SET_ORDER | ||
+ ); | ||
+ | ||
+ foreach ($matches as $match) | ||
+ { | ||
+ $str = ''; | ||
+ foreach ($data as $row) | ||
+ { | ||
+ $temp = array(); | ||
+ foreach ($row as $key => $val) | ||
+ { | ||
+ if (is_array($val)) | ||
+ { | ||
+ $pair = $this->_parse_pair($key, $val, $match[1]); | ||
+ if ( ! empty($pair)) | ||
+ { | ||
+ $temp = array_merge($temp, $pair); | ||
+ } | ||
+ | ||
+ continue; | ||
+ } | ||
+ | ||
+ $temp[$this->l_delim.$key.$this->r_delim] = $val; | ||
+ } | ||
+ | ||
+ $str .= strtr($match[1], $temp); | ||
+ } | ||
+ | ||
+ $replace[$match[0]] = $str; | ||
+ } | ||
+ | ||
+ return $replace; | ||
+ } | ||
+ | ||
+} |
570
README/Profiler.php
@@ -0,0 +1,570 @@ | ||
+<?php | ||
+/** | ||
+ * CodeIgniter | ||
+ * | ||
+ * An open source application development framework for PHP | ||
+ * | ||
+ * This content is released under the MIT License (MIT) | ||
+ * | ||
+ * Copyright (c) 2014 - 2015, British Columbia Institute of Technology | ||
+ * | ||
+ * Permission is hereby granted, free of charge, to any person obtaining a copy | ||
+ * of this software and associated documentation files (the "Software"), to deal | ||
+ * in the Software without restriction, including without limitation the rights | ||
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | ||
+ * copies of the Software, and to permit persons to whom the Software is | ||
+ * furnished to do so, subject to the following conditions: | ||
+ * | ||
+ * The above copyright notice and this permission notice shall be included in | ||
+ * all copies or substantial portions of the Software. | ||
+ * | ||
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | ||
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | ||
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN | ||
+ * THE SOFTWARE. | ||
+ * | ||
+ * @package CodeIgniter | ||
+ * @author EllisLab Dev Team | ||
+ * @copyright Copyright (c) 2008 - 2014, EllisLab, Inc. (http://ellislab.com/) | ||
+ * @copyright Copyright (c) 2014 - 2015, British Columbia Institute of Technology (http://bcit.ca/) | ||
+ * @license http://opensource.org/licenses/MIT MIT License | ||
+ * @link http://codeigniter.com | ||
+ * @since Version 1.0.0 | ||
+ * @filesource | ||
+ */ | ||
+defined('BASEPATH') OR exit('No direct script access allowed'); | ||
+ | ||
+/** | ||
+ * CodeIgniter Profiler Class | ||
+ * | ||
+ * This class enables you to display benchmark, query, and other data | ||
+ * in order to help with debugging and optimization. | ||
+ * | ||
+ * Note: At some point it would be good to move all the HTML in this class | ||
+ * into a set of template files in order to allow customization. | ||
+ * | ||
+ * @package CodeIgniter | ||
+ * @subpackage Libraries | ||
+ * @category Libraries | ||
+ * @author EllisLab Dev Team | ||
+ * @link http://codeigniter.com/user_guide/general/profiling.html | ||
+ */ | ||
+class CI_Profiler { | ||
+ | ||
+ /** | ||
+ * List of profiler sections available to show | ||
+ * | ||
+ * @var array | ||
+ */ | ||
+ protected $_available_sections = array( | ||
+ 'benchmarks', | ||
+ 'get', | ||
+ 'memory_usage', | ||
+ 'post', | ||
+ 'uri_string', | ||
+ 'controller_info', | ||
+ 'queries', | ||
+ 'http_headers', | ||
+ 'session_data', | ||
+ 'config' | ||
+ ); | ||
+ | ||
+ /** | ||
+ * Number of queries to show before making the additional queries togglable | ||
+ * | ||
+ * @var int | ||
+ */ | ||
+ protected $_query_toggle_count = 25; | ||
+ | ||
+ /** | ||
+ * Reference to the CodeIgniter singleton | ||
+ * | ||
+ * @var object | ||
+ */ | ||
+ protected $CI; | ||
+ | ||
+ // -------------------------------------------------------------------- | ||
+ | ||
+ /** | ||
+ * Class constructor | ||
+ * | ||
+ * Initialize Profiler | ||
+ * | ||
+ * @param array $config Parameters | ||
+ */ | ||
+ public function __construct($config = array()) | ||
+ { | ||
+ $this->CI =& get_instance(); | ||
+ $this->CI->load->language('profiler'); | ||
+ | ||
+ // default all sections to display | ||
+ foreach ($this->_available_sections as $section) | ||
+ { | ||
+ if ( ! isset($config[$section])) | ||
+ { | ||
+ $this->_compile_{$section} = TRUE; | ||
+ } | ||
+ } | ||
+ | ||
+ $this->set_sections($config); | ||
+ log_message('info', 'Profiler Class Initialized'); | ||
+ } | ||
+ | ||
+ // -------------------------------------------------------------------- | ||
+ | ||
+ /** | ||
+ * Set Sections | ||
+ * | ||
+ * Sets the private _compile_* properties to enable/disable Profiler sections | ||
+ * | ||
+ * @param mixed $config | ||
+ * @return void | ||
+ */ | ||
+ public function set_sections($config) | ||
+ { | ||
+ if (isset($config['query_toggle_count'])) | ||
+ { | ||
+ $this->_query_toggle_count = (int) $config['query_toggle_count']; | ||
+ unset($config['query_toggle_count']); | ||
+ } | ||
+ | ||
+ foreach ($config as $method => $enable) | ||
+ { | ||
+ if (in_array($method, $this->_available_sections)) | ||
+ { | ||
+ $this->_compile_{$method} = ($enable !== FALSE); | ||
+ } | ||
+ } | ||
+ } | ||
+ | ||
+ // -------------------------------------------------------------------- | ||
+ | ||
+ /** | ||
+ * Auto Profiler | ||
+ * | ||
+ * This function cycles through the entire array of mark points and | ||
+ * matches any two points that are named identically (ending in "_start" | ||
+ * and "_end" respectively). It then compiles the execution times for | ||
+ * all points and returns it as an array | ||
+ * | ||
+ * @return array | ||
+ */ | ||
+ protected function _compile_benchmarks() | ||
+ { | ||
+ $profile = array(); | ||
+ foreach ($this->CI->benchmark->marker as $key => $val) | ||
+ { | ||
+ // We match the "end" marker so that the list ends | ||
+ // up in the order that it was defined | ||
+ if (preg_match('/(.+?)_end$/i', $key, $match) | ||
+ && isset($this->CI->benchmark->marker[$match[1].'_end'], $this->CI->benchmark->marker[$match[1].'_start'])) | ||
+ { | ||
+ $profile[$match[1]] = $this->CI->benchmark->elapsed_time($match[1].'_start', $key); | ||
+ } | ||
+ } | ||
+ | ||
+ // Build a table containing the profile data. | ||
+ // Note: At some point we should turn this into a template that can | ||
+ // be modified. We also might want to make this data available to be logged | ||
+ | ||
+ $output = "\n\n" | ||
+ .'<fieldset id="ci_profiler_benchmarks" style="border:1px solid #900;padding:6px 10px 10px 10px;margin:20px 0 20px 0;background-color:#eee;">' | ||
+ ."\n" | ||
+ .'<legend style="color:#900;"> '.$this->CI->lang->line('profiler_benchmarks')." </legend>" | ||
+ ."\n\n\n<table style=\"width:100%;\">\n"; | ||
+ | ||
+ foreach ($profile as $key => $val) | ||
+ { | ||
+ $key = ucwords(str_replace(array('_', '-'), ' ', $key)); | ||
+ $output .= '<tr><td style="padding:5px;width:50%;color:#000;font-weight:bold;background-color:#ddd;">' | ||
+ .$key.' </td><td style="padding:5px;width:50%;color:#900;font-weight:normal;background-color:#ddd;">' | ||
+ .$val."</td></tr>\n"; | ||
+ } | ||
+ | ||
+ return $output."</table>\n</fieldset>"; | ||
+ } | ||
+ | ||
+ // -------------------------------------------------------------------- | ||
+ | ||
+ /** | ||
+ * Compile Queries | ||
+ * | ||
+ * @return string | ||
+ */ | ||
+ protected function _compile_queries() | ||
+ { | ||
+ $dbs = array(); | ||
+ | ||
+ // Let's determine which databases are currently connected to | ||
+ foreach (get_object_vars($this->CI) as $name => $cobject) | ||
+ { | ||
+ if (is_object($cobject)) | ||
+ { | ||
+ if ($cobject instanceof CI_DB) | ||
+ { | ||
+ $dbs[get_class($this->CI).':$'.$name] = $cobject; | ||
+ } | ||
+ elseif ($cobject instanceof CI_Model) | ||
+ { | ||
+ foreach (get_object_vars($cobject) as $mname => $mobject) | ||
+ { | ||
+ if ($mobject instanceof CI_DB) | ||
+ { | ||
+ $dbs[get_class($cobject).':$'.$mname] = $mobject; | ||
+ } | ||
+ } | ||
+ } | ||
+ } | ||
+ } | ||
+ | ||
+ if (count($dbs) === 0) | ||
+ { | ||
+ return "\n\n" | ||
+ .'<fieldset id="ci_profiler_queries" style="border:1px solid #0000FF;padding:6px 10px 10px 10px;margin:20px 0 20px 0;background-color:#eee;">' | ||
+ ."\n" | ||
+ .'<legend style="color:#0000FF;"> '.$this->CI->lang->line('profiler_queries').' </legend>' | ||
+ ."\n\n\n<table style=\"border:none; width:100%;\">\n" | ||
+ .'<tr><td style="width:100%;color:#0000FF;font-weight:normal;background-color:#eee;padding:5px;">' | ||
+ .$this->CI->lang->line('profiler_no_db') | ||
+ ."</td></tr>\n</table>\n</fieldset>"; | ||
+ } | ||
+ | ||
+ // Load the text helper so we can highlight the SQL | ||
+ $this->CI->load->helper('text'); | ||
+ | ||
+ // Key words we want bolded | ||
+ $highlight = array('SELECT', 'DISTINCT', 'FROM', 'WHERE', 'AND', 'LEFT JOIN', 'ORDER BY', 'GROUP BY', 'LIMIT', 'INSERT', 'INTO', 'VALUES', 'UPDATE', 'OR ', 'HAVING', 'OFFSET', 'NOT IN', 'IN', 'LIKE', 'NOT LIKE', 'COUNT', 'MAX', 'MIN', 'ON', 'AS', 'AVG', 'SUM', '(', ')'); | ||
+ | ||
+ $output = "\n\n"; | ||
+ $count = 0; | ||
+ | ||
+ foreach ($dbs as $name => $db) | ||
+ { | ||
+ $hide_queries = (count($db->queries) > $this->_query_toggle_count) ? ' display:none' : ''; | ||
+ $total_time = number_format(array_sum($db->query_times), 4).' '.$this->CI->lang->line('profiler_seconds'); | ||
+ | ||
+ $show_hide_js = '(<span style="cursor: pointer;" onclick="var s=document.getElementById(\'ci_profiler_queries_db_'.$count.'\').style;s.display=s.display==\'none\'?\'\':\'none\';this.innerHTML=this.innerHTML==\''.$this->CI->lang->line('profiler_section_hide').'\'?\''.$this->CI->lang->line('profiler_section_show').'\':\''.$this->CI->lang->line('profiler_section_hide').'\';">'.$this->CI->lang->line('profiler_section_hide').'</span>)'; | ||
+ | ||
+ if ($hide_queries !== '') | ||
+ { | ||
+ $show_hide_js = '(<span style="cursor: pointer;" onclick="var s=document.getElementById(\'ci_profiler_queries_db_'.$count.'\').style;s.display=s.display==\'none\'?\'\':\'none\';this.innerHTML=this.innerHTML==\''.$this->CI->lang->line('profiler_section_show').'\'?\''.$this->CI->lang->line('profiler_section_hide').'\':\''.$this->CI->lang->line('profiler_section_show').'\';">'.$this->CI->lang->line('profiler_section_show').'</span>)'; | ||
+ } | ||
+ | ||
+ $output .= '<fieldset style="border:1px solid #0000FF;padding:6px 10px 10px 10px;margin:20px 0 20px 0;background-color:#eee;">' | ||
+ ."\n" | ||
+ .'<legend style="color:#0000FF;"> '.$this->CI->lang->line('profiler_database') | ||
+ .': '.$db->database.' ('.$name.') '.$this->CI->lang->line('profiler_queries') | ||
+ .': '.count($db->queries).' ('.$total_time.') '.$show_hide_js."</legend>\n\n\n" | ||
+ .'<table style="width:100%;'.$hide_queries.'" id="ci_profiler_queries_db_'.$count."\">\n"; | ||
+ | ||
+ if (count($db->queries) === 0) | ||
+ { | ||
+ $output .= '<tr><td style="width:100%;color:#0000FF;font-weight:normal;background-color:#eee;padding:5px;">' | ||
+ .$this->CI->lang->line('profiler_no_queries')."</td></tr>\n"; | ||
+ } | ||
+ else | ||
+ { | ||
+ foreach ($db->queries as $key => $val) | ||
+ { | ||
+ $time = number_format($db->query_times[$key], 4); | ||
+ $val = highlight_code($val); | ||
+ | ||
+ foreach ($highlight as $bold) | ||
+ { | ||
+ $val = str_replace($bold, '<strong>'.$bold.'</strong>', $val); | ||
+ } | ||
+ | ||
+ $output .= '<tr><td style="padding:5px;vertical-align:top;width:1%;color:#900;font-weight:normal;background-color:#ddd;">' | ||
+ .$time.' </td><td style="padding:5px;color:#000;font-weight:normal;background-color:#ddd;">' | ||
+ .$val."</td></tr>\n"; | ||
+ } | ||
+ } | ||
+ | ||
+ $output .= "</table>\n</fieldset>"; | ||
+ $count++; | ||
+ } | ||
+ | ||
+ return $output; | ||
+ } | ||
+ | ||
+ // -------------------------------------------------------------------- | ||
+ | ||
+ /** | ||
+ * Compile $_GET Data | ||
+ * | ||
+ * @return string | ||
+ */ | ||
+ protected function _compile_get() | ||
+ { | ||
+ $output = "\n\n" | ||
+ .'<fieldset id="ci_profiler_get" style="border:1px solid #cd6e00;padding:6px 10px 10px 10px;margin:20px 0 20px 0;background-color:#eee;">' | ||
+ ."\n" | ||
+ .'<legend style="color:#cd6e00;"> '.$this->CI->lang->line('profiler_get_data')." </legend>\n"; | ||
+ | ||
+ if (count($_GET) === 0) | ||
+ { | ||
+ $output .= '<div style="color:#cd6e00;font-weight:normal;padding:4px 0 4px 0;">'.$this->CI->lang->line('profiler_no_get').'</div>'; | ||
+ } | ||
+ else | ||
+ { | ||
+ $output .= "\n\n<table style=\"width:100%;border:none;\">\n"; | ||
+ | ||
+ foreach ($_GET as $key => $val) | ||
+ { | ||
+ is_int($key) OR $key = "'".$key."'"; | ||
+ | ||
+ $output .= '<tr><td style="width:50%;color:#000;background-color:#ddd;padding:5px;">$_GET[' | ||
+ .$key.'] </td><td style="width:50%;padding:5px;color:#cd6e00;font-weight:normal;background-color:#ddd;">' | ||
+ .((is_array($val) OR is_object($val)) ? '<pre>'.htmlspecialchars(stripslashes(print_r($val, TRUE))).'</pre>' : htmlspecialchars(stripslashes($val))) | ||
+ ."</td></tr>\n"; | ||
+ } | ||
+ | ||
+ $output .= "</table>\n"; | ||
+ } | ||
+ | ||
+ return $output.'</fieldset>'; | ||
+ } | ||
+ | ||
+ // -------------------------------------------------------------------- | ||
+ | ||
+ /** | ||
+ * Compile $_POST Data | ||
+ * | ||
+ * @return string | ||
+ */ | ||
+ protected function _compile_post() | ||
+ { | ||
+ $output = "\n\n" | ||
+ .'<fieldset id="ci_profiler_post" style="border:1px solid #009900;padding:6px 10px 10px 10px;margin:20px 0 20px 0;background-color:#eee;">' | ||
+ ."\n" | ||
+ .'<legend style="color:#009900;"> '.$this->CI->lang->line('profiler_post_data')." </legend>\n"; | ||
+ | ||
+ if (count($_POST) === 0 && count($_FILES) === 0) | ||
+ { | ||
+ $output .= '<div style="color:#009900;font-weight:normal;padding:4px 0 4px 0;">'.$this->CI->lang->line('profiler_no_post').'</div>'; | ||
+ } | ||
+ else | ||
+ { | ||
+ $output .= "\n\n<table style=\"width:100%;\">\n"; | ||
+ | ||
+ foreach ($_POST as $key => $val) | ||
+ { | ||
+ is_int($key) OR $key = "'".$key."'"; | ||
+ | ||
+ $output .= '<tr><td style="width:50%;padding:5px;color:#000;background-color:#ddd;">$_POST[' | ||
+ .$key.'] </td><td style="width:50%;padding:5px;color:#009900;font-weight:normal;background-color:#ddd;">'; | ||
+ | ||
+ if (is_array($val) OR is_object($val)) | ||
+ { | ||
+ $output .= '<pre>'.htmlspecialchars(stripslashes(print_r($val, TRUE))).'</pre>'; | ||
+ } | ||
+ else | ||
+ { | ||
+ $output .= htmlspecialchars(stripslashes($val)); | ||
+ } | ||
+ | ||
+ $output .= "</td></tr>\n"; | ||
+ } | ||
+ | ||
+ foreach ($_FILES as $key => $val) | ||
+ { | ||
+ is_int($key) OR $key = "'".$key."'"; | ||
+ | ||
+ $output .= '<tr><td style="width:50%;padding:5px;color:#000;background-color:#ddd;">$_FILES[' | ||
+ .$key.'] </td><td style="width:50%;padding:5px;color:#009900;font-weight:normal;background-color:#ddd;">'; | ||
+ | ||
+ if (is_array($val) OR is_object($val)) | ||
+ { | ||
+ $output .= '<pre>'.htmlspecialchars(stripslashes(print_r($val, TRUE))).'</pre>'; | ||
+ } | ||
+ | ||
+ $output .= "</td></tr>\n"; | ||
+ } | ||
+ | ||
+ $output .= "</table>\n"; | ||
+ } | ||
+ | ||
+ return $output.'</fieldset>'; | ||
+ } | ||
+ | ||
+ // -------------------------------------------------------------------- | ||
+ | ||
+ /** | ||
+ * Show query string | ||
+ * | ||
+ * @return string | ||
+ */ | ||
+ protected function _compile_uri_string() | ||
+ { | ||
+ return "\n\n" | ||
+ .'<fieldset id="ci_profiler_uri_string" style="border:1px solid #000;padding:6px 10px 10px 10px;margin:20px 0 20px 0;background-color:#eee;">' | ||
+ ."\n" | ||
+ .'<legend style="color:#000;"> '.$this->CI->lang->line('profiler_uri_string')." </legend>\n" | ||
+ .'<div style="color:#000;font-weight:normal;padding:4px 0 4px 0;">' | ||
+ .($this->CI->uri->uri_string === '' ? $this->CI->lang->line('profiler_no_uri') : $this->CI->uri->uri_string) | ||
+ .'</div></fieldset>'; | ||
+ } | ||
+ | ||
+ // -------------------------------------------------------------------- | ||
+ | ||
+ /** | ||
+ * Show the controller and function that were called | ||
+ * | ||
+ * @return string | ||
+ */ | ||
+ protected function _compile_controller_info() | ||
+ { | ||
+ return "\n\n" | ||
+ .'<fieldset id="ci_profiler_controller_info" style="border:1px solid #995300;padding:6px 10px 10px 10px;margin:20px 0 20px 0;background-color:#eee;">' | ||
+ ."\n" | ||
+ .'<legend style="color:#995300;"> '.$this->CI->lang->line('profiler_controller_info')." </legend>\n" | ||
+ .'<div style="color:#995300;font-weight:normal;padding:4px 0 4px 0;">'.$this->CI->router->class.'/'.$this->CI->router->method | ||
+ .'</div></fieldset>'; | ||
+ } | ||
+ | ||
+ // -------------------------------------------------------------------- | ||
+ | ||
+ /** | ||
+ * Compile memory usage | ||
+ * | ||
+ * Display total used memory | ||
+ * | ||
+ * @return string | ||
+ */ | ||
+ protected function _compile_memory_usage() | ||
+ { | ||
+ return "\n\n" | ||
+ .'<fieldset id="ci_profiler_memory_usage" style="border:1px solid #5a0099;padding:6px 10px 10px 10px;margin:20px 0 20px 0;background-color:#eee;">' | ||
+ ."\n" | ||
+ .'<legend style="color:#5a0099;"> '.$this->CI->lang->line('profiler_memory_usage')." </legend>\n" | ||
+ .'<div style="color:#5a0099;font-weight:normal;padding:4px 0 4px 0;">' | ||
+ .(($usage = memory_get_usage()) != '' ? number_format($usage).' bytes' : $this->CI->lang->line('profiler_no_memory')) | ||
+ .'</div></fieldset>'; | ||
+ } | ||
+ | ||
+ // -------------------------------------------------------------------- | ||
+ | ||
+ /** | ||
+ * Compile header information | ||
+ * | ||
+ * Lists HTTP headers | ||
+ * | ||
+ * @return string | ||
+ */ | ||
+ protected function _compile_http_headers() | ||
+ { | ||
+ $output = "\n\n" | ||
+ .'<fieldset id="ci_profiler_http_headers" style="border:1px solid #000;padding:6px 10px 10px 10px;margin:20px 0 20px 0;background-color:#eee;">' | ||
+ ."\n" | ||
+ .'<legend style="color:#000;"> '.$this->CI->lang->line('profiler_headers') | ||
+ .' (<span style="cursor: pointer;" onclick="var s=document.getElementById(\'ci_profiler_httpheaders_table\').style;s.display=s.display==\'none\'?\'\':\'none\';this.innerHTML=this.innerHTML==\''.$this->CI->lang->line('profiler_section_show').'\'?\''.$this->CI->lang->line('profiler_section_hide').'\':\''.$this->CI->lang->line('profiler_section_show').'\';">'.$this->CI->lang->line('profiler_section_show')."</span>)</legend>\n\n\n" | ||
+ .'<table style="width:100%;display:none;" id="ci_profiler_httpheaders_table">'."\n"; | ||
+ | ||
+ foreach (array('HTTP_ACCEPT', 'HTTP_USER_AGENT', 'HTTP_CONNECTION', 'SERVER_PORT', 'SERVER_NAME', 'REMOTE_ADDR', 'SERVER_SOFTWARE', 'HTTP_ACCEPT_LANGUAGE', 'SCRIPT_NAME', 'REQUEST_METHOD',' HTTP_HOST', 'REMOTE_HOST', 'CONTENT_TYPE', 'SERVER_PROTOCOL', 'QUERY_STRING', 'HTTP_ACCEPT_ENCODING', 'HTTP_X_FORWARDED_FOR', 'HTTP_DNT') as $header) | ||
+ { | ||
+ $val = isset($_SERVER[$header]) ? $_SERVER[$header] : ''; | ||
+ $output .= '<tr><td style="vertical-align:top;width:50%;padding:5px;color:#900;background-color:#ddd;">' | ||
+ .$header.' </td><td style="width:50%;padding:5px;color:#000;background-color:#ddd;">'.$val."</td></tr>\n"; | ||
+ } | ||
+ | ||
+ return $output."</table>\n</fieldset>"; | ||
+ } | ||
+ | ||
+ // -------------------------------------------------------------------- | ||
+ | ||
+ /** | ||
+ * Compile config information | ||
+ * | ||
+ * Lists developer config variables | ||
+ * | ||
+ * @return string | ||
+ */ | ||
+ protected function _compile_config() | ||
+ { | ||
+ $output = "\n\n" | ||
+ .'<fieldset id="ci_profiler_config" style="border:1px solid #000;padding:6px 10px 10px 10px;margin:20px 0 20px 0;background-color:#eee;">' | ||
+ ."\n" | ||
+ .'<legend style="color:#000;"> '.$this->CI->lang->line('profiler_config').' (<span style="cursor: pointer;" onclick="var s=document.getElementById(\'ci_profiler_config_table\').style;s.display=s.display==\'none\'?\'\':\'none\';this.innerHTML=this.innerHTML==\''.$this->CI->lang->line('profiler_section_show').'\'?\''.$this->CI->lang->line('profiler_section_hide').'\':\''.$this->CI->lang->line('profiler_section_show').'\';">'.$this->CI->lang->line('profiler_section_show')."</span>)</legend>\n\n\n" | ||
+ .'<table style="width:100%;display:none;" id="ci_profiler_config_table">'."\n"; | ||
+ | ||
+ foreach ($this->CI->config->config as $config => $val) | ||
+ { | ||
+ if (is_array($val) OR is_object($val)) | ||
+ { | ||
+ $val = print_r($val, TRUE); | ||
+ } | ||
+ | ||
+ $output .= '<tr><td style="padding:5px;vertical-align:top;color:#900;background-color:#ddd;">' | ||
+ .$config.' </td><td style="padding:5px;color:#000;background-color:#ddd;">'.htmlspecialchars($val)."</td></tr>\n"; | ||
+ } | ||
+ | ||
+ return $output."</table>\n</fieldset>"; | ||
+ } | ||
+ | ||
+ // -------------------------------------------------------------------- | ||
+ | ||
+ /** | ||
+ * Compile session userdata | ||
+ * | ||
+ * @return string | ||
+ */ | ||
+ protected function _compile_session_data() | ||
+ { | ||
+ if ( ! isset($this->CI->session)) | ||
+ { | ||
+ return; | ||
+ } | ||
+ | ||
+ $output = '<fieldset id="ci_profiler_csession" style="border:1px solid #000;padding:6px 10px 10px 10px;margin:20px 0 20px 0;background-color:#eee;">' | ||
+ .'<legend style="color:#000;"> '.$this->CI->lang->line('profiler_session_data').' (<span style="cursor: pointer;" onclick="var s=document.getElementById(\'ci_profiler_session_data\').style;s.display=s.display==\'none\'?\'\':\'none\';this.innerHTML=this.innerHTML==\''.$this->CI->lang->line('profiler_section_show').'\'?\''.$this->CI->lang->line('profiler_section_hide').'\':\''.$this->CI->lang->line('profiler_section_show').'\';">'.$this->CI->lang->line('profiler_section_show').'</span>)</legend>' | ||
+ .'<table style="width:100%;display:none;" id="ci_profiler_session_data">'; | ||
+ | ||
+ foreach ($this->CI->session->userdata() as $key => $val) | ||
+ { | ||
+ if (is_array($val) OR is_object($val)) | ||
+ { | ||
+ $val = print_r($val, TRUE); | ||
+ } | ||
+ | ||
+ $output .= '<tr><td style="padding:5px;vertical-align:top;color:#900;background-color:#ddd;">' | ||
+ .$key.' </td><td style="padding:5px;color:#000;background-color:#ddd;">'.htmlspecialchars($val)."</td></tr>\n"; | ||
+ } | ||
+ | ||
+ return $output."</table>\n</fieldset>"; | ||
+ } | ||
+ | ||
+ // -------------------------------------------------------------------- | ||
+ | ||
+ /** | ||
+ * Run the Profiler | ||
+ * | ||
+ * @return string | ||
+ */ | ||
+ public function run() | ||
+ { | ||
+ $output = '<div id="codeigniter_profiler" style="clear:both;background-color:#fff;padding:10px;">'; | ||
+ $fields_displayed = 0; | ||
+ | ||
+ foreach ($this->_available_sections as $section) | ||
+ { | ||
+ if ($this->_compile_{$section} !== FALSE) | ||
+ { | ||
+ $func = '_compile_'.$section; | ||
+ $output .= $this->{$func}(); | ||
+ $fields_displayed++; | ||
+ } | ||
+ } | ||
+ | ||
+ if ($fields_displayed === 0) | ||
+ { | ||
+ $output .= '<p style="border:1px solid #5a0099;padding:10px;margin:20px 0;background-color:#eee;">' | ||
+ .$this->CI->lang->line('profiler_no_profiles').'</p>'; | ||
+ } | ||
+ | ||
+ return $output.'</div>'; | ||
+ } | ||
+ | ||
+} |
0
README/README.php
Sorry, we could not display the changes to this file because there were too many other changes to display.
0
README/Session/Session.php
Sorry, we could not display the changes to this file because there were too many other changes to display.
0
README/Session/SessionHandlerInterface.php
Sorry, we could not display the changes to this file because there were too many other changes to display.
0
README/Session/Session_driver.php
Sorry, we could not display the changes to this file because there were too many other changes to display.
0
README/Session/drivers/Session_database_driver.php
Sorry, we could not display the changes to this file because there were too many other changes to display.
0
README/Session/drivers/Session_files_driver.php
Sorry, we could not display the changes to this file because there were too many other changes to display.
0
README/Session/drivers/Session_memcached_driver.php
Sorry, we could not display the changes to this file because there were too many other changes to display.
0
README/Session/drivers/Session_redis_driver.php
Sorry, we could not display the changes to this file because there were too many other changes to display.
0
README/Session/drivers/index.html
Sorry, we could not display the changes to this file because there were too many other changes to display.
0
README/Session/index.html
Sorry, we could not display the changes to this file because there were too many other changes to display.
0
README/Table.php
Sorry, we could not display the changes to this file because there were too many other changes to display.
0
README/Trackback.php
Sorry, we could not display the changes to this file because there were too many other changes to display.
0
README/Typography.php
Sorry, we could not display the changes to this file because there were too many other changes to display.
0
README/Unit_test.php
Sorry, we could not display the changes to this file because there were too many other changes to display.
0
README/Upload.php
Sorry, we could not display the changes to this file because there were too many other changes to display.
0
README/User_agent.php
Sorry, we could not display the changes to this file because there were too many other changes to display.
0
README/Xmlrpc.php
Sorry, we could not display the changes to this file because there were too many other changes to display.
0
README/Xmlrpcs.php
Sorry, we could not display the changes to this file because there were too many other changes to display.
0
README/Zip.php
Sorry, we could not display the changes to this file because there were too many other changes to display.
0
README/index.html
Sorry, we could not display the changes to this file because there were too many other changes to display.
0 comments on commit
41e52c9