AN INSTRUMENTAL EXPERIMENTAL

Files

PHP View: csvhandler.php
<?php
/* csvHandler
 *
 * The CSV ("Comma Separated Value") file format is often used to exchange data between disparate 
 * applications. The file format, as it is used in Microsoft Excel, has become a pseudo standard 
 * throughout the industry, even among non-Microsoft platforms.
 * 
 * Related documentation:
 *  http://php.net/manual/en/class.splfileobject.php
 *  http://php.net/manual/en/class.arrayobject.php
 *  
 */

class csvHandler extends ArrayObject {
    
    const 
VERSION '0.1.3';
    
    
/* The csv file object declared. */
    
private $fileObj;
    private 
$fileMode;
    
    
/* The csv file control properties. */
    
public $delimiter;
    public 
$enclosure;
    public 
$escape;
    
    
/* ArrayObject Flags */
    
private $flags;
    
    
/* The csv headers */
    
private $headers;
    private 
$separator ",";
    
    
/* If extends SplFileObject 
        public __construct ($file, $mode = "r", $use_include_path = false, $context ) {
            parent::__construct($file, $mode, $use_include_path, $context );
        }
    */
    
public function __construct($file$mode "r"$delimiter ";"$enclosure "\""$escape "\\"$flags 0) {
        
$this->fileMode $mode;
        
$this->delimiter $delimiter;
        
$this->enclosure $enclosure;
        
$this->escape $escape;
        
$this->flags $flags;
        
/* ArrayObject::setFlags
            http://php.net/manual/en/arrayobject.setflags.php
            1     ArrayObject::STD_PROP_LIST
                    Properties of the object have their normal functionality when accessed as list (var_dump, foreach, etc.).
            2     ArrayObject::ARRAY_AS_PROPS
                    Entries can be accessed as properties (read and write).
        */
        
if (file_exists($file)) {
            
/* Create an instance of file ...create an instance of a class SplFileObject. 
            */
            
$this->fileObj = new splFileObject($file$this->fileMode);
            
/* Windows offers a text-mode translation flag ('t') which will transparently translate \n to \r\n when working with the file. 
                In contrast, you can also use 'b' to force binary mode, which will not translate your data. 
                To use these flags, specify either 'b' or 't' as the last character of the mode parameter. 
            */
            
            /* SplFileObject::flock
                http://php.net/manual/en/splfileobject.flock.php
                LOCK_SH to acquire a shared lock (reader).
                LOCK_EX to acquire an exclusive lock (writer).
                LOCK_UN to release a lock (shared or exclusive).
                LOCK_NB to not block while locking (not supported on Windows).
            */
            
switch($this->fileMode) {
                case 
'r':
                    
/* 'r'    Open for reading only; place the file pointer at the beginning of the file. */
                    
$this->fileObj->flock(LOCK_SH);
                    break;
                case 
'r+':
                    
/* 'r+'    Open for reading and writing; place the file pointer at the beginning of the file. */
                
case 'w':
                    
/* 'w'    Open for writing only; place the file pointer at the beginning of the file and truncate the file to zero length. 
                            If the file does not exist, attempt to create it. */
                
case 'w+':
                    
/* 'w+'    Open for reading and writing; place the file pointer at the beginning of the file and truncate the file to zero length. 
                            If the file does not exist, attempt to create it. */
                
case 'a':
                    
/* 'a'    Open for writing only; place the file pointer at the end of the file. If the file does not exist, attempt to create it. */
                
case 'a+':
                    
/* 'a+'    Open for reading and writing; place the file pointer at the end of the file. If the file does not exist, attempt to create it. */
                
case 'x':
                    
/* 'x'    Create and open for writing only; place the file pointer at the beginning of the file. 
                            If the file already exists, the fopen() call will fail by returning FALSE and generating an error of level E_WARNING. 
                            If the file does not exist, attempt to create it. This is equivalent to specifying O_EXCL|O_CREAT flags for the underlying open(2) system call. */
                
case 'x+':
                    
/* 'x+'    Create and open for reading and writing; otherwise it has the same behavior as 'x'. */
                
case 'c':
                    
/*    'c'    Open the file for writing only. If the file does not exist, it is created. 
                            If it exists, it is neither truncated (as opposed to 'w'), nor the call to this function fails (as is the case with 'x'). 
                            The file pointer is positioned on the beginning of the file. 
                            This may be useful if it's desired to get an advisory lock (see flock()) before attempting to modify the file, as using 'w' 
                            could truncate the file before the lock was obtained (if truncation is desired, ftruncate() can be used after the lock is requested). */
                
case 'c+':
                    
/* 'c+'    Open the file for reading and writing; otherwise it has the same behavior as 'c'. */
                    
$this->fileObj->flock(LOCK_EX);
                    break;
                default:
                    
$this->fileObj->flock(LOCK_NB);
                    break;
            }
            
/* SplFileObject::setFlags
                http://php.net/manual/en/splfileobject.setflags.php 
                If you want to skip blank lines when reading a CSV file, you need *all * the flags. 
                
                SplFileObject::DROP_NEW_LINE
                    Drop newlines at the end of a line.
                    
                SplFileObject::READ_AHEAD
                    Read on rewind/next.
                    
                SplFileObject::SKIP_EMPTY
                    Skips empty lines in the file. This requires the READ_AHEAD flag be enabled, to work as expected.
                    
                SplFileObject::READ_CSV
                    Read lines as CSV rows.
            */
            
$this->fileObj->setFlags(SplFileObject::READ_CSV SplFileObject::READ_AHEAD SplFileObject::SKIP_EMPTY SplFileObject::DROP_NEW_LINE);
            
            
/* SplFileObject::setCsvControl
                http://php.net/manual/en/splfileobject.setcsvcontrol.php
                Set the delimiter, enclosure and escape character for for parsing CSV fields.
            */
            
$this->fileObj->setCsvControl($this->delimiter$this->enclosure$this->escape);
            
            
/*SplFileObject::fgetcsv
                http://php.net/manual/en/splfileobject.fgetcsv.php
                Gets line from file and parse as CSV fields.
            */
            
while($line $this->fileObj->fgetcsv()) {
                
$array[]=$line;
            }
            
/* Alternate methods for parse a csv file:
            while (!$this->fileObj->eof()) {
                $array[] = $this->fileObj->fgetcsv();
            }
            foreach ($this->fileObj as $row) { // Require flag: SplFileObject::READ_CSV
                $array[]=$row;
            } 
            */
            
parent::__construct($array$this->flags);
        } else {
            throw new 
runtimeException('Missing the file: '.$file);
        }
    
    }
    
    public function 
__destruct() {
        if (
$this->fileMode != 'r') {
            foreach (
$this->getArrayCopy() as $line) {
                
/* SplFileObject::fputcsv
                    http://php.net/manual/en/splfileobject.fputcsv.php
                    Write a field array as a CSV line.
                    Returns the length of the written string or FALSE on failure. 
                */
                
$this->fileObj->fputcsv($line);
            }
        }
        
$this->fileObj->flock(LOCK_UN);
    }
    
    public function 
shiftHeaders() {
        
$array $this->getArrayCopy();
        foreach(
array_shift($array) as $col => $header) {
            
/* PHP 7 - The order that the assignment operations are performed in has changed: list() no longer assigns variables in reverse order.
                http://php.net/manual/en/migration70.incompatible.php#migration70.incompatible.variable-handling.list.order
            */
            
list($this->headers[$col]['name'], $this->headers[$col]['type'], $this->headers[$col]['default']) = explode($this->separator$header);
        }
        
parent::__construct($array$this->flags);
    }
    
    public function 
unshiftHeaders() {
        
$array $this->getArrayCopy();
        foreach(
$this->headers as $col => $header) {
            
/* PHP 5 - list() assigns variables in reverse order. */
            
$headers[$col] = implode($this->separatorarray_reverse($header));
        }
        unset(
$this->headers);
        
array_unshift($array$headers);
        
parent::__construct($array$this->flags);
    }
    
    
/* SSPM - Acronym for: slice, slice, push, merge */
    
public function arraySSPM($array = array(), $position 0$element NULL) {
        
$slice1 array_slice($array0$position);
        
$slice2 array_slice($array$position);
        
array_push($slice1$element);
        
/* Alternate push method */
        //$slice1[] = $element;
        
return array_merge($slice1$slice2);
    }
    
    
/* Crucial function used to insert header to any position of column in CSV array. */
    
public function insertHeader($col 0$header = array()) {
        if (
is_array($this->headers)) {
            
$col = (integer)$col;
            if (
$col === 0) {
                
array_unshift($this->headers$header);
            } elseif (
$col >= count($this->headers)) {
                
array_push($this->headers$header);
                
/* Alternate push method */
                //$this->headers[] = $header;
            
} else {
                
$this->headers $this->arraySSPM($this->headers$col$header);
            }
            
/* Inser new column with defaul values to CSV array corresponding with this header */
            
$this->insertCol($col$header['default']);
        } else {
            throw new 
runtimeException('Headers not set. Use method csvHandler::shiftHeaders to set the headers.');
        }
    }
    
    
/* Function used to synergic operation in CSV array with headers aka columns. */
    
public function insertCol($col 0$default NULL) {
        
$col = (integer)$col;
        
$array $this->getArrayCopy();
        foreach (
$array as $row => $line) {
            if (
$col === 0) {
                
array_unshift($line$default);
            } elseif (
$col >= count($this->headers)) {
                
array_push($line$default);
                
/* Alternate push method */
                //$this->headers[] = $header;
            
} else {
                
$line $this->arraySSPM($line$col$default);
            }
            
$array[$row] = $line;
        }
        
parent::__construct($array$this->flags);
    }
    
    
/* Crucial function used to insert any CSV line to any position of row in CSV array. */
    
public function insert($row 0$line = array()) {
        
$row = (integer)$row;
        if (
$row === 0) {
            
$array $this->getArrayCopy();
            
array_unshift($array$line);
        } elseif (
$row >= $this->count()) {
            
$this->append($line);
            return;
        } else {
            
$array $this->arraySSPM($this->getArrayCopy(), $row$line);
        }
        
parent::__construct($array$this->flags);
    }
    
    public static function 
getInstance($file) {
        return new 
self($file);
    }
    
    
/* Functions is used to testing and debuging this class. */
    
public function printArray() {
        
$dump print_r($this->getArrayCopy(),TRUE);
        
$dump.= 'Count '.$this->count();
        print(
'<pre>'.$dump.'</pre>');
    }
    
    public function 
printHeaders() {
        
$dump 'Headers ';
        
$dump.= print_r($this->headers,TRUE);
        print(
'<pre>'.$dump.'</pre>');
    }
}

class 
csvApi extends csvHandler {
    
    
/* Data types for column aka header.
     * Specifically this array...
    */
    
private $types = array(
        
'NULL' => 'NULL',
        
'INTEGER' => 'INTEGER',
        
'REAL' => 'REAL',
        
'TEXT' => 'TEXT',
        
'BLOB' => 'BLOB',
        
'BOOLEAN' => 'BOOLEAN',
        
'TIMESTAMP' => 'TIMESTAMP',
        
'IMAGE' => 'IMAGE',
        
'ID' => 'ID',
        
'TEXTAREA' => 'TEXTAREA',
        
'PASSWORD' => 'PASSWORD',
        
'COLOR' => 'COLOR',
    );
    
    public function 
receiveRow() {
        
    }
    
    public function 
receiveHeader() {
        
    }
    
    
}

class 
csvRenderer extends csvApi {
    
    private function 
typeToInput() {
        
    }
}


/* Test of csvHandler */
$csv = new csvHandler('Notice.csv');
$csv->printArray();
$csv->insert(2, array(time(),'Test3'));
$csv->shiftHeaders();
$csv->printHeaders();
$csv->insert(2, array(time(),'Test4'));
$csv->append(array(time(),'Test5'));
$csv->insert(6, array(time(),'Test6'));
$csv->printArray();
$csv->unshiftHeaders();
$csv->printArray();
$csv->printHeaders();

?>