Erster Stand des mvc-Frameworks

This commit is contained in:
2016-08-11 14:03:25 +00:00
parent 7dffe66e91
commit 5a1dd25023
32 changed files with 8715 additions and 0 deletions

View File

@@ -0,0 +1,78 @@
<?php
/**
* Created by CS medien- & kommunikationssysteme.
* @author Christian Steinle
* @date 03.08.2016
*
* @copyright CS medien- & kommunikationssysteme (http://www.steinle-computer.de)
*/
namespace Controller;
use Helper\Database;
use Model\NavigationModel;
use View\StandardView;
use View\NavigationView;
class FrontendController
{
protected $route = '';
protected $request = array();
protected $contents = array();
public function __construct($route, array $request)
{
$this->route = $route;
$this->routeParts = explode('/', $route);
$this->request = $request;
$this->init();
}
private function init()
{
NavigationModel::init($this->routeParts);
$navigation = new NavigationView(NavigationModel::getData(), $this->routeParts);
$this->contents['title'] = 'AHD Allradhaus';
$this->contents['navigation'] = $navigation->getHtml();
$this->contents['headline'] = NavigationModel::getHeadline();
$this->contents['content'] = '';
$tmpContents = NavigationModel::getContents();
/**
* @var Database $modelClass
*/
foreach ($tmpContents as $key => $data)
{
$modelClass = 'Model\\' . $data['Controller'] . 'Model';
$viewClass = 'View\\' . $data['Controller'] . 'View';
if (class_exists($modelClass, true))
{
$modelData = $modelClass::getItem($data['ID']);
}
else
{
/**
* TODO: ErrorHandler bauen
*/
return;
}
if (class_exists($viewClass, true))
{
$dataView = new $viewClass($modelData, $data['Controller']);
}
else
{
$dataView = new StandardView($modelData, $data['Controller']);
}
$this->contents['content'] .= $dataView->render();
}
$pageView = new StandardView($this->contents, 'index');
echo $pageView->render();
}
}

View File

@@ -0,0 +1,127 @@
<?php
/**
* Singleton-Klasse zur Herstellung der Datenbank-Verbindung
*
* @author Christian Steinle
* @date 02.08.2016
*
* @copyright CS medien- & kommunikationssysteme (http://www.steinle-computer.de)
*/
namespace Helper;
use mysqli;
class Database
{
/**
* Name der Datenbank-Tabelle für das Entsprechende Modell
*/
const TBL_NAME = '';
/**
* Name des Datenbank-Feldes mit dem PrimaryKey
*/
const PRIMARY_KEY = '';
/**
* Sortierung der Elemente für die Methode getIndex
*/
const ORDER_BY = '';
/**
* Der Filter für den Aufruf von getIndex()
* @var string
*/
static $filter = '1=1';
/**
* Hier werden die Daten von getIndex() gespeichert
* @var array
*/
static $data = array();
/**
* @var \mysqli|null
*/
protected static $db = null;
protected function __construct()
{
}
protected function __clone()
{
}
/**
* Stellt die Datenbank-Verbindung her
*
* return void
*/
final protected static function getInstance()
{
if (null === self::$db)
{
self::$db = new mysqli(DB_HOST, DB_USER, DB_PASS, DB_NAME);
self::$db->set_charset('utf8');
}
}
/**
* Liefert ein assoziatives Array des Datensatzes mit der übergebenen ID
*
* @param int $id
* @return array
*/
final public static function getItem($id)
{
$sql = 'SELECT * FROM ' . static::TBL_NAME . ' WHERE ' . static::PRIMARY_KEY . ' = ' . $id . ';';
$data = self::query($sql);
return (!is_array($data) || empty($data)) ? array() : current($data);
}
/**
* Liefert ein mehrdimensionales, assoziatives Array mit allen Datensätzen, die zum Filter passen
* als Schlüssel der ersten Dimension dient der Wert des Primär-Schlüssels der Datenbank-Tabelle
* Legt alle Daten in self::$data ab
*
* @see self::query()
* @see self::$data
*
* @return array
*/
final public static function getIndex()
{
$sql = 'SELECT * FROM ' . static::TBL_NAME . ' WHERE ' . static::$filter . ' ' . static::ORDER_BY . ';';
self::$data = self::query($sql);
return self::$data;
}
/**
* Liefert ein mehrdimensionales, assoziatives Array mit allen Datensätzen, die zum SQL-Query passen
* als Schlüssel der ersten Dimension dient der Wert des Primär-Schlüssels der Datenbank-Tabelle
*
* @param string $sql
* @return array
*/
final protected static function query($sql)
{
self::getInstance();
$result = self::$db->query($sql);
$data = array();
while ($tmpData = $result->fetch_assoc())
{
$data[$tmpData[static::PRIMARY_KEY]] = $tmpData;
}
return $data;
}
}

View File

@@ -0,0 +1,77 @@
<?php
/**
* Hilfsklasse zum Auslesen der Umgebungsvariablen, die in einer .htaccess gesetzt sind
*
* @author Christian Steinle
* @date 02.08.2016
*
* @copyright CS medien- & kommunikationssysteme (http://www.steinle-computer.de)
*/
namespace Helper;
use Singleton\SingletonAbstract;
class Environment extends SingletonAbstract
{
/**
* @var string
*/
protected static $_environment = '';
/**
* @return Environment|null
*/
public static function getInstance()
{
if (null === self::$_instance)
{
self::$_instance = new self;
self::setEnvironment();
}
return self::$_instance;
}
/**
* Falls ein Skript via Apache gestartet wird, zieht getenv.
* Andernfalls werden die Informationen aus einer .htaccess im FileSystem ausgelesen.
*/
protected static function setEnvironment()
{
$environment = getenv('ENVIRONMENT');
if ($environment === false)
{
$tmpPath = __DIR__;
while ($tmpPath != '/')
{
$htFile = $tmpPath . '/.htaccess';
if (is_file($htFile) && is_readable($htFile))
{
$htContent = file($htFile);
foreach ($htContent as $line => $text)
{
if (strpos($text, 'SetEnv') !== false && strpos($text, 'ENVIRONMENT') !== false)
{
self::$_environment = trim(str_replace(array('SetEnv', 'ENVIRONMENT'), '', $text));
exit();
}
}
}
$tmpPath = dirname($tmpPath);
}
$environment = '';
}
self::$_environment = $environment;
}
/**
* @return string
*/
public static function getEnvironment()
{
return self::$_environment;
}
}

View File

@@ -0,0 +1,46 @@
<?php
/**
* Hilfsklasse zur Registrierung von Variablen
*
* @author Christian Steinle
* @date 02.08.2016
*
* @copyright CS medien- & kommunikationssysteme (http://www.steinle-computer.de)
*/
namespace Helper;
use Singleton\SingletonAbstract;
class Registry extends SingletonAbstract
{
/**
* Hält alle Registrierungsdaten fürs System
* @var array
*/
private $data = array();
/**
* @param string $name
* @param mixed $value
*/
public function __set($name, $value)
{
$this->data[$name] = $value;
}
/**
* @param string $name
* @return mixed|null
*/
public function __get($name)
{
if (array_key_exists($name, $this->data))
{
return $this->data[$name];
}
return null;
}
}

View File

@@ -0,0 +1,20 @@
<?php
/**
* Created by CS medien- & kommunikationssysteme.
* @author Christian Steinle
* @date 03.08.2016
*
* @copyright CS medien- & kommunikationssysteme (http://www.steinle-computer.de)
*/
namespace Model;
use Helper\Database;
class ImageTextModel extends Database
{
const TBL_NAME = TBL_IMAGE_TEXT;
const PRIMARY_KEY = 'ID';
}

View File

@@ -0,0 +1,132 @@
<?php
/**
* Created by CS medien- & kommunikationssysteme.
* @author Christian Steinle
* @date 03.08.2016
*
* @copyright CS medien- & kommunikationssysteme (http://www.steinle-computer.de)
*/
namespace Model;
use Helper\Database;
class NavigationModel extends Database
{
const TBL_NAME = TBL_FRONT_NAVIGATION;
const PRIMARY_KEY = 'navID';
const ORDER_BY = 'ORDER BY navSort ASC';
static $filter = 'navActive = "yes"';
protected static $navigationPath = array();
protected static $activeNavID = 0;
protected static $header = '';
protected static $headline = '';
protected static $contents = array();
/**
* Setzt später benötigte Variablen für den FrontendController, so dass die Datenmodelle und die Views instanziiert werden können
* @param array $routeParts
*/
public static function init(array $routeParts)
{
self::getIndex();
$nav = self::$data;
$navStart = 0;
foreach ($routeParts as $navLink)
{
foreach ($nav as $navID => $navItem)
{
if ($navItem['navStart'] == $navStart && $navItem['navLink'] == $navLink)
{
$navStart = $navItem['navID'];
self::$navigationPath[] = self::$activeNavID = $navItem['navID'];
self::$header = $navItem['navHeader'];
self::$headline = $navItem['navHeadline'];
self::initContent($navItem['navContent']);
}
}
}
}
/**
* @param string $navContents
*/
protected static function initContent($navContents)
{
if (is_null($navContents))
{
return;
}
if (is_array(json_decode($navContents, true)))
{
self::$contents = json_decode($navContents, true);
}
}
/**
* @return array
*/
public static function getNavigationPath()
{
return self::$navigationPath;
}
/**
* @return int
*/
public static function getActiveNavID()
{
return self::$activeNavID;
}
/**
* @return string
*/
public static function getHeader()
{
return self::$header;
}
/**
* @return string
*/
public static function getHeadline()
{
return self::$headline;
}
/**
* @return array
*/
public static function getContents()
{
return self::$contents;
}
/**
* @return array
*/
public static function getData()
{
return self::$data;
}
}

View File

@@ -0,0 +1,62 @@
<?php
/**
* Standard RouteHandler
* Instanziiert den Standard Controller
* @author Christian Steinle
* @date 03.08.2016
*
* @copyright CS medien- & kommunikationssysteme (http://www.steinle-computer.de)
*/
namespace Route;
use Controller\FrontendController;
class FrontendRoute
{
/**
* @var string
*/
protected $route = '';
/**
* @var array
*/
protected $routeParts = array();
/**
* @var array
*/
protected $request = array();
protected $controller = null;
protected $action = '';
/**
* FrontendRoute constructor.
* @param string $route
* @param array $request
*/
public function __construct($route, array $request = array())
{
$this->setRoute($route);
$this->request = $request;
$this->controller = new FrontendController($this->route, $request);
}
/**
* @param string $route
*/
private function setRoute($route)
{
$this->route = trim($route, " \t\n\r\0\x0B/");
$this->routeParts = explode('/', $this->route);
}
}

View File

@@ -0,0 +1,48 @@
<?php
/**
* Created by CS medien- & kommunikationssysteme.
* @author Christian Steinle
* @date 02.08.2016
*
* @copyright CS medien- & kommunikationssysteme (http://www.steinle-computer.de)
*/
namespace Singleton;
class SingletonAbstract
{
/**
* @var null|SingletonAbstract
*/
protected static $_instance = null;
/**
* Protected wegen Singleton
*/
final protected function __construct()
{
}
/**
* Protected wegen Singleton
*/
final protected function __clone()
{
}
/**
* @return SingletonAbstract
*/
public static function getInstance()
{
if (null === self::$_instance)
{
self::$_instance = new self;
}
return self::$_instance;
}
}

View File

@@ -0,0 +1,112 @@
<?php
/**
* Created by CS medien- & kommunikationssysteme.
* @author Christian Steinle
* @date 03.08.2016
*
* @copyright CS medien- & kommunikationssysteme (http://www.steinle-computer.de)
*/
namespace View;
class NavigationView
{
/**
* Die flache Navigation
* @var array
*/
protected $navigationParts = array();
/**
* Array der aktiven Navigations-Elemente
* @var array
*/
protected $navigationPath = array();
/**
* Die strukturierte Navigation nach navStart
* @var array
*/
protected $orderedNavigation = array();
/**
* Das Html der kompletten Navigation
* @var string
*/
protected $navigationHtml = '';
public function __construct(array $navigationParts, array $navigationPath)
{
$this->navigationParts = $navigationParts;
$this->navigationPath = $navigationPath;
$this->buildOrderedNavigation();
$this->buildNavigation(0);
}
private function buildOrderedNavigation()
{
$orderedNavigation = array();
foreach ($this->navigationParts as $navID => $navItem)
{
$orderedNavigation[$navItem['navStart']][$navID] = $navItem;
}
$this->orderedNavigation = $orderedNavigation;
}
private function buildNavigation($navStart, $linkPrefix = PATH_PREFIX, $depth = 0)
{
$tmpNavigation = $this->orderedNavigation[$navStart];
$activePath = PATH_PREFIX . '/' . implode('/', $this->navigationPath);
if ($depth === 0)
{
$this->navigationHtml .= '<div class="" id="bs-example-navbar-collapse-1"><ul class="nav navbar-nav">';
}
else
{
$this->navigationHtml .= '<ul class="dropdown-menu' . (($depth > 1) ? ' pull-left' : '') . '">';
}
foreach ($tmpNavigation as $navID => $navItem)
{
$liClasses = array();
$aClass = '';
$span = '';
if (strpos($activePath, $linkPrefix . '/' . $navItem['navLink']) === 0)
{
$liClasses[] = 'active';
}
if (isset($this->orderedNavigation[$navItem['navID']]))
{
$liClasses[] = 'dropdown-submenu';
$aClass = 'class="dropdown-toggle" ';
$span = ' <span class="caret' . (($depth > 0) ? ' rotate-left' : '') . '"></span>';
}
$liClass = (empty($liClasses)) ? '' : ' class="' . implode(' ', $liClasses) . '"';
$this->navigationHtml .= '<li' . $liClass . '><a ' . $aClass . 'href="' . $linkPrefix . '/' . $navItem['navLink'] . '">' . $navItem['navName'] . $span . '</a>';
if (isset($this->orderedNavigation[$navItem['navID']]))
{
$this->buildNavigation($navItem['navID'], $linkPrefix . '/' . $navItem['navLink'], ($depth + 1));
}
$this->navigationHtml .= '</li>';
}
$this->navigationHtml .= '</ul>';
if ($depth === 0)
{
$this->navigationHtml .= '</div>';
}
}
public function getHtml()
{
return $this->navigationHtml;
}
}

View File

@@ -0,0 +1,46 @@
<?php
/**
* Created by CS medien- & kommunikationssysteme.
* @author Christian Steinle
* @date 03.08.2016
*
* @copyright CS medien- & kommunikationssysteme (http://www.steinle-computer.de)
*/
namespace View;
class StandardView
{
const TPL_PATH = PATH_TPL;
protected $template = '';
protected $data = array();
public function __construct(array $data, $template)
{
$this->setTemplate($template);
$this->data = $data;
}
private function setTemplate($template)
{
if (file_exists(static::TPL_PATH . mb_strtolower($template) . '.phtml'))
{
$this->template = static::TPL_PATH . mb_strtolower($template) . '.phtml';
}
}
public function render()
{
ob_start();
include($this->template);
$pageContent = ob_get_contents();
ob_end_clean();
return $pageContent;
}
}