<?php
/*~ class.csvlist.php
.---------------------------------------------------------------------------.
| Software: csvlist - PHP CSV String class |
| Version: 1.0 |
| Contact: Gary Tay <garytay81(at)gmail(dot)com> |
| Require: PHP 5.0+ |
| Use: Link-List style storage solution for referencing, relationship |
| without the use multiple database rows or using high mem arrays|
| Suitable for single tier relationship linking |
| Note: Each item in the list MUST be unique. |
| Date: 17 May 2010 |
| ------------------------------------------------------------------------- |
| License: Distributed under the Lesser General Public License (LGPL) |
| http://www.gnu.org/copyleft/lesser.html |
| This program is distributed in the hope that it will be useful - WITHOUT |
| ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or |
| FITNESS FOR A PARTICULAR PURPOSE. |
'---------------------------------------------------------------------------'
Functions
add
add($item,$front=false) //$front (true) = add to front
clean
clean($item)
clear_error
clear_error()
count_item
count_item()
display_error
display_error()
empty_list
empty_list()
export
export()
export_array
export_array()
export_gz
export_gz()
get_records
get_records($start,$records,$reverse=false)
import
import($list)
import_array
import_array($array)
import_gz
import_gz($data)
is_item
is_item($item)
list_cleanup
list_cleanup()
remove
remove($item)
search
search($item)
set_csv_delimiters
set_csv_delimiters($newpp,$newdl)
throw_error
throw_error($msg,$method)
*/
class csvlist
{
/****************************************************************************
* ATTRIBUTES *
****************************************************************************/
public $list;
public $count;
public $pp ="'"; //Prepend and post pend usually quotes
public $dl =","; //Delimiter
public $error;
public $error_msg;
public $error_method;
/****************************************************************************
* CONSTRUCTOR *
****************************************************************************/
function __construct($list=false)
{
$this->clear_error(); //Clear (initialise) Errors
$this->empty_list(); //Clear (initialise) list
//Quick import
if($list)
{
$this->import($list);
}
}
/****************************************************************************
* METHODS : Import Export *
****************************************************************************/
//Import List As-Is
function import($list)
{
$this->clear_error();
$this->list = $list;
$this->list_cleanup();
}
//Import single dimension array
function import_array($array)
{
foreach($array as $value)
{
$this->add($value);
}
}
//Import gzipped file list
function import_gz($data)
{
$this->clear_error();
$this->list = gzuncompress($data);
$this->list_cleanup();
}
//Export as String
function export()
{
$this->clear_error();
return $this->list;
}
//export as array
function export_array()
{
//Trim off front/back quotes for easier explode
$array = trim($this->list,$this->pp);
return explode($this->pp.$this->dl.$this->pp,$array);
unset($array);
}
//Compress and export as gz
function export_gz()
{
$this->clear_error();
return gzcompress($this->list,9);
}
/****************************************************************************
* METHODS : Core Functions *
****************************************************************************/
//Add item to list
function add($item,$front=false) //$front (true) = add to front
{
$this->clear_error();
if(!strlen($item))
{
$this->throw_error("Unable to add null item",__METHOD__);
return false;
}
//Remove $dl and $pp from item if exists
$item = $this->clean($item);
//Ensure no double entry
if(!$this->is_item($item))
{
if($front) //Add to front
{
//Add delimiter to back if list not null
if($this->list){$this->list = $this->dl.$this->list;}
$this->list=$this->pp.$item.$this->pp.$this->list;
}else //Add item to back
{
//Add delimiter to back if list not null
if($this->list){$this->list .= $this->dl;}
$this->list.=$this->pp.$item.$this->pp;
}
return true;
}else
{
$this->throw_error("item already exists",__METHOD__);
return false;
}
}
//Remove instance of item
function remove($item)
{
//Remove $dl and $pp from item if exists
$item = $this->clean($item);
$this->clear_error();
if(!strlen($item))
{
$this->throw_error("Unable to remove null item",__METHOD__);
return false;
}
//Ensure it exists
if($this->is_item($item))
{
//Remove the item
$this->list = str_replace($this->pp.$item.$this->pp,"",$this->list);
//Cleanup the extra delimters
$this->list_cleanup();
//$this->list = str_replace($this->dl.$this->dl,$this->dl,$this->list);
return true;
}
else
{
$this->throw_error("item doesnt exists",__METHOD__);
return false;
}
}
//Search with string SQL : WHERE x LIKE '%x%'
function search($item)
{
$item = (string) $item;
$this->clear_error();
$item = $this->clean($item);
$pre = "";
$post = "";
if($item[0]!="%")
{
$pre = $this->pp;
}
if($item[strlen($item)-1]!="%")
{
$post = $this->pp;
}
$item = trim($item,"%");
if(!strlen($item))
{
$this->throw_error("Search Term is null",__METHOD__);
return false;
}
$strlen = strlen($this->list);
for($i=0;$i < $strlen;$i++)
{
$i = stripos($this->list,$pre.$item.$post,$i); //stripos = caseInsensitve
if($i===false){break;}
if($pre){$i++;}
$i_front = strrpos($this->list,$this->pp,($strlen-$i)*-1);
$i = strpos($this->list,$this->pp,$i);
$match[] = substr($this->list,$i_front+1, $i-$i_front-1);
}
if($match){return $match;}
else
{
$this->throw_error("No Match found",__METHOD__);
return false;
}
}
function get_record_position($item)
{
$item = $this->clean($item);
$thispos = strpos($this->list, $this->pp.$item.$this->pp);
if($thispos!==false)
{
return substr_count(substr($this->list, 0,$thispos),$this->dl);
}else
{
return false;
}
}
function get_records_csv($start,$records,$reverse=false)
{
$records = $this->get_records($start,$records,$reverse);
$t = "";
for($i=0;$records[$i];$i++)
{
$csv .= $t.$this->pp.$records[$i].$this->pp;
$t = $this->dl;
}
return $csv;
}
//Pagination record retrival (Array)
function get_records($start,$records,$reverse=false)
{
//No records?
if(!$records)
{
$this->throw_error("0 records?",__METHOD__);
return false;
}
$strlen = strlen($this->list);
$records_counter = 0; //Record number in string
$lastitem = false;
//reverse record fetching
if($reverse)
{
//Get item count
$r_count = $this->count_item();
if(($r_count - $start) > $records)
{
$start = ($r_count - $start) - $records;
}else
{
$records = $r_count - $start;
$start -= $r_count;
}
}
for($i=0;$records AND $lastitem == false; $i++)
{
//echo "<br/>Records left : $records Record_Counter : $records_counter || ";
if($i+1 < $strlen)
{
$i = strpos($this->list, $this->dl,$i+1);
}else
{
$i = false;
}
//Last item (or only 1 in list)
//Causes exit after this loop
if($i===false)
{
$lastitem = true;
$i=$strlen;
}
$i--; //Move back by 1
//echo "$i_front : $i";
if($start <= $records_counter)
{
//echo " Match $i_front : $i";
$i_front = strrpos($this->list,$this->pp,($strlen-$i+1)*-1);
$match[] = substr($this->list,$i_front+1, $i-$i_front-1);
$records--;
}
$records_counter++;
}
if($reverse)
{
return array_reverse($match);
}
return $match;
}
//Check if an item exists in the string (FULL MATCH ONLY); SQL : WHERE x = 'x'
function is_item($item)
{
$item = $this->clean($item);
$exist = strpos($this->list, $this->pp.$item.$this->pp);
if($exist!==false)
{
return true;
}else
{
return false;
}
}
/****************************************************************************
* METHODS : Utilities *
***************************************************************************/
//Change delimiters pre-post/pend $pp
function set_csv_delimiters($newpp,$newdl)
{
$this->clear_error();
if(strlen($newpp)==1)
{
$this->pp = $newpp;
}else
{
$this->throw_error("Pre/PostPend is not 1 character",__METHOD__);
}
if(strlen($newdl)==1)
{
$this->dl = $newdl;
}else
{
$this->throw_error("Delimiter is not 1 character",__METHOD__);
}
}
//Clean inputs -- Strip $pp and $dl *Preventive Measure*
function clean($item)
{
if(strpos($item,$this->pp)!==false)
{
$item = str_replace($this->pp,htmlentities($this->pp, ENT_QUOTES),$item);
}
if(strpos($item,$this->dl)!==false)
{
$item = str_replace($this->dl,htmlentities($this->dl, ENT_QUOTES),$item);
}
return $item;
}
//Count Items in the list
function count_item()
{
$this->count = substr_count($this->list,$this->pp);
if($this->count)
{
$this->count=$this->count/2;
}
/*if($this->count!=0)
{
$this->count++;
}*/
return $this->count;
}
//Clear the list and set it to false
function empty_list()
{
$this->clear_error();
$this->list = false;
}
function list_cleanup()
{
$md5 = md5($this->list);
//Cleanup the extra delimters
$this->list = str_replace($this->dl.$this->dl,$this->dl,$this->list);
$this->list = trim($this->list,$this->dl);
if($md5!=md5($this->list))
{
return true;
}else
{
return false;
}
}
/****************************************************************************
* METHODS - Error handling *
****************************************************************************/
function clear_error()
{
//clears errors
$this->error = false;
$this->error_msg = false;
$this->error_method = false;
}
function throw_error($msg,$method)
{
//Set error
$this->error = true;
$this->error_msg = $msg;
$this->error_method = $method;
}
function display_error()
{
if($this->error)
{
return $this->error_method." :: ".$this->error_msg;
}
else
{
return false;
}
}
} // end Class
?>
|