summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/Application.php118
-rw-r--r--src/Config/ConfigServiceProvider.php26
-rw-r--r--src/Container/Container.php110
-rw-r--r--src/Container/ContainerException.php11
-rw-r--r--src/Container/NotFoundException.php10
-rw-r--r--src/Container/ServiceProvider.php31
-rw-r--r--src/Database/DatabaseServiceProvider.php31
-rw-r--r--src/Exceptions/ExceptionsServiceProvider.php15
-rw-r--r--src/Http/RequestServiceProvider.php14
-rw-r--r--src/Http/SessionServiceProvider.php52
-rw-r--r--src/Logger/LoggerServiceProvider.php18
-rw-r--r--src/Renderer/RendererServiceProvider.php36
-rw-r--r--src/Routing/RoutingServiceProvider.php14
-rw-r--r--src/helpers.php65
14 files changed, 403 insertions, 148 deletions
diff --git a/src/Application.php b/src/Application.php
index 674b3869..c9023c7b 100644
--- a/src/Application.php
+++ b/src/Application.php
@@ -2,24 +2,136 @@
namespace Engelsystem;
+use Engelsystem\Config\Config;
use Engelsystem\Container\Container;
+use Engelsystem\Container\ServiceProvider;
use Psr\Container\ContainerInterface;
class Application extends Container
{
- public function __construct()
+ /** @var string|null */
+ protected $appPath = null;
+
+ /** @var bool */
+ protected $isBootstrapped = false;
+
+ /**
+ * Registered service providers
+ *
+ * @var array
+ */
+ protected $serviceProviders = [];
+
+ /**
+ * Application constructor.
+ *
+ * @param string $appPath
+ */
+ public function __construct($appPath = null)
{
+ if (!is_null($appPath)) {
+ $this->setAppPath($appPath);
+ }
+
$this->registerBaseBindings();
}
protected function registerBaseBindings()
{
- self::setInstance($this);
+ static::setInstance($this);
Container::setInstance($this);
$this->instance('app', $this);
$this->instance('container', $this);
$this->instance(Container::class, $this);
$this->instance(Application::class, $this);
- $this->instance(ContainerInterface::class, $this);
+ $this->bind(ContainerInterface::class, Application::class);
+ }
+
+ /**
+ * @param string|ServiceProvider $provider
+ * @return ServiceProvider
+ */
+ public function register($provider)
+ {
+ if (is_string($provider)) {
+ $provider = $this->make($provider);
+ }
+
+ $this->serviceProviders[] = $provider;
+
+ $provider->register();
+
+ if ($this->isBootstrapped) {
+ $this->call([$provider, 'boot']);
+ }
+
+ return $provider;
+ }
+
+ /**
+ * Boot service providers
+ *
+ * @param Config|null $config
+ */
+ public function bootstrap(Config $config = null)
+ {
+ if ($this->isBootstrapped) {
+ return;
+ }
+
+ if ($config instanceof Config) {
+ foreach ($config->get('providers', []) as $provider) {
+ $this->register($provider);
+ }
+ }
+
+ foreach ($this->serviceProviders as $provider) {
+ $this->call([$provider, 'boot']);
+ }
+
+ $this->isBootstrapped = true;
+ }
+
+ protected function registerPaths()
+ {
+ $appPath = $this->appPath;
+
+ $this->instance('path', $appPath);
+ $this->instance('path.config', $appPath . DIRECTORY_SEPARATOR . 'config');
+ $this->instance('path.lang', $appPath . DIRECTORY_SEPARATOR . 'locale');
+ }
+
+ /**
+ * Set app base path
+ *
+ * @param string $appPath
+ * @return static
+ */
+ public function setAppPath($appPath)
+ {
+ $appPath = realpath($appPath);
+ $appPath = rtrim($appPath, DIRECTORY_SEPARATOR);
+
+ $this->appPath = $appPath;
+
+ $this->registerPaths();
+
+ return $this;
+ }
+
+ /**
+ * @return string|null
+ */
+ public function path()
+ {
+ return $this->appPath;
+ }
+
+ /**
+ * @return bool
+ */
+ public function isBooted()
+ {
+ return $this->isBootstrapped;
}
}
diff --git a/src/Config/ConfigServiceProvider.php b/src/Config/ConfigServiceProvider.php
new file mode 100644
index 00000000..01b648df
--- /dev/null
+++ b/src/Config/ConfigServiceProvider.php
@@ -0,0 +1,26 @@
+<?php
+
+namespace Engelsystem\Config;
+
+use Engelsystem\Container\ServiceProvider;
+
+class ConfigServiceProvider extends ServiceProvider
+{
+ public function register()
+ {
+ $defaultConfigFile = config_path('config.default.php');
+ $configFile = config_path('config.php');
+
+ $config = $this->app->make(Config::class);
+ $this->app->instance('config', $config);
+
+ $config->set(require $defaultConfigFile);
+
+ if (file_exists($configFile)) {
+ $config->set(array_replace_recursive(
+ $config->get(null),
+ require $configFile
+ ));
+ }
+ }
+}
diff --git a/src/Container/Container.php b/src/Container/Container.php
index 59a17a04..44c57b6f 100644
--- a/src/Container/Container.php
+++ b/src/Container/Container.php
@@ -2,115 +2,9 @@
namespace Engelsystem\Container;
-use Psr\Container\ContainerExceptionInterface;
+use Illuminate\Container\Container as IlluminateContainer;
use Psr\Container\ContainerInterface;
-use Psr\Container\NotFoundExceptionInterface;
-class Container implements ContainerInterface
+class Container extends IlluminateContainer implements ContainerInterface
{
- /**
- * The globally available container
- *
- * @var static
- */
- protected static $instance;
-
- /**
- * Contains the shared instances
- *
- * @var mixed[]
- */
- protected $instances = [];
-
- /**
- * Finds an entry of the container by its identifier and returns it
- *
- * @param string $id Identifier of the entry to look for
- *
- * @throws NotFoundExceptionInterface No entry was found for **this** identifier
- * @throws ContainerExceptionInterface Error while retrieving the entry
- *
- * @return mixed Entry
- */
- public function get($id)
- {
- if ($this->has($id)) {
- return $this->resolve($id);
- }
-
- throw new NotFoundException(sprintf('The entry with the id "%s" could not be found', $id));
- }
-
- /**
- * Register a shared entry in the container
- *
- * @param string $abstract Identifier of the entry to set
- * @param mixed $instance Entry
- */
- public function instance($abstract, $instance)
- {
- $this->singleton($abstract, $instance);
- }
-
- /**
- * Register a shared entry as singleton in the container
- *
- * @param string $abstract
- * @param mixed $instance
- */
- public function singleton($abstract, $instance)
- {
- $this->instances[$abstract] = $instance;
- }
-
- /**
- * Returns true if the container can return an entry for the given identifier
- * Returns false otherwise
- *
- * `has($id)` returning true does not mean that `get($id)` will not throw an exception
- * It does however mean that `get($id)` will not throw a `NotFoundExceptionInterface`
- *
- * @param string $id Identifier of the entry to look for
- *
- * @return bool
- */
- public function has($id)
- {
- return isset($this->instances[$id]);
- }
-
- /**
- * Resolve the requested object
- *
- * @param string $abstract
- * @return mixed
- */
- protected function resolve($abstract)
- {
- return $this->instances[$abstract];
- }
-
- /**
- * Get the globally available instance of the container
- *
- * @return self
- */
- public static function getInstance()
- {
- if (is_null(static::$instance)) {
- static::$instance = new static;
- }
-
- return static::$instance;
- }
-
- /**
- * Set the globally available instance of the container
- *
- * @param Container $container
- */
- public static function setInstance(Container $container)
- {
- static::$instance = $container;
- }
}
diff --git a/src/Container/ContainerException.php b/src/Container/ContainerException.php
deleted file mode 100644
index 3cdde506..00000000
--- a/src/Container/ContainerException.php
+++ /dev/null
@@ -1,11 +0,0 @@
-<?php
-
-namespace Engelsystem\Container;
-
-use Exception;
-use Psr\Container\ContainerExceptionInterface;
-
-class ContainerException extends Exception implements ContainerExceptionInterface
-{
-
-}
diff --git a/src/Container/NotFoundException.php b/src/Container/NotFoundException.php
deleted file mode 100644
index a83be0b1..00000000
--- a/src/Container/NotFoundException.php
+++ /dev/null
@@ -1,10 +0,0 @@
-<?php
-
-namespace Engelsystem\Container;
-
-use Psr\Container\NotFoundExceptionInterface;
-
-class NotFoundException extends ContainerException implements NotFoundExceptionInterface
-{
-
-}
diff --git a/src/Container/ServiceProvider.php b/src/Container/ServiceProvider.php
new file mode 100644
index 00000000..2a1bbebf
--- /dev/null
+++ b/src/Container/ServiceProvider.php
@@ -0,0 +1,31 @@
+<?php
+
+namespace Engelsystem\Container;
+
+use Engelsystem\Application;
+
+abstract class ServiceProvider
+{
+ /** @var Application */
+ protected $app;
+
+ /**
+ * ServiceProvider constructor.
+ *
+ * @param Application $app
+ */
+ public function __construct(Application $app)
+ {
+ $this->app = $app;
+ }
+
+ /**
+ * Register container bindings
+ */
+ public function register() { }
+
+ /**
+ * Called after other services had been registered
+ */
+ public function boot() { }
+}
diff --git a/src/Database/DatabaseServiceProvider.php b/src/Database/DatabaseServiceProvider.php
new file mode 100644
index 00000000..364816cc
--- /dev/null
+++ b/src/Database/DatabaseServiceProvider.php
@@ -0,0 +1,31 @@
+<?php
+
+namespace Engelsystem\Database;
+
+use Engelsystem\Container\ServiceProvider;
+use Exception;
+use PDO;
+
+class DatabaseServiceProvider extends ServiceProvider
+{
+ public function register()
+ {
+ $config = $this->app->get('config');
+ Db::connect(
+ 'mysql:host=' . $config->get('database')['host'] . ';dbname=' . $config->get('database')['db'] . ';charset=utf8',
+ $config->get('database')['user'],
+ $config->get('database')['pw']
+ ) || $this->exitOnError();
+
+ Db::getPdo()->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
+ Db::getPdo()->setAttribute(PDO::ATTR_EMULATE_PREPARES, false);
+ }
+
+ /**
+ * @throws Exception
+ */
+ protected function exitOnError()
+ {
+ throw new Exception('Error: Unable to connect to database');
+ }
+}
diff --git a/src/Exceptions/ExceptionsServiceProvider.php b/src/Exceptions/ExceptionsServiceProvider.php
new file mode 100644
index 00000000..7755e1e7
--- /dev/null
+++ b/src/Exceptions/ExceptionsServiceProvider.php
@@ -0,0 +1,15 @@
+<?php
+
+namespace Engelsystem\Exceptions;
+
+use Engelsystem\Container\ServiceProvider;
+use Engelsystem\Exceptions\Handler as ExceptionHandler;
+
+class ExceptionsServiceProvider extends ServiceProvider
+{
+ public function register()
+ {
+ $errorHandler = $this->app->make(ExceptionHandler::class);
+ $this->app->instance('error.handler', $errorHandler);
+ }
+}
diff --git a/src/Http/RequestServiceProvider.php b/src/Http/RequestServiceProvider.php
new file mode 100644
index 00000000..077e9ecc
--- /dev/null
+++ b/src/Http/RequestServiceProvider.php
@@ -0,0 +1,14 @@
+<?php
+
+namespace Engelsystem\Http;
+
+use Engelsystem\Container\ServiceProvider;
+
+class RequestServiceProvider extends ServiceProvider
+{
+ public function register()
+ {
+ $request = $this->app->call([Request::class, 'createFromGlobals']);
+ $this->app->instance('request', $request);
+ }
+}
diff --git a/src/Http/SessionServiceProvider.php b/src/Http/SessionServiceProvider.php
new file mode 100644
index 00000000..55e3f48b
--- /dev/null
+++ b/src/Http/SessionServiceProvider.php
@@ -0,0 +1,52 @@
+<?php
+
+namespace Engelsystem\Http;
+
+use Engelsystem\Container\ServiceProvider;
+use Symfony\Component\HttpFoundation\Session\Session;
+use Symfony\Component\HttpFoundation\Session\Storage\MockArraySessionStorage;
+use Symfony\Component\HttpFoundation\Session\Storage\NativeSessionStorage;
+use Symfony\Component\HttpFoundation\Session\Storage\SessionStorageInterface;
+
+class SessionServiceProvider extends ServiceProvider
+{
+ public function register()
+ {
+ $sessionStorage = $this->getSessionStorage();
+ $this->app->instance('session.storage', $sessionStorage);
+ $this->app->bind(SessionStorageInterface::class, 'session.storage');
+
+ $session = $this->app->make(Session::class);
+ $this->app->instance('session', $session);
+
+ /** @var Request $request */
+ $request = $this->app->get('request');
+ $request->setSession($session);
+
+ $session->start();
+ }
+
+ /**
+ * Returns the session storage
+ *
+ * @return SessionStorageInterface
+ */
+ protected function getSessionStorage()
+ {
+ if ($this->isCli()) {
+ return $this->app->make(MockArraySessionStorage::class);
+ }
+
+ return $this->app->make(NativeSessionStorage::class, ['options' => ['cookie_httponly' => true]]);
+ }
+
+ /**
+ * Test if is called from cli
+ *
+ * @return bool
+ */
+ protected function isCli()
+ {
+ return PHP_SAPI == 'cli';
+ }
+}
diff --git a/src/Logger/LoggerServiceProvider.php b/src/Logger/LoggerServiceProvider.php
new file mode 100644
index 00000000..cf22f383
--- /dev/null
+++ b/src/Logger/LoggerServiceProvider.php
@@ -0,0 +1,18 @@
+<?php
+
+namespace Engelsystem\Logger;
+
+use Engelsystem\Container\ServiceProvider;
+use Psr\Log\LoggerInterface;
+
+class LoggerServiceProvider extends ServiceProvider
+{
+ public function register()
+ {
+ $logger = $this->app->make(EngelsystemLogger::class);
+ $this->app->instance('logger', $logger);
+
+ $this->app->bind(LoggerInterface::class, 'logger');
+ $this->app->bind(EngelsystemLogger::class, 'logger');
+ }
+}
diff --git a/src/Renderer/RendererServiceProvider.php b/src/Renderer/RendererServiceProvider.php
new file mode 100644
index 00000000..3e8d69bc
--- /dev/null
+++ b/src/Renderer/RendererServiceProvider.php
@@ -0,0 +1,36 @@
+<?php
+
+namespace Engelsystem\Renderer;
+
+use Engelsystem\Container\ServiceProvider;
+
+class RendererServiceProvider extends ServiceProvider
+{
+ public function register()
+ {
+ $this->registerRenderer();
+ $this->registerHtmlEngine();
+ }
+
+ public function boot()
+ {
+ $renderer = $this->app->get('renderer');
+
+ foreach ($this->app->tagged('renderer.engine') as $engine) {
+ $renderer->addRenderer($engine);
+ }
+ }
+
+ protected function registerRenderer()
+ {
+ $renderer = $this->app->make(Renderer::class);
+ $this->app->instance('renderer', $renderer);
+ }
+
+ protected function registerHtmlEngine()
+ {
+ $htmlEngine = $this->app->make(HtmlEngine::class);
+ $this->app->instance('renderer.htmlEngine', $htmlEngine);
+ $this->app->tag('renderer.htmlEngine', ['renderer.engine']);
+ }
+}
diff --git a/src/Routing/RoutingServiceProvider.php b/src/Routing/RoutingServiceProvider.php
new file mode 100644
index 00000000..b7db1383
--- /dev/null
+++ b/src/Routing/RoutingServiceProvider.php
@@ -0,0 +1,14 @@
+<?php
+
+namespace Engelsystem\Routing;
+
+use Engelsystem\Container\ServiceProvider;
+
+class RoutingServiceProvider extends ServiceProvider
+{
+ public function register()
+ {
+ $urlGenerator = $this->app->make(UrlGenerator::class);
+ $this->app->instance('routing.urlGenerator', $urlGenerator);
+ }
+}
diff --git a/src/helpers.php b/src/helpers.php
index de303963..5a48498a 100644
--- a/src/helpers.php
+++ b/src/helpers.php
@@ -24,6 +24,15 @@ function app($id = null)
}
/**
+ * @param string $path
+ * @return string
+ */
+function base_path($path = '')
+{
+ return app('path') . (empty($path) ? '' : DIRECTORY_SEPARATOR . $path);
+}
+
+/**
* Get or set config values
*
* @param string|array $key
@@ -47,6 +56,30 @@ function config($key = null, $default = null)
}
/**
+ * @param string $path
+ * @return string
+ */
+function config_path($path = '')
+{
+ return app('path.config') . (empty($path) ? '' : DIRECTORY_SEPARATOR . $path);
+}
+
+/**
+ * @param string $key
+ * @param mixed $default
+ * @return mixed
+ */
+function env($key, $default = null)
+{
+ $value = getenv($key);
+ if ($value === false) {
+ return $default;
+ }
+
+ return $value;
+}
+
+/**
* @param string $key
* @param mixed $default
* @return Request|mixed
@@ -79,22 +112,6 @@ function session($key = null, $default = null)
}
/**
- * @param string $template
- * @param mixed[] $data
- * @return Renderer|string
- */
-function view($template = null, $data = null)
-{
- $renderer = app('renderer');
-
- if (is_null($template)) {
- return $renderer;
- }
-
- return $renderer->render($template, $data);
-}
-
-/**
* @param string $path
* @param array $parameters
* @return UrlGenerator|string
@@ -109,3 +126,19 @@ function url($path = null, $parameters = [])
return $urlGenerator->to($path, $parameters);
}
+
+/**
+ * @param string $template
+ * @param mixed[] $data
+ * @return Renderer|string
+ */
+function view($template = null, $data = null)
+{
+ $renderer = app('renderer');
+
+ if (is_null($template)) {
+ return $renderer;
+ }
+
+ return $renderer->render($template, $data);
+}