Merge pull request #349 from MyIgel/master

Changed container to Illuminate/Container and added service providers
main
msquare 7 years ago committed by GitHub
commit ebc973bf22
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -0,0 +1,90 @@
image: php
cache:
paths:
- .composer
services:
- mysql:5.6
variables:
MYSQL_DATABASE: engelsystem
MYSQL_USER: engel
MYSQL_PASSWORD: engelsystem
COMPOSER_HOME: .composer
MYSQL_RANDOM_ROOT_PASSWORD: "yes"
before_script:
# Fix permissions after gitlab messed them up
- find . -type f -exec chmod 644 {} \;
- find . -type d -exec chmod 755 {} \;
# Install required Packages
- apt update -yqq
- apt install -yqq git unzip mysql-client
- docker-php-ext-install pdo pdo_mysql gettext
# Install xdebug
- pecl install xdebug
- docker-php-ext-enable xdebug
# MySQL DB
- mysql -h mysql -u "$MYSQL_USER" -p"$MYSQL_PASSWORD" "$MYSQL_DATABASE" < db/install.sql
- mysql -h mysql -u "$MYSQL_USER" -p"$MYSQL_PASSWORD" "$MYSQL_DATABASE" < db/update.sql
# Install Composer
- curl -sS https://getcomposer.org/installer | php -- --no-ansi --install-dir /usr/local/bin/ --filename composer
- /usr/local/bin/composer --no-ansi install
.test_template: &test_definition
artifacts:
name: "${CI_JOB_NAME}_${CI_PROJECT_ID}_${PHP_VERSION}"
expire_in: 1 week
paths:
- ./coverage/
coverage: '/^\s*Lines:\s*(\d+(?:\.\d+)?%)/'
script: vendor/bin/phpunit --colors=never --coverage-text --coverage-html ./coverage/
test:7.0:
image: php:7.0
<<: *test_definition
test:7.1:
image: php:7.1
<<: *test_definition
deploy_staging:
stage: deploy
only:
- master
script:
- |-
if [ -z "${SSH_PRIVATE_KEY}" ] || [ -z "${REMOTE}" ] || [ -z "${REMOTE_PATH}" ]; then
echo "Skipping deployment";
exit
fi
- mkdir -p ~/.ssh
- echo "$SSH_PRIVATE_KEY" | sed -e 's/\r//g' > ~/.ssh/id_ed25519
- chmod 600 ~/.ssh/id_ed25519
- apt update && apt install -yqq rsync openssh-client
- /usr/local/bin/composer --no-ansi install --no-dev
- /usr/local/bin/composer --no-ansi dump-autoload --optimize
- echo "syncing ${PWD}/ to ${REMOTE}:${REMOTE_PATH}/${CI_JOB_ID}-${CI_COMMIT_SHA}/"
- |-
rsync -vAax --exclude '.git*' --exclude .composer/ \
-e "ssh -q -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no" \
./ "${REMOTE}:${REMOTE_PATH}/${CI_JOB_ID}-${CI_COMMIT_SHA}/"
- |-
ssh -q -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no "${REMOTE}" "
set -e
if [[ -f \"${REMOTE_PATH}/current/config/config.php\" ]]; then
echo \"Config backup\"
cp \"${REMOTE_PATH}/current/config/config.php\" config.php
fi
echo \"Changing symlink\"
unlink \"${REMOTE_PATH}/current\"
ln -s \"${REMOTE_PATH}/${CI_JOB_ID}-${CI_COMMIT_SHA}\" \"${REMOTE_PATH}/current\"
if [[ -f config.php ]]; then
echo \"Restoring config\"
cp config.php \"${REMOTE_PATH}/current/config/config.php\"
fi
"

@ -15,11 +15,12 @@
], ],
"require": { "require": {
"php": ">=7.0.0", "php": ">=7.0.0",
"erusev/parsedown": "1.6.*", "erusev/parsedown": "^1.6",
"twbs/bootstrap": "^3.3", "illuminate/container": "5.5.*",
"symfony/http-foundation": "^3.3",
"psr/container": "^1.0", "psr/container": "^1.0",
"psr/log": "^1.0" "psr/log": "^1.0",
"symfony/http-foundation": "^3.3",
"twbs/bootstrap": "^3.3"
}, },
"require-dev": { "require-dev": {
"phpunit/phpunit": "^6.3" "phpunit/phpunit": "^6.3"

@ -0,0 +1,17 @@
<?php
// Application config
return [
// Service providers
'providers' => [
\Engelsystem\Logger\LoggerServiceProvider::class,
\Engelsystem\Exceptions\ExceptionsServiceProvider::class,
\Engelsystem\Config\ConfigServiceProvider::class,
\Engelsystem\Routing\RoutingServiceProvider::class,
\Engelsystem\Renderer\RendererServiceProvider::class,
\Engelsystem\Database\DatabaseServiceProvider::class,
\Engelsystem\Http\RequestServiceProvider::class,
\Engelsystem\Http\SessionServiceProvider::class,
],
];

@ -5,10 +5,10 @@
return [ return [
// MySQL-Connection Settings // MySQL-Connection Settings
'database' => [ 'database' => [
'host' => 'localhost', 'host' => env('MYSQL_HOST', (env('CI', false) ? 'mysql' : 'localhost')),
'user' => 'root', 'user' => env('MYSQL_USER', 'root'),
'pw' => '', 'pw' => env('MYSQL_PASSWORD', ''),
'db' => 'engelsystem', 'db' => env('MYSQL_DATABASE', 'engelsystem'),
], ],
// For accessing stats // For accessing stats

@ -205,7 +205,7 @@ DROP TABLE IF EXISTS `NewsComments`;
CREATE TABLE `NewsComments` ( CREATE TABLE `NewsComments` (
`ID` bigint(11) NOT NULL, `ID` bigint(11) NOT NULL,
`Refid` int(11) NOT NULL DEFAULT '0', `Refid` int(11) NOT NULL DEFAULT '0',
`Datum` datetime NOT NULL DEFAULT '0000-00-00 00:00:00', `Datum` datetime NOT NULL DEFAULT '1000-01-01 00:00:00',
`Text` text NOT NULL, `Text` text NOT NULL,
`UID` int(11) NOT NULL DEFAULT '0' `UID` int(11) NOT NULL DEFAULT '0'
) ENGINE=InnoDB DEFAULT CHARSET=utf8; ) ENGINE=InnoDB DEFAULT CHARSET=utf8;
@ -395,7 +395,7 @@ CREATE TABLE `User` (
`Sprache` char(64) NOT NULL, `Sprache` char(64) NOT NULL,
`Menu` char(1) NOT NULL DEFAULT 'L', `Menu` char(1) NOT NULL DEFAULT 'L',
`lastLogIn` int(11) NOT NULL, `lastLogIn` int(11) NOT NULL,
`CreateDate` datetime NOT NULL DEFAULT '0000-00-00 00:00:00', `CreateDate` datetime NOT NULL DEFAULT '1000-01-01 00:00:00',
`Art` varchar(30) DEFAULT NULL, `Art` varchar(30) DEFAULT NULL,
`kommentar` text, `kommentar` text,
`Hometown` varchar(255) NOT NULL DEFAULT '', `Hometown` varchar(255) NOT NULL DEFAULT '',

@ -6,4 +6,4 @@ if (!is_readable(__DIR__ . '/../vendor/autoload.php')) {
} }
// Include composer autoloader // Include composer autoloader
require_once __DIR__ . '/../vendor/autoload.php'; $loader = require __DIR__ . '/../vendor/autoload.php';

@ -0,0 +1,61 @@
<?php
use Engelsystem\Application;
use Engelsystem\Config\Config;
use Engelsystem\Exceptions\Handler as ExceptionHandler;
/**
* This file includes all needed functions, connects to the db etc.
*/
require_once __DIR__ . '/autoload.php';
/**
* Include legacy code
*/
require __DIR__ . '/includes.php';
/**
* Initialize and bootstrap the application
*/
$app = new Application(realpath(__DIR__ . DIRECTORY_SEPARATOR . '..'));
$appConfig = $app->make(Config::class);
$appConfig->set(require config_path('app.php'));
$app->bootstrap($appConfig);
/**
* Configure application
*/
date_default_timezone_set($app->get('config')->get('timezone'));
if (config('environment') == 'development') {
$errorHandler = $app->get('error.handler');
$errorHandler->setEnvironment(ExceptionHandler::ENV_DEVELOPMENT);
ini_set('display_errors', true);
error_reporting(E_ALL);
} else {
ini_set('display_errors', false);
}
/**
* Check for maintenance
*/
if ($app->get('config')->get('maintenance')) {
echo file_get_contents(__DIR__ . '/../templates/maintenance.html');
die();
}
/**
* Init translations
*/
gettext_init();
/**
* Init authorization
*/
load_auth();

@ -36,7 +36,7 @@ function gettext_init()
} }
gettext_locale(); gettext_locale();
bindtextdomain('default', realpath(__DIR__ . '/../../locale')); bindtextdomain('default', app('path.lang'));
bind_textdomain_codeset('default', 'UTF-8'); bind_textdomain_codeset('default', 'UTF-8');
textdomain('default'); textdomain('default');
} }

@ -1,115 +1,5 @@
<?php <?php
use Engelsystem\Application;
use Engelsystem\Config\Config;
use Engelsystem\Database\Db;
use Engelsystem\Exceptions\Handler as ExceptionHandler;
use Engelsystem\Http\Request;
use Engelsystem\Logger\EngelsystemLogger;
use Engelsystem\Renderer\HtmlEngine;
use Engelsystem\Renderer\Renderer;
use Engelsystem\Routing\UrlGenerator;
use Psr\Log\LoggerInterface;
use Symfony\Component\HttpFoundation\Session\Session;
use Symfony\Component\HttpFoundation\Session\Storage\MockArraySessionStorage;
use Symfony\Component\HttpFoundation\Session\Storage\NativeSessionStorage;
/**
* This file includes all needed functions, connects to the db etc.
*/
require_once __DIR__ . '/autoload.php';
/**
* Initialize the application
*/
$app = Application::getInstance();
/**
* Load configuration
*/
$config = new Config();
$app->instance('config', $config);
$config->set(require __DIR__ . '/../config/config.default.php');
if (file_exists(__DIR__ . '/../config/config.php')) {
$config->set(array_replace_recursive(
$config->get(null),
require __DIR__ . '/../config/config.php'
));
}
date_default_timezone_set($config->get('timezone'));
/**
* Initialize Request
*
* @var Request $request
*/
$request = Request::createFromGlobals();
$app->instance('request', $request);
/**
* Check for maintenance
*/
if ($config->get('maintenance')) {
echo file_get_contents(__DIR__ . '/../templates/maintenance.html');
die();
}
/**
* Register UrlGenerator
*/
$urlGenerator = new UrlGenerator();
$app->instance('routing.urlGenerator', $urlGenerator);
/**
* Initialize renderer
*/
$renderer = new Renderer();
$app->instance('renderer', $renderer);
$renderer->addRenderer(new HtmlEngine());
/**
* Register error handler
*/
$errorHandler = new ExceptionHandler();
$app->instance('error.handler', $errorHandler);
if (config('environment') == 'development') {
$errorHandler->setEnvironment(ExceptionHandler::ENV_DEVELOPMENT);
ini_set('display_errors', true);
error_reporting(E_ALL);
} else {
ini_set('display_errors', false);
}
/**
* Connect to database
*/
Db::connect(
'mysql:host=' . config('database')['host'] . ';dbname=' . config('database')['db'] . ';charset=utf8',
config('database')['user'],
config('database')['pw']
) || die('Error: Unable to connect to database');
Db::getPdo()->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
Db::getPdo()->setAttribute(PDO::ATTR_EMULATE_PREPARES, false);
/**
* Init logger
*/
$logger = new EngelsystemLogger();
$app->instance('logger', $logger);
$app->instance(LoggerInterface::class, $logger);
$app->instance(EngelsystemLogger::class, $logger);
/** /**
* Include legacy code * Include legacy code
*/ */
@ -194,17 +84,3 @@ $includeFiles = [
foreach ($includeFiles as $file) { foreach ($includeFiles as $file) {
require_once realpath($file); require_once realpath($file);
} }
/**
* Init application
*/
$sessionStorage = (PHP_SAPI != 'cli' ? new NativeSessionStorage(['cookie_httponly' => true]) : new MockArraySessionStorage());
$session = new Session($sessionStorage);
$app->instance('session', $session);
$session->start();
$request->setSession($session);
gettext_init();
load_auth();

@ -481,9 +481,10 @@ function Shift_create($shift)
`URL`, `URL`,
`PSID`, `PSID`,
`created_by_user_id`, `created_by_user_id`,
`edited_at_timestamp`,
`created_at_timestamp` `created_at_timestamp`
) )
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
', ',
[ [
$shift['shifttype_id'], $shift['shifttype_id'],
@ -495,6 +496,7 @@ function Shift_create($shift)
$shift['PSID'], $shift['PSID'],
$user['UID'], $user['UID'],
time(), time(),
time(),
] ]
); );

@ -59,7 +59,7 @@ function User_unconfirmed_AngelTypes($user)
AND `UserAngelTypes`.`supporter`=TRUE AND `UserAngelTypes`.`supporter`=TRUE
AND `AngelTypes`.`restricted`=TRUE AND `AngelTypes`.`restricted`=TRUE
AND `UnconfirmedMembers`.`confirm_user_id` IS NULL AND `UnconfirmedMembers`.`confirm_user_id` IS NULL
GROUP BY `UserAngelTypes`.`angeltype_id` GROUP BY `UserAngelTypes`.`angeltype_id`, `UserAngelTypes`.`id`
ORDER BY `AngelTypes`.`name` ORDER BY `AngelTypes`.`name`
', [$user['UID']]); ', [$user['UID']]);
} }

@ -109,7 +109,7 @@ function load_days()
$days = DB::select(' $days = DB::select('
SELECT DISTINCT DATE(FROM_UNIXTIME(`start`)) AS `id`, DATE(FROM_UNIXTIME(`start`)) AS `name` SELECT DISTINCT DATE(FROM_UNIXTIME(`start`)) AS `id`, DATE(FROM_UNIXTIME(`start`)) AS `name`
FROM `Shifts` FROM `Shifts`
ORDER BY `start` ORDER BY `id`, `name`
'); ');
$days = array_map('array_shift', $days); $days = array_map('array_shift', $days);

@ -1,5 +1,5 @@
<phpunit xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" <phpunit xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
bootstrap="./includes/autoload.php" bootstrap="./tests/autoload.php"
xsi:noNamespaceSchemaLocation="http://schema.phpunit.de/6.3/phpunit.xsd" xsi:noNamespaceSchemaLocation="http://schema.phpunit.de/6.3/phpunit.xsd"
colors="true" colors="true"
> >
@ -13,7 +13,6 @@
</testsuites> </testsuites>
<filter> <filter>
<whitelist> <whitelist>
<directory>./include/</directory>
<directory>./src/</directory> <directory>./src/</directory>
</whitelist> </whitelist>
</filter> </filter>

@ -1,6 +1,8 @@
<?php <?php
require_once realpath(__DIR__ . '/../includes/engelsystem_provider.php'); use Engelsystem\Http\Request;
require_once realpath(__DIR__ . '/../includes/engelsystem.php');
$free_pages = [ $free_pages = [
'admin_event_config', 'admin_event_config',
@ -25,6 +27,8 @@ $page = '';
$title = ''; $title = '';
$content = ''; $content = '';
/** @var Request $request */
$request = $app->get('request');
$page = $request->query->get('p'); $page = $request->query->get('p');
if (empty($page)) { if (empty($page)) {
$page = $request->path(); $page = $request->path();

@ -2,24 +2,136 @@
namespace Engelsystem; namespace Engelsystem;
use Engelsystem\Config\Config;
use Engelsystem\Container\Container; use Engelsystem\Container\Container;
use Engelsystem\Container\ServiceProvider;
use Psr\Container\ContainerInterface; use Psr\Container\ContainerInterface;
class Application extends Container 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(); $this->registerBaseBindings();
} }
protected function registerBaseBindings() protected function registerBaseBindings()
{ {
self::setInstance($this); static::setInstance($this);
Container::setInstance($this); Container::setInstance($this);
$this->instance('app', $this); $this->instance('app', $this);
$this->instance('container', $this); $this->instance('container', $this);
$this->instance(Container::class, $this); $this->instance(Container::class, $this);
$this->instance(Application::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;
} }
} }

@ -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
));
}
}
}

@ -2,115 +2,9 @@
namespace Engelsystem\Container; namespace Engelsystem\Container;
use Psr\Container\ContainerExceptionInterface; use Illuminate\Container\Container as IlluminateContainer;
use Psr\Container\ContainerInterface; 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;
}
} }

@ -1,11 +0,0 @@
<?php
namespace Engelsystem\Container;
use Exception;
use Psr\Container\ContainerExceptionInterface;
class ContainerException extends Exception implements ContainerExceptionInterface
{
}

@ -1,10 +0,0 @@
<?php
namespace Engelsystem\Container;
use Psr\Container\NotFoundExceptionInterface;
class NotFoundException extends ContainerException implements NotFoundExceptionInterface
{
}

@ -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() { }
}

@ -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');
}
}

@ -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);
}
}

@ -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);
}
}

@ -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';
}
}

@ -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');
}
}

@ -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']);
}
}

@ -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);
}
}

@ -23,6 +23,15 @@ function app($id = null)
return Application::getInstance()->get($id); return Application::getInstance()->get($id);
} }
/**
* @param string $path
* @return string
*/
function base_path($path = '')
{
return app('path') . (empty($path) ? '' : DIRECTORY_SEPARATOR . $path);
}
/** /**
* Get or set config values * Get or set config values
* *
@ -46,6 +55,30 @@ function config($key = null, $default = null)
return $config->get($key, $default); return $config->get($key, $default);
} }
/**
* @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 string $key
* @param mixed $default * @param mixed $default
@ -78,22 +111,6 @@ function session($key = null, $default = null)
return $session->get($key, $default); return $session->get($key, $default);
} }
/**
* @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 string $path
* @param array $parameters * @param array $parameters
@ -109,3 +126,19 @@ function url($path = null, $parameters = [])
return $urlGenerator->to($path, $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);
}

@ -0,0 +1,40 @@
<?php
namespace Engelsystem\Test\Feature\Database;
use Engelsystem\Application;
use Engelsystem\Config\Config;
use Engelsystem\Database\DatabaseServiceProvider;
use PHPUnit_Framework_MockObject_MockObject as MockObject;
class DatabaseServiceProviderTest extends DatabaseTest
{
/**
* @covers \Engelsystem\Database\DatabaseServiceProvider::register()
*/
public function testRegister()
{
/** @var MockObject|Config $config */
$config = $this->getMockBuilder(Config::class)
->getMock();
/** @var MockObject|Application $app */
$app = $this->getMockBuilder(Application::class)
->setMethods(['get'])
->getMock();
Application::setInstance($app);
$app->expects($this->once())
->method('get')
->with('config')
->willReturn($config);
$config->expects($this->atLeastOnce())
->method('get')
->with('database')
->willReturn($this->getDbConfig());
$serviceProvider = new DatabaseServiceProvider($app);
$serviceProvider->register();
}
}

@ -0,0 +1,25 @@
<?php
namespace Engelsystem\Test\Feature\Database;
use PHPUnit\Framework\TestCase;
abstract class DatabaseTest extends TestCase
{
/**
* Returns the database config
*
* @return string[]
*/
protected function getDbConfig()
{
$configValues = require __DIR__ . '/../../../config/config.default.php';
$configFile = __DIR__ . '/../../../config/config.php';
if (file_exists($configFile)) {
$configValues = array_replace_recursive($configValues, require $configFile);
}
return $configValues['database'];
}
}

@ -1,6 +1,6 @@
<?php <?php
namespace Engelsystem\Test\Logger; namespace Engelsystem\Test\Feature\Logger;
use Engelsystem\Logger\EngelsystemLogger; use Engelsystem\Logger\EngelsystemLogger;
use PHPUnit\Framework\TestCase; use PHPUnit\Framework\TestCase;
@ -12,7 +12,7 @@ class EngelsystemLoggerTest extends TestCase
{ {
public static function setUpBeforeClass() public static function setUpBeforeClass()
{ {
require_once __DIR__ . '/../../../includes/engelsystem_provider.php'; require_once __DIR__ . '/../../../includes/engelsystem.php';
} }
/** /**

@ -1,6 +1,6 @@
<?php <?php
namespace Engelsystem\Test; namespace Engelsystem\Test\Feature\Model;
use PHPUnit\Framework\TestCase; use PHPUnit\Framework\TestCase;
use Psr\Log\LogLevel; use Psr\Log\LogLevel;
@ -9,7 +9,7 @@ class LogEntriesModelTest extends TestCase
{ {
public static function setUpBeforeClass() public static function setUpBeforeClass()
{ {
require_once __DIR__ . '/../../../includes/engelsystem_provider.php'; require_once __DIR__ . '/../../../includes/engelsystem.php';
} }
public function testCreateLogEntry() public function testCreateLogEntry()

@ -1,6 +1,6 @@
<?php <?php
namespace Engelsystem\Test; namespace Engelsystem\Test\Feature\Model;
use PHPUnit\Framework\TestCase; use PHPUnit\Framework\TestCase;
@ -10,7 +10,7 @@ class RoomModelTest extends TestCase
public static function setUpBeforeClass() public static function setUpBeforeClass()
{ {
require_once __DIR__ . '/../../../includes/engelsystem_provider.php'; require_once __DIR__ . '/../../../includes/engelsystem.php';
} }
public function create_Room() public function create_Room()

@ -1,21 +1,25 @@
<?php <?php
namespace Engelsystem\Test\Config; namespace Engelsystem\Test\Unit;
use Engelsystem\Application; use Engelsystem\Application;
use Engelsystem\Config\Config;
use Engelsystem\Container\Container; use Engelsystem\Container\Container;
use Engelsystem\Container\ServiceProvider;
use PHPUnit\Framework\TestCase; use PHPUnit\Framework\TestCase;
use PHPUnit_Framework_MockObject_MockObject;
use Psr\Container\ContainerInterface; use Psr\Container\ContainerInterface;
use ReflectionClass;
class ApplicationTest extends TestCase class ApplicationTest extends TestCase
{ {
/** /**
* @covers \Engelsystem\Application::__construct * @covers \Engelsystem\Application::__construct
* @covers \Engelsystem\Application::registerBaseBindings * @covers \Engelsystem\Application::registerBaseBindings
*/ */
public function testConstructor() public function testConstructor()
{ {
$app = new Application(); $app = new Application('.');
$this->assertInstanceOf(Container::class, $app); $this->assertInstanceOf(Container::class, $app);
$this->assertInstanceOf(ContainerInterface::class, $app); $this->assertInstanceOf(ContainerInterface::class, $app);
@ -24,6 +28,144 @@ class ApplicationTest extends TestCase
$this->assertSame($app, $app->get(Container::class)); $this->assertSame($app, $app->get(Container::class));
$this->assertSame($app, $app->get(Application::class)); $this->assertSame($app, $app->get(Application::class));
$this->assertSame($app, $app->get(ContainerInterface::class)); $this->assertSame($app, $app->get(ContainerInterface::class));
$this->assertSame($app, Application::getInstance());
$this->assertSame($app, Container::getInstance()); $this->assertSame($app, Container::getInstance());
} }
/**
* @covers \Engelsystem\Application::setAppPath
* @covers \Engelsystem\Application::registerPaths
* @covers \Engelsystem\Application::path
*/
public function testAppPath()
{
$app = new Application();
$this->assertFalse($app->has('path'));
$app->setAppPath('.');
$this->assertTrue($app->has('path'));
$this->assertTrue($app->has('path.config'));
$this->assertTrue($app->has('path.lang'));
$this->assertEquals(realpath('.'), $app->path());
$this->assertEquals(realpath('.') . '/config', $app->get('path.config'));
$app->setAppPath('./../');
$this->assertEquals(realpath('../') . '/config', $app->get('path.config'));
}
/**
* @covers \Engelsystem\Application::register
*/
public function testRegister()
{
$app = new Application();
$serviceProvider = $this->mockServiceProvider($app, ['register']);
$serviceProvider->expects($this->once())
->method('register');
$app->register($serviceProvider);
$anotherServiceProvider = $this->mockServiceProvider($app, ['register', 'boot']);
$anotherServiceProvider->expects($this->once())
->method('register');
$anotherServiceProvider->expects($this->once())
->method('boot');
$app->bootstrap();
$app->register($anotherServiceProvider);
}
/**
* @covers \Engelsystem\Application::register
*/
public function testRegisterBoot()
{
$app = new Application();
$app->bootstrap();
$serviceProvider = $this->mockServiceProvider($app, ['register', 'boot']);
$serviceProvider->expects($this->once())
->method('register');
$serviceProvider->expects($this->once())
->method('boot');
$app->register($serviceProvider);
}
/**
* @covers \Engelsystem\Application::register
*/
public function testRegisterClassName()
{
$app = new Application();
$mockClassName = $this->getMockClass(ServiceProvider::class);
$serviceProvider = $this->getMockBuilder($mockClassName)
->setConstructorArgs([$app])
->setMethods(['register'])
->getMock();
$serviceProvider->expects($this->once())
->method('register');
$app->instance($mockClassName, $serviceProvider);
$app->register($mockClassName);
}
/**
* @covers \Engelsystem\Application::bootstrap
* @covers \Engelsystem\Application::isBooted
*/
public function testBootstrap()
{
/** @var PHPUnit_Framework_MockObject_MockObject|Application $app */
$app = $this->getMockBuilder(Application::class)
->setMethods(['register'])
->getMock();
$serviceProvider = $this->mockServiceProvider($app, ['boot']);
$serviceProvider->expects($this->once())
->method('boot');
$app->expects($this->once())
->method('register')
->with($serviceProvider);
$config = $this->getMockBuilder(Config::class)
->getMock();
$config->expects($this->once())
->method('get')
->with('providers')
->willReturn([$serviceProvider]);
$property = (new ReflectionClass($app))->getProperty('serviceProviders');
$property->setAccessible(true);
$property->setValue($app, [$serviceProvider]);
$app->bootstrap($config);
$this->assertTrue($app->isBooted());
// Run bootstrap another time to ensure that providers are registered only once
$app->bootstrap($config);
}
/**
* @param Application $app
* @param array $methods
* @return PHPUnit_Framework_MockObject_MockObject|ServiceProvider
*/
protected function mockServiceProvider(Application $app, $methods = [])
{
$serviceProvider = $this->getMockBuilder(ServiceProvider::class)
->setConstructorArgs([$app])
->setMethods($methods)
->getMockForAbstractClass();
return $serviceProvider;
}
} }

@ -0,0 +1,45 @@
<?php
namespace Engelsystem\Test\Unit\Config;
use Engelsystem\Application;
use Engelsystem\Config\Config;
use Engelsystem\Config\ConfigServiceProvider;
use Engelsystem\Test\Unit\ServiceProviderTest;
use PHPUnit_Framework_MockObject_MockObject;
class ConfigServiceProviderTest extends ServiceProviderTest
{
/**
* @covers \Engelsystem\Config\ConfigServiceProvider::register()
*/
public function testRegister()
{
/** @var PHPUnit_Framework_MockObject_MockObject|Config $config */
$config = $this->getMockBuilder(Config::class)
->getMock();
$app = $this->getApp(['make', 'instance', 'get']);
Application::setInstance($app);
$this->setExpects($app, 'make', [Config::class], $config);
$this->setExpects($app, 'instance', ['config', $config]);
$this->setExpects($app, 'get', ['path.config'], __DIR__ . '/../../../config', $this->atLeastOnce());
$this->setExpects($config, 'set', null, null, $this->exactly(2));
$this->setExpects($config, 'get', [null], []);
$configFile = __DIR__ . '/../../../config/config.php';
$configExists = file_exists($configFile);
if (!$configExists) {
file_put_contents($configFile, '<?php return [];');
}
$serviceProvider = new ConfigServiceProvider($app);
$serviceProvider->register();
if (!$configExists) {
unlink($configFile);
}
}
}

@ -1,6 +1,6 @@
<?php <?php
namespace Engelsystem\Test\Config; namespace Engelsystem\Test\Unit\Config;
use Engelsystem\Config\Config; use Engelsystem\Config\Config;
use PHPUnit\Framework\TestCase; use PHPUnit\Framework\TestCase;

@ -1,104 +0,0 @@
<?php
namespace Engelsystem\Test\Config;
use Engelsystem\Container\Container;
use PHPUnit\Framework\TestCase;
class ContainerTest extends TestCase
{
/**
* @covers \Engelsystem\Container\Container::get
*/
public function testGet()
{
$container = new Container();
$class = new class
{
};
$container->instance('foo', $class);
$this->assertSame($class, $container->get('foo'));
}
/**
* @covers \Engelsystem\Container\Container::get
* @expectedException \Engelsystem\Container\NotFoundException
*/
public function testGetException()
{
$container = new Container();
$container->get('not.registered.service');
}
/**
* @covers \Engelsystem\Container\Container::instance
* @covers \Engelsystem\Container\Container::resolve
*/
public function testInstance()
{
$container = new Container();
$class = new class
{
};
$container->instance('foo', $class);
$this->assertSame($class, $container->get('foo'));
}
/**
* @covers \Engelsystem\Container\Container::has
*/
public function testHas()
{
$container = new Container();
$this->assertFalse($container->has('test'));
$class = new class
{
};
$container->instance('test', $class);
$this->assertTrue($container->has('test'));
}
/**
* @covers \Engelsystem\Container\Container::singleton
*/
public function testSingleton()
{
$container = new Container();
$class = new class
{
};
$container->singleton('foo', $class);
$this->assertSame($class, $container->get('foo'));
$this->assertSame($class, $container->get('foo'));
}
/**
* @covers \Engelsystem\Container\Container::setInstance
* @covers \Engelsystem\Container\Container::getInstance
*/
public function testContainerSingleton()
{
// Ensure that no container has been initialized
$reflection = new \ReflectionProperty(Container::class, 'instance');
$reflection->setAccessible(true);
$reflection->setValue(null, null);
$reflection->setAccessible(false);
$container0 = new Container();
$container = Container::getInstance();
$this->assertNotSame($container0, $container);
$container1 = new Container;
Container::setInstance($container1);
$this->assertSame($container1, Container::getInstance());
}
}

@ -0,0 +1,22 @@
<?php
namespace Engelsystem\Test\Unit\Container;
use Engelsystem\Container\ServiceProvider;
use Engelsystem\Test\Unit\Container\Stub\ServiceProviderImplementation;
use Engelsystem\Test\Unit\ServiceProviderTest;
class ConfigServiceProviderTest extends ServiceProviderTest
{
/**
* @covers \Engelsystem\Container\ServiceProvider::__construct
*/
public function testRegister()
{
$app = $this->getApp();
$serviceProvider = new ServiceProviderImplementation($app);
$this->assertInstanceOf(ServiceProvider::class, $serviceProvider);
}
}

@ -0,0 +1,10 @@
<?php
namespace Engelsystem\Test\Unit\Container\Stub;
use Engelsystem\Container\ServiceProvider;
class ServiceProviderImplementation extends ServiceProvider
{
}

@ -0,0 +1,37 @@
<?php
namespace Engelsystem\Test\Unit\Database;
use Engelsystem\Config\Config;
use Engelsystem\Database\DatabaseServiceProvider;
use Engelsystem\Test\Unit\ServiceProviderTest;
use Exception;
use PHPUnit_Framework_MockObject_MockObject;
class DatabaseServiceProviderTest extends ServiceProviderTest
{
/**
* @covers \Engelsystem\Database\DatabaseServiceProvider::register()
* @covers \Engelsystem\Database\DatabaseServiceProvider::exitOnError()
*/
public function testRegister()
{
/** @var PHPUnit_Framework_MockObject_MockObject|Config $config */
$config = $this->getMockBuilder(Config::class)
->getMock();
$app = $this->getApp(['get']);
$this->setExpects($app, 'get', ['config'], $config);
$this->setExpects($config, 'get', ['database'], [
'host' => 'localhost',
'db' => 'database',
'user' => 'user',
'pw' => 'password',
], $this->atLeastOnce());
$this->expectException(Exception::class);
$serviceProvider = new DatabaseServiceProvider($app);
$serviceProvider->register();
}
}

@ -0,0 +1,192 @@
<?php
namespace Engelsystem\Test\Unit\Database;
use Engelsystem\Database\Db;
use PDO;
use PDOStatement;
use PHPUnit\Framework\TestCase;
use ReflectionObject;
use Throwable;
class DbTest extends TestCase
{
/**
* @covers \Engelsystem\Database\Db::connect()
*/
public function testConnect()
{
$result = Db::connect('mysql:host=localhost;dbname=someTestDatabaseThatDoesNotExist;charset=utf8');
$this->assertFalse($result);
$result = Db::connect('sqlite::memory:');
$this->assertTrue($result);
}
/**
* @covers \Engelsystem\Database\Db::query()
*/
public function testQuery()
{
$stm = Db::query('SELECT * FROM test_data');
$this->assertEquals('00000', $stm->errorCode());
$stm = Db::query('SELECT * FROM test_data WHERE id = ?', [4]);
$this->assertEquals('00000', $stm->errorCode());
}
/**
* @covers \Engelsystem\Database\Db::unprepared()
*/
public function testUnprepared()
{
$return = Db::unprepared('SELECT * FROM test_data WHERE id = 3');
$this->assertTrue($return);
}
/**
* @covers \Engelsystem\Database\Db::select()
*/
public function testSelect()
{
$return = Db::select('SELECT * FROM test_data');
$this->assertTrue(count($return) > 3);
$return = Db::select('SELECT * FROM test_data WHERE id = ?', [2]);
$this->assertCount(1, $return);
}
/**
* @covers \Engelsystem\Database\Db::selectOne()
*/
public function testSelectOne()
{
$return = Db::selectOne('SELECT * FROM test_data');
$this->assertEquals('Foo', $return['data']);
$return = Db::selectOne('SELECT * FROM test_data WHERE id = -1');
$this->assertEmpty($return);
$return = Db::selectOne('SELECT * FROM test_data WHERE id = ?', [3]);
$return = array_pop($return);
$this->assertTrue(!is_array($return));
}
/**
* @covers \Engelsystem\Database\Db::insert()
*/
public function testInsert()
{
$count = Db::insert("INSERT INTO test_data (id, data) VALUES (5, 'Some random text'), (6, 'another text')");
$this->assertEquals(2, $count);
$count = Db::insert('INSERT INTO test_data(id, data) VALUES (:id, :alias)', ['id' => 7, 'alias' => 'Blafoo']);
$this->assertEquals(1, $count);
}
/**
* @covers \Engelsystem\Database\Db::update()
*/
public function testUpdate()
{
$count = Db::update("UPDATE test_data SET data='NOPE' WHERE data LIKE '%Replaceme%'");
$this->assertEquals(3, $count);
$count = Db::update("UPDATE test_data SET data=? WHERE data LIKE '%NOPE%'", ['Some random text!']);
$this->assertEquals(3, $count);
}
/**
* @covers \Engelsystem\Database\Db::delete()
*/
public function testDelete()
{
$count = Db::delete('DELETE FROM test_data WHERE id=1');
$this->assertEquals(1, $count);
$count = Db::delete('DELETE FROM test_data WHERE data LIKE ?', ['%Replaceme%']);
$this->assertEquals(3, $count);
}
/**
* @covers \Engelsystem\Database\Db::statement()
*/
public function testStatement()
{
$return = Db::statement('SELECT * FROM test_data WHERE id = 3');
$this->assertTrue($return);
$return = Db::statement('SELECT * FROM test_data WHERE id = ?', [2]);
$this->assertTrue($return);
}
/**
* @covers \Engelsystem\Database\Db::getError()
*/
public function testGetError()
{
try {
Db::statement('foo');
} catch (Throwable $e) {
}
$error = Db::getError();
$this->assertTrue(is_array($error));
$this->assertEquals('near "foo": syntax error', $error[2]);
$db = new Db();
$refObject = new ReflectionObject($db);
$refProperty = $refObject->getProperty('stm');
$refProperty->setAccessible(true);
$refProperty->setValue(null, null);
$error = Db::getError();
$this->assertEquals([-1, null, null], $error);
}
/**
* @covers \Engelsystem\Database\Db::getPdo()
*/
public function testGetPdo()
{
$pdo = Db::getPdo();
$this->assertInstanceOf(PDO::class, $pdo);
}
/**
* @covers \Engelsystem\Database\Db::getStm()
*/
public function testGetStm()
{
$stm = Db::getStm();
$this->assertInstanceOf(PDOStatement::class, $stm);
}
/**
* Setup in memory database
*/
protected function setUp()
{
Db::connect('sqlite::memory:');
Db::getPdo()->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
Db::query(
'
CREATE TABLE test_data(
id INT PRIMARY KEY NOT NULL,
data TEXT NOT NULL
);
');
Db::query('CREATE UNIQUE INDEX test_data_id_uindex ON test_data (id);');
Db::insert("
INSERT INTO test_data (id, data)
VALUES
(1, 'Foo'),
(2, 'Bar'),
(3, 'Batz'),
(4, 'Lorem ipsum dolor sit'),
(10, 'Replaceme ipsum dolor sit amet'),
(11, 'Lorem Replaceme dolor sit amet'),
(12, 'Lorem ipsum Replaceme sit amet')
;");
}
}

@ -0,0 +1,29 @@
<?php
namespace Engelsystem\Test\Unit\Exceptions;
use Engelsystem\Exceptions\ExceptionsServiceProvider;
use Engelsystem\Exceptions\Handler as ExceptionHandler;
use Engelsystem\Test\Unit\ServiceProviderTest;
use PHPUnit_Framework_MockObject_MockObject;
class ExceptionsServiceProviderTest extends ServiceProviderTest
{
/**
* @covers \Engelsystem\Exceptions\ExceptionsServiceProvider::register()
*/
public function testRegister()
{
/** @var PHPUnit_Framework_MockObject_MockObject|ExceptionHandler $exceptionHandler */
$exceptionHandler = $this->getMockBuilder(ExceptionHandler::class)
->getMock();
$app = $this->getApp();
$this->setExpects($app, 'make', [ExceptionHandler::class], $exceptionHandler);
$this->setExpects($app, 'instance', ['error.handler', $exceptionHandler]);
$serviceProvider = new ExceptionsServiceProvider($app);
$serviceProvider->register();
}
}

@ -1,6 +1,6 @@
<?php <?php
namespace Engelsystem\Test\Config; namespace Engelsystem\Test\Unit;
use Engelsystem\Application; use Engelsystem\Application;
use Engelsystem\Config\Config; use Engelsystem\Config\Config;
@ -9,6 +9,7 @@ use Engelsystem\Http\Request;
use Engelsystem\Renderer\Renderer; use Engelsystem\Renderer\Renderer;
use Engelsystem\Routing\UrlGenerator; use Engelsystem\Routing\UrlGenerator;
use PHPUnit\Framework\TestCase; use PHPUnit\Framework\TestCase;
use PHPUnit_Framework_MockObject_MockObject as MockObject;
use Symfony\Component\HttpFoundation\Session\Session; use Symfony\Component\HttpFoundation\Session\Session;
class HelpersTest extends TestCase class HelpersTest extends TestCase
@ -28,6 +29,25 @@ class HelpersTest extends TestCase
$this->assertEquals($class, app('some.name')); $this->assertEquals($class, app('some.name'));
} }
/**
* @covers \base_path()
*/
public function testBasePath()
{
/** @var MockObject|Application $app */
$app = $this->getMockBuilder(Container::class)
->getMock();
Application::setInstance($app);
$app->expects($this->atLeastOnce())
->method('get')
->with('path')
->willReturn('/foo/bar');
$this->assertEquals('/foo/bar', base_path());
$this->assertEquals('/foo/bar/bla-foo.conf', base_path('bla-foo.conf'));
}
/** /**
* @covers \config * @covers \config
*/ */
@ -53,6 +73,39 @@ class HelpersTest extends TestCase
$this->assertEquals(['user' => 'FooBar'], config('mail')); $this->assertEquals(['user' => 'FooBar'], config('mail'));
} }
/**
* @covers \config_path()
*/
public function testConfigPath()
{
/** @var MockObject|Application $app */
$app = $this->getMockBuilder(Container::class)
->getMock();
Application::setInstance($app);
$app->expects($this->atLeastOnce())
->method('get')
->with('path.config')
->willReturn('/foo/conf');
$this->assertEquals('/foo/conf', config_path());
$this->assertEquals('/foo/conf/bar.php', config_path('bar.php'));
}
/**
* @covers \env
*/
public function testEnv()
{
putenv('envTestVar=someContent');
$env = env('envTestVar');
$this->assertEquals('someContent', $env);
$env = env('someRandomEnvVarThatShouldNeverExist', 'someDefaultValue');
$this->assertEquals('someDefaultValue', $env);
}
/** /**
* @covers \request * @covers \request
*/ */
@ -132,7 +185,7 @@ class HelpersTest extends TestCase
/** /**
* @param string $alias * @param string $alias
* @param object $object * @param object $object
* @return Application|\PHPUnit_Framework_MockObject_MockObject * @return Application|MockObject
*/ */
protected function getAppMock($alias, $object) protected function getAppMock($alias, $object)
{ {

@ -0,0 +1,29 @@
<?php
namespace Engelsystem\Test\Unit\Http;
use Engelsystem\Http\Request;
use Engelsystem\Http\RequestServiceProvider;
use Engelsystem\Test\Unit\ServiceProviderTest;
use PHPUnit_Framework_MockObject_MockObject as MockObject;
class RequestServiceProviderTest extends ServiceProviderTest
{
/**
* @covers \Engelsystem\Http\RequestServiceProvider::register()
*/
public function testRegister()
{
/** @var MockObject|Request $request */
$request = $this->getMockBuilder(Request::class)
->getMock();
$app = $this->getApp(['call', 'instance']);
$this->setExpects($app, 'call', [[Request::class, 'createFromGlobals']], $request);
$this->setExpects($app, 'instance', ['request', $request]);
$serviceProvider = new RequestServiceProvider($app);
$serviceProvider->register();
}
}

@ -0,0 +1,98 @@
<?php
namespace Engelsystem\Test\Unit\Http;
use Engelsystem\Http\Request;
use PHPUnit\Framework\TestCase;
use PHPUnit_Framework_MockObject_MockObject as MockObject;
class RequestTest extends TestCase
{
/**
* @covers \Engelsystem\Http\Request::postData
*/
public function testPostData()
{
$request = new Request(
['foo' => 'I\'m a test!'],
['foo' => 'bar']
);
$this->assertEquals('bar', $request->postData('foo'));
$this->assertEquals('LoremIpsum', $request->postData('test-key', 'LoremIpsum'));
}
/**
* @covers \Engelsystem\Http\Request::input
*/
public function testInput()
{
$request = new Request(
['foo' => 'I\'m a test!'],
['foo' => 'bar']
);
$this->assertEquals('I\'m a test!', $request->input('foo'));
$this->assertEquals('LoremIpsum', $request->input('test-key', 'LoremIpsum'));
}
/**
* @covers \Engelsystem\Http\Request::has
*/
public function testHas()
{
$request = new Request([
'foo' => 'I\'m a test!',
'bar' => '',
]);
$this->assertTrue($request->has('foo'));
$this->assertFalse($request->has('bar'));
}
/**
* @covers \Engelsystem\Http\Request::path
*/
public function testPath()
{
/** @var MockObject|Request $request */
$request = $this
->getMockBuilder(Request::class)
->setMethods(['getPathInfo'])
->getMock();
$request
->expects($this->atLeastOnce())
->method('getPathInfo')
->willReturnOnConsecutiveCalls(
'/foo',
'/'
);
$this->assertEquals('foo', $request->path());
$this->assertEquals('/', $request->path());
}
/**
* @covers \Engelsystem\Http\Request::url
*/
public function testUrl()
{
/** @var MockObject|Request $request */
$request = $this
->getMockBuilder(Request::class)
->setMethods(['getUri'])
->getMock();
$request
->expects($this->atLeastOnce())
->method('getUri')
->willReturnOnConsecutiveCalls(
'http://foo.bar/bla/foo/',
'https://lorem.ipsum/dolor/sit?amet=consetetur&sadipscing=elitr'
);
$this->assertEquals('http://foo.bar/bla/foo', $request->url());
$this->assertEquals('https://lorem.ipsum/dolor/sit', $request->url());
}
}

@ -0,0 +1,126 @@
<?php
namespace Engelsystem\Test\Unit\Http;
use Engelsystem\Http\Request;
use Engelsystem\Http\SessionServiceProvider;
use Engelsystem\Test\Unit\ServiceProviderTest;
use PHPUnit_Framework_MockObject_MockObject as MockObject;
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 as StorageInterface;
class SessionServiceProviderTest extends ServiceProviderTest
{
/**
* @covers \Engelsystem\Http\SessionServiceProvider::register()
* @covers \Engelsystem\Http\SessionServiceProvider::getSessionStorage()
*/
public function testRegister()
{
$app = $this->getApp(['make', 'instance', 'bind', 'get']);
$sessionStorage = $this->getMockForAbstractClass(StorageInterface::class);
$sessionStorage2 = $this->getMockForAbstractClass(StorageInterface::class);
$session = $this->getSessionMock();
$request = $this->getRequestMock();
/** @var MockObject|SessionServiceProvider $serviceProvider */
$serviceProvider = $this->getMockBuilder(SessionServiceProvider::class)
->setConstructorArgs([$app])
->setMethods(['isCli'])
->getMock();
$serviceProvider->expects($this->exactly(2))
->method('isCli')
->willReturnOnConsecutiveCalls(true, false);
$app->expects($this->exactly(4))
->method('make')
->withConsecutive(
[MockArraySessionStorage::class],
[Session::class],
[NativeSessionStorage::class, ['options' => ['cookie_httponly' => true]]],
[Session::class]
)
->willReturnOnConsecutiveCalls(
$sessionStorage,
$session,
$sessionStorage2,
$session
);
$app->expects($this->atLeastOnce())
->method('instance')
->withConsecutive(
['session.storage', $sessionStorage],
['session', $session]
);
$this->setExpects($app, 'bind', [StorageInterface::class, 'session.storage'], null, $this->atLeastOnce());
$this->setExpects($app, 'get', ['request'], $request, $this->atLeastOnce());
$this->setExpects($request, 'setSession', [$session], null, $this->atLeastOnce());
$this->setExpects($session, 'start', null, null, $this->atLeastOnce());
$serviceProvider->register();
$serviceProvider->register();
}
/**
* @covers \Engelsystem\Http\SessionServiceProvider::isCli()
*/
public function testIsCli()
{
$app = $this->getApp(['make', 'instance', 'bind', 'get']);
$sessionStorage = $this->getMockForAbstractClass(StorageInterface::class);
$session = $this->getSessionMock();
$request = $this->getRequestMock();
$app->expects($this->exactly(2))
->method('make')
->withConsecutive(
[MockArraySessionStorage::class],
[Session::class]
)
->willReturnOnConsecutiveCalls(
$sessionStorage,
$session
);
$app->expects($this->exactly(2))
->method('instance')
->withConsecutive(
['session.storage', $sessionStorage],
['session', $session]
);
$this->setExpects($app, 'bind', [StorageInterface::class, 'session.storage']);
$this->setExpects($app, 'get', ['request'], $request);
$this->setExpects($request, 'setSession', [$session]);
$this->setExpects($session, 'start');
$serviceProvider = new SessionServiceProvider($app);
$serviceProvider->register();
}
/**
* @return MockObject
*/
private function getSessionMock()
{
return $this->getMockBuilder(Session::class)
->setMethods(['start'])
->getMock();
}
/**
* @return MockObject
*/
private function getRequestMock()
{
return $this->getMockBuilder(Request::class)
->setMethods(['setSession'])
->getMock();
}
}

@ -0,0 +1,37 @@
<?php
namespace Engelsystem\Test\Unit\Logger;
use Engelsystem\Logger\EngelsystemLogger;
use Engelsystem\Logger\LoggerServiceProvider;
use Engelsystem\Test\Unit\ServiceProviderTest;
use PHPUnit_Framework_MockObject_MockObject;
use Psr\Log\LoggerInterface;
class LoggerServiceProviderTest extends ServiceProviderTest
{
/**
* @covers \Engelsystem\Logger\LoggerServiceProvider::register()
*/
public function testRegister()
{
/** @var PHPUnit_Framework_MockObject_MockObject|EngelsystemLogger $logger */
$logger = $this->getMockBuilder(EngelsystemLogger::class)
->getMock();
$app = $this->getApp(['make', 'instance', 'bind']);
$this->setExpects($app, 'make', [EngelsystemLogger::class], $logger);
$this->setExpects($app, 'instance', ['logger', $logger]);
$app->expects($this->atLeastOnce())
->method('bind')
->withConsecutive(
[LoggerInterface::class, 'logger'],
[EngelsystemLogger::class, 'logger']
);
$serviceProvider = new LoggerServiceProvider($app);
$serviceProvider->register();
}
}

@ -1,6 +1,6 @@
<?php <?php
namespace Engelsystem\Test\Config; namespace Engelsystem\Test\Unit\Renderer;
use Engelsystem\Renderer\HtmlEngine; use Engelsystem\Renderer\HtmlEngine;
use PHPUnit\Framework\TestCase; use PHPUnit\Framework\TestCase;

@ -0,0 +1,81 @@
<?php
namespace Engelsystem\Test\Unit\Renderer;
use Engelsystem\Renderer\EngineInterface;
use Engelsystem\Renderer\HtmlEngine;
use Engelsystem\Renderer\Renderer;
use Engelsystem\Renderer\RendererServiceProvider;
use Engelsystem\Test\Unit\ServiceProviderTest;
use PHPUnit_Framework_MockObject_MockObject;
class RendererServiceProviderTest extends ServiceProviderTest
{
/**
* @covers \Engelsystem\Renderer\RendererServiceProvider::register()
* @covers \Engelsystem\Renderer\RendererServiceProvider::registerRenderer()
* @covers \Engelsystem\Renderer\RendererServiceProvider::registerHtmlEngine()
*/
public function testRegister()
{
/** @var PHPUnit_Framework_MockObject_MockObject|Renderer $renderer */
$renderer = $this->getMockBuilder(Renderer::class)
->getMock();
/** @var PHPUnit_Framework_MockObject_MockObject|HtmlEngine $htmlEngine */
$htmlEngine = $this->getMockBuilder(HtmlEngine::class)
->getMock();
$app = $this->getApp(['make', 'instance', 'tag']);
$app->expects($this->exactly(2))
->method('make')
->withConsecutive(
[Renderer::class],
[HtmlEngine::class]
)->willReturnOnConsecutiveCalls(
$renderer,
$htmlEngine
);
$app->expects($this->exactly(2))
->method('instance')
->withConsecutive(
['renderer', $renderer],
['renderer.htmlEngine', $htmlEngine]
);
$this->setExpects($app, 'tag', ['renderer.htmlEngine', ['renderer.engine']]);
$serviceProvider = new RendererServiceProvider($app);
$serviceProvider->register();
}
/**
* @covers \Engelsystem\Renderer\RendererServiceProvider::boot()
*/
public function testBoot()
{
/** @var PHPUnit_Framework_MockObject_MockObject|Renderer $renderer */
$renderer = $this->getMockBuilder(Renderer::class)
->getMock();
/** @var PHPUnit_Framework_MockObject_MockObject|EngineInterface $engine1 */
$engine1 = $this->getMockForAbstractClass(EngineInterface::class);
/** @var PHPUnit_Framework_MockObject_MockObject|EngineInterface $engine2 */
$engine2 = $this->getMockForAbstractClass(EngineInterface::class);
$app = $this->getApp(['get', 'tagged']);
$engines = [$engine1, $engine2];
$this->setExpects($app, 'get', ['renderer'], $renderer);
$this->setExpects($app, 'tagged', ['renderer.engine'], $engines);
$invocation = $renderer
->expects($this->exactly(count($engines)))
->method('addRenderer');
call_user_func_array([$invocation, 'withConsecutive'], $engines);
$serviceProvider = new RendererServiceProvider($app);
$serviceProvider->boot();
}
}

@ -1,10 +1,11 @@
<?php <?php
namespace Engelsystem\Test\Config; namespace Engelsystem\Test\Unit\Renderer;
use Engelsystem\Renderer\EngineInterface; use Engelsystem\Renderer\EngineInterface;
use Engelsystem\Renderer\Renderer; use Engelsystem\Renderer\Renderer;
use PHPUnit\Framework\TestCase; use PHPUnit\Framework\TestCase;
use PHPUnit_Framework_MockObject_MockObject as MockObject;
use Psr\Log\LoggerInterface; use Psr\Log\LoggerInterface;
class RendererTest extends TestCase class RendererTest extends TestCase
@ -13,6 +14,7 @@ class RendererTest extends TestCase
{ {
$renderer = new Renderer(); $renderer = new Renderer();
/** @var MockObject|EngineInterface $nullRenderer */
$nullRenderer = $this->getMockForAbstractClass(EngineInterface::class); $nullRenderer = $this->getMockForAbstractClass(EngineInterface::class);
$nullRenderer->expects($this->atLeastOnce()) $nullRenderer->expects($this->atLeastOnce())
@ -20,6 +22,7 @@ class RendererTest extends TestCase
->willReturn(false); ->willReturn(false);
$renderer->addRenderer($nullRenderer); $renderer->addRenderer($nullRenderer);
/** @var MockObject|EngineInterface $mockRenderer */
$mockRenderer = $this->getMockForAbstractClass(EngineInterface::class); $mockRenderer = $this->getMockForAbstractClass(EngineInterface::class);
$mockRenderer->expects($this->atLeastOnce()) $mockRenderer->expects($this->atLeastOnce())
@ -42,6 +45,7 @@ class RendererTest extends TestCase
{ {
$renderer = new Renderer(); $renderer = new Renderer();
/** @var MockObject|LoggerInterface $loggerMock */
$loggerMock = $this->getMockForAbstractClass(LoggerInterface::class); $loggerMock = $this->getMockForAbstractClass(LoggerInterface::class);
$loggerMock $loggerMock
->expects($this->once()) ->expects($this->once())

@ -0,0 +1,29 @@
<?php
namespace Engelsystem\Test\Unit\Routing;
use Engelsystem\Routing\RoutingServiceProvider;
use Engelsystem\Routing\UrlGenerator;
use Engelsystem\Test\Unit\ServiceProviderTest;
use PHPUnit_Framework_MockObject_MockObject;
class RoutingServiceProviderTest extends ServiceProviderTest
{
/**
* @covers \Engelsystem\Routing\RoutingServiceProvider::register()
*/
public function testRegister()
{
/** @var PHPUnit_Framework_MockObject_MockObject|UrlGenerator $urlGenerator */
$urlGenerator = $this->getMockBuilder(UrlGenerator::class)
->getMock();
$app = $this->getApp();
$this->setExpects($app, 'make', [UrlGenerator::class], $urlGenerator);
$this->setExpects($app, 'instance', ['routing.urlGenerator', $urlGenerator]);
$serviceProvider = new RoutingServiceProvider($app);
$serviceProvider->register();
}
}

@ -1,6 +1,6 @@
<?php <?php
namespace Engelsystem\Test\Config; namespace Engelsystem\Test\Unit\Routing;
use Engelsystem\Application; use Engelsystem\Application;
use Engelsystem\Container\Container; use Engelsystem\Container\Container;

@ -0,0 +1,50 @@
<?php
namespace Engelsystem\Test\Unit;
use Engelsystem\Application;
use PHPUnit\Framework\TestCase;
use PHPUnit_Framework_MockObject_Matcher_InvokedRecorder as InvokedRecorder;
use PHPUnit_Framework_MockObject_MockObject as MockObject;
abstract class ServiceProviderTest extends TestCase
{
/**
* @param array $methods
* @return Application|MockObject
*/
protected function getApp($methods = ['make', 'instance'])
{
/** @var MockObject|Application $app */
return $this->getMockBuilder(Application::class)
->setMethods($methods)
->getMock();
}
/**
* @param MockObject $object
* @param string $method
* @param array $arguments
* @param mixed $return
* @param InvokedRecorder $times
*/
protected function setExpects($object, $method, $arguments = null, $return = null, $times = null)
{
if (is_null($times)) {
$times = $this->once();
}
$invocation = $object->expects($times)
->method($method);
if (is_null($arguments)) {
$invocation->withAnyParameters();
} else {
call_user_func_array([$invocation, 'with'], $arguments);
}
if (!is_null($return)) {
$invocation->willReturn($return);
}
}
}

@ -0,0 +1,8 @@
<?php
use Composer\Autoload\ClassLoader;
require_once __DIR__ . '/../includes/autoload.php';
/** @var $loader ClassLoader */
$loader->addPsr4('Engelsystem\\Test\\', __DIR__ . '/');
Loading…
Cancel
Save