diff --git a/composer.json b/composer.json
index 13b498d..417daa6 100644
--- a/composer.json
+++ b/composer.json
@@ -19,7 +19,6 @@
"php": "8.2.*",
"ext-json": "*",
"vertexvaar/bluesprints": "@dev",
- "vertexvaar/bluefluid": "@dev",
"psr/container": "^2.0",
"vertexvaar/bluecontainer": "@dev",
"vertexvaar/blueauth": "@dev",
@@ -40,7 +39,9 @@
"config": {
"allow-plugins": {
"vertexvaar/bluecontainer": true
- },
+ }
+ },
+ "extra": {
"vertexvaar/bluesprints": {
"logs": "var/logs",
"locks": "var/locks",
diff --git a/packages/blueauth/composer.json b/packages/blueauth/composer.json
index 9836a41..1f0020d 100644
--- a/packages/blueauth/composer.json
+++ b/packages/blueauth/composer.json
@@ -19,5 +19,10 @@
"require": {
"php": "8.2.*",
"vertexvaar/bluesprints": "*"
+ },
+ "extra": {
+ "vertexvaar/bluesprints": {
+ "view": "view"
+ }
}
}
diff --git a/packages/blueauth/src/Controller/AuthenticationController.php b/packages/blueauth/src/Controller/AuthenticationController.php
index 93ff696..0782ca8 100644
--- a/packages/blueauth/src/Controller/AuthenticationController.php
+++ b/packages/blueauth/src/Controller/AuthenticationController.php
@@ -4,13 +4,14 @@
namespace VerteXVaaR\BlueAuth\Controller;
+use Psr\Http\Message\ResponseInterface;
use Psr\Http\Message\ServerRequestInterface;
use RuntimeException;
+use Twig\Environment;
use VerteXVaaR\BlueSprints\Environment\Config;
use VerteXVaaR\BlueSprints\Environment\Paths;
use VerteXVaaR\BlueSprints\Mvc\AbstractController;
use VerteXVaaR\BlueSprints\Mvc\Repository;
-use VerteXVaaR\BlueSprints\Mvc\TemplateRenderer;
use VerteXVaaR\BlueSprints\Utility\Strings;
use function array_key_exists;
@@ -18,6 +19,7 @@
use function file_exists;
use function file_put_contents;
use function getenv;
+use function is_dir;
use function json_encode;
use function mkdir;
use function setcookie;
@@ -27,18 +29,19 @@ class AuthenticationController extends AbstractController
{
public function __construct(
Repository $repository,
- TemplateRenderer $templateRenderer,
- private readonly Paths $paths,
- private readonly Config $config,
+ Environment $view,
+ private Paths $paths,
+ private Config $config
) {
- parent::__construct($repository, $templateRenderer);
+ parent::__construct($repository, $view);
}
- public function login(ServerRequestInterface $request): void
+ public function login(ServerRequestInterface $request): ResponseInterface
{
+ return $this->render('@vertexvaar_blueauth/login.html.twig');
}
- public function logout(ServerRequestInterface $request): void
+ public function logout(ServerRequestInterface $request): ResponseInterface
{
$sessionIdentifier = $request->getAttribute('session');
if ($sessionIdentifier) {
@@ -48,12 +51,11 @@ public function logout(ServerRequestInterface $request): void
}
setcookie($this->config->cookieAuthName ?: 'bluesprints_auth', '', -1, '/');
}
- $this->redirect('/');
+ return $this->redirect('/');
}
- public function authenticate(ServerRequestInterface $request): void
+ public function authenticate(ServerRequestInterface $request): ResponseInterface
{
- $this->renderTemplate = false;
$body = $request->getParsedBody();
if (array_key_exists('username', $body) && array_key_exists('password', $body)) {
$username = $body['username'];
@@ -66,14 +68,14 @@ public function authenticate(ServerRequestInterface $request): void
'username' => $username,
'authenticated' => true,
];
- if (!mkdir($path, $this->config->folderPermissions, true) && !is_dir($path)) {
+ if (!is_dir($path) && !mkdir($path, $this->config->folderPermissions, true) && !is_dir($path)) {
throw new RuntimeException(sprintf('Directory "%s" was not created', $path));
}
file_put_contents(concat_paths($path, $sessionIdentifier), json_encode($session));
setcookie($this->config->cookieAuthName ?: 'bluesprints_auth', $sessionIdentifier);
- $this->redirect('/');
+ return $this->redirect('/');
}
}
- $this->redirect('/login');
+ return $this->redirect('/login');
}
}
diff --git a/packages/blueauth/view/login.html.twig b/packages/blueauth/view/login.html.twig
new file mode 100644
index 0000000..c117d97
--- /dev/null
+++ b/packages/blueauth/view/login.html.twig
@@ -0,0 +1,22 @@
+
diff --git a/packages/bluecontainer/src/Composer/Plugin.php b/packages/bluecontainer/src/Composer/Plugin.php
index 6364536..da66397 100644
--- a/packages/bluecontainer/src/Composer/Plugin.php
+++ b/packages/bluecontainer/src/Composer/Plugin.php
@@ -17,8 +17,11 @@
use VerteXVaaR\BlueContainer\DI;
use VerteXVaaR\BlueContainer\Helper\PackageIterator;
+use function dirname;
use function file_exists;
+use function getenv;
use function is_dir;
+use function putenv;
class Plugin implements PluginInterface, EventSubscriberInterface
{
@@ -57,6 +60,10 @@ public function postAutoloadDump(): void
{
$this->io->write('Generating container');
+ if (!getenv('VXVR_BS_ROOT')) {
+ putenv('VXVR_BS_ROOT=' . dirname(__DIR__, 4));
+ }
+
$installationManager = $this->composer->getInstallationManager();
$config = $this->composer->getConfig();
$autoloadFile = $config->get('vendor-dir') . '/autoload.php';
@@ -101,7 +108,7 @@ function (Package $package, string $installPath) use ($containerBuilder): void {
);
- $packageConfig = $this->composer->getPackage()->getConfig();
+ $packageConfig = $this->composer->getPackage()->getExtra();
$configPath = $packageConfig['vertexvaar/bluesprints']['config'] ?? 'config';
if (file_exists($configPath . '/services.yaml')) {
diff --git a/packages/bluedebug/composer.json b/packages/bluedebug/composer.json
index 1272a75..202e421 100644
--- a/packages/bluedebug/composer.json
+++ b/packages/bluedebug/composer.json
@@ -19,5 +19,10 @@
"require": {
"php": "8.2.*",
"vertexvaar/bluesprints": "*"
+ },
+ "extra": {
+ "vertexvaar/bluesprints": {
+ "view": "view"
+ }
}
}
diff --git a/packages/bluedebug/src/Middleware/DebugToolbarMiddleware.php b/packages/bluedebug/src/Middleware/DebugToolbarMiddleware.php
index 8d5191a..64b616f 100644
--- a/packages/bluedebug/src/Middleware/DebugToolbarMiddleware.php
+++ b/packages/bluedebug/src/Middleware/DebugToolbarMiddleware.php
@@ -8,12 +8,12 @@
use Psr\Http\Message\ServerRequestInterface;
use Psr\Http\Server\MiddlewareInterface;
use Psr\Http\Server\RequestHandlerInterface;
-use VerteXVaaR\BlueSprints\Mvc\TemplateRenderer;
+use Twig\Environment;
readonly class DebugToolbarMiddleware implements MiddlewareInterface
{
- public function __construct(private TemplateRenderer $templateRenderer)
+ public function __construct(private Environment $view)
{
}
@@ -21,12 +21,11 @@ public function process(ServerRequestInterface $request, RequestHandlerInterface
{
$response = $handler->handle($request);
- $this->templateRenderer->setRouteConfiguration(['controller' => 'DebugToolbarMiddleware']);
-
- $this->templateRenderer->setVariable('route', $request->getAttribute('route'));
- $this->templateRenderer->setVariable('authenticated', $request->getAttribute('authenticated'));
- $this->templateRenderer->setVariable('username', $request->getAttribute('username'));
- $contents = $this->templateRenderer->render('DebugToolbar');
+ $contents = $this->view->render('@vertexvaar_bluedebug/debug_toolbar.html.twig', [
+ 'route' => $request->getAttribute('route'),
+ 'authenticated' => $request->getAttribute('authenticated'),
+ 'username' => $request->getAttribute('username'),
+ ]);
$body = $response->getBody();
$body->seek($body->getSize());
diff --git a/packages/bluedebug/view/debug_toolbar.html.twig b/packages/bluedebug/view/debug_toolbar.html.twig
new file mode 100644
index 0000000..6001d55
--- /dev/null
+++ b/packages/bluedebug/view/debug_toolbar.html.twig
@@ -0,0 +1,8 @@
+
+
Route: {{ route.controller }}::{{ route.action }}
+ {% if authenticated %}
+
User (authenticated): {{ username }}
+ {% else %}
+
User (anonymous session)
+ {% endif %}
+
diff --git a/packages/bluefluid/.editorconfig b/packages/bluefluid/.editorconfig
deleted file mode 100644
index aee148b..0000000
--- a/packages/bluefluid/.editorconfig
+++ /dev/null
@@ -1,23 +0,0 @@
-root = true
-
-[*]
-end_of_line = lf
-insert_final_newline = true
-charset = utf-8
-trim_trailing_whitespace = true
-
-[*.html]
-indent_style = tab
-indent_size = 4
-
-[*.php]
-indent_style = space
-indent_size = 4
-
-[*.md]
-indent_style = space
-indent_size = 4
-
-[*.json]
-indent_style = tab
-indent_size = 4
diff --git a/packages/bluefluid/composer.json b/packages/bluefluid/composer.json
deleted file mode 100644
index e53fc90..0000000
--- a/packages/bluefluid/composer.json
+++ /dev/null
@@ -1,24 +0,0 @@
-{
- "name": "vertexvaar/bluefluid",
- "description": "BlueFluids provides an adapter for the TYPO3 templating engine Fluid",
- "type": "project",
- "license": "GPL-3.0+",
- "authors": [
- {
- "name": "Oliver Eglseder",
- "email": "bluesprints@vxvr.de",
- "homepage": "http://vxvr.de/",
- "role": "Developer"
- }
- ],
- "autoload": {
- "psr-4": {
- "VerteXVaaR\\BlueFluid\\": "src/"
- }
- },
- "require": {
- "php": "8.2.*",
- "typo3fluid/fluid": "^2.2",
- "vertexvaar/bluesprints": "@dev"
- }
-}
diff --git a/packages/bluefluid/config/services.yaml b/packages/bluefluid/config/services.yaml
deleted file mode 100644
index 75b2c2f..0000000
--- a/packages/bluefluid/config/services.yaml
+++ /dev/null
@@ -1,9 +0,0 @@
-services:
- _defaults:
- autowire: true
- autoconfigure: true
-
- VerteXVaaR\BlueFluid\:
- resource: '../src/*'
-
- VerteXVaaR\BlueSprints\Mvc\TemplateRenderer: '@VerteXVaaR\BlueFluid\Mvc\FluidTemplateRenderer'
diff --git a/packages/bluefluid/src/Mvc/FluidTemplateRenderer.php b/packages/bluefluid/src/Mvc/FluidTemplateRenderer.php
deleted file mode 100644
index f650729..0000000
--- a/packages/bluefluid/src/Mvc/FluidTemplateRenderer.php
+++ /dev/null
@@ -1,65 +0,0 @@
-view = new TemplateView();
- }
-
- public function render(string $templateName = ''): string
- {
- $controller = str_replace('\\', '/', $this->routeConfiguration['controller']);
- $viewRootPath = concat_paths(getenv('VXVR_BS_ROOT'), $this->paths->view);
-
- $this->view->getTemplatePaths()->setTemplateRootPaths(
- [concat_paths($viewRootPath, 'Template', $controller, DIRECTORY_SEPARATOR)]
- );
- $this->view->getTemplatePaths()->setLayoutRootPaths(
- [concat_paths($viewRootPath, 'Layout', $controller, DIRECTORY_SEPARATOR)]
- );
- $this->view->getTemplatePaths()->setPartialRootPaths(
- [concat_paths($viewRootPath, 'Partial', $controller, DIRECTORY_SEPARATOR)]
- );
- if (str_contains($controller, '/')) {
- $this->view->getRenderingContext()->setControllerName(substr($controller, strrpos($controller, '/') + 1));
- } else {
- $this->view->getRenderingContext()->setControllerName($controller);
- }
-
- if (empty($templateName)) {
- $templateName = $this->routeConfiguration['action'];
- }
- return $this->view->render($templateName);
- }
-
- public function setVariable(string $key, $value = null): void
- {
- $this->view->assign($key, $value);
- }
-
- public function setRouteConfiguration(array $routeConfiguration): void
- {
- $this->routeConfiguration = $routeConfiguration;
- }
-}
diff --git a/packages/bluesprints/composer.json b/packages/bluesprints/composer.json
index 8ccd5bf..9b85b85 100644
--- a/packages/bluesprints/composer.json
+++ b/packages/bluesprints/composer.json
@@ -23,7 +23,8 @@
"psr/container": "^2.0",
"guzzlehttp/psr7": "^2.6",
"co-stack/lib": "^v5.0.0",
- "symfony/dotenv": "^v6.3.0"
+ "symfony/dotenv": "^v6.3.0",
+ "twig/twig": "^v3.7.1"
},
"bin": [
"bin/bluesprints"
diff --git a/packages/bluesprints/config/services.php b/packages/bluesprints/config/services.php
index 09d69ae..16ce7dd 100644
--- a/packages/bluesprints/config/services.php
+++ b/packages/bluesprints/config/services.php
@@ -8,6 +8,7 @@
use VerteXVaaR\BlueSprints\Mvc\Controller;
use VerteXVaaR\BlueSprints\Mvc\DependencyInjection\PublicServicePass;
use VerteXVaaR\BlueSprints\Routing\DependencyInjection\RouteCollectorCompilerPass;
+use VerteXVaaR\BlueSprints\Template\DependencyInjection\TemplateRendererCompilerPass;
return static function (ContainerBuilder $container): void {
$container->addCompilerPass(new EnvironmentCompilerPass());
@@ -15,6 +16,7 @@
$container->addCompilerPass(new ConfigCompilerPass());
$container->addCompilerPass(new MiddlewareCompilerPass());
$container->addCompilerPass(new RouteCollectorCompilerPass());
+ $container->addCompilerPass(new TemplateRendererCompilerPass());
$container->registerForAutoconfiguration(Controller::class)
->addTag('vertexvaar.bluesprints.controller');
diff --git a/packages/bluesprints/config/services.yaml b/packages/bluesprints/config/services.yaml
index 38fcfe4..e7d2431 100644
--- a/packages/bluesprints/config/services.yaml
+++ b/packages/bluesprints/config/services.yaml
@@ -27,6 +27,12 @@ services:
public: true
shared: true
+ VerteXVaaR\BlueSprints\Template\TwigFactory:
+ public: true
+
+ Twig\Environment:
+ factory: ['@VerteXVaaR\BlueSprints\Template\TwigFactory', 'create']
+
Psr\Http\Server\RequestHandlerInterface: '@VerteXVaaR\BlueSprints\Http\Server\RequestHandler\ControllerDispatcher'
VerteXVaaR\BlueSprints\Mvc\TemplateRenderer: '@VerteXVaaR\BlueSprints\Mvc\PhpTemplateRenderer'
diff --git a/packages/bluesprints/src/Environment/DependencyInjection/ConfigCompilerPass.php b/packages/bluesprints/src/Environment/DependencyInjection/ConfigCompilerPass.php
index b7ffb11..d523f70 100644
--- a/packages/bluesprints/src/Environment/DependencyInjection/ConfigCompilerPass.php
+++ b/packages/bluesprints/src/Environment/DependencyInjection/ConfigCompilerPass.php
@@ -15,7 +15,7 @@ public function process(ContainerBuilder $container)
{
/** @var Composer $composer */
$composer = $container->get('composer');
- $packageConfig = $composer->getPackage()->getConfig();
+ $packageConfig = $composer->getPackage()->getExtra();
$config = $packageConfig['vertexvaar/bluesprints'];
$permissions = $config['permissions'] ?? [];
diff --git a/packages/bluesprints/src/Environment/DependencyInjection/PathsCompilerPass.php b/packages/bluesprints/src/Environment/DependencyInjection/PathsCompilerPass.php
index 64209d6..eddb2c5 100644
--- a/packages/bluesprints/src/Environment/DependencyInjection/PathsCompilerPass.php
+++ b/packages/bluesprints/src/Environment/DependencyInjection/PathsCompilerPass.php
@@ -15,7 +15,7 @@ public function process(ContainerBuilder $container)
{
/** @var Composer $composer */
$composer = $container->get('composer');
- $packageConfig = $composer->getPackage()->getConfig();
+ $packageConfig = $composer->getPackage()->getExtra();
$config = $packageConfig['vertexvaar/bluesprints'];
$pathsDefinition = $container->getDefinition(Paths::class);
diff --git a/packages/bluesprints/src/Http/Server/RequestHandler/ControllerDispatcher.php b/packages/bluesprints/src/Http/Server/RequestHandler/ControllerDispatcher.php
index 150d82a..cc758ae 100644
--- a/packages/bluesprints/src/Http/Server/RequestHandler/ControllerDispatcher.php
+++ b/packages/bluesprints/src/Http/Server/RequestHandler/ControllerDispatcher.php
@@ -29,26 +29,17 @@ public function __construct(
public function handle(ServerRequestInterface $request): ResponseInterface
{
- ob_start();
- define('VXVR_BS_REQUEST_METHOD', $request->getMethod());
-
$route = $request->getAttribute('route');
- $response = new Response();
/** @var AbstractController $controller */
$controller = $this->container->get($route['controller']);
- $content = '';
try {
- $content = $controller->callActionMethod($route, $request);
+ return $controller->{$route['action']}($request);
} catch (RedirectException $exception) {
- $response = $response->withHeader('Location', $exception->getUrl())->withStatus($exception->getStatus());
- }
- if ($this->environment->context === Context::Development) {
- $content = ob_get_contents() . $content;
+ $response = new Response();
+ return $response
+ ->withHeader('Location', $exception->getUrl())
+ ->withStatus($exception->getStatus());
}
-
- $response->getBody()->write($content);
- ob_end_clean();
- return $response;
}
}
diff --git a/packages/bluesprints/src/Mvc/AbstractController.php b/packages/bluesprints/src/Mvc/AbstractController.php
index 9b005c5..840065c 100644
--- a/packages/bluesprints/src/Mvc/AbstractController.php
+++ b/packages/bluesprints/src/Mvc/AbstractController.php
@@ -4,44 +4,25 @@
namespace VerteXVaaR\BlueSprints\Mvc;
-use Psr\Http\Message\ServerRequestInterface;
-
-use function call_user_func;
-use function is_callable;
+use GuzzleHttp\Psr7\Response;
+use Psr\Http\Message\ResponseInterface;
+use Twig\Environment;
abstract class AbstractController implements Controller
{
-
- /**
- * @var bool Indicates if the template should be rendered after the action has been called
- */
- protected bool $renderTemplate = true;
-
public function __construct(
protected readonly Repository $repository,
- protected readonly TemplateRenderer $templateRenderer
+ protected readonly Environment $view
) {
}
- /**
- * @throws RedirectException
- */
- public function callActionMethod(array $configuration, ServerRequestInterface $request): string
+ protected function render(string $template, array $context = [])
{
- if (is_callable([$this, 'initialize'])) {
- call_user_func([$this, 'initialize']);
- }
-
- $this->templateRenderer->setRouteConfiguration($configuration);
- $this->{$configuration['action']}($request);
- if (true === $this->renderTemplate) {
- return $this->templateRenderer->render();
- }
- return '';
+ return new Response(200, [], $this->view->render($template, $context));
}
- protected function redirect($url, $code = RedirectException::SEE_OTHER): void
+ protected function redirect($url, $code = RedirectException::SEE_OTHER): ResponseInterface
{
- throw RedirectException::forUrl($url, $code);
+ return new Response($code, ['Location' => $url]);
}
}
diff --git a/packages/bluesprints/src/Mvc/PhpTemplateRenderer.php b/packages/bluesprints/src/Mvc/PhpTemplateRenderer.php
deleted file mode 100644
index bd2efb0..0000000
--- a/packages/bluesprints/src/Mvc/PhpTemplateRenderer.php
+++ /dev/null
@@ -1,60 +0,0 @@
-templateHelper = new TemplateHelper();
- }
-
- /**
- * @param string $key
- * @param mixed $value
- */
- public function setVariable(string $key, $value): void
- {
- $this->variables[$key] = $value;
- }
-
- /**
- * @param array $routeConfiguration
- */
- public function setRouteConfiguration(array $routeConfiguration): void
- {
- $this->routeConfiguration = $routeConfiguration;
- }
-
- public function render(string $templateName = ''): string
- {
- if ($templateName === '') {
- $templateName = $this->getDefaultTemplateName();
- }
- $this->setVariable('templateHelper', $this->templateHelper);
- ob_start();
- Files::requireFile('app/view/Template/' . $templateName . '.php', $this->variables);
- $body = ob_get_contents();
- $content = $this->templateHelper->renderLayoutContent($body);
- ob_end_clean();
- return $content;
- }
-
- protected function getDefaultTemplateName(): string
- {
- $templateName = ucfirst($this->routeConfiguration['action']);
- $templatePath = Folders::classNameToFolderName($this->routeConfiguration['controller']);
- return $templatePath . $templateName;
- }
-}
diff --git a/packages/bluesprints/src/Mvc/TemplateRenderer.php b/packages/bluesprints/src/Mvc/TemplateRenderer.php
deleted file mode 100644
index 2daedc6..0000000
--- a/packages/bluesprints/src/Mvc/TemplateRenderer.php
+++ /dev/null
@@ -1,19 +0,0 @@
-get('io');
- $packageConfig = $composer->getPackage()->getConfig();
+ $packageConfig = $composer->getPackage()->getExtra();
$configPath = $packageConfig['vertexvaar/bluesprints']['config'] ?? 'config';
if (!file_exists($configPath . '/routes.php')) {
diff --git a/packages/bluesprints/src/Template/DependencyInjection/TemplateRendererCompilerPass.php b/packages/bluesprints/src/Template/DependencyInjection/TemplateRendererCompilerPass.php
new file mode 100644
index 0000000..fd5d572
--- /dev/null
+++ b/packages/bluesprints/src/Template/DependencyInjection/TemplateRendererCompilerPass.php
@@ -0,0 +1,56 @@
+get('composer');
+ $packageIterator = new PackageIterator($composer);
+ $templatePaths = $packageIterator->iterate(static function (Package $package, string $installPath): ?array {
+ $extra = $package->getExtra();
+ if (isset($extra['vertexvaar/bluesprints']['view'])) {
+ $viewPath = $extra['vertexvaar/bluesprints']['view'];
+ $fullViewPath = concat_paths($installPath, $viewPath);
+ return [
+ strtr($package->getName(), '/', '_') => $fullViewPath
+ ];
+ }
+ return null;
+ });
+
+
+ $rootPaths = [];
+ $extra = $composer->getPackage()->getExtra();
+ if (isset($extra['vertexvaar/bluesprints']['view'])) {
+ $viewPath = $extra['vertexvaar/bluesprints']['view'];
+ $fullViewPath = concat_paths(getenv('VXVR_BS_ROOT'), $viewPath);
+ $rootPaths[FilesystemLoader::MAIN_NAMESPACE] = $fullViewPath;
+ }
+ $templatePaths = array_replace($rootPaths, ...array_filter($templatePaths));
+
+ $definition = $container->getDefinition(TemplatePathsRegistry::class);
+ $definition->setArgument('$paths', $templatePaths);
+ }
+}
diff --git a/packages/bluesprints/src/Template/TemplatePathsRegistry.php b/packages/bluesprints/src/Template/TemplatePathsRegistry.php
new file mode 100644
index 0000000..e0c9937
--- /dev/null
+++ b/packages/bluesprints/src/Template/TemplatePathsRegistry.php
@@ -0,0 +1,12 @@
+templatePathsRegistry->paths as $namespace => $path) {
+ $loader->addPath($path, $namespace);
+ }
+ $twigCachePath = concat_paths(getenv('VXVR_BS_ROOT'), $this->paths->cache, 'twig');
+ $filesystemCache = new FilesystemCache($twigCachePath);
+ $twig = new Environment(
+ $loader,
+ [
+ 'cache' => $filesystemCache,
+ 'debug' => $this->environment->context === Context::Development
+ ]
+ );
+ if ($this->environment->context === Context::Development) {
+ $twig->addExtension(new DebugExtension());
+ }
+ return $twig;
+ }
+}
diff --git a/src/Controller/Welcome.php b/src/Controller/Welcome.php
index 0e3fc04..600438e 100644
--- a/src/Controller/Welcome.php
+++ b/src/Controller/Welcome.php
@@ -4,34 +4,34 @@
namespace VerteXVaaR\BlueDist\Controller;
+use Psr\Http\Message\ResponseInterface;
use Psr\Http\Message\ServerRequestInterface;
use VerteXVaaR\BlueDist\Model\Fruit;
-use VerteXVaaR\BlueDist\Model\SubFolder\Branch;
-use VerteXVaaR\BlueDist\Model\SubFolder\Leaf;
-use VerteXVaaR\BlueDist\Model\SubFolder\Tree;
use VerteXVaaR\BlueSprints\Mvc\AbstractController;
use VerteXVaaR\BlueSprints\Utility\Strings;
class Welcome extends AbstractController
{
- protected function index(): void
+ /**
+ * @noinspection PhpUnused
+ */
+ public function index(): ResponseInterface
{
- $this->templateRenderer->setVariable(
- 'strings',
- [
- 'foo',
- 'bar',
- 'baz',
- ]
- );
+ return $this->render('index.html.twig', ['strings' => ['foo', 'bar', 'baz']]);
}
- protected function listFruits(): void
+ /**
+ * @noinspection PhpUnused
+ */
+ public function listFruits(): ResponseInterface
{
- $this->templateRenderer->setVariable('fruits', $this->repository->findAll(Fruit::class));
+ return $this->render('fruits.html.twig', ['fruits' => $this->repository->findAll(Fruit::class)]);
}
- protected function createDemoFruits(): void
+ /**
+ * @noinspection PhpUnused
+ */
+ public function createDemoFruits(): ResponseInterface
{
$fruitsData = [
[
@@ -57,10 +57,13 @@ protected function createDemoFruits(): void
$fruit->name = $fruitData['name'];
$this->repository->persist($fruit);
}
- $this->redirect('listFruits');
+ return $this->redirect('listFruits');
}
- protected function createFruit(ServerRequestInterface $request): void
+ /**
+ * @noinspection PhpUnused
+ */
+ public function createFruit(ServerRequestInterface $request): ResponseInterface
{
$arguments = $request->getParsedBody();
if (isset($arguments['name'], $arguments['color'])) {
@@ -69,81 +72,45 @@ protected function createFruit(ServerRequestInterface $request): void
$fruit->name = $arguments['name'];
$this->repository->persist($fruit);
}
- $this->redirect('listFruits');
+ return $this->redirect('listFruits');
}
- protected function editFruit(ServerRequestInterface $request): void
+ /**
+ * @noinspection PhpUnused
+ */
+ public function editFruit(ServerRequestInterface $request): ResponseInterface
{
$fruit = $this->repository->findByUuid(Fruit::class, $request->getQueryParams()['fruit']);
- $this->templateRenderer->setVariable('fruit', $fruit);
+ return $this->render('edit.html.twig', ['fruit' => $fruit]);
}
- protected function updateFruit(ServerRequestInterface $request): void
+ /**
+ * @noinspection PhpUnused
+ */
+ public function updateFruit(ServerRequestInterface $request): ResponseInterface
{
$arguments = $request->getParsedBody();
if (isset($arguments['uuid'], $arguments['name'], $arguments['color'])) {
$fruit = $this->repository->findByUuid(Fruit::class, $arguments['uuid']);
+ if (null === $fruit) {
+ return $this->redirect('listFruits');
+ }
$fruit->name = $arguments['name'];
$fruit->color = $arguments['color'];
$this->repository->persist($fruit);
}
- $this->redirect('listFruits');
- }
-
- protected function createTree(ServerRequestInterface $request): void
- {
- $arguments = $request->getParsedBody();
- $tree = new Tree(Strings::generateUuid());
- $tree->setGenus($arguments['genus']);
- $this->repository->persist($tree);
- $this->templateRenderer->setVariable('tree', $tree);
- $this->templateRenderer->setVariable('branches', range(1, $arguments['numberOfBranches']));
+ return $this->redirect('listFruits');
}
- protected function newTree(): void
- {
- }
-
- protected function growBranches(ServerRequestInterface $request): void
- {
- $arguments = $request->getParsedBody();
- $tree = $this->repository->findByUuid(Tree::class, $arguments['tree']);
- $branches = [];
- foreach ($arguments['branches'] as $data) {
- $branch = new Branch(Strings::generateUuid());
- $branch->setLength((int)$data['length']);
- $branches[] = $branch;
- }
- $tree->setBranches($branches);
- $this->repository->persist($tree);
- $this->redirect('applyLeaves?tree=' . $tree->uuid);
- }
-
- protected function applyLeaves(ServerRequestInterface $request): void
- {
- $arguments = $request->getQueryParams();
- $this->templateRenderer->setVariable(
- 'tree',
- $this->repository->findByUuid(Tree::class, $arguments['tree'])
- );
- }
-
- protected function addLeaf(ServerRequestInterface $request): void
- {
- $arguments = $request->getParsedBody();
- $tree = $this->repository->findByUuid(Tree::class, $arguments['tree']);
- $branch = $tree->getBranches()[$arguments['branch']];
- $leaves = $branch->getLeaves();
- $leaves[] = new Leaf(Strings::generateUuid(), count($leaves) + 1);
- $branch->setLeaves($leaves);
- $this->repository->persist($tree);
- $this->redirect('applyLeaves?tree=' . $tree->uuid);
- }
-
- protected function deleteFruit(ServerRequestInterface $request): void
+ /**
+ * @noinspection PhpUnused
+ */
+ public function deleteFruit(ServerRequestInterface $request): ResponseInterface
{
$fruit = $this->repository->findByUuid(Fruit::class, $request->getParsedBody()['fruit']);
- $this->repository->delete($fruit);
- $this->redirect('listFruits');
+ if (null !== $fruit) {
+ $this->repository->delete($fruit);
+ }
+ return $this->redirect('listFruits');
}
}
diff --git a/view/Layout/VerteXVaaR/BlueAuth/Controller/AuthenticationController/Html.html b/view/Layout/VerteXVaaR/BlueAuth/Controller/AuthenticationController/Html.html
deleted file mode 100644
index a3b77af..0000000
--- a/view/Layout/VerteXVaaR/BlueAuth/Controller/AuthenticationController/Html.html
+++ /dev/null
@@ -1,12 +0,0 @@
-
-
-
-
-
- {pageTitle}
-
-
-
-
-
-
diff --git a/view/Layout/VerteXVaaR/BlueDist/Controller/Welcome/Html.html b/view/Layout/VerteXVaaR/BlueDist/Controller/Welcome/Html.html
deleted file mode 100644
index a3b77af..0000000
--- a/view/Layout/VerteXVaaR/BlueDist/Controller/Welcome/Html.html
+++ /dev/null
@@ -1,12 +0,0 @@
-
-
-
-
-
- {pageTitle}
-
-
-
-
-
-
diff --git a/view/Template/DebugToolbarMiddleware/DebugToolbarMiddleware/DebugToolbar.html b/view/Template/DebugToolbarMiddleware/DebugToolbarMiddleware/DebugToolbar.html
deleted file mode 100644
index 6f56032..0000000
--- a/view/Template/DebugToolbarMiddleware/DebugToolbarMiddleware/DebugToolbar.html
+++ /dev/null
@@ -1,13 +0,0 @@
-
-
-
Route: {route.controller}::{route.action}
-
-
- User (authenticated): {username}
-
-
- User (anonymous session)
-
-
-
-
diff --git a/view/Template/VerteXVaaR/BlueAuth/Controller/AuthenticationController/AuthenticationController/Login.html b/view/Template/VerteXVaaR/BlueAuth/Controller/AuthenticationController/AuthenticationController/Login.html
deleted file mode 100644
index e72d23c..0000000
--- a/view/Template/VerteXVaaR/BlueAuth/Controller/AuthenticationController/AuthenticationController/Login.html
+++ /dev/null
@@ -1,28 +0,0 @@
-
-
-
-
-
-
-
diff --git a/view/Template/VerteXVaaR/BlueDist/Controller/Welcome/ApplyLeaves.html b/view/Template/VerteXVaaR/BlueDist/Controller/Welcome/ApplyLeaves.html
deleted file mode 100644
index da7047c..0000000
--- a/view/Template/VerteXVaaR/BlueDist/Controller/Welcome/ApplyLeaves.html
+++ /dev/null
@@ -1,24 +0,0 @@
-
-
-
-
-
- Put some Leaves on {tree.genus}s branches!
-
-
- Branch #{i.index} with length: {branch.length}
-
-
- Leaf #{leaf.number},
-
-
-
-
-
-
-
-
diff --git a/view/Template/VerteXVaaR/BlueDist/Controller/Welcome/CreateTree.html b/view/Template/VerteXVaaR/BlueDist/Controller/Welcome/CreateTree.html
deleted file mode 100644
index d9dcbfe..0000000
--- a/view/Template/VerteXVaaR/BlueDist/Controller/Welcome/CreateTree.html
+++ /dev/null
@@ -1,23 +0,0 @@
-
-
-
-
-
-
- Grow some branches on {tree.genus}!
-
-
-
-
-
diff --git a/view/Template/VerteXVaaR/BlueDist/Controller/Welcome/EditFruit.html b/view/Template/VerteXVaaR/BlueDist/Controller/Welcome/EditFruit.html
deleted file mode 100644
index f6c7c25..0000000
--- a/view/Template/VerteXVaaR/BlueDist/Controller/Welcome/EditFruit.html
+++ /dev/null
@@ -1,73 +0,0 @@
-
-
-
-
-
- Change a {fruit.name}
-
-
- Objects are target to many modifications, so updating a already persistend object is essential.
- Change the name or color of your selected fruit and save it, or go back to the
- list.
-
-
-
-
-
-
-
- The code behind this object update
-
-
- $arguments = $this->request->getParsedBody();
- if (isset($arguments['uuid'], $arguments['name'], $arguments['color'])) {
- $fruit = Fruit::findByUuid($arguments['uuid']);
- $fruit->setName($arguments['name']);
- $fruit->setColor($arguments['color']);
- $fruit->save();
- }
- $this->redirect('listFruits');
-
-
- About safe requests
-
-
- HTTP requests are divided into two different types. Safe and not safe requests.
- A safe request must not modify an object or persist changes.
- Safe requests exist to retrieve information from a service or website without changing any data.
- Safe requests are idempotent.
- To change the name of a fruit you must make a non-safe request, e.g. POST.
- PUT, POST, and DELETE are considered non-safe because they may change data.
-
-
- Try it
-
-
- This link will not work since the
- request parameters are expected to exist in POST.
- You will be redirected to the listFruits view.
-
-
-
-
-
diff --git a/view/Template/VerteXVaaR/BlueDist/Controller/Welcome/Index.html b/view/Template/VerteXVaaR/BlueDist/Controller/Welcome/Index.html
deleted file mode 100644
index d2224ba..0000000
--- a/view/Template/VerteXVaaR/BlueDist/Controller/Welcome/Index.html
+++ /dev/null
@@ -1,62 +0,0 @@
-
-
-
-
-
-
- Welcome to VerteXVaaR.BlueSprints
-
- An experiment gone right :D
-
-
- VerteXVaaR.BlueSprints was created in a few hours as an experiment of "what could be done in 3 hours"
- and it's development continued for 6 other hours. After 9 hours it had (all simple) routing, templating,
- of course autoloading (thanks composer) and NoDB persistence, all out of the box. But more is to come.
-
-
- It will stay simple!
-
-
- This PHP Framework is designed to stay as simple as possible but yet provide some indispensable
- features.
- So there is no Database connection or Dependency Injection and it's not about to come. If you are
- searching
- for
- a framework capable of that, you have to search for another.
-
-
- Fast framework, fast Development
-
-
- Because there are almost no classes inside of VerteXVaaR.BlueSprints and it has no reflection or
- abstraction
- it is simply fast by design, without any caching.
- This (nearly) slender design is good for performance, but it prevents some features. But if you want to
- develop
- a simple Application that stores a few models or just prints out content you will be convinced by your
- own
- development speed
-
-
- Templating
-
-
- Templating might be something you have to get used to, because it uses pure PHP. There is nothing fancy
- like
- twig, handlebars.js or TYPO3.Fluid. Just some PHP that is executed right away. Not even cached.
- Here is some data set by the controller. Only for your pleasure ;)
-
-
-
- Persistence?
-
-
- Want a demo about Persistence? Just follow me ;)
-
-
-
-
diff --git a/view/Template/VerteXVaaR/BlueDist/Controller/Welcome/ListFruits.html b/view/Template/VerteXVaaR/BlueDist/Controller/Welcome/ListFruits.html
deleted file mode 100644
index 72ba457..0000000
--- a/view/Template/VerteXVaaR/BlueDist/Controller/Welcome/ListFruits.html
+++ /dev/null
@@ -1,111 +0,0 @@
-
-
-
-
-
-
- Some Fruits freshly picked from persistence
-
-
-
-
- Hint: click on a fruit to edit it!
-
-
-
-
-
- OH WAIT! There is no Fruit yet.
-
-
-
-
-
- Not enough fruits? Just create your own fruit here:
-
-
-
-
- The NoDB Storage
-
-
- Since there is no configuration for any storage or database i owe you an explanation.
- BlueSprints just uses the file system. The full qualified class name of a model is converted into a
- directory
- structure. Inside the last directory all models are stored in files named by their automatically created
- uuid.
- The objects are serialized, since this is the fastest option to store all simple values without
- reflection,
- additional configuration or such.
-
-
- WIP !
-
-
- The Storage function is currently work in progress. Some missing features are automatic index tables for
- searching
- models by their properties or the deletion of those.
-
-
- Like it? Or not?
-
-
- Have a look at the code which creates a fruit from the form above:
-
-
-
- $arguments = $this->request->getParsedBody();
- if (isset($arguments['name'], $arguments['color'])) {
- $fruit = new Fruit();
- $fruit->setColor($arguments['color']);
- $fruit->setName($arguments['name']);
- $fruit->save();
- }
- $this->redirect('listFruits');
-
-
-
- As i promised you, it is easy as pie. If you want to alter the Model, say add a new property, just do
- it.
-
-
-
- Back to the index
-
-
-
-
diff --git a/view/Template/VerteXVaaR/BlueDist/Controller/Welcome/NewTree.html b/view/Template/VerteXVaaR/BlueDist/Controller/Welcome/NewTree.html
deleted file mode 100644
index bbc56bf..0000000
--- a/view/Template/VerteXVaaR/BlueDist/Controller/Welcome/NewTree.html
+++ /dev/null
@@ -1,32 +0,0 @@
-
-
-
-
-
-
- Plant a tree!
-
-
- Create a new Tree object. After the Tree has been planted, it will grow branches and
- each branch will grow some leaves.
-
-
-
-
-
-
diff --git a/view/edit.html.twig b/view/edit.html.twig
new file mode 100644
index 0000000..6f2f33a
--- /dev/null
+++ b/view/edit.html.twig
@@ -0,0 +1,70 @@
+{% extends "layout.html.twig" %}
+
+{% block content %}
+
+ Change a {{ fruit.name }}
+
+
+ Objects are target to many modifications, so updating a already persistend object is essential.
+ Change the name or color of your selected fruit and save it, or go back to the
+ list.
+
+
+
+
+
+
+
+ The code behind this object update
+
+
+ $arguments = $this->request->getParsedBody();
+ if (isset($arguments['uuid'], $arguments['name'], $arguments['color'])) {
+ $fruit = Fruit::findByUuid($arguments['uuid']);
+ $fruit->setName($arguments['name']);
+ $fruit->setColor($arguments['color']);
+ $fruit->save();
+ }
+ $this->redirect('listFruits');
+
+
+ About safe requests
+
+
+ HTTP requests are divided into two different types. Safe and not safe requests.
+ A safe request must not modify an object or persist changes.
+ Safe requests exist to retrieve information from a service or website without changing any data.
+ Safe requests are idempotent.
+ To change the name of a fruit you must make a non-safe request, e.g. POST.
+ PUT, POST, and DELETE are considered non-safe because they may change data.
+
+
+ Try it
+
+
+ This link will not work since the
+ request parameters are expected to exist in POST.
+ You will be redirected to the listFruits view.
+
+
+{% endblock %}
diff --git a/view/fruits.html.twig b/view/fruits.html.twig
new file mode 100644
index 0000000..ca95e20
--- /dev/null
+++ b/view/fruits.html.twig
@@ -0,0 +1,103 @@
+{% extends "layout.html.twig" %}
+
+{% block content %}
+
+
+ Some Fruits freshly picked from persistence
+
+ {% if fruits %}
+
+ Hint: click on a fruit to edit it!
+
+
+
+ {% else %}
+ OH WAIT! There is no Fruit yet.
+
+ {% endif %}
+
+
+ Not enough fruits? Just create your own fruit here:
+
+
+
+
+ The NoDB Storage
+
+
+ Since there is no configuration for any storage or database i owe you an explanation.
+ BlueSprints just uses the file system. The full qualified class name of a model is converted into a
+ directory
+ structure. Inside the last directory all models are stored in files named by their automatically created
+ uuid.
+ The objects are serialized, since this is the fastest option to store all simple values without
+ reflection,
+ additional configuration or such.
+
+
+ WIP !
+
+
+ The Storage function is currently work in progress. Some missing features are automatic index tables for
+ searching
+ models by their properties or the deletion of those.
+
+
+ Like it? Or not?
+
+
+ Have a look at the code which creates a fruit from the form above:
+
+
+
+ $arguments = $this->request->getParsedBody();
+ if (isset($arguments['name'], $arguments['color'])) {
+ $fruit = new Fruit();
+ $fruit->setColor($arguments['color']);
+ $fruit->setName($arguments['name']);
+ $fruit->save();
+ }
+ $this->redirect('listFruits');
+
+
+
+ As i promised you, it is easy as pie. If you want to alter the Model, say add a new property, just do
+ it.
+
+
+
+ Back to the index
+
+
+{% endblock %}
diff --git a/view/index.html.twig b/view/index.html.twig
new file mode 100644
index 0000000..b5fe613
--- /dev/null
+++ b/view/index.html.twig
@@ -0,0 +1,58 @@
+{% extends "layout.html.twig" %}
+
+{% block content %}
+
+
+ Welcome to VerteXVaaR.BlueSprints
+
+ An experiment gone right :D
+
+
+ VerteXVaaR.BlueSprints was created in a few hours as an experiment of "what could be done in 3 hours"
+ and it's development continued for 6 other hours. After 9 hours it had (all simple) routing, templating,
+ of course autoloading (thanks composer) and NoDB persistence, all out of the box. But more is to come.
+
+
+ It will stay simple!
+
+
+ This PHP Framework is designed to stay as simple as possible but yet provide some indispensable
+ features.
+ So there is no Database connection or Dependency Injection and it's not about to come. If you are
+ searching
+ for
+ a framework capable of that, you have to search for another.
+
+
+ Fast framework, fast Development
+
+
+ Because there are almost no classes inside of VerteXVaaR.BlueSprints and it has no reflection or
+ abstraction
+ it is simply fast by design, without any caching.
+ This (nearly) slender design is good for performance, but it prevents some features. But if you want to
+ develop
+ a simple Application that stores a few models or just prints out content you will be convinced by your
+ own
+ development speed
+
+
+ Templating
+
+
+ Templating might be something you have don't have to get used to, because it uses Twig.
+ Here is some data set by the controller:
+
+
+ {% for string in strings %}
+ - {{ string }}
+ {% endfor %}
+
+
+ Persistence?
+
+
+ Want a demo about Persistence? Just follow me ;)
+
+
+{% endblock %}
diff --git a/view/layout.html.twig b/view/layout.html.twig
new file mode 100644
index 0000000..1e894c5
--- /dev/null
+++ b/view/layout.html.twig
@@ -0,0 +1,14 @@
+
+
+
+
+ {% block head %}
+
+ {% endblock %}
+ {{ pageTitle }}
+
+
+
+ {% block content %}No content in here{% endblock %}
+
+