New upstream version 0.6.27
This commit is contained in:
@@ -1,4 +1,12 @@
|
||||
<?php defined('SYSPATH') OR die('No direct access allowed.');
|
||||
<?php
|
||||
|
||||
// phpcs:disable PSR1.Classes.ClassDeclaration.MissingNamespace
|
||||
// phpcs:disable PSR1.Files.SideEffects
|
||||
defined('SYSPATH') or die('No direct access allowed.');
|
||||
// phpcs:enable PSR1.Files.SideEffects
|
||||
// phpcs:disable Squiz.Classes.ValidClassName.NotCamelCaps
|
||||
|
||||
|
||||
/**
|
||||
* Cache driver interface.
|
||||
*
|
||||
@@ -9,32 +17,32 @@
|
||||
* @copyright (c) 2007-2008 Kohana Team
|
||||
* @license http://kohanaphp.com/license.html
|
||||
*/
|
||||
interface Cache_Driver {
|
||||
interface Cache_Driver
|
||||
{
|
||||
/**
|
||||
* Set a cache item.
|
||||
*/
|
||||
public function set($id, $data, array $tags = null, $lifetime);
|
||||
|
||||
/**
|
||||
* Set a cache item.
|
||||
*/
|
||||
public function set($id, $data, array $tags = NULL, $lifetime);
|
||||
/**
|
||||
* Find all of the cache ids for a given tag.
|
||||
*/
|
||||
public function find($tag);
|
||||
|
||||
/**
|
||||
* Find all of the cache ids for a given tag.
|
||||
*/
|
||||
public function find($tag);
|
||||
/**
|
||||
* Get a cache item.
|
||||
* Return NULL if the cache item is not found.
|
||||
*/
|
||||
public function get($id);
|
||||
|
||||
/**
|
||||
* Get a cache item.
|
||||
* Return NULL if the cache item is not found.
|
||||
*/
|
||||
public function get($id);
|
||||
/**
|
||||
* Delete cache items by id or tag.
|
||||
*/
|
||||
public function delete($id, $tag = false);
|
||||
|
||||
/**
|
||||
* Delete cache items by id or tag.
|
||||
*/
|
||||
public function delete($id, $tag = FALSE);
|
||||
|
||||
/**
|
||||
* Deletes all expired cache items.
|
||||
*/
|
||||
public function delete_expired();
|
||||
|
||||
} // End Cache Driver
|
||||
/**
|
||||
* Deletes all expired cache items.
|
||||
*/
|
||||
public function delete_expired();
|
||||
}
|
||||
// End Cache Driver
|
||||
|
||||
@@ -1,4 +1,12 @@
|
||||
<?php defined('SYSPATH') OR die('No direct access allowed.');
|
||||
<?php
|
||||
|
||||
// phpcs:disable PSR1.Classes.ClassDeclaration.MissingNamespace
|
||||
// phpcs:disable PSR1.Files.SideEffects
|
||||
defined('SYSPATH') or die('No direct access allowed.');
|
||||
// phpcs:enable PSR1.Files.SideEffects
|
||||
// phpcs:disable Squiz.Classes.ValidClassName.NotCamelCaps
|
||||
|
||||
|
||||
/**
|
||||
* APC-based Cache driver.
|
||||
*
|
||||
@@ -9,56 +17,51 @@
|
||||
* @copyright (c) 2007-2008 Kohana Team
|
||||
* @license http://kohanaphp.com/license.html
|
||||
*/
|
||||
class Cache_Apc_Driver implements Cache_Driver {
|
||||
class Cache_Apc_Driver implements Cache_Driver
|
||||
{
|
||||
public function __construct()
|
||||
{
|
||||
if (! extension_loaded('apc')) {
|
||||
throw new Kohana_Exception('cache.extension_not_loaded', 'apc');
|
||||
}
|
||||
}
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
if ( ! extension_loaded('apc'))
|
||||
throw new Kohana_Exception('cache.extension_not_loaded', 'apc');
|
||||
}
|
||||
public function get($id)
|
||||
{
|
||||
return (($return = apc_fetch($id)) === false) ? null : $return;
|
||||
}
|
||||
|
||||
public function get($id)
|
||||
{
|
||||
return (($return = apc_fetch($id)) === FALSE) ? NULL : $return;
|
||||
}
|
||||
public function set($id, $data, array $tags = null, $lifetime)
|
||||
{
|
||||
if (! empty($tags)) {
|
||||
Kohana::log('error', 'Cache: tags are unsupported by the APC driver');
|
||||
}
|
||||
|
||||
public function set($id, $data, array $tags = NULL, $lifetime)
|
||||
{
|
||||
if ( ! empty($tags))
|
||||
{
|
||||
Kohana::log('error', 'Cache: tags are unsupported by the APC driver');
|
||||
}
|
||||
return apc_store($id, $data, $lifetime);
|
||||
}
|
||||
|
||||
return apc_store($id, $data, $lifetime);
|
||||
}
|
||||
public function find($tag)
|
||||
{
|
||||
Kohana::log('error', 'Cache: tags are unsupported by the APC driver');
|
||||
|
||||
public function find($tag)
|
||||
{
|
||||
Kohana::log('error', 'Cache: tags are unsupported by the APC driver');
|
||||
return array();
|
||||
}
|
||||
|
||||
return array();
|
||||
}
|
||||
public function delete($id, $tag = false)
|
||||
{
|
||||
if ($tag === true) {
|
||||
Kohana::log('error', 'Cache: tags are unsupported by the APC driver');
|
||||
return false;
|
||||
} elseif ($id === true) {
|
||||
return apc_clear_cache('user');
|
||||
} else {
|
||||
return apc_delete($id);
|
||||
}
|
||||
}
|
||||
|
||||
public function delete($id, $tag = FALSE)
|
||||
{
|
||||
if ($tag === TRUE)
|
||||
{
|
||||
Kohana::log('error', 'Cache: tags are unsupported by the APC driver');
|
||||
return FALSE;
|
||||
}
|
||||
elseif ($id === TRUE)
|
||||
{
|
||||
return apc_clear_cache('user');
|
||||
}
|
||||
else
|
||||
{
|
||||
return apc_delete($id);
|
||||
}
|
||||
}
|
||||
|
||||
public function delete_expired()
|
||||
{
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
} // End Cache APC Driver
|
||||
public function delete_expired()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
// End Cache APC Driver
|
||||
|
||||
@@ -1,4 +1,12 @@
|
||||
<?php defined('SYSPATH') OR die('No direct access allowed.');
|
||||
<?php
|
||||
|
||||
// phpcs:disable PSR1.Classes.ClassDeclaration.MissingNamespace
|
||||
// phpcs:disable PSR1.Files.SideEffects
|
||||
defined('SYSPATH') or die('No direct access allowed.');
|
||||
// phpcs:enable PSR1.Files.SideEffects
|
||||
// phpcs:disable Squiz.Classes.ValidClassName.NotCamelCaps
|
||||
|
||||
|
||||
/**
|
||||
* Eaccelerator-based Cache driver.
|
||||
*
|
||||
@@ -9,58 +17,53 @@
|
||||
* @copyright (c) 2007-2008 Kohana Team
|
||||
* @license http://kohanaphp.com/license.html
|
||||
*/
|
||||
class Cache_Eaccelerator_Driver implements Cache_Driver {
|
||||
class Cache_Eaccelerator_Driver implements Cache_Driver
|
||||
{
|
||||
public function __construct()
|
||||
{
|
||||
if (! extension_loaded('eaccelerator')) {
|
||||
throw new Kohana_Exception('cache.extension_not_loaded', 'eaccelerator');
|
||||
}
|
||||
}
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
if ( ! extension_loaded('eaccelerator'))
|
||||
throw new Kohana_Exception('cache.extension_not_loaded', 'eaccelerator');
|
||||
}
|
||||
public function get($id)
|
||||
{
|
||||
return eaccelerator_get($id);
|
||||
}
|
||||
|
||||
public function get($id)
|
||||
{
|
||||
return eaccelerator_get($id);
|
||||
}
|
||||
public function find($tag)
|
||||
{
|
||||
Kohana::log('error', 'tags are unsupported by the eAccelerator driver');
|
||||
|
||||
public function find($tag)
|
||||
{
|
||||
Kohana::log('error', 'tags are unsupported by the eAccelerator driver');
|
||||
return array();
|
||||
}
|
||||
|
||||
return array();
|
||||
}
|
||||
public function set($id, $data, array $tags = null, $lifetime)
|
||||
{
|
||||
if (! empty($tags)) {
|
||||
Kohana::log('error', 'tags are unsupported by the eAccelerator driver');
|
||||
}
|
||||
|
||||
public function set($id, $data, array $tags = NULL, $lifetime)
|
||||
{
|
||||
if ( ! empty($tags))
|
||||
{
|
||||
Kohana::log('error', 'tags are unsupported by the eAccelerator driver');
|
||||
}
|
||||
return eaccelerator_put($id, $data, $lifetime);
|
||||
}
|
||||
|
||||
return eaccelerator_put($id, $data, $lifetime);
|
||||
}
|
||||
public function delete($id, $tag = false)
|
||||
{
|
||||
if ($tag === true) {
|
||||
Kohana::log('error', 'tags are unsupported by the eAccelerator driver');
|
||||
return false;
|
||||
} elseif ($id === true) {
|
||||
return eaccelerator_clean();
|
||||
} else {
|
||||
return eaccelerator_rm($id);
|
||||
}
|
||||
}
|
||||
|
||||
public function delete($id, $tag = FALSE)
|
||||
{
|
||||
if ($tag === TRUE)
|
||||
{
|
||||
Kohana::log('error', 'tags are unsupported by the eAccelerator driver');
|
||||
return FALSE;
|
||||
}
|
||||
elseif ($id === TRUE)
|
||||
{
|
||||
return eaccelerator_clean();
|
||||
}
|
||||
else
|
||||
{
|
||||
return eaccelerator_rm($id);
|
||||
}
|
||||
}
|
||||
public function delete_expired()
|
||||
{
|
||||
eaccelerator_gc();
|
||||
|
||||
public function delete_expired()
|
||||
{
|
||||
eaccelerator_gc();
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
} // End Cache eAccelerator Driver
|
||||
return true;
|
||||
}
|
||||
}
|
||||
// End Cache eAccelerator Driver
|
||||
|
||||
@@ -1,4 +1,12 @@
|
||||
<?php defined('SYSPATH') OR die('No direct access allowed.');
|
||||
<?php
|
||||
|
||||
// phpcs:disable PSR1.Classes.ClassDeclaration.MissingNamespace
|
||||
// phpcs:disable PSR1.Files.SideEffects
|
||||
defined('SYSPATH') or die('No direct access allowed.');
|
||||
// phpcs:enable PSR1.Files.SideEffects
|
||||
// phpcs:disable Squiz.Classes.ValidClassName.NotCamelCaps
|
||||
|
||||
|
||||
/**
|
||||
* File-based Cache driver.
|
||||
*
|
||||
@@ -9,253 +17,235 @@
|
||||
* @copyright (c) 2007-2008 Kohana Team
|
||||
* @license http://kohanaphp.com/license.html
|
||||
*/
|
||||
class Cache_File_Driver implements Cache_Driver {
|
||||
class Cache_File_Driver implements Cache_Driver
|
||||
{
|
||||
protected $directory = '';
|
||||
|
||||
protected $directory = '';
|
||||
/**
|
||||
* Tests that the storage location is a directory and is writable.
|
||||
*/
|
||||
public function __construct($directory)
|
||||
{
|
||||
// Find the real path to the directory
|
||||
$directory = str_replace('\\', '/', realpath($directory)) . '/';
|
||||
|
||||
/**
|
||||
* Tests that the storage location is a directory and is writable.
|
||||
*/
|
||||
public function __construct($directory)
|
||||
{
|
||||
// Find the real path to the directory
|
||||
$directory = str_replace('\\', '/', realpath($directory)).'/';
|
||||
// Make sure the cache directory is writable
|
||||
if (! is_dir($directory) or ! is_writable($directory)) {
|
||||
throw new Kohana_Exception('cache.unwritable', $directory);
|
||||
}
|
||||
|
||||
// Make sure the cache directory is writable
|
||||
if ( ! is_dir($directory) OR ! is_writable($directory))
|
||||
throw new Kohana_Exception('cache.unwritable', $directory);
|
||||
// Directory is valid
|
||||
$this->directory = $directory;
|
||||
}
|
||||
|
||||
// Directory is valid
|
||||
$this->directory = $directory;
|
||||
}
|
||||
/**
|
||||
* Finds an array of files matching the given id or tag.
|
||||
*
|
||||
* @param string cache id or tag
|
||||
* @param bool search for tags
|
||||
* @return array of filenames matching the id or tag
|
||||
*/
|
||||
public function exists($id, $tag = false)
|
||||
{
|
||||
if ($id === true) {
|
||||
// Find all the files
|
||||
return glob($this->directory . '*~*~*');
|
||||
} elseif ($tag === true) {
|
||||
// Find all the files that have the tag name
|
||||
$paths = glob($this->directory . '*~*' . $id . '*~*');
|
||||
|
||||
/**
|
||||
* Finds an array of files matching the given id or tag.
|
||||
*
|
||||
* @param string cache id or tag
|
||||
* @param bool search for tags
|
||||
* @return array of filenames matching the id or tag
|
||||
*/
|
||||
public function exists($id, $tag = FALSE)
|
||||
{
|
||||
if ($id === TRUE)
|
||||
{
|
||||
// Find all the files
|
||||
return glob($this->directory.'*~*~*');
|
||||
}
|
||||
elseif ($tag === TRUE)
|
||||
{
|
||||
// Find all the files that have the tag name
|
||||
$paths = glob($this->directory.'*~*'.$id.'*~*');
|
||||
// Find all tags matching the given tag
|
||||
$files = array();
|
||||
foreach ($paths as $path) {
|
||||
// Split the files
|
||||
$tags = explode('~', basename($path));
|
||||
|
||||
// Find all tags matching the given tag
|
||||
$files = array();
|
||||
foreach ($paths as $path)
|
||||
{
|
||||
// Split the files
|
||||
$tags = explode('~', basename($path));
|
||||
// Find valid tags
|
||||
if (count($tags) !== 3 or empty($tags[1])) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Find valid tags
|
||||
if (count($tags) !== 3 OR empty($tags[1]))
|
||||
continue;
|
||||
// Split the tags by plus signs, used to separate tags
|
||||
$tags = explode('+', $tags[1]);
|
||||
|
||||
// Split the tags by plus signs, used to separate tags
|
||||
$tags = explode('+', $tags[1]);
|
||||
if (in_array($tag, $tags)) {
|
||||
// Add the file to the array, it has the requested tag
|
||||
$files[] = $path;
|
||||
}
|
||||
}
|
||||
|
||||
if (in_array($tag, $tags))
|
||||
{
|
||||
// Add the file to the array, it has the requested tag
|
||||
$files[] = $path;
|
||||
}
|
||||
}
|
||||
return $files;
|
||||
} else {
|
||||
// Find the file matching the given id
|
||||
return glob($this->directory . $id . '~*');
|
||||
}
|
||||
}
|
||||
|
||||
return $files;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Find the file matching the given id
|
||||
return glob($this->directory.$id.'~*');
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Sets a cache item to the given data, tags, and lifetime.
|
||||
*
|
||||
* @param string cache id to set
|
||||
* @param string data in the cache
|
||||
* @param array cache tags
|
||||
* @param integer lifetime
|
||||
* @return bool
|
||||
*/
|
||||
public function set($id, $data, array $tags = null, $lifetime)
|
||||
{
|
||||
// Remove old cache files
|
||||
$this->delete($id);
|
||||
|
||||
/**
|
||||
* Sets a cache item to the given data, tags, and lifetime.
|
||||
*
|
||||
* @param string cache id to set
|
||||
* @param string data in the cache
|
||||
* @param array cache tags
|
||||
* @param integer lifetime
|
||||
* @return bool
|
||||
*/
|
||||
public function set($id, $data, array $tags = NULL, $lifetime)
|
||||
{
|
||||
// Remove old cache files
|
||||
$this->delete($id);
|
||||
// Cache File driver expects unix timestamp
|
||||
if ($lifetime !== 0) {
|
||||
$lifetime += time();
|
||||
}
|
||||
|
||||
// Cache File driver expects unix timestamp
|
||||
if ($lifetime !== 0)
|
||||
{
|
||||
$lifetime += time();
|
||||
}
|
||||
if (! empty($tags)) {
|
||||
// Convert the tags into a string list
|
||||
$tags = implode('+', $tags);
|
||||
}
|
||||
|
||||
if ( ! empty($tags))
|
||||
{
|
||||
// Convert the tags into a string list
|
||||
$tags = implode('+', $tags);
|
||||
}
|
||||
// Write out a serialized cache
|
||||
return (bool) file_put_contents($this->directory . $id . '~' . $tags . '~' . $lifetime, serialize($data));
|
||||
}
|
||||
|
||||
// Write out a serialized cache
|
||||
return (bool) file_put_contents($this->directory.$id.'~'.$tags.'~'.$lifetime, serialize($data));
|
||||
}
|
||||
/**
|
||||
* Finds an array of ids for a given tag.
|
||||
*
|
||||
* @param string tag name
|
||||
* @return array of ids that match the tag
|
||||
*/
|
||||
public function find($tag)
|
||||
{
|
||||
// An array will always be returned
|
||||
$result = array();
|
||||
|
||||
/**
|
||||
* Finds an array of ids for a given tag.
|
||||
*
|
||||
* @param string tag name
|
||||
* @return array of ids that match the tag
|
||||
*/
|
||||
public function find($tag)
|
||||
{
|
||||
// An array will always be returned
|
||||
$result = array();
|
||||
if ($paths = $this->exists($tag, true)) {
|
||||
// Length of directory name
|
||||
$offset = strlen($this->directory);
|
||||
|
||||
if ($paths = $this->exists($tag, TRUE))
|
||||
{
|
||||
// Length of directory name
|
||||
$offset = strlen($this->directory);
|
||||
// Find all the files with the given tag
|
||||
foreach ($paths as $path) {
|
||||
// Get the id from the filename
|
||||
list($id, $junk) = explode('~', basename($path), 2);
|
||||
|
||||
// Find all the files with the given tag
|
||||
foreach ($paths as $path)
|
||||
{
|
||||
// Get the id from the filename
|
||||
list($id, $junk) = explode('~', basename($path), 2);
|
||||
if (($data = $this->get($id)) !== false) {
|
||||
// Add the result to the array
|
||||
$result[$id] = $data;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (($data = $this->get($id)) !== FALSE)
|
||||
{
|
||||
// Add the result to the array
|
||||
$result[$id] = $data;
|
||||
}
|
||||
}
|
||||
}
|
||||
return $result;
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
/**
|
||||
* Fetches a cache item. This will delete the item if it is expired or if
|
||||
* the hash does not match the stored hash.
|
||||
*
|
||||
* @param string cache id
|
||||
* @return mixed|NULL
|
||||
*/
|
||||
public function get($id)
|
||||
{
|
||||
if ($file = $this->exists($id)) {
|
||||
// Use the first file
|
||||
$file = current($file);
|
||||
|
||||
/**
|
||||
* Fetches a cache item. This will delete the item if it is expired or if
|
||||
* the hash does not match the stored hash.
|
||||
*
|
||||
* @param string cache id
|
||||
* @return mixed|NULL
|
||||
*/
|
||||
public function get($id)
|
||||
{
|
||||
if ($file = $this->exists($id))
|
||||
{
|
||||
// Use the first file
|
||||
$file = current($file);
|
||||
// Validate that the cache has not expired
|
||||
if ($this->expired($file)) {
|
||||
// Remove this cache, it has expired
|
||||
$this->delete($id);
|
||||
} else {
|
||||
// Turn off errors while reading the file
|
||||
$ER = error_reporting(0);
|
||||
|
||||
// Validate that the cache has not expired
|
||||
if ($this->expired($file))
|
||||
{
|
||||
// Remove this cache, it has expired
|
||||
$this->delete($id);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Turn off errors while reading the file
|
||||
$ER = error_reporting(0);
|
||||
if (($data = file_get_contents($file)) !== false) {
|
||||
// Unserialize the data
|
||||
$data = unserialize($data);
|
||||
} else {
|
||||
// Delete the data
|
||||
unset($data);
|
||||
}
|
||||
|
||||
if (($data = file_get_contents($file)) !== FALSE)
|
||||
{
|
||||
// Unserialize the data
|
||||
$data = unserialize($data);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Delete the data
|
||||
unset($data);
|
||||
}
|
||||
// Turn errors back on
|
||||
error_reporting($ER);
|
||||
}
|
||||
}
|
||||
|
||||
// Turn errors back on
|
||||
error_reporting($ER);
|
||||
}
|
||||
}
|
||||
// Return NULL if there is no data
|
||||
return isset($data) ? $data : null;
|
||||
}
|
||||
|
||||
// Return NULL if there is no data
|
||||
return isset($data) ? $data : NULL;
|
||||
}
|
||||
/**
|
||||
* Deletes a cache item by id or tag
|
||||
*
|
||||
* @param string cache id or tag, or TRUE for "all items"
|
||||
* @param boolean use tags
|
||||
* @return boolean
|
||||
*/
|
||||
public function delete($id, $tag = false)
|
||||
{
|
||||
$files = $this->exists($id, $tag);
|
||||
|
||||
/**
|
||||
* Deletes a cache item by id or tag
|
||||
*
|
||||
* @param string cache id or tag, or TRUE for "all items"
|
||||
* @param boolean use tags
|
||||
* @return boolean
|
||||
*/
|
||||
public function delete($id, $tag = FALSE)
|
||||
{
|
||||
$files = $this->exists($id, $tag);
|
||||
if (empty($files)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (empty($files))
|
||||
return FALSE;
|
||||
// Disable all error reporting while deleting
|
||||
$ER = error_reporting(0);
|
||||
|
||||
// Disable all error reporting while deleting
|
||||
$ER = error_reporting(0);
|
||||
foreach ($files as $file) {
|
||||
// Remove the cache file
|
||||
if (! unlink($file)) {
|
||||
Kohana::log('error', 'Cache: Unable to delete cache file: ' . $file);
|
||||
}
|
||||
}
|
||||
|
||||
foreach ($files as $file)
|
||||
{
|
||||
// Remove the cache file
|
||||
if ( ! unlink($file))
|
||||
Kohana::log('error', 'Cache: Unable to delete cache file: '.$file);
|
||||
}
|
||||
// Turn on error reporting again
|
||||
error_reporting($ER);
|
||||
|
||||
// Turn on error reporting again
|
||||
error_reporting($ER);
|
||||
return true;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
/**
|
||||
* Deletes all cache files that are older than the current time.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function delete_expired()
|
||||
{
|
||||
if ($files = $this->exists(true)) {
|
||||
// Disable all error reporting while deleting
|
||||
$ER = error_reporting(0);
|
||||
|
||||
/**
|
||||
* Deletes all cache files that are older than the current time.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function delete_expired()
|
||||
{
|
||||
if ($files = $this->exists(TRUE))
|
||||
{
|
||||
// Disable all error reporting while deleting
|
||||
$ER = error_reporting(0);
|
||||
foreach ($files as $file) {
|
||||
if ($this->expired($file)) {
|
||||
// The cache file has already expired, delete it
|
||||
if (! unlink($file)) {
|
||||
Kohana::log('error', 'Cache: Unable to delete cache file: ' . $file);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
foreach ($files as $file)
|
||||
{
|
||||
if ($this->expired($file))
|
||||
{
|
||||
// The cache file has already expired, delete it
|
||||
if ( ! unlink($file))
|
||||
Kohana::log('error', 'Cache: Unable to delete cache file: '.$file);
|
||||
}
|
||||
}
|
||||
// Turn on error reporting again
|
||||
error_reporting($ER);
|
||||
}
|
||||
}
|
||||
|
||||
// Turn on error reporting again
|
||||
error_reporting($ER);
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Check if a cache file has expired by filename.
|
||||
*
|
||||
* @param string filename
|
||||
* @return bool
|
||||
*/
|
||||
protected function expired($file)
|
||||
{
|
||||
// Get the expiration time
|
||||
$expires = (int) substr($file, strrpos($file, '~') + 1);
|
||||
|
||||
/**
|
||||
* Check if a cache file has expired by filename.
|
||||
*
|
||||
* @param string filename
|
||||
* @return bool
|
||||
*/
|
||||
protected function expired($file)
|
||||
{
|
||||
// Get the expiration time
|
||||
$expires = (int) substr($file, strrpos($file, '~') + 1);
|
||||
|
||||
// Expirations of 0 are "never expire"
|
||||
return ($expires !== 0 AND $expires <= time());
|
||||
}
|
||||
|
||||
} // End Cache File Driver
|
||||
// Expirations of 0 are "never expire"
|
||||
return ($expires !== 0 and $expires <= time());
|
||||
}
|
||||
}
|
||||
// End Cache File Driver
|
||||
|
||||
@@ -1,4 +1,12 @@
|
||||
<?php defined('SYSPATH') OR die('No direct access allowed.');
|
||||
<?php
|
||||
|
||||
// phpcs:disable PSR1.Classes.ClassDeclaration.MissingNamespace
|
||||
// phpcs:disable PSR1.Files.SideEffects
|
||||
defined('SYSPATH') or die('No direct access allowed.');
|
||||
// phpcs:enable PSR1.Files.SideEffects
|
||||
// phpcs:disable Squiz.Classes.ValidClassName.NotCamelCaps
|
||||
|
||||
|
||||
/**
|
||||
* Memcache-based Cache driver.
|
||||
*
|
||||
@@ -9,183 +17,161 @@
|
||||
* @copyright (c) 2007-2008 Kohana Team
|
||||
* @license http://kohanaphp.com/license.html
|
||||
*/
|
||||
class Cache_Memcache_Driver implements Cache_Driver {
|
||||
class Cache_Memcache_Driver implements Cache_Driver
|
||||
{
|
||||
const TAGS_KEY = 'memcache_tags_array';
|
||||
|
||||
const TAGS_KEY = 'memcache_tags_array';
|
||||
// Cache backend object and flags
|
||||
protected $backend;
|
||||
protected $flags;
|
||||
|
||||
// Cache backend object and flags
|
||||
protected $backend;
|
||||
protected $flags;
|
||||
// Tags array
|
||||
protected static $tags;
|
||||
|
||||
// Tags array
|
||||
protected static $tags;
|
||||
// Have the tags been changed?
|
||||
protected static $tags_changed = false;
|
||||
|
||||
// Have the tags been changed?
|
||||
protected static $tags_changed = FALSE;
|
||||
public function __construct()
|
||||
{
|
||||
if (! extension_loaded('memcache')) {
|
||||
throw new Kohana_Exception('cache.extension_not_loaded', 'memcache');
|
||||
}
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
if ( ! extension_loaded('memcache'))
|
||||
throw new Kohana_Exception('cache.extension_not_loaded', 'memcache');
|
||||
$this->backend = new Memcache();
|
||||
$this->flags = Kohana::config('cache_memcache.compression') ? MEMCACHE_COMPRESSED : false;
|
||||
|
||||
$this->backend = new Memcache;
|
||||
$this->flags = Kohana::config('cache_memcache.compression') ? MEMCACHE_COMPRESSED : FALSE;
|
||||
$servers = Kohana::config('cache_memcache.servers');
|
||||
|
||||
$servers = Kohana::config('cache_memcache.servers');
|
||||
foreach ($servers as $server) {
|
||||
// Make sure all required keys are set
|
||||
$server += array('host' => '127.0.0.1', 'port' => 11211, 'persistent' => false);
|
||||
|
||||
foreach ($servers as $server)
|
||||
{
|
||||
// Make sure all required keys are set
|
||||
$server += array('host' => '127.0.0.1', 'port' => 11211, 'persistent' => FALSE);
|
||||
// Add the server to the pool
|
||||
$this->backend->addServer($server['host'], $server['port'], (bool) $server['persistent'])
|
||||
or Kohana::log('error', 'Cache: Connection failed: ' . $server['host']);
|
||||
}
|
||||
|
||||
// Add the server to the pool
|
||||
$this->backend->addServer($server['host'], $server['port'], (bool) $server['persistent'])
|
||||
or Kohana::log('error', 'Cache: Connection failed: '.$server['host']);
|
||||
}
|
||||
// Load tags
|
||||
self::$tags = $this->backend->get(self::TAGS_KEY);
|
||||
|
||||
// Load tags
|
||||
self::$tags = $this->backend->get(self::TAGS_KEY);
|
||||
if (! is_array(self::$tags)) {
|
||||
// Create a new tags array
|
||||
self::$tags = array();
|
||||
|
||||
if ( ! is_array(self::$tags))
|
||||
{
|
||||
// Create a new tags array
|
||||
self::$tags = array();
|
||||
// Tags have been created
|
||||
self::$tags_changed = true;
|
||||
}
|
||||
}
|
||||
|
||||
// Tags have been created
|
||||
self::$tags_changed = TRUE;
|
||||
}
|
||||
}
|
||||
public function __destruct()
|
||||
{
|
||||
if (self::$tags_changed === true) {
|
||||
// Save the tags
|
||||
$this->backend->set(self::TAGS_KEY, self::$tags, $this->flags, 0);
|
||||
|
||||
public function __destruct()
|
||||
{
|
||||
if (self::$tags_changed === TRUE)
|
||||
{
|
||||
// Save the tags
|
||||
$this->backend->set(self::TAGS_KEY, self::$tags, $this->flags, 0);
|
||||
// Tags are now unchanged
|
||||
self::$tags_changed = false;
|
||||
}
|
||||
}
|
||||
|
||||
// Tags are now unchanged
|
||||
self::$tags_changed = FALSE;
|
||||
}
|
||||
}
|
||||
public function find($tag)
|
||||
{
|
||||
if (isset(self::$tags[$tag]) and $results = $this->backend->get(self::$tags[$tag])) {
|
||||
// Return all the found caches
|
||||
return $results;
|
||||
} else {
|
||||
// No matching tags
|
||||
return array();
|
||||
}
|
||||
}
|
||||
|
||||
public function find($tag)
|
||||
{
|
||||
if (isset(self::$tags[$tag]) AND $results = $this->backend->get(self::$tags[$tag]))
|
||||
{
|
||||
// Return all the found caches
|
||||
return $results;
|
||||
}
|
||||
else
|
||||
{
|
||||
// No matching tags
|
||||
return array();
|
||||
}
|
||||
}
|
||||
public function get($id)
|
||||
{
|
||||
return (($return = $this->backend->get($id)) === false) ? null : $return;
|
||||
}
|
||||
|
||||
public function get($id)
|
||||
{
|
||||
return (($return = $this->backend->get($id)) === FALSE) ? NULL : $return;
|
||||
}
|
||||
public function set($id, $data, array $tags = null, $lifetime)
|
||||
{
|
||||
if (! empty($tags)) {
|
||||
// Tags will be changed
|
||||
self::$tags_changed = true;
|
||||
|
||||
public function set($id, $data, array $tags = NULL, $lifetime)
|
||||
{
|
||||
if ( ! empty($tags))
|
||||
{
|
||||
// Tags will be changed
|
||||
self::$tags_changed = TRUE;
|
||||
foreach ($tags as $tag) {
|
||||
// Add the id to each tag
|
||||
self::$tags[$tag][$id] = $id;
|
||||
}
|
||||
}
|
||||
|
||||
foreach ($tags as $tag)
|
||||
{
|
||||
// Add the id to each tag
|
||||
self::$tags[$tag][$id] = $id;
|
||||
}
|
||||
}
|
||||
if ($lifetime !== 0) {
|
||||
// Memcache driver expects unix timestamp
|
||||
$lifetime += time();
|
||||
}
|
||||
|
||||
if ($lifetime !== 0)
|
||||
{
|
||||
// Memcache driver expects unix timestamp
|
||||
$lifetime += time();
|
||||
}
|
||||
// Set a new value
|
||||
return $this->backend->set($id, $data, $this->flags, $lifetime);
|
||||
}
|
||||
|
||||
// Set a new value
|
||||
return $this->backend->set($id, $data, $this->flags, $lifetime);
|
||||
}
|
||||
public function delete($id, $tag = false)
|
||||
{
|
||||
// Tags will be changed
|
||||
self::$tags_changed = true;
|
||||
|
||||
public function delete($id, $tag = FALSE)
|
||||
{
|
||||
// Tags will be changed
|
||||
self::$tags_changed = TRUE;
|
||||
if ($id === true) {
|
||||
if ($status = $this->backend->flush()) {
|
||||
// Remove all tags, all items have been deleted
|
||||
self::$tags = array();
|
||||
|
||||
if ($id === TRUE)
|
||||
{
|
||||
if ($status = $this->backend->flush())
|
||||
{
|
||||
// Remove all tags, all items have been deleted
|
||||
self::$tags = array();
|
||||
// We must sleep after flushing, or overwriting will not work!
|
||||
// @see http://php.net/manual/en/function.memcache-flush.php#81420
|
||||
sleep(1);
|
||||
}
|
||||
|
||||
// We must sleep after flushing, or overwriting will not work!
|
||||
// @see http://php.net/manual/en/function.memcache-flush.php#81420
|
||||
sleep(1);
|
||||
}
|
||||
return $status;
|
||||
} elseif ($tag === true) {
|
||||
if (isset(self::$tags[$id])) {
|
||||
foreach (self::$tags[$id] as $_id) {
|
||||
// Delete each id in the tag
|
||||
$this->backend->delete($_id);
|
||||
}
|
||||
|
||||
return $status;
|
||||
}
|
||||
elseif ($tag === TRUE)
|
||||
{
|
||||
if (isset(self::$tags[$id]))
|
||||
{
|
||||
foreach (self::$tags[$id] as $_id)
|
||||
{
|
||||
// Delete each id in the tag
|
||||
$this->backend->delete($_id);
|
||||
}
|
||||
// Delete the tag
|
||||
unset(self::$tags[$id]);
|
||||
}
|
||||
|
||||
// Delete the tag
|
||||
unset(self::$tags[$id]);
|
||||
}
|
||||
return true;
|
||||
} else {
|
||||
foreach (self::$tags as $tag => $_ids) {
|
||||
if (isset(self::$tags[$tag][$id])) {
|
||||
// Remove the id from the tags
|
||||
unset(self::$tags[$tag][$id]);
|
||||
}
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
else
|
||||
{
|
||||
foreach (self::$tags as $tag => $_ids)
|
||||
{
|
||||
if (isset(self::$tags[$tag][$id]))
|
||||
{
|
||||
// Remove the id from the tags
|
||||
unset(self::$tags[$tag][$id]);
|
||||
}
|
||||
}
|
||||
return $this->backend->delete($id);
|
||||
}
|
||||
}
|
||||
|
||||
return $this->backend->delete($id);
|
||||
}
|
||||
}
|
||||
public function delete_expired()
|
||||
{
|
||||
// Tags will be changed
|
||||
self::$tags_changed = true;
|
||||
|
||||
public function delete_expired()
|
||||
{
|
||||
// Tags will be changed
|
||||
self::$tags_changed = TRUE;
|
||||
foreach (self::$tags as $tag => $_ids) {
|
||||
foreach ($_ids as $id) {
|
||||
if (! $this->backend->get($id)) {
|
||||
// This id has disappeared, delete it from the tags
|
||||
unset(self::$tags[$tag][$id]);
|
||||
}
|
||||
}
|
||||
|
||||
foreach (self::$tags as $tag => $_ids)
|
||||
{
|
||||
foreach ($_ids as $id)
|
||||
{
|
||||
if ( ! $this->backend->get($id))
|
||||
{
|
||||
// This id has disappeared, delete it from the tags
|
||||
unset(self::$tags[$tag][$id]);
|
||||
}
|
||||
}
|
||||
if (empty(self::$tags[$tag])) {
|
||||
// The tag no longer has any valid ids
|
||||
unset(self::$tags[$tag]);
|
||||
}
|
||||
}
|
||||
|
||||
if (empty(self::$tags[$tag]))
|
||||
{
|
||||
// The tag no longer has any valid ids
|
||||
unset(self::$tags[$tag]);
|
||||
}
|
||||
}
|
||||
|
||||
// Memcache handles garbage collection internally
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
} // End Cache Memcache Driver
|
||||
// Memcache handles garbage collection internally
|
||||
return true;
|
||||
}
|
||||
}
|
||||
// End Cache Memcache Driver
|
||||
|
||||
@@ -1,4 +1,12 @@
|
||||
<?php defined('SYSPATH') OR die('No direct access allowed.');
|
||||
<?php
|
||||
|
||||
// phpcs:disable PSR1.Classes.ClassDeclaration.MissingNamespace
|
||||
// phpcs:disable PSR1.Files.SideEffects
|
||||
defined('SYSPATH') or die('No direct access allowed.');
|
||||
// phpcs:enable PSR1.Files.SideEffects
|
||||
// phpcs:disable Squiz.Classes.ValidClassName.NotCamelCaps
|
||||
|
||||
|
||||
/**
|
||||
* SQLite-based Cache driver.
|
||||
*
|
||||
@@ -9,249 +17,229 @@
|
||||
* @copyright (c) 2007-2008 Kohana Team
|
||||
* @license http://kohanaphp.com/license.html
|
||||
*/
|
||||
class Cache_Sqlite_Driver implements Cache_Driver {
|
||||
class Cache_Sqlite_Driver implements Cache_Driver
|
||||
{
|
||||
// SQLite database instance
|
||||
protected $db;
|
||||
|
||||
// SQLite database instance
|
||||
protected $db;
|
||||
// Database error messages
|
||||
protected $error;
|
||||
|
||||
// Database error messages
|
||||
protected $error;
|
||||
/**
|
||||
* Logs an SQLite error.
|
||||
*/
|
||||
protected static function log_error($code)
|
||||
{
|
||||
// Log an error
|
||||
Kohana::log('error', 'Cache: SQLite error: ' . sqlite_error_string($error));
|
||||
}
|
||||
|
||||
/**
|
||||
* Logs an SQLite error.
|
||||
*/
|
||||
protected static function log_error($code)
|
||||
{
|
||||
// Log an error
|
||||
Kohana::log('error', 'Cache: SQLite error: '.sqlite_error_string($error));
|
||||
}
|
||||
/**
|
||||
* Tests that the storage location is a directory and is writable.
|
||||
*/
|
||||
public function __construct($filename)
|
||||
{
|
||||
// Get the directory name
|
||||
$directory = str_replace('\\', '/', realpath(pathinfo($filename, PATHINFO_DIRNAME))) . '/';
|
||||
|
||||
/**
|
||||
* Tests that the storage location is a directory and is writable.
|
||||
*/
|
||||
public function __construct($filename)
|
||||
{
|
||||
// Get the directory name
|
||||
$directory = str_replace('\\', '/', realpath(pathinfo($filename, PATHINFO_DIRNAME))).'/';
|
||||
// Set the filename from the real directory path
|
||||
$filename = $directory . basename($filename);
|
||||
|
||||
// Set the filename from the real directory path
|
||||
$filename = $directory.basename($filename);
|
||||
// Make sure the cache directory is writable
|
||||
if (! is_dir($directory) or ! is_writable($directory)) {
|
||||
throw new Kohana_Exception('cache.unwritable', $directory);
|
||||
}
|
||||
|
||||
// Make sure the cache directory is writable
|
||||
if ( ! is_dir($directory) OR ! is_writable($directory))
|
||||
throw new Kohana_Exception('cache.unwritable', $directory);
|
||||
// Make sure the cache database is writable
|
||||
if (is_file($filename) and ! is_writable($filename)) {
|
||||
throw new Kohana_Exception('cache.unwritable', $filename);
|
||||
}
|
||||
|
||||
// Make sure the cache database is writable
|
||||
if (is_file($filename) AND ! is_writable($filename))
|
||||
throw new Kohana_Exception('cache.unwritable', $filename);
|
||||
// Open up an instance of the database
|
||||
$this->db = new SQLiteDatabase($filename, '0666', $error);
|
||||
|
||||
// Open up an instance of the database
|
||||
$this->db = new SQLiteDatabase($filename, '0666', $error);
|
||||
// Throw an exception if there's an error
|
||||
if (! empty($error)) {
|
||||
throw new Kohana_Exception('cache.driver_error', sqlite_error_string($error));
|
||||
}
|
||||
|
||||
// Throw an exception if there's an error
|
||||
if ( ! empty($error))
|
||||
throw new Kohana_Exception('cache.driver_error', sqlite_error_string($error));
|
||||
$query = "SELECT name FROM sqlite_master WHERE type = 'table' AND name = 'caches'";
|
||||
$tables = $this->db->query($query, SQLITE_BOTH, $error);
|
||||
|
||||
$query = "SELECT name FROM sqlite_master WHERE type = 'table' AND name = 'caches'";
|
||||
$tables = $this->db->query($query, SQLITE_BOTH, $error);
|
||||
// Throw an exception if there's an error
|
||||
if (! empty($error)) {
|
||||
throw new Kohana_Exception('cache.driver_error', sqlite_error_string($error));
|
||||
}
|
||||
|
||||
// Throw an exception if there's an error
|
||||
if ( ! empty($error))
|
||||
throw new Kohana_Exception('cache.driver_error', sqlite_error_string($error));
|
||||
if ($tables->numRows() == 0) {
|
||||
Kohana::log('error', 'Cache: Initializing new SQLite cache database');
|
||||
|
||||
if ($tables->numRows() == 0)
|
||||
{
|
||||
Kohana::log('error', 'Cache: Initializing new SQLite cache database');
|
||||
// Issue a CREATE TABLE command
|
||||
$this->db->unbufferedQuery(Kohana::config('cache_sqlite.schema'));
|
||||
}
|
||||
}
|
||||
|
||||
// Issue a CREATE TABLE command
|
||||
$this->db->unbufferedQuery(Kohana::config('cache_sqlite.schema'));
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Checks if a cache id is already set.
|
||||
*
|
||||
* @param string cache id
|
||||
* @return boolean
|
||||
*/
|
||||
public function exists($id)
|
||||
{
|
||||
// Find the id that matches
|
||||
$query = "SELECT id FROM caches WHERE id = '$id'";
|
||||
|
||||
/**
|
||||
* Checks if a cache id is already set.
|
||||
*
|
||||
* @param string cache id
|
||||
* @return boolean
|
||||
*/
|
||||
public function exists($id)
|
||||
{
|
||||
// Find the id that matches
|
||||
$query = "SELECT id FROM caches WHERE id = '$id'";
|
||||
return ($this->db->query($query)->numRows() > 0);
|
||||
}
|
||||
|
||||
return ($this->db->query($query)->numRows() > 0);
|
||||
}
|
||||
/**
|
||||
* Sets a cache item to the given data, tags, and lifetime.
|
||||
*
|
||||
* @param string cache id to set
|
||||
* @param string data in the cache
|
||||
* @param array cache tags
|
||||
* @param integer lifetime
|
||||
* @return bool
|
||||
*/
|
||||
public function set($id, $data, array $tags = null, $lifetime)
|
||||
{
|
||||
// Serialize and escape the data
|
||||
$data = sqlite_escape_string(serialize($data));
|
||||
|
||||
/**
|
||||
* Sets a cache item to the given data, tags, and lifetime.
|
||||
*
|
||||
* @param string cache id to set
|
||||
* @param string data in the cache
|
||||
* @param array cache tags
|
||||
* @param integer lifetime
|
||||
* @return bool
|
||||
*/
|
||||
public function set($id, $data, array $tags = NULL, $lifetime)
|
||||
{
|
||||
// Serialize and escape the data
|
||||
$data = sqlite_escape_string(serialize($data));
|
||||
if (! empty($tags)) {
|
||||
// Escape the tags, adding brackets so the tag can be explicitly matched
|
||||
$tags = sqlite_escape_string('<' . implode('>,<', $tags) . '>');
|
||||
}
|
||||
|
||||
if ( ! empty($tags))
|
||||
{
|
||||
// Escape the tags, adding brackets so the tag can be explicitly matched
|
||||
$tags = sqlite_escape_string('<'.implode('>,<', $tags).'>');
|
||||
}
|
||||
// Cache Sqlite driver expects unix timestamp
|
||||
if ($lifetime !== 0) {
|
||||
$lifetime += time();
|
||||
}
|
||||
|
||||
// Cache Sqlite driver expects unix timestamp
|
||||
if ($lifetime !== 0)
|
||||
{
|
||||
$lifetime += time();
|
||||
}
|
||||
$query = $this->exists($id)
|
||||
? "UPDATE caches SET tags = '$tags', expiration = '$lifetime', cache = '$data' WHERE id = '$id'"
|
||||
: "INSERT INTO caches VALUES('$id', '$tags', '$lifetime', '$data')";
|
||||
|
||||
$query = $this->exists($id)
|
||||
? "UPDATE caches SET tags = '$tags', expiration = '$lifetime', cache = '$data' WHERE id = '$id'"
|
||||
: "INSERT INTO caches VALUES('$id', '$tags', '$lifetime', '$data')";
|
||||
// Run the query
|
||||
$this->db->unbufferedQuery($query, SQLITE_BOTH, $error);
|
||||
|
||||
// Run the query
|
||||
$this->db->unbufferedQuery($query, SQLITE_BOTH, $error);
|
||||
if (! empty($error)) {
|
||||
self::log_error($error);
|
||||
return false;
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
if ( ! empty($error))
|
||||
{
|
||||
self::log_error($error);
|
||||
return FALSE;
|
||||
}
|
||||
else
|
||||
{
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Finds an array of ids for a given tag.
|
||||
*
|
||||
* @param string tag name
|
||||
* @return array of ids that match the tag
|
||||
*/
|
||||
public function find($tag)
|
||||
{
|
||||
$query = "SELECT id,cache FROM caches WHERE tags LIKE '%<{$tag}>%'";
|
||||
$query = $this->db->query($query, SQLITE_BOTH, $error);
|
||||
|
||||
/**
|
||||
* Finds an array of ids for a given tag.
|
||||
*
|
||||
* @param string tag name
|
||||
* @return array of ids that match the tag
|
||||
*/
|
||||
public function find($tag)
|
||||
{
|
||||
$query = "SELECT id,cache FROM caches WHERE tags LIKE '%<{$tag}>%'";
|
||||
$query = $this->db->query($query, SQLITE_BOTH, $error);
|
||||
// An array will always be returned
|
||||
$result = array();
|
||||
|
||||
// An array will always be returned
|
||||
$result = array();
|
||||
if (! empty($error)) {
|
||||
self::log_error($error);
|
||||
} elseif ($query->numRows() > 0) {
|
||||
// Disable notices for unserializing
|
||||
$ER = error_reporting(~E_NOTICE);
|
||||
|
||||
if ( ! empty($error))
|
||||
{
|
||||
self::log_error($error);
|
||||
}
|
||||
elseif ($query->numRows() > 0)
|
||||
{
|
||||
// Disable notices for unserializing
|
||||
$ER = error_reporting(~E_NOTICE);
|
||||
while ($row = $query->fetchObject()) {
|
||||
// Add each cache to the array
|
||||
$result[$row->id] = unserialize($row->cache);
|
||||
}
|
||||
|
||||
while ($row = $query->fetchObject())
|
||||
{
|
||||
// Add each cache to the array
|
||||
$result[$row->id] = unserialize($row->cache);
|
||||
}
|
||||
// Turn notices back on
|
||||
error_reporting($ER);
|
||||
}
|
||||
|
||||
// Turn notices back on
|
||||
error_reporting($ER);
|
||||
}
|
||||
return $result;
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
/**
|
||||
* Fetches a cache item. This will delete the item if it is expired or if
|
||||
* the hash does not match the stored hash.
|
||||
*
|
||||
* @param string cache id
|
||||
* @return mixed|NULL
|
||||
*/
|
||||
public function get($id)
|
||||
{
|
||||
$query = "SELECT id, expiration, cache FROM caches WHERE id = '$id' LIMIT 0, 1";
|
||||
$query = $this->db->query($query, SQLITE_BOTH, $error);
|
||||
|
||||
/**
|
||||
* Fetches a cache item. This will delete the item if it is expired or if
|
||||
* the hash does not match the stored hash.
|
||||
*
|
||||
* @param string cache id
|
||||
* @return mixed|NULL
|
||||
*/
|
||||
public function get($id)
|
||||
{
|
||||
$query = "SELECT id, expiration, cache FROM caches WHERE id = '$id' LIMIT 0, 1";
|
||||
$query = $this->db->query($query, SQLITE_BOTH, $error);
|
||||
if (! empty($error)) {
|
||||
self::log_error($error);
|
||||
} elseif ($cache = $query->fetchObject()) {
|
||||
// Make sure the expiration is valid and that the hash matches
|
||||
if ($cache->expiration != 0 and $cache->expiration <= time()) {
|
||||
// Cache is not valid, delete it now
|
||||
$this->delete($cache->id);
|
||||
} else {
|
||||
// Disable notices for unserializing
|
||||
$ER = error_reporting(~E_NOTICE);
|
||||
|
||||
if ( ! empty($error))
|
||||
{
|
||||
self::log_error($error);
|
||||
}
|
||||
elseif ($cache = $query->fetchObject())
|
||||
{
|
||||
// Make sure the expiration is valid and that the hash matches
|
||||
if ($cache->expiration != 0 AND $cache->expiration <= time())
|
||||
{
|
||||
// Cache is not valid, delete it now
|
||||
$this->delete($cache->id);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Disable notices for unserializing
|
||||
$ER = error_reporting(~E_NOTICE);
|
||||
|
||||
// Return the valid cache data
|
||||
$data = $cache->cache;
|
||||
// Return the valid cache data
|
||||
$data = $cache->cache;
|
||||
|
||||
// Turn notices back on
|
||||
error_reporting($ER);
|
||||
}
|
||||
}
|
||||
// Turn notices back on
|
||||
error_reporting($ER);
|
||||
}
|
||||
}
|
||||
|
||||
// No valid cache found
|
||||
return NULL;
|
||||
}
|
||||
// No valid cache found
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Deletes a cache item by id or tag
|
||||
*
|
||||
* @param string cache id or tag, or TRUE for "all items"
|
||||
* @param bool delete a tag
|
||||
* @return bool
|
||||
*/
|
||||
public function delete($id, $tag = FALSE)
|
||||
{
|
||||
if ($id === TRUE)
|
||||
{
|
||||
// Delete all caches
|
||||
$where = '1';
|
||||
}
|
||||
elseif ($tag === TRUE)
|
||||
{
|
||||
// Delete by tag
|
||||
$where = "tags LIKE '%<{$id}>%'";
|
||||
}
|
||||
else
|
||||
{
|
||||
// Delete by id
|
||||
$where = "id = '$id'";
|
||||
}
|
||||
/**
|
||||
* Deletes a cache item by id or tag
|
||||
*
|
||||
* @param string cache id or tag, or TRUE for "all items"
|
||||
* @param bool delete a tag
|
||||
* @return bool
|
||||
*/
|
||||
public function delete($id, $tag = false)
|
||||
{
|
||||
if ($id === true) {
|
||||
// Delete all caches
|
||||
$where = '1';
|
||||
} elseif ($tag === true) {
|
||||
// Delete by tag
|
||||
$where = "tags LIKE '%<{$id}>%'";
|
||||
} else {
|
||||
// Delete by id
|
||||
$where = "id = '$id'";
|
||||
}
|
||||
|
||||
$this->db->unbufferedQuery('DELETE FROM caches WHERE '.$where, SQLITE_BOTH, $error);
|
||||
$this->db->unbufferedQuery('DELETE FROM caches WHERE ' . $where, SQLITE_BOTH, $error);
|
||||
|
||||
if ( ! empty($error))
|
||||
{
|
||||
self::log_error($error);
|
||||
return FALSE;
|
||||
}
|
||||
else
|
||||
{
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
if (! empty($error)) {
|
||||
self::log_error($error);
|
||||
return false;
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Deletes all cache files that are older than the current time.
|
||||
*/
|
||||
public function delete_expired()
|
||||
{
|
||||
// Delete all expired caches
|
||||
$query = 'DELETE FROM caches WHERE expiration != 0 AND expiration <= '.time();
|
||||
/**
|
||||
* Deletes all cache files that are older than the current time.
|
||||
*/
|
||||
public function delete_expired()
|
||||
{
|
||||
// Delete all expired caches
|
||||
$query = 'DELETE FROM caches WHERE expiration != 0 AND expiration <= ' . time();
|
||||
|
||||
$this->db->unbufferedQuery($query);
|
||||
$this->db->unbufferedQuery($query);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
} // End Cache SQLite Driver
|
||||
return true;
|
||||
}
|
||||
}
|
||||
// End Cache SQLite Driver
|
||||
|
||||
@@ -1,4 +1,12 @@
|
||||
<?php defined('SYSPATH') OR die('No direct access allowed.');
|
||||
<?php
|
||||
|
||||
// phpcs:disable PSR1.Classes.ClassDeclaration.MissingNamespace
|
||||
// phpcs:disable PSR1.Files.SideEffects
|
||||
defined('SYSPATH') or die('No direct access allowed.');
|
||||
// phpcs:enable PSR1.Files.SideEffects
|
||||
// phpcs:disable Squiz.Classes.ValidClassName.NotCamelCaps
|
||||
|
||||
|
||||
/**
|
||||
* Xcache Cache driver.
|
||||
*
|
||||
@@ -9,111 +17,98 @@
|
||||
* @copyright (c) 2007-2008 Kohana Team
|
||||
* @license http://kohanaphp.com/license.html
|
||||
*/
|
||||
class Cache_Xcache_Driver implements Cache_Driver {
|
||||
class Cache_Xcache_Driver implements Cache_Driver
|
||||
{
|
||||
public function __construct()
|
||||
{
|
||||
if (! extension_loaded('xcache')) {
|
||||
throw new Kohana_Exception('cache.extension_not_loaded', 'xcache');
|
||||
}
|
||||
}
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
if ( ! extension_loaded('xcache'))
|
||||
throw new Kohana_Exception('cache.extension_not_loaded', 'xcache');
|
||||
}
|
||||
public function get($id)
|
||||
{
|
||||
if (xcache_isset($id)) {
|
||||
return xcache_get($id);
|
||||
}
|
||||
|
||||
public function get($id)
|
||||
{
|
||||
if (xcache_isset($id))
|
||||
return xcache_get($id);
|
||||
return null;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
public function set($id, $data, array $tags = null, $lifetime)
|
||||
{
|
||||
if (! empty($tags)) {
|
||||
Kohana::log('error', 'Cache: tags are unsupported by the Xcache driver');
|
||||
}
|
||||
|
||||
public function set($id, $data, array $tags = NULL, $lifetime)
|
||||
{
|
||||
if ( ! empty($tags))
|
||||
{
|
||||
Kohana::log('error', 'Cache: tags are unsupported by the Xcache driver');
|
||||
}
|
||||
return xcache_set($id, $data, $lifetime);
|
||||
}
|
||||
|
||||
return xcache_set($id, $data, $lifetime);
|
||||
}
|
||||
public function find($tag)
|
||||
{
|
||||
Kohana::log('error', 'Cache: tags are unsupported by the Xcache driver');
|
||||
return false;
|
||||
}
|
||||
|
||||
public function find($tag)
|
||||
{
|
||||
Kohana::log('error', 'Cache: tags are unsupported by the Xcache driver');
|
||||
return FALSE;
|
||||
}
|
||||
public function delete($id, $tag = false)
|
||||
{
|
||||
if ($tag !== false) {
|
||||
Kohana::log('error', 'Cache: tags are unsupported by the Xcache driver');
|
||||
return true;
|
||||
} elseif ($id !== true) {
|
||||
if (xcache_isset($id)) {
|
||||
return xcache_unset($id);
|
||||
}
|
||||
|
||||
public function delete($id, $tag = FALSE)
|
||||
{
|
||||
if ($tag !== FALSE)
|
||||
{
|
||||
Kohana::log('error', 'Cache: tags are unsupported by the Xcache driver');
|
||||
return TRUE;
|
||||
}
|
||||
elseif ($id !== TRUE)
|
||||
{
|
||||
if (xcache_isset($id))
|
||||
return xcache_unset($id);
|
||||
return false;
|
||||
} else {
|
||||
// Do the login
|
||||
$this->auth();
|
||||
$result = true;
|
||||
for ($i = 0, $max = xcache_count(XC_TYPE_VAR); $i < $max; $i++) {
|
||||
if (xcache_clear_cache(XC_TYPE_VAR, $i) !== null) {
|
||||
$result = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Do the login
|
||||
$this->auth();
|
||||
$result = TRUE;
|
||||
for ($i = 0, $max = xcache_count(XC_TYPE_VAR); $i < $max; $i++)
|
||||
{
|
||||
if (xcache_clear_cache(XC_TYPE_VAR, $i) !== NULL)
|
||||
{
|
||||
$result = FALSE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
// Undo the login
|
||||
$this->auth(true);
|
||||
return $result;
|
||||
}
|
||||
|
||||
// Undo the login
|
||||
$this->auth(TRUE);
|
||||
return $result;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
public function delete_expired()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
public function delete_expired()
|
||||
{
|
||||
return TRUE;
|
||||
}
|
||||
private function auth($reverse = false)
|
||||
{
|
||||
static $backup = array();
|
||||
|
||||
private function auth($reverse = FALSE)
|
||||
{
|
||||
static $backup = array();
|
||||
$keys = array('PHP_AUTH_USER', 'PHP_AUTH_PW');
|
||||
|
||||
$keys = array('PHP_AUTH_USER', 'PHP_AUTH_PW');
|
||||
foreach ($keys as $key) {
|
||||
if ($reverse) {
|
||||
if (isset($backup[$key])) {
|
||||
$_SERVER[$key] = $backup[$key];
|
||||
unset($backup[$key]);
|
||||
} else {
|
||||
unset($_SERVER[$key]);
|
||||
}
|
||||
} else {
|
||||
$value = getenv($key);
|
||||
|
||||
foreach ($keys as $key)
|
||||
{
|
||||
if ($reverse)
|
||||
{
|
||||
if (isset($backup[$key]))
|
||||
{
|
||||
$_SERVER[$key] = $backup[$key];
|
||||
unset($backup[$key]);
|
||||
}
|
||||
else
|
||||
{
|
||||
unset($_SERVER[$key]);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
$value = getenv($key);
|
||||
if (! empty($value)) {
|
||||
$backup[$key] = $value;
|
||||
}
|
||||
|
||||
if ( ! empty($value))
|
||||
{
|
||||
$backup[$key] = $value;
|
||||
}
|
||||
|
||||
$_SERVER[$key] = Kohana::config('cache_xcache.'.$key);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} // End Cache Xcache Driver
|
||||
$_SERVER[$key] = Kohana::config('cache_xcache.' . $key);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// End Cache Xcache Driver
|
||||
|
||||
@@ -1,4 +1,11 @@
|
||||
<?php defined('SYSPATH') OR die('No direct access allowed.');
|
||||
<?php
|
||||
|
||||
// phpcs:disable PSR1.Classes.ClassDeclaration.MissingNamespace
|
||||
// phpcs:disable PSR1.Files.SideEffects
|
||||
defined('SYSPATH') or die('No direct access allowed.');
|
||||
// phpcs:enable PSR1.Files.SideEffects
|
||||
// phpcs:disable Squiz.Classes.ValidClassName.NotCamelCaps
|
||||
|
||||
/**
|
||||
* Captcha driver class.
|
||||
*
|
||||
@@ -9,219 +16,223 @@
|
||||
* @copyright (c) 2007-2008 Kohana Team
|
||||
* @license http://kohanaphp.com/license.html
|
||||
*/
|
||||
abstract class Captcha_Driver {
|
||||
abstract class Captcha_Driver
|
||||
{
|
||||
// The correct Captcha challenge answer
|
||||
protected $response;
|
||||
|
||||
// The correct Captcha challenge answer
|
||||
protected $response;
|
||||
// Image resource identifier and type ("png", "gif" or "jpeg")
|
||||
protected $image;
|
||||
protected $image_type = 'png';
|
||||
|
||||
// Image resource identifier and type ("png", "gif" or "jpeg")
|
||||
protected $image;
|
||||
protected $image_type = 'png';
|
||||
/**
|
||||
* Constructs a new challenge.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
// Generate a new challenge
|
||||
$this->response = $this->generate_challenge();
|
||||
|
||||
/**
|
||||
* Constructs a new challenge.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
// Generate a new challenge
|
||||
$this->response = $this->generate_challenge();
|
||||
// Store the correct Captcha response in a session
|
||||
Event::add('system.post_controller', array($this, 'update_response_session'));
|
||||
}
|
||||
|
||||
// Store the correct Captcha response in a session
|
||||
Event::add('system.post_controller', array($this, 'update_response_session'));
|
||||
}
|
||||
/**
|
||||
* Generate a new Captcha challenge.
|
||||
*
|
||||
* @return string the challenge answer
|
||||
*/
|
||||
abstract public function generate_challenge();
|
||||
|
||||
/**
|
||||
* Generate a new Captcha challenge.
|
||||
*
|
||||
* @return string the challenge answer
|
||||
*/
|
||||
abstract public function generate_challenge();
|
||||
/**
|
||||
* Output the Captcha challenge.
|
||||
*
|
||||
* @param boolean html output
|
||||
* @return mixed the rendered Captcha (e.g. an image, riddle, etc.)
|
||||
*/
|
||||
abstract public function render($html);
|
||||
|
||||
/**
|
||||
* Output the Captcha challenge.
|
||||
*
|
||||
* @param boolean html output
|
||||
* @return mixed the rendered Captcha (e.g. an image, riddle, etc.)
|
||||
*/
|
||||
abstract public function render($html);
|
||||
/**
|
||||
* Stores the response for the current Captcha challenge in a session so it is available
|
||||
* on the next page load for Captcha::valid(). This method is called after controller
|
||||
* execution (in the system.post_controller event) in order not to overwrite itself too soon.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function update_response_session()
|
||||
{
|
||||
Session::instance()->set('captcha_response', sha1(strtoupper($this->response)));
|
||||
}
|
||||
|
||||
/**
|
||||
* Stores the response for the current Captcha challenge in a session so it is available
|
||||
* on the next page load for Captcha::valid(). This method is called after controller
|
||||
* execution (in the system.post_controller event) in order not to overwrite itself too soon.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function update_response_session()
|
||||
{
|
||||
Session::instance()->set('captcha_response', sha1(strtoupper($this->response)));
|
||||
}
|
||||
/**
|
||||
* Validates a Captcha response from a user.
|
||||
*
|
||||
* @param string captcha response
|
||||
* @return boolean
|
||||
*/
|
||||
public function valid($response)
|
||||
{
|
||||
return (sha1(strtoupper($response)) === Session::instance()->get('captcha_response'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Validates a Captcha response from a user.
|
||||
*
|
||||
* @param string captcha response
|
||||
* @return boolean
|
||||
*/
|
||||
public function valid($response)
|
||||
{
|
||||
return (sha1(strtoupper($response)) === Session::instance()->get('captcha_response'));
|
||||
}
|
||||
/**
|
||||
* Returns the image type.
|
||||
*
|
||||
* @param string filename
|
||||
* @return string|FALSE image type ("png", "gif" or "jpeg")
|
||||
*/
|
||||
public function image_type($filename)
|
||||
{
|
||||
switch (strtolower(substr(strrchr($filename, '.'), 1))) {
|
||||
case 'png':
|
||||
return 'png';
|
||||
|
||||
/**
|
||||
* Returns the image type.
|
||||
*
|
||||
* @param string filename
|
||||
* @return string|FALSE image type ("png", "gif" or "jpeg")
|
||||
*/
|
||||
public function image_type($filename)
|
||||
{
|
||||
switch (strtolower(substr(strrchr($filename, '.'), 1)))
|
||||
{
|
||||
case 'png':
|
||||
return 'png';
|
||||
case 'gif':
|
||||
return 'gif';
|
||||
|
||||
case 'gif':
|
||||
return 'gif';
|
||||
case 'jpg':
|
||||
case 'jpeg':
|
||||
// Return "jpeg" and not "jpg" because of the GD2 function names
|
||||
return 'jpeg';
|
||||
|
||||
case 'jpg':
|
||||
case 'jpeg':
|
||||
// Return "jpeg" and not "jpg" because of the GD2 function names
|
||||
return 'jpeg';
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
default:
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Creates an image resource with the dimensions specified in config.
|
||||
* If a background image is supplied, the image dimensions are used.
|
||||
*
|
||||
* @throws Kohana_Exception if no GD2 support
|
||||
* @param string path to the background image file
|
||||
* @return void
|
||||
*/
|
||||
public function image_create($background = null)
|
||||
{
|
||||
// Check for GD2 support
|
||||
if (! function_exists('imagegd2')) {
|
||||
throw new Kohana_Exception('captcha.requires_GD2');
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates an image resource with the dimensions specified in config.
|
||||
* If a background image is supplied, the image dimensions are used.
|
||||
*
|
||||
* @throws Kohana_Exception if no GD2 support
|
||||
* @param string path to the background image file
|
||||
* @return void
|
||||
*/
|
||||
public function image_create($background = NULL)
|
||||
{
|
||||
// Check for GD2 support
|
||||
if ( ! function_exists('imagegd2'))
|
||||
throw new Kohana_Exception('captcha.requires_GD2');
|
||||
// Create a new image (black)
|
||||
$this->image = imagecreatetruecolor(Captcha::$config['width'], Captcha::$config['height']);
|
||||
|
||||
// Create a new image (black)
|
||||
$this->image = imagecreatetruecolor(Captcha::$config['width'], Captcha::$config['height']);
|
||||
// Use a background image
|
||||
if (! empty($background)) {
|
||||
// Create the image using the right function for the filetype
|
||||
$function = 'imagecreatefrom' . $this->image_type($background);
|
||||
$this->background_image = $function($background);
|
||||
|
||||
// Use a background image
|
||||
if ( ! empty($background))
|
||||
{
|
||||
// Create the image using the right function for the filetype
|
||||
$function = 'imagecreatefrom'.$this->image_type($background);
|
||||
$this->background_image = $function($background);
|
||||
// Resize the image if needed
|
||||
if (
|
||||
imagesx($this->background_image) !== Captcha::$config['width']
|
||||
or imagesy($this->background_image) !== Captcha::$config['height']
|
||||
) {
|
||||
imagecopyresampled(
|
||||
$this->image,
|
||||
$this->background_image,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
Captcha::$config['width'],
|
||||
Captcha::$config['height'],
|
||||
imagesx($this->background_image),
|
||||
imagesy($this->background_image)
|
||||
);
|
||||
}
|
||||
|
||||
// Resize the image if needed
|
||||
if (imagesx($this->background_image) !== Captcha::$config['width']
|
||||
OR imagesy($this->background_image) !== Captcha::$config['height'])
|
||||
{
|
||||
imagecopyresampled
|
||||
(
|
||||
$this->image, $this->background_image, 0, 0, 0, 0,
|
||||
Captcha::$config['width'], Captcha::$config['height'],
|
||||
imagesx($this->background_image), imagesy($this->background_image)
|
||||
);
|
||||
}
|
||||
// Free up resources
|
||||
imagedestroy($this->background_image);
|
||||
}
|
||||
}
|
||||
|
||||
// Free up resources
|
||||
imagedestroy($this->background_image);
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Fills the background with a gradient.
|
||||
*
|
||||
* @param resource gd image color identifier for start color
|
||||
* @param resource gd image color identifier for end color
|
||||
* @param string direction: 'horizontal' or 'vertical', 'random' by default
|
||||
* @return void
|
||||
*/
|
||||
public function image_gradient($color1, $color2, $direction = null)
|
||||
{
|
||||
$directions = array('horizontal', 'vertical');
|
||||
|
||||
/**
|
||||
* Fills the background with a gradient.
|
||||
*
|
||||
* @param resource gd image color identifier for start color
|
||||
* @param resource gd image color identifier for end color
|
||||
* @param string direction: 'horizontal' or 'vertical', 'random' by default
|
||||
* @return void
|
||||
*/
|
||||
public function image_gradient($color1, $color2, $direction = NULL)
|
||||
{
|
||||
$directions = array('horizontal', 'vertical');
|
||||
// Pick a random direction if needed
|
||||
if (! in_array($direction, $directions)) {
|
||||
$direction = $directions[array_rand($directions)];
|
||||
|
||||
// Pick a random direction if needed
|
||||
if ( ! in_array($direction, $directions))
|
||||
{
|
||||
$direction = $directions[array_rand($directions)];
|
||||
// Switch colors
|
||||
if (mt_rand(0, 1) === 1) {
|
||||
$temp = $color1;
|
||||
$color1 = $color2;
|
||||
$color2 = $temp;
|
||||
}
|
||||
}
|
||||
|
||||
// Switch colors
|
||||
if (mt_rand(0, 1) === 1)
|
||||
{
|
||||
$temp = $color1;
|
||||
$color1 = $color2;
|
||||
$color2 = $temp;
|
||||
}
|
||||
}
|
||||
// Extract RGB values
|
||||
$color1 = imagecolorsforindex($this->image, $color1);
|
||||
$color2 = imagecolorsforindex($this->image, $color2);
|
||||
|
||||
// Extract RGB values
|
||||
$color1 = imagecolorsforindex($this->image, $color1);
|
||||
$color2 = imagecolorsforindex($this->image, $color2);
|
||||
// Preparations for the gradient loop
|
||||
$steps = ($direction === 'horizontal') ? Captcha::$config['width'] : Captcha::$config['height'];
|
||||
|
||||
// Preparations for the gradient loop
|
||||
$steps = ($direction === 'horizontal') ? Captcha::$config['width'] : Captcha::$config['height'];
|
||||
$r1 = ($color1['red'] - $color2['red']) / $steps;
|
||||
$g1 = ($color1['green'] - $color2['green']) / $steps;
|
||||
$b1 = ($color1['blue'] - $color2['blue']) / $steps;
|
||||
|
||||
$r1 = ($color1['red'] - $color2['red']) / $steps;
|
||||
$g1 = ($color1['green'] - $color2['green']) / $steps;
|
||||
$b1 = ($color1['blue'] - $color2['blue']) / $steps;
|
||||
if ($direction === 'horizontal') {
|
||||
$x1 =& $i;
|
||||
$y1 = 0;
|
||||
$x2 =& $i;
|
||||
$y2 = Captcha::$config['height'];
|
||||
} else {
|
||||
$x1 = 0;
|
||||
$y1 =& $i;
|
||||
$x2 = Captcha::$config['width'];
|
||||
$y2 =& $i;
|
||||
}
|
||||
|
||||
if ($direction === 'horizontal')
|
||||
{
|
||||
$x1 =& $i;
|
||||
$y1 = 0;
|
||||
$x2 =& $i;
|
||||
$y2 = Captcha::$config['height'];
|
||||
}
|
||||
else
|
||||
{
|
||||
$x1 = 0;
|
||||
$y1 =& $i;
|
||||
$x2 = Captcha::$config['width'];
|
||||
$y2 =& $i;
|
||||
}
|
||||
// Execute the gradient loop
|
||||
for ($i = 0; $i <= $steps; $i++) {
|
||||
$r2 = $color1['red'] - floor($i * $r1);
|
||||
$g2 = $color1['green'] - floor($i * $g1);
|
||||
$b2 = $color1['blue'] - floor($i * $b1);
|
||||
$color = imagecolorallocate($this->image, $r2, $g2, $b2);
|
||||
|
||||
// Execute the gradient loop
|
||||
for ($i = 0; $i <= $steps; $i++)
|
||||
{
|
||||
$r2 = $color1['red'] - floor($i * $r1);
|
||||
$g2 = $color1['green'] - floor($i * $g1);
|
||||
$b2 = $color1['blue'] - floor($i * $b1);
|
||||
$color = imagecolorallocate($this->image, $r2, $g2, $b2);
|
||||
imageline($this->image, $x1, $y1, $x2, $y2, $color);
|
||||
}
|
||||
}
|
||||
|
||||
imageline($this->image, $x1, $y1, $x2, $y2, $color);
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Returns the img html element or outputs the image to the browser.
|
||||
*
|
||||
* @param boolean html output
|
||||
* @return mixed html string or void
|
||||
*/
|
||||
public function image_render($html)
|
||||
{
|
||||
// Output html element
|
||||
if ($html) {
|
||||
return '<img alt="Captcha" src="' .
|
||||
url::site('captcha/' . Captcha::$config['group']) .
|
||||
'" width="' . Captcha::$config['width'] .
|
||||
'" height="' . Captcha::$config['height'] . '" />';
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the img html element or outputs the image to the browser.
|
||||
*
|
||||
* @param boolean html output
|
||||
* @return mixed html string or void
|
||||
*/
|
||||
public function image_render($html)
|
||||
{
|
||||
// Output html element
|
||||
if ($html)
|
||||
return '<img alt="Captcha" src="'.url::site('captcha/'.Captcha::$config['group']).'" width="'.Captcha::$config['width'].'" height="'.Captcha::$config['height'].'" />';
|
||||
// Send the correct HTTP header
|
||||
header('Content-Type: image/' . $this->image_type);
|
||||
|
||||
// Send the correct HTTP header
|
||||
header('Content-Type: image/'.$this->image_type);
|
||||
// Pick the correct output function
|
||||
$function = 'image' . $this->image_type;
|
||||
$function($this->image);
|
||||
|
||||
// Pick the correct output function
|
||||
$function = 'image'.$this->image_type;
|
||||
$function($this->image);
|
||||
|
||||
// Free up resources
|
||||
imagedestroy($this->image);
|
||||
}
|
||||
|
||||
} // End Captcha Driver
|
||||
// Free up resources
|
||||
imagedestroy($this->image);
|
||||
}
|
||||
}
|
||||
// End Captcha Driver
|
||||
|
||||
@@ -1,4 +1,12 @@
|
||||
<?php defined('SYSPATH') OR die('No direct access allowed.');
|
||||
<?php
|
||||
|
||||
// phpcs:disable PSR1.Classes.ClassDeclaration.MissingNamespace
|
||||
// phpcs:disable PSR1.Files.SideEffects
|
||||
defined('SYSPATH') or die('No direct access allowed.');
|
||||
// phpcs:enable PSR1.Files.SideEffects
|
||||
// phpcs:disable Squiz.Classes.ValidClassName.NotCamelCaps
|
||||
|
||||
|
||||
/**
|
||||
* Captcha driver for "alpha" style.
|
||||
*
|
||||
@@ -9,84 +17,87 @@
|
||||
* @copyright (c) 2007-2008 Kohana Team
|
||||
* @license http://kohanaphp.com/license.html
|
||||
*/
|
||||
class Captcha_Alpha_Driver extends Captcha_Driver {
|
||||
class Captcha_Alpha_Driver extends Captcha_Driver
|
||||
{
|
||||
/**
|
||||
* Generates a new Captcha challenge.
|
||||
*
|
||||
* @return string the challenge answer
|
||||
*/
|
||||
public function generate_challenge()
|
||||
{
|
||||
// Complexity setting is used as character count
|
||||
return text::random('distinct', max(1, Captcha::$config['complexity']));
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates a new Captcha challenge.
|
||||
*
|
||||
* @return string the challenge answer
|
||||
*/
|
||||
public function generate_challenge()
|
||||
{
|
||||
// Complexity setting is used as character count
|
||||
return text::random('distinct', max(1, Captcha::$config['complexity']));
|
||||
}
|
||||
/**
|
||||
* Outputs the Captcha image.
|
||||
*
|
||||
* @param boolean html output
|
||||
* @return mixed
|
||||
*/
|
||||
public function render($html)
|
||||
{
|
||||
// Creates $this->image
|
||||
$this->image_create(Captcha::$config['background']);
|
||||
|
||||
/**
|
||||
* Outputs the Captcha image.
|
||||
*
|
||||
* @param boolean html output
|
||||
* @return mixed
|
||||
*/
|
||||
public function render($html)
|
||||
{
|
||||
// Creates $this->image
|
||||
$this->image_create(Captcha::$config['background']);
|
||||
// Add a random gradient
|
||||
if (empty(Captcha::$config['background'])) {
|
||||
$color1 = imagecolorallocate($this->image, mt_rand(0, 100), mt_rand(0, 100), mt_rand(0, 100));
|
||||
$color2 = imagecolorallocate($this->image, mt_rand(0, 100), mt_rand(0, 100), mt_rand(0, 100));
|
||||
$this->image_gradient($color1, $color2);
|
||||
}
|
||||
|
||||
// Add a random gradient
|
||||
if (empty(Captcha::$config['background']))
|
||||
{
|
||||
$color1 = imagecolorallocate($this->image, mt_rand(0, 100), mt_rand(0, 100), mt_rand(0, 100));
|
||||
$color2 = imagecolorallocate($this->image, mt_rand(0, 100), mt_rand(0, 100), mt_rand(0, 100));
|
||||
$this->image_gradient($color1, $color2);
|
||||
}
|
||||
// Add a few random circles
|
||||
for ($i = 0, $count = mt_rand(10, Captcha::$config['complexity'] * 3); $i < $count; $i++) {
|
||||
$color = imagecolorallocatealpha($this->image, mt_rand(0, 255), mt_rand(0, 255), mt_rand(0, 255), mt_rand(80, 120));
|
||||
$size = mt_rand(5, Captcha::$config['height'] / 3);
|
||||
imagefilledellipse($this->image, mt_rand(0, Captcha::$config['width']), mt_rand(0, Captcha::$config['height']), $size, $size, $color);
|
||||
}
|
||||
|
||||
// Add a few random circles
|
||||
for ($i = 0, $count = mt_rand(10, Captcha::$config['complexity'] * 3); $i < $count; $i++)
|
||||
{
|
||||
$color = imagecolorallocatealpha($this->image, mt_rand(0, 255), mt_rand(0, 255), mt_rand(0, 255), mt_rand(80, 120));
|
||||
$size = mt_rand(5, Captcha::$config['height'] / 3);
|
||||
imagefilledellipse($this->image, mt_rand(0, Captcha::$config['width']), mt_rand(0, Captcha::$config['height']), $size, $size, $color);
|
||||
}
|
||||
// Calculate character font-size and spacing
|
||||
$default_size = min(Captcha::$config['width'], Captcha::$config['height'] * 2) / strlen($this->response);
|
||||
$spacing = (int) (Captcha::$config['width'] * 0.9 / strlen($this->response));
|
||||
|
||||
// Calculate character font-size and spacing
|
||||
$default_size = min(Captcha::$config['width'], Captcha::$config['height'] * 2) / strlen($this->response);
|
||||
$spacing = (int) (Captcha::$config['width'] * 0.9 / strlen($this->response));
|
||||
// Background alphabetic character attributes
|
||||
$color_limit = mt_rand(96, 160);
|
||||
$chars = 'ABEFGJKLPQRTVY';
|
||||
|
||||
// Background alphabetic character attributes
|
||||
$color_limit = mt_rand(96, 160);
|
||||
$chars = 'ABEFGJKLPQRTVY';
|
||||
// Draw each Captcha character with varying attributes
|
||||
for ($i = 0, $strlen = strlen($this->response); $i < $strlen; $i++) {
|
||||
// Use different fonts if available
|
||||
$font = Captcha::$config['fontpath'] . Captcha::$config['fonts'][array_rand(Captcha::$config['fonts'])];
|
||||
|
||||
// Draw each Captcha character with varying attributes
|
||||
for ($i = 0, $strlen = strlen($this->response); $i < $strlen; $i++)
|
||||
{
|
||||
// Use different fonts if available
|
||||
$font = Captcha::$config['fontpath'].Captcha::$config['fonts'][array_rand(Captcha::$config['fonts'])];
|
||||
$angle = mt_rand(-40, 20);
|
||||
// Scale the character size on image height
|
||||
$size = $default_size / 10 * mt_rand(8, 12);
|
||||
$box = imageftbbox($size, $angle, $font, $this->response[$i]);
|
||||
|
||||
$angle = mt_rand(-40, 20);
|
||||
// Scale the character size on image height
|
||||
$size = $default_size / 10 * mt_rand(8, 12);
|
||||
$box = imageftbbox($size, $angle, $font, $this->response[$i]);
|
||||
// Calculate character starting coordinates
|
||||
$x = $spacing / 4 + $i * $spacing;
|
||||
$y = Captcha::$config['height'] / 2 + ($box[2] - $box[5]) / 4;
|
||||
|
||||
// Calculate character starting coordinates
|
||||
$x = $spacing / 4 + $i * $spacing;
|
||||
$y = Captcha::$config['height'] / 2 + ($box[2] - $box[5]) / 4;
|
||||
// Draw captcha text character
|
||||
// Allocate random color, size and rotation attributes to text
|
||||
$color = imagecolorallocate($this->image, mt_rand(150, 255), mt_rand(200, 255), mt_rand(0, 255));
|
||||
|
||||
// Draw captcha text character
|
||||
// Allocate random color, size and rotation attributes to text
|
||||
$color = imagecolorallocate($this->image, mt_rand(150, 255), mt_rand(200, 255), mt_rand(0, 255));
|
||||
// Write text character to image
|
||||
imagefttext($this->image, $size, $angle, $x, $y, $color, $font, $this->response[$i]);
|
||||
|
||||
// Write text character to image
|
||||
imagefttext($this->image, $size, $angle, $x, $y, $color, $font, $this->response[$i]);
|
||||
// Draw "ghost" alphabetic character
|
||||
$text_color = imagecolorallocatealpha(
|
||||
$this->image,
|
||||
mt_rand($color_limit + 8, 255),
|
||||
mt_rand($color_limit + 8, 255),
|
||||
mt_rand($color_limit + 8, 255),
|
||||
mt_rand(70, 120)
|
||||
);
|
||||
$char = $chars[mt_rand(0, 14)];
|
||||
imagettftext($this->image, $size * 2, mt_rand(-45, 45), ($x - (mt_rand(5, 10))), ($y + (mt_rand(5, 10))), $text_color, $font, $char);
|
||||
}
|
||||
|
||||
// Draw "ghost" alphabetic character
|
||||
$text_color = imagecolorallocatealpha($this->image, mt_rand($color_limit + 8, 255), mt_rand($color_limit + 8, 255), mt_rand($color_limit + 8, 255), mt_rand(70, 120));
|
||||
$char = $chars[mt_rand(0, 14)];
|
||||
imagettftext($this->image, $size * 2, mt_rand(-45, 45), ($x - (mt_rand(5, 10))), ($y + (mt_rand(5, 10))), $text_color, $font, $char);
|
||||
}
|
||||
|
||||
// Output
|
||||
return $this->image_render($html);
|
||||
}
|
||||
|
||||
} // End Captcha Alpha Driver Class
|
||||
// Output
|
||||
return $this->image_render($html);
|
||||
}
|
||||
}
|
||||
// End Captcha Alpha Driver Class
|
||||
|
||||
@@ -1,4 +1,12 @@
|
||||
<?php defined('SYSPATH') OR die('No direct access allowed.');
|
||||
<?php
|
||||
|
||||
// phpcs:disable PSR1.Classes.ClassDeclaration.MissingNamespace
|
||||
// phpcs:disable PSR1.Files.SideEffects
|
||||
defined('SYSPATH') or die('No direct access allowed.');
|
||||
// phpcs:enable PSR1.Files.SideEffects
|
||||
// phpcs:disable Squiz.Classes.ValidClassName.NotCamelCaps
|
||||
|
||||
|
||||
/**
|
||||
* Captcha driver for "basic" style.
|
||||
*
|
||||
@@ -9,73 +17,70 @@
|
||||
* @copyright (c) 2007-2008 Kohana Team
|
||||
* @license http://kohanaphp.com/license.html
|
||||
*/
|
||||
class Captcha_Basic_Driver extends Captcha_Driver {
|
||||
class Captcha_Basic_Driver extends Captcha_Driver
|
||||
{
|
||||
/**
|
||||
* Generates a new Captcha challenge.
|
||||
*
|
||||
* @return string the challenge answer
|
||||
*/
|
||||
public function generate_challenge()
|
||||
{
|
||||
// Complexity setting is used as character count
|
||||
return text::random('distinct', max(1, Captcha::$config['complexity']));
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates a new Captcha challenge.
|
||||
*
|
||||
* @return string the challenge answer
|
||||
*/
|
||||
public function generate_challenge()
|
||||
{
|
||||
// Complexity setting is used as character count
|
||||
return text::random('distinct', max(1, Captcha::$config['complexity']));
|
||||
}
|
||||
/**
|
||||
* Outputs the Captcha image.
|
||||
*
|
||||
* @param boolean html output
|
||||
* @return mixed
|
||||
*/
|
||||
public function render($html)
|
||||
{
|
||||
// Creates $this->image
|
||||
$this->image_create(Captcha::$config['background']);
|
||||
|
||||
/**
|
||||
* Outputs the Captcha image.
|
||||
*
|
||||
* @param boolean html output
|
||||
* @return mixed
|
||||
*/
|
||||
public function render($html)
|
||||
{
|
||||
// Creates $this->image
|
||||
$this->image_create(Captcha::$config['background']);
|
||||
// Add a random gradient
|
||||
if (empty(Captcha::$config['background'])) {
|
||||
$color1 = imagecolorallocate($this->image, mt_rand(200, 255), mt_rand(200, 255), mt_rand(150, 255));
|
||||
$color2 = imagecolorallocate($this->image, mt_rand(200, 255), mt_rand(200, 255), mt_rand(150, 255));
|
||||
$this->image_gradient($color1, $color2);
|
||||
}
|
||||
|
||||
// Add a random gradient
|
||||
if (empty(Captcha::$config['background']))
|
||||
{
|
||||
$color1 = imagecolorallocate($this->image, mt_rand(200, 255), mt_rand(200, 255), mt_rand(150, 255));
|
||||
$color2 = imagecolorallocate($this->image, mt_rand(200, 255), mt_rand(200, 255), mt_rand(150, 255));
|
||||
$this->image_gradient($color1, $color2);
|
||||
}
|
||||
// Add a few random lines
|
||||
for ($i = 0, $count = mt_rand(5, Captcha::$config['complexity'] * 4); $i < $count; $i++) {
|
||||
$color = imagecolorallocatealpha($this->image, mt_rand(0, 255), mt_rand(0, 255), mt_rand(100, 255), mt_rand(50, 120));
|
||||
imageline($this->image, mt_rand(0, Captcha::$config['width']), 0, mt_rand(0, Captcha::$config['width']), Captcha::$config['height'], $color);
|
||||
}
|
||||
|
||||
// Add a few random lines
|
||||
for ($i = 0, $count = mt_rand(5, Captcha::$config['complexity'] * 4); $i < $count; $i++)
|
||||
{
|
||||
$color = imagecolorallocatealpha($this->image, mt_rand(0, 255), mt_rand(0, 255), mt_rand(100, 255), mt_rand(50, 120));
|
||||
imageline($this->image, mt_rand(0, Captcha::$config['width']), 0, mt_rand(0, Captcha::$config['width']), Captcha::$config['height'], $color);
|
||||
}
|
||||
// Calculate character font-size and spacing
|
||||
$default_size = min(Captcha::$config['width'], Captcha::$config['height'] * 2) / (strlen($this->response) + 1);
|
||||
$spacing = (int) (Captcha::$config['width'] * 0.9 / strlen($this->response));
|
||||
|
||||
// Calculate character font-size and spacing
|
||||
$default_size = min(Captcha::$config['width'], Captcha::$config['height'] * 2) / (strlen($this->response) + 1);
|
||||
$spacing = (int) (Captcha::$config['width'] * 0.9 / strlen($this->response));
|
||||
// Draw each Captcha character with varying attributes
|
||||
for ($i = 0, $strlen = strlen($this->response); $i < $strlen; $i++) {
|
||||
// Use different fonts if available
|
||||
$font = Captcha::$config['fontpath'] . Captcha::$config['fonts'][array_rand(Captcha::$config['fonts'])];
|
||||
|
||||
// Draw each Captcha character with varying attributes
|
||||
for ($i = 0, $strlen = strlen($this->response); $i < $strlen; $i++)
|
||||
{
|
||||
// Use different fonts if available
|
||||
$font = Captcha::$config['fontpath'].Captcha::$config['fonts'][array_rand(Captcha::$config['fonts'])];
|
||||
// Allocate random color, size and rotation attributes to text
|
||||
$color = imagecolorallocate($this->image, mt_rand(0, 150), mt_rand(0, 150), mt_rand(0, 150));
|
||||
$angle = mt_rand(-40, 20);
|
||||
|
||||
// Allocate random color, size and rotation attributes to text
|
||||
$color = imagecolorallocate($this->image, mt_rand(0, 150), mt_rand(0, 150), mt_rand(0, 150));
|
||||
$angle = mt_rand(-40, 20);
|
||||
// Scale the character size on image height
|
||||
$size = $default_size / 10 * mt_rand(8, 12);
|
||||
$box = imageftbbox($size, $angle, $font, $this->response[$i]);
|
||||
|
||||
// Scale the character size on image height
|
||||
$size = $default_size / 10 * mt_rand(8, 12);
|
||||
$box = imageftbbox($size, $angle, $font, $this->response[$i]);
|
||||
// Calculate character starting coordinates
|
||||
$x = $spacing / 4 + $i * $spacing;
|
||||
$y = Captcha::$config['height'] / 2 + ($box[2] - $box[5]) / 4;
|
||||
|
||||
// Calculate character starting coordinates
|
||||
$x = $spacing / 4 + $i * $spacing;
|
||||
$y = Captcha::$config['height'] / 2 + ($box[2] - $box[5]) / 4;
|
||||
// Write text character to image
|
||||
imagefttext($this->image, $size, $angle, $x, $y, $color, $font, $this->response[$i]);
|
||||
}
|
||||
|
||||
// Write text character to image
|
||||
imagefttext($this->image, $size, $angle, $x, $y, $color, $font, $this->response[$i]);
|
||||
}
|
||||
|
||||
// Output
|
||||
return $this->image_render($html);
|
||||
}
|
||||
|
||||
} // End Captcha Basic Driver Class
|
||||
// Output
|
||||
return $this->image_render($html);
|
||||
}
|
||||
}
|
||||
// End Captcha Basic Driver Class
|
||||
|
||||
@@ -1,4 +1,12 @@
|
||||
<?php defined('SYSPATH') OR die('No direct access allowed.');
|
||||
<?php
|
||||
|
||||
// phpcs:disable PSR1.Classes.ClassDeclaration.MissingNamespace
|
||||
// phpcs:disable PSR1.Files.SideEffects
|
||||
defined('SYSPATH') or die('No direct access allowed.');
|
||||
// phpcs:enable PSR1.Files.SideEffects
|
||||
// phpcs:disable Squiz.Classes.ValidClassName.NotCamelCaps
|
||||
|
||||
|
||||
/**
|
||||
* Captcha driver for "black" style.
|
||||
*
|
||||
@@ -9,64 +17,84 @@
|
||||
* @copyright (c) 2007-2008 Kohana Team
|
||||
* @license http://kohanaphp.com/license.html
|
||||
*/
|
||||
class Captcha_Black_Driver extends Captcha_Driver {
|
||||
class Captcha_Black_Driver extends Captcha_Driver
|
||||
{
|
||||
/**
|
||||
* Generates a new Captcha challenge.
|
||||
*
|
||||
* @return string the challenge answer
|
||||
*/
|
||||
public function generate_challenge()
|
||||
{
|
||||
// Complexity setting is used as character count
|
||||
return text::random('distinct', max(1, ceil(Captcha::$config['complexity'] / 1.5)));
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates a new Captcha challenge.
|
||||
*
|
||||
* @return string the challenge answer
|
||||
*/
|
||||
public function generate_challenge()
|
||||
{
|
||||
// Complexity setting is used as character count
|
||||
return text::random('distinct', max(1, ceil(Captcha::$config['complexity'] / 1.5)));
|
||||
}
|
||||
/**
|
||||
* Outputs the Captcha image.
|
||||
*
|
||||
* @param boolean html output
|
||||
* @return mixed
|
||||
*/
|
||||
public function render($html)
|
||||
{
|
||||
// Creates a black image to start from
|
||||
$this->image_create(Captcha::$config['background']);
|
||||
|
||||
/**
|
||||
* Outputs the Captcha image.
|
||||
*
|
||||
* @param boolean html output
|
||||
* @return mixed
|
||||
*/
|
||||
public function render($html)
|
||||
{
|
||||
// Creates a black image to start from
|
||||
$this->image_create(Captcha::$config['background']);
|
||||
// Add random white/gray arcs, amount depends on complexity setting
|
||||
$count = (Captcha::$config['width'] + Captcha::$config['height']) / 2;
|
||||
$count = $count / 5 * min(10, Captcha::$config['complexity']);
|
||||
for ($i = 0; $i < $count; $i++) {
|
||||
imagesetthickness($this->image, mt_rand(1, 2));
|
||||
$color = imagecolorallocatealpha($this->image, 255, 255, 255, mt_rand(0, 120));
|
||||
imagearc(
|
||||
$this->image,
|
||||
mt_rand(
|
||||
-Captcha::$config['width'],
|
||||
Captcha::$config['width']
|
||||
),
|
||||
mt_rand(
|
||||
-Captcha::$config['height'],
|
||||
Captcha::$config['height']
|
||||
),
|
||||
mt_rand(
|
||||
-Captcha::$config['width'],
|
||||
Captcha::$config['width']
|
||||
),
|
||||
mt_rand(
|
||||
-Captcha::$config['height'],
|
||||
Captcha::$config['height']
|
||||
),
|
||||
mt_rand(0, 360),
|
||||
mt_rand(0, 360),
|
||||
$color
|
||||
);
|
||||
}
|
||||
|
||||
// Add random white/gray arcs, amount depends on complexity setting
|
||||
$count = (Captcha::$config['width'] + Captcha::$config['height']) / 2;
|
||||
$count = $count / 5 * min(10, Captcha::$config['complexity']);
|
||||
for ($i = 0; $i < $count; $i++)
|
||||
{
|
||||
imagesetthickness($this->image, mt_rand(1, 2));
|
||||
$color = imagecolorallocatealpha($this->image, 255, 255, 255, mt_rand(0, 120));
|
||||
imagearc($this->image, mt_rand(-Captcha::$config['width'], Captcha::$config['width']), mt_rand(-Captcha::$config['height'], Captcha::$config['height']), mt_rand(-Captcha::$config['width'], Captcha::$config['width']), mt_rand(-Captcha::$config['height'], Captcha::$config['height']), mt_rand(0, 360), mt_rand(0, 360), $color);
|
||||
}
|
||||
// Use different fonts if available
|
||||
$font = Captcha::$config['fontpath'] . Captcha::$config['fonts'][array_rand(Captcha::$config['fonts'])];
|
||||
|
||||
// Use different fonts if available
|
||||
$font = Captcha::$config['fontpath'].Captcha::$config['fonts'][array_rand(Captcha::$config['fonts'])];
|
||||
// Draw the character's white shadows
|
||||
$size = (int) min(Captcha::$config['height'] / 2, Captcha::$config['width'] * 0.8 / strlen($this->response));
|
||||
$angle = mt_rand(-15 + strlen($this->response), 15 - strlen($this->response));
|
||||
$x = mt_rand(1, Captcha::$config['width'] * 0.9 - $size * strlen($this->response));
|
||||
$y = ((Captcha::$config['height'] - $size) / 2) + $size;
|
||||
$color = imagecolorallocate($this->image, 255, 255, 255);
|
||||
imagefttext($this->image, $size, $angle, $x + 1, $y + 1, $color, $font, $this->response);
|
||||
|
||||
// Draw the character's white shadows
|
||||
$size = (int) min(Captcha::$config['height'] / 2, Captcha::$config['width'] * 0.8 / strlen($this->response));
|
||||
$angle = mt_rand(-15 + strlen($this->response), 15 - strlen($this->response));
|
||||
$x = mt_rand(1, Captcha::$config['width'] * 0.9 - $size * strlen($this->response));
|
||||
$y = ((Captcha::$config['height'] - $size) / 2) + $size;
|
||||
$color = imagecolorallocate($this->image, 255, 255, 255);
|
||||
imagefttext($this->image, $size, $angle, $x + 1, $y + 1, $color, $font, $this->response);
|
||||
// Add more shadows for lower complexities
|
||||
(Captcha::$config['complexity'] < 10) and imagefttext($this->image, $size, $angle, $x - 1, $y - 1, $color, $font, $this->response);
|
||||
(Captcha::$config['complexity'] < 8) and imagefttext($this->image, $size, $angle, $x - 2, $y + 2, $color, $font, $this->response);
|
||||
(Captcha::$config['complexity'] < 6) and imagefttext($this->image, $size, $angle, $x + 2, $y - 2, $color, $font, $this->response);
|
||||
(Captcha::$config['complexity'] < 4) and imagefttext($this->image, $size, $angle, $x + 3, $y + 3, $color, $font, $this->response);
|
||||
(Captcha::$config['complexity'] < 2) and imagefttext($this->image, $size, $angle, $x - 3, $y - 3, $color, $font, $this->response);
|
||||
|
||||
// Add more shadows for lower complexities
|
||||
(Captcha::$config['complexity'] < 10) and imagefttext($this->image, $size, $angle, $x - 1, $y - 1, $color, $font , $this->response);
|
||||
(Captcha::$config['complexity'] < 8) and imagefttext($this->image, $size, $angle, $x - 2, $y + 2, $color, $font , $this->response);
|
||||
(Captcha::$config['complexity'] < 6) and imagefttext($this->image, $size, $angle, $x + 2, $y - 2, $color, $font , $this->response);
|
||||
(Captcha::$config['complexity'] < 4) and imagefttext($this->image, $size, $angle, $x + 3, $y + 3, $color, $font , $this->response);
|
||||
(Captcha::$config['complexity'] < 2) and imagefttext($this->image, $size, $angle, $x - 3, $y - 3, $color, $font , $this->response);
|
||||
// Finally draw the foreground characters
|
||||
$color = imagecolorallocate($this->image, 0, 0, 0);
|
||||
imagefttext($this->image, $size, $angle, $x, $y, $color, $font, $this->response);
|
||||
|
||||
// Finally draw the foreground characters
|
||||
$color = imagecolorallocate($this->image, 0, 0, 0);
|
||||
imagefttext($this->image, $size, $angle, $x, $y, $color, $font, $this->response);
|
||||
|
||||
// Output
|
||||
return $this->image_render($html);
|
||||
}
|
||||
|
||||
} // End Captcha Black Driver Class
|
||||
// Output
|
||||
return $this->image_render($html);
|
||||
}
|
||||
}
|
||||
// End Captcha Black Driver Class
|
||||
|
||||
@@ -1,4 +1,12 @@
|
||||
<?php defined('SYSPATH') OR die('No direct access allowed.');
|
||||
<?php
|
||||
|
||||
// phpcs:disable PSR1.Classes.ClassDeclaration.MissingNamespace
|
||||
// phpcs:disable PSR1.Files.SideEffects
|
||||
defined('SYSPATH') or die('No direct access allowed.');
|
||||
// phpcs:enable PSR1.Files.SideEffects
|
||||
// phpcs:disable Squiz.Classes.ValidClassName.NotCamelCaps
|
||||
|
||||
|
||||
/**
|
||||
* Captcha driver for "math" style.
|
||||
*
|
||||
@@ -9,53 +17,48 @@
|
||||
* @copyright (c) 2007-2008 Kohana Team
|
||||
* @license http://kohanaphp.com/license.html
|
||||
*/
|
||||
class Captcha_Math_Driver extends Captcha_Driver {
|
||||
class Captcha_Math_Driver extends Captcha_Driver
|
||||
{
|
||||
private $math_exercice;
|
||||
|
||||
private $math_exercice;
|
||||
/**
|
||||
* Generates a new Captcha challenge.
|
||||
*
|
||||
* @return string the challenge answer
|
||||
*/
|
||||
public function generate_challenge()
|
||||
{
|
||||
// Easy
|
||||
if (Captcha::$config['complexity'] < 4) {
|
||||
$numbers[] = mt_rand(1, 5);
|
||||
$numbers[] = mt_rand(1, 4);
|
||||
} elseif (Captcha::$config['complexity'] < 7) {
|
||||
// Normal
|
||||
$numbers[] = mt_rand(10, 20);
|
||||
$numbers[] = mt_rand(1, 10);
|
||||
} else {
|
||||
// Difficult, well, not really ;)
|
||||
$numbers[] = mt_rand(100, 200);
|
||||
$numbers[] = mt_rand(10, 20);
|
||||
$numbers[] = mt_rand(1, 10);
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates a new Captcha challenge.
|
||||
*
|
||||
* @return string the challenge answer
|
||||
*/
|
||||
public function generate_challenge()
|
||||
{
|
||||
// Easy
|
||||
if (Captcha::$config['complexity'] < 4)
|
||||
{
|
||||
$numbers[] = mt_rand(1, 5);
|
||||
$numbers[] = mt_rand(1, 4);
|
||||
}
|
||||
// Normal
|
||||
elseif (Captcha::$config['complexity'] < 7)
|
||||
{
|
||||
$numbers[] = mt_rand(10, 20);
|
||||
$numbers[] = mt_rand(1, 10);
|
||||
}
|
||||
// Difficult, well, not really ;)
|
||||
else
|
||||
{
|
||||
$numbers[] = mt_rand(100, 200);
|
||||
$numbers[] = mt_rand(10, 20);
|
||||
$numbers[] = mt_rand(1, 10);
|
||||
}
|
||||
// Store the question for output
|
||||
$this->math_exercice = implode(' + ', $numbers) . ' = ';
|
||||
|
||||
// Store the question for output
|
||||
$this->math_exercice = implode(' + ', $numbers).' = ';
|
||||
// Return the answer
|
||||
return array_sum($numbers);
|
||||
}
|
||||
|
||||
// Return the answer
|
||||
return array_sum($numbers);
|
||||
}
|
||||
|
||||
/**
|
||||
* Outputs the Captcha riddle.
|
||||
*
|
||||
* @param boolean html output
|
||||
* @return mixed
|
||||
*/
|
||||
public function render($html)
|
||||
{
|
||||
return $this->math_exercice;
|
||||
}
|
||||
|
||||
} // End Captcha Math Driver Class
|
||||
/**
|
||||
* Outputs the Captcha riddle.
|
||||
*
|
||||
* @param boolean html output
|
||||
* @return mixed
|
||||
*/
|
||||
public function render($html)
|
||||
{
|
||||
return $this->math_exercice;
|
||||
}
|
||||
}
|
||||
// End Captcha Math Driver Class
|
||||
|
||||
@@ -1,4 +1,12 @@
|
||||
<?php defined('SYSPATH') OR die('No direct access allowed.');
|
||||
<?php
|
||||
|
||||
// phpcs:disable PSR1.Classes.ClassDeclaration.MissingNamespace
|
||||
// phpcs:disable PSR1.Files.SideEffects
|
||||
defined('SYSPATH') or die('No direct access allowed.');
|
||||
// phpcs:enable PSR1.Files.SideEffects
|
||||
// phpcs:disable Squiz.Classes.ValidClassName.NotCamelCaps
|
||||
|
||||
|
||||
/**
|
||||
* Captcha driver for "riddle" style.
|
||||
*
|
||||
@@ -9,39 +17,39 @@
|
||||
* @copyright (c) 2007-2008 Kohana Team
|
||||
* @license http://kohanaphp.com/license.html
|
||||
*/
|
||||
class Captcha_Riddle_Driver extends Captcha_Driver {
|
||||
class Captcha_Riddle_Driver extends Captcha_Driver
|
||||
{
|
||||
private $riddle;
|
||||
|
||||
private $riddle;
|
||||
/**
|
||||
* Generates a new Captcha challenge.
|
||||
*
|
||||
* @return string the challenge answer
|
||||
*/
|
||||
public function generate_challenge()
|
||||
{
|
||||
// Load riddles from the current language
|
||||
$riddles = Kohana::lang('captcha.riddles');
|
||||
|
||||
/**
|
||||
* Generates a new Captcha challenge.
|
||||
*
|
||||
* @return string the challenge answer
|
||||
*/
|
||||
public function generate_challenge()
|
||||
{
|
||||
// Load riddles from the current language
|
||||
$riddles = Kohana::lang('captcha.riddles');
|
||||
// Pick a random riddle
|
||||
$riddle = $riddles[array_rand($riddles)];
|
||||
|
||||
// Pick a random riddle
|
||||
$riddle = $riddles[array_rand($riddles)];
|
||||
// Store the question for output
|
||||
$this->riddle = $riddle[0];
|
||||
|
||||
// Store the question for output
|
||||
$this->riddle = $riddle[0];
|
||||
// Return the answer
|
||||
return $riddle[1];
|
||||
}
|
||||
|
||||
// Return the answer
|
||||
return $riddle[1];
|
||||
}
|
||||
|
||||
/**
|
||||
* Outputs the Captcha riddle.
|
||||
*
|
||||
* @param boolean html output
|
||||
* @return mixed
|
||||
*/
|
||||
public function render($html)
|
||||
{
|
||||
return $this->riddle;
|
||||
}
|
||||
|
||||
} // End Captcha Riddle Driver Class
|
||||
/**
|
||||
* Outputs the Captcha riddle.
|
||||
*
|
||||
* @param boolean html output
|
||||
* @return mixed
|
||||
*/
|
||||
public function render($html)
|
||||
{
|
||||
return $this->riddle;
|
||||
}
|
||||
}
|
||||
// End Captcha Riddle Driver Class
|
||||
|
||||
@@ -1,4 +1,12 @@
|
||||
<?php defined('SYSPATH') OR die('No direct access allowed.');
|
||||
<?php
|
||||
|
||||
// phpcs:disable PSR1.Classes.ClassDeclaration.MissingNamespace
|
||||
// phpcs:disable PSR1.Files.SideEffects
|
||||
defined('SYSPATH') or die('No direct access allowed.');
|
||||
// phpcs:enable PSR1.Files.SideEffects
|
||||
// phpcs:disable Squiz.Classes.ValidClassName.NotCamelCaps
|
||||
|
||||
|
||||
/**
|
||||
* Captcha driver for "word" style.
|
||||
*
|
||||
@@ -9,29 +17,29 @@
|
||||
* @copyright (c) 2007-2008 Kohana Team
|
||||
* @license http://kohanaphp.com/license.html
|
||||
*/
|
||||
class Captcha_Word_Driver extends Captcha_Basic_Driver {
|
||||
class Captcha_Word_Driver extends Captcha_Basic_Driver
|
||||
{
|
||||
/**
|
||||
* Generates a new Captcha challenge.
|
||||
*
|
||||
* @return string the challenge answer
|
||||
*/
|
||||
public function generate_challenge()
|
||||
{
|
||||
// Load words from the current language and randomize them
|
||||
$words = Kohana::lang('captcha.words');
|
||||
shuffle($words);
|
||||
|
||||
/**
|
||||
* Generates a new Captcha challenge.
|
||||
*
|
||||
* @return string the challenge answer
|
||||
*/
|
||||
public function generate_challenge()
|
||||
{
|
||||
// Load words from the current language and randomize them
|
||||
$words = Kohana::lang('captcha.words');
|
||||
shuffle($words);
|
||||
// Loop over each word...
|
||||
foreach ($words as $word) {
|
||||
// ...until we find one of the desired length
|
||||
if (abs(Captcha::$config['complexity'] - strlen($word)) < 2) {
|
||||
return strtoupper($word);
|
||||
}
|
||||
}
|
||||
|
||||
// Loop over each word...
|
||||
foreach ($words as $word)
|
||||
{
|
||||
// ...until we find one of the desired length
|
||||
if (abs(Captcha::$config['complexity'] - strlen($word)) < 2)
|
||||
return strtoupper($word);
|
||||
}
|
||||
|
||||
// Return any random word as final fallback
|
||||
return strtoupper($words[array_rand($words)]);
|
||||
}
|
||||
|
||||
} // End Captcha Word Driver Class
|
||||
// Return any random word as final fallback
|
||||
return strtoupper($words[array_rand($words)]);
|
||||
}
|
||||
}
|
||||
// End Captcha Word Driver Class
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,4 +1,13 @@
|
||||
<?php defined('SYSPATH') OR die('No direct access allowed.');
|
||||
<?php
|
||||
|
||||
// phpcs:disable PSR1.Classes.ClassDeclaration.MissingNamespace
|
||||
// phpcs:disable PSR1.Classes.ClassDeclaration.MultipleClasses
|
||||
// phpcs:disable PSR1.Files.SideEffects
|
||||
defined('SYSPATH') or die('No direct access allowed.');
|
||||
// phpcs:enable PSR1.Files.SideEffects
|
||||
// phpcs:disable Squiz.Classes.ValidClassName.NotCamelCaps
|
||||
|
||||
|
||||
/**
|
||||
* MSSQL Database Driver
|
||||
*
|
||||
@@ -9,454 +18,417 @@
|
||||
*/
|
||||
class Database_Mssql_Driver extends Database_Driver
|
||||
{
|
||||
/**
|
||||
* Database connection link
|
||||
*/
|
||||
protected $link;
|
||||
/**
|
||||
* Database connection link
|
||||
*/
|
||||
protected $link;
|
||||
|
||||
/**
|
||||
* Database configuration
|
||||
*/
|
||||
protected $db_config;
|
||||
/**
|
||||
* Database configuration
|
||||
*/
|
||||
protected $db_config;
|
||||
|
||||
/**
|
||||
* Sets the config for the class.
|
||||
*
|
||||
* @param array database configuration
|
||||
*/
|
||||
public function __construct($config)
|
||||
{
|
||||
$this->db_config = $config;
|
||||
/**
|
||||
* Sets the config for the class.
|
||||
*
|
||||
* @param array database configuration
|
||||
*/
|
||||
public function __construct($config)
|
||||
{
|
||||
$this->db_config = $config;
|
||||
|
||||
Kohana::log('debug', 'MSSQL Database Driver Initialized');
|
||||
}
|
||||
Kohana::log('debug', 'MSSQL Database Driver Initialized');
|
||||
}
|
||||
|
||||
/**
|
||||
* Closes the database connection.
|
||||
*/
|
||||
public function __destruct()
|
||||
{
|
||||
is_resource($this->link) and mssql_close($this->link);
|
||||
}
|
||||
/**
|
||||
* Closes the database connection.
|
||||
*/
|
||||
public function __destruct()
|
||||
{
|
||||
is_resource($this->link) and mssql_close($this->link);
|
||||
}
|
||||
|
||||
/**
|
||||
* Make the connection
|
||||
*
|
||||
* @return return connection
|
||||
*/
|
||||
public function connect()
|
||||
{
|
||||
// Check if link already exists
|
||||
if (is_resource($this->link))
|
||||
return $this->link;
|
||||
/**
|
||||
* Make the connection
|
||||
*
|
||||
* @return return connection
|
||||
*/
|
||||
public function connect()
|
||||
{
|
||||
// Check if link already exists
|
||||
if (is_resource($this->link)) {
|
||||
return $this->link;
|
||||
}
|
||||
|
||||
// Import the connect variables
|
||||
extract($this->db_config['connection']);
|
||||
// Import the connect variables
|
||||
extract($this->db_config['connection']);
|
||||
|
||||
// Persistent connections enabled?
|
||||
$connect = ($this->db_config['persistent'] == TRUE) ? 'mssql_pconnect' : 'mssql_connect';
|
||||
// Persistent connections enabled?
|
||||
$connect = ($this->db_config['persistent'] == true) ? 'mssql_pconnect' : 'mssql_connect';
|
||||
|
||||
// Build the connection info
|
||||
$host = isset($host) ? $host : $socket;
|
||||
// Build the connection info
|
||||
$host = isset($host) ? $host : $socket;
|
||||
|
||||
// Windows uses a comma instead of a colon
|
||||
$port = (isset($port) AND is_string($port)) ? (KOHANA_IS_WIN ? ',' : ':').$port : '';
|
||||
// Windows uses a comma instead of a colon
|
||||
$port = (isset($port) and is_string($port)) ? (KOHANA_IS_WIN ? ',' : ':') . $port : '';
|
||||
|
||||
// Make the connection and select the database
|
||||
if (($this->link = $connect($host.$port, $user, $pass, TRUE)) AND mssql_select_db($database, $this->link))
|
||||
{
|
||||
/* This is being removed so I can use it, will need to come up with a more elegant workaround in the future...
|
||||
*
|
||||
if ($charset = $this->db_config['character_set'])
|
||||
{
|
||||
$this->set_charset($charset);
|
||||
}
|
||||
*/
|
||||
// Make the connection and select the database
|
||||
if (($this->link = $connect($host . $port, $user, $pass, true)) and mssql_select_db($database, $this->link)) {
|
||||
/* This is being removed so I can use it, will need to come up with a more elegant workaround in the future...
|
||||
*
|
||||
if ($charset = $this->db_config['character_set'])
|
||||
{
|
||||
$this->set_charset($charset);
|
||||
}
|
||||
*/
|
||||
|
||||
// Clear password after successful connect
|
||||
$this->db_config['connection']['pass'] = NULL;
|
||||
// Clear password after successful connect
|
||||
$this->db_config['connection']['pass'] = null;
|
||||
|
||||
return $this->link;
|
||||
}
|
||||
return $this->link;
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public function query($sql)
|
||||
{
|
||||
// Only cache if it's turned on, and only cache if it's not a write statement
|
||||
if ($this->db_config['cache'] AND ! preg_match('#\b(?:INSERT|UPDATE|REPLACE|SET)\b#i', $sql))
|
||||
{
|
||||
$hash = $this->query_hash($sql);
|
||||
public function query($sql)
|
||||
{
|
||||
// Only cache if it's turned on, and only cache if it's not a write statement
|
||||
if ($this->db_config['cache'] and ! preg_match('#\b(?:INSERT|UPDATE|REPLACE|SET)\b#i', $sql)) {
|
||||
$hash = $this->query_hash($sql);
|
||||
|
||||
if ( ! isset($this->query_cache[$hash]))
|
||||
{
|
||||
// Set the cached object
|
||||
$this->query_cache[$hash] = new Mssql_Result(mssql_query($sql, $this->link), $this->link, $this->db_config['object'], $sql);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Rewind cached result
|
||||
$this->query_cache[$hash]->rewind();
|
||||
}
|
||||
if (! isset($this->query_cache[$hash])) {
|
||||
// Set the cached object
|
||||
$this->query_cache[$hash] = new Mssql_Result(mssql_query($sql, $this->link), $this->link, $this->db_config['object'], $sql);
|
||||
} else {
|
||||
// Rewind cached result
|
||||
$this->query_cache[$hash]->rewind();
|
||||
}
|
||||
|
||||
// Return the cached query
|
||||
return $this->query_cache[$hash];
|
||||
}
|
||||
// Return the cached query
|
||||
return $this->query_cache[$hash];
|
||||
}
|
||||
|
||||
return new Mssql_Result(mssql_query($sql, $this->link), $this->link, $this->db_config['object'], $sql);
|
||||
}
|
||||
return new Mssql_Result(mssql_query($sql, $this->link), $this->link, $this->db_config['object'], $sql);
|
||||
}
|
||||
|
||||
public function escape_table($table)
|
||||
{
|
||||
if (stripos($table, ' AS ') !== FALSE)
|
||||
{
|
||||
// Force 'AS' to uppercase
|
||||
$table = str_ireplace(' AS ', ' AS ', $table);
|
||||
public function escape_table($table)
|
||||
{
|
||||
if (stripos($table, ' AS ') !== false) {
|
||||
// Force 'AS' to uppercase
|
||||
$table = str_ireplace(' AS ', ' AS ', $table);
|
||||
|
||||
// Runs escape_table on both sides of an AS statement
|
||||
$table = array_map(array($this, __FUNCTION__), explode(' AS ', $table));
|
||||
// Runs escape_table on both sides of an AS statement
|
||||
$table = array_map(array($this, __FUNCTION__), explode(' AS ', $table));
|
||||
|
||||
// Re-create the AS statement
|
||||
return implode(' AS ', $table);
|
||||
}
|
||||
return '['.str_replace('.', '[.]', $table).']';
|
||||
}
|
||||
// Re-create the AS statement
|
||||
return implode(' AS ', $table);
|
||||
}
|
||||
return '[' . str_replace('.', '[.]', $table) . ']';
|
||||
}
|
||||
|
||||
public function escape_column($column)
|
||||
{
|
||||
if (!$this->db_config['escape'])
|
||||
return $column;
|
||||
public function escape_column($column)
|
||||
{
|
||||
if (!$this->db_config['escape']) {
|
||||
return $column;
|
||||
}
|
||||
|
||||
if ($column == '*')
|
||||
return $column;
|
||||
if ($column == '*') {
|
||||
return $column;
|
||||
}
|
||||
|
||||
// This matches any functions we support to SELECT.
|
||||
if ( preg_match('/(avg|count|sum|max|min)\(\s*(.*)\s*\)(\s*as\s*(.+)?)?/i', $column, $matches))
|
||||
{
|
||||
if ( count($matches) == 3)
|
||||
{
|
||||
return $matches[1].'('.$this->escape_column($matches[2]).')';
|
||||
}
|
||||
else if ( count($matches) == 5)
|
||||
{
|
||||
return $matches[1].'('.$this->escape_column($matches[2]).') AS '.$this->escape_column($matches[2]);
|
||||
}
|
||||
}
|
||||
// This matches any functions we support to SELECT.
|
||||
if (preg_match('/(avg|count|sum|max|min)\(\s*(.*)\s*\)(\s*as\s*(.+)?)?/i', $column, $matches)) {
|
||||
if (count($matches) == 3) {
|
||||
return $matches[1] . '(' . $this->escape_column($matches[2]) . ')';
|
||||
} elseif (count($matches) == 5) {
|
||||
return $matches[1] . '(' . $this->escape_column($matches[2]) . ') AS ' . $this->escape_column($matches[2]);
|
||||
}
|
||||
}
|
||||
|
||||
// This matches any modifiers we support to SELECT.
|
||||
if ( ! preg_match('/\b(?:rand|all|distinct(?:row)?|high_priority|sql_(?:small_result|b(?:ig_result|uffer_result)|no_cache|ca(?:che|lc_found_rows)))\s/i', $column))
|
||||
{
|
||||
if (stripos($column, ' AS ') !== FALSE)
|
||||
{
|
||||
// Force 'AS' to uppercase
|
||||
$column = str_ireplace(' AS ', ' AS ', $column);
|
||||
// This matches any modifiers we support to SELECT.
|
||||
if (! preg_match('/\b(?:rand|all|distinct(?:row)?|high_priority|sql_(?:small_result|b(?:ig_result|uffer_result)|no_cache|ca(?:che|lc_found_rows)))\s/i', $column)) {
|
||||
if (stripos($column, ' AS ') !== false) {
|
||||
// Force 'AS' to uppercase
|
||||
$column = str_ireplace(' AS ', ' AS ', $column);
|
||||
|
||||
// Runs escape_column on both sides of an AS statement
|
||||
$column = array_map(array($this, __FUNCTION__), explode(' AS ', $column));
|
||||
// Runs escape_column on both sides of an AS statement
|
||||
$column = array_map(array($this, __FUNCTION__), explode(' AS ', $column));
|
||||
|
||||
// Re-create the AS statement
|
||||
return implode(' AS ', $column);
|
||||
}
|
||||
// Re-create the AS statement
|
||||
return implode(' AS ', $column);
|
||||
}
|
||||
|
||||
return preg_replace('/[^.*]+/', '[$0]', $column);
|
||||
}
|
||||
return preg_replace('/[^.*]+/', '[$0]', $column);
|
||||
}
|
||||
|
||||
$parts = explode(' ', $column);
|
||||
$column = '';
|
||||
$parts = explode(' ', $column);
|
||||
$column = '';
|
||||
|
||||
for ($i = 0, $c = count($parts); $i < $c; $i++)
|
||||
{
|
||||
// The column is always last
|
||||
if ($i == ($c - 1))
|
||||
{
|
||||
$column .= preg_replace('/[^.*]+/', '[$0]', $parts[$i]);
|
||||
}
|
||||
else // otherwise, it's a modifier
|
||||
{
|
||||
$column .= $parts[$i].' ';
|
||||
}
|
||||
}
|
||||
return $column;
|
||||
}
|
||||
for ($i = 0, $c = count($parts); $i < $c; $i++) {
|
||||
// The column is always last
|
||||
if ($i == ($c - 1)) {
|
||||
$column .= preg_replace('/[^.*]+/', '[$0]', $parts[$i]);
|
||||
} else // otherwise, it's a modifier
|
||||
{
|
||||
$column .= $parts[$i] . ' ';
|
||||
}
|
||||
}
|
||||
return $column;
|
||||
}
|
||||
|
||||
/**
|
||||
* Limit in SQL Server 2000 only uses the keyword
|
||||
* 'TOP'; 2007 may have an offset keyword, but
|
||||
* I am unsure - for pagination style limit,offset
|
||||
* functionality, a fancy query needs to be built.
|
||||
*
|
||||
* @param unknown_type $limit
|
||||
* @return unknown
|
||||
*/
|
||||
public function limit($limit, $offset=null)
|
||||
{
|
||||
return 'TOP '.$limit;
|
||||
}
|
||||
/**
|
||||
* Limit in SQL Server 2000 only uses the keyword
|
||||
* 'TOP'; 2007 may have an offset keyword, but
|
||||
* I am unsure - for pagination style limit,offset
|
||||
* functionality, a fancy query needs to be built.
|
||||
*
|
||||
* @param unknown_type $limit
|
||||
* @return unknown
|
||||
*/
|
||||
public function limit($limit, $offset = null)
|
||||
{
|
||||
return 'TOP ' . $limit;
|
||||
}
|
||||
|
||||
public function compile_select($database)
|
||||
{
|
||||
$sql = ($database['distinct'] == TRUE) ? 'SELECT DISTINCT ' : 'SELECT ';
|
||||
$sql .= (count($database['select']) > 0) ? implode(', ', $database['select']) : '*';
|
||||
public function compile_select($database)
|
||||
{
|
||||
$sql = ($database['distinct'] == true) ? 'SELECT DISTINCT ' : 'SELECT ';
|
||||
$sql .= (count($database['select']) > 0) ? implode(', ', $database['select']) : '*';
|
||||
|
||||
if (count($database['from']) > 0)
|
||||
{
|
||||
// Escape the tables
|
||||
$froms = array();
|
||||
foreach ($database['from'] as $from)
|
||||
$froms[] = $this->escape_column($from);
|
||||
$sql .= "\nFROM ";
|
||||
$sql .= implode(', ', $froms);
|
||||
}
|
||||
if (count($database['from']) > 0) {
|
||||
// Escape the tables
|
||||
$froms = array();
|
||||
foreach ($database['from'] as $from) {
|
||||
$froms[] = $this->escape_column($from);
|
||||
}
|
||||
$sql .= "\nFROM ";
|
||||
$sql .= implode(', ', $froms);
|
||||
}
|
||||
|
||||
if (count($database['join']) > 0)
|
||||
{
|
||||
foreach($database['join'] AS $join)
|
||||
{
|
||||
$sql .= "\n".$join['type'].'JOIN '.implode(', ', $join['tables']).' ON '.$join['conditions'];
|
||||
}
|
||||
}
|
||||
if (count($database['join']) > 0) {
|
||||
foreach ($database['join'] as $join) {
|
||||
$sql .= "\n" . $join['type'] . 'JOIN ' . implode(', ', $join['tables']) . ' ON ' . $join['conditions'];
|
||||
}
|
||||
}
|
||||
|
||||
if (count($database['where']) > 0)
|
||||
{
|
||||
$sql .= "\nWHERE ";
|
||||
}
|
||||
if (count($database['where']) > 0) {
|
||||
$sql .= "\nWHERE ";
|
||||
}
|
||||
|
||||
$sql .= implode("\n", $database['where']);
|
||||
$sql .= implode("\n", $database['where']);
|
||||
|
||||
if (count($database['groupby']) > 0)
|
||||
{
|
||||
$sql .= "\nGROUP BY ";
|
||||
$sql .= implode(', ', $database['groupby']);
|
||||
}
|
||||
if (count($database['groupby']) > 0) {
|
||||
$sql .= "\nGROUP BY ";
|
||||
$sql .= implode(', ', $database['groupby']);
|
||||
}
|
||||
|
||||
if (count($database['having']) > 0)
|
||||
{
|
||||
$sql .= "\nHAVING ";
|
||||
$sql .= implode("\n", $database['having']);
|
||||
}
|
||||
if (count($database['having']) > 0) {
|
||||
$sql .= "\nHAVING ";
|
||||
$sql .= implode("\n", $database['having']);
|
||||
}
|
||||
|
||||
if (count($database['orderby']) > 0)
|
||||
{
|
||||
$sql .= "\nORDER BY ";
|
||||
$sql .= implode(', ', $database['orderby']);
|
||||
}
|
||||
if (count($database['orderby']) > 0) {
|
||||
$sql .= "\nORDER BY ";
|
||||
$sql .= implode(', ', $database['orderby']);
|
||||
}
|
||||
|
||||
if (is_numeric($database['limit']))
|
||||
{
|
||||
$sql .= "\n";
|
||||
$sql .= $this->limit($database['limit']);
|
||||
}
|
||||
if (is_numeric($database['limit'])) {
|
||||
$sql .= "\n";
|
||||
$sql .= $this->limit($database['limit']);
|
||||
}
|
||||
|
||||
return $sql;
|
||||
}
|
||||
return $sql;
|
||||
}
|
||||
|
||||
public function escape_str($str)
|
||||
{
|
||||
if (!$this->db_config['escape'])
|
||||
return $str;
|
||||
public function escape_str($str)
|
||||
{
|
||||
if (!$this->db_config['escape']) {
|
||||
return $str;
|
||||
}
|
||||
|
||||
is_resource($this->link) or $this->connect();
|
||||
//mssql_real_escape_string($str, $this->link); <-- this function doesn't exist
|
||||
is_resource($this->link) or $this->connect();
|
||||
//mssql_real_escape_string($str, $this->link); <-- this function doesn't exist
|
||||
|
||||
$characters = array('/\x00/', '/\x1a/', '/\n/', '/\r/', '/\\\/', '/\'/');
|
||||
$replace = array('\\\x00', '\\x1a', '\\n', '\\r', '\\\\', "''");
|
||||
return preg_replace($characters, $replace, $str);
|
||||
}
|
||||
$characters = array('/\x00/', '/\x1a/', '/\n/', '/\r/', '/\\\/', '/\'/');
|
||||
$replace = array('\\\x00', '\\x1a', '\\n', '\\r', '\\\\', "''");
|
||||
return preg_replace($characters, $replace, $str);
|
||||
}
|
||||
|
||||
public function list_tables()
|
||||
{
|
||||
$sql = 'SHOW TABLES FROM ['.$this->db_config['connection']['database'].']';
|
||||
$result = $this->query($sql)->result(FALSE, MSSQL_ASSOC);
|
||||
public function list_tables()
|
||||
{
|
||||
$sql = 'SHOW TABLES FROM [' . $this->db_config['connection']['database'] . ']';
|
||||
$result = $this->query($sql)->result(false, MSSQL_ASSOC);
|
||||
|
||||
$retval = array();
|
||||
foreach ($result as $row)
|
||||
{
|
||||
$retval[] = current($row);
|
||||
}
|
||||
$retval = array();
|
||||
foreach ($result as $row) {
|
||||
$retval[] = current($row);
|
||||
}
|
||||
|
||||
return $retval;
|
||||
}
|
||||
return $retval;
|
||||
}
|
||||
|
||||
public function show_error()
|
||||
{
|
||||
return mssql_get_last_message($this->link);
|
||||
}
|
||||
public function show_error()
|
||||
{
|
||||
return mssql_get_last_message($this->link);
|
||||
}
|
||||
|
||||
public function list_fields($table)
|
||||
{
|
||||
$result = array();
|
||||
public function list_fields($table)
|
||||
{
|
||||
$result = array();
|
||||
|
||||
foreach ($this->field_data($table) as $row)
|
||||
{
|
||||
// Make an associative array
|
||||
$result[$row->Field] = $this->sql_type($row->Type);
|
||||
}
|
||||
foreach ($this->field_data($table) as $row) {
|
||||
// Make an associative array
|
||||
$result[$row->Field] = $this->sql_type($row->Type);
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
return $result;
|
||||
}
|
||||
|
||||
public function field_data($table)
|
||||
{
|
||||
$query = $this->query("SELECT COLUMN_NAME AS Field, DATA_TYPE as Type FROM INFORMATION_SCHEMA.Columns WHERE TABLE_NAME = '".$this->escape_table($table)."'", $this->link);
|
||||
public function field_data($table)
|
||||
{
|
||||
$query = $this->query(
|
||||
"SELECT COLUMN_NAME AS Field, DATA_TYPE as Type FROM INFORMATION_SCHEMA.Columns WHERE TABLE_NAME = '" .
|
||||
$this->escape_table($table) . "'",
|
||||
$this->link
|
||||
);
|
||||
|
||||
return $query->result_array(TRUE);
|
||||
}
|
||||
return $query->result_array(true);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* MSSQL Result
|
||||
*/
|
||||
class Mssql_Result extends Database_Result {
|
||||
class Mssql_Result extends Database_Result
|
||||
{
|
||||
// Fetch function and return type
|
||||
protected $fetch_type = 'mssql_fetch_object';
|
||||
protected $return_type = MSSQL_ASSOC;
|
||||
|
||||
// Fetch function and return type
|
||||
protected $fetch_type = 'mssql_fetch_object';
|
||||
protected $return_type = MSSQL_ASSOC;
|
||||
/**
|
||||
* Sets up the result variables.
|
||||
*
|
||||
* @param resource query result
|
||||
* @param resource database link
|
||||
* @param boolean return objects or arrays
|
||||
* @param string SQL query that was run
|
||||
*/
|
||||
public function __construct($result, $link, $object = true, $sql = '')
|
||||
{
|
||||
$this->result = $result;
|
||||
|
||||
/**
|
||||
* Sets up the result variables.
|
||||
*
|
||||
* @param resource query result
|
||||
* @param resource database link
|
||||
* @param boolean return objects or arrays
|
||||
* @param string SQL query that was run
|
||||
*/
|
||||
public function __construct($result, $link, $object = TRUE, $sql)
|
||||
{
|
||||
$this->result = $result;
|
||||
// If the query is a resource, it was a SELECT, SHOW, DESCRIBE, EXPLAIN query
|
||||
if (is_resource($result)) {
|
||||
$this->current_row = 0;
|
||||
$this->total_rows = mssql_num_rows($this->result);
|
||||
$this->fetch_type = ($object === true) ? 'mssql_fetch_object' : 'mssql_fetch_array';
|
||||
} elseif (is_bool($result)) {
|
||||
if ($result == false) {
|
||||
// SQL error
|
||||
throw new Kohana_Database_Exception('database.error', mssql_get_last_message($link) . ' - ' . $sql);
|
||||
} else {
|
||||
// Its an DELETE, INSERT, REPLACE, or UPDATE querys
|
||||
$last_id = mssql_query('SELECT @@IDENTITY AS last_id', $link);
|
||||
$result = mssql_fetch_assoc($last_id);
|
||||
$this->insert_id = $result['last_id'];
|
||||
$this->total_rows = mssql_rows_affected($link);
|
||||
}
|
||||
}
|
||||
|
||||
// If the query is a resource, it was a SELECT, SHOW, DESCRIBE, EXPLAIN query
|
||||
if (is_resource($result))
|
||||
{
|
||||
$this->current_row = 0;
|
||||
$this->total_rows = mssql_num_rows($this->result);
|
||||
$this->fetch_type = ($object === TRUE) ? 'mssql_fetch_object' : 'mssql_fetch_array';
|
||||
}
|
||||
elseif (is_bool($result))
|
||||
{
|
||||
if ($result == FALSE)
|
||||
{
|
||||
// SQL error
|
||||
throw new Kohana_Database_Exception('database.error', mssql_get_last_message($link).' - '.$sql);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Its an DELETE, INSERT, REPLACE, or UPDATE querys
|
||||
$last_id = mssql_query('SELECT @@IDENTITY AS last_id', $link);
|
||||
$result = mssql_fetch_assoc($last_id);
|
||||
$this->insert_id = $result['last_id'];
|
||||
$this->total_rows = mssql_rows_affected($link);
|
||||
}
|
||||
}
|
||||
// Set result type
|
||||
$this->result($object);
|
||||
|
||||
// Set result type
|
||||
$this->result($object);
|
||||
// Store the SQL
|
||||
$this->sql = $sql;
|
||||
}
|
||||
|
||||
// Store the SQL
|
||||
$this->sql = $sql;
|
||||
}
|
||||
/**
|
||||
* Destruct, the cleanup crew!
|
||||
*/
|
||||
public function __destruct()
|
||||
{
|
||||
if (is_resource($this->result)) {
|
||||
mssql_free_result($this->result);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Destruct, the cleanup crew!
|
||||
*/
|
||||
public function __destruct()
|
||||
{
|
||||
if (is_resource($this->result))
|
||||
{
|
||||
mssql_free_result($this->result);
|
||||
}
|
||||
}
|
||||
public function result($object = true, $type = MSSQL_ASSOC)
|
||||
{
|
||||
$this->fetch_type = ((bool) $object) ? 'mssql_fetch_object' : 'mssql_fetch_array';
|
||||
|
||||
public function result($object = TRUE, $type = MSSQL_ASSOC)
|
||||
{
|
||||
$this->fetch_type = ((bool) $object) ? 'mssql_fetch_object' : 'mssql_fetch_array';
|
||||
// This check has to be outside the previous statement, because we do not
|
||||
// know the state of fetch_type when $object = NULL
|
||||
// NOTE - The class set by $type must be defined before fetching the result,
|
||||
// autoloading is disabled to save a lot of stupid overhead.
|
||||
if ($this->fetch_type == 'mssql_fetch_object') {
|
||||
$this->return_type = (is_string($type) and Kohana::auto_load($type)) ? $type : 'stdClass';
|
||||
} else {
|
||||
$this->return_type = $type;
|
||||
}
|
||||
|
||||
// This check has to be outside the previous statement, because we do not
|
||||
// know the state of fetch_type when $object = NULL
|
||||
// NOTE - The class set by $type must be defined before fetching the result,
|
||||
// autoloading is disabled to save a lot of stupid overhead.
|
||||
if ($this->fetch_type == 'mssql_fetch_object')
|
||||
{
|
||||
$this->return_type = (is_string($type) AND Kohana::auto_load($type)) ? $type : 'stdClass';
|
||||
}
|
||||
else
|
||||
{
|
||||
$this->return_type = $type;
|
||||
}
|
||||
return $this;
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
public function as_array($object = null, $type = MSSQL_ASSOC)
|
||||
{
|
||||
return $this->result_array($object, $type);
|
||||
}
|
||||
|
||||
public function as_array($object = NULL, $type = MSSQL_ASSOC)
|
||||
{
|
||||
return $this->result_array($object, $type);
|
||||
}
|
||||
public function result_array($object = null, $type = MSSQL_ASSOC)
|
||||
{
|
||||
$rows = array();
|
||||
|
||||
public function result_array($object = NULL, $type = MSSQL_ASSOC)
|
||||
{
|
||||
$rows = array();
|
||||
if (is_string($object)) {
|
||||
$fetch = $object;
|
||||
} elseif (is_bool($object)) {
|
||||
if ($object === true) {
|
||||
$fetch = 'mssql_fetch_object';
|
||||
|
||||
if (is_string($object))
|
||||
{
|
||||
$fetch = $object;
|
||||
}
|
||||
elseif (is_bool($object))
|
||||
{
|
||||
if ($object === TRUE)
|
||||
{
|
||||
$fetch = 'mssql_fetch_object';
|
||||
// NOTE - The class set by $type must be defined before fetching the result,
|
||||
// autoloading is disabled to save a lot of stupid overhead.
|
||||
$type = (is_string($type) and Kohana::auto_load($type)) ? $type : 'stdClass';
|
||||
} else {
|
||||
$fetch = 'mssql_fetch_array';
|
||||
}
|
||||
} else {
|
||||
// Use the default config values
|
||||
$fetch = $this->fetch_type;
|
||||
|
||||
// NOTE - The class set by $type must be defined before fetching the result,
|
||||
// autoloading is disabled to save a lot of stupid overhead.
|
||||
$type = (is_string($type) AND Kohana::auto_load($type)) ? $type : 'stdClass';
|
||||
}
|
||||
else
|
||||
{
|
||||
$fetch = 'mssql_fetch_array';
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Use the default config values
|
||||
$fetch = $this->fetch_type;
|
||||
if ($fetch == 'mssql_fetch_object') {
|
||||
$type = (is_string($type) and Kohana::auto_load($type)) ? $type : 'stdClass';
|
||||
}
|
||||
}
|
||||
|
||||
if ($fetch == 'mssql_fetch_object')
|
||||
{
|
||||
$type = (is_string($type) AND Kohana::auto_load($type)) ? $type : 'stdClass';
|
||||
}
|
||||
}
|
||||
if (mssql_num_rows($this->result)) {
|
||||
// Reset the pointer location to make sure things work properly
|
||||
mssql_data_seek($this->result, 0);
|
||||
|
||||
if (mssql_num_rows($this->result))
|
||||
{
|
||||
// Reset the pointer location to make sure things work properly
|
||||
mssql_data_seek($this->result, 0);
|
||||
while ($row = $fetch($this->result, $type)) {
|
||||
$rows[] = $row;
|
||||
}
|
||||
}
|
||||
|
||||
while ($row = $fetch($this->result, $type))
|
||||
{
|
||||
$rows[] = $row;
|
||||
}
|
||||
}
|
||||
return isset($rows) ? $rows : array();
|
||||
}
|
||||
|
||||
return isset($rows) ? $rows : array();
|
||||
}
|
||||
public function list_fields()
|
||||
{
|
||||
$field_names = array();
|
||||
while ($field = mssql_fetch_field($this->result)) {
|
||||
$field_names[] = $field->name;
|
||||
}
|
||||
|
||||
public function list_fields()
|
||||
{
|
||||
$field_names = array();
|
||||
while ($field = mssql_fetch_field($this->result))
|
||||
{
|
||||
$field_names[] = $field->name;
|
||||
}
|
||||
return $field_names;
|
||||
}
|
||||
|
||||
return $field_names;
|
||||
}
|
||||
public function seek($offset)
|
||||
{
|
||||
if (! $this->offsetExists($offset)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
public function seek($offset)
|
||||
{
|
||||
if ( ! $this->offsetExists($offset))
|
||||
return FALSE;
|
||||
|
||||
return mssql_data_seek($this->result, $offset);
|
||||
}
|
||||
|
||||
} // End mssql_Result Class
|
||||
return mssql_data_seek($this->result, $offset);
|
||||
}
|
||||
}
|
||||
// End mssql_Result Class
|
||||
|
||||
@@ -1,4 +1,13 @@
|
||||
<?php defined('SYSPATH') OR die('No direct access allowed.');
|
||||
<?php
|
||||
|
||||
// phpcs:disable PSR1.Classes.ClassDeclaration.MissingNamespace
|
||||
// phpcs:disable PSR1.Classes.ClassDeclaration.MultipleClasses
|
||||
// phpcs:disable PSR1.Files.SideEffects
|
||||
defined('SYSPATH') or die('No direct access allowed.');
|
||||
// phpcs:enable PSR1.Files.SideEffects
|
||||
// phpcs:disable Squiz.Classes.ValidClassName.NotCamelCaps
|
||||
|
||||
|
||||
/**
|
||||
* MySQL Database Driver
|
||||
*
|
||||
@@ -9,488 +18,438 @@
|
||||
* @copyright (c) 2007-2008 Kohana Team
|
||||
* @license http://kohanaphp.com/license.html
|
||||
*/
|
||||
class Database_Mysql_Driver extends Database_Driver {
|
||||
class Database_Mysql_Driver extends Database_Driver
|
||||
{
|
||||
/**
|
||||
* Database connection link
|
||||
*/
|
||||
protected $link;
|
||||
|
||||
/**
|
||||
* Database connection link
|
||||
*/
|
||||
protected $link;
|
||||
/**
|
||||
* Database configuration
|
||||
*/
|
||||
protected $db_config;
|
||||
|
||||
/**
|
||||
* Database configuration
|
||||
*/
|
||||
protected $db_config;
|
||||
/**
|
||||
* Sets the config for the class.
|
||||
*
|
||||
* @param array database configuration
|
||||
*/
|
||||
public function __construct($config)
|
||||
{
|
||||
$this->db_config = $config;
|
||||
|
||||
/**
|
||||
* Sets the config for the class.
|
||||
*
|
||||
* @param array database configuration
|
||||
*/
|
||||
public function __construct($config)
|
||||
{
|
||||
$this->db_config = $config;
|
||||
Kohana::log('debug', 'MySQL Database Driver Initialized');
|
||||
}
|
||||
|
||||
Kohana::log('debug', 'MySQL Database Driver Initialized');
|
||||
}
|
||||
/**
|
||||
* Closes the database connection.
|
||||
*/
|
||||
public function __destruct()
|
||||
{
|
||||
is_resource($this->link) and mysql_close($this->link);
|
||||
}
|
||||
|
||||
/**
|
||||
* Closes the database connection.
|
||||
*/
|
||||
public function __destruct()
|
||||
{
|
||||
is_resource($this->link) and mysql_close($this->link);
|
||||
}
|
||||
public function connect()
|
||||
{
|
||||
// Check if link already exists
|
||||
if (is_resource($this->link)) {
|
||||
return $this->link;
|
||||
}
|
||||
|
||||
public function connect()
|
||||
{
|
||||
// Check if link already exists
|
||||
if (is_resource($this->link))
|
||||
return $this->link;
|
||||
// Import the connect variables
|
||||
extract($this->db_config['connection']);
|
||||
|
||||
// Import the connect variables
|
||||
extract($this->db_config['connection']);
|
||||
// Persistent connections enabled?
|
||||
$connect = ($this->db_config['persistent'] == true) ? 'mysql_pconnect' : 'mysql_connect';
|
||||
|
||||
// Persistent connections enabled?
|
||||
$connect = ($this->db_config['persistent'] == TRUE) ? 'mysql_pconnect' : 'mysql_connect';
|
||||
// Build the connection info
|
||||
$host = isset($host) ? $host : $socket;
|
||||
$port = isset($port) ? ':' . $port : '';
|
||||
|
||||
// Build the connection info
|
||||
$host = isset($host) ? $host : $socket;
|
||||
$port = isset($port) ? ':'.$port : '';
|
||||
// Make the connection and select the database
|
||||
if (($this->link = $connect($host . $port, $user, $pass, true)) and mysql_select_db($database, $this->link)) {
|
||||
if ($charset = $this->db_config['character_set']) {
|
||||
$this->set_charset($charset);
|
||||
}
|
||||
|
||||
// Make the connection and select the database
|
||||
if (($this->link = $connect($host.$port, $user, $pass, TRUE)) AND mysql_select_db($database, $this->link))
|
||||
{
|
||||
if ($charset = $this->db_config['character_set'])
|
||||
{
|
||||
$this->set_charset($charset);
|
||||
}
|
||||
// Clear password after successful connect
|
||||
$this->db_config['connection']['pass'] = null;
|
||||
|
||||
// Clear password after successful connect
|
||||
$this->db_config['connection']['pass'] = NULL;
|
||||
return $this->link;
|
||||
}
|
||||
|
||||
return $this->link;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
public function query($sql)
|
||||
{
|
||||
// Only cache if it's turned on, and only cache if it's not a write statement
|
||||
if ($this->db_config['cache'] and ! preg_match('#\b(?:INSERT|UPDATE|REPLACE|SET|DELETE|TRUNCATE)\b#i', $sql)) {
|
||||
$hash = $this->query_hash($sql);
|
||||
|
||||
public function query($sql)
|
||||
{
|
||||
// Only cache if it's turned on, and only cache if it's not a write statement
|
||||
if ($this->db_config['cache'] AND ! preg_match('#\b(?:INSERT|UPDATE|REPLACE|SET|DELETE|TRUNCATE)\b#i', $sql))
|
||||
{
|
||||
$hash = $this->query_hash($sql);
|
||||
if (! isset($this->query_cache[$hash])) {
|
||||
// Set the cached object
|
||||
$this->query_cache[$hash] = new Mysql_Result(mysql_query($sql, $this->link), $this->link, $this->db_config['object'], $sql);
|
||||
} else {
|
||||
// Rewind cached result
|
||||
$this->query_cache[$hash]->rewind();
|
||||
}
|
||||
|
||||
if ( ! isset($this->query_cache[$hash]))
|
||||
{
|
||||
// Set the cached object
|
||||
$this->query_cache[$hash] = new Mysql_Result(mysql_query($sql, $this->link), $this->link, $this->db_config['object'], $sql);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Rewind cached result
|
||||
$this->query_cache[$hash]->rewind();
|
||||
}
|
||||
// Return the cached query
|
||||
return $this->query_cache[$hash];
|
||||
}
|
||||
|
||||
// Return the cached query
|
||||
return $this->query_cache[$hash];
|
||||
}
|
||||
return new Mysql_Result(mysql_query($sql, $this->link), $this->link, $this->db_config['object'], $sql);
|
||||
}
|
||||
|
||||
return new Mysql_Result(mysql_query($sql, $this->link), $this->link, $this->db_config['object'], $sql);
|
||||
}
|
||||
public function set_charset($charset)
|
||||
{
|
||||
$this->query('SET NAMES ' . $this->escape_str($charset));
|
||||
}
|
||||
|
||||
public function set_charset($charset)
|
||||
{
|
||||
$this->query('SET NAMES '.$this->escape_str($charset));
|
||||
}
|
||||
public function escape_table($table)
|
||||
{
|
||||
if (!$this->db_config['escape']) {
|
||||
return $table;
|
||||
}
|
||||
|
||||
public function escape_table($table)
|
||||
{
|
||||
if (!$this->db_config['escape'])
|
||||
return $table;
|
||||
if (stripos($table, ' AS ') !== false) {
|
||||
// Force 'AS' to uppercase
|
||||
$table = str_ireplace(' AS ', ' AS ', $table);
|
||||
|
||||
if (stripos($table, ' AS ') !== FALSE)
|
||||
{
|
||||
// Force 'AS' to uppercase
|
||||
$table = str_ireplace(' AS ', ' AS ', $table);
|
||||
// Runs escape_table on both sides of an AS statement
|
||||
$table = array_map(array($this, __FUNCTION__), explode(' AS ', $table));
|
||||
|
||||
// Runs escape_table on both sides of an AS statement
|
||||
$table = array_map(array($this, __FUNCTION__), explode(' AS ', $table));
|
||||
// Re-create the AS statement
|
||||
return implode(' AS ', $table);
|
||||
}
|
||||
return '`' . str_replace('.', '`.`', $table) . '`';
|
||||
}
|
||||
|
||||
// Re-create the AS statement
|
||||
return implode(' AS ', $table);
|
||||
}
|
||||
return '`'.str_replace('.', '`.`', $table).'`';
|
||||
}
|
||||
public function escape_column($column)
|
||||
{
|
||||
if (!$this->db_config['escape']) {
|
||||
return $column;
|
||||
}
|
||||
|
||||
public function escape_column($column)
|
||||
{
|
||||
if (!$this->db_config['escape'])
|
||||
return $column;
|
||||
if ($column == '*') {
|
||||
return $column;
|
||||
}
|
||||
|
||||
if ($column == '*')
|
||||
return $column;
|
||||
// This matches any functions we support to SELECT.
|
||||
if (preg_match('/(avg|count|sum|max|min)\(\s*(.*)\s*\)(\s*as\s*(.+)?)?/i', $column, $matches)) {
|
||||
if (count($matches) == 3) {
|
||||
return $matches[1] . '(' . $this->escape_column($matches[2]) . ')';
|
||||
} elseif (count($matches) == 5) {
|
||||
return $matches[1] . '(' . $this->escape_column($matches[2]) . ') AS ' . $this->escape_column($matches[2]);
|
||||
}
|
||||
}
|
||||
|
||||
// This matches any functions we support to SELECT.
|
||||
if ( preg_match('/(avg|count|sum|max|min)\(\s*(.*)\s*\)(\s*as\s*(.+)?)?/i', $column, $matches))
|
||||
{
|
||||
if ( count($matches) == 3)
|
||||
{
|
||||
return $matches[1].'('.$this->escape_column($matches[2]).')';
|
||||
}
|
||||
else if ( count($matches) == 5)
|
||||
{
|
||||
return $matches[1].'('.$this->escape_column($matches[2]).') AS '.$this->escape_column($matches[2]);
|
||||
}
|
||||
}
|
||||
|
||||
// This matches any modifiers we support to SELECT.
|
||||
if ( ! preg_match('/\b(?:rand|all|distinct(?:row)?|high_priority|sql_(?:small_result|b(?:ig_result|uffer_result)|no_cache|ca(?:che|lc_found_rows)))\s/i', $column))
|
||||
{
|
||||
if (stripos($column, ' AS ') !== FALSE)
|
||||
{
|
||||
// Force 'AS' to uppercase
|
||||
$column = str_ireplace(' AS ', ' AS ', $column);
|
||||
// This matches any modifiers we support to SELECT.
|
||||
if (! preg_match('/\b(?:rand|all|distinct(?:row)?|high_priority|sql_(?:small_result|b(?:ig_result|uffer_result)|no_cache|ca(?:che|lc_found_rows)))\s/i', $column)) {
|
||||
if (stripos($column, ' AS ') !== false) {
|
||||
// Force 'AS' to uppercase
|
||||
$column = str_ireplace(' AS ', ' AS ', $column);
|
||||
|
||||
// Runs escape_column on both sides of an AS statement
|
||||
$column = array_map(array($this, __FUNCTION__), explode(' AS ', $column));
|
||||
// Runs escape_column on both sides of an AS statement
|
||||
$column = array_map(array($this, __FUNCTION__), explode(' AS ', $column));
|
||||
|
||||
// Re-create the AS statement
|
||||
return implode(' AS ', $column);
|
||||
}
|
||||
// Re-create the AS statement
|
||||
return implode(' AS ', $column);
|
||||
}
|
||||
|
||||
return preg_replace('/[^.*]+/', '`$0`', $column);
|
||||
}
|
||||
return preg_replace('/[^.*]+/', '`$0`', $column);
|
||||
}
|
||||
|
||||
$parts = explode(' ', $column);
|
||||
$column = '';
|
||||
$parts = explode(' ', $column);
|
||||
$column = '';
|
||||
|
||||
for ($i = 0, $c = count($parts); $i < $c; $i++)
|
||||
{
|
||||
// The column is always last
|
||||
if ($i == ($c - 1))
|
||||
{
|
||||
$column .= preg_replace('/[^.*]+/', '`$0`', $parts[$i]);
|
||||
}
|
||||
else // otherwise, it's a modifier
|
||||
{
|
||||
$column .= $parts[$i].' ';
|
||||
}
|
||||
}
|
||||
return $column;
|
||||
}
|
||||
for ($i = 0, $c = count($parts); $i < $c; $i++) {
|
||||
// The column is always last
|
||||
if ($i == ($c - 1)) {
|
||||
$column .= preg_replace('/[^.*]+/', '`$0`', $parts[$i]);
|
||||
} else // otherwise, it's a modifier
|
||||
{
|
||||
$column .= $parts[$i] . ' ';
|
||||
}
|
||||
}
|
||||
return $column;
|
||||
}
|
||||
|
||||
public function regex($field, $match, $type, $num_regexs)
|
||||
{
|
||||
$prefix = ($num_regexs == 0) ? '' : $type;
|
||||
public function regex($field, $match, $type, $num_regexs)
|
||||
{
|
||||
$prefix = ($num_regexs == 0) ? '' : $type;
|
||||
|
||||
return $prefix.' '.$this->escape_column($field).' REGEXP \''.$this->escape_str($match).'\'';
|
||||
}
|
||||
return $prefix . ' ' . $this->escape_column($field) . ' REGEXP \'' . $this->escape_str($match) . '\'';
|
||||
}
|
||||
|
||||
public function notregex($field, $match, $type, $num_regexs)
|
||||
{
|
||||
$prefix = $num_regexs == 0 ? '' : $type;
|
||||
public function notregex($field, $match, $type, $num_regexs)
|
||||
{
|
||||
$prefix = $num_regexs == 0 ? '' : $type;
|
||||
|
||||
return $prefix.' '.$this->escape_column($field).' NOT REGEXP \''.$this->escape_str($match) . '\'';
|
||||
}
|
||||
return $prefix . ' ' . $this->escape_column($field) . ' NOT REGEXP \'' . $this->escape_str($match) . '\'';
|
||||
}
|
||||
|
||||
public function merge($table, $keys, $values)
|
||||
{
|
||||
// Escape the column names
|
||||
foreach ($keys as $key => $value)
|
||||
{
|
||||
$keys[$key] = $this->escape_column($value);
|
||||
}
|
||||
return 'REPLACE INTO '.$this->escape_table($table).' ('.implode(', ', $keys).') VALUES ('.implode(', ', $values).')';
|
||||
}
|
||||
public function merge($table, $keys, $values)
|
||||
{
|
||||
// Escape the column names
|
||||
foreach ($keys as $key => $value) {
|
||||
$keys[$key] = $this->escape_column($value);
|
||||
}
|
||||
return 'REPLACE INTO ' . $this->escape_table($table) . ' (' . implode(', ', $keys) . ') VALUES (' . implode(', ', $values) . ')';
|
||||
}
|
||||
|
||||
public function limit($limit, $offset = 0)
|
||||
{
|
||||
return 'LIMIT '.$offset.', '.$limit;
|
||||
}
|
||||
public function limit($limit, $offset = 0)
|
||||
{
|
||||
return 'LIMIT ' . $offset . ', ' . $limit;
|
||||
}
|
||||
|
||||
public function compile_select($database)
|
||||
{
|
||||
$sql = ($database['distinct'] == TRUE) ? 'SELECT DISTINCT ' : 'SELECT ';
|
||||
$sql .= (count($database['select']) > 0) ? implode(', ', $database['select']) : '*';
|
||||
public function compile_select($database)
|
||||
{
|
||||
$sql = ($database['distinct'] == true) ? 'SELECT DISTINCT ' : 'SELECT ';
|
||||
$sql .= (count($database['select']) > 0) ? implode(', ', $database['select']) : '*';
|
||||
|
||||
if (count($database['from']) > 0)
|
||||
{
|
||||
// Escape the tables
|
||||
$froms = array();
|
||||
foreach ($database['from'] as $from)
|
||||
{
|
||||
$froms[] = $this->escape_column($from);
|
||||
}
|
||||
$sql .= "\nFROM (";
|
||||
$sql .= implode(', ', $froms).")";
|
||||
}
|
||||
if (count($database['from']) > 0) {
|
||||
// Escape the tables
|
||||
$froms = array();
|
||||
foreach ($database['from'] as $from) {
|
||||
$froms[] = $this->escape_column($from);
|
||||
}
|
||||
$sql .= "\nFROM (";
|
||||
$sql .= implode(', ', $froms) . ")";
|
||||
}
|
||||
|
||||
if (count($database['join']) > 0)
|
||||
{
|
||||
foreach($database['join'] AS $join)
|
||||
{
|
||||
$sql .= "\n".$join['type'].'JOIN '.implode(', ', $join['tables']).' ON '.$join['conditions'];
|
||||
}
|
||||
}
|
||||
if (count($database['join']) > 0) {
|
||||
foreach ($database['join'] as $join) {
|
||||
$sql .= "\n" . $join['type'] . 'JOIN ' . implode(', ', $join['tables']) . ' ON ' . $join['conditions'];
|
||||
}
|
||||
}
|
||||
|
||||
if (count($database['where']) > 0)
|
||||
{
|
||||
$sql .= "\nWHERE ";
|
||||
}
|
||||
if (count($database['where']) > 0) {
|
||||
$sql .= "\nWHERE ";
|
||||
}
|
||||
|
||||
$sql .= implode("\n", $database['where']);
|
||||
$sql .= implode("\n", $database['where']);
|
||||
|
||||
if (count($database['groupby']) > 0)
|
||||
{
|
||||
$sql .= "\nGROUP BY ";
|
||||
$sql .= implode(', ', $database['groupby']);
|
||||
}
|
||||
if (count($database['groupby']) > 0) {
|
||||
$sql .= "\nGROUP BY ";
|
||||
$sql .= implode(', ', $database['groupby']);
|
||||
}
|
||||
|
||||
if (count($database['having']) > 0)
|
||||
{
|
||||
$sql .= "\nHAVING ";
|
||||
$sql .= implode("\n", $database['having']);
|
||||
}
|
||||
if (count($database['having']) > 0) {
|
||||
$sql .= "\nHAVING ";
|
||||
$sql .= implode("\n", $database['having']);
|
||||
}
|
||||
|
||||
if (count($database['orderby']) > 0)
|
||||
{
|
||||
$sql .= "\nORDER BY ";
|
||||
$sql .= implode(', ', $database['orderby']);
|
||||
}
|
||||
if (count($database['orderby']) > 0) {
|
||||
$sql .= "\nORDER BY ";
|
||||
$sql .= implode(', ', $database['orderby']);
|
||||
}
|
||||
|
||||
if (is_numeric($database['limit']))
|
||||
{
|
||||
$sql .= "\n";
|
||||
$sql .= $this->limit($database['limit'], $database['offset']);
|
||||
}
|
||||
if (is_numeric($database['limit'])) {
|
||||
$sql .= "\n";
|
||||
$sql .= $this->limit($database['limit'], $database['offset']);
|
||||
}
|
||||
|
||||
return $sql;
|
||||
}
|
||||
return $sql;
|
||||
}
|
||||
|
||||
public function escape_str($str)
|
||||
{
|
||||
if (!$this->db_config['escape'])
|
||||
return $str;
|
||||
public function escape_str($str)
|
||||
{
|
||||
if (!$this->db_config['escape']) {
|
||||
return $str;
|
||||
}
|
||||
|
||||
is_resource($this->link) or $this->connect();
|
||||
is_resource($this->link) or $this->connect();
|
||||
|
||||
return mysql_real_escape_string($str, $this->link);
|
||||
}
|
||||
return mysql_real_escape_string($str, $this->link);
|
||||
}
|
||||
|
||||
public function list_tables()
|
||||
{
|
||||
$tables = array();
|
||||
public function list_tables()
|
||||
{
|
||||
$tables = array();
|
||||
|
||||
if ($query = $this->query('SHOW TABLES FROM '.$this->escape_table($this->db_config['connection']['database'])))
|
||||
{
|
||||
foreach ($query->result(FALSE) as $row)
|
||||
{
|
||||
$tables[] = current($row);
|
||||
}
|
||||
}
|
||||
if ($query = $this->query('SHOW TABLES FROM ' . $this->escape_table($this->db_config['connection']['database']))) {
|
||||
foreach ($query->result(false) as $row) {
|
||||
$tables[] = current($row);
|
||||
}
|
||||
}
|
||||
|
||||
return $tables;
|
||||
}
|
||||
return $tables;
|
||||
}
|
||||
|
||||
public function show_error()
|
||||
{
|
||||
return mysql_error($this->link);
|
||||
}
|
||||
public function show_error()
|
||||
{
|
||||
return mysql_error($this->link);
|
||||
}
|
||||
|
||||
public function list_fields($table)
|
||||
{
|
||||
$result = NULL;
|
||||
public function list_fields($table)
|
||||
{
|
||||
$result = null;
|
||||
|
||||
foreach ($this->field_data($table) as $row)
|
||||
{
|
||||
// Make an associative array
|
||||
$result[$row->Field] = $this->sql_type($row->Type);
|
||||
foreach ($this->field_data($table) as $row) {
|
||||
// Make an associative array
|
||||
$result[$row->Field] = $this->sql_type($row->Type);
|
||||
|
||||
if ($row->Key === 'PRI' AND $row->Extra === 'auto_increment')
|
||||
{
|
||||
// For sequenced (AUTO_INCREMENT) tables
|
||||
$result[$row->Field]['sequenced'] = TRUE;
|
||||
}
|
||||
if ($row->Key === 'PRI' and $row->Extra === 'auto_increment') {
|
||||
// For sequenced (AUTO_INCREMENT) tables
|
||||
$result[$row->Field]['sequenced'] = true;
|
||||
}
|
||||
|
||||
if ($row->Null === 'YES')
|
||||
{
|
||||
// Set NULL status
|
||||
$result[$row->Field]['null'] = TRUE;
|
||||
}
|
||||
}
|
||||
if ($row->Null === 'YES') {
|
||||
// Set NULL status
|
||||
$result[$row->Field]['null'] = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (!isset($result))
|
||||
throw new Kohana_Database_Exception('database.table_not_found', $table);
|
||||
if (!isset($result)) {
|
||||
throw new Kohana_Database_Exception('database.table_not_found', $table);
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
return $result;
|
||||
}
|
||||
|
||||
public function field_data($table)
|
||||
{
|
||||
$result = $this->query('SHOW COLUMNS FROM '.$this->escape_table($table));
|
||||
public function field_data($table)
|
||||
{
|
||||
$result = $this->query('SHOW COLUMNS FROM ' . $this->escape_table($table));
|
||||
|
||||
return $result->result_array(TRUE);
|
||||
}
|
||||
|
||||
} // End Database_Mysql_Driver Class
|
||||
return $result->result_array(true);
|
||||
}
|
||||
}
|
||||
// End Database_Mysql_Driver Class
|
||||
|
||||
/**
|
||||
* MySQL Result
|
||||
*/
|
||||
class Mysql_Result extends Database_Result {
|
||||
class Mysql_Result extends Database_Result
|
||||
{
|
||||
// Fetch function and return type
|
||||
protected $fetch_type = 'mysql_fetch_object';
|
||||
protected $return_type = MYSQL_ASSOC;
|
||||
|
||||
// Fetch function and return type
|
||||
protected $fetch_type = 'mysql_fetch_object';
|
||||
protected $return_type = MYSQL_ASSOC;
|
||||
/**
|
||||
* Sets up the result variables.
|
||||
*
|
||||
* @param resource query result
|
||||
* @param resource database link
|
||||
* @param boolean return objects or arrays
|
||||
* @param string SQL query that was run
|
||||
*/
|
||||
public function __construct($result, $link, $object = true, $sql = '')
|
||||
{
|
||||
$this->result = $result;
|
||||
|
||||
/**
|
||||
* Sets up the result variables.
|
||||
*
|
||||
* @param resource query result
|
||||
* @param resource database link
|
||||
* @param boolean return objects or arrays
|
||||
* @param string SQL query that was run
|
||||
*/
|
||||
public function __construct($result, $link, $object = TRUE, $sql)
|
||||
{
|
||||
$this->result = $result;
|
||||
// If the query is a resource, it was a SELECT, SHOW, DESCRIBE, EXPLAIN query
|
||||
if (is_resource($result)) {
|
||||
$this->current_row = 0;
|
||||
$this->total_rows = mysql_num_rows($this->result);
|
||||
$this->fetch_type = ($object === true) ? 'mysql_fetch_object' : 'mysql_fetch_array';
|
||||
} elseif (is_bool($result)) {
|
||||
if ($result == false) {
|
||||
// SQL error
|
||||
throw new Kohana_Database_Exception('database.error', mysql_error($link) . ' - ' . $sql);
|
||||
} else {
|
||||
// Its an DELETE, INSERT, REPLACE, or UPDATE query
|
||||
$this->insert_id = mysql_insert_id($link);
|
||||
$this->total_rows = mysql_affected_rows($link);
|
||||
}
|
||||
}
|
||||
|
||||
// If the query is a resource, it was a SELECT, SHOW, DESCRIBE, EXPLAIN query
|
||||
if (is_resource($result))
|
||||
{
|
||||
$this->current_row = 0;
|
||||
$this->total_rows = mysql_num_rows($this->result);
|
||||
$this->fetch_type = ($object === TRUE) ? 'mysql_fetch_object' : 'mysql_fetch_array';
|
||||
}
|
||||
elseif (is_bool($result))
|
||||
{
|
||||
if ($result == FALSE)
|
||||
{
|
||||
// SQL error
|
||||
throw new Kohana_Database_Exception('database.error', mysql_error($link).' - '.$sql);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Its an DELETE, INSERT, REPLACE, or UPDATE query
|
||||
$this->insert_id = mysql_insert_id($link);
|
||||
$this->total_rows = mysql_affected_rows($link);
|
||||
}
|
||||
}
|
||||
// Set result type
|
||||
$this->result($object);
|
||||
|
||||
// Set result type
|
||||
$this->result($object);
|
||||
// Store the SQL
|
||||
$this->sql = $sql;
|
||||
}
|
||||
|
||||
// Store the SQL
|
||||
$this->sql = $sql;
|
||||
}
|
||||
/**
|
||||
* Destruct, the cleanup crew!
|
||||
*/
|
||||
public function __destruct()
|
||||
{
|
||||
if (is_resource($this->result)) {
|
||||
mysql_free_result($this->result);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Destruct, the cleanup crew!
|
||||
*/
|
||||
public function __destruct()
|
||||
{
|
||||
if (is_resource($this->result))
|
||||
{
|
||||
mysql_free_result($this->result);
|
||||
}
|
||||
}
|
||||
public function result($object = true, $type = MYSQL_ASSOC)
|
||||
{
|
||||
$this->fetch_type = ((bool) $object) ? 'mysql_fetch_object' : 'mysql_fetch_array';
|
||||
|
||||
public function result($object = TRUE, $type = MYSQL_ASSOC)
|
||||
{
|
||||
$this->fetch_type = ((bool) $object) ? 'mysql_fetch_object' : 'mysql_fetch_array';
|
||||
// This check has to be outside the previous statement, because we do not
|
||||
// know the state of fetch_type when $object = NULL
|
||||
// NOTE - The class set by $type must be defined before fetching the result,
|
||||
// autoloading is disabled to save a lot of stupid overhead.
|
||||
if ($this->fetch_type == 'mysql_fetch_object' and $object === true) {
|
||||
$this->return_type = (is_string($type) and Kohana::auto_load($type)) ? $type : 'stdClass';
|
||||
} else {
|
||||
$this->return_type = $type;
|
||||
}
|
||||
|
||||
// This check has to be outside the previous statement, because we do not
|
||||
// know the state of fetch_type when $object = NULL
|
||||
// NOTE - The class set by $type must be defined before fetching the result,
|
||||
// autoloading is disabled to save a lot of stupid overhead.
|
||||
if ($this->fetch_type == 'mysql_fetch_object' AND $object === TRUE)
|
||||
{
|
||||
$this->return_type = (is_string($type) AND Kohana::auto_load($type)) ? $type : 'stdClass';
|
||||
}
|
||||
else
|
||||
{
|
||||
$this->return_type = $type;
|
||||
}
|
||||
return $this;
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
public function as_array($object = null, $type = MYSQL_ASSOC)
|
||||
{
|
||||
return $this->result_array($object, $type);
|
||||
}
|
||||
|
||||
public function as_array($object = NULL, $type = MYSQL_ASSOC)
|
||||
{
|
||||
return $this->result_array($object, $type);
|
||||
}
|
||||
public function result_array($object = null, $type = MYSQL_ASSOC)
|
||||
{
|
||||
$rows = array();
|
||||
|
||||
public function result_array($object = NULL, $type = MYSQL_ASSOC)
|
||||
{
|
||||
$rows = array();
|
||||
if (is_string($object)) {
|
||||
$fetch = $object;
|
||||
} elseif (is_bool($object)) {
|
||||
if ($object === true) {
|
||||
$fetch = 'mysql_fetch_object';
|
||||
|
||||
if (is_string($object))
|
||||
{
|
||||
$fetch = $object;
|
||||
}
|
||||
elseif (is_bool($object))
|
||||
{
|
||||
if ($object === TRUE)
|
||||
{
|
||||
$fetch = 'mysql_fetch_object';
|
||||
$type = (is_string($type) and Kohana::auto_load($type)) ? $type : 'stdClass';
|
||||
} else {
|
||||
$fetch = 'mysql_fetch_array';
|
||||
}
|
||||
} else {
|
||||
// Use the default config values
|
||||
$fetch = $this->fetch_type;
|
||||
|
||||
$type = (is_string($type) AND Kohana::auto_load($type)) ? $type : 'stdClass';
|
||||
}
|
||||
else
|
||||
{
|
||||
$fetch = 'mysql_fetch_array';
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Use the default config values
|
||||
$fetch = $this->fetch_type;
|
||||
if ($fetch == 'mysql_fetch_object') {
|
||||
$type = (is_string($this->return_type) and Kohana::auto_load($this->return_type)) ? $this->return_type : 'stdClass';
|
||||
}
|
||||
}
|
||||
|
||||
if ($fetch == 'mysql_fetch_object')
|
||||
{
|
||||
$type = (is_string($this->return_type) AND Kohana::auto_load($this->return_type)) ? $this->return_type : 'stdClass';
|
||||
}
|
||||
}
|
||||
if (mysql_num_rows($this->result)) {
|
||||
// Reset the pointer location to make sure things work properly
|
||||
mysql_data_seek($this->result, 0);
|
||||
|
||||
if (mysql_num_rows($this->result))
|
||||
{
|
||||
// Reset the pointer location to make sure things work properly
|
||||
mysql_data_seek($this->result, 0);
|
||||
while ($row = $fetch($this->result, $type)) {
|
||||
$rows[] = $row;
|
||||
}
|
||||
}
|
||||
|
||||
while ($row = $fetch($this->result, $type))
|
||||
{
|
||||
$rows[] = $row;
|
||||
}
|
||||
}
|
||||
return isset($rows) ? $rows : array();
|
||||
}
|
||||
|
||||
return isset($rows) ? $rows : array();
|
||||
}
|
||||
public function list_fields()
|
||||
{
|
||||
$field_names = array();
|
||||
while ($field = mysql_fetch_field($this->result)) {
|
||||
$field_names[] = $field->name;
|
||||
}
|
||||
|
||||
public function list_fields()
|
||||
{
|
||||
$field_names = array();
|
||||
while ($field = mysql_fetch_field($this->result))
|
||||
{
|
||||
$field_names[] = $field->name;
|
||||
}
|
||||
return $field_names;
|
||||
}
|
||||
|
||||
return $field_names;
|
||||
}
|
||||
public function seek($offset)
|
||||
{
|
||||
if ($this->offsetExists($offset) and mysql_data_seek($this->result, $offset)) {
|
||||
// Set the current row to the offset
|
||||
$this->current_row = $offset;
|
||||
|
||||
public function seek($offset)
|
||||
{
|
||||
if ($this->offsetExists($offset) AND mysql_data_seek($this->result, $offset))
|
||||
{
|
||||
// Set the current row to the offset
|
||||
$this->current_row = $offset;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
else
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
} // End Mysql_Result Class
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
// End Mysql_Result Class
|
||||
|
||||
@@ -1,4 +1,13 @@
|
||||
<?php defined('SYSPATH') OR die('No direct access allowed.');
|
||||
<?php
|
||||
|
||||
// phpcs:disable PSR1.Classes.ClassDeclaration.MissingNamespace
|
||||
// phpcs:disable PSR1.Classes.ClassDeclaration.MultipleClasses
|
||||
// phpcs:disable PSR1.Files.SideEffects
|
||||
defined('SYSPATH') or die('No direct access allowed.');
|
||||
// phpcs:enable PSR1.Files.SideEffects
|
||||
// phpcs:disable Squiz.Classes.ValidClassName.NotCamelCaps
|
||||
|
||||
|
||||
/**
|
||||
* MySQLi Database Driver
|
||||
*
|
||||
@@ -9,350 +18,319 @@
|
||||
* @copyright (c) 2007-2008 Kohana Team
|
||||
* @license http://kohanaphp.com/license.html
|
||||
*/
|
||||
class Database_Mysqli_Driver extends Database_Mysql_Driver {
|
||||
class Database_Mysqli_Driver extends Database_Mysql_Driver
|
||||
{
|
||||
// Database connection link
|
||||
protected $link;
|
||||
protected $db_config;
|
||||
protected $statements = array();
|
||||
|
||||
// Database connection link
|
||||
protected $link;
|
||||
protected $db_config;
|
||||
protected $statements = array();
|
||||
/**
|
||||
* Sets the config for the class.
|
||||
*
|
||||
* @param array database configuration
|
||||
*/
|
||||
public function __construct($config)
|
||||
{
|
||||
$this->db_config = $config;
|
||||
|
||||
/**
|
||||
* Sets the config for the class.
|
||||
*
|
||||
* @param array database configuration
|
||||
*/
|
||||
public function __construct($config)
|
||||
{
|
||||
$this->db_config = $config;
|
||||
Kohana::log('debug', 'MySQLi Database Driver Initialized');
|
||||
}
|
||||
|
||||
Kohana::log('debug', 'MySQLi Database Driver Initialized');
|
||||
}
|
||||
/**
|
||||
* Closes the database connection.
|
||||
*/
|
||||
public function __destruct()
|
||||
{
|
||||
is_object($this->link) and $this->link->close();
|
||||
}
|
||||
|
||||
/**
|
||||
* Closes the database connection.
|
||||
*/
|
||||
public function __destruct()
|
||||
{
|
||||
is_object($this->link) and $this->link->close();
|
||||
}
|
||||
public function connect()
|
||||
{
|
||||
// Check if link already exists
|
||||
if (is_object($this->link)) {
|
||||
return $this->link;
|
||||
}
|
||||
|
||||
public function connect()
|
||||
{
|
||||
// Check if link already exists
|
||||
if (is_object($this->link))
|
||||
return $this->link;
|
||||
// Import the connect variables
|
||||
extract($this->db_config['connection']);
|
||||
|
||||
// Import the connect variables
|
||||
extract($this->db_config['connection']);
|
||||
// Build the connection info
|
||||
$host = isset($host) ? $host : $socket;
|
||||
|
||||
// Build the connection info
|
||||
$host = isset($host) ? $host : $socket;
|
||||
// Make the connection and select the database
|
||||
if ($this->link = new mysqli($host, $user, $pass, $database, $port)) {
|
||||
if ($charset = $this->db_config['character_set']) {
|
||||
$this->set_charset($charset);
|
||||
}
|
||||
|
||||
// Make the connection and select the database
|
||||
if ($this->link = new mysqli($host, $user, $pass, $database, $port))
|
||||
{
|
||||
if ($charset = $this->db_config['character_set'])
|
||||
{
|
||||
$this->set_charset($charset);
|
||||
}
|
||||
// Clear password after successful connect
|
||||
$this->db_config['connection']['pass'] = null;
|
||||
|
||||
// Clear password after successful connect
|
||||
$this->db_config['connection']['pass'] = NULL;
|
||||
return $this->link;
|
||||
}
|
||||
|
||||
return $this->link;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
public function query($sql)
|
||||
{
|
||||
// Only cache if it's turned on, and only cache if it's not a write statement
|
||||
if ($this->db_config['cache'] and ! preg_match('#\b(?:INSERT|UPDATE|REPLACE|SET|DELETE|TRUNCATE)\b#i', $sql)) {
|
||||
$hash = $this->query_hash($sql);
|
||||
|
||||
public function query($sql)
|
||||
{
|
||||
// Only cache if it's turned on, and only cache if it's not a write statement
|
||||
if ($this->db_config['cache'] AND ! preg_match('#\b(?:INSERT|UPDATE|REPLACE|SET|DELETE|TRUNCATE)\b#i', $sql))
|
||||
{
|
||||
$hash = $this->query_hash($sql);
|
||||
if (! isset($this->query_cache[$hash])) {
|
||||
// Set the cached object
|
||||
$this->query_cache[$hash] = new Kohana_Mysqli_Result($this->link, $this->db_config['object'], $sql);
|
||||
} else {
|
||||
// Rewind cached result
|
||||
$this->query_cache[$hash]->rewind();
|
||||
}
|
||||
|
||||
if ( ! isset($this->query_cache[$hash]))
|
||||
{
|
||||
// Set the cached object
|
||||
$this->query_cache[$hash] = new Kohana_Mysqli_Result($this->link, $this->db_config['object'], $sql);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Rewind cached result
|
||||
$this->query_cache[$hash]->rewind();
|
||||
}
|
||||
// Return the cached query
|
||||
return $this->query_cache[$hash];
|
||||
}
|
||||
|
||||
// Return the cached query
|
||||
return $this->query_cache[$hash];
|
||||
}
|
||||
return new Kohana_Mysqli_Result($this->link, $this->db_config['object'], $sql);
|
||||
}
|
||||
|
||||
return new Kohana_Mysqli_Result($this->link, $this->db_config['object'], $sql);
|
||||
}
|
||||
public function set_charset($charset)
|
||||
{
|
||||
if ($this->link->set_charset($charset) === false) {
|
||||
throw new Kohana_Database_Exception('database.error', $this->show_error());
|
||||
}
|
||||
}
|
||||
|
||||
public function set_charset($charset)
|
||||
{
|
||||
if ($this->link->set_charset($charset) === FALSE)
|
||||
throw new Kohana_Database_Exception('database.error', $this->show_error());
|
||||
}
|
||||
public function escape_str($str)
|
||||
{
|
||||
if (!$this->db_config['escape']) {
|
||||
return $str;
|
||||
}
|
||||
|
||||
public function escape_str($str)
|
||||
{
|
||||
if (!$this->db_config['escape'])
|
||||
return $str;
|
||||
is_object($this->link) or $this->connect();
|
||||
|
||||
is_object($this->link) or $this->connect();
|
||||
return $this->link->real_escape_string($str);
|
||||
}
|
||||
|
||||
return $this->link->real_escape_string($str);
|
||||
}
|
||||
|
||||
public function show_error()
|
||||
{
|
||||
return $this->link->error;
|
||||
}
|
||||
|
||||
} // End Database_Mysqli_Driver Class
|
||||
public function show_error()
|
||||
{
|
||||
return $this->link->error;
|
||||
}
|
||||
}
|
||||
// End Database_Mysqli_Driver Class
|
||||
|
||||
/**
|
||||
* MySQLi Result
|
||||
*/
|
||||
class Kohana_Mysqli_Result extends Database_Result {
|
||||
class Kohana_Mysqli_Result extends Database_Result
|
||||
{
|
||||
// Database connection
|
||||
protected $link;
|
||||
|
||||
// Database connection
|
||||
protected $link;
|
||||
// Data fetching types
|
||||
protected $fetch_type = 'mysqli_fetch_object';
|
||||
protected $return_type = MYSQLI_ASSOC;
|
||||
|
||||
// Data fetching types
|
||||
protected $fetch_type = 'mysqli_fetch_object';
|
||||
protected $return_type = MYSQLI_ASSOC;
|
||||
/**
|
||||
* Sets up the result variables.
|
||||
*
|
||||
* @param object database link
|
||||
* @param boolean return objects or arrays
|
||||
* @param string SQL query that was run
|
||||
*/
|
||||
public function __construct($link, $object = true, $sql = '')
|
||||
{
|
||||
$this->link = $link;
|
||||
|
||||
/**
|
||||
* Sets up the result variables.
|
||||
*
|
||||
* @param object database link
|
||||
* @param boolean return objects or arrays
|
||||
* @param string SQL query that was run
|
||||
*/
|
||||
public function __construct($link, $object = TRUE, $sql)
|
||||
{
|
||||
$this->link = $link;
|
||||
if (! $this->link->multi_query($sql)) {
|
||||
// SQL error
|
||||
throw new Kohana_Database_Exception('database.error', $this->link->error . ' - ' . $sql);
|
||||
} else {
|
||||
$this->result = $this->link->store_result();
|
||||
|
||||
if ( ! $this->link->multi_query($sql))
|
||||
{
|
||||
// SQL error
|
||||
throw new Kohana_Database_Exception('database.error', $this->link->error.' - '.$sql);
|
||||
}
|
||||
else
|
||||
{
|
||||
$this->result = $this->link->store_result();
|
||||
// If the query is an object, it was a SELECT, SHOW, DESCRIBE, EXPLAIN query
|
||||
if (is_object($this->result)) {
|
||||
$this->current_row = 0;
|
||||
$this->total_rows = $this->result->num_rows;
|
||||
$this->fetch_type = ($object === true) ? 'fetch_object' : 'fetch_array';
|
||||
} elseif ($this->link->error) {
|
||||
// SQL error
|
||||
throw new Kohana_Database_Exception('database.error', $this->link->error . ' - ' . $sql);
|
||||
} else {
|
||||
// Its an DELETE, INSERT, REPLACE, or UPDATE query
|
||||
$this->insert_id = $this->link->insert_id;
|
||||
$this->total_rows = $this->link->affected_rows;
|
||||
}
|
||||
}
|
||||
|
||||
// If the query is an object, it was a SELECT, SHOW, DESCRIBE, EXPLAIN query
|
||||
if (is_object($this->result))
|
||||
{
|
||||
$this->current_row = 0;
|
||||
$this->total_rows = $this->result->num_rows;
|
||||
$this->fetch_type = ($object === TRUE) ? 'fetch_object' : 'fetch_array';
|
||||
}
|
||||
elseif ($this->link->error)
|
||||
{
|
||||
// SQL error
|
||||
throw new Kohana_Database_Exception('database.error', $this->link->error.' - '.$sql);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Its an DELETE, INSERT, REPLACE, or UPDATE query
|
||||
$this->insert_id = $this->link->insert_id;
|
||||
$this->total_rows = $this->link->affected_rows;
|
||||
}
|
||||
}
|
||||
// Set result type
|
||||
$this->result($object);
|
||||
|
||||
// Set result type
|
||||
$this->result($object);
|
||||
// Store the SQL
|
||||
$this->sql = $sql;
|
||||
}
|
||||
|
||||
// Store the SQL
|
||||
$this->sql = $sql;
|
||||
}
|
||||
/**
|
||||
* Magic __destruct function, frees the result.
|
||||
*/
|
||||
public function __destruct()
|
||||
{
|
||||
if (is_object($this->result)) {
|
||||
$this->result->free_result();
|
||||
|
||||
/**
|
||||
* Magic __destruct function, frees the result.
|
||||
*/
|
||||
public function __destruct()
|
||||
{
|
||||
if (is_object($this->result))
|
||||
{
|
||||
$this->result->free_result();
|
||||
// this is kinda useless, but needs to be done to avoid the "Commands out of sync; you
|
||||
// can't run this command now" error. Basically, we get all results after the first one
|
||||
// (the one we actually need) and free them.
|
||||
if (is_resource($this->link) and $this->link->more_results()) {
|
||||
do {
|
||||
if ($result = $this->link->store_result()) {
|
||||
$result->free_result();
|
||||
}
|
||||
} while ($this->link->next_result());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// this is kinda useless, but needs to be done to avoid the "Commands out of sync; you
|
||||
// can't run this command now" error. Basically, we get all results after the first one
|
||||
// (the one we actually need) and free them.
|
||||
if (is_resource($this->link) AND $this->link->more_results())
|
||||
{
|
||||
do
|
||||
{
|
||||
if ($result = $this->link->store_result())
|
||||
{
|
||||
$result->free_result();
|
||||
}
|
||||
} while ($this->link->next_result());
|
||||
}
|
||||
}
|
||||
}
|
||||
public function result($object = true, $type = MYSQLI_ASSOC)
|
||||
{
|
||||
$this->fetch_type = ((bool) $object) ? 'fetch_object' : 'fetch_array';
|
||||
|
||||
public function result($object = TRUE, $type = MYSQLI_ASSOC)
|
||||
{
|
||||
$this->fetch_type = ((bool) $object) ? 'fetch_object' : 'fetch_array';
|
||||
// This check has to be outside the previous statement, because we do not
|
||||
// know the state of fetch_type when $object = NULL
|
||||
// NOTE - The class set by $type must be defined before fetching the result,
|
||||
// autoloading is disabled to save a lot of stupid overhead.
|
||||
if ($this->fetch_type == 'fetch_object') {
|
||||
$this->return_type = (is_string($type) and Kohana::auto_load($type)) ? $type : 'stdClass';
|
||||
} else {
|
||||
$this->return_type = $type;
|
||||
}
|
||||
|
||||
// This check has to be outside the previous statement, because we do not
|
||||
// know the state of fetch_type when $object = NULL
|
||||
// NOTE - The class set by $type must be defined before fetching the result,
|
||||
// autoloading is disabled to save a lot of stupid overhead.
|
||||
if ($this->fetch_type == 'fetch_object')
|
||||
{
|
||||
$this->return_type = (is_string($type) AND Kohana::auto_load($type)) ? $type : 'stdClass';
|
||||
}
|
||||
else
|
||||
{
|
||||
$this->return_type = $type;
|
||||
}
|
||||
return $this;
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
public function as_array($object = null, $type = MYSQLI_ASSOC)
|
||||
{
|
||||
return $this->result_array($object, $type);
|
||||
}
|
||||
|
||||
public function as_array($object = NULL, $type = MYSQLI_ASSOC)
|
||||
{
|
||||
return $this->result_array($object, $type);
|
||||
}
|
||||
public function result_array($object = null, $type = MYSQLI_ASSOC)
|
||||
{
|
||||
$rows = array();
|
||||
|
||||
public function result_array($object = NULL, $type = MYSQLI_ASSOC)
|
||||
{
|
||||
$rows = array();
|
||||
if (is_string($object)) {
|
||||
$fetch = $object;
|
||||
} elseif (is_bool($object)) {
|
||||
if ($object === true) {
|
||||
$fetch = 'fetch_object';
|
||||
|
||||
if (is_string($object))
|
||||
{
|
||||
$fetch = $object;
|
||||
}
|
||||
elseif (is_bool($object))
|
||||
{
|
||||
if ($object === TRUE)
|
||||
{
|
||||
$fetch = 'fetch_object';
|
||||
// NOTE - The class set by $type must be defined before fetching the result,
|
||||
// autoloading is disabled to save a lot of stupid overhead.
|
||||
$type = (is_string($type) and Kohana::auto_load($type)) ? $type : 'stdClass';
|
||||
} else {
|
||||
$fetch = 'fetch_array';
|
||||
}
|
||||
} else {
|
||||
// Use the default config values
|
||||
$fetch = $this->fetch_type;
|
||||
|
||||
// NOTE - The class set by $type must be defined before fetching the result,
|
||||
// autoloading is disabled to save a lot of stupid overhead.
|
||||
$type = (is_string($type) AND Kohana::auto_load($type)) ? $type : 'stdClass';
|
||||
}
|
||||
else
|
||||
{
|
||||
$fetch = 'fetch_array';
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Use the default config values
|
||||
$fetch = $this->fetch_type;
|
||||
if ($fetch == 'fetch_object') {
|
||||
$type = (is_string($type) and Kohana::auto_load($type)) ? $type : 'stdClass';
|
||||
}
|
||||
}
|
||||
|
||||
if ($fetch == 'fetch_object')
|
||||
{
|
||||
$type = (is_string($type) AND Kohana::auto_load($type)) ? $type : 'stdClass';
|
||||
}
|
||||
}
|
||||
if ($this->result->num_rows) {
|
||||
// Reset the pointer location to make sure things work properly
|
||||
$this->result->data_seek(0);
|
||||
|
||||
if ($this->result->num_rows)
|
||||
{
|
||||
// Reset the pointer location to make sure things work properly
|
||||
$this->result->data_seek(0);
|
||||
while ($row = $this->result->$fetch($type)) {
|
||||
$rows[] = $row;
|
||||
}
|
||||
}
|
||||
|
||||
while ($row = $this->result->$fetch($type))
|
||||
{
|
||||
$rows[] = $row;
|
||||
}
|
||||
}
|
||||
return isset($rows) ? $rows : array();
|
||||
}
|
||||
|
||||
return isset($rows) ? $rows : array();
|
||||
}
|
||||
public function list_fields()
|
||||
{
|
||||
$field_names = array();
|
||||
while ($field = $this->result->fetch_field()) {
|
||||
$field_names[] = $field->name;
|
||||
}
|
||||
|
||||
public function list_fields()
|
||||
{
|
||||
$field_names = array();
|
||||
while ($field = $this->result->fetch_field())
|
||||
{
|
||||
$field_names[] = $field->name;
|
||||
}
|
||||
return $field_names;
|
||||
}
|
||||
|
||||
return $field_names;
|
||||
}
|
||||
public function seek($offset)
|
||||
{
|
||||
if ($this->offsetExists($offset) and $this->result->data_seek($offset)) {
|
||||
// Set the current row to the offset
|
||||
$this->current_row = $offset;
|
||||
|
||||
public function seek($offset)
|
||||
{
|
||||
if ($this->offsetExists($offset) AND $this->result->data_seek($offset))
|
||||
{
|
||||
// Set the current row to the offset
|
||||
$this->current_row = $offset;
|
||||
return true;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
public function offsetGet($offset)
|
||||
{
|
||||
if (! $this->seek($offset)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
public function offsetGet($offset)
|
||||
{
|
||||
if ( ! $this->seek($offset))
|
||||
return FALSE;
|
||||
|
||||
// Return the row
|
||||
$fetch = $this->fetch_type;
|
||||
return $this->result->$fetch($this->return_type);
|
||||
}
|
||||
|
||||
} // End Mysqli_Result Class
|
||||
// Return the row
|
||||
$fetch = $this->fetch_type;
|
||||
return $this->result->$fetch($this->return_type);
|
||||
}
|
||||
}
|
||||
// End Mysqli_Result Class
|
||||
|
||||
/**
|
||||
* MySQLi Prepared Statement (experimental)
|
||||
*/
|
||||
class Kohana_Mysqli_Statement {
|
||||
class Kohana_Mysqli_Statement
|
||||
{
|
||||
protected $link = null;
|
||||
protected $stmt;
|
||||
protected $var_names = array();
|
||||
protected $var_values = array();
|
||||
|
||||
protected $link = NULL;
|
||||
protected $stmt;
|
||||
protected $var_names = array();
|
||||
protected $var_values = array();
|
||||
public function __construct($sql, $link)
|
||||
{
|
||||
$this->link = $link;
|
||||
|
||||
public function __construct($sql, $link)
|
||||
{
|
||||
$this->link = $link;
|
||||
$this->stmt = $this->link->prepare($sql);
|
||||
|
||||
$this->stmt = $this->link->prepare($sql);
|
||||
return $this;
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
public function __destruct()
|
||||
{
|
||||
$this->stmt->close();
|
||||
}
|
||||
|
||||
public function __destruct()
|
||||
{
|
||||
$this->stmt->close();
|
||||
}
|
||||
// Sets the bind parameters
|
||||
public function bind_params($param_types, $params)
|
||||
{
|
||||
$this->var_names = array_keys($params);
|
||||
$this->var_values = array_values($params);
|
||||
call_user_func_array(array($this->stmt, 'bind_param'), array_merge($param_types, $var_names));
|
||||
|
||||
// Sets the bind parameters
|
||||
public function bind_params($param_types, $params)
|
||||
{
|
||||
$this->var_names = array_keys($params);
|
||||
$this->var_values = array_values($params);
|
||||
call_user_func_array(array($this->stmt, 'bind_param'), array_merge($param_types, $var_names));
|
||||
return $this;
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
public function bind_result($params)
|
||||
{
|
||||
call_user_func_array(array($this->stmt, 'bind_result'), $params);
|
||||
}
|
||||
|
||||
public function bind_result($params)
|
||||
{
|
||||
call_user_func_array(array($this->stmt, 'bind_result'), $params);
|
||||
}
|
||||
|
||||
// Runs the statement
|
||||
public function execute()
|
||||
{
|
||||
foreach ($this->var_names as $key => $name)
|
||||
{
|
||||
$$name = $this->var_values[$key];
|
||||
}
|
||||
$this->stmt->execute();
|
||||
return $this->stmt;
|
||||
}
|
||||
// Runs the statement
|
||||
public function execute()
|
||||
{
|
||||
foreach ($this->var_names as $key => $name) {
|
||||
$$name = $this->var_values[$key];
|
||||
}
|
||||
$this->stmt->execute();
|
||||
return $this->stmt;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,13 @@
|
||||
<?php defined('SYSPATH') OR die('No direct access allowed.');
|
||||
<?php
|
||||
|
||||
// phpcs:disable PSR1.Classes.ClassDeclaration.MissingNamespace
|
||||
// phpcs:disable PSR1.Classes.ClassDeclaration.MultipleClasses
|
||||
// phpcs:disable PSR1.Files.SideEffects
|
||||
defined('SYSPATH') or die('No direct access allowed.');
|
||||
// phpcs:enable PSR1.Files.SideEffects
|
||||
// phpcs:disable Squiz.Classes.ValidClassName.NotCamelCaps
|
||||
|
||||
|
||||
/*
|
||||
* Class: Database_PdoSqlite_Driver
|
||||
* Provides specific database items for Sqlite.
|
||||
@@ -11,476 +20,418 @@
|
||||
* license - <no>
|
||||
*/
|
||||
|
||||
class Database_Pdosqlite_Driver extends Database_Driver {
|
||||
class Database_Pdosqlite_Driver extends Database_Driver
|
||||
{
|
||||
// Database connection link
|
||||
protected $link;
|
||||
protected $db_config;
|
||||
|
||||
// Database connection link
|
||||
protected $link;
|
||||
protected $db_config;
|
||||
/*
|
||||
* Constructor: __construct
|
||||
* Sets up the config for the class.
|
||||
*
|
||||
* Parameters:
|
||||
* config - database configuration
|
||||
*
|
||||
*/
|
||||
public function __construct($config)
|
||||
{
|
||||
$this->db_config = $config;
|
||||
|
||||
/*
|
||||
* Constructor: __construct
|
||||
* Sets up the config for the class.
|
||||
*
|
||||
* Parameters:
|
||||
* config - database configuration
|
||||
*
|
||||
*/
|
||||
public function __construct($config)
|
||||
{
|
||||
$this->db_config = $config;
|
||||
Kohana::log('debug', 'PDO:Sqlite Database Driver Initialized');
|
||||
}
|
||||
|
||||
Kohana::log('debug', 'PDO:Sqlite Database Driver Initialized');
|
||||
}
|
||||
public function connect()
|
||||
{
|
||||
// Import the connect variables
|
||||
extract($this->db_config['connection']);
|
||||
|
||||
public function connect()
|
||||
{
|
||||
// Import the connect variables
|
||||
extract($this->db_config['connection']);
|
||||
try {
|
||||
$this->link = new PDO(
|
||||
'sqlite:' . $socket . $database,
|
||||
$user,
|
||||
$pass,
|
||||
array(PDO::ATTR_PERSISTENT => $this->db_config['persistent'])
|
||||
);
|
||||
|
||||
try
|
||||
{
|
||||
$this->link = new PDO('sqlite:'.$socket.$database, $user, $pass,
|
||||
array(PDO::ATTR_PERSISTENT => $this->db_config['persistent']));
|
||||
$this->link->setAttribute(PDO::ATTR_CASE, PDO::CASE_NATURAL);
|
||||
//$this->link->query('PRAGMA count_changes=1;');
|
||||
|
||||
$this->link->setAttribute(PDO::ATTR_CASE, PDO::CASE_NATURAL);
|
||||
//$this->link->query('PRAGMA count_changes=1;');
|
||||
if ($charset = $this->db_config['character_set']) {
|
||||
$this->set_charset($charset);
|
||||
}
|
||||
} catch (PDOException $e) {
|
||||
throw new Kohana_Database_Exception('database.error', $e->getMessage());
|
||||
}
|
||||
|
||||
if ($charset = $this->db_config['character_set'])
|
||||
{
|
||||
$this->set_charset($charset);
|
||||
}
|
||||
}
|
||||
catch (PDOException $e)
|
||||
{
|
||||
throw new Kohana_Database_Exception('database.error', $e->getMessage());
|
||||
}
|
||||
// Clear password after successful connect
|
||||
$this->db_config['connection']['pass'] = null;
|
||||
|
||||
// Clear password after successful connect
|
||||
$this->db_config['connection']['pass'] = NULL;
|
||||
return $this->link;
|
||||
}
|
||||
|
||||
return $this->link;
|
||||
}
|
||||
public function query($sql)
|
||||
{
|
||||
try {
|
||||
$sth = $this->link->prepare($sql);
|
||||
} catch (PDOException $e) {
|
||||
throw new Kohana_Database_Exception('database.error', $e->getMessage());
|
||||
}
|
||||
return new Pdosqlite_Result($sth, $this->link, $this->db_config['object'], $sql);
|
||||
}
|
||||
|
||||
public function query($sql)
|
||||
{
|
||||
try
|
||||
{
|
||||
$sth = $this->link->prepare($sql);
|
||||
}
|
||||
catch (PDOException $e)
|
||||
{
|
||||
throw new Kohana_Database_Exception('database.error', $e->getMessage());
|
||||
}
|
||||
return new Pdosqlite_Result($sth, $this->link, $this->db_config['object'], $sql);
|
||||
}
|
||||
public function set_charset($charset)
|
||||
{
|
||||
$this->link->query('PRAGMA encoding = ' . $this->escape_str($charset));
|
||||
}
|
||||
|
||||
public function set_charset($charset)
|
||||
{
|
||||
$this->link->query('PRAGMA encoding = '.$this->escape_str($charset));
|
||||
}
|
||||
public function escape_table($table)
|
||||
{
|
||||
if (! $this->db_config['escape']) {
|
||||
return $table;
|
||||
}
|
||||
|
||||
public function escape_table($table)
|
||||
{
|
||||
if ( ! $this->db_config['escape'])
|
||||
return $table;
|
||||
return '`' . str_replace('.', '`.`', $table) . '`';
|
||||
}
|
||||
|
||||
return '`'.str_replace('.', '`.`', $table).'`';
|
||||
}
|
||||
public function escape_column($column)
|
||||
{
|
||||
if (! $this->db_config['escape']) {
|
||||
return $column;
|
||||
}
|
||||
|
||||
public function escape_column($column)
|
||||
{
|
||||
if ( ! $this->db_config['escape'])
|
||||
return $column;
|
||||
if ($column == '*') {
|
||||
return $column;
|
||||
}
|
||||
|
||||
if ($column == '*')
|
||||
return $column;
|
||||
// This matches any functions we support to SELECT.
|
||||
if (preg_match('/(avg|count|sum|max|min)\(\s*(.*)\s*\)(\s*as\s*(.+)?)?/i', $column, $matches)) {
|
||||
if (count($matches) == 3) {
|
||||
return $matches[1] . '(' . $this->escape_column($matches[2]) . ')';
|
||||
} elseif (count($matches) == 5) {
|
||||
return $matches[1] . '(' . $this->escape_column($matches[2]) . ') AS ' . $this->escape_column($matches[2]);
|
||||
}
|
||||
}
|
||||
|
||||
// This matches any functions we support to SELECT.
|
||||
if ( preg_match('/(avg|count|sum|max|min)\(\s*(.*)\s*\)(\s*as\s*(.+)?)?/i', $column, $matches))
|
||||
{
|
||||
if ( count($matches) == 3)
|
||||
{
|
||||
return $matches[1].'('.$this->escape_column($matches[2]).')';
|
||||
}
|
||||
else if ( count($matches) == 5)
|
||||
{
|
||||
return $matches[1].'('.$this->escape_column($matches[2]).') AS '.$this->escape_column($matches[2]);
|
||||
}
|
||||
}
|
||||
// This matches any modifiers we support to SELECT.
|
||||
if (! preg_match('/\b(?:rand|all|distinct(?:row)?|high_priority|sql_(?:small_result|b(?:ig_result|uffer_result)|no_cache|ca(?:che|lc_found_rows)))\s/i', $column)) {
|
||||
if (stripos($column, ' AS ') !== false) {
|
||||
// Force 'AS' to uppercase
|
||||
$column = str_ireplace(' AS ', ' AS ', $column);
|
||||
|
||||
// This matches any modifiers we support to SELECT.
|
||||
if ( ! preg_match('/\b(?:rand|all|distinct(?:row)?|high_priority|sql_(?:small_result|b(?:ig_result|uffer_result)|no_cache|ca(?:che|lc_found_rows)))\s/i', $column))
|
||||
{
|
||||
if (stripos($column, ' AS ') !== FALSE)
|
||||
{
|
||||
// Force 'AS' to uppercase
|
||||
$column = str_ireplace(' AS ', ' AS ', $column);
|
||||
// Runs escape_column on both sides of an AS statement
|
||||
$column = array_map(array($this, __FUNCTION__), explode(' AS ', $column));
|
||||
|
||||
// Runs escape_column on both sides of an AS statement
|
||||
$column = array_map(array($this, __FUNCTION__), explode(' AS ', $column));
|
||||
// Re-create the AS statement
|
||||
return implode(' AS ', $column);
|
||||
}
|
||||
|
||||
// Re-create the AS statement
|
||||
return implode(' AS ', $column);
|
||||
}
|
||||
return preg_replace('/[^.*]+/', '`$0`', $column);
|
||||
}
|
||||
|
||||
return preg_replace('/[^.*]+/', '`$0`', $column);
|
||||
}
|
||||
$parts = explode(' ', $column);
|
||||
$column = '';
|
||||
|
||||
$parts = explode(' ', $column);
|
||||
$column = '';
|
||||
for ($i = 0, $c = count($parts); $i < $c; $i++) {
|
||||
// The column is always last
|
||||
if ($i == ($c - 1)) {
|
||||
$column .= preg_replace('/[^.*]+/', '`$0`', $parts[$i]);
|
||||
} else // otherwise, it's a modifier
|
||||
{
|
||||
$column .= $parts[$i] . ' ';
|
||||
}
|
||||
}
|
||||
return $column;
|
||||
}
|
||||
|
||||
for ($i = 0, $c = count($parts); $i < $c; $i++)
|
||||
{
|
||||
// The column is always last
|
||||
if ($i == ($c - 1))
|
||||
{
|
||||
$column .= preg_replace('/[^.*]+/', '`$0`', $parts[$i]);
|
||||
}
|
||||
else // otherwise, it's a modifier
|
||||
{
|
||||
$column .= $parts[$i].' ';
|
||||
}
|
||||
}
|
||||
return $column;
|
||||
}
|
||||
public function limit($limit, $offset = 0)
|
||||
{
|
||||
return 'LIMIT ' . $offset . ', ' . $limit;
|
||||
}
|
||||
|
||||
public function limit($limit, $offset = 0)
|
||||
{
|
||||
return 'LIMIT '.$offset.', '.$limit;
|
||||
}
|
||||
public function compile_select($database)
|
||||
{
|
||||
$sql = ($database['distinct'] == true) ? 'SELECT DISTINCT ' : 'SELECT ';
|
||||
$sql .= (count($database['select']) > 0) ? implode(', ', $database['select']) : '*';
|
||||
|
||||
public function compile_select($database)
|
||||
{
|
||||
$sql = ($database['distinct'] == TRUE) ? 'SELECT DISTINCT ' : 'SELECT ';
|
||||
$sql .= (count($database['select']) > 0) ? implode(', ', $database['select']) : '*';
|
||||
if (count($database['from']) > 0) {
|
||||
$sql .= "\nFROM ";
|
||||
$sql .= implode(', ', $database['from']);
|
||||
}
|
||||
|
||||
if (count($database['from']) > 0)
|
||||
{
|
||||
$sql .= "\nFROM ";
|
||||
$sql .= implode(', ', $database['from']);
|
||||
}
|
||||
if (count($database['join']) > 0) {
|
||||
foreach ($database['join'] as $join) {
|
||||
$sql .= "\n" . $join['type'] . 'JOIN ' . implode(', ', $join['tables']) . ' ON ' . $join['conditions'];
|
||||
}
|
||||
}
|
||||
|
||||
if (count($database['join']) > 0)
|
||||
{
|
||||
foreach($database['join'] AS $join)
|
||||
{
|
||||
$sql .= "\n".$join['type'].'JOIN '.implode(', ', $join['tables']).' ON '.$join['conditions'];
|
||||
}
|
||||
}
|
||||
if (count($database['where']) > 0) {
|
||||
$sql .= "\nWHERE ";
|
||||
}
|
||||
|
||||
if (count($database['where']) > 0)
|
||||
{
|
||||
$sql .= "\nWHERE ";
|
||||
}
|
||||
$sql .= implode("\n", $database['where']);
|
||||
|
||||
$sql .= implode("\n", $database['where']);
|
||||
if (count($database['groupby']) > 0) {
|
||||
$sql .= "\nGROUP BY ";
|
||||
$sql .= implode(', ', $database['groupby']);
|
||||
}
|
||||
|
||||
if (count($database['groupby']) > 0)
|
||||
{
|
||||
$sql .= "\nGROUP BY ";
|
||||
$sql .= implode(', ', $database['groupby']);
|
||||
}
|
||||
if (count($database['having']) > 0) {
|
||||
$sql .= "\nHAVING ";
|
||||
$sql .= implode("\n", $database['having']);
|
||||
}
|
||||
|
||||
if (count($database['having']) > 0)
|
||||
{
|
||||
$sql .= "\nHAVING ";
|
||||
$sql .= implode("\n", $database['having']);
|
||||
}
|
||||
if (count($database['orderby']) > 0) {
|
||||
$sql .= "\nORDER BY ";
|
||||
$sql .= implode(', ', $database['orderby']);
|
||||
}
|
||||
|
||||
if (count($database['orderby']) > 0)
|
||||
{
|
||||
$sql .= "\nORDER BY ";
|
||||
$sql .= implode(', ', $database['orderby']);
|
||||
}
|
||||
if (is_numeric($database['limit'])) {
|
||||
$sql .= "\n";
|
||||
$sql .= $this->limit($database['limit'], $database['offset']);
|
||||
}
|
||||
|
||||
if (is_numeric($database['limit']))
|
||||
{
|
||||
$sql .= "\n";
|
||||
$sql .= $this->limit($database['limit'], $database['offset']);
|
||||
}
|
||||
return $sql;
|
||||
}
|
||||
|
||||
return $sql;
|
||||
}
|
||||
public function escape_str($str)
|
||||
{
|
||||
if (! $this->db_config['escape']) {
|
||||
return $str;
|
||||
}
|
||||
|
||||
public function escape_str($str)
|
||||
{
|
||||
if ( ! $this->db_config['escape'])
|
||||
return $str;
|
||||
if (function_exists('sqlite_escape_string')) {
|
||||
$res = sqlite_escape_string($str);
|
||||
} else {
|
||||
$res = str_replace("'", "''", $str);
|
||||
}
|
||||
return $res;
|
||||
}
|
||||
|
||||
if (function_exists('sqlite_escape_string'))
|
||||
{
|
||||
$res = sqlite_escape_string($str);
|
||||
}
|
||||
else
|
||||
{
|
||||
$res = str_replace("'", "''", $str);
|
||||
}
|
||||
return $res;
|
||||
}
|
||||
public function list_tables()
|
||||
{
|
||||
$sql = "SELECT `name` FROM `sqlite_master` WHERE `type`='table' ORDER BY `name`;";
|
||||
try {
|
||||
$result = $this->query($sql)->result(false, PDO::FETCH_ASSOC);
|
||||
$tables = array();
|
||||
foreach ($result as $row) {
|
||||
$tables[] = current($row);
|
||||
}
|
||||
} catch (PDOException $e) {
|
||||
throw new Kohana_Database_Exception('database.error', $e->getMessage());
|
||||
}
|
||||
return $tables;
|
||||
}
|
||||
|
||||
public function list_tables()
|
||||
{
|
||||
$sql = "SELECT `name` FROM `sqlite_master` WHERE `type`='table' ORDER BY `name`;";
|
||||
try
|
||||
{
|
||||
$result = $this->query($sql)->result(FALSE, PDO::FETCH_ASSOC);
|
||||
$tables = array();
|
||||
foreach ($result as $row)
|
||||
{
|
||||
$tables[] = current($row);
|
||||
}
|
||||
}
|
||||
catch (PDOException $e)
|
||||
{
|
||||
throw new Kohana_Database_Exception('database.error', $e->getMessage());
|
||||
}
|
||||
return $tables;
|
||||
}
|
||||
public function show_error()
|
||||
{
|
||||
$err = $this->link->errorInfo();
|
||||
return isset($err[2]) ? $err[2] : 'Unknown error!';
|
||||
}
|
||||
|
||||
public function show_error()
|
||||
{
|
||||
$err = $this->link->errorInfo();
|
||||
return isset($err[2]) ? $err[2] : 'Unknown error!';
|
||||
}
|
||||
public function list_fields($table, $query = false)
|
||||
{
|
||||
static $tables;
|
||||
if (is_object($query)) {
|
||||
if (empty($tables[$table])) {
|
||||
$tables[$table] = array();
|
||||
|
||||
public function list_fields($table, $query = FALSE)
|
||||
{
|
||||
static $tables;
|
||||
if (is_object($query))
|
||||
{
|
||||
if (empty($tables[$table]))
|
||||
{
|
||||
$tables[$table] = array();
|
||||
foreach ($query->result() as $row) {
|
||||
$tables[$table][] = $row->name;
|
||||
}
|
||||
}
|
||||
|
||||
foreach ($query->result() as $row)
|
||||
{
|
||||
$tables[$table][] = $row->name;
|
||||
}
|
||||
}
|
||||
return $tables[$table];
|
||||
} else {
|
||||
$result = $this->link->query('PRAGMA table_info(' . $this->escape_table($table) . ')');
|
||||
|
||||
return $tables[$table];
|
||||
}
|
||||
else
|
||||
{
|
||||
$result = $this->link->query( 'PRAGMA table_info('.$this->escape_table($table).')' );
|
||||
foreach ($result as $row) {
|
||||
$tables[$table][$row['name']] = $this->sql_type($row['type']);
|
||||
}
|
||||
|
||||
foreach ($result as $row)
|
||||
{
|
||||
$tables[$table][$row['name']] = $this->sql_type($row['type']);
|
||||
}
|
||||
return $tables[$table];
|
||||
}
|
||||
}
|
||||
|
||||
return $tables[$table];
|
||||
}
|
||||
}
|
||||
|
||||
public function field_data($table)
|
||||
{
|
||||
Kohana::log('error', 'This method is under developing');
|
||||
}
|
||||
/**
|
||||
* Version number query string
|
||||
*
|
||||
* @access public
|
||||
* @return string
|
||||
*/
|
||||
function version()
|
||||
{
|
||||
return $this->link->getAttribute(constant("PDO::ATTR_SERVER_VERSION"));
|
||||
}
|
||||
|
||||
} // End Database_PdoSqlite_Driver Class
|
||||
public function field_data($table)
|
||||
{
|
||||
Kohana::log('error', 'This method is under developing');
|
||||
}
|
||||
/**
|
||||
* Version number query string
|
||||
*
|
||||
* @access public
|
||||
* @return string
|
||||
*/
|
||||
public function version()
|
||||
{
|
||||
return $this->link->getAttribute(constant("PDO::ATTR_SERVER_VERSION"));
|
||||
}
|
||||
}
|
||||
// End Database_PdoSqlite_Driver Class
|
||||
|
||||
/*
|
||||
* PDO-sqlite Result
|
||||
*/
|
||||
class Pdosqlite_Result extends Database_Result {
|
||||
class Pdosqlite_Result extends Database_Result
|
||||
{
|
||||
// Data fetching types
|
||||
protected $fetch_type = PDO::FETCH_OBJ;
|
||||
protected $return_type = PDO::FETCH_ASSOC;
|
||||
|
||||
// Data fetching types
|
||||
protected $fetch_type = PDO::FETCH_OBJ;
|
||||
protected $return_type = PDO::FETCH_ASSOC;
|
||||
/**
|
||||
* Sets up the result variables.
|
||||
*
|
||||
* @param resource query result
|
||||
* @param resource database link
|
||||
* @param boolean return objects or arrays
|
||||
* @param string SQL query that was run
|
||||
*/
|
||||
public function __construct($result, $link, $object = true, $sql = '')
|
||||
{
|
||||
if (is_object($result) or $result = $link->prepare($sql)) {
|
||||
// run the query. Return true if success, false otherwise
|
||||
if (! $result->execute()) {
|
||||
// Throw Kohana Exception with error message. See PDOStatement errorInfo() method
|
||||
$arr_infos = $result->errorInfo();
|
||||
throw new Kohana_Database_Exception('database.error', $arr_infos[2]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets up the result variables.
|
||||
*
|
||||
* @param resource query result
|
||||
* @param resource database link
|
||||
* @param boolean return objects or arrays
|
||||
* @param string SQL query that was run
|
||||
*/
|
||||
public function __construct($result, $link, $object = TRUE, $sql)
|
||||
{
|
||||
if (is_object($result) OR $result = $link->prepare($sql))
|
||||
{
|
||||
// run the query. Return true if success, false otherwise
|
||||
if( ! $result->execute())
|
||||
{
|
||||
// Throw Kohana Exception with error message. See PDOStatement errorInfo() method
|
||||
$arr_infos = $result->errorInfo();
|
||||
throw new Kohana_Database_Exception('database.error', $arr_infos[2]);
|
||||
}
|
||||
if (preg_match('/^SELECT|PRAGMA|EXPLAIN/i', $sql)) {
|
||||
$this->result = $result;
|
||||
$this->current_row = 0;
|
||||
|
||||
if (preg_match('/^SELECT|PRAGMA|EXPLAIN/i', $sql))
|
||||
{
|
||||
$this->result = $result;
|
||||
$this->current_row = 0;
|
||||
$this->total_rows = $this->sqlite_row_count();
|
||||
|
||||
$this->total_rows = $this->sqlite_row_count();
|
||||
$this->fetch_type = ($object === true) ? PDO::FETCH_OBJ : PDO::FETCH_ASSOC;
|
||||
} elseif (preg_match('/^DELETE|INSERT|UPDATE/i', $sql)) {
|
||||
$this->insert_id = $link->lastInsertId();
|
||||
|
||||
$this->fetch_type = ($object === TRUE) ? PDO::FETCH_OBJ : PDO::FETCH_ASSOC;
|
||||
}
|
||||
elseif (preg_match('/^DELETE|INSERT|UPDATE/i', $sql))
|
||||
{
|
||||
$this->insert_id = $link->lastInsertId();
|
||||
$this->total_rows = $result->rowCount();
|
||||
}
|
||||
} else {
|
||||
// SQL error
|
||||
throw new Kohana_Database_Exception('database.error', $link->errorInfo() . ' - ' . $sql);
|
||||
}
|
||||
|
||||
$this->total_rows = $result->rowCount();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// SQL error
|
||||
throw new Kohana_Database_Exception('database.error', $link->errorInfo().' - '.$sql);
|
||||
}
|
||||
// Set result type
|
||||
$this->result($object);
|
||||
|
||||
// Set result type
|
||||
$this->result($object);
|
||||
// Store the SQL
|
||||
$this->sql = $sql;
|
||||
}
|
||||
|
||||
// Store the SQL
|
||||
$this->sql = $sql;
|
||||
}
|
||||
private function sqlite_row_count()
|
||||
{
|
||||
$count = 0;
|
||||
while ($this->result->fetch()) {
|
||||
$count++;
|
||||
}
|
||||
|
||||
private function sqlite_row_count()
|
||||
{
|
||||
$count = 0;
|
||||
while ($this->result->fetch())
|
||||
{
|
||||
$count++;
|
||||
}
|
||||
// The query must be re-fetched now.
|
||||
$this->result->execute();
|
||||
|
||||
// The query must be re-fetched now.
|
||||
$this->result->execute();
|
||||
return $count;
|
||||
}
|
||||
|
||||
return $count;
|
||||
}
|
||||
/*
|
||||
* Destructor: __destruct
|
||||
* Magic __destruct function, frees the result.
|
||||
*/
|
||||
public function __destruct()
|
||||
{
|
||||
if (is_object($this->result)) {
|
||||
$this->result->closeCursor();
|
||||
$this->result = null;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Destructor: __destruct
|
||||
* Magic __destruct function, frees the result.
|
||||
*/
|
||||
public function __destruct()
|
||||
{
|
||||
if (is_object($this->result))
|
||||
{
|
||||
$this->result->closeCursor();
|
||||
$this->result = NULL;
|
||||
}
|
||||
}
|
||||
public function result($object = true, $type = PDO::FETCH_BOTH)
|
||||
{
|
||||
$this->fetch_type = (bool) $object ? PDO::FETCH_OBJ : PDO::FETCH_BOTH;
|
||||
|
||||
public function result($object = TRUE, $type = PDO::FETCH_BOTH)
|
||||
{
|
||||
$this->fetch_type = (bool) $object ? PDO::FETCH_OBJ : PDO::FETCH_BOTH;
|
||||
if ($this->fetch_type == PDO::FETCH_OBJ) {
|
||||
$this->return_type = (is_string($type) and Kohana::auto_load($type)) ? $type : 'stdClass';
|
||||
} else {
|
||||
$this->return_type = $type;
|
||||
}
|
||||
|
||||
if ($this->fetch_type == PDO::FETCH_OBJ)
|
||||
{
|
||||
$this->return_type = (is_string($type) AND Kohana::auto_load($type)) ? $type : 'stdClass';
|
||||
}
|
||||
else
|
||||
{
|
||||
$this->return_type = $type;
|
||||
}
|
||||
return $this;
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
public function as_array($object = null, $type = PDO::FETCH_ASSOC)
|
||||
{
|
||||
return $this->result_array($object, $type);
|
||||
}
|
||||
|
||||
public function as_array($object = NULL, $type = PDO::FETCH_ASSOC)
|
||||
{
|
||||
return $this->result_array($object, $type);
|
||||
}
|
||||
public function result_array($object = null, $type = PDO::FETCH_ASSOC)
|
||||
{
|
||||
$rows = array();
|
||||
|
||||
public function result_array($object = NULL, $type = PDO::FETCH_ASSOC)
|
||||
{
|
||||
$rows = array();
|
||||
if (is_string($object)) {
|
||||
$fetch = $object;
|
||||
} elseif (is_bool($object)) {
|
||||
if ($object === true) {
|
||||
$fetch = PDO::FETCH_OBJ;
|
||||
|
||||
if (is_string($object))
|
||||
{
|
||||
$fetch = $object;
|
||||
}
|
||||
elseif (is_bool($object))
|
||||
{
|
||||
if ($object === TRUE)
|
||||
{
|
||||
$fetch = PDO::FETCH_OBJ;
|
||||
// NOTE - The class set by $type must be defined before fetching the result,
|
||||
// autoloading is disabled to save a lot of stupid overhead.
|
||||
$type = (is_string($type) and Kohana::auto_load($type)) ? $type : 'stdClass';
|
||||
} else {
|
||||
$fetch = PDO::FETCH_OBJ;
|
||||
}
|
||||
} else {
|
||||
// Use the default config values
|
||||
$fetch = $this->fetch_type;
|
||||
|
||||
// NOTE - The class set by $type must be defined before fetching the result,
|
||||
// autoloading is disabled to save a lot of stupid overhead.
|
||||
$type = (is_string($type) AND Kohana::auto_load($type)) ? $type : 'stdClass';
|
||||
}
|
||||
else
|
||||
{
|
||||
$fetch = PDO::FETCH_OBJ;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Use the default config values
|
||||
$fetch = $this->fetch_type;
|
||||
if ($fetch == PDO::FETCH_OBJ) {
|
||||
$type = (is_string($type) and Kohana::auto_load($type)) ? $type : 'stdClass';
|
||||
}
|
||||
}
|
||||
try {
|
||||
while ($row = $this->result->fetch($fetch)) {
|
||||
$rows[] = $row;
|
||||
}
|
||||
} catch (PDOException $e) {
|
||||
throw new Kohana_Database_Exception('database.error', $e->getMessage());
|
||||
return false;
|
||||
}
|
||||
return $rows;
|
||||
}
|
||||
|
||||
if ($fetch == PDO::FETCH_OBJ)
|
||||
{
|
||||
$type = (is_string($type) AND Kohana::auto_load($type)) ? $type : 'stdClass';
|
||||
}
|
||||
}
|
||||
try
|
||||
{
|
||||
while ($row = $this->result->fetch($fetch))
|
||||
{
|
||||
$rows[] = $row;
|
||||
}
|
||||
}
|
||||
catch(PDOException $e)
|
||||
{
|
||||
throw new Kohana_Database_Exception('database.error', $e->getMessage());
|
||||
return FALSE;
|
||||
}
|
||||
return $rows;
|
||||
}
|
||||
public function list_fields()
|
||||
{
|
||||
$field_names = array();
|
||||
for ($i = 0, $max = $this->result->columnCount(); $i < $max; $i++) {
|
||||
$info = $this->result->getColumnMeta($i);
|
||||
$field_names[] = $info['name'];
|
||||
}
|
||||
return $field_names;
|
||||
}
|
||||
|
||||
public function list_fields()
|
||||
{
|
||||
$field_names = array();
|
||||
for ($i = 0, $max = $this->result->columnCount(); $i < $max; $i++)
|
||||
{
|
||||
$info = $this->result->getColumnMeta($i);
|
||||
$field_names[] = $info['name'];
|
||||
}
|
||||
return $field_names;
|
||||
}
|
||||
public function seek($offset)
|
||||
{
|
||||
// To request a scrollable cursor for your PDOStatement object, you must
|
||||
// set the PDO::ATTR_CURSOR attribute to PDO::CURSOR_SCROLL when you
|
||||
// prepare the statement.
|
||||
Kohana::log('error', get_class($this) . ' does not support scrollable cursors, ' . __FUNCTION__ . ' call ignored');
|
||||
|
||||
public function seek($offset)
|
||||
{
|
||||
// To request a scrollable cursor for your PDOStatement object, you must
|
||||
// set the PDO::ATTR_CURSOR attribute to PDO::CURSOR_SCROLL when you
|
||||
// prepare the statement.
|
||||
Kohana::log('error', get_class($this).' does not support scrollable cursors, '.__FUNCTION__.' call ignored');
|
||||
return false;
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
public function offsetGet($offset)
|
||||
{
|
||||
try {
|
||||
return $this->result->fetch($this->fetch_type, PDO::FETCH_ORI_ABS, $offset);
|
||||
} catch (PDOException $e) {
|
||||
throw new Kohana_Database_Exception('database.error', $e->getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
public function offsetGet($offset)
|
||||
{
|
||||
try
|
||||
{
|
||||
return $this->result->fetch($this->fetch_type, PDO::FETCH_ORI_ABS, $offset);
|
||||
}
|
||||
catch(PDOException $e)
|
||||
{
|
||||
throw new Kohana_Database_Exception('database.error', $e->getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
public function rewind()
|
||||
{
|
||||
// Same problem that seek() has, see above.
|
||||
return $this->seek(0);
|
||||
}
|
||||
|
||||
} // End PdoSqlite_Result Class
|
||||
public function rewind()
|
||||
{
|
||||
// Same problem that seek() has, see above.
|
||||
return $this->seek(0);
|
||||
}
|
||||
}
|
||||
// End PdoSqlite_Result Class
|
||||
|
||||
@@ -1,4 +1,13 @@
|
||||
<?php defined('SYSPATH') OR die('No direct access allowed.');
|
||||
<?php
|
||||
|
||||
// phpcs:disable PSR1.Classes.ClassDeclaration.MissingNamespace
|
||||
// phpcs:disable PSR1.Classes.ClassDeclaration.MultipleClasses
|
||||
// phpcs:disable PSR1.Files.SideEffects
|
||||
defined('SYSPATH') or die('No direct access allowed.');
|
||||
// phpcs:enable PSR1.Files.SideEffects
|
||||
// phpcs:disable Squiz.Classes.ValidClassName.NotCamelCaps
|
||||
|
||||
|
||||
/**
|
||||
* PostgreSQL 8.1+ Database Driver
|
||||
*
|
||||
@@ -9,530 +18,486 @@
|
||||
* @copyright (c) 2007-2008 Kohana Team
|
||||
* @license http://kohanaphp.com/license.html
|
||||
*/
|
||||
class Database_Pgsql_Driver extends Database_Driver {
|
||||
class Database_Pgsql_Driver extends Database_Driver
|
||||
{
|
||||
// Database connection link
|
||||
protected $link;
|
||||
protected $db_config;
|
||||
|
||||
// Database connection link
|
||||
protected $link;
|
||||
protected $db_config;
|
||||
/**
|
||||
* Sets the config for the class.
|
||||
*
|
||||
* @param array database configuration
|
||||
*/
|
||||
public function __construct($config)
|
||||
{
|
||||
$this->db_config = $config;
|
||||
|
||||
/**
|
||||
* Sets the config for the class.
|
||||
*
|
||||
* @param array database configuration
|
||||
*/
|
||||
public function __construct($config)
|
||||
{
|
||||
$this->db_config = $config;
|
||||
Kohana::log('debug', 'PgSQL Database Driver Initialized');
|
||||
}
|
||||
|
||||
Kohana::log('debug', 'PgSQL Database Driver Initialized');
|
||||
}
|
||||
public function connect()
|
||||
{
|
||||
// Check if link already exists
|
||||
if (is_resource($this->link)) {
|
||||
return $this->link;
|
||||
}
|
||||
|
||||
public function connect()
|
||||
{
|
||||
// Check if link already exists
|
||||
if (is_resource($this->link))
|
||||
return $this->link;
|
||||
// Import the connect variables
|
||||
extract($this->db_config['connection']);
|
||||
|
||||
// Import the connect variables
|
||||
extract($this->db_config['connection']);
|
||||
// Persistent connections enabled?
|
||||
$connect = ($this->db_config['persistent'] == true) ? 'pg_pconnect' : 'pg_connect';
|
||||
|
||||
// Persistent connections enabled?
|
||||
$connect = ($this->db_config['persistent'] == TRUE) ? 'pg_pconnect' : 'pg_connect';
|
||||
// Build the connection info
|
||||
$port = isset($port) ? 'port=\'' . $port . '\'' : '';
|
||||
$host = isset($host) ? 'host=\'' . $host . '\' ' . $port : ''; // if no host, connect with the socket
|
||||
|
||||
// Build the connection info
|
||||
$port = isset($port) ? 'port=\''.$port.'\'' : '';
|
||||
$host = isset($host) ? 'host=\''.$host.'\' '.$port : ''; // if no host, connect with the socket
|
||||
$connection_string = $host . ' dbname=\'' . $database . '\' user=\'' . $user . '\' password=\'' . $pass . '\'';
|
||||
// Make the connection and select the database
|
||||
if ($this->link = $connect($connection_string)) {
|
||||
if ($charset = $this->db_config['character_set']) {
|
||||
echo $this->set_charset($charset);
|
||||
}
|
||||
|
||||
$connection_string = $host.' dbname=\''.$database.'\' user=\''.$user.'\' password=\''.$pass.'\'';
|
||||
// Make the connection and select the database
|
||||
if ($this->link = $connect($connection_string))
|
||||
{
|
||||
if ($charset = $this->db_config['character_set'])
|
||||
{
|
||||
echo $this->set_charset($charset);
|
||||
}
|
||||
// Clear password after successful connect
|
||||
$this->db_config['connection']['pass'] = null;
|
||||
|
||||
// Clear password after successful connect
|
||||
$this->db_config['connection']['pass'] = NULL;
|
||||
return $this->link;
|
||||
}
|
||||
|
||||
return $this->link;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
public function query($sql)
|
||||
{
|
||||
// Only cache if it's turned on, and only cache if it's not a write statement
|
||||
if ($this->db_config['cache'] and ! preg_match('#\b(?:INSERT|UPDATE|SET)\b#i', $sql)) {
|
||||
$hash = $this->query_hash($sql);
|
||||
|
||||
public function query($sql)
|
||||
{
|
||||
// Only cache if it's turned on, and only cache if it's not a write statement
|
||||
if ($this->db_config['cache'] AND ! preg_match('#\b(?:INSERT|UPDATE|SET)\b#i', $sql))
|
||||
{
|
||||
$hash = $this->query_hash($sql);
|
||||
if (! isset($this->query_cache[$hash])) {
|
||||
// Set the cached object
|
||||
$this->query_cache[$hash] = new Pgsql_Result(pg_query($this->link, $sql), $this->link, $this->db_config['object'], $sql);
|
||||
} else {
|
||||
// Rewind cached result
|
||||
$this->query_cache[$hash]->rewind();
|
||||
}
|
||||
|
||||
if ( ! isset($this->query_cache[$hash]))
|
||||
{
|
||||
// Set the cached object
|
||||
$this->query_cache[$hash] = new Pgsql_Result(pg_query($this->link, $sql), $this->link, $this->db_config['object'], $sql);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Rewind cached result
|
||||
$this->query_cache[$hash]->rewind();
|
||||
}
|
||||
return $this->query_cache[$hash];
|
||||
}
|
||||
|
||||
return $this->query_cache[$hash];
|
||||
}
|
||||
// Suppress warning triggered when a database error occurs (e.g., a constraint violation)
|
||||
return new Pgsql_Result(@pg_query($this->link, $sql), $this->link, $this->db_config['object'], $sql);
|
||||
}
|
||||
|
||||
// Suppress warning triggered when a database error occurs (e.g., a constraint violation)
|
||||
return new Pgsql_Result(@pg_query($this->link, $sql), $this->link, $this->db_config['object'], $sql);
|
||||
}
|
||||
public function set_charset($charset)
|
||||
{
|
||||
$this->query('SET client_encoding TO ' . pg_escape_string($this->link, $charset));
|
||||
}
|
||||
|
||||
public function set_charset($charset)
|
||||
{
|
||||
$this->query('SET client_encoding TO '.pg_escape_string($this->link, $charset));
|
||||
}
|
||||
public function escape_table($table)
|
||||
{
|
||||
if (!$this->db_config['escape']) {
|
||||
return $table;
|
||||
}
|
||||
|
||||
public function escape_table($table)
|
||||
{
|
||||
if (!$this->db_config['escape'])
|
||||
return $table;
|
||||
return '"' . str_replace('.', '"."', $table) . '"';
|
||||
}
|
||||
|
||||
return '"'.str_replace('.', '"."', $table).'"';
|
||||
}
|
||||
public function escape_column($column)
|
||||
{
|
||||
if (!$this->db_config['escape']) {
|
||||
return $column;
|
||||
}
|
||||
|
||||
public function escape_column($column)
|
||||
{
|
||||
if (!$this->db_config['escape'])
|
||||
return $column;
|
||||
if ($column == '*') {
|
||||
return $column;
|
||||
}
|
||||
|
||||
if ($column == '*')
|
||||
return $column;
|
||||
// This matches any functions we support to SELECT.
|
||||
if (preg_match('/(avg|count|sum|max|min)\(\s*(.*)\s*\)(\s*as\s*(.+)?)?/i', $column, $matches)) {
|
||||
if (count($matches) == 3) {
|
||||
return $matches[1] . '(' . $this->escape_column($matches[2]) . ')';
|
||||
} elseif (count($matches) == 5) {
|
||||
return $matches[1] . '(' . $this->escape_column($matches[2]) . ') AS ' . $this->escape_column($matches[2]);
|
||||
}
|
||||
}
|
||||
|
||||
// This matches any functions we support to SELECT.
|
||||
if ( preg_match('/(avg|count|sum|max|min)\(\s*(.*)\s*\)(\s*as\s*(.+)?)?/i', $column, $matches))
|
||||
{
|
||||
if ( count($matches) == 3)
|
||||
{
|
||||
return $matches[1].'('.$this->escape_column($matches[2]).')';
|
||||
}
|
||||
else if ( count($matches) == 5)
|
||||
{
|
||||
return $matches[1].'('.$this->escape_column($matches[2]).') AS '.$this->escape_column($matches[2]);
|
||||
}
|
||||
}
|
||||
// This matches any modifiers we support to SELECT.
|
||||
if (! preg_match('/\b(?:all|distinct)\s/i', $column)) {
|
||||
if (stripos($column, ' AS ') !== false) {
|
||||
// Force 'AS' to uppercase
|
||||
$column = str_ireplace(' AS ', ' AS ', $column);
|
||||
|
||||
// This matches any modifiers we support to SELECT.
|
||||
if ( ! preg_match('/\b(?:all|distinct)\s/i', $column))
|
||||
{
|
||||
if (stripos($column, ' AS ') !== FALSE)
|
||||
{
|
||||
// Force 'AS' to uppercase
|
||||
$column = str_ireplace(' AS ', ' AS ', $column);
|
||||
// Runs escape_column on both sides of an AS statement
|
||||
$column = array_map(array($this, __FUNCTION__), explode(' AS ', $column));
|
||||
|
||||
// Runs escape_column on both sides of an AS statement
|
||||
$column = array_map(array($this, __FUNCTION__), explode(' AS ', $column));
|
||||
// Re-create the AS statement
|
||||
return implode(' AS ', $column);
|
||||
}
|
||||
|
||||
// Re-create the AS statement
|
||||
return implode(' AS ', $column);
|
||||
}
|
||||
return preg_replace('/[^.*]+/', '"$0"', $column);
|
||||
}
|
||||
|
||||
return preg_replace('/[^.*]+/', '"$0"', $column);
|
||||
}
|
||||
$parts = explode(' ', $column);
|
||||
$column = '';
|
||||
|
||||
$parts = explode(' ', $column);
|
||||
$column = '';
|
||||
for ($i = 0, $c = count($parts); $i < $c; $i++) {
|
||||
// The column is always last
|
||||
if ($i == ($c - 1)) {
|
||||
$column .= preg_replace('/[^.*]+/', '"$0"', $parts[$i]);
|
||||
} else // otherwise, it's a modifier
|
||||
{
|
||||
$column .= $parts[$i] . ' ';
|
||||
}
|
||||
}
|
||||
return $column;
|
||||
}
|
||||
|
||||
for ($i = 0, $c = count($parts); $i < $c; $i++)
|
||||
{
|
||||
// The column is always last
|
||||
if ($i == ($c - 1))
|
||||
{
|
||||
$column .= preg_replace('/[^.*]+/', '"$0"', $parts[$i]);
|
||||
}
|
||||
else // otherwise, it's a modifier
|
||||
{
|
||||
$column .= $parts[$i].' ';
|
||||
}
|
||||
}
|
||||
return $column;
|
||||
}
|
||||
public function regex($field, $match, $type, $num_regexs)
|
||||
{
|
||||
$prefix = ($num_regexs == 0) ? '' : $type;
|
||||
|
||||
public function regex($field, $match, $type, $num_regexs)
|
||||
{
|
||||
$prefix = ($num_regexs == 0) ? '' : $type;
|
||||
return $prefix . ' ' . $this->escape_column($field) . ' ~* \'' . $this->escape_str($match) . '\'';
|
||||
}
|
||||
|
||||
return $prefix.' '.$this->escape_column($field).' ~* \''.$this->escape_str($match).'\'';
|
||||
}
|
||||
public function notregex($field, $match, $type, $num_regexs)
|
||||
{
|
||||
$prefix = $num_regexs == 0 ? '' : $type;
|
||||
|
||||
public function notregex($field, $match, $type, $num_regexs)
|
||||
{
|
||||
$prefix = $num_regexs == 0 ? '' : $type;
|
||||
return $prefix . ' ' . $this->escape_column($field) . ' !~* \'' . $this->escape_str($match) . '\'';
|
||||
}
|
||||
|
||||
return $prefix.' '.$this->escape_column($field).' !~* \''.$this->escape_str($match) . '\'';
|
||||
}
|
||||
public function limit($limit, $offset = 0)
|
||||
{
|
||||
return 'LIMIT ' . $limit . ' OFFSET ' . $offset;
|
||||
}
|
||||
|
||||
public function limit($limit, $offset = 0)
|
||||
{
|
||||
return 'LIMIT '.$limit.' OFFSET '.$offset;
|
||||
}
|
||||
public function compile_select($database)
|
||||
{
|
||||
$sql = ($database['distinct'] == true) ? 'SELECT DISTINCT ' : 'SELECT ';
|
||||
$sql .= (count($database['select']) > 0) ? implode(', ', $database['select']) : '*';
|
||||
|
||||
public function compile_select($database)
|
||||
{
|
||||
$sql = ($database['distinct'] == TRUE) ? 'SELECT DISTINCT ' : 'SELECT ';
|
||||
$sql .= (count($database['select']) > 0) ? implode(', ', $database['select']) : '*';
|
||||
if (count($database['from']) > 0) {
|
||||
$sql .= "\nFROM ";
|
||||
$sql .= implode(', ', $database['from']);
|
||||
}
|
||||
|
||||
if (count($database['from']) > 0)
|
||||
{
|
||||
$sql .= "\nFROM ";
|
||||
$sql .= implode(', ', $database['from']);
|
||||
}
|
||||
if (count($database['join']) > 0) {
|
||||
foreach ($database['join'] as $join) {
|
||||
$sql .= "\n" . $join['type'] . 'JOIN ' . implode(', ', $join['tables']) . ' ON ' . $join['conditions'];
|
||||
}
|
||||
}
|
||||
|
||||
if (count($database['join']) > 0)
|
||||
{
|
||||
foreach($database['join'] AS $join)
|
||||
{
|
||||
$sql .= "\n".$join['type'].'JOIN '.implode(', ', $join['tables']).' ON '.$join['conditions'];
|
||||
}
|
||||
}
|
||||
if (count($database['where']) > 0) {
|
||||
$sql .= "\nWHERE ";
|
||||
}
|
||||
|
||||
if (count($database['where']) > 0)
|
||||
{
|
||||
$sql .= "\nWHERE ";
|
||||
}
|
||||
$sql .= implode("\n", $database['where']);
|
||||
|
||||
$sql .= implode("\n", $database['where']);
|
||||
if (count($database['groupby']) > 0) {
|
||||
$sql .= "\nGROUP BY ";
|
||||
$sql .= implode(', ', $database['groupby']);
|
||||
}
|
||||
|
||||
if (count($database['groupby']) > 0)
|
||||
{
|
||||
$sql .= "\nGROUP BY ";
|
||||
$sql .= implode(', ', $database['groupby']);
|
||||
}
|
||||
if (count($database['having']) > 0) {
|
||||
$sql .= "\nHAVING ";
|
||||
$sql .= implode("\n", $database['having']);
|
||||
}
|
||||
|
||||
if (count($database['having']) > 0)
|
||||
{
|
||||
$sql .= "\nHAVING ";
|
||||
$sql .= implode("\n", $database['having']);
|
||||
}
|
||||
if (count($database['orderby']) > 0) {
|
||||
$sql .= "\nORDER BY ";
|
||||
$sql .= implode(', ', $database['orderby']);
|
||||
}
|
||||
|
||||
if (count($database['orderby']) > 0)
|
||||
{
|
||||
$sql .= "\nORDER BY ";
|
||||
$sql .= implode(', ', $database['orderby']);
|
||||
}
|
||||
if (is_numeric($database['limit'])) {
|
||||
$sql .= "\n";
|
||||
$sql .= $this->limit($database['limit'], $database['offset']);
|
||||
}
|
||||
|
||||
if (is_numeric($database['limit']))
|
||||
{
|
||||
$sql .= "\n";
|
||||
$sql .= $this->limit($database['limit'], $database['offset']);
|
||||
}
|
||||
return $sql;
|
||||
}
|
||||
|
||||
return $sql;
|
||||
}
|
||||
public function escape_str($str)
|
||||
{
|
||||
if (!$this->db_config['escape']) {
|
||||
return $str;
|
||||
}
|
||||
|
||||
public function escape_str($str)
|
||||
{
|
||||
if (!$this->db_config['escape'])
|
||||
return $str;
|
||||
is_resource($this->link) or $this->connect();
|
||||
|
||||
is_resource($this->link) or $this->connect();
|
||||
return pg_escape_string($this->link, $str);
|
||||
}
|
||||
|
||||
return pg_escape_string($this->link, $str);
|
||||
}
|
||||
public function list_tables()
|
||||
{
|
||||
$sql = 'SELECT table_schema || \'.\' || table_name FROM information_schema.tables WHERE table_schema NOT IN (\'pg_catalog\', \'information_schema\')';
|
||||
$result = $this->query($sql)->result(false, PGSQL_ASSOC);
|
||||
|
||||
public function list_tables()
|
||||
{
|
||||
$sql = 'SELECT table_schema || \'.\' || table_name FROM information_schema.tables WHERE table_schema NOT IN (\'pg_catalog\', \'information_schema\')';
|
||||
$result = $this->query($sql)->result(FALSE, PGSQL_ASSOC);
|
||||
$retval = array();
|
||||
foreach ($result as $row) {
|
||||
$retval[] = current($row);
|
||||
}
|
||||
|
||||
$retval = array();
|
||||
foreach ($result as $row)
|
||||
{
|
||||
$retval[] = current($row);
|
||||
}
|
||||
return $retval;
|
||||
}
|
||||
|
||||
return $retval;
|
||||
}
|
||||
public function show_error()
|
||||
{
|
||||
return pg_last_error($this->link);
|
||||
}
|
||||
|
||||
public function show_error()
|
||||
{
|
||||
return pg_last_error($this->link);
|
||||
}
|
||||
public function list_fields($table)
|
||||
{
|
||||
$result = null;
|
||||
|
||||
public function list_fields($table)
|
||||
{
|
||||
$result = NULL;
|
||||
foreach ($this->field_data($table) as $row) {
|
||||
// Make an associative array
|
||||
$result[$row->column_name] = $this->sql_type($row->data_type);
|
||||
|
||||
foreach ($this->field_data($table) as $row)
|
||||
{
|
||||
// Make an associative array
|
||||
$result[$row->column_name] = $this->sql_type($row->data_type);
|
||||
if (!strncmp($row->column_default, 'nextval(', 8)) {
|
||||
$result[$row->column_name]['sequenced'] = true;
|
||||
}
|
||||
|
||||
if (!strncmp($row->column_default, 'nextval(', 8))
|
||||
{
|
||||
$result[$row->column_name]['sequenced'] = TRUE;
|
||||
}
|
||||
if ($row->is_nullable === 'YES') {
|
||||
$result[$row->column_name]['null'] = true;
|
||||
}
|
||||
}
|
||||
|
||||
if ($row->is_nullable === 'YES')
|
||||
{
|
||||
$result[$row->column_name]['null'] = TRUE;
|
||||
}
|
||||
}
|
||||
if (!isset($result)) {
|
||||
throw new Kohana_Database_Exception('database.table_not_found', $table);
|
||||
}
|
||||
|
||||
if (!isset($result))
|
||||
throw new Kohana_Database_Exception('database.table_not_found', $table);
|
||||
return $result;
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
public function field_data($table)
|
||||
{
|
||||
// http://www.postgresql.org/docs/8.3/static/infoschema-columns.html
|
||||
$result = $this->query('
|
||||
public function field_data($table)
|
||||
{
|
||||
// http://www.postgresql.org/docs/8.3/static/infoschema-columns.html
|
||||
$result = $this->query('
|
||||
SELECT column_name, column_default, is_nullable, data_type, udt_name,
|
||||
character_maximum_length, numeric_precision, numeric_precision_radix, numeric_scale
|
||||
FROM information_schema.columns
|
||||
WHERE table_name = \''. $this->escape_str($table) .'\'
|
||||
WHERE table_name = \'' . $this->escape_str($table) . '\'
|
||||
ORDER BY ordinal_position
|
||||
');
|
||||
|
||||
return $result->result_array(TRUE);
|
||||
}
|
||||
|
||||
} // End Database_Pgsql_Driver Class
|
||||
return $result->result_array(true);
|
||||
}
|
||||
}
|
||||
// End Database_Pgsql_Driver Class
|
||||
|
||||
/**
|
||||
* PostgreSQL Result
|
||||
*/
|
||||
class Pgsql_Result extends Database_Result {
|
||||
class Pgsql_Result extends Database_Result
|
||||
{
|
||||
// Data fetching types
|
||||
protected $fetch_type = 'pgsql_fetch_object';
|
||||
protected $return_type = PGSQL_ASSOC;
|
||||
|
||||
// Data fetching types
|
||||
protected $fetch_type = 'pgsql_fetch_object';
|
||||
protected $return_type = PGSQL_ASSOC;
|
||||
/**
|
||||
* Sets up the result variables.
|
||||
*
|
||||
* @param resource query result
|
||||
* @param resource database link
|
||||
* @param boolean return objects or arrays
|
||||
* @param string SQL query that was run
|
||||
*/
|
||||
public function __construct($result, $link, $object = true, $sql = '')
|
||||
{
|
||||
$this->link = $link;
|
||||
$this->result = $result;
|
||||
|
||||
/**
|
||||
* Sets up the result variables.
|
||||
*
|
||||
* @param resource query result
|
||||
* @param resource database link
|
||||
* @param boolean return objects or arrays
|
||||
* @param string SQL query that was run
|
||||
*/
|
||||
public function __construct($result, $link, $object = TRUE, $sql)
|
||||
{
|
||||
$this->link = $link;
|
||||
$this->result = $result;
|
||||
// If the query is a resource, it was a SELECT, SHOW, DESCRIBE, EXPLAIN query
|
||||
if (is_resource($result)) {
|
||||
// Its an DELETE, INSERT, REPLACE, or UPDATE query
|
||||
if (preg_match('/^(?:delete|insert|replace|update)\b/iD', trim($sql), $matches)) {
|
||||
$this->insert_id = (strtolower($matches[0]) == 'insert') ? $this->insert_id() : false;
|
||||
$this->total_rows = pg_affected_rows($this->result);
|
||||
} else {
|
||||
$this->current_row = 0;
|
||||
$this->total_rows = pg_num_rows($this->result);
|
||||
$this->fetch_type = ($object === true) ? 'pg_fetch_object' : 'pg_fetch_array';
|
||||
}
|
||||
} else {
|
||||
throw new Kohana_Database_Exception('database.error', pg_last_error() . ' - ' . $sql);
|
||||
}
|
||||
|
||||
// If the query is a resource, it was a SELECT, SHOW, DESCRIBE, EXPLAIN query
|
||||
if (is_resource($result))
|
||||
{
|
||||
// Its an DELETE, INSERT, REPLACE, or UPDATE query
|
||||
if (preg_match('/^(?:delete|insert|replace|update)\b/iD', trim($sql), $matches))
|
||||
{
|
||||
$this->insert_id = (strtolower($matches[0]) == 'insert') ? $this->insert_id() : FALSE;
|
||||
$this->total_rows = pg_affected_rows($this->result);
|
||||
}
|
||||
else
|
||||
{
|
||||
$this->current_row = 0;
|
||||
$this->total_rows = pg_num_rows($this->result);
|
||||
$this->fetch_type = ($object === TRUE) ? 'pg_fetch_object' : 'pg_fetch_array';
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new Kohana_Database_Exception('database.error', pg_last_error().' - '.$sql);
|
||||
}
|
||||
// Set result type
|
||||
$this->result($object);
|
||||
|
||||
// Set result type
|
||||
$this->result($object);
|
||||
// Store the SQL
|
||||
$this->sql = $sql;
|
||||
}
|
||||
|
||||
// Store the SQL
|
||||
$this->sql = $sql;
|
||||
}
|
||||
/**
|
||||
* Magic __destruct function, frees the result.
|
||||
*/
|
||||
public function __destruct()
|
||||
{
|
||||
if (is_resource($this->result)) {
|
||||
pg_free_result($this->result);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Magic __destruct function, frees the result.
|
||||
*/
|
||||
public function __destruct()
|
||||
{
|
||||
if (is_resource($this->result))
|
||||
{
|
||||
pg_free_result($this->result);
|
||||
}
|
||||
}
|
||||
public function result($object = true, $type = PGSQL_ASSOC)
|
||||
{
|
||||
$this->fetch_type = ((bool) $object) ? 'pg_fetch_object' : 'pg_fetch_array';
|
||||
|
||||
public function result($object = TRUE, $type = PGSQL_ASSOC)
|
||||
{
|
||||
$this->fetch_type = ((bool) $object) ? 'pg_fetch_object' : 'pg_fetch_array';
|
||||
// This check has to be outside the previous statement, because we do not
|
||||
// know the state of fetch_type when $object = NULL
|
||||
// NOTE - The class set by $type must be defined before fetching the result,
|
||||
// autoloading is disabled to save a lot of stupid overhead.
|
||||
if ($this->fetch_type == 'pg_fetch_object') {
|
||||
$this->return_type = (is_string($type) and Kohana::auto_load($type)) ? $type : 'stdClass';
|
||||
} else {
|
||||
$this->return_type = $type;
|
||||
}
|
||||
|
||||
// This check has to be outside the previous statement, because we do not
|
||||
// know the state of fetch_type when $object = NULL
|
||||
// NOTE - The class set by $type must be defined before fetching the result,
|
||||
// autoloading is disabled to save a lot of stupid overhead.
|
||||
if ($this->fetch_type == 'pg_fetch_object')
|
||||
{
|
||||
$this->return_type = (is_string($type) AND Kohana::auto_load($type)) ? $type : 'stdClass';
|
||||
}
|
||||
else
|
||||
{
|
||||
$this->return_type = $type;
|
||||
}
|
||||
return $this;
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
public function as_array($object = null, $type = PGSQL_ASSOC)
|
||||
{
|
||||
return $this->result_array($object, $type);
|
||||
}
|
||||
|
||||
public function as_array($object = NULL, $type = PGSQL_ASSOC)
|
||||
{
|
||||
return $this->result_array($object, $type);
|
||||
}
|
||||
public function result_array($object = null, $type = PGSQL_ASSOC)
|
||||
{
|
||||
$rows = array();
|
||||
|
||||
public function result_array($object = NULL, $type = PGSQL_ASSOC)
|
||||
{
|
||||
$rows = array();
|
||||
if (is_string($object)) {
|
||||
$fetch = $object;
|
||||
} elseif (is_bool($object)) {
|
||||
if ($object === true) {
|
||||
$fetch = 'pg_fetch_object';
|
||||
|
||||
if (is_string($object))
|
||||
{
|
||||
$fetch = $object;
|
||||
}
|
||||
elseif (is_bool($object))
|
||||
{
|
||||
if ($object === TRUE)
|
||||
{
|
||||
$fetch = 'pg_fetch_object';
|
||||
// NOTE - The class set by $type must be defined before fetching the result,
|
||||
// autoloading is disabled to save a lot of stupid overhead.
|
||||
$type = (is_string($type) and Kohana::auto_load($type)) ? $type : 'stdClass';
|
||||
} else {
|
||||
$fetch = 'pg_fetch_array';
|
||||
}
|
||||
} else {
|
||||
// Use the default config values
|
||||
$fetch = $this->fetch_type;
|
||||
|
||||
// NOTE - The class set by $type must be defined before fetching the result,
|
||||
// autoloading is disabled to save a lot of stupid overhead.
|
||||
$type = (is_string($type) AND Kohana::auto_load($type)) ? $type : 'stdClass';
|
||||
}
|
||||
else
|
||||
{
|
||||
$fetch = 'pg_fetch_array';
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Use the default config values
|
||||
$fetch = $this->fetch_type;
|
||||
if ($fetch == 'pg_fetch_object') {
|
||||
$type = (is_string($type) and Kohana::auto_load($type)) ? $type : 'stdClass';
|
||||
}
|
||||
}
|
||||
|
||||
if ($fetch == 'pg_fetch_object')
|
||||
{
|
||||
$type = (is_string($type) AND Kohana::auto_load($type)) ? $type : 'stdClass';
|
||||
}
|
||||
}
|
||||
if ($this->total_rows) {
|
||||
pg_result_seek($this->result, 0);
|
||||
|
||||
if ($this->total_rows)
|
||||
{
|
||||
pg_result_seek($this->result, 0);
|
||||
while ($row = $fetch($this->result, null, $type)) {
|
||||
$rows[] = $row;
|
||||
}
|
||||
}
|
||||
|
||||
while ($row = $fetch($this->result, NULL, $type))
|
||||
{
|
||||
$rows[] = $row;
|
||||
}
|
||||
}
|
||||
return $rows;
|
||||
}
|
||||
|
||||
return $rows;
|
||||
}
|
||||
public function insert_id()
|
||||
{
|
||||
if ($this->insert_id === null) {
|
||||
$query = 'SELECT LASTVAL() AS insert_id';
|
||||
|
||||
public function insert_id()
|
||||
{
|
||||
if ($this->insert_id === NULL)
|
||||
{
|
||||
$query = 'SELECT LASTVAL() AS insert_id';
|
||||
// Disable error reporting for this, just to silence errors on
|
||||
// tables that have no serial column.
|
||||
$ER = error_reporting(0);
|
||||
|
||||
// Disable error reporting for this, just to silence errors on
|
||||
// tables that have no serial column.
|
||||
$ER = error_reporting(0);
|
||||
$result = pg_query($this->link, $query);
|
||||
$insert_id = pg_fetch_array($result, null, PGSQL_ASSOC);
|
||||
|
||||
$result = pg_query($this->link, $query);
|
||||
$insert_id = pg_fetch_array($result, NULL, PGSQL_ASSOC);
|
||||
$this->insert_id = $insert_id['insert_id'];
|
||||
|
||||
$this->insert_id = $insert_id['insert_id'];
|
||||
// Reset error reporting
|
||||
error_reporting($ER);
|
||||
}
|
||||
|
||||
// Reset error reporting
|
||||
error_reporting($ER);
|
||||
}
|
||||
return $this->insert_id;
|
||||
}
|
||||
|
||||
return $this->insert_id;
|
||||
}
|
||||
public function seek($offset)
|
||||
{
|
||||
if ($this->offsetExists($offset) and pg_result_seek($this->result, $offset)) {
|
||||
// Set the current row to the offset
|
||||
$this->current_row = $offset;
|
||||
|
||||
public function seek($offset)
|
||||
{
|
||||
if ($this->offsetExists($offset) AND pg_result_seek($this->result, $offset))
|
||||
{
|
||||
// Set the current row to the offset
|
||||
$this->current_row = $offset;
|
||||
return true;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
public function list_fields()
|
||||
{
|
||||
$field_names = array();
|
||||
|
||||
public function list_fields()
|
||||
{
|
||||
$field_names = array();
|
||||
$fields = pg_num_fields($this->result);
|
||||
for ($i = 0; $i < $fields; ++$i) {
|
||||
$field_names[] = pg_field_name($this->result, $i);
|
||||
}
|
||||
|
||||
$fields = pg_num_fields($this->result);
|
||||
for ($i = 0; $i < $fields; ++$i)
|
||||
{
|
||||
$field_names[] = pg_field_name($this->result, $i);
|
||||
}
|
||||
return $field_names;
|
||||
}
|
||||
|
||||
return $field_names;
|
||||
}
|
||||
/**
|
||||
* ArrayAccess: offsetGet
|
||||
*/
|
||||
public function offsetGet($offset)
|
||||
{
|
||||
if (! $this->seek($offset)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* ArrayAccess: offsetGet
|
||||
*/
|
||||
public function offsetGet($offset)
|
||||
{
|
||||
if ( ! $this->seek($offset))
|
||||
return FALSE;
|
||||
|
||||
// Return the row by calling the defined fetching callback
|
||||
$fetch = $this->fetch_type;
|
||||
return $fetch($this->result, NULL, $this->return_type);
|
||||
}
|
||||
|
||||
} // End Pgsql_Result Class
|
||||
// Return the row by calling the defined fetching callback
|
||||
$fetch = $this->fetch_type;
|
||||
return $fetch($this->result, null, $this->return_type);
|
||||
}
|
||||
}
|
||||
// End Pgsql_Result Class
|
||||
|
||||
/**
|
||||
* PostgreSQL Prepared Statement (experimental)
|
||||
*/
|
||||
class Kohana_Pgsql_Statement {
|
||||
class Kohana_Pgsql_Statement
|
||||
{
|
||||
protected $link = null;
|
||||
protected $stmt;
|
||||
|
||||
protected $link = NULL;
|
||||
protected $stmt;
|
||||
public function __construct($sql, $link)
|
||||
{
|
||||
$this->link = $link;
|
||||
|
||||
public function __construct($sql, $link)
|
||||
{
|
||||
$this->link = $link;
|
||||
$this->stmt = $this->link->prepare($sql);
|
||||
|
||||
$this->stmt = $this->link->prepare($sql);
|
||||
return $this;
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
public function __destruct()
|
||||
{
|
||||
$this->stmt->close();
|
||||
}
|
||||
|
||||
public function __destruct()
|
||||
{
|
||||
$this->stmt->close();
|
||||
}
|
||||
// Sets the bind parameters
|
||||
public function bind_params()
|
||||
{
|
||||
$argv = func_get_args();
|
||||
return $this;
|
||||
}
|
||||
|
||||
// Sets the bind parameters
|
||||
public function bind_params()
|
||||
{
|
||||
$argv = func_get_args();
|
||||
return $this;
|
||||
}
|
||||
// sets the statement values to the bound parameters
|
||||
public function set_vals()
|
||||
{
|
||||
return $this;
|
||||
}
|
||||
|
||||
// sets the statement values to the bound parameters
|
||||
public function set_vals()
|
||||
{
|
||||
return $this;
|
||||
}
|
||||
|
||||
// Runs the statement
|
||||
public function execute()
|
||||
{
|
||||
return $this;
|
||||
}
|
||||
// Runs the statement
|
||||
public function execute()
|
||||
{
|
||||
return $this;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,12 @@
|
||||
<?php defined('SYSPATH') OR die('No direct access allowed.');
|
||||
<?php
|
||||
|
||||
// phpcs:disable PSR1.Classes.ClassDeclaration.MissingNamespace
|
||||
// phpcs:disable PSR1.Files.SideEffects
|
||||
defined('SYSPATH') or die('No direct access allowed.');
|
||||
// phpcs:enable PSR1.Files.SideEffects
|
||||
// phpcs:disable Squiz.Classes.ValidClassName.NotCamelCaps
|
||||
|
||||
|
||||
/**
|
||||
* Image API driver.
|
||||
*
|
||||
@@ -9,141 +17,131 @@
|
||||
* @copyright (c) 2007-2008 Kohana Team
|
||||
* @license http://kohanaphp.com/license.html
|
||||
*/
|
||||
abstract class Image_Driver {
|
||||
abstract class Image_Driver
|
||||
{
|
||||
// Reference to the current image
|
||||
protected $image;
|
||||
|
||||
// Reference to the current image
|
||||
protected $image;
|
||||
// Reference to the temporary processing image
|
||||
protected $tmp_image;
|
||||
|
||||
// Reference to the temporary processing image
|
||||
protected $tmp_image;
|
||||
// Processing errors
|
||||
protected $errors = array();
|
||||
|
||||
// Processing errors
|
||||
protected $errors = array();
|
||||
/**
|
||||
* Executes a set of actions, defined in pairs.
|
||||
*
|
||||
* @param array actions
|
||||
* @return boolean
|
||||
*/
|
||||
public function execute($actions)
|
||||
{
|
||||
foreach ($actions as $func => $args) {
|
||||
if (! $this->$func($args)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Executes a set of actions, defined in pairs.
|
||||
*
|
||||
* @param array actions
|
||||
* @return boolean
|
||||
*/
|
||||
public function execute($actions)
|
||||
{
|
||||
foreach ($actions as $func => $args)
|
||||
{
|
||||
if ( ! $this->$func($args))
|
||||
return FALSE;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
/**
|
||||
* Sanitize and normalize a geometry array based on the temporary image
|
||||
* width and height. Valid properties are: width, height, top, left.
|
||||
*
|
||||
* @param array geometry properties
|
||||
* @return void
|
||||
*/
|
||||
protected function sanitize_geometry(&$geometry)
|
||||
{
|
||||
list($width, $height) = $this->properties();
|
||||
|
||||
/**
|
||||
* Sanitize and normalize a geometry array based on the temporary image
|
||||
* width and height. Valid properties are: width, height, top, left.
|
||||
*
|
||||
* @param array geometry properties
|
||||
* @return void
|
||||
*/
|
||||
protected function sanitize_geometry( & $geometry)
|
||||
{
|
||||
list($width, $height) = $this->properties();
|
||||
// Turn off error reporting
|
||||
$reporting = error_reporting(0);
|
||||
|
||||
// Turn off error reporting
|
||||
$reporting = error_reporting(0);
|
||||
// Width and height cannot exceed current image size
|
||||
$geometry['width'] = min($geometry['width'], $width);
|
||||
$geometry['height'] = min($geometry['height'], $height);
|
||||
|
||||
// Width and height cannot exceed current image size
|
||||
$geometry['width'] = min($geometry['width'], $width);
|
||||
$geometry['height'] = min($geometry['height'], $height);
|
||||
// Set standard coordinates if given, otherwise use pixel values
|
||||
if ($geometry['top'] === 'center') {
|
||||
$geometry['top'] = floor(($height / 2) - ($geometry['height'] / 2));
|
||||
} elseif ($geometry['top'] === 'top') {
|
||||
$geometry['top'] = 0;
|
||||
} elseif ($geometry['top'] === 'bottom') {
|
||||
$geometry['top'] = $height - $geometry['height'];
|
||||
}
|
||||
|
||||
// Set standard coordinates if given, otherwise use pixel values
|
||||
if ($geometry['top'] === 'center')
|
||||
{
|
||||
$geometry['top'] = floor(($height / 2) - ($geometry['height'] / 2));
|
||||
}
|
||||
elseif ($geometry['top'] === 'top')
|
||||
{
|
||||
$geometry['top'] = 0;
|
||||
}
|
||||
elseif ($geometry['top'] === 'bottom')
|
||||
{
|
||||
$geometry['top'] = $height - $geometry['height'];
|
||||
}
|
||||
// Set standard coordinates if given, otherwise use pixel values
|
||||
if ($geometry['left'] === 'center') {
|
||||
$geometry['left'] = floor(($width / 2) - ($geometry['width'] / 2));
|
||||
} elseif ($geometry['left'] === 'left') {
|
||||
$geometry['left'] = 0;
|
||||
} elseif ($geometry['left'] === 'right') {
|
||||
$geometry['left'] = $width - $geometry['height'];
|
||||
}
|
||||
|
||||
// Set standard coordinates if given, otherwise use pixel values
|
||||
if ($geometry['left'] === 'center')
|
||||
{
|
||||
$geometry['left'] = floor(($width / 2) - ($geometry['width'] / 2));
|
||||
}
|
||||
elseif ($geometry['left'] === 'left')
|
||||
{
|
||||
$geometry['left'] = 0;
|
||||
}
|
||||
elseif ($geometry['left'] === 'right')
|
||||
{
|
||||
$geometry['left'] = $width - $geometry['height'];
|
||||
}
|
||||
// Restore error reporting
|
||||
error_reporting($reporting);
|
||||
}
|
||||
|
||||
// Restore error reporting
|
||||
error_reporting($reporting);
|
||||
}
|
||||
/**
|
||||
* Return the current width and height of the temporary image. This is mainly
|
||||
* needed for sanitizing the geometry.
|
||||
*
|
||||
* @return array width, height
|
||||
*/
|
||||
abstract protected function properties();
|
||||
|
||||
/**
|
||||
* Return the current width and height of the temporary image. This is mainly
|
||||
* needed for sanitizing the geometry.
|
||||
*
|
||||
* @return array width, height
|
||||
*/
|
||||
abstract protected function properties();
|
||||
/**
|
||||
* Process an image with a set of actions.
|
||||
*
|
||||
* @param string image filename
|
||||
* @param array actions to execute
|
||||
* @param string destination directory path
|
||||
* @param string destination filename
|
||||
* @return boolean
|
||||
*/
|
||||
abstract public function process($image, $actions, $dir, $file);
|
||||
|
||||
/**
|
||||
* Process an image with a set of actions.
|
||||
*
|
||||
* @param string image filename
|
||||
* @param array actions to execute
|
||||
* @param string destination directory path
|
||||
* @param string destination filename
|
||||
* @return boolean
|
||||
*/
|
||||
abstract public function process($image, $actions, $dir, $file);
|
||||
/**
|
||||
* Flip an image. Valid directions are horizontal and vertical.
|
||||
*
|
||||
* @param integer direction to flip
|
||||
* @return boolean
|
||||
*/
|
||||
abstract public function flip($direction);
|
||||
|
||||
/**
|
||||
* Flip an image. Valid directions are horizontal and vertical.
|
||||
*
|
||||
* @param integer direction to flip
|
||||
* @return boolean
|
||||
*/
|
||||
abstract function flip($direction);
|
||||
/**
|
||||
* Crop an image. Valid properties are: width, height, top, left.
|
||||
*
|
||||
* @param array new properties
|
||||
* @return boolean
|
||||
*/
|
||||
abstract public function crop($properties);
|
||||
|
||||
/**
|
||||
* Crop an image. Valid properties are: width, height, top, left.
|
||||
*
|
||||
* @param array new properties
|
||||
* @return boolean
|
||||
*/
|
||||
abstract function crop($properties);
|
||||
/**
|
||||
* Resize an image. Valid properties are: width, height, and master.
|
||||
*
|
||||
* @param array new properties
|
||||
* @return boolean
|
||||
*/
|
||||
abstract public function resize($properties);
|
||||
|
||||
/**
|
||||
* Resize an image. Valid properties are: width, height, and master.
|
||||
*
|
||||
* @param array new properties
|
||||
* @return boolean
|
||||
*/
|
||||
abstract public function resize($properties);
|
||||
/**
|
||||
* Rotate an image. Valid amounts are -180 to 180.
|
||||
*
|
||||
* @param integer amount to rotate
|
||||
* @return boolean
|
||||
*/
|
||||
abstract public function rotate($amount);
|
||||
|
||||
/**
|
||||
* Rotate an image. Valid amounts are -180 to 180.
|
||||
*
|
||||
* @param integer amount to rotate
|
||||
* @return boolean
|
||||
*/
|
||||
abstract public function rotate($amount);
|
||||
|
||||
/**
|
||||
* Sharpen and image. Valid amounts are 1 to 100.
|
||||
*
|
||||
* @param integer amount to sharpen
|
||||
* @return boolean
|
||||
*/
|
||||
abstract public function sharpen($amount);
|
||||
|
||||
} // End Image Driver
|
||||
/**
|
||||
* Sharpen and image. Valid amounts are 1 to 100.
|
||||
*
|
||||
* @param integer amount to sharpen
|
||||
* @return boolean
|
||||
*/
|
||||
abstract public function sharpen($amount);
|
||||
}
|
||||
// End Image Driver
|
||||
|
||||
@@ -1,4 +1,12 @@
|
||||
<?php defined('SYSPATH') OR die('No direct access allowed.');
|
||||
<?php
|
||||
|
||||
// phpcs:disable PSR1.Classes.ClassDeclaration.MissingNamespace
|
||||
// phpcs:disable PSR1.Files.SideEffects
|
||||
defined('SYSPATH') or die('No direct access allowed.');
|
||||
// phpcs:enable PSR1.Files.SideEffects
|
||||
// phpcs:disable Squiz.Classes.ValidClassName.NotCamelCaps
|
||||
|
||||
|
||||
/**
|
||||
* GD Image Driver.
|
||||
*
|
||||
@@ -9,371 +17,347 @@
|
||||
* @copyright (c) 2007-2008 Kohana Team
|
||||
* @license http://kohanaphp.com/license.html
|
||||
*/
|
||||
class Image_GD_Driver extends Image_Driver {
|
||||
class Image_GD_Driver extends Image_Driver
|
||||
{
|
||||
// A transparent PNG as a string
|
||||
protected static $blank_png;
|
||||
protected static $blank_png_width;
|
||||
protected static $blank_png_height;
|
||||
|
||||
// A transparent PNG as a string
|
||||
protected static $blank_png;
|
||||
protected static $blank_png_width;
|
||||
protected static $blank_png_height;
|
||||
public function __construct()
|
||||
{
|
||||
// Make sure that GD2 is available
|
||||
if (! function_exists('gd_info')) {
|
||||
throw new Kohana_Exception('image.gd.requires_v2');
|
||||
}
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
// Make sure that GD2 is available
|
||||
if ( ! function_exists('gd_info'))
|
||||
throw new Kohana_Exception('image.gd.requires_v2');
|
||||
// Get the GD information
|
||||
$info = gd_info();
|
||||
|
||||
// Get the GD information
|
||||
$info = gd_info();
|
||||
// Make sure that the GD2 is installed
|
||||
if (strpos($info['GD Version'], '2.') === false) {
|
||||
throw new Kohana_Exception('image.gd.requires_v2');
|
||||
}
|
||||
}
|
||||
|
||||
// Make sure that the GD2 is installed
|
||||
if (strpos($info['GD Version'], '2.') === FALSE)
|
||||
throw new Kohana_Exception('image.gd.requires_v2');
|
||||
}
|
||||
public function process($image, $actions, $dir, $file, $render = false)
|
||||
{
|
||||
// Set the "create" function
|
||||
switch ($image['type']) {
|
||||
case IMAGETYPE_JPEG:
|
||||
$create = 'imagecreatefromjpeg';
|
||||
break;
|
||||
case IMAGETYPE_GIF:
|
||||
$create = 'imagecreatefromgif';
|
||||
break;
|
||||
case IMAGETYPE_PNG:
|
||||
$create = 'imagecreatefrompng';
|
||||
break;
|
||||
}
|
||||
|
||||
public function process($image, $actions, $dir, $file, $render = FALSE)
|
||||
{
|
||||
// Set the "create" function
|
||||
switch ($image['type'])
|
||||
{
|
||||
case IMAGETYPE_JPEG:
|
||||
$create = 'imagecreatefromjpeg';
|
||||
break;
|
||||
case IMAGETYPE_GIF:
|
||||
$create = 'imagecreatefromgif';
|
||||
break;
|
||||
case IMAGETYPE_PNG:
|
||||
$create = 'imagecreatefrompng';
|
||||
break;
|
||||
}
|
||||
// Set the "save" function
|
||||
switch (strtolower(substr(strrchr($file, '.'), 1))) {
|
||||
case 'jpg':
|
||||
case 'jpeg':
|
||||
$save = 'imagejpeg';
|
||||
break;
|
||||
case 'gif':
|
||||
$save = 'imagegif';
|
||||
break;
|
||||
case 'png':
|
||||
$save = 'imagepng';
|
||||
break;
|
||||
}
|
||||
|
||||
// Set the "save" function
|
||||
switch (strtolower(substr(strrchr($file, '.'), 1)))
|
||||
{
|
||||
case 'jpg':
|
||||
case 'jpeg':
|
||||
$save = 'imagejpeg';
|
||||
break;
|
||||
case 'gif':
|
||||
$save = 'imagegif';
|
||||
break;
|
||||
case 'png':
|
||||
$save = 'imagepng';
|
||||
break;
|
||||
}
|
||||
// Make sure the image type is supported for import
|
||||
if (empty($create) or ! function_exists($create)) {
|
||||
throw new Kohana_Exception('image.type_not_allowed', $image['file']);
|
||||
}
|
||||
|
||||
// Make sure the image type is supported for import
|
||||
if (empty($create) OR ! function_exists($create))
|
||||
throw new Kohana_Exception('image.type_not_allowed', $image['file']);
|
||||
// Make sure the image type is supported for saving
|
||||
if (empty($save) or ! function_exists($save)) {
|
||||
throw new Kohana_Exception('image.type_not_allowed', $dir . $file);
|
||||
}
|
||||
|
||||
// Make sure the image type is supported for saving
|
||||
if (empty($save) OR ! function_exists($save))
|
||||
throw new Kohana_Exception('image.type_not_allowed', $dir.$file);
|
||||
// Load the image
|
||||
$this->image = $image;
|
||||
|
||||
// Load the image
|
||||
$this->image = $image;
|
||||
// Create the GD image resource
|
||||
$this->tmp_image = $create($image['file']);
|
||||
|
||||
// Create the GD image resource
|
||||
$this->tmp_image = $create($image['file']);
|
||||
// Get the quality setting from the actions
|
||||
$quality = arr::remove('quality', $actions);
|
||||
|
||||
// Get the quality setting from the actions
|
||||
$quality = arr::remove('quality', $actions);
|
||||
if ($status = $this->execute($actions)) {
|
||||
// Prevent the alpha from being lost
|
||||
imagealphablending($this->tmp_image, true);
|
||||
imagesavealpha($this->tmp_image, true);
|
||||
|
||||
if ($status = $this->execute($actions))
|
||||
{
|
||||
// Prevent the alpha from being lost
|
||||
imagealphablending($this->tmp_image, TRUE);
|
||||
imagesavealpha($this->tmp_image, TRUE);
|
||||
switch ($save) {
|
||||
case 'imagejpeg':
|
||||
// Default the quality to 95
|
||||
($quality === null) and $quality = 95;
|
||||
break;
|
||||
case 'imagegif':
|
||||
// Remove the quality setting, GIF doesn't use it
|
||||
unset($quality);
|
||||
break;
|
||||
case 'imagepng':
|
||||
// Always use a compression level of 9 for PNGs. This does not
|
||||
// affect quality, it only increases the level of compression!
|
||||
$quality = 9;
|
||||
break;
|
||||
}
|
||||
|
||||
switch ($save)
|
||||
{
|
||||
case 'imagejpeg':
|
||||
// Default the quality to 95
|
||||
($quality === NULL) and $quality = 95;
|
||||
break;
|
||||
case 'imagegif':
|
||||
// Remove the quality setting, GIF doesn't use it
|
||||
unset($quality);
|
||||
break;
|
||||
case 'imagepng':
|
||||
// Always use a compression level of 9 for PNGs. This does not
|
||||
// affect quality, it only increases the level of compression!
|
||||
$quality = 9;
|
||||
break;
|
||||
}
|
||||
if ($render === false) {
|
||||
// Set the status to the save return value, saving with the quality requested
|
||||
$status = isset($quality) ? $save($this->tmp_image, $dir . $file, $quality) : $save($this->tmp_image, $dir . $file);
|
||||
} else {
|
||||
// Output the image directly to the browser
|
||||
switch ($save) {
|
||||
case 'imagejpeg':
|
||||
header('Content-Type: image/jpeg');
|
||||
break;
|
||||
case 'imagegif':
|
||||
header('Content-Type: image/gif');
|
||||
break;
|
||||
case 'imagepng':
|
||||
header('Content-Type: image/png');
|
||||
break;
|
||||
}
|
||||
|
||||
if ($render === FALSE)
|
||||
{
|
||||
// Set the status to the save return value, saving with the quality requested
|
||||
$status = isset($quality) ? $save($this->tmp_image, $dir.$file, $quality) : $save($this->tmp_image, $dir.$file);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Output the image directly to the browser
|
||||
switch ($save)
|
||||
{
|
||||
case 'imagejpeg':
|
||||
header('Content-Type: image/jpeg');
|
||||
break;
|
||||
case 'imagegif':
|
||||
header('Content-Type: image/gif');
|
||||
break;
|
||||
case 'imagepng':
|
||||
header('Content-Type: image/png');
|
||||
break;
|
||||
}
|
||||
$status = isset($quality) ? $save($this->tmp_image, null, $quality) : $save($this->tmp_image);
|
||||
}
|
||||
|
||||
$status = isset($quality) ? $save($this->tmp_image, NULL, $quality) : $save($this->tmp_image);
|
||||
}
|
||||
// Destroy the temporary image
|
||||
imagedestroy($this->tmp_image);
|
||||
}
|
||||
|
||||
// Destroy the temporary image
|
||||
imagedestroy($this->tmp_image);
|
||||
}
|
||||
return $status;
|
||||
}
|
||||
|
||||
return $status;
|
||||
}
|
||||
public function flip($direction)
|
||||
{
|
||||
// Get the current width and height
|
||||
$width = imagesx($this->tmp_image);
|
||||
$height = imagesy($this->tmp_image);
|
||||
|
||||
public function flip($direction)
|
||||
{
|
||||
// Get the current width and height
|
||||
$width = imagesx($this->tmp_image);
|
||||
$height = imagesy($this->tmp_image);
|
||||
// Create the flipped image
|
||||
$flipped = $this->imagecreatetransparent($width, $height);
|
||||
|
||||
// Create the flipped image
|
||||
$flipped = $this->imagecreatetransparent($width, $height);
|
||||
if ($direction === Image::HORIZONTAL) {
|
||||
for ($x = 0; $x < $width; $x++) {
|
||||
$status = imagecopy($flipped, $this->tmp_image, $x, 0, $width - $x - 1, 0, 1, $height);
|
||||
}
|
||||
} elseif ($direction === Image::VERTICAL) {
|
||||
for ($y = 0; $y < $height; $y++) {
|
||||
$status = imagecopy($flipped, $this->tmp_image, 0, $y, 0, $height - $y - 1, $width, 1);
|
||||
}
|
||||
} else {
|
||||
// Do nothing
|
||||
return true;
|
||||
}
|
||||
|
||||
if ($direction === Image::HORIZONTAL)
|
||||
{
|
||||
for ($x = 0; $x < $width; $x++)
|
||||
{
|
||||
$status = imagecopy($flipped, $this->tmp_image, $x, 0, $width - $x - 1, 0, 1, $height);
|
||||
}
|
||||
}
|
||||
elseif ($direction === Image::VERTICAL)
|
||||
{
|
||||
for ($y = 0; $y < $height; $y++)
|
||||
{
|
||||
$status = imagecopy($flipped, $this->tmp_image, 0, $y, 0, $height - $y - 1, $width, 1);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Do nothing
|
||||
return TRUE;
|
||||
}
|
||||
if ($status === true) {
|
||||
// Swap the new image for the old one
|
||||
imagedestroy($this->tmp_image);
|
||||
$this->tmp_image = $flipped;
|
||||
}
|
||||
|
||||
if ($status === TRUE)
|
||||
{
|
||||
// Swap the new image for the old one
|
||||
imagedestroy($this->tmp_image);
|
||||
$this->tmp_image = $flipped;
|
||||
}
|
||||
return $status;
|
||||
}
|
||||
|
||||
return $status;
|
||||
}
|
||||
public function crop($properties)
|
||||
{
|
||||
// Sanitize the cropping settings
|
||||
$this->sanitize_geometry($properties);
|
||||
|
||||
public function crop($properties)
|
||||
{
|
||||
// Sanitize the cropping settings
|
||||
$this->sanitize_geometry($properties);
|
||||
// Get the current width and height
|
||||
$width = imagesx($this->tmp_image);
|
||||
$height = imagesy($this->tmp_image);
|
||||
|
||||
// Get the current width and height
|
||||
$width = imagesx($this->tmp_image);
|
||||
$height = imagesy($this->tmp_image);
|
||||
// Create the temporary image to copy to
|
||||
$img = $this->imagecreatetransparent($properties['width'], $properties['height']);
|
||||
|
||||
// Create the temporary image to copy to
|
||||
$img = $this->imagecreatetransparent($properties['width'], $properties['height']);
|
||||
// Execute the crop
|
||||
if ($status = imagecopyresampled($img, $this->tmp_image, 0, 0, $properties['left'], $properties['top'], $width, $height, $width, $height)) {
|
||||
// Swap the new image for the old one
|
||||
imagedestroy($this->tmp_image);
|
||||
$this->tmp_image = $img;
|
||||
}
|
||||
|
||||
// Execute the crop
|
||||
if ($status = imagecopyresampled($img, $this->tmp_image, 0, 0, $properties['left'], $properties['top'], $width, $height, $width, $height))
|
||||
{
|
||||
// Swap the new image for the old one
|
||||
imagedestroy($this->tmp_image);
|
||||
$this->tmp_image = $img;
|
||||
}
|
||||
return $status;
|
||||
}
|
||||
|
||||
return $status;
|
||||
}
|
||||
public function resize($properties)
|
||||
{
|
||||
// Get the current width and height
|
||||
$width = imagesx($this->tmp_image);
|
||||
$height = imagesy($this->tmp_image);
|
||||
|
||||
public function resize($properties)
|
||||
{
|
||||
// Get the current width and height
|
||||
$width = imagesx($this->tmp_image);
|
||||
$height = imagesy($this->tmp_image);
|
||||
if (substr($properties['width'], -1) === '%') {
|
||||
// Recalculate the percentage to a pixel size
|
||||
$properties['width'] = round($width * (substr($properties['width'], 0, -1) / 100));
|
||||
}
|
||||
|
||||
if (substr($properties['width'], -1) === '%')
|
||||
{
|
||||
// Recalculate the percentage to a pixel size
|
||||
$properties['width'] = round($width * (substr($properties['width'], 0, -1) / 100));
|
||||
}
|
||||
if (substr($properties['height'], -1) === '%') {
|
||||
// Recalculate the percentage to a pixel size
|
||||
$properties['height'] = round($height * (substr($properties['height'], 0, -1) / 100));
|
||||
}
|
||||
|
||||
if (substr($properties['height'], -1) === '%')
|
||||
{
|
||||
// Recalculate the percentage to a pixel size
|
||||
$properties['height'] = round($height * (substr($properties['height'], 0, -1) / 100));
|
||||
}
|
||||
|
||||
// Recalculate the width and height, if they are missing
|
||||
empty($properties['width']) and $properties['width'] = round($width * $properties['height'] / $height);
|
||||
empty($properties['height']) and $properties['height'] = round($height * $properties['width'] / $width);
|
||||
|
||||
if ($properties['master'] === Image::AUTO)
|
||||
{
|
||||
// Change an automatic master dim to the correct type
|
||||
$properties['master'] = (($width / $properties['width']) > ($height / $properties['height'])) ? Image::WIDTH : Image::HEIGHT;
|
||||
}
|
||||
// Recalculate the width and height, if they are missing
|
||||
empty($properties['width']) and $properties['width'] = round($width * $properties['height'] / $height);
|
||||
empty($properties['height']) and $properties['height'] = round($height * $properties['width'] / $width);
|
||||
|
||||
if (empty($properties['height']) OR $properties['master'] === Image::WIDTH)
|
||||
{
|
||||
// Recalculate the height based on the width
|
||||
$properties['height'] = round($height * $properties['width'] / $width);
|
||||
}
|
||||
if ($properties['master'] === Image::AUTO) {
|
||||
// Change an automatic master dim to the correct type
|
||||
$properties['master'] = (($width / $properties['width']) > ($height / $properties['height'])) ? Image::WIDTH : Image::HEIGHT;
|
||||
}
|
||||
|
||||
if (empty($properties['width']) OR $properties['master'] === Image::HEIGHT)
|
||||
{
|
||||
// Recalculate the width based on the height
|
||||
$properties['width'] = round($width * $properties['height'] / $height);
|
||||
}
|
||||
if (empty($properties['height']) or $properties['master'] === Image::WIDTH) {
|
||||
// Recalculate the height based on the width
|
||||
$properties['height'] = round($height * $properties['width'] / $width);
|
||||
}
|
||||
|
||||
// Test if we can do a resize without resampling to speed up the final resize
|
||||
if ($properties['width'] > $width / 2 AND $properties['height'] > $height / 2)
|
||||
{
|
||||
// Presize width and height
|
||||
$pre_width = $width;
|
||||
$pre_height = $height;
|
||||
if (empty($properties['width']) or $properties['master'] === Image::HEIGHT) {
|
||||
// Recalculate the width based on the height
|
||||
$properties['width'] = round($width * $properties['height'] / $height);
|
||||
}
|
||||
|
||||
// The maximum reduction is 10% greater than the final size
|
||||
$max_reduction_width = round($properties['width'] * 1.1);
|
||||
$max_reduction_height = round($properties['height'] * 1.1);
|
||||
// Test if we can do a resize without resampling to speed up the final resize
|
||||
if ($properties['width'] > $width / 2 and $properties['height'] > $height / 2) {
|
||||
// Presize width and height
|
||||
$pre_width = $width;
|
||||
$pre_height = $height;
|
||||
|
||||
// Reduce the size using an O(2n) algorithm, until it reaches the maximum reduction
|
||||
while ($pre_width / 2 > $max_reduction_width AND $pre_height / 2 > $max_reduction_height)
|
||||
{
|
||||
$pre_width /= 2;
|
||||
$pre_height /= 2;
|
||||
}
|
||||
// The maximum reduction is 10% greater than the final size
|
||||
$max_reduction_width = round($properties['width'] * 1.1);
|
||||
$max_reduction_height = round($properties['height'] * 1.1);
|
||||
|
||||
// Create the temporary image to copy to
|
||||
$img = $this->imagecreatetransparent($pre_width, $pre_height);
|
||||
// Reduce the size using an O(2n) algorithm, until it reaches the maximum reduction
|
||||
while ($pre_width / 2 > $max_reduction_width and $pre_height / 2 > $max_reduction_height) {
|
||||
$pre_width /= 2;
|
||||
$pre_height /= 2;
|
||||
}
|
||||
|
||||
if ($status = imagecopyresized($img, $this->tmp_image, 0, 0, 0, 0, $pre_width, $pre_height, $width, $height))
|
||||
{
|
||||
// Swap the new image for the old one
|
||||
imagedestroy($this->tmp_image);
|
||||
$this->tmp_image = $img;
|
||||
}
|
||||
// Create the temporary image to copy to
|
||||
$img = $this->imagecreatetransparent($pre_width, $pre_height);
|
||||
|
||||
// Set the width and height to the presize
|
||||
$width = $pre_width;
|
||||
$height = $pre_height;
|
||||
}
|
||||
if ($status = imagecopyresized($img, $this->tmp_image, 0, 0, 0, 0, $pre_width, $pre_height, $width, $height)) {
|
||||
// Swap the new image for the old one
|
||||
imagedestroy($this->tmp_image);
|
||||
$this->tmp_image = $img;
|
||||
}
|
||||
|
||||
// Create the temporary image to copy to
|
||||
$img = $this->imagecreatetransparent($properties['width'], $properties['height']);
|
||||
// Set the width and height to the presize
|
||||
$width = $pre_width;
|
||||
$height = $pre_height;
|
||||
}
|
||||
|
||||
// Execute the resize
|
||||
if ($status = imagecopyresampled($img, $this->tmp_image, 0, 0, 0, 0, $properties['width'], $properties['height'], $width, $height))
|
||||
{
|
||||
// Swap the new image for the old one
|
||||
imagedestroy($this->tmp_image);
|
||||
$this->tmp_image = $img;
|
||||
}
|
||||
// Create the temporary image to copy to
|
||||
$img = $this->imagecreatetransparent($properties['width'], $properties['height']);
|
||||
|
||||
return $status;
|
||||
}
|
||||
// Execute the resize
|
||||
if ($status = imagecopyresampled($img, $this->tmp_image, 0, 0, 0, 0, $properties['width'], $properties['height'], $width, $height)) {
|
||||
// Swap the new image for the old one
|
||||
imagedestroy($this->tmp_image);
|
||||
$this->tmp_image = $img;
|
||||
}
|
||||
|
||||
public function rotate($amount)
|
||||
{
|
||||
// Use current image to rotate
|
||||
$img = $this->tmp_image;
|
||||
return $status;
|
||||
}
|
||||
|
||||
// White, with an alpha of 0
|
||||
$transparent = imagecolorallocatealpha($img, 255, 255, 255, 127);
|
||||
public function rotate($amount)
|
||||
{
|
||||
// Use current image to rotate
|
||||
$img = $this->tmp_image;
|
||||
|
||||
// Rotate, setting the transparent color
|
||||
$img = imagerotate($img, 360 - $amount, $transparent, -1);
|
||||
// White, with an alpha of 0
|
||||
$transparent = imagecolorallocatealpha($img, 255, 255, 255, 127);
|
||||
|
||||
// Fill the background with the transparent "color"
|
||||
imagecolortransparent($img, $transparent);
|
||||
// Rotate, setting the transparent color
|
||||
$img = imagerotate($img, 360 - $amount, $transparent, -1);
|
||||
|
||||
// Merge the images
|
||||
if ($status = imagecopymerge($this->tmp_image, $img, 0, 0, 0, 0, imagesx($this->tmp_image), imagesy($this->tmp_image), 100))
|
||||
{
|
||||
// Prevent the alpha from being lost
|
||||
imagealphablending($img, TRUE);
|
||||
imagesavealpha($img, TRUE);
|
||||
// Fill the background with the transparent "color"
|
||||
imagecolortransparent($img, $transparent);
|
||||
|
||||
// Swap the new image for the old one
|
||||
imagedestroy($this->tmp_image);
|
||||
$this->tmp_image = $img;
|
||||
}
|
||||
// Merge the images
|
||||
if ($status = imagecopymerge($this->tmp_image, $img, 0, 0, 0, 0, imagesx($this->tmp_image), imagesy($this->tmp_image), 100)) {
|
||||
// Prevent the alpha from being lost
|
||||
imagealphablending($img, true);
|
||||
imagesavealpha($img, true);
|
||||
|
||||
return $status;
|
||||
}
|
||||
// Swap the new image for the old one
|
||||
imagedestroy($this->tmp_image);
|
||||
$this->tmp_image = $img;
|
||||
}
|
||||
|
||||
public function sharpen($amount)
|
||||
{
|
||||
// Make sure that the sharpening function is available
|
||||
if ( ! function_exists('imageconvolution'))
|
||||
throw new Kohana_Exception('image.unsupported_method', __FUNCTION__);
|
||||
return $status;
|
||||
}
|
||||
|
||||
// Amount should be in the range of 18-10
|
||||
$amount = round(abs(-18 + ($amount * 0.08)), 2);
|
||||
public function sharpen($amount)
|
||||
{
|
||||
// Make sure that the sharpening function is available
|
||||
if (! function_exists('imageconvolution')) {
|
||||
throw new Kohana_Exception('image.unsupported_method', __FUNCTION__);
|
||||
}
|
||||
|
||||
// Gaussian blur matrix
|
||||
$matrix = array
|
||||
(
|
||||
array(-1, -1, -1),
|
||||
array(-1, $amount, -1),
|
||||
array(-1, -1, -1),
|
||||
);
|
||||
// Amount should be in the range of 18-10
|
||||
$amount = round(abs(-18 + ($amount * 0.08)), 2);
|
||||
|
||||
// Perform the sharpen
|
||||
return imageconvolution($this->tmp_image, $matrix, $amount - 8, 0);
|
||||
}
|
||||
// Gaussian blur matrix
|
||||
$matrix = array
|
||||
(
|
||||
array(-1, -1, -1),
|
||||
array(-1, $amount, -1),
|
||||
array(-1, -1, -1),
|
||||
);
|
||||
|
||||
protected function properties()
|
||||
{
|
||||
return array(imagesx($this->tmp_image), imagesy($this->tmp_image));
|
||||
}
|
||||
// Perform the sharpen
|
||||
return imageconvolution($this->tmp_image, $matrix, $amount - 8, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an image with a transparent background. Used for rotating to
|
||||
* prevent unfilled backgrounds.
|
||||
*
|
||||
* @param integer image width
|
||||
* @param integer image height
|
||||
* @return resource
|
||||
*/
|
||||
protected function imagecreatetransparent($width, $height)
|
||||
{
|
||||
if (self::$blank_png === NULL)
|
||||
{
|
||||
// Decode the blank PNG if it has not been done already
|
||||
self::$blank_png = imagecreatefromstring(base64_decode
|
||||
(
|
||||
'iVBORw0KGgoAAAANSUhEUgAAACgAAAAoCAYAAACM/rhtAAAABGdBTUEAAK/INwWK6QAAABl0RVh0U29'.
|
||||
'mdHdhcmUAQWRvYmUgSW1hZ2VSZWFkeXHJZTwAAADqSURBVHjaYvz//z/DYAYAAcTEMMgBQAANegcCBN'.
|
||||
'CgdyBAAA16BwIE0KB3IEAADXoHAgTQoHcgQAANegcCBNCgdyBAAA16BwIE0KB3IEAADXoHAgTQoHcgQ'.
|
||||
'AANegcCBNCgdyBAAA16BwIE0KB3IEAADXoHAgTQoHcgQAANegcCBNCgdyBAAA16BwIE0KB3IEAADXoH'.
|
||||
'AgTQoHcgQAANegcCBNCgdyBAAA16BwIE0KB3IEAADXoHAgTQoHcgQAANegcCBNCgdyBAAA16BwIE0KB'.
|
||||
'3IEAADXoHAgTQoHcgQAANegcCBNCgdyBAgAEAMpcDTTQWJVEAAAAASUVORK5CYII='
|
||||
));
|
||||
protected function properties()
|
||||
{
|
||||
return array(imagesx($this->tmp_image), imagesy($this->tmp_image));
|
||||
}
|
||||
|
||||
// Set the blank PNG width and height
|
||||
self::$blank_png_width = imagesx(self::$blank_png);
|
||||
self::$blank_png_height = imagesy(self::$blank_png);
|
||||
}
|
||||
/**
|
||||
* Returns an image with a transparent background. Used for rotating to
|
||||
* prevent unfilled backgrounds.
|
||||
*
|
||||
* @param integer image width
|
||||
* @param integer image height
|
||||
* @return resource
|
||||
*/
|
||||
protected function imagecreatetransparent($width, $height)
|
||||
{
|
||||
if (self::$blank_png === null) {
|
||||
// Decode the blank PNG if it has not been done already
|
||||
self::$blank_png = imagecreatefromstring(base64_decode(
|
||||
'iVBORw0KGgoAAAANSUhEUgAAACgAAAAoCAYAAACM/rhtAAAABGdBTUEAAK/INwWK6QAAABl0RVh0U29' .
|
||||
'mdHdhcmUAQWRvYmUgSW1hZ2VSZWFkeXHJZTwAAADqSURBVHjaYvz//z/DYAYAAcTEMMgBQAANegcCBN' .
|
||||
'CgdyBAAA16BwIE0KB3IEAADXoHAgTQoHcgQAANegcCBNCgdyBAAA16BwIE0KB3IEAADXoHAgTQoHcgQ' .
|
||||
'AANegcCBNCgdyBAAA16BwIE0KB3IEAADXoHAgTQoHcgQAANegcCBNCgdyBAAA16BwIE0KB3IEAADXoH' .
|
||||
'AgTQoHcgQAANegcCBNCgdyBAAA16BwIE0KB3IEAADXoHAgTQoHcgQAANegcCBNCgdyBAAA16BwIE0KB' .
|
||||
'3IEAADXoHAgTQoHcgQAANegcCBNCgdyBAgAEAMpcDTTQWJVEAAAAASUVORK5CYII='
|
||||
));
|
||||
|
||||
$img = imagecreatetruecolor($width, $height);
|
||||
// Set the blank PNG width and height
|
||||
self::$blank_png_width = imagesx(self::$blank_png);
|
||||
self::$blank_png_height = imagesy(self::$blank_png);
|
||||
}
|
||||
|
||||
// Resize the blank image
|
||||
imagecopyresized($img, self::$blank_png, 0, 0, 0, 0, $width, $height, self::$blank_png_width, self::$blank_png_height);
|
||||
$img = imagecreatetruecolor($width, $height);
|
||||
|
||||
// Prevent the alpha from being lost
|
||||
imagealphablending($img, FALSE);
|
||||
imagesavealpha($img, TRUE);
|
||||
// Resize the blank image
|
||||
imagecopyresized($img, self::$blank_png, 0, 0, 0, 0, $width, $height, self::$blank_png_width, self::$blank_png_height);
|
||||
|
||||
return $img;
|
||||
}
|
||||
// Prevent the alpha from being lost
|
||||
imagealphablending($img, false);
|
||||
imagesavealpha($img, true);
|
||||
|
||||
} // End Image GD Driver
|
||||
return $img;
|
||||
}
|
||||
}
|
||||
// End Image GD Driver
|
||||
|
||||
@@ -1,4 +1,12 @@
|
||||
<?php defined('SYSPATH') OR die('No direct access allowed.');
|
||||
<?php
|
||||
|
||||
// phpcs:disable PSR1.Classes.ClassDeclaration.MissingNamespace
|
||||
// phpcs:disable PSR1.Files.SideEffects
|
||||
defined('SYSPATH') or die('No direct access allowed.');
|
||||
// phpcs:enable PSR1.Files.SideEffects
|
||||
// phpcs:disable Squiz.Classes.ValidClassName.NotCamelCaps
|
||||
|
||||
|
||||
/**
|
||||
* GraphicsMagick Image Driver.
|
||||
*
|
||||
@@ -7,205 +15,200 @@
|
||||
* @copyright (c) 2007-2008 Kohana Team
|
||||
* @license http://kohanaphp.com/license.html
|
||||
*/
|
||||
class Image_GraphicsMagick_Driver extends Image_Driver {
|
||||
class Image_GraphicsMagick_Driver extends Image_Driver
|
||||
{
|
||||
// Directory that GM is installed in
|
||||
protected $dir = '';
|
||||
|
||||
// Directory that GM is installed in
|
||||
protected $dir = '';
|
||||
// Command extension (exe for windows)
|
||||
protected $ext = '';
|
||||
|
||||
// Command extension (exe for windows)
|
||||
protected $ext = '';
|
||||
// Temporary image filename
|
||||
protected $tmp_image;
|
||||
|
||||
// Temporary image filename
|
||||
protected $tmp_image;
|
||||
/**
|
||||
* Attempts to detect the GraphicsMagick installation directory.
|
||||
*
|
||||
* @throws Kohana_Exception
|
||||
* @param array configuration
|
||||
* @return void
|
||||
*/
|
||||
public function __construct($config)
|
||||
{
|
||||
if (empty($config['directory'])) {
|
||||
// Attempt to locate GM by using "which" (only works for *nix!)
|
||||
if (! is_file($path = exec('which gm'))) {
|
||||
throw new Kohana_Exception('image.graphicsmagick.not_found');
|
||||
}
|
||||
|
||||
/**
|
||||
* Attempts to detect the GraphicsMagick installation directory.
|
||||
*
|
||||
* @throws Kohana_Exception
|
||||
* @param array configuration
|
||||
* @return void
|
||||
*/
|
||||
public function __construct($config)
|
||||
{
|
||||
if (empty($config['directory']))
|
||||
{
|
||||
// Attempt to locate GM by using "which" (only works for *nix!)
|
||||
if ( ! is_file($path = exec('which gm')))
|
||||
throw new Kohana_Exception('image.graphicsmagick.not_found');
|
||||
$config['directory'] = dirname($path);
|
||||
}
|
||||
|
||||
$config['directory'] = dirname($path);
|
||||
}
|
||||
// Set the command extension
|
||||
$this->ext = (PHP_SHLIB_SUFFIX === 'dll') ? '.exe' : '';
|
||||
|
||||
// Set the command extension
|
||||
$this->ext = (PHP_SHLIB_SUFFIX === 'dll') ? '.exe' : '';
|
||||
|
||||
// Check to make sure the provided path is correct
|
||||
if ( ! is_file(realpath($config['directory']).'/gm'.$this->ext))
|
||||
throw new Kohana_Exception('image.graphicsmagick.not_found', 'gm'.$this->ext);
|
||||
// Check to make sure the provided path is correct
|
||||
if (! is_file(realpath($config['directory']) . '/gm' . $this->ext)) {
|
||||
throw new Kohana_Exception('image.graphicsmagick.not_found', 'gm' . $this->ext);
|
||||
}
|
||||
|
||||
|
||||
// Set the installation directory
|
||||
$this->dir = str_replace('\\', '/', realpath($config['directory'])).'/';
|
||||
}
|
||||
// Set the installation directory
|
||||
$this->dir = str_replace('\\', '/', realpath($config['directory'])) . '/';
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a temporary image and executes the given actions. By creating a
|
||||
* temporary copy of the image before manipulating it, this process is atomic.
|
||||
*/
|
||||
public function process($image, $actions, $dir, $file, $render = FALSE)
|
||||
{
|
||||
// We only need the filename
|
||||
$image = $image['file'];
|
||||
/**
|
||||
* Creates a temporary image and executes the given actions. By creating a
|
||||
* temporary copy of the image before manipulating it, this process is atomic.
|
||||
*/
|
||||
public function process($image, $actions, $dir, $file, $render = false)
|
||||
{
|
||||
// We only need the filename
|
||||
$image = $image['file'];
|
||||
|
||||
// Unique temporary filename
|
||||
$this->tmp_image = $dir.'k2img--'.sha1(time().$dir.$file).substr($file, strrpos($file, '.'));
|
||||
// Unique temporary filename
|
||||
$this->tmp_image = $dir . 'k2img--' . sha1(time() . $dir . $file) . substr($file, strrpos($file, '.'));
|
||||
|
||||
// Copy the image to the temporary file
|
||||
copy($image, $this->tmp_image);
|
||||
// Copy the image to the temporary file
|
||||
copy($image, $this->tmp_image);
|
||||
|
||||
// Quality change is done last
|
||||
$quality = (int) arr::remove('quality', $actions);
|
||||
// Quality change is done last
|
||||
$quality = (int) arr::remove('quality', $actions);
|
||||
|
||||
// Use 95 for the default quality
|
||||
empty($quality) and $quality = 95;
|
||||
// Use 95 for the default quality
|
||||
empty($quality) and $quality = 95;
|
||||
|
||||
// All calls to these will need to be escaped, so do it now
|
||||
$this->cmd_image = escapeshellarg($this->tmp_image);
|
||||
$this->new_image = ($render)? $this->cmd_image : escapeshellarg($dir.$file);
|
||||
// All calls to these will need to be escaped, so do it now
|
||||
$this->cmd_image = escapeshellarg($this->tmp_image);
|
||||
$this->new_image = ($render) ? $this->cmd_image : escapeshellarg($dir . $file);
|
||||
|
||||
if ($status = $this->execute($actions))
|
||||
{
|
||||
// Use convert to change the image into its final version. This is
|
||||
// done to allow the file type to change correctly, and to handle
|
||||
// the quality conversion in the most effective way possible.
|
||||
if ($error = exec(escapeshellcmd($this->dir.'gm'.$this->ext.' convert').' -quality '.$quality.'% '.$this->cmd_image.' '.$this->new_image))
|
||||
{
|
||||
$this->errors[] = $error;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Output the image directly to the browser
|
||||
if ($render !== FALSE)
|
||||
{
|
||||
$contents = file_get_contents($this->tmp_image);
|
||||
switch (substr($file, strrpos($file, '.') + 1))
|
||||
{
|
||||
case 'jpg':
|
||||
case 'jpeg':
|
||||
header('Content-Type: image/jpeg');
|
||||
break;
|
||||
case 'gif':
|
||||
header('Content-Type: image/gif');
|
||||
break;
|
||||
case 'png':
|
||||
header('Content-Type: image/png');
|
||||
break;
|
||||
}
|
||||
echo $contents;
|
||||
}
|
||||
}
|
||||
}
|
||||
if ($status = $this->execute($actions)) {
|
||||
// Use convert to change the image into its final version. This is
|
||||
// done to allow the file type to change correctly, and to handle
|
||||
// the quality conversion in the most effective way possible.
|
||||
if ($error = exec(escapeshellcmd($this->dir . 'gm' . $this->ext . ' convert') . ' -quality ' . $quality . '% ' . $this->cmd_image . ' ' . $this->new_image)) {
|
||||
$this->errors[] = $error;
|
||||
} else {
|
||||
// Output the image directly to the browser
|
||||
if ($render !== false) {
|
||||
$contents = file_get_contents($this->tmp_image);
|
||||
switch (substr($file, strrpos($file, '.') + 1)) {
|
||||
case 'jpg':
|
||||
case 'jpeg':
|
||||
header('Content-Type: image/jpeg');
|
||||
break;
|
||||
case 'gif':
|
||||
header('Content-Type: image/gif');
|
||||
break;
|
||||
case 'png':
|
||||
header('Content-Type: image/png');
|
||||
break;
|
||||
}
|
||||
echo $contents;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Remove the temporary image
|
||||
unlink($this->tmp_image);
|
||||
$this->tmp_image = '';
|
||||
// Remove the temporary image
|
||||
unlink($this->tmp_image);
|
||||
$this->tmp_image = '';
|
||||
|
||||
return $status;
|
||||
}
|
||||
return $status;
|
||||
}
|
||||
|
||||
public function crop($prop)
|
||||
{
|
||||
// Sanitize and normalize the properties into geometry
|
||||
$this->sanitize_geometry($prop);
|
||||
public function crop($prop)
|
||||
{
|
||||
// Sanitize and normalize the properties into geometry
|
||||
$this->sanitize_geometry($prop);
|
||||
|
||||
// Set the IM geometry based on the properties
|
||||
$geometry = escapeshellarg($prop['width'].'x'.$prop['height'].'+'.$prop['left'].'+'.$prop['top']);
|
||||
// Set the IM geometry based on the properties
|
||||
$geometry = escapeshellarg($prop['width'] . 'x' . $prop['height'] . '+' . $prop['left'] . '+' . $prop['top']);
|
||||
|
||||
if ($error = exec(escapeshellcmd($this->dir.'gm'.$this->ext.' convert').' -crop '.$geometry.' '.$this->cmd_image.' '.$this->cmd_image))
|
||||
{
|
||||
$this->errors[] = $error;
|
||||
return FALSE;
|
||||
}
|
||||
if ($error = exec(escapeshellcmd($this->dir . 'gm' . $this->ext . ' convert') . ' -crop ' . $geometry . ' ' . $this->cmd_image . ' ' . $this->cmd_image)) {
|
||||
$this->errors[] = $error;
|
||||
return false;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public function flip($dir)
|
||||
{
|
||||
// Convert the direction into a GM command
|
||||
$dir = ($dir === Image::HORIZONTAL) ? '-flop' : '-flip';
|
||||
public function flip($dir)
|
||||
{
|
||||
// Convert the direction into a GM command
|
||||
$dir = ($dir === Image::HORIZONTAL) ? '-flop' : '-flip';
|
||||
|
||||
if ($error = exec(escapeshellcmd($this->dir.'gm'.$this->ext.' convert').' '.$dir.' '.$this->cmd_image.' '.$this->cmd_image))
|
||||
{
|
||||
$this->errors[] = $error;
|
||||
return FALSE;
|
||||
}
|
||||
if ($error = exec(escapeshellcmd($this->dir . 'gm' . $this->ext . ' convert') . ' ' . $dir . ' ' . $this->cmd_image . ' ' . $this->cmd_image)) {
|
||||
$this->errors[] = $error;
|
||||
return false;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public function resize($prop)
|
||||
{
|
||||
switch ($prop['master'])
|
||||
{
|
||||
case Image::WIDTH: // Wx
|
||||
$dim = escapeshellarg($prop['width'].'x');
|
||||
break;
|
||||
case Image::HEIGHT: // xH
|
||||
$dim = escapeshellarg('x'.$prop['height']);
|
||||
break;
|
||||
case Image::AUTO: // WxH
|
||||
$dim = escapeshellarg($prop['width'].'x'.$prop['height']);
|
||||
break;
|
||||
case Image::NONE: // WxH!
|
||||
$dim = escapeshellarg($prop['width'].'x'.$prop['height'].'!');
|
||||
break;
|
||||
}
|
||||
public function resize($prop)
|
||||
{
|
||||
switch ($prop['master']) {
|
||||
case Image::WIDTH: // Wx
|
||||
$dim = escapeshellarg($prop['width'] . 'x');
|
||||
break;
|
||||
case Image::HEIGHT: // xH
|
||||
$dim = escapeshellarg('x' . $prop['height']);
|
||||
break;
|
||||
case Image::AUTO: // WxH
|
||||
$dim = escapeshellarg($prop['width'] . 'x' . $prop['height']);
|
||||
break;
|
||||
case Image::NONE: // WxH!
|
||||
$dim = escapeshellarg($prop['width'] . 'x' . $prop['height'] . '!');
|
||||
break;
|
||||
}
|
||||
|
||||
// Use "convert" to change the width and height
|
||||
if ($error = exec(escapeshellcmd($this->dir.'gm'.$this->ext.' convert').' -resize '.$dim.' '.$this->cmd_image.' '.$this->cmd_image))
|
||||
{
|
||||
$this->errors[] = $error;
|
||||
return FALSE;
|
||||
}
|
||||
// Use "convert" to change the width and height
|
||||
if ($error = exec(escapeshellcmd($this->dir . 'gm' . $this->ext . ' convert') . ' -resize ' . $dim . ' ' . $this->cmd_image . ' ' . $this->cmd_image)) {
|
||||
$this->errors[] = $error;
|
||||
return false;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public function rotate($amt)
|
||||
{
|
||||
if ($error = exec(escapeshellcmd($this->dir.'gm'.$this->ext.' convert').' -rotate '.escapeshellarg($amt).' -background transparent '.$this->cmd_image.' '.$this->cmd_image))
|
||||
{
|
||||
$this->errors[] = $error;
|
||||
return FALSE;
|
||||
}
|
||||
public function rotate($amt)
|
||||
{
|
||||
if (
|
||||
$error = exec(escapeshellcmd($this->dir . 'gm' . $this->ext . ' convert') .
|
||||
' -rotate ' . escapeshellarg($amt) .
|
||||
' -background transparent ' .
|
||||
$this->cmd_image .
|
||||
' ' . $this->cmd_image)
|
||||
) {
|
||||
$this->errors[] = $error;
|
||||
return false;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public function sharpen($amount)
|
||||
{
|
||||
// Set the sigma, radius, and amount. The amount formula allows a nice
|
||||
// spread between 1 and 100 without pixelizing the image badly.
|
||||
$sigma = 0.5;
|
||||
$radius = $sigma * 2;
|
||||
$amount = round(($amount / 80) * 3.14, 2);
|
||||
public function sharpen($amount)
|
||||
{
|
||||
// Set the sigma, radius, and amount. The amount formula allows a nice
|
||||
// spread between 1 and 100 without pixelizing the image badly.
|
||||
$sigma = 0.5;
|
||||
$radius = $sigma * 2;
|
||||
$amount = round(($amount / 80) * 3.14, 2);
|
||||
|
||||
// Convert the amount to an GM command
|
||||
$sharpen = escapeshellarg($radius.'x'.$sigma.'+'.$amount.'+0');
|
||||
// Convert the amount to an GM command
|
||||
$sharpen = escapeshellarg($radius . 'x' . $sigma . '+' . $amount . '+0');
|
||||
|
||||
if ($error = exec(escapeshellcmd($this->dir.'gm'.$this->ext.' convert').' -unsharp '.$sharpen.' '.$this->cmd_image.' '.$this->cmd_image))
|
||||
{
|
||||
$this->errors[] = $error;
|
||||
return FALSE;
|
||||
}
|
||||
if ($error = exec(escapeshellcmd($this->dir . 'gm' . $this->ext . ' convert') . ' -unsharp ' . $sharpen . ' ' . $this->cmd_image . ' ' . $this->cmd_image)) {
|
||||
$this->errors[] = $error;
|
||||
return false;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
protected function properties()
|
||||
{
|
||||
return array_slice(getimagesize($this->tmp_image), 0, 2, FALSE);
|
||||
}
|
||||
|
||||
} // End Image GraphicsMagick Driver
|
||||
protected function properties()
|
||||
{
|
||||
return array_slice(getimagesize($this->tmp_image), 0, 2, false);
|
||||
}
|
||||
}
|
||||
// End Image GraphicsMagick Driver
|
||||
|
||||
@@ -1,4 +1,13 @@
|
||||
<?php defined('SYSPATH') OR die('No direct access allowed.');
|
||||
<?php
|
||||
|
||||
// phpcs:disable PSR1.Classes.ClassDeclaration.MissingNamespace
|
||||
// phpcs:disable PSR1.Files.SideEffects
|
||||
defined('SYSPATH') or die('No direct access allowed.');
|
||||
// phpcs:enable PSR1.Files.SideEffects
|
||||
// phpcs:disable Squiz.Classes.ValidClassName.NotCamelCaps
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* ImageMagick Image Driver.
|
||||
*
|
||||
@@ -9,204 +18,200 @@
|
||||
* @copyright (c) 2007-2008 Kohana Team
|
||||
* @license http://kohanaphp.com/license.html
|
||||
*/
|
||||
class Image_ImageMagick_Driver extends Image_Driver {
|
||||
class Image_ImageMagick_Driver extends Image_Driver
|
||||
{
|
||||
// Directory that IM is installed in
|
||||
protected $dir = '';
|
||||
|
||||
// Directory that IM is installed in
|
||||
protected $dir = '';
|
||||
// Command extension (exe for windows)
|
||||
protected $ext = '';
|
||||
|
||||
// Command extension (exe for windows)
|
||||
protected $ext = '';
|
||||
// Temporary image filename
|
||||
protected $tmp_image;
|
||||
|
||||
// Temporary image filename
|
||||
protected $tmp_image;
|
||||
/**
|
||||
* Attempts to detect the ImageMagick installation directory.
|
||||
*
|
||||
* @throws Kohana_Exception
|
||||
* @param array configuration
|
||||
* @return void
|
||||
*/
|
||||
public function __construct($config)
|
||||
{
|
||||
if (empty($config['directory'])) {
|
||||
// Attempt to locate IM by using "which" (only works for *nix!)
|
||||
if (! is_file($path = exec('which convert'))) {
|
||||
throw new Kohana_Exception('image.imagemagick.not_found');
|
||||
}
|
||||
|
||||
/**
|
||||
* Attempts to detect the ImageMagick installation directory.
|
||||
*
|
||||
* @throws Kohana_Exception
|
||||
* @param array configuration
|
||||
* @return void
|
||||
*/
|
||||
public function __construct($config)
|
||||
{
|
||||
if (empty($config['directory']))
|
||||
{
|
||||
// Attempt to locate IM by using "which" (only works for *nix!)
|
||||
if ( ! is_file($path = exec('which convert')))
|
||||
throw new Kohana_Exception('image.imagemagick.not_found');
|
||||
$config['directory'] = dirname($path);
|
||||
}
|
||||
|
||||
$config['directory'] = dirname($path);
|
||||
}
|
||||
// Set the command extension
|
||||
$this->ext = (PHP_SHLIB_SUFFIX === 'dll') ? '.exe' : '';
|
||||
|
||||
// Set the command extension
|
||||
$this->ext = (PHP_SHLIB_SUFFIX === 'dll') ? '.exe' : '';
|
||||
// Check to make sure the provided path is correct
|
||||
if (! is_file(realpath($config['directory']) . '/convert' . $this->ext)) {
|
||||
throw new Kohana_Exception('image.imagemagick.not_found', 'convert' . $this->ext);
|
||||
}
|
||||
|
||||
// Check to make sure the provided path is correct
|
||||
if ( ! is_file(realpath($config['directory']).'/convert'.$this->ext))
|
||||
throw new Kohana_Exception('image.imagemagick.not_found', 'convert'.$this->ext);
|
||||
// Set the installation directory
|
||||
$this->dir = str_replace('\\', '/', realpath($config['directory'])) . '/';
|
||||
}
|
||||
|
||||
// Set the installation directory
|
||||
$this->dir = str_replace('\\', '/', realpath($config['directory'])).'/';
|
||||
}
|
||||
/**
|
||||
* Creates a temporary image and executes the given actions. By creating a
|
||||
* temporary copy of the image before manipulating it, this process is atomic.
|
||||
*/
|
||||
public function process($image, $actions, $dir, $file, $render = false)
|
||||
{
|
||||
// We only need the filename
|
||||
$image = $image['file'];
|
||||
|
||||
/**
|
||||
* Creates a temporary image and executes the given actions. By creating a
|
||||
* temporary copy of the image before manipulating it, this process is atomic.
|
||||
*/
|
||||
public function process($image, $actions, $dir, $file, $render = FALSE)
|
||||
{
|
||||
// We only need the filename
|
||||
$image = $image['file'];
|
||||
// Unique temporary filename
|
||||
$this->tmp_image = $dir . 'k2img--' . sha1(time() . $dir . $file) . substr($file, strrpos($file, '.'));
|
||||
|
||||
// Unique temporary filename
|
||||
$this->tmp_image = $dir.'k2img--'.sha1(time().$dir.$file).substr($file, strrpos($file, '.'));
|
||||
// Copy the image to the temporary file
|
||||
copy($image, $this->tmp_image);
|
||||
|
||||
// Copy the image to the temporary file
|
||||
copy($image, $this->tmp_image);
|
||||
// Quality change is done last
|
||||
$quality = (int) arr::remove('quality', $actions);
|
||||
|
||||
// Quality change is done last
|
||||
$quality = (int) arr::remove('quality', $actions);
|
||||
// Use 95 for the default quality
|
||||
empty($quality) and $quality = 95;
|
||||
|
||||
// Use 95 for the default quality
|
||||
empty($quality) and $quality = 95;
|
||||
// All calls to these will need to be escaped, so do it now
|
||||
$this->cmd_image = escapeshellarg($this->tmp_image);
|
||||
$this->new_image = ($render) ? $this->cmd_image : escapeshellarg($dir . $file);
|
||||
|
||||
// All calls to these will need to be escaped, so do it now
|
||||
$this->cmd_image = escapeshellarg($this->tmp_image);
|
||||
$this->new_image = ($render)? $this->cmd_image : escapeshellarg($dir.$file);
|
||||
if ($status = $this->execute($actions)) {
|
||||
// Use convert to change the image into its final version. This is
|
||||
// done to allow the file type to change correctly, and to handle
|
||||
// the quality conversion in the most effective way possible.
|
||||
if ($error = exec(escapeshellcmd($this->dir . 'convert' . $this->ext) . ' -quality ' . $quality . '% ' . $this->cmd_image . ' ' . $this->new_image)) {
|
||||
$this->errors[] = $error;
|
||||
} else {
|
||||
// Output the image directly to the browser
|
||||
if ($render !== false) {
|
||||
$contents = file_get_contents($this->tmp_image);
|
||||
switch (substr($file, strrpos($file, '.') + 1)) {
|
||||
case 'jpg':
|
||||
case 'jpeg':
|
||||
header('Content-Type: image/jpeg');
|
||||
break;
|
||||
case 'gif':
|
||||
header('Content-Type: image/gif');
|
||||
break;
|
||||
case 'png':
|
||||
header('Content-Type: image/png');
|
||||
break;
|
||||
}
|
||||
echo $contents;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ($status = $this->execute($actions))
|
||||
{
|
||||
// Use convert to change the image into its final version. This is
|
||||
// done to allow the file type to change correctly, and to handle
|
||||
// the quality conversion in the most effective way possible.
|
||||
if ($error = exec(escapeshellcmd($this->dir.'convert'.$this->ext).' -quality '.$quality.'% '.$this->cmd_image.' '.$this->new_image))
|
||||
{
|
||||
$this->errors[] = $error;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Output the image directly to the browser
|
||||
if ($render !== FALSE)
|
||||
{
|
||||
$contents = file_get_contents($this->tmp_image);
|
||||
switch (substr($file, strrpos($file, '.') + 1))
|
||||
{
|
||||
case 'jpg':
|
||||
case 'jpeg':
|
||||
header('Content-Type: image/jpeg');
|
||||
break;
|
||||
case 'gif':
|
||||
header('Content-Type: image/gif');
|
||||
break;
|
||||
case 'png':
|
||||
header('Content-Type: image/png');
|
||||
break;
|
||||
}
|
||||
echo $contents;
|
||||
}
|
||||
}
|
||||
}
|
||||
// Remove the temporary image
|
||||
unlink($this->tmp_image);
|
||||
$this->tmp_image = '';
|
||||
|
||||
// Remove the temporary image
|
||||
unlink($this->tmp_image);
|
||||
$this->tmp_image = '';
|
||||
return $status;
|
||||
}
|
||||
|
||||
return $status;
|
||||
}
|
||||
public function crop($prop)
|
||||
{
|
||||
// Sanitize and normalize the properties into geometry
|
||||
$this->sanitize_geometry($prop);
|
||||
|
||||
public function crop($prop)
|
||||
{
|
||||
// Sanitize and normalize the properties into geometry
|
||||
$this->sanitize_geometry($prop);
|
||||
// Set the IM geometry based on the properties
|
||||
$geometry = escapeshellarg($prop['width'] . 'x' . $prop['height'] . '+' . $prop['left'] . '+' . $prop['top']);
|
||||
|
||||
// Set the IM geometry based on the properties
|
||||
$geometry = escapeshellarg($prop['width'].'x'.$prop['height'].'+'.$prop['left'].'+'.$prop['top']);
|
||||
if ($error = exec(escapeshellcmd($this->dir . 'convert' . $this->ext) . ' -crop ' . $geometry . ' ' . $this->cmd_image . ' ' . $this->cmd_image)) {
|
||||
$this->errors[] = $error;
|
||||
return false;
|
||||
}
|
||||
|
||||
if ($error = exec(escapeshellcmd($this->dir.'convert'.$this->ext).' -crop '.$geometry.' '.$this->cmd_image.' '.$this->cmd_image))
|
||||
{
|
||||
$this->errors[] = $error;
|
||||
return FALSE;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
public function flip($dir)
|
||||
{
|
||||
// Convert the direction into a IM command
|
||||
$dir = ($dir === Image::HORIZONTAL) ? '-flop' : '-flip';
|
||||
|
||||
public function flip($dir)
|
||||
{
|
||||
// Convert the direction into a IM command
|
||||
$dir = ($dir === Image::HORIZONTAL) ? '-flop' : '-flip';
|
||||
if ($error = exec(escapeshellcmd($this->dir . 'convert' . $this->ext) . ' ' . $dir . ' ' . $this->cmd_image . ' ' . $this->cmd_image)) {
|
||||
$this->errors[] = $error;
|
||||
return false;
|
||||
}
|
||||
|
||||
if ($error = exec(escapeshellcmd($this->dir.'convert'.$this->ext).' '.$dir.' '.$this->cmd_image.' '.$this->cmd_image))
|
||||
{
|
||||
$this->errors[] = $error;
|
||||
return FALSE;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
public function resize($prop)
|
||||
{
|
||||
switch ($prop['master']) {
|
||||
case Image::WIDTH: // Wx
|
||||
$dim = escapeshellarg($prop['width'] . 'x');
|
||||
break;
|
||||
case Image::HEIGHT: // xH
|
||||
$dim = escapeshellarg('x' . $prop['height']);
|
||||
break;
|
||||
case Image::AUTO: // WxH
|
||||
$dim = escapeshellarg($prop['width'] . 'x' . $prop['height']);
|
||||
break;
|
||||
case Image::NONE: // WxH!
|
||||
$dim = escapeshellarg($prop['width'] . 'x' . $prop['height'] . '!');
|
||||
break;
|
||||
}
|
||||
|
||||
public function resize($prop)
|
||||
{
|
||||
switch ($prop['master'])
|
||||
{
|
||||
case Image::WIDTH: // Wx
|
||||
$dim = escapeshellarg($prop['width'].'x');
|
||||
break;
|
||||
case Image::HEIGHT: // xH
|
||||
$dim = escapeshellarg('x'.$prop['height']);
|
||||
break;
|
||||
case Image::AUTO: // WxH
|
||||
$dim = escapeshellarg($prop['width'].'x'.$prop['height']);
|
||||
break;
|
||||
case Image::NONE: // WxH!
|
||||
$dim = escapeshellarg($prop['width'].'x'.$prop['height'].'!');
|
||||
break;
|
||||
}
|
||||
// Use "convert" to change the width and height
|
||||
if ($error = exec(escapeshellcmd($this->dir . 'convert' . $this->ext) . ' -resize ' . $dim . ' ' . $this->cmd_image . ' ' . $this->cmd_image)) {
|
||||
$this->errors[] = $error;
|
||||
return false;
|
||||
}
|
||||
|
||||
// Use "convert" to change the width and height
|
||||
if ($error = exec(escapeshellcmd($this->dir.'convert'.$this->ext).' -resize '.$dim.' '.$this->cmd_image.' '.$this->cmd_image))
|
||||
{
|
||||
$this->errors[] = $error;
|
||||
return FALSE;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
public function rotate($amt)
|
||||
{
|
||||
if (
|
||||
$error = exec(escapeshellcmd($this->dir . 'convert' . $this->ext) .
|
||||
' -rotate ' .
|
||||
escapeshellarg($amt) .
|
||||
' -background transparent ' .
|
||||
$this->cmd_image . ' ' .
|
||||
$this->cmd_image)
|
||||
) {
|
||||
$this->errors[] = $error;
|
||||
return false;
|
||||
}
|
||||
|
||||
public function rotate($amt)
|
||||
{
|
||||
if ($error = exec(escapeshellcmd($this->dir.'convert'.$this->ext).' -rotate '.escapeshellarg($amt).' -background transparent '.$this->cmd_image.' '.$this->cmd_image))
|
||||
{
|
||||
$this->errors[] = $error;
|
||||
return FALSE;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
public function sharpen($amount)
|
||||
{
|
||||
// Set the sigma, radius, and amount. The amount formula allows a nice
|
||||
// spread between 1 and 100 without pixelizing the image badly.
|
||||
$sigma = 0.5;
|
||||
$radius = $sigma * 2;
|
||||
$amount = round(($amount / 80) * 3.14, 2);
|
||||
|
||||
public function sharpen($amount)
|
||||
{
|
||||
// Set the sigma, radius, and amount. The amount formula allows a nice
|
||||
// spread between 1 and 100 without pixelizing the image badly.
|
||||
$sigma = 0.5;
|
||||
$radius = $sigma * 2;
|
||||
$amount = round(($amount / 80) * 3.14, 2);
|
||||
// Convert the amount to an IM command
|
||||
$sharpen = escapeshellarg($radius . 'x' . $sigma . '+' . $amount . '+0');
|
||||
|
||||
// Convert the amount to an IM command
|
||||
$sharpen = escapeshellarg($radius.'x'.$sigma.'+'.$amount.'+0');
|
||||
if ($error = exec(escapeshellcmd($this->dir . 'convert' . $this->ext) . ' -unsharp ' . $sharpen . ' ' . $this->cmd_image . ' ' . $this->cmd_image)) {
|
||||
$this->errors[] = $error;
|
||||
return false;
|
||||
}
|
||||
|
||||
if ($error = exec(escapeshellcmd($this->dir.'convert'.$this->ext).' -unsharp '.$sharpen.' '.$this->cmd_image.' '.$this->cmd_image))
|
||||
{
|
||||
$this->errors[] = $error;
|
||||
return FALSE;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
protected function properties()
|
||||
{
|
||||
return array_slice(getimagesize($this->tmp_image), 0, 2, FALSE);
|
||||
}
|
||||
|
||||
} // End Image ImageMagick Driver
|
||||
protected function properties()
|
||||
{
|
||||
return array_slice(getimagesize($this->tmp_image), 0, 2, false);
|
||||
}
|
||||
}
|
||||
// End Image ImageMagick Driver
|
||||
|
||||
@@ -1,4 +1,12 @@
|
||||
<?php defined('SYSPATH') OR die('No direct access allowed.');
|
||||
<?php
|
||||
|
||||
// phpcs:disable PSR1.Classes.ClassDeclaration.MissingNamespace
|
||||
// phpcs:disable PSR1.Files.SideEffects
|
||||
defined('SYSPATH') or die('No direct access allowed.');
|
||||
// phpcs:enable PSR1.Files.SideEffects
|
||||
// phpcs:disable Squiz.Classes.ValidClassName.NotCamelCaps
|
||||
|
||||
|
||||
/**
|
||||
* Session driver interface
|
||||
*
|
||||
@@ -9,62 +17,62 @@
|
||||
* @copyright (c) 2007-2008 Kohana Team
|
||||
* @license http://kohanaphp.com/license.html
|
||||
*/
|
||||
interface Session_Driver {
|
||||
interface Session_Driver
|
||||
{
|
||||
/**
|
||||
* Opens a session.
|
||||
*
|
||||
* @param string save path
|
||||
* @param string session name
|
||||
* @return boolean
|
||||
*/
|
||||
public function open($path, $name);
|
||||
|
||||
/**
|
||||
* Opens a session.
|
||||
*
|
||||
* @param string save path
|
||||
* @param string session name
|
||||
* @return boolean
|
||||
*/
|
||||
public function open($path, $name);
|
||||
/**
|
||||
* Closes a session.
|
||||
*
|
||||
* @return boolean
|
||||
*/
|
||||
public function close();
|
||||
|
||||
/**
|
||||
* Closes a session.
|
||||
*
|
||||
* @return boolean
|
||||
*/
|
||||
public function close();
|
||||
/**
|
||||
* Reads a session.
|
||||
*
|
||||
* @param string session id
|
||||
* @return string
|
||||
*/
|
||||
public function read($id);
|
||||
|
||||
/**
|
||||
* Reads a session.
|
||||
*
|
||||
* @param string session id
|
||||
* @return string
|
||||
*/
|
||||
public function read($id);
|
||||
/**
|
||||
* Writes a session.
|
||||
*
|
||||
* @param string session id
|
||||
* @param string session data
|
||||
* @return boolean
|
||||
*/
|
||||
public function write($id, $data);
|
||||
|
||||
/**
|
||||
* Writes a session.
|
||||
*
|
||||
* @param string session id
|
||||
* @param string session data
|
||||
* @return boolean
|
||||
*/
|
||||
public function write($id, $data);
|
||||
/**
|
||||
* Destroys a session.
|
||||
*
|
||||
* @param string session id
|
||||
* @return boolean
|
||||
*/
|
||||
public function destroy($id);
|
||||
|
||||
/**
|
||||
* Destroys a session.
|
||||
*
|
||||
* @param string session id
|
||||
* @return boolean
|
||||
*/
|
||||
public function destroy($id);
|
||||
/**
|
||||
* Regenerates the session id.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function regenerate();
|
||||
|
||||
/**
|
||||
* Regenerates the session id.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function regenerate();
|
||||
|
||||
/**
|
||||
* Garbage collection.
|
||||
*
|
||||
* @param integer session expiration period
|
||||
* @return boolean
|
||||
*/
|
||||
public function gc($maxlifetime);
|
||||
|
||||
} // End Session Driver Interface
|
||||
/**
|
||||
* Garbage collection.
|
||||
*
|
||||
* @param integer session expiration period
|
||||
* @return boolean
|
||||
*/
|
||||
public function gc($maxlifetime);
|
||||
}
|
||||
// End Session Driver Interface
|
||||
|
||||
@@ -1,4 +1,12 @@
|
||||
<?php defined('SYSPATH') OR die('No direct access allowed.');
|
||||
<?php
|
||||
|
||||
// phpcs:disable PSR1.Classes.ClassDeclaration.MissingNamespace
|
||||
// phpcs:disable PSR1.Files.SideEffects
|
||||
defined('SYSPATH') or die('No direct access allowed.');
|
||||
// phpcs:enable PSR1.Files.SideEffects
|
||||
// phpcs:disable Squiz.Classes.ValidClassName.NotCamelCaps
|
||||
|
||||
|
||||
/**
|
||||
* Session cache driver.
|
||||
*
|
||||
@@ -17,89 +25,85 @@
|
||||
* @copyright (c) 2007-2008 Kohana Team
|
||||
* @license http://kohanaphp.com/license.html
|
||||
*/
|
||||
class Session_Cache_Driver implements Session_Driver {
|
||||
class Session_Cache_Driver implements Session_Driver
|
||||
{
|
||||
protected $cache;
|
||||
protected $encrypt;
|
||||
|
||||
protected $cache;
|
||||
protected $encrypt;
|
||||
public function __construct()
|
||||
{
|
||||
// Load Encrypt library
|
||||
if (Kohana::config('session.encryption')) {
|
||||
$this->encrypt = new Encrypt();
|
||||
}
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
// Load Encrypt library
|
||||
if (Kohana::config('session.encryption'))
|
||||
{
|
||||
$this->encrypt = new Encrypt;
|
||||
}
|
||||
Kohana::log('debug', 'Session Cache Driver Initialized');
|
||||
}
|
||||
|
||||
Kohana::log('debug', 'Session Cache Driver Initialized');
|
||||
}
|
||||
public function open($path, $name)
|
||||
{
|
||||
$config = Kohana::config('session.storage');
|
||||
|
||||
public function open($path, $name)
|
||||
{
|
||||
$config = Kohana::config('session.storage');
|
||||
if (empty($config)) {
|
||||
// Load the default group
|
||||
$config = Kohana::config('cache.default');
|
||||
} elseif (is_string($config)) {
|
||||
$name = $config;
|
||||
|
||||
if (empty($config))
|
||||
{
|
||||
// Load the default group
|
||||
$config = Kohana::config('cache.default');
|
||||
}
|
||||
elseif (is_string($config))
|
||||
{
|
||||
$name = $config;
|
||||
// Test the config group name
|
||||
if (($config = Kohana::config('cache.' . $config)) === null) {
|
||||
throw new Kohana_Exception('cache.undefined_group', $name);
|
||||
}
|
||||
}
|
||||
|
||||
// Test the config group name
|
||||
if (($config = Kohana::config('cache.'.$config)) === NULL)
|
||||
throw new Kohana_Exception('cache.undefined_group', $name);
|
||||
}
|
||||
$config['lifetime'] = (Kohana::config('session.expiration') == 0) ? 86400 : Kohana::config('session.expiration');
|
||||
$this->cache = new Cache($config);
|
||||
|
||||
$config['lifetime'] = (Kohana::config('session.expiration') == 0) ? 86400 : Kohana::config('session.expiration');
|
||||
$this->cache = new Cache($config);
|
||||
return is_object($this->cache);
|
||||
}
|
||||
|
||||
return is_object($this->cache);
|
||||
}
|
||||
public function close()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
public function close()
|
||||
{
|
||||
return TRUE;
|
||||
}
|
||||
public function read($id)
|
||||
{
|
||||
$id = 'session_' . $id;
|
||||
if ($data = $this->cache->get($id)) {
|
||||
return Kohana::config('session.encryption') ? $this->encrypt->decode($data) : $data;
|
||||
}
|
||||
|
||||
public function read($id)
|
||||
{
|
||||
$id = 'session_'.$id;
|
||||
if ($data = $this->cache->get($id))
|
||||
{
|
||||
return Kohana::config('session.encryption') ? $this->encrypt->decode($data) : $data;
|
||||
}
|
||||
// Return value must be string, NOT a boolean
|
||||
return '';
|
||||
}
|
||||
|
||||
// Return value must be string, NOT a boolean
|
||||
return '';
|
||||
}
|
||||
public function write($id, $data)
|
||||
{
|
||||
$id = 'session_' . $id;
|
||||
$data = Kohana::config('session.encryption') ? $this->encrypt->encode($data) : $data;
|
||||
|
||||
public function write($id, $data)
|
||||
{
|
||||
$id = 'session_'.$id;
|
||||
$data = Kohana::config('session.encryption') ? $this->encrypt->encode($data) : $data;
|
||||
return $this->cache->set($id, $data);
|
||||
}
|
||||
|
||||
return $this->cache->set($id, $data);
|
||||
}
|
||||
public function destroy($id)
|
||||
{
|
||||
$id = 'session_' . $id;
|
||||
return $this->cache->delete($id);
|
||||
}
|
||||
|
||||
public function destroy($id)
|
||||
{
|
||||
$id = 'session_'.$id;
|
||||
return $this->cache->delete($id);
|
||||
}
|
||||
public function regenerate()
|
||||
{
|
||||
session_regenerate_id(true);
|
||||
|
||||
public function regenerate()
|
||||
{
|
||||
session_regenerate_id(TRUE);
|
||||
// Return new session id
|
||||
return session_id();
|
||||
}
|
||||
|
||||
// Return new session id
|
||||
return session_id();
|
||||
}
|
||||
|
||||
public function gc($maxlifetime)
|
||||
{
|
||||
// Just return, caches are automatically cleaned up
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
} // End Session Cache Driver
|
||||
public function gc($maxlifetime)
|
||||
{
|
||||
// Just return, caches are automatically cleaned up
|
||||
return true;
|
||||
}
|
||||
}
|
||||
// End Session Cache Driver
|
||||
|
||||
@@ -1,4 +1,12 @@
|
||||
<?php defined('SYSPATH') OR die('No direct access allowed.');
|
||||
<?php
|
||||
|
||||
// phpcs:disable PSR1.Classes.ClassDeclaration.MissingNamespace
|
||||
// phpcs:disable PSR1.Files.SideEffects
|
||||
defined('SYSPATH') or die('No direct access allowed.');
|
||||
// phpcs:enable PSR1.Files.SideEffects
|
||||
// phpcs:disable Squiz.Classes.ValidClassName.NotCamelCaps
|
||||
|
||||
|
||||
/**
|
||||
* Session cookie driver.
|
||||
*
|
||||
@@ -9,72 +17,71 @@
|
||||
* @copyright (c) 2007-2008 Kohana Team
|
||||
* @license http://kohanaphp.com/license.html
|
||||
*/
|
||||
class Session_Cookie_Driver implements Session_Driver {
|
||||
class Session_Cookie_Driver implements Session_Driver
|
||||
{
|
||||
protected $cookie_name;
|
||||
protected $encrypt; // Library
|
||||
|
||||
protected $cookie_name;
|
||||
protected $encrypt; // Library
|
||||
public function __construct()
|
||||
{
|
||||
$this->cookie_name = Kohana::config('session.name') . '_data';
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
$this->cookie_name = Kohana::config('session.name').'_data';
|
||||
if (Kohana::config('session.encryption')) {
|
||||
$this->encrypt = Encrypt::instance();
|
||||
}
|
||||
|
||||
if (Kohana::config('session.encryption'))
|
||||
{
|
||||
$this->encrypt = Encrypt::instance();
|
||||
}
|
||||
Kohana::log('debug', 'Session Cookie Driver Initialized');
|
||||
}
|
||||
|
||||
Kohana::log('debug', 'Session Cookie Driver Initialized');
|
||||
}
|
||||
public function open($path, $name)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
public function open($path, $name)
|
||||
{
|
||||
return TRUE;
|
||||
}
|
||||
public function close()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
public function close()
|
||||
{
|
||||
return TRUE;
|
||||
}
|
||||
public function read($id)
|
||||
{
|
||||
$data = (string) cookie::get($this->cookie_name);
|
||||
|
||||
public function read($id)
|
||||
{
|
||||
$data = (string) cookie::get($this->cookie_name);
|
||||
if ($data == '') {
|
||||
return $data;
|
||||
}
|
||||
|
||||
if ($data == '')
|
||||
return $data;
|
||||
return empty($this->encrypt) ? base64_decode($data) : $this->encrypt->decode($data);
|
||||
}
|
||||
|
||||
return empty($this->encrypt) ? base64_decode($data) : $this->encrypt->decode($data);
|
||||
}
|
||||
public function write($id, $data)
|
||||
{
|
||||
$data = empty($this->encrypt) ? base64_encode($data) : $this->encrypt->encode($data);
|
||||
|
||||
public function write($id, $data)
|
||||
{
|
||||
$data = empty($this->encrypt) ? base64_encode($data) : $this->encrypt->encode($data);
|
||||
if (strlen($data) > 4048) {
|
||||
Kohana::log('error', 'Session (' . $id . ') data exceeds the 4KB limit, ignoring write.');
|
||||
return false;
|
||||
}
|
||||
|
||||
if (strlen($data) > 4048)
|
||||
{
|
||||
Kohana::log('error', 'Session ('.$id.') data exceeds the 4KB limit, ignoring write.');
|
||||
return FALSE;
|
||||
}
|
||||
return cookie::set($this->cookie_name, $data, Kohana::config('session.expiration'));
|
||||
}
|
||||
|
||||
return cookie::set($this->cookie_name, $data, Kohana::config('session.expiration'));
|
||||
}
|
||||
public function destroy($id)
|
||||
{
|
||||
return cookie::delete($this->cookie_name);
|
||||
}
|
||||
|
||||
public function destroy($id)
|
||||
{
|
||||
return cookie::delete($this->cookie_name);
|
||||
}
|
||||
public function regenerate()
|
||||
{
|
||||
session_regenerate_id(true);
|
||||
|
||||
public function regenerate()
|
||||
{
|
||||
session_regenerate_id(TRUE);
|
||||
// Return new id
|
||||
return session_id();
|
||||
}
|
||||
|
||||
// Return new id
|
||||
return session_id();
|
||||
}
|
||||
|
||||
public function gc($maxlifetime)
|
||||
{
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
} // End Session Cookie Driver Class
|
||||
public function gc($maxlifetime)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
// End Session Cookie Driver Class
|
||||
|
||||
@@ -1,4 +1,12 @@
|
||||
<?php defined('SYSPATH') OR die('No direct access allowed.');
|
||||
<?php
|
||||
|
||||
// phpcs:disable PSR1.Classes.ClassDeclaration.MissingNamespace
|
||||
// phpcs:disable PSR1.Files.SideEffects
|
||||
defined('SYSPATH') or die('No direct access allowed.');
|
||||
// phpcs:enable PSR1.Files.SideEffects
|
||||
// phpcs:disable Squiz.Classes.ValidClassName.NotCamelCaps
|
||||
|
||||
|
||||
/**
|
||||
* Session database driver.
|
||||
*
|
||||
@@ -9,155 +17,145 @@
|
||||
* @copyright (c) 2007-2008 Kohana Team
|
||||
* @license http://kohanaphp.com/license.html
|
||||
*/
|
||||
class Session_Database_Driver implements Session_Driver {
|
||||
class Session_Database_Driver implements Session_Driver
|
||||
{
|
||||
/*
|
||||
CREATE TABLE sessions
|
||||
(
|
||||
session_id VARCHAR(127) NOT NULL,
|
||||
last_activity INT(10) UNSIGNED NOT NULL,
|
||||
data TEXT NOT NULL,
|
||||
PRIMARY KEY (session_id)
|
||||
);
|
||||
*/
|
||||
|
||||
/*
|
||||
CREATE TABLE sessions
|
||||
(
|
||||
session_id VARCHAR(127) NOT NULL,
|
||||
last_activity INT(10) UNSIGNED NOT NULL,
|
||||
data TEXT NOT NULL,
|
||||
PRIMARY KEY (session_id)
|
||||
);
|
||||
*/
|
||||
// Database settings
|
||||
protected $db = 'default';
|
||||
protected $table = 'sessions';
|
||||
|
||||
// Database settings
|
||||
protected $db = 'default';
|
||||
protected $table = 'sessions';
|
||||
// Encryption
|
||||
protected $encrypt;
|
||||
|
||||
// Encryption
|
||||
protected $encrypt;
|
||||
// Session settings
|
||||
protected $session_id;
|
||||
protected $written = false;
|
||||
|
||||
// Session settings
|
||||
protected $session_id;
|
||||
protected $written = FALSE;
|
||||
public function __construct()
|
||||
{
|
||||
// Load configuration
|
||||
$config = Kohana::config('session');
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
// Load configuration
|
||||
$config = Kohana::config('session');
|
||||
if (! empty($config['encryption'])) {
|
||||
// Load encryption
|
||||
$this->encrypt = Encrypt::instance();
|
||||
}
|
||||
|
||||
if ( ! empty($config['encryption']))
|
||||
{
|
||||
// Load encryption
|
||||
$this->encrypt = Encrypt::instance();
|
||||
}
|
||||
if (is_array($config['storage'])) {
|
||||
if (! empty($config['storage']['group'])) {
|
||||
// Set the group name
|
||||
$this->db = $config['storage']['group'];
|
||||
}
|
||||
|
||||
if (is_array($config['storage']))
|
||||
{
|
||||
if ( ! empty($config['storage']['group']))
|
||||
{
|
||||
// Set the group name
|
||||
$this->db = $config['storage']['group'];
|
||||
}
|
||||
if (! empty($config['storage']['table'])) {
|
||||
// Set the table name
|
||||
$this->table = $config['storage']['table'];
|
||||
}
|
||||
}
|
||||
|
||||
if ( ! empty($config['storage']['table']))
|
||||
{
|
||||
// Set the table name
|
||||
$this->table = $config['storage']['table'];
|
||||
}
|
||||
}
|
||||
// Load database
|
||||
$this->db = Database::instance($this->db);
|
||||
|
||||
// Load database
|
||||
$this->db = Database::instance($this->db);
|
||||
Kohana::log('debug', 'Session Database Driver Initialized');
|
||||
}
|
||||
|
||||
Kohana::log('debug', 'Session Database Driver Initialized');
|
||||
}
|
||||
public function open($path, $name)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
public function open($path, $name)
|
||||
{
|
||||
return TRUE;
|
||||
}
|
||||
public function close()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
public function close()
|
||||
{
|
||||
return TRUE;
|
||||
}
|
||||
public function read($id)
|
||||
{
|
||||
// Load the session
|
||||
$query = $this->db->from($this->table)->where('session_id', $id)->limit(1)->get()->result(true);
|
||||
|
||||
public function read($id)
|
||||
{
|
||||
// Load the session
|
||||
$query = $this->db->from($this->table)->where('session_id', $id)->limit(1)->get()->result(TRUE);
|
||||
if ($query->count() === 0) {
|
||||
// No current session
|
||||
$this->session_id = null;
|
||||
|
||||
if ($query->count() === 0)
|
||||
{
|
||||
// No current session
|
||||
$this->session_id = NULL;
|
||||
return '';
|
||||
}
|
||||
|
||||
return '';
|
||||
}
|
||||
// Set the current session id
|
||||
$this->session_id = $id;
|
||||
|
||||
// Set the current session id
|
||||
$this->session_id = $id;
|
||||
// Load the data
|
||||
$data = $query->current()->data;
|
||||
|
||||
// Load the data
|
||||
$data = $query->current()->data;
|
||||
return ($this->encrypt === null) ? base64_decode($data) : $this->encrypt->decode($data);
|
||||
}
|
||||
|
||||
return ($this->encrypt === NULL) ? base64_decode($data) : $this->encrypt->decode($data);
|
||||
}
|
||||
public function write($id, $data)
|
||||
{
|
||||
$data = array
|
||||
(
|
||||
'session_id' => $id,
|
||||
'last_activity' => time(),
|
||||
'data' => ($this->encrypt === null) ? base64_encode($data) : $this->encrypt->encode($data)
|
||||
);
|
||||
|
||||
public function write($id, $data)
|
||||
{
|
||||
$data = array
|
||||
(
|
||||
'session_id' => $id,
|
||||
'last_activity' => time(),
|
||||
'data' => ($this->encrypt === NULL) ? base64_encode($data) : $this->encrypt->encode($data)
|
||||
);
|
||||
if ($this->session_id === null) {
|
||||
// Insert a new session
|
||||
$query = $this->db->insert($this->table, $data);
|
||||
} elseif ($id === $this->session_id) {
|
||||
// Do not update the session_id
|
||||
unset($data['session_id']);
|
||||
|
||||
if ($this->session_id === NULL)
|
||||
{
|
||||
// Insert a new session
|
||||
$query = $this->db->insert($this->table, $data);
|
||||
}
|
||||
elseif ($id === $this->session_id)
|
||||
{
|
||||
// Do not update the session_id
|
||||
unset($data['session_id']);
|
||||
// Update the existing session
|
||||
$query = $this->db->update($this->table, $data, array('session_id' => $id));
|
||||
} else {
|
||||
// Update the session and id
|
||||
$query = $this->db->update($this->table, $data, array('session_id' => $this->session_id));
|
||||
|
||||
// Update the existing session
|
||||
$query = $this->db->update($this->table, $data, array('session_id' => $id));
|
||||
}
|
||||
else
|
||||
{
|
||||
// Update the session and id
|
||||
$query = $this->db->update($this->table, $data, array('session_id' => $this->session_id));
|
||||
// Set the new session id
|
||||
$this->session_id = $id;
|
||||
}
|
||||
|
||||
// Set the new session id
|
||||
$this->session_id = $id;
|
||||
}
|
||||
return (bool) $query->count();
|
||||
}
|
||||
|
||||
return (bool) $query->count();
|
||||
}
|
||||
public function destroy($id)
|
||||
{
|
||||
// Delete the requested session
|
||||
$this->db->delete($this->table, array('session_id' => $id));
|
||||
|
||||
public function destroy($id)
|
||||
{
|
||||
// Delete the requested session
|
||||
$this->db->delete($this->table, array('session_id' => $id));
|
||||
// Session id is no longer valid
|
||||
$this->session_id = null;
|
||||
|
||||
// Session id is no longer valid
|
||||
$this->session_id = NULL;
|
||||
return true;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
public function regenerate()
|
||||
{
|
||||
// Generate a new session id
|
||||
session_regenerate_id();
|
||||
|
||||
public function regenerate()
|
||||
{
|
||||
// Generate a new session id
|
||||
session_regenerate_id();
|
||||
// Return new session id
|
||||
return session_id();
|
||||
}
|
||||
|
||||
// Return new session id
|
||||
return session_id();
|
||||
}
|
||||
public function gc($maxlifetime)
|
||||
{
|
||||
// Delete all expired sessions
|
||||
$query = $this->db->delete($this->table, array('last_activity <' => time() - $maxlifetime));
|
||||
|
||||
public function gc($maxlifetime)
|
||||
{
|
||||
// Delete all expired sessions
|
||||
$query = $this->db->delete($this->table, array('last_activity <' => time() - $maxlifetime));
|
||||
Kohana::log('debug', 'Session garbage collected: ' . $query->count() . ' row(s) deleted.');
|
||||
|
||||
Kohana::log('debug', 'Session garbage collected: '.$query->count().' row(s) deleted.');
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
} // End Session Database Driver
|
||||
return true;
|
||||
}
|
||||
}
|
||||
// End Session Database Driver
|
||||
|
||||
Reference in New Issue
Block a user