openrat-cms

Unnamed repository; edit this file 'description' to name the repository.
Log | Files | Refs | README

Database.class.php (6621B)


      1 <?php
      2 // OpenRat Content Management System
      3 // Copyright (C) 2002-2006 Jan Dankert, jandankert@jandankert.de
      4 //
      5 // This program is free software; you can redistribute it and/or
      6 // modify it under the terms of the GNU General Public License
      7 // as published by the Free Software Foundation; either version 2
      8 // of the License, or (at your option) any later version.
      9 //
     10 // This program is distributed in the hope that it will be useful,
     11 // but WITHOUT ANY WARRANTY; without even the implied warranty of
     12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     13 // GNU General Public License for more details.
     14 //
     15 // You should have received a copy of the GNU General Public License
     16 // along with this program; if not, write to the Free Software
     17 // Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
     18 
     19 namespace database;
     20 use cms\base\Configuration as C;
     21 use database\driver\PDODriver;
     22 use logger\Logger;
     23 use util\exception\DatabaseException;
     24 
     25 /**
     26  * Darstellung einer Datenbank-Verbindung.
     27  * 
     28  * Fuer die echten DB-Aufrufe werden die entsprechenden
     29  * Methoden des passenden Clients aufgerufen.
     30  * 
     31  * Diese Klasse stammt urspruenglich aus dem PHP-Pear-DB-Projekt, wurde hier aber intensiv veraendert.
     32  * 
     33  * @author Jan Dankert
     34  * @package openrat.database
     35  */
     36 class Database
     37 {
     38 	/**
     39 	 * Datenbank-Id.
     40 	 *
     41 	 * @var String
     42 	 */
     43 	public $id;
     44 	
     45 	/**
     46 	 * Konfiguration der Datenbank-Verbindung
     47 	 *
     48 	 * @var array
     49 	 */
     50 	public $conf;
     51 	
     52 	/**
     53 	 * Client.
     54 	 *
     55 	 * @var PDODriver
     56 	 */
     57 	private $client;
     58 	
     59 	/**
     60 	 * Schalter, ob eine Transaktion begonnen wurde.
     61 	 * @var boolean
     62 	 */
     63 	private $transactionInProgress = false;
     64 
     65 
     66 	/**
     67 	 * Default configuration.
     68 	 * @var array
     69 	 */
     70 	private static $DEFAULT_CONFIG = [
     71 		// we need at least 1 prefix or suffix, because the raw table names are partially keywords in ANSI SQL.
     72 		'prefix'         => 'cms_',
     73 		'suffix'         => '',
     74 		'enabled'        => true,
     75 		'name'           => '',
     76 		'description'    => '',
     77 		'type'           => 'pdo', // we are only supporting PDO
     78 		'driver'         => 'mysql',
     79 		'dsn'            => '',    // if no DSN is given, it will be created from user,host,port.
     80 		'user'           => '',
     81 		'password'       => '',
     82 		'host'           => 'localhost',
     83 		'port'           => 0,
     84 		'database'       => '',
     85 		'base64'         => false,   // should BLOBs be converted to Base64?
     86 		'persistent'     => true,    // persistent connections are faster
     87 		'charset'        => 'UTF-8', // should be UTF-8
     88 		'connection_sql' => '',      // Startup-SQL
     89 		'cmd'            => '',      // maybe you want to start a SSH tunnel here
     90 		'prepare'        => true,    // using prepared statements is a good idea
     91 		'transaction'    => true,    // using transaction is a good idea
     92 		'update'         =>
     93 			[
     94 			],
     95 		'auto_update'    => true,    // auto update should always be enabled
     96 	];
     97 
     98 
     99 	/**
    100 	 * Kontruktor.
    101 	 * Erwartet die Datenbank-Konfiguration als Parameter.
    102 	 *
    103 	 * @param array Konfiguration der Verbindung
    104 	 */
    105 	public function __construct( $dbconf )
    106 	{
    107 		$this->conf = array_merge(
    108 			Database::$DEFAULT_CONFIG, // internal defaults
    109 			C::subset('database-default')->subset('defaults')->getConfig(), // defaults from config
    110 			$dbconf  // per-connection DB configuration
    111 		);
    112 
    113 		$this->connect();
    114 	}
    115 	
    116 
    117 	/**
    118 	 * Verbindung zur Datenbank aufbauen.
    119 	 *
    120 	 * @return bool Status
    121 	 */
    122 	public function connect()
    123 	{
    124         // Ausfuehren des Systemkommandos vor Verbindungsaufbau
    125         if ( $this->conf['cmd'] )
    126             $this->executeSystemCommand( $this->conf['cmd'] );
    127 
    128 		// Client instanziieren
    129 		$this->client = new PDODriver();
    130 
    131 		// Verbindung aufbauen
    132 		$this->client->connect( $this->conf );
    133 		
    134 		// SQL nach Verbindungsaufbau ausfuehren.
    135 		if	( ! empty($this->conf['connection_sql']) )
    136 		{
    137 			$cmd = $this->conf['connection_sql'];
    138 			
    139 			$stmt = $this->sql($cmd);
    140 			
    141 			$ok = $stmt->execute();
    142 			
    143 			if	( ! $ok )
    144 			{
    145 				throw new DatabaseException( "Could not execute connection-query '".$cmd."'");
    146 			}
    147 		}
    148 
    149 		// Setting isolation level to "read committed".
    150         // if another session is committing data, we want to read that immediatly
    151         if  ( $this->conf['persistent'])
    152         {
    153 //            $sql = $this->sql('ROLLBACK');
    154 //            $sql->execute();
    155 //            $sql = $this->sql('SET TRANSACTION ISOLATION LEVEL READ COMMITTED');
    156 //            $sql->execute();
    157         }
    158 
    159 
    160         Logger::debug('Database connection established');
    161 	}
    162 
    163 	/**
    164 	 * Startet eine Transaktion.
    165 	 */
    166 	public function start()
    167 	{
    168 	    Logger::debug("Starting database transaction!");
    169 		$this->transactionInProgress = true;
    170 		$this->client->start();
    171 	}
    172 	
    173 	
    174 	/**
    175 	 * Beendet und bestaetigt eine Transaktion.
    176 	 * Falls der Schalter 'transaction' nicht gesetzt ist, passiert nichts.
    177 	 */
    178 	public function commit()
    179 	{
    180         if	( $this->transactionInProgress )
    181         {
    182             Logger::debug("Committing database transaction!");
    183             $this->client->commit();
    184 			$this->transactionInProgress = false;
    185 		} else {
    186             Logger::warn("No Transaction in progress, ignoring commit request.");
    187         }
    188 	}
    189 	
    190 
    191 	
    192 	/**
    193 	 * Setzt eine Transaktion zurueck. 
    194 	 * Falls der Schalter 'transaction' nicht gesetzt ist, passiert nichts.
    195 	 */
    196 	public function rollback()
    197 	{
    198         if	( $this->transactionInProgress )
    199         {
    200             Logger::debug("Rolling back database transaction!");
    201             $this->client->rollback();
    202 			$this->transactionInProgress = false;
    203         } else {
    204             Logger::warn("No Transaction in progress, ignoring rollback request.");
    205         }
    206 	}
    207 
    208 
    209 	public function disconnect()
    210     {
    211         $this->client->disconnect();
    212         $this->client = null; // clear references to the client
    213     }
    214     /**
    215      * @param $sql string das SQL
    216      * @return Statement
    217      */
    218     public function sql($sql )
    219 	{
    220 		return new Statement( $sql,$this->client,$this->conf);
    221 	}
    222 
    223 
    224     private function executeSystemCommand( $cmd )
    225     {
    226         $ausgabe = array();
    227         $rc      = false;
    228 
    229         Logger::debug("Database command executing: " . $cmd );
    230         exec($cmd, $ausgabe, $rc);
    231 
    232         foreach ($ausgabe as $zeile)
    233             Logger::debug("Database command output: " . $zeile);
    234 
    235         if ($rc != 0) {
    236             throw new DatabaseException('Command failed: ' . implode("", $ausgabe));
    237         }
    238     }
    239 
    240 
    241 	/**
    242 	 * database label.
    243 	 *
    244 	 * @return string
    245 	 */
    246     public function getLabel() {
    247 		return array_values(array_filter( array(
    248 			@$this->conf['description'],
    249 			@$this->conf['name'  ],
    250 			$this->id,
    251 			@$this->conf['host'  ],
    252 			@$this->conf['driver'],
    253 			@$this->conf['type'  ],
    254 		)))[0];
    255 	}
    256 }