Compare commits

..

No commits in common. "feature/VENOM-2-admin-panel" and "master" have entirely different histories.

100 changed files with 257 additions and 3608 deletions

5
.gitignore vendored
View file

@ -466,8 +466,3 @@ conf/modules.inc.php
conf/routers.inc.php conf/routers.inc.php
conf/lang.inc.php conf/lang.inc.php
logs/Exception.log logs/Exception.log
z_dome/
composer.lock
adminer.php

View file

@ -1,18 +1,18 @@
<?php <?php
use Venom\Core\Config; use Venom\Core\Config;
use Venom\Core\Database\Database; use Venom\Core\DatabaseHandler;
$config = Config::getInstance(); $config = Config::getInstance();
$config->setVersion(1.0); $config->setVersion(1.0);
$config->setDatabase([ $config->setDatabase([
Database::DB_TYPE => 'mysql', //please change only if you know what you're doing! this can break a lot. DatabaseHandler::DB_TYPE => 'mysql', //please change only if you know what you're doing! this can break a lot.
Database::DB_HOST => '127.0.0.1', DatabaseHandler::DB_HOST => '127.0.0.1',
Database::DB_PORT => '3306', //default port is 3306 DatabaseHandler::DB_PORT => '3306', //default port is 3306
Database::DB_USER => 'venom', DatabaseHandler::DB_USER => 'venom',
Database::DB_PASSWORD => 'venomPassword', DatabaseHandler::DB_PASSWORD => 'venomPassword',
Database::DB_DB => 'venomCMS', DatabaseHandler::DB_DB => 'venomCMS',
Database::DB_EXTRA => '' // need to start with ';' DatabaseHandler::DB_EXTRA => '' // need to start with ';'
]); ]);
/** /**

0
base/lang.base.php Executable file → Normal file
View file

View file

@ -1,4 +1,9 @@
<?php <?php
//register modules -> only apply Module Path! like Meta now the ModuleLoader search for /modules/Meta/module.php! //register modules -> need to have the Module Class at parent with the init function ;)
$modules = []; $modules = [];
// register controllers that can handle templates ;) need to have a render function for this
$controllers = [
'test' => \Controllers\TestController::class,
];

18
base/router.base.php Executable file → Normal file
View file

@ -11,5 +11,19 @@ if (!isset($venom)) {
exit(1); exit(1);
} }
$router = new Router(Router::DEFAULT_ROUTER, 1.0, 'api/'); $router = new Router('defaultRouter', 1.0, 'api/');
$venom->addRouter($router); $router->addRoutes([
'/test' => [
'cl' => Route::class,
'roles' => ['ROLE_GUEST'],
'routes' => [
'*' => [
"GET" => 'getAll'
],
'1' => [
"GET" => 'getAll'
]
]
],
]);
$venom->addRouter('defaultRouter', $router);

View file

@ -5,19 +5,11 @@
"authors": [ "authors": [
{ {
"name": "Maurice Grönwoldt", "name": "Maurice Grönwoldt",
"email": "mauricegroenwoldt@gmail.com", "email": "mauricegroenwoldt@gmail.com"
"role": "founder"
},
{
"name": "Dominic Seela",
"email": "kontakt@engineertrooper.com",
"role": "friendly developer, supporter"
} }
], ],
"require": { "require": {
"ext-pdo": "*", "ext-pdo": "*"
"ext-http": "*",
"ext-json": "*"
}, },
"autoload": { "autoload": {
"psr-4": { "psr-4": {

0
conf/.gitkeep Executable file → Normal file
View file

View file

@ -7,14 +7,6 @@ create table if not exists seoData
) )
comment 'seo url mapping'; comment 'seo url mapping';
create table if not exists metaTagData
(
id int(255) auto_increment not null unique primary key,
content JSON not null,
isActive tinyint(1) default 1 null
)
comment 'Meta Tag File';
create table if not exists language create table if not exists language
( (
id int(255) auto_increment not null unique primary key, id int(255) auto_increment not null unique primary key,
@ -35,26 +27,3 @@ create table if not exists data
datatype enum ('content', 'form') datatype enum ('content', 'form')
) )
comment 'DataLoader File'; comment 'DataLoader File';
create table if not exists users
(
id int(255) auto_increment not null unique primary key,
username varchar(255) not null unique,
firstname varchar(255) not null,
lastname varchar(255) not null,
email varchar(255) not null,
password varchar(255) not null,
token varchar(255) not null,
salt varchar(255) not null,
roleId text default '0' not null,
isActive tinyint(1) default 1 null
)
comment 'User File';
create table if not exists roles
(
id int(255) auto_increment not null unique primary key,
name varchar(255) not null unique,
content JSON not null,
isActive tinyint(1) default 1 null
)

0
lang/example.php Executable file → Normal file
View file

0
logs/.gitkeep Executable file → Normal file
View file

0
public/.htaccess Executable file → Normal file
View file

7
public/admin/.htaccess Normal file
View file

@ -0,0 +1,7 @@
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_URI} (/[^.]*|\.)$ [NC]
RewriteRule .* index.php [L]

24
public/admin/index.php Normal file
View file

@ -0,0 +1,24 @@
<?php
use Venom\Core\Config;
use Venom\Core\Setup;
use Venom\Venom;
require_once '../../vendor/autoload.php';
Setup::loadConfig(true);
Setup::loadLanguage();
$config = Config::getInstance();
if ($config->isMaintenance()) {
echo 'Currently not available';
exit;
}
//if devMode is on show all errors!
if ($config->isDevMode()) {
error_reporting(E_ALL);
ini_set('error_reporting', E_ALL);
}
$venom = new Venom();
Setup::loadRouters($venom);
Setup::loadModules($venom);
$venom->run();

0
public/content/.gitkeep Executable file → Normal file
View file

View file

@ -2,12 +2,10 @@
use Venom\Core\Config; use Venom\Core\Config;
use Venom\Core\Setup; use Venom\Core\Setup;
use Venom\Helper\URLHelper;
use Venom\Venom; use Venom\Venom;
require_once '../vendor/autoload.php'; require_once '../vendor/autoload.php';
session_start(); Setup::loadConfig(false);
Setup::loadConfig(URLHelper::getInstance()->isAdminUrl());
Setup::loadLanguage(); Setup::loadLanguage();
$config = Config::getInstance(); $config = Config::getInstance();
@ -23,4 +21,4 @@ if ($config->isDevMode()) {
$venom = new Venom(); $venom = new Venom();
Setup::loadRouters($venom); Setup::loadRouters($venom);
Setup::loadModules($venom); Setup::loadModules($venom);
$venom->inject(); $venom->run();

View file

@ -1 +0,0 @@
main{display:flex;height:100vh;overflow:hidden}main h1{margin-top:30px;margin-bottom:20px}main h2{margin-top:35px;margin-bottom:25px}main h3{margin-top:20px;margin-bottom:15px}main h4{margin-top:15px;margin-bottom:10px}main.nav-open .menu{transform:translateX(0)}main.nav-open .app{transform:translateX(220px)}main.nav-open .app .nav-toggle span{transition:width .3s;width:0}main.nav-open .app .nav-toggle span:before{transform:translateY(8px) rotate(-135deg)}main.nav-open .app .nav-toggle span:after{transform:translateY(-8px) rotate(135deg)}.app{transform:translateX(0);transition:transform .4s;flex-grow:1;overflow-y:auto;margin:.6rem .8rem;width:100%;max-height:100%;background:rgba(27,27,27,.5);position:relative}.app .nav-toggle{position:absolute;cursor:pointer;left:1rem;height:25px;width:25px}.app .nav-toggle span{transform:translateY(21px)}.app .nav-toggle span,.app .nav-toggle span:after,.app .nav-toggle span:before{border-radius:1px;height:2px;width:25px;background:#fff;position:absolute;content:'';transition:transform .5s,width .4s ease-in}.app .nav-toggle span:before{top:-8px}.app .nav-toggle span:after{bottom:-8px}.menu{width:220px;background-color:#1b1b1b;box-shadow:0 3px 6px rgba(0,0,0,.16),0 3px 6px rgba(0,0,0,.23);height:100%;position:fixed;z-index:1;top:0;left:0;overflow-x:hidden;transition:.4s;transform:translateX(-220px);display:flex;flex-direction:column}.menu .logo{text-align:center;font-family:monospace}.menu div[data-link]{padding:.75rem .5rem;position:relative}.menu div[data-link]:after{background-color:#3949ab;content:"";position:absolute;left:0;bottom:0;height:3px;width:100%;transform:scaleX(0);transition:transform .4s;transform-origin:left}.menu div[data-link]:hover:after{transform:scaleX(1)}.menu div[data-link]:last-child{margin-top:auto}.menu div[data-link].active{font-weight:700}.content-area{width:calc(100% - 20px);padding-top:30px;margin:0 auto;display:block}.content-area header{display:block;text-align:center}.content-area header h2{margin:25px 0}.content-area .back-arrow{width:36px;height:36px}.content-area textarea{background:rgba(27,27,27,.5);color:#fff;margin:15px 0 0 0;font-family:sans-serif;font-size:1.1rem;min-width:100%}.content-area .modules div{padding:6px 20px 6px 0}.content-area .add-new,.content-area .overview{width:100%}.content-area .overview div[data-link]{margin-right:10px;padding:10px;background-color:rgba(0,0,0,.3)}.content-area .overview div[data-link]:hover{background-color:rgba(0,0,0,.5)}.content-area .overview .icon{display:inline-block}.content-area .add-new{padding-top:25px}@media only screen and (min-width:768px){.content-area{width:calc(100% - 40px)}.content-area .flexbox{display:flex}.content-area .overview{flex-grow:1;width:60%}.content-area .add-new{padding-top:0;flex-grow:1;width:40%}}@media only screen and (min-width:1024px){.content-area{max-width:860px;padding-top:0;margin:0 0 0 20px}}@media only screen and (min-width:1024px){main,main.nav-open{display:flex}main .app,main.nav-open .app{transform:translateX(0)}main .menu,main.nav-open .menu{position:relative;transform:translateX(0)}main .nav-toggle,main.nav-open .nav-toggle{display:none}}.role-edit .privileges .name{font-size:1.15rem}

View file

@ -1 +0,0 @@
body,html{display:flex;justify-content:center;align-items:center}.hide{display:none!important}#login-background{background-color:rgba(31,31,31,.25);-webkit-filter:blur(10px);filter:blur(10px);position:absolute;top:0;left:0;width:100%;height:100%}login{display:flex;position:relative;max-width:860px;width:90%;height:400px;padding:1rem;border-radius:10px 40px;overflow:hidden;box-shadow:0 10px 20px rgba(0,0,0,.19),0 6px 6px rgba(0,0,0,.23)}#login{z-index:1;display:flex;flex-direction:column;align-items:center;width:100%}#login .logo{width:50%;margin-bottom:20px}#login .error-message{background-color:#c51162;padding:1rem;font-size:.7rem;display:block;width:50%}#login .input-group{width:50%}#login a{text-decoration:none;color:#fff}#login a:hover{color:#3949ab}

File diff suppressed because one or more lines are too long

View file

@ -1 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?><svg xmlns="http://www.w3.org/2000/svg"><symbol viewBox="0 0 24 24" id="vt-add" xmlns="http://www.w3.org/2000/svg"><path fill="#fff" d="M13 7h-2v4H7v2h4v4h2v-4h4v-2h-4V7zm-1-5C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm0 18c-4.41 0-8-3.59-8-8s3.59-8 8-8 8 3.59 8 8-3.59 8-8 8z"/></symbol><symbol viewBox="0 0 24 24" id="vt-arrow-back" xmlns="http://www.w3.org/2000/svg"><path fill="#fff" d="M20 11H7.83l5.59-5.59L12 4l-8 8 8 8 1.41-1.41L7.83 13H20v-2z"/></symbol><symbol viewBox="0 0 24 24" id="vt-check" xmlns="http://www.w3.org/2000/svg"><path fill="#fff" d="M19 3H5a2 2 0 00-2 2v14a2 2 0 002 2h14a2 2 0 002-2V5a2 2 0 00-2-2zm-9 14l-5-5 1.41-1.41L10 14.17l7.59-7.59L19 8l-9 9z"/></symbol><symbol viewBox="0 0 24 24" id="vt-delete" xmlns="http://www.w3.org/2000/svg"><path fill="#fff" d="M6 19c0 1.1.9 2 2 2h8c1.1 0 2-.9 2-2V7H6v12zM19 4h-3.5l-1-1h-5l-1 1H5v2h14V4z"/><path d="M0 0h24v24H0z" fill="none"/></symbol><symbol viewBox="0 0 24 24" id="vt-edit" xmlns="http://www.w3.org/2000/svg"><path fill="#fff" d="M3 17.25V21h3.75L17.81 9.94l-3.75-3.75L3 17.25zM20.71 7.04a.996.996 0 000-1.41l-2.34-2.34a.996.996 0 00-1.41 0l-1.83 1.83 3.75 3.75 1.83-1.83z"/></symbol><symbol viewBox="0 0 24 24" id="vt-visibility" xmlns="http://www.w3.org/2000/svg"><path fill="#fff" d="M12 4.5C7 4.5 2.73 7.61 1 12c1.73 4.39 6 7.5 11 7.5s9.27-3.11 11-7.5c-1.73-4.39-6-7.5-11-7.5zM12 17c-2.76 0-5-2.24-5-5s2.24-5 5-5 5 2.24 5 5-2.24 5-5 5zm0-8c-1.66 0-3 1.34-3 3s1.34 3 3 3 3-1.34 3-3-1.34-3-3-3z"/></symbol></svg>

Before

Width:  |  Height:  |  Size: 1.5 KiB

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 5.9 KiB

View file

@ -1,186 +0,0 @@
class Component {
constructor(name) {
this.name = name;
this.start();
}
handle(data, ds) {
}
init() {
}
getUrl(ds) {
return '';
}
start() {
if (window.routerIsReady) {
router.addComponent(this.name || VUtils.tempId(), this);
this.init();
} else {
window.addEventListener('routerReady', this.start.bind(this));
}
}
}
class MetaDataComponent extends Component {
constructor() {
super("/metaData");
this.tpl = "metaDataList";
this.tpl2 = "metaDataEdit";
this._url = "/admin/api/metaData";
}
async handle(data, ds) {
let meTpl = ds.id ? this.tpl2 : this.tpl;
await tpl.loadTemplate(meTpl);
return await tpl.renderOn(meTpl, data.content);
}
getUrl(ds) {
let url = this._url;
if (ds.id) {
url += '/' + ds.id;
}
return url;
}
}
class OverviewComponent extends Component {
constructor() {
super("/overview");
this.tpl = "overview";
this._url = "/admin/api/overview";
}
async handle(data, ds) {
await tpl.loadTemplate(this.tpl);
return await tpl.renderOn(this.tpl, data.content);
}
getUrl(ds) {
return this._url;
}
}
class PagesComponent extends Component {
constructor() {
super("/pages");
this.tpl = "pagesList";
this.tpl2 = "pageEdit";
this._url = "/admin/api/pages";
}
async handle(data, ds) {
let meTpl = ds.id ? this.tpl2 : this.tpl;
await tpl.loadTemplate(meTpl);
return await tpl.renderOn(meTpl, data.content);
}
getUrl(ds) {
let url = this._url;
if (ds.id) {
url += '/' + ds.id;
}
return url;
}
}
class RolesComponent extends Component {
constructor() {
super("/roles");
this.tpl = "rolesList";
this.tpl2 = "roleEdit";
this._url = "/admin/api/roles";
}
async handle(data, ds) {
let meTpl = ds.id ? this.tpl2 : this.tpl;
await tpl.loadTemplate(meTpl);
return await tpl.renderOn(meTpl, data.content);
}
getUrl(ds) {
let url = this._url;
if (ds.id) {
url += '/' + ds.id;
}
return url;
}
}
class SeoUrlComponent extends Component {
constructor() {
super("/seoUrl");
this.tpl = "seoUrlList";
this.tpl2 = "seoUrlEdit";
this._url = "/admin/api/seoUrl";
}
async handle(data, ds) {
let meTpl = ds.id ? this.tpl2 : this.tpl;
await tpl.loadTemplate(meTpl);
return await tpl.renderOn(meTpl, data.content);
}
getUrl(ds) {
let url = this._url;
if (ds.id) {
url += '/' + ds.id;
}
return url;
}
}
class UsersComponent extends Component {
constructor() {
super("/users");
this.tpl = "usersList";
this.tpl2 = "userEdit";
this._url = "/admin/api/users";
}
async handle(data, ds) {
let meTpl = ds.id ? this.tpl2 : this.tpl;
await tpl.loadTemplate(meTpl);
return await tpl.renderOn(meTpl, data.content);
}
getUrl(ds) {
let url = this._url;
if (ds.id) {
url += '/' + ds.id;
}
return url;
}
}
class VenomStatusComponent extends Component {
constructor() {
super("/venomStatus");
this.tpl = "venomStatus";
this._url = "/admin/api/venomStatus";
}
async handle(data, ds) {
await tpl.loadTemplate(this.tpl);
return await tpl.renderOn(this.tpl, data.content);
}
getUrl(ds) {
return this._url;
}
}
(() => {
// init all Components ;)
new MetaDataComponent();
new OverviewComponent();
new PagesComponent();
new RolesComponent();
new SeoUrlComponent();
new UsersComponent();
new VenomStatusComponent();
if (routerIsReady) {
document.body.dispatchEvent(new CustomEvent('triggerRouter'));
} else {
document.addEventListener('routerReady', e => {
document.body.dispatchEvent(new CustomEvent('triggerRouter'));
})
}
})();

View file

@ -1 +0,0 @@
class Component{constructor(t){this.name=t,this.start()}handle(t,e){}init(){}getUrl(t){return""}start(){window.routerIsReady?(router.addComponent(this.name||VUtils.tempId(),this),this.init()):window.addEventListener("routerReady",this.start.bind(this))}}class MetaDataComponent extends Component{constructor(){super("/metaData"),this.tpl="metaDataList",this.tpl2="metaDataEdit",this._url="/admin/api/metaData"}async handle(t,e){let n=e.id?this.tpl2:this.tpl;return await tpl.loadTemplate(n),await tpl.renderOn(n,t.content)}getUrl(t){let e=this._url;return t.id&&(e+="/"+t.id),e}}class OverviewComponent extends Component{constructor(){super("/overview"),this.tpl="overview",this._url="/admin/api/overview"}async handle(t,e){return await tpl.loadTemplate(this.tpl),await tpl.renderOn(this.tpl,t.content)}getUrl(t){return this._url}}class PagesComponent extends Component{constructor(){super("/pages"),this.tpl="pagesList",this.tpl2="pageEdit",this._url="/admin/api/pages"}async handle(t,e){let n=e.id?this.tpl2:this.tpl;return await tpl.loadTemplate(n),await tpl.renderOn(n,t.content)}getUrl(t){let e=this._url;return t.id&&(e+="/"+t.id),e}}class RolesComponent extends Component{constructor(){super("/roles"),this.tpl="rolesList",this.tpl2="roleEdit",this._url="/admin/api/roles"}async handle(t,e){let n=e.id?this.tpl2:this.tpl;return await tpl.loadTemplate(n),await tpl.renderOn(n,t.content)}getUrl(t){let e=this._url;return t.id&&(e+="/"+t.id),e}}class SeoUrlComponent extends Component{constructor(){super("/seoUrl"),this.tpl="seoUrlList",this.tpl2="seoUrlEdit",this._url="/admin/api/seoUrl"}async handle(t,e){let n=e.id?this.tpl2:this.tpl;return await tpl.loadTemplate(n),await tpl.renderOn(n,t.content)}getUrl(t){let e=this._url;return t.id&&(e+="/"+t.id),e}}class UsersComponent extends Component{constructor(){super("/users"),this.tpl="usersList",this.tpl2="userEdit",this._url="/admin/api/users"}async handle(t,e){let n=e.id?this.tpl2:this.tpl;return await tpl.loadTemplate(n),await tpl.renderOn(n,t.content)}getUrl(t){let e=this._url;return t.id&&(e+="/"+t.id),e}}class VenomStatusComponent extends Component{constructor(){super("/venomStatus"),this.tpl="venomStatus",this._url="/admin/api/venomStatus"}async handle(t,e){return await tpl.loadTemplate(this.tpl),await tpl.renderOn(this.tpl,t.content)}getUrl(t){return this._url}}new MetaDataComponent,new OverviewComponent,new PagesComponent,new RolesComponent,new SeoUrlComponent,new UsersComponent,new VenomStatusComponent,routerIsReady?document.body.dispatchEvent(new CustomEvent("triggerRouter")):document.addEventListener("routerReady",t=>{document.body.dispatchEvent(new CustomEvent("triggerRouter"))});

File diff suppressed because it is too large Load diff

File diff suppressed because one or more lines are too long

0
public/theme/default/css/test.css Executable file → Normal file
View file

0
public/theme/default/js/test.js Executable file → Normal file
View file

View file

@ -1,51 +0,0 @@
<?php
namespace Venom\Admin;
use Venom\Entities\RoleEntity;
use Venom\Helper\URLHelper;
use Venom\Security\Security;
use Venom\Views\Asset;
use Venom\Views\RenderController;
use Venom\Views\VenomRenderer;
class AdminController implements RenderController
{
private string $tpl = 'default';
public function register(): bool
{
return true;
}
public function render(VenomRenderer $renderer): bool
{
if (!in_array(URLHelper::getInstance()->getUrl(), ['/admin/', '/admin'])) {
http_response_code(404);
$this->tpl = 'async';
}
$isLogin = Security::get()->hasPermission("admin", RoleEntity::TYPE_READ);
$renderer->addVar('isLoggedIn', $isLogin);
if (!$isLogin) {
Asset::get()->addCSS('login', 'login.css');
} else {
Asset::get()->addCSS('admin', 'admin-panel.css');
}
Asset::get()->addCSS('styles', 'style.css', 1);
Asset::get()->addJS('scripts', 'scripts.min.js', 1);
// Components are the Rendering-Pipeline to know how each Admin-Component needs to be rendered
Asset::get()->addJS('components', 'components.min.js', 5);
return true;
}
public function getTemplate(): string
{
return $this->tpl;
}
}

View file

@ -1,38 +0,0 @@
<?php
namespace Venom\Admin;
use Venom\Admin\Routes\LoginRoute;
use Venom\Admin\Routes\TemplateLoader;
use Venom\Routing\Route;
use Venom\Routing\Router;
use Venom\Venom;
class AdminRouterInit
{
public static function registerAdminRouters(Venom $venom): void
{
$venom->getRouter(Router::ADMIN_ROUTER)->addRoutes(self::getRoutes());
}
public static function getRoutes(): array
{
return [
'/login' => new Route(LoginRoute::class, [
'*' => [
"POST" => 'login'
],
'1' => [
"GET" => 'handle'
]
]),
'/templateLoader' => new Route(TemplateLoader::class, [
'*' => [
"GET" => 'handle'
],
]),
];
}
}

View file

@ -1,27 +0,0 @@
<?php
namespace Venom\Admin\Routes;
use Venom\Security\Security;
class LoginRoute
{
public function login(): bool
{
Security::get()->login();
return true;
}
public function handle($fnc): bool
{
if ($fnc === 'logout') {
Security::get()->logout();
echo '{"reload": true}';
die();
}
return true;
}
}

View file

@ -1,25 +0,0 @@
<?php
namespace Venom\Admin\Routes;
use Venom\Core\ArgumentHandler;
use Venom\Core\Config;
use Venom\Helper\TemplateUtil;
class TemplateLoader
{
public function handle(): bool
{
if (!Config::getInstance()->isDevMode()) {
header('Expires: ' . gmdate('D, d M Y H:i:s \G\M\T', time() + (60 * 60 * 60 * 30)));
header('Cache-Control: public');
}
$id = ArgumentHandler::get()->getItem('tpl', '..');
if (strpos($id, '..')) {
return false;
}
echo TemplateUtil::includeTemplate('jsTemplates/' . $id, '.tpl');
die();
}
}

View file

@ -8,7 +8,6 @@ class ArgumentHandler
{ {
public static ?ArgumentHandler $instance = null; public static ?ArgumentHandler $instance = null;
private array $arguments = []; private array $arguments = [];
private array $post = [];
public function __construct() public function __construct()
{ {
@ -17,7 +16,6 @@ class ArgumentHandler
} }
foreach ($_POST as $key => $item) { foreach ($_POST as $key => $item) {
$this->arguments[htmlspecialchars($key)] = htmlspecialchars($item); $this->arguments[htmlspecialchars($key)] = htmlspecialchars($item);
$this->post[htmlspecialchars($key)] = htmlspecialchars($item);
} }
} }
@ -43,14 +41,4 @@ class ArgumentHandler
{ {
return isset($this->arguments[$key]); return isset($this->arguments[$key]);
} }
public function getPostItem(string $key, $default = null)
{
return $this->post[$key] ?? $default;
}
public function hasPostItem(string $key): bool
{
return isset($this->post[$key]);
}
} }

3
src/Venom/Core/Config.php Executable file → Normal file
View file

@ -2,8 +2,7 @@
namespace Venom\Core; namespace Venom\Core;
use Venom\Core\Database\DatabaseHandler; use Venom\Models\ConfigObject;
use Venom\Entities\ConfigObject;
class Config class Config
{ {

View file

@ -1,102 +0,0 @@
<?php
namespace Venom\Core\Database;
// class that hold the Database Connection! and Executes like the DatabaseHandler
use PDO;
use PDOException;
use PDOStatement;
use Venom\Entities\DatabaseObject;
class Database
{
// constants
public const DB_TYPE = 'type';
public const DB_HOST = 'host';
public const DB_PORT = 'port';
public const DB_USER = 'user';
public const DB_PASSWORD = 'pw';
public const DB_DB = 'db';
public const DB_EXTRA = 'extra';
private ?\PDO $db = null;
public function init(array $data): void
{
//init instance with the current data... only working if the db is not init!
if ($this->db != null) {
return;
}
$dsn = '%s:host=%s;dbname=%s;port=%s';
$connectString = sprintf($dsn, $data[self::DB_TYPE], $data[self::DB_HOST], $data[self::DB_DB], $data[self::DB_PORT] . $data[self::DB_EXTRA]);
try {
$this->db = new PDO($connectString, $data[self::DB_USER], $data[self::DB_PASSWORD]);
} catch (PDOException $e) {
trigger_error($e->getMessage());
die($e->getCode());
}
}
public function getOne(string|EasyQuery $query, array $args = []): ?DatabaseObject
{
$sql = $query;
if ($query instanceof EasyQuery) {
$sql = $query->getQuery();
$args = $query->getArgs();
}
$data = $this->getAll($sql, $args);
if (count($data) > 0) {
return $data[0];
}
return null;
}
public function getAll(string|EasyQuery $query, array $args = []): array
{
$sql = $query;
if ($query instanceof EasyQuery) {
$sql = $query->getQuery();
$args = $query->getArgs();
}
$stmt = $this->db->prepare($sql);
$stmt->setFetchMode(PDO::FETCH_CLASS, DatabaseObject::class);
$stmt->execute($args);
return $stmt->fetchAll();
}
public function execute(string|EasyQuery $query, array $args = []): bool
{
$sql = $query;
if ($query instanceof EasyQuery) {
$sql = $query->getQuery();
$args = $query->getArgs();
}
$stmt = $this->db->prepare($sql);
return $stmt->execute($args);
}
public function createStatement($query): bool|PDOStatement
{
$stmt = $this->db->prepare($query);
$stmt->setFetchMode(PDO::FETCH_CLASS, DatabaseObject::class); // set to default fetch-mode :D
return $stmt;
}
public function setClass($stmt, $class)
{
$stmt->setFetchMode(PDO::FETCH_CLASS, $class);
}
public function start()
{
$this->db->beginTransaction();
}
public function commit()
{
$this->db->commit();
}
public function rollBack()
{
$this->db->rollBack();
}
}

View file

@ -1,38 +0,0 @@
<?php
namespace Venom\Core\Database;
class DatabaseHandler
{
private static ?DatabaseHandler $instance = null;
private Database $db;
private array $cache; //EntityManager Cache!
protected function __construct()
{
$this->db = new Database();
}
public static function get(): Database
{
return self::getInstance()->db;
}
public static function getInstance(): DatabaseHandler
{
if (self::$instance === null) {
self::$instance = new DatabaseHandler();
}
return self::$instance;
}
public static function getEntityManager($entityClass): EntityManager
{
$instance = self::getInstance();
// i dont make sure this class exist because the user should do this ;)
if (!isset($instance->cache[$entityClass])) {
$instance->cache[$entityClass] = new EntityManager($entityClass, self::get());
}
return $instance->cache[$entityClass];
}
}

View file

@ -1,220 +0,0 @@
<?php
namespace Venom\Core\Database;
// the QueryBuilder is stupid! dont use it for Very Complex Queries because it's should do Entity Loading Easier :)
class EasyQuery
{
const ORDER_ASC = 0;
const ORDER_DESC = 1;
const WHERE_AND = "AND";
const WHERE_AND_NOT = "AND NOT";
const WHERE_OR = "OR";
const WHERE_OR_NOT = "OR NOT";
const WHERE_NOT = "NOT";
private array $where = [];
private array $args = [];
private string $query = "";
private int $limit = -1;
private int $offset = 0;
private string $whereStmt = "";
private string $havingStmt = "";
private array $order = [];
private array $groupBy = [];
private array $having = [];
public function __construct(private string $tableName, private array $fields = [])
{
}
public static function createSelect(array $fields, string $table): string
{
return "SELECT " . implode(", ", $fields) . " FROM " . $table;
}
public function setWhere(string $statement): static
{
$this->whereStmt = $statement;
return $this;
}
public function setHaving(string $statement): static
{
$this->havingStmt = $statement;
return $this;
}
public function setLimit(int $limit): static
{
$this->limit = $limit;
return $this;
}
public function setOffset(int $offset): static
{
$this->offset = $offset;
return $this;
}
public function addField($field, $as = ""): static
{
if ($as !== "") {
$field .= " AS " . $as;
}
$this->fields[] = $field;
return $this;
}
public function addFields(array $fields): static
{
foreach ($fields as $field) {
$this->fields[] = $field;
}
return $this;
}
public function where($key, $value, $type = "AND"): static
{
$this->where[] = [$key, $type];
$this->args[":" . $key] = $value;
return $this;
}
public function having($key, $value, $type = "AND"): static
{
$this->having[] = [$key, $type];
$this->args[":" . $key] = $value;
return $this;
}
public function orderBy(string $key, int $mode = self::ORDER_ASC): static
{
$this->order[] = $mode === self::ORDER_DESC ? $key . " DESC" : $key;
return $this;
}
public function groupBy(string $key): static
{
$this->groupBy[] = $key;
return $this;
}
public function setArg($key, $value): static
{
$this->args[":" . $key] = $value;
return $this;
}
// returns a Query
public function addArgAndField($key, $value): static
{
$this->args[":" . $key] = $value;
$this->fields[] = $key;
return $this;
}
public function buildSelect(): static
{
// we build an easyQuery Builder that can very easy stuff
$query = self::createSelect($this->fields, $this->tableName);
if (count($this->where) > 0) {
$this->whereStmt = $this->parseStmt($this->where, $this->whereStmt);
}
if (count($this->having) > 0) {
$this->havingStmt = $this->parseStmt($this->having, $this->havingStmt);
}
if ($this->whereStmt !== "") {
$query .= " WHERE " . $this->whereStmt;
}
if (count($this->groupBy)) {
$query .= " GROUP BY " . implode(", ", $this->groupBy);
}
if ($this->havingStmt !== "") {
$query .= " HAVING " . $this->havingStmt;
}
if (count($this->order)) {
$query .= " ORDER BY " . implode(", ", $this->order);
}
if ($this->offset > 0) {
$query .= " OFFSET " . $this->offset;
}
if ($this->limit > 0) {
$query .= " LIMIT " . $this->limit;
}
$this->query = $query;
return $this;
}
public function buildInsertQuery(): static
{
$query = "INSERT INTO " . $this->tableName;
$joinedFields = implode(", ", $this->fields);
$values = implode(", ", array_keys($this->args));
$query .= "(" . $joinedFields . ") VALUES (" . $values . ")";
$this->query = $query;
return $this;
}
public function buildUpdateQuery(): static
{
$query = "UPDATE " . $this->tableName . " SET ";
$setFields = [];
foreach ($this->fields as $field) {
$setFields[] = $field . " = :" . $field;
}
$query .= implode(", ", $setFields);
if (count($this->where) > 0) {
$this->whereStmt = $this->parseStmt($this->where, $this->whereStmt);
}
if ($this->whereStmt !== "") {
$query .= " WHERE " . $this->whereStmt;
}
$this->query = $query;
return $this;
}
public function buildDeleteQuery(): static
{
$query = "DELETE FROM " . $this->tableName;
if (count($this->where) > 0) {
$this->whereStmt = $this->parseStmt($this->where, $this->whereStmt);
}
if ($this->whereStmt !== "") {
$query .= " WHERE " . $this->whereStmt;
}
$this->query = $query;
return $this;
}
public function getQuery(): string
{
return $this->query;
}
public function getArgs(): array
{
return $this->args;
}
public function getFields(): array
{
return $this->fields;
}
private function parseStmt($items, $default = ""): string
{
$query = $default;
foreach ($items as $item) {
if ($query !== "") {
$query .= " " . $item[1] . " ";
}
if ($item[1] === self::WHERE_NOT && $query === "") {
$query .= "NOT ";
}
$query .= $item[0] . " = :" . $item[0];
}
return $query;
}
}

View file

@ -1,137 +0,0 @@
<?php
namespace Venom\Core\Database;
// Entity has a Load and Save function!
// The Entity needs to have a primary key... most of the time this is a id!
use JsonSerializable;
use RuntimeException;
abstract class Entity implements JsonSerializable
{
public static string $tableName = "";
// make sure this exists!
public int $id = -1;
public string $primaryKey = "id";
public array $loadedFields = [];
public array $blackList = ["id"];
// Please override this Property in the Class you implement the Abstract Class! this is needed to run the right SQL calls
public ?array $fields = null;
// Override this if you want special fields :)
public function getLoadedFieldValues(): array
{
$keyValue = [];
foreach ($this->loadedFields as $var) {
$keyValue[$var] = $this->$var;
}
return $keyValue;
}
public function getFieldsToWrite(): array
{
if ($this->fields !== null) {
return $this->fields;
}
$localBlacklist = array_merge(["primaryKey", "tableName", "loadedFields", "blackList", "fields"], $this->blackList);
$allLoaded = in_array("*", $this->loadedFields);
$vars = get_object_vars($this);
foreach ($vars as $key => $var) {
if (in_array($key, $localBlacklist)) {
unset($vars[$key]);
}
}
if (!$allLoaded) {
foreach ($vars as $key => $var) {
if (!in_array($key, $this->loadedFields)) {
unset($vars[$key]);
}
}
}
unset($vars[$this->primaryKey]);
$this->fields = $vars;
return $this->fields;
}
public function save(): bool
{
$this->preSave();
$primaryKey = $this->primaryKey;
$fields = $this->removeEmptyFields($this->getFieldsToWrite());
$query = new EasyQuery(static::$tableName);
foreach ($fields as $key => $field) {
$query->addArgAndField($key, $field);
}
if ($this->$primaryKey === "") {
$query->buildInsertQuery();
} else {
$query->where($primaryKey, $this->$primaryKey)->buildUpdateQuery();
}
return DatabaseHandler::get()->execute($query);
}
public function load($fields = ['*'], ?EasyQuery $query = null): static
{
if ($query === null) {
$primaryKey = $this->primaryKey;
$query = new EasyQuery(static::$tableName, $fields);
$query->where($primaryKey, $this->$primaryKey)->setLimit(1)->buildSelect();
} else {
$query->setLimit(1)->buildSelect();
}
$item = DatabaseHandler::get()->getOne($query);
if ($item === null) {
return $this;
}
$lazy = $item->getData();
$this->id = $item->id;
foreach ($lazy as $key => $item) {
$this->$key = $item;
}
$this->fields = null;
$this->loadedFields = array_merge($this->loadedFields, $query->getFields());
$this->postLoad();
return $this;
}
public function __set($name, $value)
{
// Implement your own if you want to override this behaviour!
throw new RuntimeException("Write to Property: $name that is not Available in the Entity!");
}
public function delete()
{
$key = $this->primaryKey;
$query = new EasyQuery(self::$tableName);
$query->setArg($this->primaryKey, $this->$key)->buildDeleteQuery();
DatabaseHandler::get()->execute($query->getQuery(), $query->getArgs());
}
public function jsonSerialize(): array
{
return $this->getLoadedFieldValues();
}
public function preSave()
{
}
public function postLoad()
{
}
private function removeEmptyFields(array $vars): array
{
foreach ($vars as $name => $item) {
if (empty($item) && $name != $this->primaryKey) {
unset($vars[$name]);
}
}
return $vars;
}
}

View file

@ -1,136 +0,0 @@
<?php
namespace Venom\Core\Database;
use Exception;
class EntityManager
{
/** @var Entity[] */
private array $entities = [];
public function __construct(private string $classType, private Database $db)
{
}
public static function create($callable): EntityManager
{
return DatabaseHandler::getEntityManager($callable);
}
public function createEntity()
{
$ent = new $this->classType;
$this->entities[] = $ent;
return $ent;
}
public function addEntity(Entity $entity)
{
$this->entities[] = $entity;
}
public function removeEntity(Entity $entity)
{
foreach ($this->entities as $key => $item) {
if ($entity === $item) {
unset($this->entities[$key]);
break;
}
}
}
public function findBy($key, $value): ?Entity
{
foreach ($this->entities as $entity) {
if ($entity->$key === $value) {
return $entity;
}
}
return null;
}
public function saveAll(): bool
{
if (count($this->entities) === 0) {
return true;
}
try {
$this->db->start();
foreach ($this->entities as $entity) {
$entity->save();
}
$this->db->commit();
} catch (Exception $ex) {
trigger_error($ex->getMessage());
$this->db->rollBack();
return false;
}
return true;
}
public function deleteEntities(): bool
{
try {
$this->db->start();
foreach ($this->entities as $entity) {
$entity->delete();
}
$this->db->commit();
} catch (Exception $ex) {
trigger_error($ex->getMessage());
$this->db->rollBack();
return false;
}
return true;
}
public function clearAll()
{
$this->entities = [];
}
public function load(string|EasyQuery $query, $args = [], array $fields = ["*"])
{
$sql = $query;
if ($query instanceof EasyQuery) {
$query->buildSelect();
$sql = $query->getQuery();
$args = $query->getArgs();
$fields = $query->getFields();
}
$stmt = $this->db->createStatement($sql);
$this->db->setClass($stmt, $this->classType);
if ($stmt->execute($args)) {
/** @var Entity[] $all */
$all = $stmt->fetchAll();
foreach ($all as $item) {
$item->loadedFields = $fields;
$item->postLoad();
$this->addEntity($item);
}
}
}
public function execute($query): bool
{
return $this->db->execute($query);
}
public function getAll(): array
{
return $this->entities;
}
public function getFirst(): ?Entity
{
return $this->entities[0] ?? null;
}
private function addEntities(array $entities)
{
foreach ($entities as $entity) {
$this->entities[] = $entity;
}
}
}

View file

@ -0,0 +1,74 @@
<?php
namespace Venom\Core;
use PDO;
use PDOException;
use Venom\Models\DatabaseObject;
/**
* Singleton DatabaseHandler... make sure we only have one connection to the database..
* @package Venom\Database
*/
class DatabaseHandler
{
// constants
public const DB_TYPE = 'type';
public const DB_HOST = 'host';
public const DB_PORT = 'port';
public const DB_USER = 'user';
public const DB_PASSWORD = 'pw';
public const DB_DB = 'db';
public const DB_EXTRA = 'extra';
private static ?self $instance = null;
private ?PDO $db = null;
public static function get(): DatabaseHandler
{
if (self::$instance === null) {
self::$instance = new self();
}
return self::$instance;
}
public function init(array $data): void
{
//init instance with the current data... only working if the db is not init!
if ($this->db != null) {
return;
}
$dsn = '%s:host=%s;dbname=%s;port=%s';
$connectString = sprintf($dsn, $data[self::DB_TYPE], $data[self::DB_HOST], $data[self::DB_DB], $data[self::DB_PORT] . $data[self::DB_EXTRA]);
try {
$this->db = new PDO($connectString, $data[self::DB_USER], $data[self::DB_PASSWORD]);
} catch (PDOException $e) {
trigger_error($e->getMessage());
die($e->getCode());
}
}
public function getOne(string $query, array $args): ?DatabaseObject
{
$data = $this->getAll($query, $args);
if (count($data) > 0) {
return $data[0];
}
return null;
}
public function getAll(string $query, array $args): array
{
$stmt = $this->db->prepare($query);
$stmt->setFetchMode(PDO::FETCH_CLASS, DatabaseObject::class);
$stmt->execute($args);
return $stmt->fetchAll();
}
public function execute(string $query, array $args): bool
{
$stmt = $this->db->prepare($query);
return $stmt->execute($args);
}
}

5
src/Venom/Core/Language.php Executable file → Normal file
View file

@ -5,8 +5,7 @@ namespace Venom\Core;
use RuntimeException; use RuntimeException;
use Venom\Core\Database\DatabaseHandler; use Venom\Models\DatabaseObject;
use Venom\Entities\DatabaseObject;
class Language class Language
{ {
@ -21,7 +20,7 @@ class Language
public function initLang() public function initLang()
{ {
$lang = ArgumentHandler::get()->getItem("lang", $this->defaultLang->shortTag ?? 'de'); $lang = ArgumentHandler::get()->getItem("lang", $this->defaultLang->shortTag);
//check if language exists //check if language exists
$data = DatabaseHandler::get()->getOne("select id from language where shortTag = :shortTag", [ $data = DatabaseHandler::get()->getOne("select id from language where shortTag = :shortTag", [
':shortTag' => $lang ':shortTag' => $lang

15
src/Venom/Core/Module.php Executable file → Normal file
View file

@ -3,17 +3,10 @@
namespace Venom\Core; namespace Venom\Core;
interface Module interface Module
{ {
const NAME = "name"; public function register(): bool;
const AUTHOR = "author";
const SECURE = "secure"; public function init(): void;
const ROUTE = "routes";
const ADMIN_ROUTE = "adminRoutes";
const DESC = "description";
const TEMPLATES = "templates";
const ADMIN_TEMPLATES = "adminTemplates";
const CONTROLLER = "controllers";
const TEMPLATE_PATH = "tplPath";
const ACTIVE = "isActive";
} }

View file

@ -1,72 +0,0 @@
<?php
namespace Venom\Core;
use RuntimeException;
use Venom\Helper\TemplateUtil;
use Venom\Routing\Route;
use Venom\Routing\Router;
use Venom\Venom;
class ModuleLoader
{
public static function getModules(): array
{
return [
'Meta',
'User',
'Data',
'Role',
'SEO',
'VenomStatus',
];
}
public static function loadModule(string $name, Venom $venom)
{
// load module search in the Module Path for a module.php file
$dir = __DIR__ . "/../../modules/" . $name . "/module.php";
if (!file_exists($dir)) {
throw new RuntimeException("Module File: \"$dir\" Not found");
}
include_once $dir;
}
public static function initModule(array $module, Venom $venom): bool
{
if (!$module[Module::ACTIVE]) {
return false;
}
// register Router, Templates and more :)
$isAdmin = Config::getInstance()->isAdmin();
if ($isAdmin) {
self::registerRoutes($module,
$venom,
$module[Module::ADMIN_ROUTE],
$venom->getRouter(Router::ADMIN_ROUTER)
);
TemplateUtil::getInstance()->addTemplates($module[Module::ADMIN_TEMPLATES], $module[Module::TEMPLATE_PATH]);
} else {
self::registerRoutes($module,
$venom,
$module[Module::ROUTE],
$venom->getRouter(Router::DEFAULT_ROUTER)
);
TemplateUtil::getInstance()->addTemplates($module[Module::TEMPLATES], $module[Module::TEMPLATE_PATH]);
}
$venom->addControllers($module[Module::CONTROLLER]);
return true;
}
public static function registerRoutes(array $module, Venom $venom, array $routes, Router $router)
{
foreach ($routes as $key => $route) {
/** @var Route $route */
$route->module = $module[Module::NAME];
$route->isSecure = $module[Module::SECURE];
$route->venom = $venom;
$router->addRoute($key, $route);
}
}
}

2
src/Venom/Core/Registry.php Executable file → Normal file
View file

@ -3,7 +3,7 @@
namespace Venom\Core; namespace Venom\Core;
use Venom\Controller\SeoController; use Venom\Routing\SeoController;
/** /**
* Singleton Class... hold current URL => can * Singleton Class... hold current URL => can

3
src/Venom/Core/Setup.php Executable file → Normal file
View file

@ -39,6 +39,9 @@ class Setup
if (isset($modules)) { if (isset($modules)) {
$venom->initModules($modules); $venom->initModules($modules);
} }
if (isset($controllers)) {
$venom->initControllers($controllers);
}
} }
public static function loadRouters(Venom $venom): void public static function loadRouters(Venom $venom): void

View file

@ -1,59 +0,0 @@
<?php
namespace Venom\Entities;
use Venom\Core\Database\EasyQuery;
use Venom\Core\Database\Entity;
class RoleEntity extends Entity
{
public static string $tableName = "roles";
public string $name = "";
public string $content = "";
public bool $isActive = true;
private array $roles = [];
public const TYPE_WRITE = 1;
public const TYPE_READ = 0;
public const TYPE_NO = -1;
public function hasPermission(string $module, int $type): bool
{
if ($this->id === -1) {
return true;
}
if ($type === self::TYPE_NO) {
return true;
}
if (!isset($this->roles[$module]) && $type) {
return false;
}
$mod = $this->roles[$module];
return $mod["type"] === $type;
}
public function postLoad()
{
if (!empty($this->content)) {
$this->roles = json_decode($this->content);
}
}
public function preSave()
{
$this->content = json_encode($this->roles);
}
public function load($fields = ['*'], ?EasyQuery $query = null): static
{
if ($this->id === -1 || $this->id === 0) {
return $this;
}
return parent::load($fields, $query);
}
}

View file

@ -1,57 +0,0 @@
<?php
namespace Venom\Entities;
use Venom\Core\Database\EasyQuery;
use Venom\Core\Database\Entity;
class User extends Entity
{
public const ADMIN_ROLE = '-1';
public const GUEST_ROLE = '0';
public static string $tableName = "users";
public string $username = "GUEST";
public string $firstname = "";
public string $lastname = "";
public string $email = "";
public string $password = "";
public string $token = "";
public string $salt = "";
public int $roleId = 0;
public bool $isActive = true;
private ?RoleEntity $roleEntity = null;
private bool $loaded = false;
public function hasPermission(string $module, $type = RoleEntity::TYPE_WRITE): bool
{
if ($this->roleEntity === null) {
$this->roleEntity = new RoleEntity();
$this->roleEntity->id = $this->roleId;
$this->roleEntity->load();
}
return $this->roleEntity->hasPermission($module, $type);
}
public function postLoad()
{
$this->loaded = true;
}
public function isLoaded(): bool
{
return $this->loaded;
}
public function loadUser()
{
$eq = new EasyQuery(User::$tableName, ["*"]);
$eq->where("username", $this->username)
->where("id", $this->id, EasyQuery::WHERE_OR);
$this->load([], $eq);
return true;
}
}

0
src/Venom/Exceptions/ExceptionHandler.php Executable file → Normal file
View file

View file

@ -1,37 +0,0 @@
<?php
namespace Venom\Helper;
class AdminHelper
{
public static function sendResponse($content, string $component = '', bool $shouldReload = false, $extra = false)
{
$response = [
'content' => $content,
'component' => $component
];
if ($shouldReload) {
$response['reload'] = true;
}
if ($extra) {
$response['extra'] = $extra;
}
echo json_encode($response);
die();
}
public static function sendStatus(bool $isSuccess, string $message = "")
{
if ($message == "") {
$message = $isSuccess ? "Operation Success" : "Operation failed";
}
echo json_encode([
"status" => $isSuccess ? 'success' : 'failed',
"message" => $message
]);
die();
}
}

29
src/Venom/Helper/MetaGenerator.php Executable file → Normal file
View file

@ -4,40 +4,11 @@
namespace Venom\Helper; namespace Venom\Helper;
use Venom\Core\ArgumentHandler;
use Venom\Core\DatabaseHandler;
/** /**
* Class MetaGenerator * Class MetaGenerator
* @package Venom\Helper * @package Venom\Helper
*/ */
class MetaGenerator class MetaGenerator
{ {
private array $container = [];
private string $id;
public function __construct()
{
$this->id = (string)ArgumentHandler::get()->getItem('metaId', '-1');
}
public function loadById(): void
{
if ($this->id === '-1') {
return;
}
$db = DatabaseHandler::get();
$data = $db->getOne('select content from metaTagData where id = :id', [':id' => $this->id]);
if ($data !== null) {
$this->container = json_decode($data->content ?? '', true);
$this->container = array_merge([], $this->container);
}
}
public function render(): void
{
foreach ($this->container as $key => $value) {
echo '<meta name="' . $key . '" content="' . $value . '">';
}
}
} }

View file

@ -1,75 +0,0 @@
<?php
namespace Venom\Helper;
use Venom\Core\Config;
class TemplateUtil
{
private static ?TemplateUtil $instance = null;
private string $baseTemplate;
private string $templateDir;
private array $templates = [];
private function __construct()
{
if (Config::getInstance()->isAdmin()) {
$base = 'base';
$theme = 'admin';
} else {
$data = Config::getInstance()->getRenderer();
$theme = $data->theme;
$base = $data->baseFile ?? 'base';
}
$this->baseTemplate = $base . '.php';
$this->templateDir = __DIR__ . '/../../../tpl/' . $theme . '/';
}
public static function getInstance(): TemplateUtil
{
if (self::$instance === null) {
self::$instance = new TemplateUtil();
}
return self::$instance;
}
public function getDir(): string
{
return $this->templateDir;
}
public function getBase(): string
{
return $this->baseTemplate;
}
public function addTemplates($templates, string $basePath)
{
foreach ($templates as $key => $template) {
$this->templates[$key] = $basePath . $template;
}
}
public static function includeTemplate($template, $suffix = '.php'): bool|string
{
$tx = self::getInstance()->getCache($template);
if ($tx === "") {
$dir = self::getInstance()->getDir();
$tx = $dir . $template;
}
$tx .= $suffix;
if (file_exists($tx)) {
ob_start();
include_once $tx;
return ob_get_clean();
}
return '';
}
private function getCache($template)
{
return $this->templates[$template] ?? '';
}
}

5
src/Venom/Helper/URLHelper.php Executable file → Normal file
View file

@ -42,9 +42,4 @@ class URLHelper
{ {
return $url; return $url;
} }
public function isAdminUrl(): bool
{
return strpos($this->parsedUrl, '/admin') === 0;
}
} }

View file

@ -1,12 +1,10 @@
<?php <?php
namespace Venom\Entities; namespace Venom\Models;
use Venom\Core\Database\Entity; class ConfigObject
class ConfigObject extends Entity
{ {
private array $data = []; private array $data = [];

View file

@ -1,25 +1,31 @@
<?php <?php
namespace Venom\Entities; namespace Venom\Models;
use Venom\Core\Database\Entity; class DataModel
class DataEntity extends Entity
{ {
public const TYPE_CONTENT = 'content'; public const TYPE_CONTENT = 'content';
public const TYPE_FORM = 'form'; public const TYPE_FORM = 'form';
public string $id;
public string $raw;
public string $generated;
public string $type;
public int $active = 1; public int $active = 1;
public function __construct( public function __construct(
public string $id, string $id,
public string $type = self::TYPE_CONTENT, string $type = self::TYPE_CONTENT,
public string $raw = '', string $raw = '',
public string $generated = '' string $generated = ''
) )
{ {
$this->id = $id;
$this->type = $type;
$this->raw = $raw;
$this->generated = $generated;
} }
public function getId(): string public function getId(): string

View file

@ -1,16 +1,15 @@
<?php <?php
namespace Venom\Entities; namespace Venom\Models;
use Venom\Core\Database\Entity;
/** /**
* Database Object to use queries like this $obj->id, $obj->value * Database Object to use queries like this $obj->id, $obj->value
* also the option to print it in csv format ; as delimiter * also the option to print it in csv format ; as delimiter
* @package Venom\Database * @package Venom\Database
*/ */
class DatabaseObject extends Entity class DatabaseObject
{ {
private array $data = []; private array $data = [];
@ -27,24 +26,19 @@ class DatabaseObject extends Entity
$this->data[$name] = $value; $this->data[$name] = $value;
} }
public function __isset($name): bool public function __isset($name)
{ {
return isset($this->data[$name]); return isset($this->data[$name]);
} }
public function toString(): string public function toString()
{ {
return implode(';', $this->data); return implode(';', $this->data);
} }
public function getHead(): string public function getHead()
{ {
$keys = array_keys($this->data); $keys = array_keys($this->data);
return implode(';', $keys); return implode(';', $keys);
} }
public function getData(): array
{
return $this->data;
}
} }

14
src/Venom/Models/User.php Normal file
View file

@ -0,0 +1,14 @@
<?php
namespace Venom\Models;
class User
{
private string $username;
private string $password;
private string $salt;
private string $token;
private array $roles;
}

42
src/Venom/Routing/Route.php Executable file → Normal file
View file

@ -4,47 +4,7 @@
namespace Venom\Routing; namespace Venom\Routing;
use RuntimeException; interface Route
use Venom\Entities\RoleEntity;
use Venom\Security\Security;
use Venom\Venom;
class Route
{ {
const GET = "GET";
const POST = "POST";
const PUT = "PUT";
const DELETE = "DELETE";
public string $url;
public array $routes = [];
public int $maxParameters = 0;
public string $module = "unknown";
public bool $isSecure = false;
public Venom $venom;
public function __construct(public string $controller, array $config)
{
$count = count($config);
if ($count === 0) {
throw new RuntimeException("Route: \"$controller\" no valid Routes Found!");
}
$count -= isset($config["*"]) ? 1 : 0;
$this->maxParameters = $count;
$this->routes = $config;
}
public function getDefinitions($method, mixed $subRoute): ?array
{
if ($this->isSecure && !Security::get()->hasPermission($this->module, $method === Route::GET ? RoleEntity::TYPE_READ : RoleEntity::TYPE_WRITE)) {
return null;
}
if (isset($this->routes[$subRoute]) && isset($this->routes[$subRoute][$method])) {
return [
"cl" => $this->controller,
"fnc" => $this->routes[$subRoute][$method]
];
}
return null;
}
} }

48
src/Venom/Routing/Router.php Executable file → Normal file
View file

@ -5,12 +5,9 @@ namespace Venom\Routing;
use Exception; use Exception;
use Venom\Exceptions\ExceptionHandler;
class Router class Router
{ {
public const DEFAULT_ROUTER = 'defaultRouter';
public const ADMIN_ROUTER = 'adminRouter';
protected string $id = 'defaultRouter'; protected string $id = 'defaultRouter';
protected int $version; protected int $version;
protected string $prefix = ''; protected string $prefix = '';
@ -25,10 +22,10 @@ class Router
public function addRoutes(array $routes): void public function addRoutes(array $routes): void
{ {
$this->routes = array_merge($this->routes, $routes); $this->routes = $routes;
} }
public function addRoute(string $path, Route $route): void public function addRoute(string $path, array $route): void
{ {
$this->routes[$path] = $route; $this->routes[$path] = $route;
} }
@ -39,7 +36,6 @@ class Router
public function findRoute($url, $method): ?array public function findRoute($url, $method): ?array
{ {
$url = $this->removeIfFirst($url, $this->prefix); $url = $this->removeIfFirst($url, $this->prefix);
$url = $this->removeTrailingSlash($url);
// check if full match... this can easily done if the url isset select the empty! // check if full match... this can easily done if the url isset select the empty!
$method = strtoupper($method); $method = strtoupper($method);
$route = $this->getRouteByName($url, $method); $route = $this->getRouteByName($url, $method);
@ -55,25 +51,26 @@ class Router
return null; return null;
} }
private function removeIfFirst($rawString, $string): bool|string private function removeIfFirst($rawString, $string)
{ {
if ($string !== '' && str_starts_with($rawString, $string)) { if ($string !== '' && 0 === strpos($rawString, $string)) {
return substr($rawString, strlen($string)); return substr($rawString, strlen($string));
} }
return $rawString; return $rawString;
} }
/* @todo implement Security Check if SecurityModule is used */
private function getRouteByName($url, $method, $subRoute = '*', $params = []): ?array private function getRouteByName($url, $method, $subRoute = '*', $params = []): ?array
{ {
if (isset($this->routes[$url])) { $routeAvailable = isset($this->routes[$url]);
/** @var Route $route */ $subRouteFound = isset($this->routes[$url]['routes'][$subRoute]);
$route = $this->routes[$url]; $methodFound = isset($this->routes[$url]['routes'][$subRoute][$method]);
$sub = $route->getDefinitions($method, $subRoute); if ($routeAvailable && $subRouteFound && $methodFound) {
if ($sub === null) { return [
return null; 'cl' => $this->routes[$url]['cl'],
} 'fnc' => $this->routes[$url]['routes'][$subRoute][$method],
$sub["params"] = array_reverse($params); 'params' => $params
return $sub; ];
} }
return null; return null;
} }
@ -98,32 +95,17 @@ class Router
public function tryFunctionCall(?array $aRoute): bool public function tryFunctionCall(?array $aRoute): bool
{ {
if ($aRoute === null || empty($aRoute['cl']) || empty($aRoute['fnc']) || !class_exists($aRoute['cl'])) { if ($aRoute === null || !is_callable(array($aRoute['cl'], $aRoute['fnc']))) {
return false; return false;
} }
$route = new $aRoute['cl'](); $route = new $aRoute['cl']();
if (!is_callable(array($route, $aRoute['fnc']))) {
return false;
}
try { try {
$fnc = $aRoute['fnc']; $fnc = $aRoute['fnc'];
$params = $aRoute['params'] ?? []; $params = $aRoute['params'] ?? [];
$route->$fnc(...$params); $route->$fnc(...$params);
return true; return true;
} catch (Exception $ex) { } catch (Exception $ex) {
ExceptionHandler::handleException($ex);
return false; return false;
} }
} }
private function removeTrailingSlash(string $rawString): bool|string
{
$len = strlen($rawString);
return $rawString[$len - 1] === '/' ? substr($rawString, 0, strlen($rawString) - 1) : $rawString;
}
public function getId(): string
{
return $this->id;
}
} }

View file

@ -1,12 +1,12 @@
<?php <?php
namespace Venom\Controller; namespace Venom\Routing;
use Venom\Core\ArgumentHandler; use Venom\Core\ArgumentHandler;
use Venom\Core\Config; use Venom\Core\Config;
use Venom\Core\Database\DatabaseHandler; use Venom\Core\DatabaseHandler;
use Venom\Helper\ErrorHandler; use Venom\Helper\ErrorHandler;
use Venom\Helper\URLHelper; use Venom\Helper\URLHelper;

46
src/Venom/Security/BaseLogin.php Executable file → Normal file
View file

@ -4,54 +4,10 @@
namespace Venom\Security; namespace Venom\Security;
use Venom\Core\ArgumentHandler;
use Venom\Core\Config;
use Venom\Entities\User;
use Venom\Helper\URLHelper;
/** /**
* Class that Login stupid via Password, Username * Class that Login stupid via Password, Username
*/ */
class BaseLogin implements Login class BaseLogin
{ {
private User $user;
public function __construct(User $user)
{
$this->user = $user;
}
public function checkCredentials(): bool
{
$handler = ArgumentHandler::get();
return $handler->hasPostItem('USERNAME') && $handler->hasPostItem('PASSWORD');
}
public function redirect(): void
{
$url = ArgumentHandler::get()->getPostItem('REDIRECT_TO', URLHelper::getInstance()->getUrl());
if ($url === 'NO') {
echo json_encode(['message' => 'login'], JSON_THROW_ON_ERROR);
} else {
header('Location: ' . $url);
}
die();
}
public function login(): bool
{
$sec = Config::getInstance()->getSecurity();
$this->user->username = (string)ArgumentHandler::get()->getPostItem('USERNAME');
if (!$this->user->loadUser()) {
return false;
}
$secret = $sec->secret ?? 'venom';
$hashed = hash($sec->algo ?? 'SHA256', ArgumentHandler::get()->getPostItem('PASSWORD') . $secret . $this->user->salt);
if ($this->user->password === $hashed) {
$_SESSION['userID'] = $this->user->id;
return true;
}
return false;
}
} }

6
src/Venom/Security/Login.php Executable file → Normal file
View file

@ -4,12 +4,16 @@
namespace Venom\Security; namespace Venom\Security;
use Venom\Entities\User; use Venom\Models\User;
interface Login interface Login
{ {
public function __construct(User $user); public function __construct(User $user);
public function checkUsername(): bool;
public function checkPassword(): bool;
public function checkCredentials(): bool; public function checkCredentials(): bool;
public function login(): bool; public function login(): bool;

38
src/Venom/Security/Security.php Executable file → Normal file
View file

@ -3,22 +3,10 @@
namespace Venom\Security; namespace Venom\Security;
use RuntimeException;
use Venom\Core\Config;
use Venom\Entities\RoleEntity;
use Venom\Entities\User;
class Security class Security
{ {
private static ?Security $instance = null; private static ?Security $instance = null;
private ?User $user;
public function __construct()
{
$this->user = new User();
$this->user->id = $_SESSION['userID'] ?? "-1";
$this->user->load();
}
public static function get(): Security public static function get(): Security
{ {
@ -28,29 +16,15 @@ class Security
return self::$instance; return self::$instance;
} }
public function hasPermission(string $module, $type = RoleEntity::TYPE_WRITE): bool /* @todo implement logic */
public function hasRole(string $role): bool
{ {
return $this->user->hasPermission($module, $type); return true;
} }
public function login(): void /* @todo implement logic */
public function hasRoles(array $roles): bool
{ {
if ($this->user->isLoaded()) { return true;
throw new RuntimeException('Try to re-login!');
}
$sec = Config::getInstance()->getSecurity();
$login = new $sec->securityClass($this->user);
if ($login instanceof Login) {
if (!$login->checkCredentials() || !$login->login()) {
http_response_code(401);
}
$login->redirect();
}
}
public function logout(): void
{
unset($_SESSION['userID']);
$this->user = new User();
} }
} }

View file

@ -4,12 +4,9 @@
namespace Venom; namespace Venom;
use Venom\Admin\AdminController;
use Venom\Admin\AdminRouterInit;
use Venom\Core\ArgumentHandler; use Venom\Core\ArgumentHandler;
use Venom\Core\Config; use Venom\Core\Config;
use Venom\Core\Module; use Venom\Core\Module;
use Venom\Core\ModuleLoader;
use Venom\Core\Registry; use Venom\Core\Registry;
use Venom\Exceptions\ExceptionHandler; use Venom\Exceptions\ExceptionHandler;
use Venom\Helper\ErrorHandler; use Venom\Helper\ErrorHandler;
@ -30,26 +27,16 @@ class Venom
{ {
ExceptionHandler::setExceptionHandler(); ExceptionHandler::setExceptionHandler();
$this->renderer = new VenomRenderer($this); $this->renderer = new VenomRenderer($this);
$this->routers[Router::ADMIN_ROUTER] = new Router(Router::ADMIN_ROUTER, 1.0, '/admin/api');
Asset::get()->setRenderer($this->renderer); Asset::get()->setRenderer($this->renderer);
} }
public function inject(): void
{
$this->run();
}
public function run(): void public function run(): void
{ {
$arguments = ArgumentHandler::get(); $arguments = ArgumentHandler::get();
$arguments->setItem(ErrorHandler::ERROR_KEY, false); $arguments->setItem(ErrorHandler::ERROR_KEY, false);
$config = Config::getInstance();
if ($config->isAdmin()) {
$this->initAdmin();
}
// we need to load the current controller and the current start template. // we need to load the current controller and the current start template.
// after this we can start the renderer // after this we can start the renderer
if ($config->isRouterEnabled() || $config->isAdmin()) { if (Config::getInstance()->isRouterEnabled()) {
$status = $this->useRouter(); $status = $this->useRouter();
if ($status['found']) { if ($status['found']) {
if ($status['status']) { if ($status['status']) {
@ -61,32 +48,18 @@ class Venom
$registry = Registry::getInstance(); $registry = Registry::getInstance();
$registry->getLang()->initLang(); $registry->getLang()->initLang();
// if site is errored then dont load via SEO // if site is errored then dont load via SEO
if (!$config->isAdmin() && !$arguments->getItem(ErrorHandler::ERROR_KEY)) { if (!$arguments->getItem(ErrorHandler::ERROR_KEY)) {
$registry->getSeo()->loadSite(); $registry->getSeo()->loadSite();
} }
$this->renderer->init($this->findController()); $this->renderer->init($this->findController());
$this->renderer->render(); $this->renderer->render();
} }
public function initAdmin(): void
{
$this->controllers['adminCtrl'] = AdminController::class;
AdminRouterInit::registerAdminRouters($this);
ArgumentHandler::get()->setItem('cl', 'adminCtrl');
}
private function useRouter(): array private function useRouter(): array
{ {
$url = URLHelper::getInstance()->getUrl(); $url = URLHelper::getInstance()->getUrl();
$isAdmin = Config::getInstance()->isAdmin();
/** @var Router $router */ /** @var Router $router */
foreach ($this->routers as $key => $router) { foreach ($this->routers as $router) {
if ($isAdmin && $key !== Router::ADMIN_ROUTER) {
continue;
}
if (!$isAdmin && $key === Router::ADMIN_ROUTER) {
continue;
}
$route = $router->findRoute($url, $_SERVER['REQUEST_METHOD']); $route = $router->findRoute($url, $_SERVER['REQUEST_METHOD']);
$status = $router->tryFunctionCall($route); $status = $router->tryFunctionCall($route);
if ($route !== null) { if ($route !== null) {
@ -116,33 +89,21 @@ class Venom
public function initModules(array $modules): void public function initModules(array $modules): void
{ {
if (Config::getInstance()->isAdmin()) { foreach ($modules as $key => $moduleClass) {
$modules = array_merge(ModuleLoader::getModules(), $modules); $module = new $moduleClass;
} if ($module instanceof Module && $module->register()) {
foreach ($modules as $module) { $this->modules[$key] = $module;
ModuleLoader::loadModule($module, $this); }
} }
} }
public function addControllers(array $controllers): void public function initControllers(array $controllers): void
{ {
$this->controllers = array_merge($this->controllers, $controllers); $this->controllers = $controllers;
} }
public function addRouter(Router $router): void public function addRouter(string $name, Router $router): void
{ {
$this->routers[$router->getId()] = $router; $this->routers[$name] = $router;
}
public function getRouter(string $router): ?Router
{
return $this->routers[$router];
}
public function registerModule(array $module)
{
if (ModuleLoader::initModule($module, $this)) {
$this->modules[$module[Module::NAME]] = $module;
}
} }
} }

View file

@ -62,7 +62,7 @@ class Asset
usort($this->jsFiles, function ($a, $b) { usort($this->jsFiles, function ($a, $b) {
return $a['pos'] <=> $b['pos']; return $a['pos'] <=> $b['pos'];
}); });
$theme = $this->getPath('/js/'); $theme = $this->getPath('/theme/' . Config::getInstance()->getRenderer()->assetDir . '/js/');
foreach ($this->jsFiles as $key => $file) { foreach ($this->jsFiles as $key => $file) {
echo '<script src="' . $theme . $file['file'] . '" id="js-' . $key . '"></script>'; echo '<script src="' . $theme . $file['file'] . '" id="js-' . $key . '"></script>';
} }
@ -70,8 +70,7 @@ class Asset
private function getPath($base): string private function getPath($base): string
{ {
$dir = Config::getInstance()->isAdmin() ? 'admin' : Config::getInstance()->getRenderer()->assetDir; $preDir = $base;
$preDir = '/theme/' . $dir . $base;
$config = Config::getInstance(); $config = Config::getInstance();
$baseUrl = Config::getInstance()->getBaseUrl(); $baseUrl = Config::getInstance()->getBaseUrl();
if ($baseUrl !== '' && $config->getRenderer()->useStaticUrl) { if ($baseUrl !== '' && $config->getRenderer()->useStaticUrl) {
@ -85,7 +84,7 @@ class Asset
usort($this->cssFiles, function ($a, $b) { usort($this->cssFiles, function ($a, $b) {
return $a['pos'] <=> $b['pos']; return $a['pos'] <=> $b['pos'];
}); });
$theme = $this->getPath('/css/'); $theme = $this->getPath('/theme/' . Config::getInstance()->getRenderer()->assetDir . '/css/');
foreach ($this->cssFiles as $key => $file) { foreach ($this->cssFiles as $key => $file) {
echo '<link rel="stylesheet" href="' . $theme . $file['file'] . '" id="css-' . $key . '">'; echo '<link rel="stylesheet" href="' . $theme . $file['file'] . '" id="css-' . $key . '">';
} }

View file

@ -5,7 +5,7 @@ namespace Venom\Views;
use RuntimeException; use RuntimeException;
use Venom\Core\DatabaseHandler; use Venom\Core\DatabaseHandler;
use Venom\Entities\DataEntity; use Venom\Models\DataModel;
class DataLoader class DataLoader
{ {
@ -23,7 +23,7 @@ class DataLoader
return self::$instance; return self::$instance;
} }
public static function loadById(string $id): ?DataEntity public static function loadById(string $id): ?DataModel
{ {
if ($id === '') { if ($id === '') {
throw new RuntimeException('Try to Load empty ID from Database'); throw new RuntimeException('Try to Load empty ID from Database');
@ -33,14 +33,14 @@ class DataLoader
]); ]);
if ($data !== null) { if ($data !== null) {
$model = new DataEntity($data->identity, $data->datatype, $data->raw, $data->generated); $model = new DataModel($data->identity, $data->datatype, $data->raw, $data->generated);
$model->setActive(true); $model->setActive(true);
return $model; return $model;
} }
return null; return null;
} }
public function updateData(DataEntity $model): bool public function updateData(DataModel $model): bool
{ {
if ($model->getId() === '') { if ($model->getId() === '') {
return $this->insertData($model); return $this->insertData($model);
@ -57,7 +57,7 @@ class DataLoader
); );
} }
public function insertData(DataEntity $model): bool public function insertData(DataModel $model): bool
{ {
$this->validateModel($model); $this->validateModel($model);
@ -73,7 +73,7 @@ class DataLoader
); );
} }
private function validateModel(DataEntity $model): void private function validateModel(DataModel $model): void
{ {
if ($model->getId() === '') { if ($model->getId() === '') {
$model->setId($this->generateID()); $model->setId($this->generateID());
@ -87,8 +87,8 @@ class DataLoader
private function generateID(string $id = ''): string private function generateID(string $id = ''): string
{ {
if ($id === '') { if ($id === '') {
$id = bin2hex(random_bytes(32)); $id = bin2hex(random_bytes(16));
} }
return hash('SHA256', $id); return $id;
} }
} }

0
src/Venom/Views/RenderController.php Executable file → Normal file
View file

View file

@ -6,17 +6,14 @@ namespace Venom\Views;
use Venom\Core\ArgumentHandler; use Venom\Core\ArgumentHandler;
use Venom\Core\Config; use Venom\Core\Config;
use Venom\Helper\MetaGenerator;
use Venom\Helper\TemplateUtil;
use Venom\Venom; use Venom\Venom;
class VenomRenderer class VenomRenderer
{ {
private Venom $venom; private Venom $venom;
private ?RenderController $controller; private ?RenderController $controller;
private ?MetaGenerator $metaGenerator;
private string $templateData = ''; private string $templateData = '';
private array $vars = []; private array $vars = [];
private string $baseTemplate = ''; private string $baseTemplate = '';
private string $templateDir = ''; private string $templateDir = '';
@ -53,7 +50,8 @@ class VenomRenderer
public function renderTemplate($template): void public function renderTemplate($template): void
{ {
// random variable name... to remove it instantly // random variable name... to remove it instantly
echo TemplateUtil::includeTemplate($template); echo $this->includeTemplate($template, '1408138186');
unset($this->vars['1408138186']);
} }
/** /**
@ -64,9 +62,16 @@ class VenomRenderer
*/ */
public function includeTemplate($template, $varName = '') public function includeTemplate($template, $varName = '')
{ {
$data = TemplateUtil::includeTemplate($template); $template .= '.php';
$this->vars[$varName] = $data; if (file_exists($this->templateDir . $template)) {
return $data; ob_start();
include_once $this->templateDir . $template;
$data = ob_get_clean();
$this->vars[$varName] = $data;
return $data;
}
$this->vars[$varName] = '';
return '';
} }
public function addVar($name, $value): void public function addVar($name, $value): void
@ -79,7 +84,7 @@ class VenomRenderer
return $this->vars[$name]; return $this->vars[$name];
} }
public function deleteVar($name): void public function deleteVar($name)
{ {
unset($this->vars[$name]); unset($this->vars[$name]);
} }
@ -87,12 +92,8 @@ class VenomRenderer
public function init(?RenderController $controller): void public function init(?RenderController $controller): void
{ {
$this->controller = $controller; $this->controller = $controller;
if (!Config::getInstance()->isAdmin()) { $data = Config::getInstance()->getRenderer();
$this->metaGenerator = new MetaGenerator(); $this->baseTemplate = $data->baseFile . '.php' ?? 'base.php';
$this->metaGenerator->loadById(); $this->templateDir = __DIR__ . '/../../../tpl/' . $data->theme . '/';
}
$util = TemplateUtil::getInstance();
$this->templateDir = $util->getDir();
$this->baseTemplate = $util->getBase();
} }
} }

0
src/modules/.gitkeep Executable file → Normal file
View file

View file

@ -1,13 +0,0 @@
<?php
namespace Modules\Data\Controller;
class DataController
{
public function get()
{
}
}

View file

@ -1,34 +0,0 @@
<?php
use Modules\Data\Controller\DataController;
use Venom\Core\Module;
use Venom\Routing\Route;
$venom = $venom ?? die();
$venom->registerModule([
Module::ACTIVE => true,
Module::NAME => 'DataModule',
Module::DESC => 'Data Module for Content every',
Module::AUTHOR => 'VstZ dev',
// NEED TO CHECK RIGHTS? :D IF FALSE WRITE IS ALWAYS ALLOWED ALSO READ!
Module::SECURE => true,
Module::ROUTE => [],
Module::ADMIN_ROUTE => [
'/data' => new Route(DataController::class, [
"*" => [
Route::GET => 'get'
]
])
],
Module::TEMPLATE_PATH => __DIR__ . "/tpl/",
Module::TEMPLATES => [
],
Module::ADMIN_TEMPLATES => [
],
Module::CONTROLLER => [
]
]);

View file

@ -1,36 +0,0 @@
<?php
namespace Modules\Meta\Controller;
use Venom\Core\DatabaseHandler;
use Venom\Helper\AdminHelper;
class MetaAPIController
{
public function get()
{
AdminHelper::sendResponse([]);
}
public function getById($id)
{
AdminHelper::sendResponse(SeoUrlController::getById($id));
}
public function update($id)
{
return true;
}
public function delete($id)
{
return true;
}
public function create($id)
{
return true;
}
}

View file

@ -1,18 +0,0 @@
<?php
namespace Modules\Meta\Controller;
class MetaController
{
public static function get(): array
{
return [];
}
public static function getById($id): array
{
return [];
}
}

View file

@ -1,41 +0,0 @@
<?php
use Modules\Meta\Controller\MetaAPIController;
use Venom\Core\Module;
use Venom\Routing\Route;
$venom = $venom ?? die();
$venom->registerModule([
Module::ACTIVE => true,
Module::NAME => 'MetaModule',
Module::DESC => 'Meta Data Module for SEO',
Module::AUTHOR => 'VstZ dev',
// NEED TO CHECK RIGHTS? :D IF FALSE WRITE IS ALWAYS ALLOWED ALSO READ!
Module::SECURE => true,
Module::ROUTE => [],
Module::ADMIN_ROUTE => [
'/metaData' => new Route(MetaAPIController::class, [
"*" => [
Route::GET => 'get'
],
"1" => [
Route::GET => 'getById',
Route::POST => 'update',
Route::PUT => 'insert',
Route::DELETE => 'delete'
]
])
],
Module::TEMPLATE_PATH => __DIR__ . "/tpl/",
Module::TEMPLATES => [
// Include Templates with shorter names! $render->include("meta_roles")
//'meta_roles' => 'PATH_TO_TEMPLATE_FROM_TEMPLATE_PATH'
],
Module::ADMIN_TEMPLATES => [
//
],
Module::CONTROLLER => [
]
]);

View file

@ -1,21 +0,0 @@
<?php
namespace Modules\Role\Controller;
use Venom\Helper\AdminHelper;
class RoleController
{
public function get()
{
AdminHelper::sendResponse([
'roles' => [
['id' => 1, 'name' => 'Admin', 'icon' => 'vt-visibility'],
['id' => 2, 'name' => 'Moderator', 'icon' => 'vt-edit'],
['id' => 3, 'name' => 'Gast', 'icon' => 'vt-edit'],
]
]);
}
}

View file

@ -1,34 +0,0 @@
<?php
use Modules\Role\Controller\RoleController;
use Venom\Core\Module;
use Venom\Routing\Route;
$venom = $venom ?? die();
$venom->registerModule([
Module::ACTIVE => true,
Module::NAME => 'RoleModule',
Module::DESC => 'Role Management',
Module::AUTHOR => 'VstZ dev',
// NEED TO CHECK RIGHTS? :D IF FALSE WRITE IS ALWAYS ALLOWED ALSO READ!
Module::SECURE => true,
Module::ROUTE => [],
Module::ADMIN_ROUTE => [
'/roles' => new Route(RoleController::class, [
"*" => [
Route::GET => 'get'
]
])
],
Module::TEMPLATE_PATH => __DIR__ . "/tpl/",
Module::TEMPLATES => [
],
Module::ADMIN_TEMPLATES => [
],
Module::CONTROLLER => [
]
]);

View file

@ -1,18 +0,0 @@
<?php
namespace Modules\SEO\Controller;
class SeoUrlController
{
public static function get(): array
{
return [];
}
public static function getById($id): array
{
return [];
}
}

View file

@ -1,40 +0,0 @@
<?php
use Modules\SEO\Controller\SeoUrlController;
use Venom\Core\Module;
use Venom\Routing\Route;
$venom = $venom ?? die();
$venom->registerModule([
Module::ACTIVE => true,
Module::NAME => 'SeoModule',
Module::DESC => 'SEO Management for beautiful URLs',
Module::AUTHOR => 'VstZ dev',
// NEED TO CHECK RIGHTS? :D IF FALSE WRITE IS ALWAYS ALLOWED ALSO READ!
Module::SECURE => true,
Module::ROUTE => [],
Module::ADMIN_ROUTE => [
'/seoUrl' => new Route(SeoUrlController::class, [
"*" => [
Route::GET => 'get'
],
"1" => [
Route::GET => 'getById',
Route::POST => 'update',
Route::PUT => 'insert',
Route::DELETE => 'delete'
]
])
],
Module::TEMPLATE_PATH => __DIR__ . "/tpl/",
Module::TEMPLATES => [
],
Module::ADMIN_TEMPLATES => [
],
Module::CONTROLLER => [
]
]);

View file

@ -1,57 +0,0 @@
<?php
namespace Modules\User\Controller;
use Venom\Core\ArgumentHandler;
use Venom\Core\Database\EasyQuery;
use Venom\Core\Database\EntityManager;
use Venom\Entities\User;
use Venom\Helper\AdminHelper;
class UserAPIController
{
public function get()
{
$entityManager = EntityManager::create(User::class);
$easyQuery = new EasyQuery(User::$tableName, ["id", "username", "firstname", "lastname", "email", "isActive"]);
$entityManager->load($easyQuery);
//['id' => 1, 'name' => 'engineertrooper', 'icon' => 'vt-edit'],
AdminHelper::sendResponse(["users" => $entityManager->getAll()]);
}
public function getById($id)
{
$entityManager = EntityManager::create(User::class);
$easyQuery = new EasyQuery(User::$tableName, ["id", "username", "firstname", "lastname", "email", "isActive"]);
$easyQuery->where("id", $id);
$entityManager->load($easyQuery);
AdminHelper::sendResponse($entityManager->getFirst());
}
public function update($id)
{
$entityManager = EntityManager::create(User::class);
$easyQuery = new EasyQuery(User::$tableName, ["id", "username", "firstname", "lastname", "email", "isActive"]);
$easyQuery->where("id", $id);
$entityManager->load($easyQuery);
/** @var User|null $original */
$original = $entityManager->getFirst();
if ($original == null) {
AdminHelper::sendStatus(false, "User not Found");
}
parse_str(file_get_contents('php://input'), $_PUT);
/* var_dump(array_keys($_PUT));*/
AdminHelper::sendStatus($entityManager->saveAll());
}
public function delete($id)
{
}
public function create($id)
{
// INSERT INTO
AdminHelper::sendStatus(true);
}
}

View file

@ -1,42 +0,0 @@
<?php
use Modules\User\Controller\UserAPIController;
use Venom\Core\Module;
use Venom\Routing\Route;
use Venom\Venom;
/** @var Venom $venom */
$venom = $venom ?? die();
$venom->registerModule([
Module::ACTIVE => true,
Module::NAME => 'UserModule',
Module::DESC => 'User Management',
Module::AUTHOR => 'VstZ dev',
// NEED TO CHECK RIGHTS? :D IF FALSE WRITE IS ALWAYS ALLOWED ALSO READ!
Module::SECURE => true,
Module::ROUTE => [],
Module::ADMIN_ROUTE => [
'/users' => new Route(UserAPIController::class, [
"*" => [
Route::GET => 'get'
],
"1" => [
Route::GET => 'getById',
Route::POST => 'update',
Route::PUT => 'update',
Route::DELETE => 'delete'
]
]
)
],
Module::TEMPLATE_PATH => __DIR__ . "/tpl/",
Module::TEMPLATES => [
],
Module::ADMIN_TEMPLATES => [
//
],
Module::CONTROLLER => [
]
]);

View file

@ -1,13 +0,0 @@
<?php
namespace Modules\VenomStatus\Controller;
class VenomStatusController
{
public function get()
{
}
}

View file

@ -1,34 +0,0 @@
<?php
use Modules\VenomStatus\Controller\VenomStatusController;
use Venom\Core\Module;
use Venom\Routing\Route;
$venom = $venom ?? die();
$venom->registerModule([
Module::ACTIVE => true,
Module::NAME => 'VenomStatusModule',
Module::DESC => 'Show Routes and Modules!',
Module::AUTHOR => 'VstZ dev',
// NEED TO CHECK RIGHTS? :D IF FALSE WRITE IS ALWAYS ALLOWED ALSO READ!
Module::SECURE => true,
Module::ROUTE => [],
Module::ADMIN_ROUTE => [
'/venomStatus' => new Route(VenomStatusController::class, [
"*" => [
Route::GET => 'get'
]
])
],
Module::TEMPLATE_PATH => __DIR__ . "/tpl/",
Module::TEMPLATES => [
],
Module::ADMIN_TEMPLATES => [
],
Module::CONTROLLER => [
]
]);

0
tpl/.gitkeep Executable file → Normal file
View file

View file

@ -1,22 +0,0 @@
<main>
<nav class="menu">
<h1 class="logo">Venom</h1>
<div data-link="/metaData">Meta Data</div>
<div data-link="/pages">Pages</div>
<div data-link="/roles">Roles</div>
<div data-link="/seoUrl">SEO-URL</div>
<div data-link="/users">Users</div>
<div data-link="/venomStatus">Venom-Status</div>
<div data-link="/admin/api/login/logout">Ausloggen</div>
</nav>
<div class="app">
<div class="nav-toggle"><span></span></div>
<div class="content-area">
</div>
</div>
<div class="loader hide">
<svg class="spinner" width="65px" height="65px" viewBox="0 0 66 66" xmlns="http://www.w3.org/2000/svg">
<circle class="path" fill="none" stroke-width="6" stroke-linecap="round" cx="33" cy="33" r="30"></circle>
</svg>
</div>
</main>

View file

@ -1,28 +0,0 @@
<?php
use Venom\Views\Asset;
use Venom\Core\Config;
?>
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport"
content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Venom Admin Interface</title>
<?php Asset::get()->renderCSS(); ?>
<!--link rel="stylesheet" href="/theme/admin/css/admin-panel.css"-->
</head>
<body <?=Config::getInstance()->isDevMode() ? 'debug' : ''?>>
<?php
if (!$this->getVar('isLoggedIn')) {
$this->renderTemplate('login');
} else {
$this->renderTemplate('admin-panel');
}
Asset::get()->renderJS();
?>
</body>
</html>

View file

@ -1,4 +0,0 @@
<button class="btn btn--${type} ${classes}">
<span class="btn-ripple"></span>
<span class="btn__content">${content}</span>
</button>

View file

@ -1,9 +0,0 @@
<v-input
class="${classes}"
data-label="${label}"
required
name="${name}"
type="${type}"
data-error="${error}"
class="${class}">${default}
</v-input>

View file

@ -1,8 +0,0 @@
<v-select ${required} name="${name}" class="${classes}">
<v-label empty="${label}"></v-label>
<v-options>
{foreach(object as item)}
<v-option value="${item.value}" ${item.selected}>${item.name}</v-option>
{/for}
</v-options>
</v-select>

View file

@ -1,3 +0,0 @@
<svg role="img" class="icon ${class}">
<use href="/theme/admin/icon-sprite.svg#${icon}" xlink:href="/theme/admin/icon-sprite.svg#${icon}"></use>
</svg>

Before

Width:  |  Height:  |  Size: 155 B

View file

@ -1,5 +0,0 @@
<v-switch data-id="${id}" class="${classes}">
<input type="checkbox" required name="${name}">
<label></label>
<span>${desc}</span>
</v-switch>

View file

@ -1,5 +0,0 @@
<div class="meta-data">
<header>
<h2>Meta Data</h2>
</header>
</div>

View file

@ -1,3 +0,0 @@
<header>
<h2>Overview</h2>
</header>

View file

@ -1,35 +0,0 @@
<div class="page-edit">
<header>
<h2>Page Edit: Turbinen sind geil</h2>
</header>
<div>
<span data-link="/pages" class="icon-text">
{include(includes/svg;class=back-arrow;icon=vt-arrow-back)}
</span>
</div>
<div>
<h3>Page Information</h3>
{include(includes/input;class=input-group;label=Page Name;name=PageName;error=Page Name is required;default=Turbinen sind geil)}
</div>
<div>
{include(includes/select;name=pageVisibility;label=Current Author;object=$users)}
</div>
<div>
<v-select required name="pageVisibility">
<v-label empty="Page Visibility"></v-label>
<v-options>
<v-option value="visible">Visible</v-option>
<v-option value="privat">Privat</v-option>
</v-options>
</v-select>
</div>
<div>
<v-editor name="pageTextArea" rows="25">!</v-editor>
</div>
<div class="btn-line">
{include(includes/btn;type=valid;content=Save)}
{include(includes/btn;type=primary;content=Reset)}
{include(includes/btn;type=warn;content=Delete Page)}
</div>
</div>

View file

@ -1,22 +0,0 @@
<div class="pages-list">
<header>
<h2>Pages</h2>
</header>
<div class="add-new">
<h3>Add new Page</h3>
{include(includes/input;label=New Page Name;name=newPageName;error=New Page Name is required;type=text)}
{include(includes/btn;type=primary;content=Add)}
</div>
<div class="overview">
<h3>All Pages</h3>
{foreach(pages as page,key)}
<div data-link="/pages" data-id="${page.id}">
<span>
{include(includes/svg;icon=$page.icon)}
</span>
<span>${page.name}</span>
</div>
{/for}
</div>
</div>

View file

@ -1,59 +0,0 @@
<div class="role-edit">
<header>
<h2>Role: ${roles.name}</h2>
</header>
<span data-link="/roles" class="icon-back">
{include(includes/svg;class=back-arrow;icon=vt-arrow-back)}
</span>
<div class="spacer">
{include(includes/switch;id=${switch.id};name=permissionEditMetaData;desc=Active)}
{include(includes/input;class=input-group;label=Name;name=roleName;error=Name is required;default=$roles.name;classes=spacer)}
</div>
<v-table class="privileges">
<h3>Privileges</h3>
<v-table-body>
<v-table-header>
<v-cell class="name">Module</v-cell>
<v-cell class="name">Edit</v-cell>
<v-cell class="name">View</v-cell>
</v-table-header>
<v-table-row>
<v-cell class="description">Meta-Data</v-cell>
<v-cell>{include(includes/switch;id=${switch.id};name=permissionEditMetaData)}</v-cell>
<v-cell>{include(includes/switch;id=${switch.id};name=permissionViewMetaData)}</v-cell>
</v-table-row>
<v-table-row>
<v-cell class="description">Pages</v-cell>
<v-cell>{include(includes/switch;id=${switch.id};name=permissionEditPages)}</v-cell>
<v-cell>{include(includes/switch;id=${switch.id};name=permissionViewPages)}</v-cell>
</v-table-row>
<v-table-row>
<v-cell class="description">Roles</v-cell>
<v-cell>{include(includes/switch;id=${switch.id};name=permissionEditRoles)}</v-cell>
<v-cell>{include(includes/switch;id=${switch.id};name=permissionViewRoles)}</v-cell>
</v-table-row>
<v-table-row>
<v-cell class="description">SEO-URL</v-cell>
<v-cell>{include(includes/switch;id=${switch.id};name=permissionEditSeoUrl)}</v-cell>
<v-cell>{include(includes/switch;id=${switch.id};name=permissionViewSeoUrl)}</v-cell>
</v-table-row>
<v-table-row>
<v-cell class="description">Users</v-cell>
<v-cell>{include(includes/switch;id=${switch.id};name=permissionEditUsers)}</v-cell>
<v-cell>{include(includes/switch;id=${switch.id};name=permissionViewUsers)}</v-cell>
</v-table-row>
<v-table-row>
<v-cell class="description">VENOM-Status</v-cell>
<v-cell>{include(includes/switch;id=${switch.id};name=permissionEditVenomStatus)}</v-cell>
<v-cell>{include(includes/switch;id=${switch.id};name=permissionViewVenomStatus)}</v-cell>
</v-table-row>
</v-table-body>
</v-table>
<div class="btn-line">
<div>
{include(includes/btn;type=valid;content=Save)}
{include(includes/btn;type=primary;content=Reset)}
{include(includes/btn;type=warn;content=Delete Role)}
</div>
</div>
</div>

View file

@ -1,23 +0,0 @@
<div class="roles-list">
<header>
<h2>Roles</h2>
</header>
<div class="flexbox">
<div class="overview">
<h3>Overview</h3>
{foreach(roles as role,key)}
<div data-link="/roles" data-id="${role.id}">
<span>
{include(includes/svg;icon=$role.icon)}
</span>
<span>${role.name}</span>
</div>
{/for}
</div>
<div class="add-new">
<h3>Add new Role</h3>
{include(includes/input;label=New Role Name;name=newRoleName;error=New Role Name is required;type=text)}
{include(includes/btn;type=primary;content=Add)}
</div>
</div>
</div>

View file

@ -1,10 +0,0 @@
<div class="seo-url-list">
<header>
<h2>SEO Urls Edit</h2>
</header>
<div>
<span data-link="/seoUrl" class="icon-text">
{include(includes/svg;class=back-arrow;icon=vt-arrow-back)}
</span>
</div>
</div>

View file

@ -1,5 +0,0 @@
<div class="seo-url-list">
<header>
<h2>SEO Urls</h2>
</header>
</div>

View file

@ -1,34 +0,0 @@
<div class="users-edit">
<header>
<h2>User: ${username}</h2>
</header>
<div>
<span data-link="/users" class="icon-text">
{include(includes/svg;class=back-arrow;icon=vt-arrow-back)}
</span>
</div>
<h3>User-Data</h3>
<form id="user-form" data-id="${id}">
<div class="spacer">
{include(includes/input;class=input-group;label=Username;name=username;error=Username is required;default=$username)}
{include(includes/input;class=input-group;label=Firstname;name=firstname;error=Firstname is required;default=$firstname;classes=spacer)}
{include(includes/input;class=input-group;label=Lastname;name=lastname;error=Lastname is required;default=$lastname;classes=spacer)}
{include(includes/input;class=input-group;label=E-Mail;name=newEMailAddress;error=E-Mail Address is required;default=$email;classes=spacer)}
</div>
<div class="btn-line">
{include(includes/btn;type=valid;content=Save)}
{include(includes/btn;type=warn;content=Delete User)}
</div>
</form>
<h3>Change Password</h3>
<form id="password-form" data-id="${id}">
{include(includes/input;class=input-group;label=Password;name=password;type=password;classes=spacer)}
{include(includes/input;class=input-group;label=Password (Repeat);name=passwordRepeat;type=password;classes=spacer)}
<div class="btn-line">
{include(includes/btn;type=valid;content=Save)}
</div>
</form>
</div>

View file

@ -1,23 +0,0 @@
<div class="users-list">
<header>
<h2>Users</h2>
</header>
</div>
<div class="roles-list">
<div class="flexbox">
<div class="overview">
<h3>Overview</h3>
{foreach(users as user)}
<div data-link="/users" data-id="${user.id}">
<span class="icon-text">
{include(includes/svg;icon=vt-edit)}
</span>
<span>${user.username} (${user.firstname} ${user.lastname})</span>
</div>
{/for}
</div>
<div class="add-new">
{include(includes/btn;type=primary;content=Add User)}
</div>
</div>
</div>

View file

@ -1,5 +0,0 @@
<div class="venom-status">
<header>
<h2>Venom Status</h2>
</header>
</div>

View file

@ -1,28 +0,0 @@
<login>
<div id="login-background"></div>
<form id="login" novalidate method="POST" action="/admin/api/login">
<img class="logo" alt="Be Careful" src="/theme/admin/images/logo.svg">
<p class="error-message hide">Login Failed</p>
<input type="hidden" name="REDIRECT_TO" value="NO">
<v-input
class="input-group"
data-label="Username"
required
name="USERNAME"
data-error="Username is required">
</v-input>
<v-input
class="input-group"
data-label="Password"
required
name="PASSWORD"
type="password"
data-error="Password is required">
</v-input>
<button class="btn btn--primary">
<span class="btn-ripple"></span>
<span class="btn__content">Login</span>
</button>
<a href="">Forgotten Password? [not active!]</a>
</form>
</login>

0
tpl/default/base.php Executable file → Normal file
View file