Added/updated comments
This commit is contained in:
parent
9bf9bd2823
commit
905d91d6ed
11
README.md
11
README.md
|
@ -28,7 +28,7 @@ The Engelsystem may be installed manually or by using the provided [docker setup
|
||||||
* MySQL-Server >= 5.7.8 or MariaDB-Server >= 10.2.2
|
* MySQL-Server >= 5.7.8 or MariaDB-Server >= 10.2.2
|
||||||
* Webserver, i.e. lighttpd, nginx, or Apache
|
* Webserver, i.e. lighttpd, nginx, or Apache
|
||||||
|
|
||||||
From experience 2 cores and 2GB ram are roughly enough for about 1000 Angels (~700 arrived + 500 arrived but not working) during an event.
|
From previous experience, 2 cores and 2GB ram are roughly enough for up to 1000 Angels (~700 arrived + 500 arrived but not working) during an event.
|
||||||
|
|
||||||
### Download
|
### Download
|
||||||
* Go to the [Releases](https://github.com/engelsystem/engelsystem/releases) page and download the latest stable release file.
|
* Go to the [Releases](https://github.com/engelsystem/engelsystem/releases) page and download the latest stable release file.
|
||||||
|
@ -42,7 +42,14 @@ From experience 2 cores and 2GB ram are roughly enough for about 1000 Angels (~7
|
||||||
* Recommended: Directory Listing should be disabled.
|
* Recommended: Directory Listing should be disabled.
|
||||||
* There must be a MySQL database set up with a user who has full rights to that database.
|
* There must be a MySQL database set up with a user who has full rights to that database.
|
||||||
* If necessary, create a `config/config.php` to override values from `config/config.default.php`.
|
* If necessary, create a `config/config.php` to override values from `config/config.default.php`.
|
||||||
* To disable/remove values from the `themes`, `tshirt_sizes`, `headers`, `header_items`, `footer_items`, or `locales` lists, set the value of the entry to `null`.
|
* To disable/remove values from the following lists, set the value of the entry to `null`:
|
||||||
|
* `themes`
|
||||||
|
* `tshirt_sizes`
|
||||||
|
* `headers`
|
||||||
|
* `header_items`
|
||||||
|
* `footer_items`
|
||||||
|
* `locales`
|
||||||
|
* `contact_options`
|
||||||
* To import the database, the `bin/migrate` script has to be run. If you can't execute scripts, you can use the `initial-install.sql` file from the release zip.
|
* To import the database, the `bin/migrate` script has to be run. If you can't execute scripts, you can use the `initial-install.sql` file from the release zip.
|
||||||
* In the browser, login with credentials `admin` : `asdfasdf` and change the password.
|
* In the browser, login with credentials `admin` : `asdfasdf` and change the password.
|
||||||
|
|
||||||
|
|
|
@ -128,11 +128,14 @@ function User_get_shifts_sum_query()
|
||||||
'
|
'
|
||||||
COALESCE(SUM(
|
COALESCE(SUM(
|
||||||
(1 + (
|
(1 + (
|
||||||
|
/* Starts during night */
|
||||||
HOUR(shifts.start) >= %1$d AND HOUR(shifts.start) < %2$d
|
HOUR(shifts.start) >= %1$d AND HOUR(shifts.start) < %2$d
|
||||||
|
/* Ends during night */
|
||||||
OR (
|
OR (
|
||||||
HOUR(shifts.end) > %1$d
|
HOUR(shifts.end) > %1$d
|
||||||
|| HOUR(shifts.end) = %1$d AND MINUTE(shifts.end) > 0
|
|| HOUR(shifts.end) = %1$d AND MINUTE(shifts.end) > 0
|
||||||
) AND HOUR(shifts.end) <= %2$d
|
) AND HOUR(shifts.end) <= %2$d
|
||||||
|
/* Starts before and ends after night */
|
||||||
OR HOUR(shifts.start) <= %1$d AND HOUR(shifts.end) >= %2$d
|
OR HOUR(shifts.start) <= %1$d AND HOUR(shifts.end) >= %2$d
|
||||||
))
|
))
|
||||||
* (UNIX_TIMESTAMP(shifts.end) - UNIX_TIMESTAMP(shifts.start))
|
* (UNIX_TIMESTAMP(shifts.end) - UNIX_TIMESTAMP(shifts.start))
|
||||||
|
|
|
@ -6,6 +6,7 @@ use Engelsystem\Application;
|
||||||
use Engelsystem\Middleware\Dispatcher;
|
use Engelsystem\Middleware\Dispatcher;
|
||||||
use Psr\Http\Message\ServerRequestInterface;
|
use Psr\Http\Message\ServerRequestInterface;
|
||||||
|
|
||||||
|
// Include app bootstrapping
|
||||||
require_once realpath(__DIR__ . '/../includes/engelsystem.php');
|
require_once realpath(__DIR__ . '/../includes/engelsystem.php');
|
||||||
|
|
||||||
/** @var Application $app */
|
/** @var Application $app */
|
||||||
|
@ -18,4 +19,5 @@ $middleware = $app->getMiddleware();
|
||||||
$dispatcher = new Dispatcher($middleware);
|
$dispatcher = new Dispatcher($middleware);
|
||||||
$dispatcher->setContainer($app);
|
$dispatcher->setContainer($app);
|
||||||
|
|
||||||
|
// Handle the request
|
||||||
$dispatcher->handle($request);
|
$dispatcher->handle($request);
|
||||||
|
|
|
@ -14,9 +14,16 @@ class ConfigServiceProvider extends ServiceProvider
|
||||||
{
|
{
|
||||||
protected array $configFiles = ['app.php', 'config.default.php', 'config.php'];
|
protected array $configFiles = ['app.php', 'config.default.php', 'config.php'];
|
||||||
|
|
||||||
# remember to update ConfigServiceProviderTest, config.default.php, and README.md
|
// Remember to update ConfigServiceProviderTest, config.default.php, and README.md
|
||||||
protected array $configVarsToPruneNulls
|
protected array $configVarsToPruneNulls = [
|
||||||
= ['themes', 'tshirt_sizes', 'headers', 'header_items', 'footer_items', 'locales', 'contact_options'];
|
'themes',
|
||||||
|
'tshirt_sizes',
|
||||||
|
'headers',
|
||||||
|
'header_items',
|
||||||
|
'footer_items',
|
||||||
|
'locales',
|
||||||
|
'contact_options',
|
||||||
|
];
|
||||||
|
|
||||||
public function __construct(Application $app, protected ?EventConfig $eventConfig = null)
|
public function __construct(Application $app, protected ?EventConfig $eventConfig = null)
|
||||||
{
|
{
|
||||||
|
@ -29,6 +36,7 @@ class ConfigServiceProvider extends ServiceProvider
|
||||||
$this->app->instance(Config::class, $config);
|
$this->app->instance(Config::class, $config);
|
||||||
$this->app->instance('config', $config);
|
$this->app->instance('config', $config);
|
||||||
|
|
||||||
|
// Load configuration from files
|
||||||
foreach ($this->configFiles as $file) {
|
foreach ($this->configFiles as $file) {
|
||||||
$file = $this->getConfigPath($file);
|
$file = $this->getConfigPath($file);
|
||||||
|
|
||||||
|
@ -47,6 +55,7 @@ class ConfigServiceProvider extends ServiceProvider
|
||||||
throw new Exception('Configuration not found');
|
throw new Exception('Configuration not found');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Prune values with null to remove them
|
||||||
foreach ($this->configVarsToPruneNulls as $key) {
|
foreach ($this->configVarsToPruneNulls as $key) {
|
||||||
$config->set($key, array_filter($config->get($key), function ($v) {
|
$config->set($key, array_filter($config->get($key), function ($v) {
|
||||||
return !is_null($v);
|
return !is_null($v);
|
||||||
|
|
|
@ -98,6 +98,7 @@ class LocationsController extends BaseController
|
||||||
$location->neededAngelTypes()->getQuery()->delete();
|
$location->neededAngelTypes()->getQuery()->delete();
|
||||||
$angelsInfo = '';
|
$angelsInfo = '';
|
||||||
|
|
||||||
|
// Associate angel types with the room
|
||||||
foreach ($angelTypes as $angelType) {
|
foreach ($angelTypes as $angelType) {
|
||||||
$count = $data['angel_type_' . $angelType->id];
|
$count = $data['angel_type_' . $angelType->id];
|
||||||
if (!$count) {
|
if (!$count) {
|
||||||
|
|
|
@ -113,6 +113,7 @@ class ShiftTypesController extends BaseController
|
||||||
$shiftType->save();
|
$shiftType->save();
|
||||||
$shiftType->neededAngelTypes()->delete();
|
$shiftType->neededAngelTypes()->delete();
|
||||||
|
|
||||||
|
// Associate angel types with the shift type
|
||||||
$angelsInfo = '';
|
$angelsInfo = '';
|
||||||
foreach ($angelTypes as $angelType) {
|
foreach ($angelTypes as $angelType) {
|
||||||
$count = $data['angel_type_' . $angelType->id];
|
$count = $data['angel_type_' . $angelType->id];
|
||||||
|
|
|
@ -69,6 +69,7 @@ class UserWorkLogController extends BaseController
|
||||||
'comment' => 'required|max:200',
|
'comment' => 'required|max:200',
|
||||||
]);
|
]);
|
||||||
|
|
||||||
|
// Search / create worklog
|
||||||
if (isset($worklogId)) {
|
if (isset($worklogId)) {
|
||||||
$worklog = $this->worklog->findOrFail((int) $worklogId);
|
$worklog = $this->worklog->findOrFail((int) $worklogId);
|
||||||
|
|
||||||
|
|
|
@ -70,6 +70,7 @@ class FeedController extends BaseController
|
||||||
$shift = $entry->shift;
|
$shift = $entry->shift;
|
||||||
// Data required for the Fahrplan app integration https://github.com/johnjohndoe/engelsystem
|
// Data required for the Fahrplan app integration https://github.com/johnjohndoe/engelsystem
|
||||||
// See engelsystem-base/src/main/kotlin/info/metadude/kotlin/library/engelsystem/models/Shift.kt
|
// See engelsystem-base/src/main/kotlin/info/metadude/kotlin/library/engelsystem/models/Shift.kt
|
||||||
|
// Explicitly typecasts used to stay consistent
|
||||||
// ! All attributes not defined in $data might change at any time !
|
// ! All attributes not defined in $data might change at any time !
|
||||||
$data = [
|
$data = [
|
||||||
// Name of the shift (type)
|
// Name of the shift (type)
|
||||||
|
|
|
@ -171,7 +171,7 @@ class MessagesController extends BaseController
|
||||||
if ($msg->user_id == $currentUser->id) {
|
if ($msg->user_id == $currentUser->id) {
|
||||||
$msg->delete();
|
$msg->delete();
|
||||||
} else {
|
} else {
|
||||||
throw new HttpForbidden('You can not delete a message you haven\'t send');
|
throw new HttpForbidden();
|
||||||
}
|
}
|
||||||
|
|
||||||
return $this->redirect->to('/messages/' . $otherUserId . '#newest');
|
return $this->redirect->to('/messages/' . $otherUserId . '#newest');
|
||||||
|
|
|
@ -225,7 +225,7 @@ class Controller extends BaseController
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Ensure that the if the request is authorized
|
* Ensure that the request is authorized
|
||||||
*/
|
*/
|
||||||
protected function checkAuth(bool $isJson = false): void
|
protected function checkAuth(bool $isJson = false): void
|
||||||
{
|
{
|
||||||
|
|
|
@ -51,6 +51,7 @@ class OAuthController extends BaseController
|
||||||
throw new HttpNotFound('oauth.' . $request->get('error'));
|
throw new HttpNotFound('oauth.' . $request->get('error'));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Initial request redirects to provider
|
||||||
if (!$request->has('code')) {
|
if (!$request->has('code')) {
|
||||||
$authorizationUrl = $provider->getAuthorizationUrl(
|
$authorizationUrl = $provider->getAuthorizationUrl(
|
||||||
[
|
[
|
||||||
|
@ -64,6 +65,7 @@ class OAuthController extends BaseController
|
||||||
return $this->redirect->to($authorizationUrl);
|
return $this->redirect->to($authorizationUrl);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Redirected URL got called a second time
|
||||||
if (
|
if (
|
||||||
!$this->session->get('oauth2_state')
|
!$this->session->get('oauth2_state')
|
||||||
|| $request->get('state') !== $this->session->get('oauth2_state')
|
|| $request->get('state') !== $this->session->get('oauth2_state')
|
||||||
|
@ -75,6 +77,7 @@ class OAuthController extends BaseController
|
||||||
throw new HttpNotFound('oauth.invalid-state');
|
throw new HttpNotFound('oauth.invalid-state');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Fetch access token
|
||||||
$accessToken = null;
|
$accessToken = null;
|
||||||
try {
|
try {
|
||||||
$accessToken = $provider->getAccessToken(
|
$accessToken = $provider->getAccessToken(
|
||||||
|
@ -87,6 +90,7 @@ class OAuthController extends BaseController
|
||||||
$this->handleOAuthError($e, $providerName);
|
$this->handleOAuthError($e, $providerName);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Load resource identifier
|
||||||
$resourceOwner = null;
|
$resourceOwner = null;
|
||||||
try {
|
try {
|
||||||
$resourceOwner = $provider->getResourceOwner($accessToken);
|
$resourceOwner = $provider->getResourceOwner($accessToken);
|
||||||
|
@ -95,6 +99,7 @@ class OAuthController extends BaseController
|
||||||
}
|
}
|
||||||
$resourceId = $this->getId($providerName, $resourceOwner);
|
$resourceId = $this->getId($providerName, $resourceOwner);
|
||||||
|
|
||||||
|
// Fetch existing oauth state
|
||||||
/** @var OAuth|null $oauth */
|
/** @var OAuth|null $oauth */
|
||||||
$oauth = $this->oauth
|
$oauth = $this->oauth
|
||||||
->query()
|
->query()
|
||||||
|
@ -105,6 +110,7 @@ class OAuthController extends BaseController
|
||||||
->where('identifier', '===', (string) $resourceId)
|
->where('identifier', '===', (string) $resourceId)
|
||||||
->first();
|
->first();
|
||||||
|
|
||||||
|
// Update oauth state
|
||||||
$expirationTime = $accessToken->getExpires();
|
$expirationTime = $accessToken->getExpires();
|
||||||
$expirationTime = $expirationTime ? Carbon::createFromTimestamp($expirationTime) : null;
|
$expirationTime = $expirationTime ? Carbon::createFromTimestamp($expirationTime) : null;
|
||||||
if ($oauth) {
|
if ($oauth) {
|
||||||
|
@ -115,6 +121,7 @@ class OAuthController extends BaseController
|
||||||
$oauth->save();
|
$oauth->save();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Load user
|
||||||
$user = $this->auth->user();
|
$user = $this->auth->user();
|
||||||
if ($oauth && $user && $user->id != $oauth->user_id) {
|
if ($oauth && $user && $user->id != $oauth->user_id) {
|
||||||
throw new HttpNotFound('oauth.already-connected');
|
throw new HttpNotFound('oauth.already-connected');
|
||||||
|
@ -122,6 +129,7 @@ class OAuthController extends BaseController
|
||||||
|
|
||||||
$connectProvider = $this->session->get('oauth2_connect_provider');
|
$connectProvider = $this->session->get('oauth2_connect_provider');
|
||||||
$this->session->remove('oauth2_connect_provider');
|
$this->session->remove('oauth2_connect_provider');
|
||||||
|
// Connect user with oauth
|
||||||
if (!$oauth && $user && $connectProvider && $connectProvider == $providerName) {
|
if (!$oauth && $user && $connectProvider && $connectProvider == $providerName) {
|
||||||
$oauth = new OAuth([
|
$oauth = new OAuth([
|
||||||
'provider' => $providerName,
|
'provider' => $providerName,
|
||||||
|
@ -141,6 +149,7 @@ class OAuthController extends BaseController
|
||||||
$this->addNotification('oauth.connected');
|
$this->addNotification('oauth.connected');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Load user data
|
||||||
$resourceData = $resourceOwner->toArray();
|
$resourceData = $resourceOwner->toArray();
|
||||||
if (!empty($config['nested_info'])) {
|
if (!empty($config['nested_info'])) {
|
||||||
$resourceData = Arr::dot($resourceData);
|
$resourceData = Arr::dot($resourceData);
|
||||||
|
@ -148,6 +157,7 @@ class OAuthController extends BaseController
|
||||||
|
|
||||||
$userdata = new Collection($resourceData);
|
$userdata = new Collection($resourceData);
|
||||||
if (!$oauth) {
|
if (!$oauth) {
|
||||||
|
// User authenticated but has no account
|
||||||
return $this->redirectRegister(
|
return $this->redirectRegister(
|
||||||
$providerName,
|
$providerName,
|
||||||
(string) $resourceId,
|
(string) $resourceId,
|
||||||
|
@ -307,11 +317,13 @@ class OAuthController extends BaseController
|
||||||
throw new HttpNotFound('oauth.not-found');
|
throw new HttpNotFound('oauth.not-found');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Set registration form field data
|
||||||
$this->session->set('form-data-username', $userdata->get($config['username']));
|
$this->session->set('form-data-username', $userdata->get($config['username']));
|
||||||
$this->session->set('form-data-email', $userdata->get($config['email']));
|
$this->session->set('form-data-email', $userdata->get($config['email']));
|
||||||
$this->session->set('form-data-firstname', $userdata->get($config['first_name']));
|
$this->session->set('form-data-firstname', $userdata->get($config['first_name']));
|
||||||
$this->session->set('form-data-lastname', $userdata->get($config['last_name']));
|
$this->session->set('form-data-lastname', $userdata->get($config['last_name']));
|
||||||
|
|
||||||
|
// Define OAuth state
|
||||||
$this->session->set('oauth2_groups', $userdata->get($config['groups'], []));
|
$this->session->set('oauth2_groups', $userdata->get($config['groups'], []));
|
||||||
$this->session->set('oauth2_connect_provider', $providerName);
|
$this->session->set('oauth2_connect_provider', $providerName);
|
||||||
$this->session->set('oauth2_user_id', $providerUserIdentifier);
|
$this->session->set('oauth2_user_id', $providerUserIdentifier);
|
||||||
|
|
|
@ -115,7 +115,7 @@ class RegistrationController extends BaseController
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return Array<string, 1> Checkbox field name/Id → 1
|
* @return Array<string, 1> Checkbox field name/id → 1
|
||||||
*/
|
*/
|
||||||
private function determinePreselectedAngelTypes(): array
|
private function determinePreselectedAngelTypes(): array
|
||||||
{
|
{
|
||||||
|
|
|
@ -210,6 +210,7 @@ class User
|
||||||
*/
|
*/
|
||||||
private function createUser(array $data, array $rawData): EngelsystemUser
|
private function createUser(array $data, array $rawData): EngelsystemUser
|
||||||
{
|
{
|
||||||
|
// Ensure all user entries got created before saving
|
||||||
$this->dbConnection->beginTransaction();
|
$this->dbConnection->beginTransaction();
|
||||||
|
|
||||||
$user = new EngelsystemUser([
|
$user = new EngelsystemUser([
|
||||||
|
@ -274,6 +275,7 @@ class User
|
||||||
->associate($user)
|
->associate($user)
|
||||||
->save();
|
->save();
|
||||||
|
|
||||||
|
// Handle OAuth registration
|
||||||
if ($this->session->has('oauth2_connect_provider') && $this->session->has('oauth2_user_id')) {
|
if ($this->session->has('oauth2_connect_provider') && $this->session->has('oauth2_user_id')) {
|
||||||
$oauth = new OAuth([
|
$oauth = new OAuth([
|
||||||
'provider' => $this->session->get('oauth2_connect_provider'),
|
'provider' => $this->session->get('oauth2_connect_provider'),
|
||||||
|
|
|
@ -4,15 +4,12 @@ declare(strict_types=1);
|
||||||
|
|
||||||
namespace Engelsystem\Helpers;
|
namespace Engelsystem\Helpers;
|
||||||
|
|
||||||
use Engelsystem\Helpers\Carbon;
|
|
||||||
|
|
||||||
class DayOfEvent
|
class DayOfEvent
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
* @return The current day of the event.
|
* @return ?int The current day of the event.
|
||||||
* If "event_has_day0" is set to true in config,
|
* If `event_has_day0` is set to true in config, the first day of the event will be 0, else 1.
|
||||||
* the first day of the event will be 0, else 1.
|
* Returns null if "event_start" is not set.
|
||||||
* Returns null if "event_start" is not set.
|
|
||||||
*/
|
*/
|
||||||
public static function get(Carbon $date = null): int | null
|
public static function get(Carbon $date = null): int | null
|
||||||
{
|
{
|
||||||
|
|
|
@ -18,11 +18,14 @@ class Shifts
|
||||||
|
|
||||||
/** @see User_get_shifts_sum_query to keep it in sync */
|
/** @see User_get_shifts_sum_query to keep it in sync */
|
||||||
return $config['enabled'] && (
|
return $config['enabled'] && (
|
||||||
|
// Starts during night
|
||||||
$start->hour >= $config['start'] && $start->hour < $config['end']
|
$start->hour >= $config['start'] && $start->hour < $config['end']
|
||||||
|
// Ends during night
|
||||||
|| (
|
|| (
|
||||||
$end->hour > $config['start']
|
$end->hour > $config['start']
|
||||||
|| $end->hour == $config['start'] && $end->minute > 0
|
|| $end->hour == $config['start'] && $end->minute > 0
|
||||||
) && $end->hour <= $config['end']
|
) && $end->hour <= $config['end']
|
||||||
|
// Starts before and ends after night
|
||||||
|| $start->hour <= $config['start'] && $end->hour >= $config['end']
|
|| $start->hour <= $config['start'] && $end->hour >= $config['end']
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -72,24 +72,27 @@ class TranslationServiceProvider extends ServiceProvider
|
||||||
|
|
||||||
public function getTranslator(string $locale): GettextTranslator
|
public function getTranslator(string $locale): GettextTranslator
|
||||||
{
|
{
|
||||||
if (!isset($this->translators[$locale])) {
|
if (isset($this->translators[$locale])) {
|
||||||
$names = ['default', 'additional'];
|
return $this->translators[$locale];
|
||||||
|
|
||||||
/** @var Translations $translations */
|
|
||||||
$translations = $this->app->call([Translations::class, 'create']);
|
|
||||||
$path = $this->app->get('path.lang');
|
|
||||||
foreach ($names as $name) {
|
|
||||||
$file = $this->getFile($locale, $path, $name);
|
|
||||||
$translations = $this->loadFile($file, $translations);
|
|
||||||
}
|
|
||||||
|
|
||||||
$file = $this->getFile($locale, $this->app->get('path.config') . '/lang', 'custom');
|
|
||||||
$translations = $this->loadFile($file, $translations);
|
|
||||||
|
|
||||||
$translator = GettextTranslator::createFromTranslations($translations);
|
|
||||||
$this->translators[$locale] = $translator;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$names = ['default', 'additional'];
|
||||||
|
|
||||||
|
/** @var Translations $translations */
|
||||||
|
$translations = $this->app->call([Translations::class, 'create']);
|
||||||
|
$path = $this->app->get('path.lang');
|
||||||
|
foreach ($names as $name) {
|
||||||
|
$file = $this->getFile($locale, $path, $name);
|
||||||
|
$translations = $this->loadFile($file, $translations);
|
||||||
|
}
|
||||||
|
|
||||||
|
$file = $this->getFile($locale, $this->app->get('path.config') . '/lang', 'custom');
|
||||||
|
$translations = $this->loadFile($file, $translations);
|
||||||
|
|
||||||
|
/** @var GettextTranslator $translator */
|
||||||
|
$translator = GettextTranslator::createFromTranslations($translations);
|
||||||
|
$this->translators[$locale] = $translator;
|
||||||
|
|
||||||
return $this->translators[$locale];
|
return $this->translators[$locale];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -21,7 +21,7 @@ class Uuid
|
||||||
mt_rand(0, 0xffff),
|
mt_rand(0, 0xffff),
|
||||||
// first bit is the uuid version, here 4
|
// first bit is the uuid version, here 4
|
||||||
mt_rand(0, 0x0fff) | 0x4000,
|
mt_rand(0, 0x0fff) | 0x4000,
|
||||||
// variant
|
// variant, here OSF DCE UUID
|
||||||
mt_rand(0, 0x3fff) | 0x8000,
|
mt_rand(0, 0x3fff) | 0x8000,
|
||||||
mt_rand(0, 0xffffffffffff)
|
mt_rand(0, 0xffffffffffff)
|
||||||
);
|
);
|
||||||
|
@ -53,7 +53,7 @@ class Uuid
|
||||||
Str::substr($value, 8, 4),
|
Str::substr($value, 8, 4),
|
||||||
// first bit is the uuid version, here 4
|
// first bit is the uuid version, here 4
|
||||||
'4' . Str::substr($value, 13, 3),
|
'4' . Str::substr($value, 13, 3),
|
||||||
// first bit is the variant (0x8-0xb)
|
// first bit is the variant (0x8-0xb), here OSF DCE UUID
|
||||||
dechex(8 + (hexdec(Str::substr($value, 16, 1)) % 4))
|
dechex(8 + (hexdec(Str::substr($value, 16, 1)) % 4))
|
||||||
. Str::substr($value, 17, 3),
|
. Str::substr($value, 17, 3),
|
||||||
Str::substr($value, 20, 12)
|
Str::substr($value, 20, 12)
|
||||||
|
|
|
@ -41,7 +41,7 @@ class UrlGenerator implements UrlGeneratorInterface
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Prepend the auto detected or configured app base path and domain
|
* Prepend the auto-detected or configured app base path and domain
|
||||||
*
|
*
|
||||||
* @param $path
|
* @param $path
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -37,6 +37,7 @@ class Validator
|
||||||
$value = isset($data[$key]) ? $data[$key] : null;
|
$value = isset($data[$key]) ? $data[$key] : null;
|
||||||
$values = explode('|', $values);
|
$values = explode('|', $values);
|
||||||
|
|
||||||
|
// Rules that have side effects on others like inverting the result with not and making them optional
|
||||||
$packing = [];
|
$packing = [];
|
||||||
foreach ($this->nestedRules as $rule) {
|
foreach ($this->nestedRules as $rule) {
|
||||||
if (in_array($rule, $values)) {
|
if (in_array($rule, $values)) {
|
||||||
|
|
|
@ -12,6 +12,9 @@ use Psr\Http\Message\ServerRequestInterface;
|
||||||
use Psr\Http\Server\MiddlewareInterface;
|
use Psr\Http\Server\MiddlewareInterface;
|
||||||
use Psr\Http\Server\RequestHandlerInterface;
|
use Psr\Http\Server\RequestHandlerInterface;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Wraps a callable to be used to respond / as a middleware
|
||||||
|
*/
|
||||||
class CallableHandler implements MiddlewareInterface, RequestHandlerInterface
|
class CallableHandler implements MiddlewareInterface, RequestHandlerInterface
|
||||||
{
|
{
|
||||||
/** @var callable */
|
/** @var callable */
|
||||||
|
|
|
@ -43,7 +43,7 @@ class Dispatcher implements MiddlewareInterface, RequestHandlerInterface
|
||||||
/**
|
/**
|
||||||
* Handle the request and return a response.
|
* Handle the request and return a response.
|
||||||
*
|
*
|
||||||
* It calls all configured middleware and handles their response
|
* It calls all configured middlewares and handles their response
|
||||||
*/
|
*/
|
||||||
public function handle(ServerRequestInterface $request): ResponseInterface
|
public function handle(ServerRequestInterface $request): ResponseInterface
|
||||||
{
|
{
|
||||||
|
|
|
@ -22,7 +22,7 @@ class ErrorHandler implements MiddlewareInterface
|
||||||
protected string $viewPrefix = 'errors/';
|
protected string $viewPrefix = 'errors/';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A list of inputs that are not saved from form input
|
* A list of inputs that are not saved from input
|
||||||
*
|
*
|
||||||
* @var array<string>
|
* @var array<string>
|
||||||
*/
|
*/
|
||||||
|
@ -42,7 +42,7 @@ class ErrorHandler implements MiddlewareInterface
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Handles any error messages
|
* Handles any error messages / http exceptions / validation errors
|
||||||
*
|
*
|
||||||
* Should be added at the beginning
|
* Should be added at the beginning
|
||||||
*/
|
*/
|
||||||
|
@ -50,6 +50,7 @@ class ErrorHandler implements MiddlewareInterface
|
||||||
ServerRequestInterface $request,
|
ServerRequestInterface $request,
|
||||||
RequestHandlerInterface $handler
|
RequestHandlerInterface $handler
|
||||||
): ResponseInterface {
|
): ResponseInterface {
|
||||||
|
// Handle response
|
||||||
try {
|
try {
|
||||||
$response = $handler->handle($request);
|
$response = $handler->handle($request);
|
||||||
} catch (HttpException $e) {
|
} catch (HttpException $e) {
|
||||||
|
@ -75,6 +76,7 @@ class ErrorHandler implements MiddlewareInterface
|
||||||
$contentType = 'text/html';
|
$contentType = 'text/html';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Handle response based on status
|
||||||
if (
|
if (
|
||||||
$statusCode < 400
|
$statusCode < 400
|
||||||
|| !$response instanceof Response
|
|| !$response instanceof Response
|
||||||
|
|
|
@ -13,6 +13,9 @@ use Psr\Http\Message\ServerRequestInterface;
|
||||||
use Psr\Http\Server\MiddlewareInterface;
|
use Psr\Http\Server\MiddlewareInterface;
|
||||||
use Psr\Http\Server\RequestHandlerInterface;
|
use Psr\Http\Server\RequestHandlerInterface;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Middleware to support the old routing / pages from includes
|
||||||
|
*/
|
||||||
class LegacyMiddleware implements MiddlewareInterface
|
class LegacyMiddleware implements MiddlewareInterface
|
||||||
{
|
{
|
||||||
/** @var array<string> */
|
/** @var array<string> */
|
||||||
|
@ -33,7 +36,7 @@ class LegacyMiddleware implements MiddlewareInterface
|
||||||
/**
|
/**
|
||||||
* Handle the request the old way
|
* Handle the request the old way
|
||||||
*
|
*
|
||||||
* Should be used before a 404 is send
|
* Should be used before a 404 is sent
|
||||||
*/
|
*/
|
||||||
public function process(
|
public function process(
|
||||||
ServerRequestInterface $request,
|
ServerRequestInterface $request,
|
||||||
|
@ -42,6 +45,7 @@ class LegacyMiddleware implements MiddlewareInterface
|
||||||
/** @var Request $appRequest */
|
/** @var Request $appRequest */
|
||||||
$appRequest = $this->container->get('request');
|
$appRequest = $this->container->get('request');
|
||||||
$page = $appRequest->query->get('p');
|
$page = $appRequest->query->get('p');
|
||||||
|
// Support old URL scheme
|
||||||
if (empty($page)) {
|
if (empty($page)) {
|
||||||
$page = $appRequest->path();
|
$page = $appRequest->path();
|
||||||
$page = str_replace('-', '_', $page);
|
$page = str_replace('-', '_', $page);
|
||||||
|
|
|
@ -24,6 +24,7 @@ class RequestHandler implements MiddlewareInterface
|
||||||
/**
|
/**
|
||||||
* Process an incoming server request and return a response, optionally delegating
|
* Process an incoming server request and return a response, optionally delegating
|
||||||
* response creation to a handler.
|
* response creation to a handler.
|
||||||
|
* Implements basic permission checking if the controller supports it.
|
||||||
*/
|
*/
|
||||||
public function process(ServerRequestInterface $request, RequestHandlerInterface $handler): ResponseInterface
|
public function process(ServerRequestInterface $request, RequestHandlerInterface $handler): ResponseInterface
|
||||||
{
|
{
|
||||||
|
|
|
@ -35,7 +35,6 @@ class TrimInput implements MiddlewareInterface
|
||||||
$request = $request->withParsedBody($trimmedParsedBody);
|
$request = $request->withParsedBody($trimmedParsedBody);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
return $handler->handle($request);
|
return $handler->handle($request);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -39,11 +39,10 @@ class Globals extends TwigExtension implements GlobalsInterface
|
||||||
{
|
{
|
||||||
$user = $this->auth->user();
|
$user = $this->auth->user();
|
||||||
$themes = config('themes');
|
$themes = config('themes');
|
||||||
|
$themeId = config('theme');
|
||||||
$userMessages = null;
|
$userMessages = null;
|
||||||
|
|
||||||
if ($user === null) {
|
if ($user) {
|
||||||
$themeId = config('theme');
|
|
||||||
} else {
|
|
||||||
$themeId = $user->settings->theme;
|
$themeId = $user->settings->theme;
|
||||||
$userMessages = $user
|
$userMessages = $user
|
||||||
->messagesReceived()
|
->messagesReceived()
|
||||||
|
|
|
@ -26,6 +26,7 @@ class Url extends TwigExtension
|
||||||
|
|
||||||
public function getUrl(string $path, array $parameters = []): string
|
public function getUrl(string $path, array $parameters = []): string
|
||||||
{
|
{
|
||||||
|
// Fix legacy URLs
|
||||||
$path = str_replace('_', '-', $path);
|
$path = str_replace('_', '-', $path);
|
||||||
|
|
||||||
return $this->urlGenerator->to($path, $parameters);
|
return $this->urlGenerator->to($path, $parameters);
|
||||||
|
|
Loading…
Reference in New Issue