<?php   ### get_csv_data.php ###
##      Stand 2009-06-27 16:37


error_reporting(E_ALL);


#------------------------------------------------------------------------------

define('MAX_LINE_LENGTH', 8192); ## Maximale Datensatzgröße incl. Delimiters usw.
define('DELIMITER', ';');        ## Feldtrenner
define('ENCLOSURE', '"');        ## Einschlusszeichen für Textfelder
define('MISSING_COL','###');     ## Ersatzwert für fehlenden Spaltenwert

#------------------------------------------------------------------------------





#------------------------------------------------------------------------------
function get_csv_data($filename, $_colnames = false)
{
    $selfopen = false;

    if (gettype($filename) == 'string')
    {
        $selfopen = true;
        $fh = fopen($filename,'r');

        if (!$fh) return false;    ## oder Fehlernummer

        if (!flock($fh, LOCK_SH))
        {
            fclose($fh);
            return false;          ## oder Fehlernummer
        }     
    }    
    elseif(gettype($filename) == 'resource')
    {
        $fh = $filename;
    }
    else return false;
   

    $_data = array();          ## leeren Rückgabewert bereitstellen

    if ($_colnames !== false)  ## wenn eine spaltenweise Darstellung stattfinden soll
    {
       if (is_string($_colnames))  ## Wenn die Spaltennamen als Komma-separierter String übergeben wurden
       {
           $_colnames = trim($_colnames,'()');   ## Wenn die Spaltennamen z.B. aus einem enum-Feld stammen
           $_colnames = explode(',',$_colnames);
       } 

       if (!is_array($_colnames))  ## Wenn das Zerlegen nicht geklappt hat oder kein Array übergeben wurde
       {
           $_colnames = fgetcsv($fh, MAX_LINE_LENGTH, DELIMITER, ENCLOSURE);  ## erste Zeile enthält Spaltennamen
       }

       if (!$_colnames)            ## Holen der ersten Zeile ist schon schief gegangen -> Ende im Gelände
       {
           if ($selfopen) fclose($fh);
           return false;      ## oder Fehlernummer
       }
    }       

    if ($_colnames === false)      ## es soll ein zeilenweise organisiertes Array zurückgegeben werden
    {
        while(false!==($_rec = fgetcsv($fh, MAX_LINE_LENGTH, DELIMITER, ENCLOSURE)))
        {
            $_data[] = $_rec;
        }    
    }
    else                           ## es wird ein spaltenweise organisiertes Array zurückgegeben
    {
        $recno = 0; 

        while(false!==($_rec = fgetcsv($fh, MAX_LINE_LENGTH, DELIMITER, ENCLOSURE)))
        {
            $recno++;

            foreach($_colnames as $key => $col)   ## nur benannte Spalten werden übernommen.
            {
                ##-- Due to the buggy php function in Versions less than 5.2.10
                ##-- empty rows aren't reported as an one element array pointing to NULL
                ## Wenn aktuelle Version >= 5.2.10
                
                if (strnatcmp(phpversion(),'5.2.10') >= 0) 
                {
                    $_data[$col][$recno] = (isset($_rec[$key]) and !is_null($_rec[$key]))?$_rec[$key]:MISSING_COL;    
                }
                else
                {
                    $_data[$col][$recno] = (isset($_rec[$key]) and isset($_rec[1]))?$_rec[$key]:MISSING_COL;    
                }    
            }
        }
    }  
    
    if ($selfopen) fclose($fh);

    return $_data;
}   
#------------------------------------------------------------------------------
function put_csv_data($filename, &$_data, $_colnames = true)
{
    $selfopen = false;
    $reccount = 0;
    
    if (!is_array($_data)) return false;

    if (gettype($filename) == 'string')
    {
       $selfopen = true;

       ## Wenn die Datei nicht vorhanden ist, wird sie durch den Append-Mode
       ## angelegt, anderenfalls zerstörungsfrei geöffnet.
       ## sie wird mit LOCK_SH gegen schreiben geschützt
       ## anschließend wird ein zweites Handle auf die datei geholt
       ## das ebenfalls mit LOCK_SH geschützt wird.
       ## Nach der Rückgabe von Handle $fa kann $fh auf LOCK_EX gesetzt werden
       ## Nun ist die Datei sicher beschreibbar für diesen Vorgang

       $fa = fopen($filename, 'a');                     
       if (!$fa) return false;    
       if (!flock($fa, LOCK_SH))
       {
           fclose($fh);
           return false;          
       }     

       $fh = fopen($filename,'r+');

       if (!$fh) return false;    

       if (!flock($fh, LOCK_SH))
       {
           fclose($fh);
           return false;          
       }

       fclose($fa);

       if (!flock($fh, LOCK_EX))
       {
           fclose($fh);
           return false;          
       }
    }    
    elseif(gettype($filename) == 'resource')
    {
       $fh = $filename;
    }
    else return false;
   
    if ($_colnames !== false)  ## wenn Spaltennamen als erste Zeile der CSV-Datei geschrieben werden sollen
    {
       if (is_string($_colnames))  ## Wenn die neuen Spaltennamen als Komma-separierter String übergeben wurden
       {
           $_colnames = trim($_colnames,'()');   ## Wenn die Spaltennamen z.B. aus einem enum-Feld stammen
           $_colnames = explode(',',$_colnames);
       } 

       if (!is_array($_colnames))  ## Wenn das Zerlegen nicht geklappt hat oder kein Array übergeben wurde
       {
           $_colnames = array_keys($_data);
       }

       $_newcolnames = array();
       foreach ($_colnames as $colname)                            # -> 3a
       {
           if (!is_null($colname))  $_newcolnames[] = $colname;
       }
       
       fputcsv($fh, $_newcolnames, DELIMITER, ENCLOSURE);
    }       

    $_oldcolnames = array_keys($_data);

    foreach($_data[$_oldcolnames[0]] as $index => $value)
    {
        $reccount++;   
       
        $_record = array();
        foreach($_oldcolnames as $key => $colname)
        {
            if( isset($_data[$colname][$index]) 
                and $_data[$colname][$index] != MISSING_COL 
                and isset($_colnames[$key])
                and !is_null($_colnames[$key])
              )
            {
                $_record[$colname] = $_data[$colname][$index];
            }
            else
            {
                $_record[$colname] = '';
            }
        }

        fputcsv($fh, $_record, DELIMITER, ENCLOSURE); 
    }
        
    ftruncate($fh,ftell($fh));

    if($selfopen) fclose($fh);
    return $reccount;

}       
#------------------------------------------------------------------------------       
function get_record (&$_data, $recno)
{
    $_rec = array();
    
    foreach ($_data as $colname => $field)
    {
        $_rec[$colname] = isset($_data[$colname][$recno])?$_data[$colname][$recno]:NULL;
    }

    return $_rec;
}

#------------------------------------------------------------------------------       
function delete_record (&$_data, $recno)
{
    $cols_deleted = 0; 
    
    foreach ($_data as $colname => $field)
    {
        unset($_data[$colname][$recno]);
        $cols_deleted++;        
    }
    
    return $cols_deleted;
}

#------------------------------------------------------------------------------       
function update_record(&$_data, $recno, $_record, $expand=false)
{
    $cols_updated = 0; 
     
    foreach ($_record as $colname => $data)
    {
        if ($expand or isset($_data[$colname][$recno]))
        {
            $_data[$colname][$recno] = $data;
            $cols_updated++;
        }
    }
    
    return $cols_updated;
}

#------------------------------------------------------------------------------       
function insert_record(&$_data, $recno, $_record, $expand=false, $overwrite=false)
{
    $cols_inserted = 0;

    if (!$overwrite)
    {
        foreach($_record as $colname => $data)
        {
            if (isset($_data[$colname][$recno]))
            {
                return 0;
            }
        }
    }

    foreach ($_record as $colname => $data)
    {
        if ($expand or isset($_data[$colname]))
        {
            $_data[$colname][$recno] = $data;
            $cols_inserted++;
        }
    }

    return $cols_inserted;
}


#==============================================================================
# PHP main
#==============================================================================

$_columns = array('NO','SUBJ','QTTY','MEMO','EXTRA');
$_columns3 = array('NO','SUBJ','QTTY',NULL,'EXTRA');

#$_csv = get_csv_data('csv02.txt', '(nummer,subject,anzahl,memo)');
#$_csv = get_csv_data('csv02.txt', $_columns);
$_csv = get_csv_data('csv02.txt', true);
#$_csv = get_csv_data('csv02.txt');

$_record = array();
$_record['nr']      = 6;
$_record['betreff'] = 'Inserttest';
$_record['anzahl']  = 1;
$_record['beschreibung'] = "Hier ist 'was los!\r\nUnd das nicht zu knapp.";
$_record['extra']   = 'Spalte hinzugefügt?';

$cols_inserted1 = insert_record($_csv, 6, $_record, true);
$cols_inserted2 = insert_record($_csv, 3, $_record, true);

#$recs = put_csv_data('newcsv2.csv',$_csv, $_columns);
$recs = put_csv_data('newcsv3a.csv',$_csv, $_columns3);

echo "<pre>\r\n";
echo htmlspecialchars(print_r($_csv,1))."\r\n";
echo htmlspecialchars(print_r(get_record($_csv,3),1))."\r\n";
#var_dump($_csv)."\r\n";
echo "<p>Eingefügte Spalten 1.: $cols_inserted1</p>\r\n";
echo "<p>Eingefügte Spalten 2.: $cols_inserted2</p>\r\n";

echo "<p>geschriebene Datensätze: $recs</p>\r\n";

echo "</pre>\r\n";





?>