new file mode 100644
--- /dev/null
+++ b/classes/bfw/Database.php
@@ -0,0 +1,438 @@
+<?php
+
+namespace bfw {
+
+ /**
+ * Copyright(C) 2015 Markus Bröker<broeker.markus@googlemail.com>
+ *
+ */
+ class Database implements DBInterface {
+ private static $logger = null;
+
+ private $link;
+ private static $handle = null;
+
+ private function __construct() {
+ self::$logger = \Logger::getLogger('__CLASS__');
+
+ $this->link = mysqli_connect($host = 'localhost', $user = 'ticketsystem', $password = 'ticketsystem', $database = 'ticketsystem');
+ mysqli_set_charset($this->link, 'utf8');
+ }
+
+ /**
+ * <b>Liefert das Singleton-Pattern der Datenbank-Schicht</b>
+ *
+ * Es existiert in einem Lauf, einem Scope, immer nur ein DB-Handle zur gleichen Zeit.
+ *
+ * Damit das ganze vernünftig flutscht, muss man natürlich berücksichtigen, dass ein SP state-lastig ist!
+ *
+ * Definition des States: Ein Abfrageergebnis stellt solange den State des SP da, bis eine neue Abfrage
+ * einen neuen State erzeugt.
+ *
+ * @return Database|null
+ */
+ public static function getInstance() {
+ if (self::$handle == null) {
+ self::$handle = new Database();
+ }
+
+ return self::$handle;
+ }
+
+ /**
+ * <b>Std-Abfrage Methode der DB-Klasse</b>
+ *
+ * Das übergebene SQL-Statement wird als assoziatives, ein-oder mehrdimensionales Array zurück geliefert.
+ *
+ * array = (
+ * 'id' => 1,
+ * 'name' => 'Ticket',
+ * );
+ *
+ * @param $sql
+ * @return array|null
+ */
+ public function query($sql) {
+ self::$logger->info(sprintf('%s(%s) ', __METHOD__, $sql));
+
+ $result = mysqli_query($this->link, $sql);
+
+ if ($result == false) {
+ return null;
+ }
+
+ if ($result->num_rows == 0) {
+ return null;
+ }
+
+ $rows = array();
+ while (($row = $result->fetch_assoc())) {
+ $rows[] = $row;
+ }
+
+
+ return $rows;
+ }
+
+ /**
+ * <b>Abfragen, die kein ResultSet zurück liefern</b>
+ *
+ * SQL-Statements, die nur TRUE oder FALSE zurück liefern,
+ * müssen per EXECUTE ausgeführt werden.
+ *
+ * @param $sql
+ * @return bool|mysqli_result
+ */
+ public function execute($sql) {
+ self::$logger->info(sprintf('%s(%s) ', __METHOD__, $sql));
+
+ $result = mysqli_query($this->link, $sql);
+
+ return $result;
+ }
+
+ /**
+ * <b>Die einfache Fetch-Methode für das Table-Row-Pattern</b>
+ *
+ * Es wird ein SQL Statement bezogen auf die aktuelle Tabelle zusammen
+ * gebaut. Dieses kann optional eine WHERE clause beinhalten.
+ *
+ * @param $table
+ * @param string $cond
+ * @return array|null
+ */
+ public function fetch($table, $cond = 'id > 1') {
+ self::$logger->info(sprintf('%s(%s, %s) ', __METHOD__, $table, $cond));
+
+ $sql = "
+ SELECT
+ *
+ FROM
+ $table
+ WHERE
+ $cond
+ ";
+
+ $result = mysqli_query($this->link, $sql);
+
+ if ($result == false) {
+ return null;
+ }
+
+ return $result->fetch_assoc();
+ }
+
+ /**
+ * <b>Die multiple Fetch-Methode für das Table-Row-Pattern</b>
+ *
+ * Der Rückgabewert ist ein Array mit allen Zeilen als assoziatives Array
+ *
+ * @param $table
+ * @param string $cond
+ * @return array|null
+ */
+ public function fetchAll($table, $cond = 'id > 0') {
+ self::$logger->info(sprintf('%s(%s, %s) ', __METHOD__, $table, $cond));
+
+ $sql = sprintf("
+ SELECT
+ *
+ FROM
+ `%s`
+ WHERE
+ %s
+ ", $table, $cond);
+
+ return $this->query($sql);
+ }
+
+ /**
+ * <b>Die einfache Find-Methode für das Table-Row-Pattern</b>
+ *
+ * Der Rückgabewert ist entweder die Tabellenzeile 'id' oder null
+ * im assoziativen Array.
+ *
+ * @param $table
+ * @param $id
+ * @return array|null
+ */
+ public function find($table, $id) {
+ self::$logger->info(sprintf('%s(%s, %s) ', __METHOD__, $table, $id));
+
+ $sql = sprintf("
+ SELECT
+ *
+ FROM
+ `%s`
+ WHERE
+ `id` = %d
+ ", $table, $id);
+
+ $result = mysqli_query($this->link, $sql);
+
+ if ($result == false) {
+ return null;
+ }
+
+ return $result->fetch_assoc();
+ }
+
+ /**
+ * <b>Die multiple Find-Methode für das Table-Row-Pattern</b>
+ *
+ * Es liefert alle Reihen als assoziatives Array zurück.
+ *
+ * @param $table
+ * @return array|null
+ */
+ public function findAll($table, $sys_id = 1) {
+ self::$logger->info(sprintf('%s(%s) ', __METHOD__, $table));
+
+ $sql = sprintf("
+ SELECT
+ *
+ FROM
+ `%s`
+ WHERE
+ `id` > %d
+ ", $table, $sys_id);
+
+ return $this->query($sql);
+ }
+
+ /**
+ * <b>Liefert ein Resultset bezogen auf ein bestimmtes Feld zurück</b>
+ *
+ * @param $table
+ * @param $field
+ * @param $value
+ * @return array|null
+ */
+ public function findByField($table, $field, $value) {
+ self::$logger->info(sprintf('%s(%s, %s, %s) ', __METHOD__, $table, $field, $value));
+
+ $sql = sprintf("
+ SELECT
+ *
+ FROM
+ `%s`
+ WHERE
+ `%s` = '%s'
+ ", $table, $field, $value);
+
+ $result = mysqli_query($this->link, $sql);
+
+ if ($result == false) {
+ return null;
+ }
+
+ return $result->fetch_assoc();
+ }
+
+ /**
+ * <b>Liefert mehrere Resultsets bezogen auf ein bestimmtes Feld zurück</b>
+ *
+ * @param $table
+ * @param $field
+ * @param $value
+ * @return array|null
+ */
+ public function findAllByField($table, $field, $value) {
+ self::$logger->info(sprintf('%s(%s, %s) ', __METHOD__, $table, $field));
+
+ $sql = sprintf("
+ SELECT
+ *
+ FROM
+ `%s`
+ WHERE
+ `%s` = '%s'
+ ", $table, $field, $value);
+
+ return $this->query($sql);
+ }
+
+ /**
+ * <b>Die Standard Persist Methode erstellt einen neuen DB-Eintrag in der angegebenen Tabelle</b>
+ *
+ * @param $table
+ * @param $array
+ * @return bool|mysqli_result
+ */
+ public function persist($table, $array) {
+ self::$logger->info(sprintf('%s(%s, %s) ', __METHOD__, $table, print_r($array, true)));
+
+ $keys = array();
+ foreach (array_keys($array) as $key) {
+ if ($key != 'id') {
+ $keys[] = sprintf("`%s`", $key);
+ }
+ }
+
+ $fieldList = implode(", ", $keys);
+
+ $values = array();
+ foreach ($array as $key => $value) {
+ if ($key != 'id') {
+ $values[] = sprintf("'%s'", $value);
+ }
+ }
+
+ $fields = implode(",", $values);
+
+ $sql = sprintf("
+ INSERT INTO `%s`
+ (`id`, %s) VALUES (NULL, %s)
+ ", $table, $fieldList, $fields);
+
+ return $this->execute($sql);
+ }
+
+ /**
+ * <b>Die Standard store Methode aktualisiert einen DB-Eintrag in der angegebenen Tabelle</b>
+ *
+ * @param $table
+ * @param $id
+ * @param $array
+ * @return bool
+ */
+ public function store($table, $id, $array) {
+ self::$logger->info(sprintf('%s(%s, %d, %s) ', __METHOD__, $table, $id, print_r($array, true)));
+
+ $list = array();
+ foreach ($array as $key => $value) {
+ if ($key != 'id') {
+ $list[] = sprintf("`%s` = '%s'", $key, $value);
+ }
+ }
+
+ $listItems = implode(", ", $list);
+
+ $sql = sprintf("
+ UPDATE `%s`
+ SET %s
+ WHERE `id` = %d
+ ", $table, $listItems, $id);
+
+
+ return $this->execute($sql);
+ }
+
+ /**
+ * <b>Die Standard Delete Methode löscht einen bestehenden DB-Eintrag aus der angegebenen Tabelle</b>
+ *
+ * @param $table
+ * @param $id
+ * @return bool
+ */
+ public function delete($table, $id) {
+ self::$logger->info(sprintf('%s(%s, %s) ', __METHOD__, $table, $id));
+
+ $sql = sprintf("
+ DELETE FROM `%s`
+ WHERE `id` = %d;
+ ", $table, $id);
+
+ return $this->execute($sql);
+ }
+
+ /**
+ * <b>Liefert die letzte, verwendete ID, die eingefügt wurde.</b>
+ *
+ * Es gilt zu beachten, dass es sich hierbei um eine state-behaftete Methode handelt.
+ *
+ * <b>Nach 3 Inserts liefert diese Methode definitiv nur den PK des letzten INSERTS.</b>
+ *
+ * @return int|string
+ */
+ public function getLastInsertedId() {
+ $lastInsertedId = mysqli_insert_id($this->link);
+
+ self::$logger->info(sprintf('%s(): %d', __METHOD__, $lastInsertedId));
+
+ return $lastInsertedId;
+ }
+
+ /**
+ * <b>Diese Methode löscht alle Tickets, History und Benutzer weg</b>
+ *
+ * Diese Methode sollte dann aufgerufen werden, wenn die Anwendung deployed wird
+ *
+ * Auf Deutsch: "Vor der Präsi alles weglöschen."
+ *
+ * @return bool
+ */
+ public function cleanup() {
+ $status = $this->execute("DELETE FROM `t_ticket` WHERE `id` > 1;");
+ $status &= $this->execute("DELETE FROM `t_history` WHERE `id` > 1;");
+ $status &= $this->execute("DELETE FROM `t_user` WHERE `id` > 2;");
+
+ $status &= $this->execute("ALTER TABLE `t_history` AUTO_INCREMENT = 1;");
+ $status &= $this->execute("ALTER TABLE `t_ticket` AUTO_INCREMENT = 1;");
+ $status &= $this->execute("ALTER TABLE `t_user` AUTO_INCREMENT = 2;");
+
+ return $status;
+ }
+
+ /**
+ * <b>Import von Datensätzen im CSV-Format(besser gesagt SSV-Format)</b>
+ *
+ * Die Tabelle 'table' wird automatisiert mit den Werten aus der SSV-Datei befüllt.
+ *
+ * @param $table
+ * @param $filename
+ * @return bool
+ */
+ public function csvImport($table, $filename) {
+ $db = Database::getInstance();
+
+ $handle = fopen($filename, 'r');
+
+ $lines = array();
+ while (!feof($handle)) {
+ $lines[] = trim(fgets($handle), "[\r\n\t]");
+ }
+
+ fclose($handle);
+
+ if (count($lines) < 2) {
+ return false;
+ }
+
+ $spaltenKoepfeArray = explode(';', $lines[0]);
+ for ($i = 0; $i < count($spaltenKoepfeArray); $i++) {
+ $spaltenKoepfeArray[$i] = sprintf("`%s`", $spaltenKoepfeArray[$i]);
+ }
+
+ $spaltenInhaltArray = array();
+ for ($i = 1; $i < count($lines); $i++) {
+ $spaltenInhaltArray[] = explode(';', $lines[$i]);
+ }
+
+ $spaltenKoepfe = implode(', ', $spaltenKoepfeArray);
+
+ foreach ($spaltenInhaltArray as $sia) {
+ for ($i = 0; $i < count($sia); $i++) {
+
+ if ($spaltenKoepfeArray[$i] == '`last_access`') {
+ $sia[$i] = sprintf("'%s'", date("Y-m-d H:i:s"));
+ } else {
+ $sia[$i] = sprintf("'%s'", $sia[$i]);
+ }
+ }
+
+ $spaltenInhalt = implode(', ', $sia);
+ if (count($spaltenKoepfeArray) == count($sia)) {
+ $sql = sprintf("INSERT INTO %s(id, %s) VALUES(NULL, %s);", $table, $spaltenKoepfe, $spaltenInhalt);
+ if (!$db->execute($sql)) {
+
+ return false;
+ }
+ }
+ }
+
+ return true;
+ }
+
+ }
+}
\ No newline at end of file