Location: PHPKode > scripts > Admidio > admidio-2.2.9/adm_program/system/classes/table_access.php
<?php 
/******************************************************************************
 * Abstrakte Klasse steuert den Zugriff auf die entsprechenden Datenbanktabellen
 *
 * Copyright    : (c) 2004 - 2011 The Admidio Team
 * Homepage     : http://www.admidio.org
 * License      : GNU Public License 2 http://www.gnu.org/licenses/gpl-2.0.html
 *
 * Von dieser Klasse werden saemtliche Datenbankzugriffsklassen abgeleitet.
 * Es stehen diverse Methoden zur Verfuegung, welche in den abgeleiteten Klassen
 * durch vordefinierte Methoden angepasst werden koennen
 *
 * Folgende Funktionen stehen zur Verfuegung:
 *
 * readData($id, $sql_where_condition = "", $sql_additional_tables = "")
 *                  - Liest den Datensatz zur uebergebenen ID ($key_value) ein
 * clear()          - Die Klassenvariablen werden neu initialisiert
 * countAllRecords()- Anzahl aller Datensaetze der Tabelle werden zurueckgegeben
 * setArray($field_array)
 *                  - es wird ein Array mit allen noetigen gefuellten Tabellenfeldern
 *                    uebergeben. Key ist Spaltenname und Wert ist der Inhalt.
 *                    Mit dieser Methode kann das Einlesen der Werte umgangen werden.
 * setValue($field_name, $field_value) 
 *                  - setzt einen Wert fuer ein bestimmtes Feld der Tabelle
 * getValue($field_name)- gibt den Wert eines Feldes der Tabelle zurueck
 * save()           - die aktuellen Daten werden in die Datenbank zurueckgeschrieben
 *                    Es wird automatisch ein Update oder Insert erstellt
 * delete()         - der aktuelle Datensatz wird aus der Tabelle geloescht
 *
 *****************************************************************************/

class TableAccess
{
    protected $table_name;
    protected $column_praefix;
    protected $key_name;
    public    $db;
    
    protected $new_record;          // Merker, ob ein neuer Datensatz oder vorhandener Datensatz bearbeitet wird
    protected $columnsValueChanged; // Merker ob an den dbColumns Daten was geaendert wurde
    public $dbColumns = array();    // Array ueber alle Felder der entsprechenden Tabelle zu dem gewaehlten Datensatz
    public $columnsInfos = array(); // Array, welches weitere Informationen (geaendert ja/nein, Feldtyp) speichert
    
    // wird diese Klasse nicht abgeleitet, so muss dem Konstruktor neben der DB-Objekt auch der Tabellenname,
    // das Präfix der Spalten übergeben werden und optional noch die ID, die direkt eingelesen werden soll
    public function __construct(&$db, $tableName, $columnPraefix, $id = '')
    {
        $this->db            =& $db;
        $this->table_name     = $tableName;
        $this->column_praefix = $columnPraefix;

        // wurde eine ID uebergeben, dann Daten aus DB einlesen
        if(strlen($id) > 0 || (is_numeric($id) && $id > 0))
        {
            $this->readData($id);
        }
        else
        {
            $this->clear();
        }
    }
    
    // alle Klassenvariablen wieder zuruecksetzen
   public function clear()
   {
        $this->columnsValueChanged = false;
        $this->new_record   = true;
        $this->record_count = -1;

        if(count($this->columnsInfos) > 0)
        {
            // die Spalteninfos wurden bereits eingelesen
            // und werden nun nur noch neu initialisiert
            foreach($this->dbColumns as $field_name => $field_value)
            {
                $this->dbColumns[$field_name] = '';
                $this->columnsInfos[$field_name]['changed'] = false;
            }
        }
        else
        {
            // alle Spalten der Tabelle ins Array einlesen und auf leer setzen
            $sql = 'SHOW COLUMNS FROM '.$this->table_name;
            $this->db->query($sql);

            while ($row = $this->db->fetch_array())
            {
                $this->dbColumns[$row['Field']] = '';
                $this->columnsInfos[$row['Field']]['changed'] = false;
                $this->columnsInfos[$row['Field']]['type']    = $row['Type'];
                $this->columnsInfos[$row['Field']]['key']     = $row['Key'];
                $this->columnsInfos[$row['Field']]['extra']   = $row['Extra'];
                
                if($row['Key'] == 'PRI')
                {
                    $this->key_name = $row['Field'];
                }
            }
        }
    }
    
    // Methode gibt die Anzahl aller Datensaetze dieser Tabelle zurueck
    public function countAllRecords()
    {
        $sql = 'SELECT COUNT(1) as count FROM '.$this->table_name;
        $this->db->query($sql);
        $row = $this->db->fetch_array();
        return $row['count'];
    }

    // aktuelle Datensatz loeschen und ggf. noch die Referenzen
    public function delete()
    {
        $sql    = 'DELETE FROM '.$this->table_name.' 
                    WHERE '.$this->key_name.' = "'. $this->dbColumns[$this->key_name]. '"';
        $this->db->query($sql);

        $this->clear();
        return true;
    }

    // Methode gibt den Wert eines Feldes ($field_name) zurueck
    // $format kann fuer Datetime-Felder das Format aus der PHP-Funktion date() angegeben werden
    public function getValue($field_name, $format = '')
    {
        global $g_preferences;
        $field_value = '';
        
        if(isset($this->dbColumns[$field_name]))
        {
            // wenn Schluesselfeld leer ist, dann 0 zurueckgeben
            if($field_name == $this->key_name && empty($this->dbColumns[$field_name]))
            {
                $field_value = 0;
            }
            else
            {
                $field_value = $this->dbColumns[$field_name];
            }
        }

        // bei Textfeldern muessen Anfuehrungszeichen noch escaped werden
        if(isset($this->columnsInfos[$field_name]['type'])
        && (  strpos($this->columnsInfos[$field_name]['type'], 'char') !== false
           || strpos($this->columnsInfos[$field_name]['type'], 'text') !== false))
        {
            return htmlspecialchars($field_value, ENT_QUOTES);
        }
        // Datum in dem uebergebenen Format bzw. Systemformat zurueckgeben
        elseif(isset($this->columnsInfos[$field_name]['type'])
        &&  (  strpos($this->columnsInfos[$field_name]['type'], 'datetime') !== false
            || strpos($this->columnsInfos[$field_name]['type'], 'date') !== false
            || strpos($this->columnsInfos[$field_name]['type'], 'time') !== false))
        {
            if(strlen($field_value) > 0)
            {
                if(strlen($format) == 0 && isset($g_preferences))
                {
                    if(strpos($this->columnsInfos[$field_name]['type'], 'datetime') !== false)
                    {
                        $format = $g_preferences['system_date'].' '.$g_preferences['system_time'];
                    }
                    elseif(strpos($this->columnsInfos[$field_name]['type'], 'date') !== false)
                    {
                        $format = $g_preferences['system_date'];
                    }
                    else
                    {
                        $format = $g_preferences['system_time'];
                    }
                }

                // probieren das Datum zu formatieren, ansonsten Ausgabe der vorhandenen Daten
                try
                {
                    $datetime = new DateTime($field_value);
                    $field_value = $datetime->format($format);
                }
                catch(Exception $e)
                {
                    $field_value = $this->dbColumns[$field_name];
                }
            }
            return $field_value;
        }
        else
        {
            return $field_value;
        }
    }

    // liest den Datensatz von $id ein
    // die Methode gibt true zurueck, wenn ein DS gefunden wurde, andernfalls false
    // id : Schluesselwert von dem der Datensatz gelesen werden soll
    // sql_where_condition : optional eine individuelle WHERE-Bedinugung fuer das SQL-Statement
    // sql_additioinal_tables : mit Komma getrennte Auflistung weiterer Tabelle, die mit
    //                          eingelesen werden soll, dabei muessen die Verknuepfungen
    //                          in sql_where_condition stehen
    public function readData($id, $sql_where_condition = '', $sql_additional_tables = '')
    {
        // erst einmal alle Felder in das Array schreiben, falls kein Satz gefunden wird
        $this->clear();

        // es wurde keine Bedingung uebergeben, dann den Satz mit der Key-Id lesen, 
        // falls diese sinnvoll gefuellt ist
        if(strlen($sql_where_condition) == 0 && strlen($id) > 0 && $id != '0')
        {
            $sql_where_condition = ' '.$this->key_name.' = "'.$id.'" ';
        }
        if(strlen($sql_additional_tables) > 0)
        {
            $sql_additional_tables = ', '. $sql_additional_tables;
        }
        
        if(strlen($sql_where_condition) > 0)
        {
            $sql = 'SELECT * FROM '.$this->table_name.' '.$sql_additional_tables.'
                     WHERE '.$sql_where_condition.' ';
            $result = $this->db->query($sql);
    
            if($row = $this->db->fetch_array($result, MYSQL_ASSOC))
            {
                $this->new_record = false;
                
                // Daten in das Klassenarray schieben
                foreach($row as $key => $value)
                {
                    if(is_null($value))
                    {
                        $this->dbColumns[$key] = '';
                    }
                    else
                    {
                        $this->dbColumns[$key] = $value;
                    }
                }
                return true;
            }
            else
            {
                $this->clear();
            }
        }
        return false;
    }
    
    // die Methode speichert die Organisationsdaten in der Datenbank,
    // je nach Bedarf wird ein Insert oder Update gemacht
    // updateFingerPrint : steuert, ob in den Tabellen der Ersteller und Aenderer aktualisiert wird
    public function save($updateFingerPrint = true)
    {
        if($this->columnsValueChanged || strlen($this->dbColumns[$this->key_name]) == 0)
        {
            // SQL-Update-Statement fuer User-Tabelle zusammenbasteln
            $item_connection = '';                
            $sql_field_list  = '';
            $sql_value_list  = '';

            if($updateFingerPrint)
            {
                // besitzt die Tabelle Felder zum Speichern des Erstellers und der letzten Aenderung, 
                // dann diese hier automatisiert fuellen
                if($this->new_record && isset($this->dbColumns[$this->column_praefix.'_usr_id_create']))
                {
                    global $g_current_user;
                    $this->setValue($this->column_praefix.'_timestamp_create', DATETIME_NOW);
                    $this->setValue($this->column_praefix.'_usr_id_create', $g_current_user->getValue('usr_id'));
                }
                elseif(isset($this->dbColumns[$this->column_praefix.'_usr_id_change']))
                {
                    global $g_current_user;
                    // Daten nicht aktualisieren, wenn derselbe User dies innerhalb von 15 Minuten gemacht hat
                    if(time() > (strtotime($this->getValue($this->column_praefix.'_timestamp_create')) + 900)
                    || $g_current_user->getValue('usr_id') != $this->getValue($this->column_praefix.'_usr_id_create') )
                    {
                        $this->setValue($this->column_praefix.'_timestamp_change', DATETIME_NOW);
                        $this->setValue($this->column_praefix.'_usr_id_change', $g_current_user->getValue('usr_id'));
                    }
                }
            }

            // Schleife ueber alle DB-Felder und diese dem Update hinzufuegen                
            foreach($this->dbColumns as $key => $value)
            {
                // Auto-Increment-Felder duerfen nicht im Insert/Update erscheinen
                // Felder anderer Tabellen auch nicht
                if(strpos($key, $this->column_praefix. '_') === 0
                && $this->columnsInfos[$key]['extra'] != 'auto_increment') 
                {
                    if($this->columnsInfos[$key]['changed'] == true)
                    {
                        if($this->new_record)
                        {
                            if(strlen($value) > 0)
                            {
                                // Daten fuer ein Insert aufbereiten
                                $sql_field_list = $sql_field_list. ' '.$item_connection.' '.$key.' ';
                                // unterscheiden zwischen Numerisch und Text
                                if(strpos($this->columnsInfos[$key]['type'], 'int') !== false)
                                {
                                    $sql_value_list = $sql_value_list. ' '.$item_connection.' '.$value.' ';
                                }
                                else
                                {
                                    // Slashs (falls vorhanden) erst einmal entfernen und dann neu Zuordnen, 
                                    // damit sie auf jeden Fall da sind
                                    $value = stripslashes($value);
                                    $value = addslashes($value);
                                    $sql_value_list = $sql_value_list. ' '.$item_connection.' "'.$value.'" ';
                                }
                            }
                        }
                        else
                        {
                            // Daten fuer ein Update aufbereiten
                            if(strlen($value) == 0 || is_null($value))
                            {
                                $sql_field_list = $sql_field_list. ' '.$item_connection.' '.$key.' = NULL ';
                            }
                            elseif(strpos($this->columnsInfos[$key]['type'], 'int') !== false)
                            {
                                // numerisch
                                $sql_field_list = $sql_field_list. ' '.$item_connection.' '.$key.' = '.$value.' ';
                            }
                            else
                            {
                                // Slashs (falls vorhanden) erst einmal entfernen und dann neu Zuordnen, 
                                // damit sie auf jeden Fall da sind
                                $value = stripslashes($value);
                                $value = addslashes($value);
                                $sql_field_list = $sql_field_list. ' '.$item_connection.' '.$key.' = "'.$value.'" ';
                            }
                        }
                        if(strlen($item_connection) == 0 && strlen($sql_field_list) > 0)
                        {
                            $item_connection = ',';
                        }
                        $this->columnsInfos[$key]['changed'] = false;
                    }
                }
            }

            if($this->new_record)
            {
                $sql = 'INSERT INTO '.$this->table_name.' ('.$sql_field_list.') VALUES ('.$sql_value_list.') ';
                $this->db->query($sql);
                $this->dbColumns[$this->key_name] = $this->db->insert_id();
                $this->new_record = false;
            }
            else
            {
                $sql = 'UPDATE '.$this->table_name.' SET '.$sql_field_list.' 
                         WHERE '.$this->key_name.' = "'. $this->dbColumns[$this->key_name]. '"';
                $this->db->query($sql);
            }
        }

        $this->columnsValueChanged = false;
        return 0;
    }

    // es wird ein Array mit allen noetigen gefuellten Tabellenfeldern
    // uebergeben. Key ist Spaltenname und Wert ist der Inhalt.
    // Mit dieser Methode kann das Einlesen der Werte umgangen werden.
    public function setArray($field_array)
    {
        foreach($field_array as $field => $value)
        {
            $this->dbColumns[$field] = $value;
            $this->columnsInfos[$field]['changed'] = false;
        }
        $this->new_record = false;
    }

    // Methode setzt den Wert eines Feldes neu, 
    // dabei koennen noch noetige Plausibilitaetspruefungen gemacht werden
    public function setValue($field_name, $field_value)
    {
        $return_code = false;

        if(array_key_exists($field_name, $this->dbColumns))
        {
            // Allgemeine Plausibilitaets-Checks anhand des Feldtyps
            if(strlen($field_value) > 0)
            {
                // Numerische Felder
                if(strpos($this->columnsInfos[$field_name]['type'], 'int') !== false)
                {
                    if(is_numeric($field_value) == false)
                    {
                        $field_value = '';
                    }

                    // Schluesselfelder duerfen keine 0 enthalten
                    if((  $this->columnsInfos[$field_name]['key'] == 'PRI'
                       || $this->columnsInfos[$field_name]['key'] == 'MUL')
                    && $field_value == 0)
                    {
                        $field_value = '';
                    }
                }
                
                // Strings
                elseif(strpos($this->columnsInfos[$field_name]['type'], 'char') !== false
                ||     strpos($this->columnsInfos[$field_name]['type'], 'text') !== false)
                {
                    $field_value = strStripTags($field_value);
                }

                // Daten
                elseif(strpos($this->columnsInfos[$field_name]['type'], 'blob') !== false)
                {
                    $field_value = addslashes($field_value);
                }
            }

            // wurde das Schluesselfeld auf 0 gesetzt, dann soll ein neuer Datensatz angelegt werden
            if($field_name == $this->key_name && $field_value == 0)
            {
                $this->new_record = true;
            }

            if(array_key_exists($field_name, $this->dbColumns))
            {
                $return_code = true;

                // nur wenn der Wert sich geaendert hat, dann auch als geaendert markieren                
                if($field_value != $this->dbColumns[$field_name])
                {
                    $this->dbColumns[$field_name] = $field_value;
                    $this->columnsValueChanged    = true;
                    $this->columnsInfos[$field_name]['changed'] = true;
                }
            }
        }
        return $return_code;
    } 
}
?>
Return current item: Admidio