Last active
June 20, 2020 01:06
-
-
Save bkader/90c4fc4fce199fd04d2ea2deddf2126b to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
defined('BASEPATH') OR exit('No direct script access allowed'); | |
/** | |
* Dinabase Class | |
* | |
* @package CodeIgniter | |
* @subpackage Libraries | |
* @author Kader Bouyakoub <[email protected]> | |
* @link http://www.bkader.com/ | |
* @license MIT, DBAD | |
* | |
* INFORMATIONS: | |
* | |
* This library allow you to get rid of other database engine | |
* as its uses flat-files with content encoded usin json_ecode | |
* or bson_encode (if the function exists - php mongo ext needed) | |
* | |
* Make sure to create a config file for this library and name it | |
* "dinabase.php" inside which you put: | |
* | |
* $config['path'] path to your data folder with trailing slash. | |
* $config['database'] name of the main database folder. | |
* | |
* That's it! Feel free to use it by please, DBAD. | |
* | |
* HOW TO USE: | |
* | |
* You simply need to load the library inside your controller or another | |
* library and pass the tablename so it works. | |
* | |
* i.e: $this->load->library('dinabase', array('tablename' => 'users')); | |
* | |
* 'users' folder will be automatically created inside your data folder | |
* and you can after proceed to using the library. | |
* | |
* Dinabase tables accept any values types because the result will be | |
* either a JSON encoded or BSON encoded if you have Mongodb extension | |
* enabled. | |
* | |
*/ | |
class Dinabase | |
{ | |
protected $CI; | |
/** | |
* @var string - folder where database files will be stored | |
*/ | |
protected $path = null; | |
/** | |
* @var string - database name | |
*/ | |
protected $database = null; | |
/** | |
* @var string - table name | |
*/ | |
protected $tablename = null; | |
/** | |
* @var string - path to data folder | |
*/ | |
protected $data_dir = null; | |
/** | |
* @var string - path to table folder | |
*/ | |
protected $table_dir = null; | |
/** | |
* Creates a new database instance | |
* @access public | |
* @param string $data_path | |
* @param string $dbname | |
*/ | |
public function __construct($config = array()) | |
{ | |
// Prepare CI object | |
$this->CI =& get_instance(); | |
// Load library configuration file | |
$this->CI->load->config('dinabase'); | |
// Prepare path to data folder | |
$config['path'] = config_item('path') | |
? config_item('path') | |
: APPPATH.'data'.DS; | |
$this->path = $config['path']; | |
// Create data folder if it does not already exist. | |
if ( ! is_dir($this->path)) | |
{ | |
// Create the data folder | |
if ( ! mkdir($this->path, 0777, true)) | |
{ | |
throw new Exception("Could not create data folder. Permission Denied!"); | |
} | |
// Write our protection index.php | |
else | |
{ | |
$this->_create_index($this->path); | |
} | |
} | |
// Set database connection | |
$config['database'] = config_item('database') | |
? config_item('database') | |
: 'main'; | |
$this->database = $config['database']; | |
// Make sure the database folder exists or create it | |
if ( ! is_dir($this->path.$this->database)) | |
{ | |
if ( ! mkdir($this->path.$this->database, 0755, true)) | |
{ | |
throw new Exception("Could not create database. Permission Denied!"); | |
} | |
else | |
{ | |
$this->_create_index($this->path.$this->database); | |
} | |
} | |
// Prepare table name | |
isset($config['tablename']) or $config['tablename'] = null; | |
if ($config['tablename'] !== null) | |
{ | |
$this->tablename = $config['tablename']; | |
//debug($this->data_dir.$this->tablename, true); | |
// Create the table now | |
if ( ! is_dir($this->data_dir.$this->tablename)) | |
if ( ! @mkdir($this->data_dir.$this->tablename, 0755, true)) | |
throw new Exception("Could not create database table. Permission Denied!"); | |
else | |
$this->_create_index($this->data_dir.$this->tablename); | |
} | |
$this->data_dir = $this->path.$this->database.DS; | |
if ($this->tablename !== null) | |
{ | |
$this->table_dir = $this->data_dir.$this->tablename.DS; | |
} | |
} | |
/** | |
* Insert new record into table | |
* @access public | |
* @param array $data array of key=>value | |
* @param string $tablename table name | |
* @return boolean | |
*/ | |
public function insert(array $data, $tablename = null) | |
{ | |
$tablename or $tablename = $this->tablename; | |
if ($tablename !== null) | |
{ | |
$guid = $this->_generate_guid(); | |
$data = array_merge(array('id' => $guid), $data); | |
$row_file = $this->table_dir.md5($guid).'.dat'; | |
// return serialize($data); | |
if ( ! file_put_contents($row_file, bson_encode($data))) | |
throw new Exception("Could not insert new record."); | |
return true; | |
} | |
return false; | |
} | |
/** | |
* Retrieves a single row by its ID | |
* @access public | |
* @param string $id ID of the row to retrieve | |
* @param string $tablename | |
* @return array | |
*/ | |
public function find($id, $tablename = null) | |
{ | |
$tablename or $tablename = $this->tablename; | |
return $this->find_one('id', $id, $tablename); | |
} | |
/** | |
* Retrieves multiple rows by conditions | |
* @access public | |
* @param mixed $field field name or array of WHERE | |
* @param mixed | |
* @param string $tablename | |
* @return array | |
*/ | |
public function find_one($field, $match = null, $tablename = null) | |
{ | |
$tablename or $tablename = $this->tablename; | |
if($rows = $this->_read_rows($tablename)) | |
{ | |
$where = (is_array($field) and $match === null) | |
? $field : array($field => $match); | |
if ($indexes = $this->_search_array($rows, $where)) | |
{ | |
return $rows[$indexes[0]]; | |
} | |
return false; | |
} | |
return false; | |
} | |
/** | |
* Retrieves multiple or all rows inside a table | |
* @access public | |
* @param array $where array of WHERE statements | |
* @param string $tablename | |
* @return array | |
*/ | |
public function find_all($where = array(), $tablename = null) | |
{ | |
$tablename or $tablename = $this->tablename; | |
if ($rows = $this->_read_rows($tablename)) | |
{ | |
$_found = false; | |
if ($indexes = $this->_search_array($rows, $where)) | |
{ | |
foreach ($indexes as $index) | |
{ | |
$_found[$index] = $rows[$index]; | |
} | |
} | |
return $_found; | |
} | |
return false; | |
} | |
/** | |
* Alias of the method above for CI active records fans | |
* @access public | |
* @param array | |
* @param string | |
* @return array | |
*/ | |
public function get_where($where = array(), $tablename = null) | |
{ | |
return $this->find_all($where, $tablename); | |
} | |
/** | |
* Alias of the find_all but it takes only table name | |
* so it retrieves all records. | |
* @access public | |
* @param string $tablename | |
* @return array | |
*/ | |
public function all($tablename = null) | |
{ | |
return $this->find_all(array(), $tablename); | |
} | |
/** | |
* Updates an existing row by its ID | |
* @access public | |
* @param string $id ID of the row to update | |
* @param array $data array of SET statements | |
* @param string $tablename | |
* @return boolean | |
*/ | |
public function update($id, array $data, $tablename = null) | |
{ | |
$tablename or $tablename = $this->tablename; | |
if ($row = $this->find($id)) | |
{ | |
foreach($data as $key => $value) | |
{ | |
$row[$key] = $value; | |
} | |
$file = $this->data_dir.$tablename.DS.md5($row['id']).'.dat'; | |
$content = function_exists('bson_encode') | |
? bson_encode($row) | |
: json_encode($row); | |
if (file_put_contents($file, $content)) | |
return true; | |
return false; | |
} | |
return false; | |
} | |
/** | |
* Updates multiple or all rows | |
* @access public | |
* @param array $data array of SET statements | |
* @param array $where array of WHERE statements | |
* @param string $tablename | |
* @return boolean | |
*/ | |
public function update_all(array $data, $where = array(), $tablename = null) | |
{ | |
$tablename or $tablename = $this->tablename; | |
if ($rows = $this->find_all($where)) | |
{ | |
foreach($rows as $id => $row) | |
$this->update($id, $data, $tablename); | |
return true; | |
} | |
return false; | |
} | |
/** | |
* Deletes a single existing row by its ID | |
* @access public | |
* @param string $id ID of the row to delete | |
* @param string $tablename | |
* @return boolean | |
*/ | |
public function delete($id, $tablename = null) | |
{ | |
$tablename or $tablename = $this->tablename; | |
return $this->delete_all(array('id' => $id), $tablename); | |
} | |
/** | |
* Deletes multiple or all rows by conditions | |
* @access public | |
* @param array $where array of WHERE statements | |
* @param string $tablename | |
* @return boolean | |
*/ | |
public function delete_all($where = array(), $tablename = null) | |
{ | |
$tablename or $tablename = $this->tablename; | |
if ($tablename !== null and $rows = $this->find_all($where)) | |
{ | |
foreach($rows as $id => $row) | |
{ | |
if (isset($row['deleted'])) | |
{ | |
if ((bool) $row['deleted'] === false) | |
{ | |
$this->update($id, array( | |
'deleted' => true, | |
'deleted_at' => time(), | |
)); | |
} | |
} | |
else | |
{ | |
$this->remove($id, $tablename); | |
} | |
} | |
return true; | |
} | |
return false; | |
} | |
/** | |
* Completely removes a single row bypassing soft delete | |
* @access public | |
* @param string $id ID of the row to delete | |
* @param string $tablename | |
* @return boolean | |
*/ | |
public function remove($id, $tablename = null) | |
{ | |
$tablename or $tablename = $this->tablename; | |
return $this->remove_all(array('id' => $id)); | |
} | |
/** | |
* Completely remove multiple or all rows bypassing soft delete | |
* @access public | |
* @param array $where array of where statements | |
* @param string $tablename | |
* @return boolean | |
*/ | |
public function remove_all(array $where, $tablename = null) | |
{ | |
$tablename or $tablename = $this->tablename; | |
if ($tablename !== null and $rows = $this->find_all($where)) | |
{ | |
$files = array(); | |
foreach($rows as $id => $row) | |
{ | |
$files[] = $this->table_dir.md5($row['id']).'.dat'; | |
} | |
if ( ! empty($files)) | |
{ | |
foreach($files as $file) | |
@unlink($file); | |
return true; | |
} | |
return false; | |
} | |
return false; | |
} | |
/** | |
* Searches inside an array | |
* @access protected | |
* @param array $array | |
* @param array $where | |
*/ | |
protected function _search_array(array $array, array $where) | |
{ | |
$found = false; | |
foreach ($array as $aKey => $aVal) | |
{ | |
$coincidences = 0; | |
foreach ($where as $pKey => $pVal) | |
{ | |
if (array_key_exists($pKey, $aVal) && $aVal[$pKey] == $pVal) | |
{ | |
$coincidences++; | |
} | |
} | |
if ($coincidences == count($where)) | |
{ | |
$found[] = $aKey; | |
} | |
} | |
return $found; | |
} | |
/** | |
* Read all row inside table folder | |
* @access protected | |
* @param string $tablename | |
* @return array | |
*/ | |
protected function _read_rows($tablename = null) | |
{ | |
$tablename or $tablename = $this->tablename; | |
if ($tablename !== null) | |
{ | |
$rows = array(); | |
foreach(glob($this->table_dir.'*.dat') as $row) | |
{ | |
$index = preg_replace('/\\.[^.\\s]{3,4}$/', '', basename($row)); | |
$row = file_get_contents($row); | |
$decoded = function_exists('bson_decode') | |
? bson_decode($row) | |
: json_decode($row); | |
$rows[$decoded['id']] = $decoded; | |
} | |
return $rows; | |
} | |
return false; | |
} | |
/** | |
* Create the index.php protection file | |
* @access protected | |
* @param string $path path where the create the file | |
* @return void | |
*/ | |
protected function _create_index($path) | |
{ | |
$o = umask(0); | |
file_put_contents( | |
$path.DS.'index.php', | |
'<?php'."\n".'die("Directory access is forbidden.");'."\n" | |
); | |
umask($o); | |
} | |
/** | |
* Generates a fresh new GUID | |
* @access protected | |
* @param none | |
* @return string | |
*/ | |
protected function _generate_guid($striped = true) | |
{ | |
$guid = '%04x%04x-%04x-%04x-%04x-%04x%04x%04x'; | |
if ($striped === true) | |
$guid = '%04x%04x%04x%04x%04x%04x%04x%04x'; | |
return vsprintf($guid, array( | |
mt_rand(0, 0xffff), mt_rand(0, 0xffff), | |
mt_rand(0, 0xffff), | |
mt_rand(0, 0x0fff) | 0x4000, | |
mt_rand(0, 0x3fff) | 0x8000, | |
mt_rand(0, 0xffff), mt_rand(0, 0xffff), mt_rand(0, 0xffff), | |
)); | |
} | |
} | |
/* End of file Dinabase.php */ | |
/* Location: ./application/libraries/Dinabase.php */ |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment