Initial Code commit

This commit is contained in:
nisch.codes 2025-07-23 22:08:42 +02:00
parent 6b95ce5845
commit 5882940435
25 changed files with 375 additions and 164 deletions

View File

@ -22,10 +22,17 @@ namespace Nischcodes\Shiftcalc\App\Controller;
use Nischcodes\Shiftcalc\Attributes\Route; use Nischcodes\Shiftcalc\Attributes\Route;
use Nischcodes\Shiftcalc\MVC\BaseController; use Nischcodes\Shiftcalc\MVC\BaseController;
use Nischcodes\Shiftcalc\App\Model\WorkingHoursEntryModel;
class HomeController extends BaseController { class HomeController extends BaseController {
#[Route('GET', '/')] #[Route('GET', '/')]
public function index() { public function index() {
WorkingHoursEntryModel::load();
$entries = WorkingHoursEntryModel::all();
var_dump($entries);
echo "Homepage"; echo "Homepage";
} }

View File

@ -1,38 +0,0 @@
<?php declare(strict_types=1);
namespace Nischcodes\Shiftcalc\App\Model;
/**
* Date
*
* date model for this application
*
* PHP version 8.4 or higher
*
* LICENSE: GPL-3
*
* @package ShiftCalc
* @author nisch.codes <nischcodes@noreply.projects.nisch.codes>
* @copyright 2021 nisch.codes
* @license https://projects.nisch.codes/nischcodes/shiftcalc/src/branch/main/LICENSE GPL-3
* @version 1.0.0
* @link https://projects.nisch.codes/nischcodes/shiftcalc
*/
use Nischcodes\Shiftcalc\MVC\BaseModel;
class HomeModel extends BaseModel {
// implement the init function
public function init() {
echo "HomeModel init";
}
// implement the load function
public function load() {
$this->repository = [
['date' => '01/01/2025', 'start' => '', 'end' => '', 'sdec' => 0, 'edec' => 0, 'worktime' => 8, 'break' => 0, 'worktime_total' => 8, 'info' => 'Holiday', 'desc' => 'First Example Holiday'],
['date' => '03/05/2025', 'start' => '', 'end' => '', 'sdec' => 0, 'edec' => 0, 'worktime' => 8, 'break' => 0, 'worktime_total' => 8, 'info' => 'Holiday', 'desc' => 'Second Example Holiday']
];
}
}

View File

@ -1,38 +0,0 @@
<?php declare(strict_types=1);
namespace Nischcodes\Shiftcalc\App\Model;
/**
* HomeModel
*
* main model for this application
*
* PHP version 8.4 or higher
*
* LICENSE: GPL-3
*
* @package ShiftCalc
* @author nisch.codes <nischcodes@noreply.projects.nisch.codes>
* @copyright 2021 nisch.codes
* @license https://projects.nisch.codes/nischcodes/shiftcalc/src/branch/main/LICENSE GPL-3
* @version 1.0.0
* @link https://projects.nisch.codes/nischcodes/shiftcalc
*/
use Nischcodes\Shiftcalc\MVC\BaseModel;
class HomeModel extends BaseModel {
// implement the init function
public function init() {
echo "HomeModel init";
}
// implement the load function
public function load() {
$this->repository = [
['date' => '01/01/2025', 'start' => '', 'end' => '', 'sdec' => 0, 'edec' => 0, 'worktime' => 8, 'break' => 0, 'worktime_total' => 8, 'info' => 'Holiday', 'desc' => 'First Example Holiday'],
['date' => '03/05/2025', 'start' => '', 'end' => '', 'sdec' => 0, 'edec' => 0, 'worktime' => 8, 'break' => 0, 'worktime_total' => 8, 'info' => 'Holiday', 'desc' => 'Second Example Holiday']
];
}
}

View File

@ -0,0 +1,51 @@
<?php declare(strict_types=1);
namespace Nischcodes\Shiftcalc\App\Model;
/**
* Date
*
* date model for this application
*
* PHP version 8.4 or higher
*
* LICENSE: GPL-3
*
* @package ShiftCalc
* @author nisch.codes <nischcodes@noreply.projects.nisch.codes>
* @copyright 2021 nisch.codes
* @license https://projects.nisch.codes/nischcodes/shiftcalc/src/branch/main/LICENSE GPL-3
* @version 1.0.0
* @link https://projects.nisch.codes/nischcodes/shiftcalc
*/
use Nischcodes\Shiftcalc\MVC\BaseModel;
class WorkingHoursEntryModel extends BaseModel {
public function __construct(
protected string $date,
protected string $start,
protected string $end,
protected string $type,
protected string $info,
protected float $start_decimal,
protected float $end_decimal,
protected float $worktime_decimal,
protected float $break_decimal,
protected float $worktime_total_decimal
){
parent::__construct();
}
// implement the load function
public static function load() {
static::$repository = [
new self('2025-01-01','','','Holiday', 'First Example Holiday', 0, 0, 0, 0, 0),
new self('2025-05-03','','','Holiday', 'Second Example Holiday', 0, 0, 0, 0, 0),
new self('2025-01-02','','','Vacation', '', 0, 0, 0, 0, 8.00),
new self('2025-07-01','08:41','17:48','Office', '', 8.68, 17.8, 9.12, 0.75, 7.72),
new self('2025-07-15','08:23','16:36','Homeoffice', '', 8.38, 16.6, 8.22, 0.5, 0)
];
}
}

View File

@ -1,11 +1,11 @@
<?php declare(strict_types=1); <?php declare(strict_types=1);
namespace Nischcodes\Shiftcalc\App\View; namespace Nischcodes\Shiftcalc\App\Task;
/** /**
* HomeView * Backup
* *
* main view for this application * cron task to backup all important data for this application
* *
* PHP version 8.4 or higher * PHP version 8.4 or higher
* *
@ -19,13 +19,12 @@ namespace Nischcodes\Shiftcalc\App\View;
* @link https://projects.nisch.codes/nischcodes/shiftcalc * @link https://projects.nisch.codes/nischcodes/shiftcalc
*/ */
use Nischcodes\Shiftcalc\MVC\BaseView; use Nischcodes\Shiftcalc\Task\BaseTask;
class HomeView implements BaseView { class BackupTask implements BaseTask {
// implement the render function public static function run() {
public function render($data) { echo "I am running :)";
echo "HomeView render";
} }
} }

View File

@ -17,6 +17,10 @@
], ],
"require": {}, "require": {},
"scripts": { "scripts": {
"serve": "php -S 127.0.0.1:8000 -t public" "setup": "php public/index.php run:setup",
"serve-dev": "podman-compose up -d --build --build-arg INSTALL_XDEBUG=true",
"stop-serve-dev": "podman-compose down",
"serve": "docker-compose up -d --build",
"stop-serve": "docker-compose down"
} }
} }

0
data/database/.gitkeep Normal file
View File

0
data/logging/.gitkeep Normal file
View File

55
docker-compose.yml Normal file
View File

@ -0,0 +1,55 @@
version: "3.8"
services:
php:
build:
context: .
dockerfile: docker/php/Dockerfile
args:
INSTALL_XDEBUG: "false"
container_name: app-php
working_dir: /var/www/html
volumes:
- ./:/var/www/html:Z
extra_hosts:
- "host.docker.internal:host-gateway"
entrypoint: >
sh -c "
if [ ! -d vendor ]; then
composer install --no-dev --optimize-autoloader;
php scripts/setup.php;
fi;
php-fpm
"
networks:
- appnet
web:
image: docker.io/library/httpd:2.4
container_name: app-web
depends_on: [php]
ports:
- "8080:80"
volumes:
- ./public:/usr/local/apache2/htdocs:Z
- ./docker/apache/vhost.conf:/usr/local/apache2/conf/extra/vhost.conf:ro,Z
command: >
sh -c "
# ───────── Module laden ─────────
echo 'LoadModule rewrite_module modules/mod_rewrite.so' \
>> /usr/local/apache2/conf/httpd.conf;
echo 'LoadModule proxy_module modules/mod_proxy.so' \
>> /usr/local/apache2/conf/httpd.conf;
echo 'LoadModule proxy_fcgi_module modules/mod_proxy_fcgi.so' \
>> /usr/local/apache2/conf/httpd.conf;
# ───────── VHost aktivieren ─────────
echo 'Include conf/extra/vhost.conf' \
>> /usr/local/apache2/conf/httpd.conf;
httpd-foreground
"
networks:
- appnet
networks:
appnet:
driver: bridge

21
docker/apache/vhost.conf Normal file
View File

@ -0,0 +1,21 @@
<VirtualHost *:80>
ServerName localhost
DocumentRoot /usr/local/apache2/htdocs
<Directory /usr/local/apache2/htdocs>
Options Indexes FollowSymLinks
AllowOverride All
Require all granted
</Directory>
DirectoryIndex index.php index.html
#<FilesMatch \.php$>
# SetHandler "proxy:fcgi://php:9000/var/www/html/public"
#</FilesMatch>
ProxyPassMatch "^/(.*\.php(/.*)?)$" "fcgi://php:9000/var/www/html/public/$1"
ErrorLog /usr/local/apache2/logs/error.log
CustomLog /usr/local/apache2/logs/access.log combined
</VirtualHost>

24
docker/php/Dockerfile Normal file
View File

@ -0,0 +1,24 @@
FROM php:8.4-fpm
# Build-Arg default: kein Xdebug
ARG INSTALL_XDEBUG=false
# System-Tools für pecl
RUN apt-get update \
&& DEBIAN_FRONTEND=noninteractive apt-get install -y --no-install-recommends \
git unzip \
&& rm -rf /var/lib/apt/lists/*
# Conditionally install Xdebug
RUN if [ "$INSTALL_XDEBUG" = "true" ]; then \
pecl install xdebug \
&& docker-php-ext-enable xdebug \
&& { \
echo "zend_extension=xdebug.so"; \
echo "xdebug.mode=develop,trace"; \
echo "xdebug.start_with_request=yes"; \
echo "xdebug.client_host=host.docker.internal"; \
echo "xdebug.client_port=9003"; \
echo "xdebug.log=/tmp/xdebug.log"; \
} > /usr/local/etc/php/conf.d/xdebug.ini ; \
fi

20
public/cron.php Normal file
View File

@ -0,0 +1,20 @@
<?php declare(strict_types=1);
// require the vendor autoload file
require '../vendor/autoload.php';
// define working context to prevent data breaching
define("SHIFTCALC", 1);
// import the task runner class
use Nischcodes\Shiftcalc\TaskRunner;
//ini_set('display_errors', '1');
//ini_set('display_startup_errors', '1');
//error_reporting(E_ALL);
// initilize the TaskRunner
TaskRunner::init();
// run the TaskRunner
TaskRunner::run();

View File

@ -2,14 +2,14 @@
tr.current { background-color: #008080; } </style></head><body><?php tr.current { background-color: #008080; } </style></head><body><?php
// require the vendor autoload file // require the vendor autoload file
require '../vendor/autoload.php'; require dirname(__FILE__) . '/../vendor/autoload.php';
// define working context to prevent data breaching // define working context to prevent data breaching
define("SHIFTCALC", 1); define("SHIFTCALC", 1);
// use the application namespace // use the application namespace
use Nischcodes\Shiftcalc\Application; use Nischcodes\Shiftcalc\Application;
use Nischcodes\Shiftcalc\HTTP; use Nischcodes\Shiftcalc\Utilities\HTTP;
//ini_set('display_errors', '1'); //ini_set('display_errors', '1');
//ini_set('display_startup_errors', '1'); //ini_set('display_startup_errors', '1');
@ -126,7 +126,7 @@
return strcmp($a['date'], $b['date']); return strcmp($a['date'], $b['date']);
}); });
// print_r($dates); //var_dump($dates);
$groupedDates = []; $groupedDates = [];

View File

@ -19,78 +19,71 @@ namespace Nischcodes\Shiftcalc;
* @link https://projects.nisch.codes/nischcodes/shiftcalc * @link https://projects.nisch.codes/nischcodes/shiftcalc
*/ */
use Nischcodes\Shiftcalc\DotEnv; use Nischcodes\Shiftcalc\Utilities\DotEnv;
use Nischcodes\Shiftcalc\Router; use Nischcodes\Shiftcalc\Routing\Router;
use Nischcodes\Shiftcalc\Request; use Nischcodes\Shiftcalc\Routing\Request;
class Application { class Application {
static $router; protected static Router $router;
protected static string $projectRoot;
static $basenamespace = "Nischcodes\\Shiftcalc\\App\\"; protected static bool $isContextCli;
static $controllernamespace = "Nischcodes\\Shiftcalc\\App\\Controller\\";
static function init() { protected static string $basenamespace = "Nischcodes\\Shiftcalc\\App\\";
protected static string $controllernamespace = "Nischcodes\\Shiftcalc\\App\\Controller\\";
public static function init() {
// check if the current context is CLI or web
static::$isContextCli = (PHP_SAPI === 'cli');
// get the current root directory // get the current root directory
$projectRoot = self::getProjectRoot(); static::$projectRoot = static::getProjectRoot();
// load the config file from the config folder // load the config file from the config folder
require_once $projectRoot . '/config/config.php'; require_once static::$projectRoot . '/config/config.php';
// load the env file if the config file constant says so // load the env file if the config file constant says so
if(SC_LOADDOTENV) { if(SC_LOADDOTENV) {
// load .env file // load .env file
DotEnv::load("$projectRoot/.env"); DotEnv::load(static::$projectRoot."/.env");
} }
// initilise the router object // check if the application is running on the cli or not
self::$router = new Router(); if (static::$isContextCli) {
// get all controller from the application directory // init the console part by loading the commands
$appControllers = glob("$projectRoot/app/Controller/*.php"); static::initConsole();
} else {
// iterate over all application controller and register the routes with model // init the website part by loading the controllers
foreach($appControllers as $appController) { static::initWeb();
// extract the class name
$controllerClassName = basename($appController, '.php');
// construct the namespaces
$controllerFQN = self::$controllernamespace.$controllerClassName;
$modelFQN = str_replace("Controller", "Model", $controllerFQN);
$viewFQN = str_replace("Controller", "View", $controllerFQN);
// check if classes exists
$controllerClass = (class_exists($controllerFQN) ? $controllerFQN : false);
$modelClass = (class_exists($modelFQN) ? $modelFQN : '');
$viewClass = (class_exists($viewFQN) ? $viewFQN : '');
// check if the current classname is loaded
if($controllerClass) {
// register controller for routing with model
self::$router->registerRoutesFromController(
$controllerClass,
$modelClass,
$viewClass
);
}
} }
}
static function run() {
// call the route for the requested path
self::$router->dispatch(
Request::uri(),
Request::method(),
Request::parameters()
);
} }
public static function run() {
static function getProjectRoot(?string $startDir = null): string { // check if the application is running on the cli or not
if (static::$isContextCli) {
// run the console part
static::runConsole();
} else {
// run the website part
static::runWeb();
}
}
public static function getProjectRoot(?string $startDir = null): string {
$dir = realpath($startDir ?? __DIR__); $dir = realpath($startDir ?? __DIR__);
while ($dir) { while ($dir) {
@ -108,4 +101,55 @@ class Application {
throw new \RuntimeException('Project root folder not found.'); throw new \RuntimeException('Project root folder not found.');
} }
private static function initConsole() {
}
private static function initWeb() {
// initilise the router object
self::$router = new Router();
// get all controller from the application directory
$appControllers = glob(static::$projectRoot."/app/Controller/*.php");
// iterate over all application controller and register the routes with model
foreach($appControllers as $appController) {
// extract the class name
$controllerClassName = basename($appController, '.php');
// construct the namespaces
$controllerFQN = self::$controllernamespace.$controllerClassName;
// check if classes exists
$controllerClass = (class_exists($controllerFQN) ? $controllerFQN : false);
// check if the current classname is loaded
if($controllerClass) {
// register controller for routing
self::$router->registerRoutesFromController(
$controllerClass
);
}
}
}
private static function runConsole() {
}
private static function runWeb() {
// call the route for the requested path
self::$router->dispatch(
Request::uri(),
Request::method(),
Request::parameters()
);
}
} }

View File

@ -18,13 +18,9 @@ namespace Nischcodes\Shiftcalc\MVC;
*/ */
abstract class BaseController { abstract class BaseController {
public function __construct(
protected BaseModel $model,
protected BaseView $view
) {
// initilise the model protected function view(string $template, array $data = []): BaseView {
$model->init(); return new BaseView($template, $data);
} }
} }

View File

@ -19,18 +19,23 @@ namespace Nischcodes\Shiftcalc\MVC;
abstract class BaseModel { abstract class BaseModel {
protected $repository = []; protected static $repository = [];
abstract public static function load();
abstract public function init();
abstract public function load();
// implement the getAll function // implement the all function
public function getAll() { public static function all() {
return $this->repository; return static::$repository;
} }
// implement the get function // implement the find function
public function get($index){ public static function find($index){
return $this->repository[$index]; return static::$repository[$index];
} }
/*
public static function find(int|string $id): ?self
{
return static::query()->where('id', $id)->first();
}
*/
} }

View File

@ -19,6 +19,15 @@ namespace Nischcodes\Shiftcalc\MVC;
abstract class BaseView { abstract class BaseView {
abstract public function render($data); public function __construct(
private string $template,
private array $data = []
) {}
public function render(): void {
// create array entries with data property as key
extract($this->data, EXTR_SKIP);
//TODO: load template from dist and compile template to code
}
} }

View File

View File

@ -1,6 +1,6 @@
<?php declare(strict_types=1); <?php declare(strict_types=1);
namespace Nischcodes\Shiftcalc; namespace Nischcodes\Shiftcalc\Routing;
/** /**
* Request interface * Request interface

View File

@ -1,6 +1,6 @@
<?php declare(strict_types=1); <?php declare(strict_types=1);
namespace Nischcodes\Shiftcalc; namespace Nischcodes\Shiftcalc\Routing;
/** /**
* Router interface * Router interface
@ -31,10 +31,8 @@ class Router {
var_dump($parameter); var_dump($parameter);
} }
public function registerRoutesFromController(string $controller, string $model = '', string $view = '') { public function registerRoutesFromController(string $controller) {
var_dump($controller); var_dump($controller);
var_dump($model);
var_dump($view);
} }
} }

24
src/Task/BaseTask.php Normal file
View File

@ -0,0 +1,24 @@
<?php declare(strict_types=1);
namespace Nischcodes\Shiftcalc\Task;
/**
* Base Task
*
* PHP version 8.4 or higher
*
* LICENSE: GPL-3
*
* @package ShiftCalc
* @author nisch.codes <nischcodes@noreply.projects.nisch.codes>
* @copyright 2021 nisch.codes
* @license https://projects.nisch.codes/nischcodes/shiftcalc/src/branch/main/LICENSE GPL-3
* @version 1.0.0
* @link https://projects.nisch.codes/nischcodes/shiftcalc
*/
abstract class BaseTask {
abstract public static function run();
}

30
src/TaskRunner.php Normal file
View File

@ -0,0 +1,30 @@
<?php declare(strict_types=1);
namespace Nischcodes\Shiftcalc;
/**
* TaskRunner
*
* Runs Tasks
*
* PHP version 8.4 or higher
*
* LICENSE: GPL-3
*
* @package ShiftCalc
* @author nisch.codes <nischcodes@noreply.projects.nisch.codes>
* @copyright 2021 nisch.codes
* @license https://projects.nisch.codes/nischcodes/shiftcalc/src/branch/main/LICENSE GPL-3
* @version 1.0.0
* @link https://projects.nisch.codes/nischcodes/shiftcalc
*/
use Nischcodes\Shiftcalc\Utilities\DotEnv;
class TaskRunner {
static function init() {}
static function run() {}
}

View File

@ -1,6 +1,6 @@
<?php declare(strict_types=1); <?php declare(strict_types=1);
namespace Nischcodes\Shiftcalc; namespace Nischcodes\Shiftcalc\Utilities;
/** /**
* Simple DotEnv parser * Simple DotEnv parser
@ -25,7 +25,7 @@ class DotEnv {
// check if given path contains a valid file // check if given path contains a valid file
if (!file_exists($path)) { if (!file_exists($path)) {
throw new Exception("No valid file: $path"); throw new \Exception("No valid file: $path");
return; return;
} }

View File

@ -1,6 +1,6 @@
<?php declare(strict_types=1); <?php declare(strict_types=1);
namespace Nischcodes\Shiftcalc; namespace Nischcodes\Shiftcalc\Utilities;
/** /**
* HTTP interface * HTTP interface