Advertisement
bkader

CodeIgniter Filebase.php - File-base database

Aug 6th, 2016
409
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
PHP 27.15 KB | None | 0 0
  1. <?php
  2. defined('BASEPATH') OR exit('No direct script access allowed');
  3.  
  4. /**
  5.  * CodeIgniter Filebase Class
  6.  *
  7.  *  HOW TO USE - see at the bottom of the file.
  8.  *  
  9.  * @package     CodeIgniter
  10.  * @subpackage  Third Party
  11.  * @category    File-based database engine
  12.  * @author  Kader Bouyakoub <bkader@mail.com>
  13.  * @link    https://github.com/bkader/filebase
  14.  * @link    http://www.bkader.com/
  15.  */
  16.  
  17. // Make sure the DIRECTORY_SEPARATOR is defined
  18. defined('DS') OR define('DS', DIRECTORY_SEPARATOR);
  19.  
  20. class Filebase
  21. {
  22.     /**
  23.      * @var string - path to data folder
  24.      */
  25.     protected $path = NULL;
  26.  
  27.     /**
  28.      * @var string - main database name
  29.      */
  30.     protected $database = NULL;
  31.  
  32.     /**
  33.      * @var string - table name set when class is called
  34.      */
  35.     protected $table = NULL;
  36.  
  37.     /**
  38.      * @var string - realpath to the data folder
  39.      */
  40.     protected $data_dir = NULL;
  41.  
  42.     /**
  43.      * @var string - realpath to table folder
  44.      */
  45.     protected $table_dir = NULL;
  46.  
  47.     /**
  48.      * @var array - array of ALL tables' indices
  49.      */
  50.     protected $indices = array();
  51.  
  52.     /**
  53.      * @var boolean - turn on/off safe delete
  54.      */
  55.     protected $safe_delete = FALSE;
  56.  
  57.     /**
  58.      * @var array - array of fields with unique values.
  59.      */
  60.     protected $unique_fields = array();
  61.  
  62.     /**
  63.      * Constructor:
  64.      * We start by settings our path, database, table, data_dir and table_dir
  65.      * @access  public
  66.      * @param   array   $config     array of class config.
  67.      * @param   string  $database   the database name
  68.      */
  69.     public function __construct($config = array(), $database = 'main')
  70.     {
  71.         // We start by setting real path to data folder.
  72.         $this->path = realpath(($config['path'] !== NULL) ? $config['path'] : './').DS;
  73.  
  74.         // We set our database
  75.         $this->db   = $database;
  76.  
  77.         // Set path to data folder and create it if it does snot exist.
  78.         $this->data_dir = $this->path.$this->db.DS;
  79.  
  80.         // Create all needed folder
  81.         $this->_create_datafolder();
  82.         $this->_create_database();
  83.  
  84.         // Make sure our table is set and not NULL so we can create
  85.         // our table's folder where files will be stored.
  86.         $this->table = $config['table'];
  87.         if ($this->table !== NULL)
  88.         {
  89.             $this->table_dir = $this->data_dir.$this->table.DS;
  90.         }
  91.         if ($this->table_dir !== NULL)
  92.         {
  93.             $this->_create_folder($this->table_dir);
  94.         }
  95.  
  96.         // Check if our safe delete is turned on.
  97.         if (isset($config['safe_delete']))
  98.         {
  99.             $this->safe_delete = (bool) $config['safe_delete'];
  100.         }
  101.  
  102.         // Are there any unique fields?
  103.         if (isset($config['unique_fields']) && is_array($config['unique_fields']))
  104.         {
  105.             $this->unique_fields = array_merge(
  106.                 $this->unique_fields,
  107.                 $config['unique_fields']
  108.             );
  109.         }
  110.  
  111.         // List all indices to be used to call files but also
  112.         // to keep track of records count.
  113.         $this->indices = $this->_list_indices();
  114.     }
  115.  
  116.     /*
  117.     |======================================================================
  118.     | READERS
  119.     |======================================================================
  120.     */
  121.  
  122.     /**
  123.      * Get the row where the value matches that of the key and return the value of the other key
  124.      *
  125.      * @param   string  $col    the column to get
  126.      * @param   string  $key    the key whose value to match
  127.      * @param   string  $val    the value to match
  128.      * @param   array   $table  the array to get from
  129.      *
  130.      * @return array
  131.      */
  132.     public function get($col, $key, $val, $table = NULL)
  133.     {
  134.         $table or $table = $this->table;
  135.         if ($table !== NULL and $rows = $this->all($table))
  136.         {
  137.             foreach ($rows as $row)
  138.             {
  139.                 if ($row[$key] === $val && $row[$col])
  140.                 {
  141.                     return $row[$col];
  142.                     break;
  143.                 }
  144.             }
  145.         }
  146.         return FALSE;
  147.     }
  148.  
  149.     /**
  150.      * Returns an array of selected columns for all rows
  151.      * @access  public
  152.      * @param   array   $cols   columns to get
  153.      * @param   string  $table  table name
  154.      * @return  array
  155.      */
  156.     public function select($cols = array(), $table = NULL)
  157.     {
  158.         $table or $table = $this->table;
  159.         if ($table !== NULL and $rows = $this->all($table))
  160.         {
  161.             $_result = array();
  162.             $_values = array();
  163.             if ($cols === array())
  164.             {
  165.                 foreach ($rows as $row)
  166.                 {
  167.                     foreach (array_keys($row) as $c)
  168.                     {
  169.                         $_values[$c] = $row[$c];
  170.                     }
  171.                     if ($_values)
  172.                     {
  173.                         $_result[] = $_values;
  174.                     }
  175.                     $_values = array();
  176.                 }
  177.             }
  178.             else
  179.             {
  180.                 foreach ($rows as $row)
  181.                 {
  182.                     foreach ((array) $cols as $c)
  183.                     {
  184.                         if ($row[$c])
  185.                             $_values[$c] = $row[$c];
  186.                     }
  187.                     if ($_values)
  188.                     {
  189.                         $_result[] = $_values;
  190.                     }
  191.                     $_values = array();
  192.                 }
  193.             }
  194.             return $_result;
  195.         }
  196.         return FALSE;
  197.     }
  198.  
  199.     /**
  200.      * Get columns from records in which key's value is part of an array of value
  201.      * @access  public
  202.      * @param   array   $cols   columns to get
  203.      * @param   string  $key    key to look for the value
  204.      * @param   array   $values array of value to be compared to
  205.      * @return  array
  206.      */
  207.     public function where_in($cols = array(), $key, $values = array(), $table = NULL)
  208.     {
  209.         $table or $table = $this->table;
  210.         if ($table !== NULL and $rows = $this->all($table))
  211.         {
  212.             $_result = array();
  213.             $_values = array();
  214.             if ($cols === array())
  215.             {
  216.                 foreach ($rows as $row)
  217.                 {
  218.                     if (in_array($row[$key], $values))
  219.                     {
  220.                         foreach (array_keys($row) as $c)
  221.                         {
  222.                             $_values[$c] = $row[$c];
  223.                         }
  224.                         $_result[] = $_values;
  225.                         $_values = array();
  226.                     }
  227.                 }
  228.             }
  229.             else
  230.             {
  231.                 foreach ($rows as $row)
  232.                 {
  233.                     if (in_array($row[$key], $values))
  234.                     {
  235.                         foreach ((array) $cols as $c)
  236.                         {
  237.                             $_values[$c] = $row[$c];
  238.                         }
  239.                         $_result[] = $_values;
  240.                         $_values = array();
  241.                     }
  242.                 }
  243.             }
  244.             return $_result;
  245.         }
  246.         return FALSE;
  247.     }
  248.  
  249.     /**
  250.      * Get columns from records in which key's value is NOT part of an array of value
  251.      * @access  public
  252.      * @param   array   $cols   columns to get
  253.      * @param   string  $key    key to look for the value
  254.      * @param   array   $values array of value to be compared to
  255.      * @return  array
  256.      */
  257.     public function where_not_in($cols = array(), $key, $values = array(), $table = NULL)
  258.     {
  259.         $table or $table = $this->table;
  260.         if ($table !== NULL and $rows = $this->all($table))
  261.         {
  262.             $_result = array();
  263.             $_values = array();
  264.             if ($cols === array())
  265.             {
  266.                 foreach ($rows as $row)
  267.                 {
  268.                     if ( ! in_array($row[$key], $values))
  269.                     {
  270.                         foreach (array_keys($row) as $c)
  271.                         {
  272.                             $_values[$c] = $row[$c];
  273.                         }
  274.                         $_result[] = $_values;
  275.                         $_values = array();
  276.                     }
  277.                 }
  278.             }
  279.             else
  280.             {
  281.                 foreach ($rows as $row)
  282.                 {
  283.                     if ( ! in_array($row[$key], $values))
  284.                     {
  285.                         foreach ((array) $cols as $c)
  286.                         {
  287.                             $_values[$c] = $row[$c];
  288.                         }
  289.                         $_result[] = $_values;
  290.                         $_values = array();
  291.                     }
  292.                 }
  293.             }
  294.             return $_result;
  295.         }
  296.         return FALSE;
  297.     }
  298.  
  299.     /**
  300.      * Matches keys and values bases on a regular expression
  301.      * @param  array $cols  the columns to return
  302.      * @param  string $key   the key to check
  303.      * @param  string $regex the regular expression to match
  304.      * @param  string $table table to execute the search on
  305.      * @return array
  306.      */
  307.     public function like($cols, $key, $regex, $table = NULL)
  308.     {
  309.         $table or $table = $this->table;
  310.         if ($table !== NULL and $rows = $this->all($table))
  311.         {
  312.             $_result = array();
  313.             $_values = array();
  314.             if ($cols === array())
  315.             {
  316.                 foreach ($rows as $row)
  317.                 {
  318.                     if (preg_match($regex, $row[$key]))
  319.                     {
  320.                         foreach (array_keys($row) as $c)
  321.                         {
  322.                             $_values[$c] = $row[$c];
  323.                         }
  324.                         $_result[] = $_values;
  325.                         $_values = array();
  326.                     }
  327.                 }
  328.             }
  329.             else
  330.             {
  331.                 foreach ($rows as $row)
  332.                 {
  333.                     if (preg_match($regex, $row[$key]))
  334.                     {
  335.                         foreach ((array) $cols as $c)
  336.                         {
  337.                             $_values[$c] = $row[$c];
  338.                         }
  339.                         $_result[] = $_values;
  340.                         $_values = array();
  341.                     }
  342.                 }
  343.             }
  344.             return $_result;
  345.         }
  346.         return FALSE;
  347.     }
  348.  
  349.     /**
  350.      * Matches keys and values bases on a regular expression
  351.      * @param  array $cols  the columns to return
  352.      * @param  string $key   the key to check
  353.      * @param  string $regex the regular expression to match
  354.      * @param  string $table table to execute the search on
  355.      * @return array
  356.      */
  357.     public function not_like($cols, $key, $regex, $table = NULL)
  358.     {
  359.         $table or $table = $this->table;
  360.         if ($table !== NULL and $rows = $this->all($table))
  361.         {
  362.             $_result = array();
  363.             $_values = array();
  364.             if ($cols === array())
  365.             {
  366.                 foreach ($rows as $row)
  367.                 {
  368.                     if ( ! preg_match($regex, $row[$key]))
  369.                     {
  370.                         foreach (array_keys($row) as $c)
  371.                         {
  372.                             $_values[$c] = $row[$c];
  373.                         }
  374.                         $_result[] = $_values;
  375.                         $_values = array();
  376.                     }
  377.                 }
  378.             }
  379.             else
  380.             {
  381.                 foreach ($rows as $row)
  382.                 {
  383.                     if ( ! preg_match($regex, $row[$key]))
  384.                     {
  385.                         foreach ((array) $cols as $c)
  386.                         {
  387.                             $_values[$c] = $row[$c];
  388.                         }
  389.                         $_result[] = $_values;
  390.                         $_values = array();
  391.                     }
  392.                 }
  393.             }
  394.             return $_result;
  395.         }
  396.         return FALSE;
  397.     }
  398.  
  399.     /**
  400.      * Retrieves a single row by its ID
  401.      * @access  public
  402.      * @param   string  $id     ID of the row to retrieve
  403.      * @param   string  $table
  404.      * @return  array
  405.      */
  406.     public function find($id, $table = NULL)
  407.     {
  408.         $table or $table = $this->table;
  409.         if ($table !== NULL and in_array(md5($id), $this->indices))
  410.         {
  411.             $content = file_get_contents($this->table_dir.md5($id).'.dat');
  412.             return $this->_unserialize($content);
  413.         }
  414.         return NULL;
  415.     }
  416.  
  417.     /**
  418.      * Retrieves multiple rows by conditions
  419.      * @access  public
  420.      * @param   mixed   $field  field name or array of WHERE
  421.      * @param   mixed
  422.      * @param   string  $table
  423.      * @return  array
  424.      */
  425.     public function find_one($field, $match = NULL, $table = NULL)
  426.     {
  427.         $table or $table = $this->table;
  428.         if($rows = $this->_read_files($table))
  429.         {
  430.             $where = (is_array($field) and $match === NULL) ? $field : array($field => $match);
  431.             if ($indices = $this->_search_array($rows, $where))
  432.             {
  433.                 return $rows[$indices[0]];
  434.             }
  435.             return NULL;
  436.         }
  437.         return NULL;
  438.     }
  439.  
  440.     /**
  441.      * Retrieves multiple or all rows inside a table
  442.      * @access  public
  443.      * @param   array   $where      array of WHERE statements
  444.      * @param   string  $table
  445.      * @return  array
  446.      */
  447.     // public function find_all($where = array(), $table = NULL)
  448.     public function find_all($field, $match = NULL, $table = NULL)
  449.     {
  450.         $table or $table = $this->table;
  451.         if ($rows = $this->_read_files($table))
  452.         {
  453.             $where = (is_array($field) AND $match === NULL)
  454.                     ? $field : array($field => $match);
  455.             $found = array();
  456.             if ($indices = $this->_search_array($rows, $where))
  457.             {
  458.                 foreach ($indices as $index)
  459.                 {
  460.                     $found[] = $rows[$index];
  461.                 }
  462.             }
  463.             return $found;
  464.         }
  465.         return NULL;
  466.     }
  467.  
  468.     /**
  469.      * Alias of the method above but it takes only the table nam
  470.      * so it would retrieve ALL records.
  471.      * @access  public
  472.      * @param   array   $where  array of WHERE statements
  473.      * @param   string  $table  table name
  474.      * @return  array
  475.      */
  476.     public function all($table = NULL)
  477.     {
  478.         return $this->find_all(array(), NULL, $table);
  479.     }
  480.  
  481.     /*
  482.     |======================================================================
  483.     | CRUD INTERFACE
  484.     |======================================================================
  485.     */
  486.  
  487.     /**
  488.      * Insert new record into table
  489.      * @access  public
  490.      * @param   array   $data       array of key=>value
  491.      * @param   string  $table  table name
  492.      * @return  boolean
  493.      */
  494.     public function insert($data, $table = NULL)
  495.     {
  496.         // Make sure to use a table, otherwise return FALSE
  497.         $table or $table = $this->table;
  498.         if ($this->table !== NULL)
  499.         {
  500.             // Prepare our default
  501.             $default = array();
  502.  
  503.             // Loop through all our records and append to $default
  504.             foreach($data as $key => $val)
  505.             {
  506.                 // Make sure there is no duplicate entry!
  507.                 if (in_array($key, $this->unique_fields)
  508.                     && $this->get($key, $key, $val))
  509.                 {
  510.                     throw new Exception("Duplicate entry '{$val}' for key '{$key}'.");
  511.                     break;
  512.                 }
  513.                 // Loop through and set our data
  514.                 $default[$key] = $val;
  515.             }
  516.  
  517.             // Generate new UUID and add it to the $data array
  518.             $guid = $this->_generate_guid();
  519.  
  520.             // Add both id and sid to $default.
  521.             $default = array_merge(
  522.                 array(  'id' => $guid,
  523.                         'sid' => $this->_shorten_guid($guid)),
  524.                 $default
  525.             );
  526.  
  527.             // Make sure to insert our created_at and created_by in case it is not set
  528.             $default['created_at'] = @$default['created_at'] ?: time();
  529.             $default['created_by'] = @$default['created_by'] ?: NULL;
  530.            
  531.             // This is the first time the file is created! So, we set our
  532.             // update fields and make them empty.
  533.             $default['updated_at'] = 0;
  534.             $default['updated_by'] = NULL;
  535.  
  536.             // Create safe delete fields if safe delete is turned on
  537.             if ($this->safe_delete === TRUE)
  538.             {
  539.                 $default['deleted']    = FALSE;
  540.                 $default['deleted_at'] = 0;
  541.                 $default['deleted_by'] = NULL;
  542.             }
  543.            
  544.             // Prepare out file to store, put content into file and
  545.             // return a simple the newly inserted ID.
  546.             $file = $this->table_dir.md5($guid).'.dat';
  547.             file_put_contents($file, $this->_serialize($default));
  548.             return $guid;
  549.         }
  550.         return FALSE;
  551.     }
  552.  
  553.     /**
  554.      * Updates an existing row by its ID
  555.      * @access  public
  556.      * @param   string  $id     ID of the row to update
  557.      * @param   array   $data   array of SET statements
  558.      * @param   string  $table
  559.      * @return  boolean
  560.      */
  561.     public function update($id, array $data, $table = NULL)
  562.     {
  563.         $table or $table = $this->table;
  564.         if ($table !== NULL and $row = $this->find($id))
  565.         {
  566.             foreach($data as $key => $val)
  567.             {
  568.                 // Are there any duplicate entries?
  569.                 if (in_array($key, $this->unique_fields)
  570.                     && $this->get($key, $key, $val))
  571.                 {
  572.                     throw new Exception("Duplicate entry '{$val}' for key '{$key}'.");
  573.                     break;
  574.                 }
  575.  
  576.                 $row[$key] = $val;
  577.                 if (isset($data['updated_at']))
  578.                 {
  579.                     $row['updated_at'] = time();
  580.                 }
  581.                 else
  582.                 {
  583.                     $row['updated_at'] = time();
  584.                 }
  585.             }
  586.            
  587.             $file = $this->data_dir.$table.DS.md5($row['id']).'.dat';
  588.  
  589.             return (file_put_contents($file, $this->_serialize($row))) ? TRUE : FALSE;
  590.         }
  591.         return FALSE;
  592.     }
  593.  
  594.     /**
  595.      * Updates multiple or all rows
  596.      * @access  public
  597.      * @param   array   $data   array of SET statements
  598.      * @param   array   $where  array of WHERE statements
  599.      * @param   string  $table
  600.      * @return  boolean
  601.      */
  602.     public function update_all(array $data, $where = array(), $table = NULL)
  603.     {
  604.         $table or $table = $this->table;
  605.         if ($table !== NULL and $rows = $this->find_all($where, NULL, $table))
  606.         {
  607.             foreach($rows as $row)
  608.             {
  609.                 $this->update($row['id'], $data, $table);
  610.             }
  611.             return TRUE;
  612.         }
  613.         return FALSE;
  614.     }
  615.  
  616.     /**
  617.      * Deletes a single existing row by its ID
  618.      * @access  public
  619.      * @param   string  $id     ID of the row to delete
  620.      * @param   string  $table
  621.      * @return  boolean
  622.      */
  623.     public function delete($id, $table = NULL)
  624.     {
  625.         $table or $table = $this->table;
  626.         if ($table !== NULL and $row = $this->find($id, $table))
  627.         {
  628.             if ($this->safe_delete === TRUE or isset($row['deleted']))
  629.             {
  630.                 return $this->update($id, array(
  631.                     'deleted'    => TRUE,
  632.                     'deleted_at' => time(),
  633.                 ), $table);
  634.             }
  635.             else
  636.             {
  637.                 return $this->remove($id, $table);
  638.             }
  639.         }
  640.         return FALSE;
  641.     }
  642.  
  643.     /**
  644.      * Deletes multiple or all rows by conditions
  645.      * @access  public
  646.      * @param   array   $where  array of WHERE statements
  647.      * @param   string  $table
  648.      * @return  boolean
  649.      */
  650.     public function delete_all($where = array(), $table = NULL)
  651.     {
  652.         $table or $table = $this->table;
  653.         if ($table !== NULL and $rows = $this->find_all($where, NULL, $table))
  654.         {
  655.             foreach($rows as $row)
  656.             {
  657.                 $this->delete($row['id']);
  658.             }
  659.             return TRUE;
  660.         }
  661.         return FALSE;
  662.     }
  663.  
  664.     /**
  665.      * Completely removes a single row bypassing soft delete
  666.      * @access  public
  667.      * @param   string  $id     ID of the row to delete
  668.      * @param   string  $table
  669.      * @return  boolean
  670.      */
  671.     public function remove($id, $table = NULL)
  672.     {
  673.         $table or $table = $this->table;
  674.         if ($table !== NULL and $row = $this->find($id, $table))
  675.         {
  676.             @unlink($this->table_dir.md5($row['id']).'.dat');
  677.             clearstatcache();
  678.             return TRUE;
  679.         }
  680.         return FALSE;
  681.     }
  682.  
  683.     /**
  684.      * Completely remove multiple or all rows bypassing soft delete
  685.      * @access  public
  686.      * @param   array   $where  array of where statements
  687.      * @param   string  $table
  688.      * @return  boolean
  689.      */
  690.     public function remove_all($where = array(), $table = NULL)
  691.     {
  692.         $table or $table = $this->table;
  693.         if ($table !== NULL and $rows = $this->find_all($where, NULL, $table))
  694.         {
  695.             foreach($rows as $row)
  696.             {
  697.                 $this->remove($row['id'], $table);
  698.             }
  699.             clearstatcache();
  700.             return TRUE;
  701.         }
  702.         return FALSE;
  703.     }
  704.  
  705.     /**
  706.      * This empties the table folder
  707.      * NOTE: This is an alias of the method above
  708.      * @access  public
  709.      * @param   none
  710.      * @return  boolean
  711.      */
  712.     public function truncate($table = NULL)
  713.     {
  714.         $table or $table = $this->table;
  715.         return ($table !== NULL) ? $this->remove_all() : FALSE;
  716.     }
  717.  
  718.     /*
  719.     |======================================================================
  720.     | UTILITIES
  721.     |======================================================================
  722.     */
  723.  
  724.     /**
  725.      * Checks whether the given key/value pair exists
  726.      *
  727.      * @param string $key       the key
  728.      * @param string $val       the value
  729.      * @param array  $table     the array to work on
  730.      *
  731.      * @return boolean whether the pair exists
  732.      */
  733.     public function exists($key, $val, $table = NULL)
  734.     {
  735.         $table or $table = $this->table;
  736.         if ($table !== NULL and $rows = $thi->all($table))
  737.         {
  738.             $_result = FALSE;
  739.             foreach ($rows as $row)
  740.             {
  741.                 if ($row[$key] === $val)
  742.                 {
  743.                     $_result = TRUE;
  744.                 }
  745.             }
  746.             return $_result;
  747.         }
  748.         return FALSE;
  749.     }
  750.  
  751.     /**
  752.      * Counts the number of items per column or for all columns
  753.      *
  754.      * @param string $col the column name to count. No input counts all columns.
  755.      * @param string  $table  table to use
  756.      *
  757.      * @return int the number of rows containing that column.
  758.      */
  759.     public function count($col, $table = NULL)
  760.     {
  761.         $table or $table = $this->table;
  762.         if ($table !== NULL)
  763.         {
  764.             is_array($col) or $col = (array) $col;
  765.             return count($this->select($col, $table));
  766.         }
  767.         return 0;
  768.     }
  769.  
  770.     /**
  771.      * Gets the first item of a column
  772.      *
  773.      * @param   string  $col    the column to look at
  774.      * @param   string  $table  the table name
  775.      *
  776.      * @return mixed the first item in the column
  777.      */
  778.     public function first($col = array(), $table = NULL)
  779.     {
  780.         $table or $table = $this->table;
  781.         return ($table !== NULL)
  782.                 ? $this->select((array) $col, $table)[0]
  783.                 : FALSE;
  784.     }
  785.  
  786.     /**
  787.      * Gets the last item in a column
  788.      *
  789.      * @param   string  $col    the name of the column to look at
  790.      * @param   string  $table  the array to work on
  791.      *
  792.      * @return mixed the last item in the column
  793.      */
  794.     public function last($col, $table = NULL)
  795.     {
  796.         $table or $table = $this->table;
  797.         if ($table !== NULL)
  798.         {
  799.             $_values = $this->select((array) $col, $table);
  800.             return end($_values)[$col];
  801.         }
  802.         return FALSE;
  803.     }
  804.  
  805.     /*
  806.     |======================================================================
  807.     | PRIVATE METHODS
  808.     |======================================================================
  809.     */
  810.  
  811.     /**
  812.      * Searches inside an array
  813.      * @access  protected
  814.      * @param   array       $array
  815.      * @param   array       $where
  816.      */
  817.     protected function _search_array(array $array, array $where)
  818.     {
  819.         $found = FALSE;
  820.         foreach ($array as $aKey => $aVal)
  821.         {
  822.             $coincidences = 0;
  823.             foreach ($where as $pKey => $pVal)
  824.             {
  825.                 if (array_key_exists($pKey, $aVal) && $aVal[$pKey] == $pVal)
  826.                 {
  827.                     $coincidences++;
  828.                 }
  829.             }
  830.             if ($coincidences == count($where))
  831.             {
  832.                 $found[] = $aKey;
  833.             }
  834.         }
  835.  
  836.         return $found;
  837.     }
  838.  
  839.     /**
  840.      * Reads all files inside table folder
  841.      * @access  protected
  842.      * @param   string  $table
  843.      * @return  array
  844.      */
  845.     protected function _read_files($table = NULL)
  846.     {
  847.         $table or $table = $this->table;
  848.         if ($table !== NULL)
  849.         {
  850.             $rows = array();
  851.             foreach (glob($this->table_dir.'*.dat') as $row)
  852.             {
  853.                 $content = file_get_contents($row);
  854.                 $rows[] = $this->_unserialize($content);
  855.             }
  856.             return $rows;
  857.         }
  858.         return NULL;
  859.     }
  860.  
  861.     // ------------------------------------------------------------------------
  862.  
  863.     /**
  864.      * Creates a new folder in a specified path
  865.      * @access  protected
  866.      * @param   string  $path   folder to create
  867.      * @return  boolean
  868.      */
  869.     protected function _create_folder($path = NULL)
  870.     {
  871.         if ($path !== NULL)
  872.         {
  873.             // Create data folder if it does not already exist.
  874.             if ( ! is_dir($path))
  875.             {
  876.                 // Create the data folder
  877.                 if ( ! mkdir($path, 0777, TRUE))
  878.                 {
  879.                     throw new Exception("Could not create data folder. Permission Denied!");
  880.                 }
  881.             }
  882.  
  883.             // Write our protection index.php if does not exists
  884.             if ( ! file_exists($path.'index.php'))
  885.             {
  886.                 $this->_create_index($path);
  887.             }
  888.         }
  889.         return FALSE;
  890.     }
  891.  
  892.     /**
  893.      * Creates data folder if it does not exit.
  894.      * @access  protected
  895.      * @param   string  $path   path to data folder
  896.      * @return  boolean
  897.      */
  898.     protected function _create_datafolder($path = NULL)
  899.     {
  900.         $path or $path = $this->path;
  901.         return ($path !== NULL)
  902.                 ? $this->_create_folder($path)
  903.                 : FALSE;
  904.     }
  905.  
  906.     /**
  907.      * Creates database folder
  908.      * @access  protected
  909.      * @param   string  $path   path to database folder
  910.      * @return boolean
  911.      */
  912.     protected function _create_database($database = NULL)
  913.     {
  914.         $database or $database = $this->database;
  915.         return ($this->database !== NULL) ?
  916.                 $this->_create_folder($this->data_dir)
  917.                 : FALSE;
  918.     }
  919.  
  920.     /**
  921.      * Create the index.php protection file
  922.      * @access  protected
  923.      * @param   string $path path where the create the file
  924.      * @return  void
  925.      */
  926.     protected function _create_index($path)
  927.     {
  928.         $o = umask(0);
  929.         file_put_contents(
  930.             $path.'index.php',
  931.             '<?php'."\n".'die("No direct script access allowed.");'."\n"
  932.         );
  933.         umask($o);
  934.     }
  935.  
  936.     // ------------------------------------------------------------------------
  937.  
  938.     /**
  939.      * Returns an array of all IDs
  940.      * @access  protected
  941.      * @param   string  $table  table's name
  942.      * @return  array
  943.      */
  944.     protected function _list_indices($table = NULL)
  945.     {
  946.         $table or $table = $this->table;
  947.         if ($table !== NULL)
  948.         {
  949.             $indices = array();
  950.             foreach (glob($this->table_dir.'*.dat') as $row)
  951.             {
  952.                 $indices[] = str_replace('.dat', '', basename($row));
  953.             }
  954.             return $indices;
  955.         }
  956.         return FALSE;
  957.     }
  958.  
  959.     /**
  960.      * Generates a fresh new GUID
  961.      * @access  protected
  962.      * @param   none
  963.      * @return  string
  964.      */
  965.     protected function _generate_guid($striped = FALSE)
  966.     {
  967.         $guid = '%04x%04x-%04x-%04x-%04x-%04x%04x%04x';
  968.         if ($striped === TRUE)
  969.             $guid = '%04x%04x%04x%04x%04x%04x%04x%04x';
  970.  
  971.         return vsprintf($guid, array(
  972.             mt_rand(0, 0xffff), mt_rand(0, 0xffff),
  973.             mt_rand(0, 0xffff),
  974.             mt_rand(0, 0x0fff) | 0x4000,
  975.             mt_rand(0, 0x3fff) | 0x8000,
  976.             mt_rand(0, 0xffff), mt_rand(0, 0xffff), mt_rand(0, 0xffff),
  977.         ));
  978.     }
  979.  
  980.     /**
  981.      * Generates a new shortened URL for a specific GUID
  982.      * @access  protected
  983.      * @param   string  $id     id to shorten
  984.      * @return  string  $sid    shortened id
  985.      */
  986.     protected function _shorten_guid($guid = NULL)
  987.     {
  988.         if ($guid !== NULL and $this->table !== NULL)
  989.         {
  990.             do {
  991.                 $sid = $this->random_string();
  992.                 return $sid;
  993.             } while ( ! $this->find_one('sid', $sid));
  994.         }
  995.         return FALSE;
  996.     }
  997.  
  998.     /**
  999.      * Generate random string
  1000.      * @access  public
  1001.      * @param   string  string to use to generate a random one
  1002.      * @return  string
  1003.      */
  1004.     public function random_string($str = NULL)
  1005.     {
  1006.         is_array($str) or $str = (array) $str;
  1007.         ! empty($str) or $str = array(uniqid(), session_id());
  1008.         for ($i=0; $i < count(array($str)); $i++)
  1009.         {
  1010.             $str = hash('crc32b', $str[$i]."-".$i);        
  1011.         }
  1012.         return $str;
  1013.        
  1014.     }
  1015.  
  1016.     // ------------------------------------------------------------------------
  1017.  
  1018.     /**
  1019.      * Serializes an array
  1020.      * @access  protected
  1021.      * @param   array   $data   array of data to serialize
  1022.      * @return  string  serialized $data
  1023.      */
  1024.     protected function _serialize(array $data = array())
  1025.     {
  1026.         // Now we serialize and prepare our data!
  1027.         // 1. Try to use igbinary_serialize/igbinary_unserialize
  1028.         // 2. Try to use bson_encode/bson_decode (MongoDB)
  1029.         // 3. If none of the above found, we use json_encode/json_decode
  1030.         // 4. If none of the functions are available
  1031.         //    we use php serialize/unserialize
  1032.        
  1033.         if (function_exists('igbinary_serialize'))
  1034.             return igbinary_serialize($data);
  1035.         elseif (function_exists('bson_encode'))
  1036.             return bson_encode($data);
  1037.         elseif (function_exists('json_encode'))
  1038.             return json_encode($data);
  1039.         else
  1040.             return serialize($data);
  1041.     }
  1042.  
  1043.     /**
  1044.      * Unerializes a string into an array
  1045.      * @access  protected
  1046.      * @param   string  $str    the string to unserialize
  1047.      * @return  array   serialized string
  1048.      */
  1049.     protected function _unserialize($str = '')
  1050.     {
  1051.         if (function_exists('igbinary_unserialize'))
  1052.             $array = igbinary_unserialize($str);
  1053.         elseif (function_exists('bson_decode'))
  1054.             $array = bson_decode($str);
  1055.         elseif (function_exists('json_decode'))
  1056.             $array = json_decode($str);
  1057.         else
  1058.             $array = unserialize($str);
  1059.  
  1060.         // Because functions above, except php serialize, return
  1061.         // objects instead of array, we convert them into arrays.
  1062.         return (array) $array;
  1063.     }
  1064. }
  1065.  
  1066. // What is Filebase.php?
  1067. // ---------------------
  1068. // This class allows you to use CodeIgniter without any database server. It brings a homemade file-based, serverless database mechanism.
  1069.  
  1070. // How it works?
  1071. // -------------
  1072. // Once use, "Filebase" will automatically create a folder with the database name you provide. If you do not provide any, the database name "main" will be used.
  1073.  
  1074. // Each library using this class will have (preferably) its own table, which means, its own folder.
  1075.  
  1076. // Each record will be stored as a serialized array using in-order:
  1077. // 1. igbinary_serialize() and igbinary_unserialize() if they exist (Look for php_igbinary extension).
  1078. // 2. bson_encode() and bson_decode() if they exist (php_mongo extension).
  1079. // 3. json_encode() and json_decode()
  1080.  
  1081. // How to install?
  1082. // ---------------
  1083. // 1. Put the php files "Filebase.php" anywhere you want as long as you will correctly include.
  1084.  
  1085. // 2. Create a library (CodeIgniter) and include Filebase like so:
  1086. // require APPPATH.'third_party/Filebase/Filebase.php';
  1087. // (assuming that it is inside third_party folder)
  1088.  
  1089. // 3. In library's constructor you can put:
  1090.  
  1091. // - already declared $table -
  1092. // $this->table = new Filebase(array(
  1093. //     'path'        => $dbpath,
  1094. //     'table'       => $tablename,
  1095. //     'safe_delete' => TRUE/FALSE
  1096. // ), $database);
  1097. // - $dbpath: path to your writable database folder.
  1098. // - $tablename: library's table name.
  1099. // - safe_delete: whether to delete OR hide records.
  1100. // - $database : your database name (default: main)
  1101. //
  1102. // Once done, you can use the $table object like so:
  1103. // 1. $this->table->insert($data) where $data is the array to insert
  1104. // 2. $this->table->update($id, $data) & $this->table->update_all($data, $where)
  1105. // 3. $this->table->delete($id), ...->delete_all($where)
  1106. // ... etc
  1107.  
  1108. /* End of file Filebase.php */
  1109. /* Location: ./application/third_party/Filebase/Filebase.php */
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement