basic website, basic templating

This commit is contained in:
tracer 2022-10-21 14:31:48 +02:00
parent 303fc11327
commit fdd24d90da
11 changed files with 196 additions and 0 deletions

View File

@ -0,0 +1,29 @@
body {
background: #1f1f1f;
color: #cdcdcd;
}
/* unvisited link */
a:link {
color: #ff8844;
text-decoration: none;
}
/* visited link */
a:visited {
color: #ff8844;
text-decoration: none;
}
/* mouse over link */
a:hover {
color: #ff8844;
text-decoration: none;
}
/* selected link */
a:active {
color: #ff8844;
text-decoration: none;
font-weight: bold;
}

13
public/index.php Normal file
View File

@ -0,0 +1,13 @@
<?php
ini_set(option: 'display_errors', value: 1);
ini_set(option: 'display_startup_errors', value: 1);
error_reporting(error_level: E_ALL);
require dirname(path: __DIR__) . '/src/bootstrap.php';
use App\Controller\AddressBook;
$container = new \App\Service\Container();
$addressBook = $container->get(AddressBook::class);
//$addressBook = new AddressBook();

View File

@ -0,0 +1,14 @@
<?php
namespace App\Controller;
use App\Service\Template;
use stdClass;
class AddressBook extends stdClass
{
public function __construct(Template $template)
{
$template->render(templateName: 'index.tpl');
}
}

View File

@ -0,0 +1,16 @@
<?php
namespace App\Entity;
class AddressBookEntry
{
public function __construct(
private int $userid,
private string $first,
private string $last,
private string $nick,
)
{
// empty body
}
}

17
src/Entity/User.php Normal file
View File

@ -0,0 +1,17 @@
<?php
namespace App\Entity;
class User
{
public function __construct(
private string $nick,
private string $password,
private string $first = '',
private string $last = '',
private int $id = 0
)
{
// empty body
}
}

33
src/Service/Container.php Normal file
View File

@ -0,0 +1,33 @@
<?php
namespace App\Service;
use App\Controller\AddressBook;
use Exception;
use stdClass;
class Container
{
// no autowiring yet, maybe later, but it might fit for a demo
private Template $template;
private AddressBook $addressBook;
public function __construct()
{
$this->template = new Template(templateDir: dirname(path: __DIR__, levels: 2) . '/templates/');
$this->addressBook = new AddressBook(template: $this->template);
}
/**
* @throws Exception
*/
public function get(string $class): stdClass
{
return match($class) {
'App\Controller\AddressBook' => $this->addressBook,
default => throw new Exception(message: "Missing class definition: $class")
};
}
}

40
src/Service/Template.php Normal file
View File

@ -0,0 +1,40 @@
<?php
namespace App\Service;
use Exception;
class Template
{
public function __construct(private readonly string $templateDir)
{
// empty body
}
/**
* @throws Exception
*/
public function render(string $templateName): void
{
$template = file_get_contents(filename: $this->templateDir . $templateName);
// search for includes
preg_match_all(pattern: '/{% include ?\'?(.*?)\'? ?%}/i', subject: $template, matches: $matches, flags: PREG_SET_ORDER);
foreach ($matches as $value) {
$token = $value[0];
$include = $this->templateDir . $value[1];
if (file_exists(filename: $include)) {
$replacement = file_get_contents(filename: $include);
} else {
throw new Exception(message: "Missing included file: $include");
}
$template = str_replace(search: $token, replace: $replacement, subject: $template);
}
// remove the original template code
$template = preg_replace(pattern: '/{% include ?\'?(.*?)\'? ?%}/i', replacement: '', subject: $template);
echo $template;
}
}

18
src/bootstrap.php Normal file
View File

@ -0,0 +1,18 @@
<?php
spl_autoload_register(callback: function($className) {
$prefix = 'App';
$baseDir = __DIR__;
$len = strlen(string: $prefix);
if (strncmp(string1: $prefix, string2: $className, length: $len) !== 0) {
return;
}
$realClassName = substr(string: $className, offset: $len);
$classLocation = $baseDir . str_replace(search: '\\', replace: '/', subject: $realClassName) . '.php';
if (file_exists(filename: $classLocation)) {
require $classLocation;
} else {
die("Invalid class: $className");
}
});

3
templates/_footer.tpl Normal file
View File

@ -0,0 +1,3 @@
<!-- mind the javascript -->
</body>
</html>

5
templates/_header.tpl Normal file
View File

@ -0,0 +1,5 @@
<html>
<head>
<title>Address Book</title>
<link rel="stylesheet" href="/assets/styles/main.css">
</head>

8
templates/index.tpl Normal file
View File

@ -0,0 +1,8 @@
{% include '_header.tpl' %}
<h1>Address Book</h1>
<a href="/">🏠 Home</a>
<a href="/">⚙ Admin</a>
<a href="/">🚪 Login</a>
{% include '_footer.tpl' %}