Compare commits

..

29 Commits

Author SHA1 Message Date
Dave Mc Nicoll
81e124b144 - Added getenvonce 2026-06-01 15:23:49 +00:00
Dave Mc Nicoll
9cd6f10d7e - Merged with master done 2026-06-01 15:23:48 +00:00
Dave Mc Nicoll
a36dbeeef2 - Fixed conflicts 2026-06-01 15:23:42 +00:00
7ed88ec89f - Added createStream methods and fixed multiple errors views 2026-06-01 15:23:11 +00:00
c6e9bb6a38 - Added MethodNotAllowed interface 2026-06-01 15:23:04 +00:00
Dave Mc Nicoll
e934c1a92c -Rebasing 2026-06-01 15:23:04 +00:00
baf6fdf952 - Added createStream methods and fixed multiple errors views 2026-06-01 15:23:03 +00:00
Dave Mc Nicoll
e0da7ae734 - Merged with master done 2026-06-01 15:22:54 +00:00
Dave Mc Nicoll
64f273e65c - Rebased 2026-06-01 15:22:54 +00:00
Dave Mc Nicoll
9031236930 - WIP on ulmus-user mechanics updates 2026-06-01 15:22:54 +00:00
7ee4b2d8bb - Added createStream methods and fixed multiple errors views 2026-06-01 15:22:38 +00:00
06c4f46486 - Added MethodNotAllowed interface 2026-06-01 15:21:56 +00:00
Dave Mc Nicoll
01d48463b3 - Merged with master done 2026-05-21 15:18:50 +00:00
Dave Mc Nicoll
abe94e498f - Fixed conflicts 2026-05-21 15:18:49 +00:00
Dev
adfd619c5f - Fixed default view order to 1000 2026-05-21 15:18:04 +00:00
16ee06593c - Added createStream methods and fixed multiple errors views 2026-05-21 15:18:03 +00:00
5bb5e8ce61 - Added MethodNotAllowed interface 2026-05-21 15:16:58 +00:00
Dave Mc Nicoll
fda052d2f3 - Redefined view order 2026-03-03 16:34:41 +00:00
Dave Mc Nicoll
dac7acde87 - Fixed email route argument pattern and added getenvonce() method 2026-02-25 19:43:36 +00:00
Dave Mc Nicoll
b16b4803c5 -Rebasing 2026-02-25 19:43:32 +00:00
Dev
d54d78ccc5 - Default URL in back button 2026-02-25 19:41:00 +00:00
9ff4d6c44d - Restored PHP 8.3 compatibility. 2026-02-25 19:41:00 +00:00
a4b02607f3 - WIP on skeleton 2026-02-25 19:41:00 +00:00
d74c916558 - Added createStream methods and fixed multiple errors views 2026-02-25 19:40:58 +00:00
Dave Mc Nicoll
ca388e8a52 - Merged with master done 2026-02-25 19:40:07 +00:00
b12fc65ea9 Fixed missing namespace of Factory 2026-02-25 19:39:12 +00:00
4b76a387fe - Various fixes bugs and missing code in project's skeleton 2026-02-25 19:39:12 +00:00
Dave Mc Nicoll
1c2ce07179 - Fixed merges of latest master 2025-06-13 19:25:08 +00:00
Dave Mc Nicoll
af8b686e3b - WIP on ulmus-user mechanics updates 2025-06-13 19:14:30 +00:00
29 changed files with 314 additions and 211 deletions

View File

@ -16,26 +16,54 @@
"ext-posix": "*", "ext-posix": "*",
"ext-xmlreader": "*", "ext-xmlreader": "*",
"ext-fileinfo": "*", "ext-fileinfo": "*",
"league/route": "^7.0.0-dev", "league/route": "^5.0.0-dev",
"laminas/laminas-diactoros": "3.9.x-dev", "laminas/laminas-diactoros": "2.24.x-dev",
"laminas/laminas-httphandlerrunner": "2.14.x-dev", "laminas/laminas-httphandlerrunner": "2.5.x-dev",
"vlucas/phpdotenv": "^3.4@dev", "vlucas/phpdotenv": "^3.4@dev",
"middlewares/whoops": "dev-master", "middlewares/whoops": "dev-master",
"mcnd/dump": "~1.0.0", "mcnd/storage": "dev-master",
"mcnd/storage": "~1.0.0", "mcnd/lean-console": "dev-master",
"mcnd/event": "~1.0.0", "mcnd/ulmus": "dev-master",
"mcnd/tell": "~1.0.0", "mcnd/tell": "dev-master",
"mcnd/ulmus": "^1.0 || ^2.0", "mcnd/dump": "dev-master",
"mcnd/kash": "~1.0.0", "mcnd/event": "dev-master",
"mcnd/taxus": "1.1.0", "mcnd/thebugs": "dev-master",
"mcnd/notes": "^2.1.1", "mcnd/taxus": "dev-master",
"mcnd/thebugs": "^1.0.0", "mcnd/notes": "dev-master",
"psr/simple-cache": "*" "psr/simple-cache": "*"
}, },
"repositories": [ "repositories": [
{ {
"type": "composer", "type": "vcs",
"url": "https://git.mcnd.ca/api/packages/mcndave/composer" "url": "https://git.mcnd.ca/mcndave/event.git"
},
{
"type": "vcs",
"url": "https://git.mcnd.ca/mcndave/the-bugs.git"
},
{
"type": "vcs",
"url": "https://git.mcnd.ca/mcndave/storage.git"
},
{
"type": "vcs",
"url": "https://git.mcnd.ca/mcndave/ulmus.git"
},
{
"type": "vcs",
"url": "https://git.mcnd.ca/mcndave/notes.git"
},
{
"type": "vcs",
"url": "https://git.mcnd.ca/mcndave/tell.git"
},
{
"type": "vcs",
"url": "https://git.mcnd.ca/mcndave/lean-console.git"
},
{
"type": "vcs",
"url": "https://git.mcnd.ca/mcndave/dump.git"
} }
], ],
"autoload": { "autoload": {

View File

@ -1,40 +1,44 @@
<?php <?php
use Ulmus\User\{Entity, use Lean\Factory\HttpFactoryInterface;
use Ulmus\User\{Authorize\HeaderAuthentication,
Entity,
Lib\Authenticate, Lib\Authenticate,
Lib\Authorize, Lib\Authorize,
Middleware\AuthenticationMiddleware,
Middleware\HeaderAuthenticationMiddleware, Middleware\HeaderAuthenticationMiddleware,
Middleware\PostRequestAuthenticationMiddleware, Middleware\PostRequestAuthenticationMiddleware,
Middleware\LocalMacAddressMiddleware,
Authorize\MacAddressAuthentication,
Authorize\PostRequestAuthentication}; Authorize\PostRequestAuthentication};
use Picea\Picea; use Picea\Picea;
use Storage\{ Cookie, Session }; use Storage\{ Cookie, Session };
use function DI\{get, create}; use Psr\Container\ContainerInterface;
use function DI\{get, autowire, create};
return [ return [
Authenticate::class => create(Authenticate::class)->constructor(get(Entity\UserInterface::class), get(Session::class), get(Cookie::class), get('authentication.method')),
Authorize::class => create(Authorize::class)->constructor(get(Entity\UserInterface::class), get(Session::class), get(Cookie::class), get('authentication.method')), Authorize::class => create(Authorize::class)->constructor(get(Entity\UserInterface::class), get(Session::class), get(Cookie::class), get('authentication.method')),
HeaderAuthenticationMiddleware::class => create(HeaderAuthenticationMiddleware::class)->constructor(get(Authorize::class), get(Entity\UserInterface::class), get('authorize.error')), Authenticate::class => create(Authenticate::class)->constructor(get(Entity\UserInterface::class), get(Session::class), get(Cookie::class), get('authentication.method')),
PostRequestAuthentication::class => create(PostRequestAuthentication::class)->constructor(get(Authenticate::class), "email", "email", "password"), AuthenticationMiddleware::class => create(AuthenticationMiddleware::class)->constructor(get(Authorize::class), get('authorize.error')),
PostRequestAuthenticationMiddleware::class => create(PostRequestAuthenticationMiddleware::class)->constructor(get(Entity\UserInterface::class), get('authentication.error'), get(PostRequestAuthentication::class)), HeaderAuthentication::class => autowire(HeaderAuthentication::class),
MacAddressAuthentication::class => create(MacAddressAuthentication::class)->constructor(get(Authenticate::class), "mac"), HeaderAuthenticationMiddleware::class => create(HeaderAuthenticationMiddleware::class)->constructor(get(HeaderAuthentication::class)),
LocalMacAddressMiddleware::class => create(LocalMacAddressMiddleware::class)->constructor(get(Entity\UserInterface::class), get('authentication.error'), get(MacAddressAuthentication::class)), PostRequestAuthentication::class => create(PostRequestAuthentication::class)->constructor("email", "email", "password"),
PostRequestAuthenticationMiddleware::class => create(PostRequestAuthenticationMiddleware::class)->constructor(get(PostRequestAuthentication::class)),
'authentication.method' => null, 'authentication.method' => null,
'authorize.error' => function($c) { 'authorize.error' => function(ContainerInterface $c) {
return function(array $errorData) use ($c) { return function(array $errorData) use ($c) {
return $c->get(\Lean\Factory\HttpFactoryInterface::class)::createJsonResponse($errorData + [ return $c->get(HttpFactoryInterface::class)::createJsonResponse($errorData + [
'api.error' => "Authorization failed", 'api.error' => "Authorization failed",
'api.datetime' => (new \DateTime)->format(\DateTime::ATOM), 'api.datetime' => (new \DateTime)->format(\DateTime::ATOM),
], 403); ], 403);
@ -42,8 +46,9 @@ return [
}, },
'authentication.error' => function($c, Picea $picea) { 'authentication.error' => function($c, Picea $picea) {
return function($message) use ($picea, $c) { return function($message) use ($c, $picea) {
return $c->get(\Lean\Factory\HttpFactoryInterface::class)::createHtmlResponse($picea->renderHtml('lean/error/500', [ return $c->get(HttpFactoryInterface::class)::createHtmlResponse($picea->renderHtml('lean/error/500', [
'title' => "Authentication failed", 'title' => "Authentication failed",
'subtitle' => "", 'subtitle' => "",
'message' => $message, 'message' => $message,

View File

@ -37,7 +37,7 @@ return [
public function execute(Routing $routing, Route $attribute) : void public function execute(Routing $routing, Route $attribute) : void
{ {
if (null !== ($name = $attribute->name ?? null)) { if (null !== ($name = $attribute->name ?? null)) {
$this->extension->registerRoute($name, $attribute->getRoute(), $attribute->class, $attribute->classMethod, (array) ( $attribute->method )); $this->extension->registerRoute($name, $attribute->getRoute(), $attribute->class, $attribute->classMethod, (array) ( $attribute->method ?? $attribute->methods ));
} }
} }
}, },
@ -52,6 +52,7 @@ return [
{ {
$class = $attribute->class; $class = $attribute->class;
$method = $attribute->classMethod; $method = $attribute->classMethod;
$object = $container->get($class);
$request = $request->withAttribute('lean.route', $attribute); $request = $request->withAttribute('lean.route', $attribute);

View File

@ -1,11 +1,13 @@
<?php <?php
use Lean\ApplicationStrategy\{ ThrowableHandler, ThrowableHandlerInterface, NotFoundDecoratorInterface, NotFoundDecorator, MethodNotAllowedInterface, }; use Lean\ApplicationStrategy\{ ThrowableHandler, ThrowableHandlerInterface, NotFoundDecoratorInterface, NotFoundDecorator, MethodNotAllowedInterface, };
use function DI\autowire, DI\create, DI\get; use Psr\Container\ContainerInterface;
use Psr\Http\Message\ServerRequestInterface; use Psr\Http\Message\ServerRequestInterface;
use Laminas\{ Diactoros\ServerRequestFactory, HttpHandlerRunner\Emitter\EmitterInterface, HttpHandlerRunner\Emitter\SapiEmitter }; use Laminas\{ Diactoros\ServerRequestFactory, HttpHandlerRunner\Emitter\EmitterInterface, HttpHandlerRunner\Emitter\SapiEmitter };
use Lean\Factory\{ HttpFactory, HttpFactoryInterface };
use Picea\Picea;
use function DI\{ autowire, create, get };
return [ return [
ServerRequestInterface::class => function ($c) { ServerRequestInterface::class => function ($c) {
@ -15,8 +17,22 @@ return [
}, },
EmitterInterface::class => create(SapiEmitter::class), EmitterInterface::class => create(SapiEmitter::class),
ThrowableHandlerInterface::class => autowire(ThrowableHandler::class), ThrowableHandlerInterface::class => autowire(ThrowableHandler::class),
NotFoundDecoratorInterface::class => autowire(NotFoundDecorator::class), NotFoundDecoratorInterface::class => autowire(NotFoundDecorator::class),
# MethodNotAllowedInterface::class => autowire(MethodNotAllowedDecorator::class), # MethodNotAllowedInterface::class => autowire(MethodNotAllowedDecorator::class),
HttpFactoryInterface::class => create(HttpFactory::class),
'error.401' => function(ContainerInterface $c, Picea $picea) {
return $c->get(HttpFactoryInterface::class)::createHtmlResponse($picea->renderHtml("lean/error/401", []), 401);
},
'error.404' => function(ContainerInterface $c, Picea $picea) {
return $c->get(HttpFactoryInterface::class)::createHtmlResponse($picea->renderHtml("lean/error/404", []), 404);
},
'error.500' => function(ContainerInterface $c, Picea $picea) {
return $c->get(HttpFactoryInterface::class)::createHtmlResponse($picea->renderHtml("lean/error/500", []), 500);
}
]; ];

View File

@ -2,6 +2,7 @@
use Tell\I18n; use Tell\I18n;
use Psr\Container\ContainerInterface; use Psr\Container\ContainerInterface;
use Notes\Tell\LanguageHandler;
use function DI\autowire, DI\create, DI\get, DI\add; use function DI\autowire, DI\create, DI\get, DI\add;

View File

@ -15,7 +15,10 @@ use Notes\Breadcrumb\Breadcrumb;
use Storage\SessionMiddleware; use Storage\SessionMiddleware;
use Psr\Http\Message\{ ResponseInterface, ServerRequestInterface }; use Ulmus\User\Middleware\{
HeaderAuthenticationMiddleware,
PostRequestAuthenticationMiddleware
};
return [ return [
Lean\Routing::class => autowire(Lean\Routing::class), Lean\Routing::class => autowire(Lean\Routing::class),
@ -66,6 +69,7 @@ return [
} }
$router->addPatternMatcher('email', '[^@ \t\r\n]+@[^@ \t\r\n]+\.[^@ \t\r\n/]+'); $router->addPatternMatcher('email', '[^@ \t\r\n]+@[^@ \t\r\n]+\.[^@ \t\r\n/]+');
$router->addPatternMatcher('ids', '\b\d[\d,]*\b');
$routing = $container->get(Lean\Routing::class); $routing = $container->get(Lean\Routing::class);
$routing->registerRoute($container, getenv('URL_BASE')); $routing->registerRoute($container, getenv('URL_BASE'));

View File

@ -5,8 +5,7 @@ CRON_KEY = dev
# Route # Route
URL_BASE = "" URL_BASE = ""
APP_URL = "myapp.ca" APP_URL = "dev.mcnd.ca"
ASSET_PATH = "static/"
# Path # Path
CACHE_DIR = "var/cache" CACHE_DIR = "var/cache"
@ -24,18 +23,19 @@ DEFAULT_TIME = "fr.UTF-8"
DEFAULT_TIME_FALLBACK = "french.UTF-8" DEFAULT_TIME_FALLBACK = "french.UTF-8"
# Database # Database
SQLITE_PATH = "var/myapp.sqlite3" #SQLITE_PATH = "var/home.sqlite3"
SQLITE_ADAPTER = "SQLite" #SQLITE_ADAPTER = "SQLite"
SQLITE_PRAGMA_BEGIN = "foreign_keys=ON,synchronous=NORMAL" #SQLITE_PRAGMA_BEGIN = "foreign_keys=ON,synchronous=NORMAL"
SQLITE_PRAGMA_DEBUG_BEGIN = "journal_mode=WAL" #SQLITE_PRAGMA_DEBUG_BEGIN = "journal_mode=WAL"
SQLITE_PRAGMA_CLOSE = "analysis_limit=500,optimize" #SQLITE_PRAGMA_CLOSE = "analysis_limit=500,optimize"
#DATABASE_PORT = "" DATABASE_PORT = ""
#DATABASE_HOST = "" DATABASE_HOST = ""
#DATABASE_NAME = "" DATABASE_NAME = ""
#DATABASE_USERNAME = "" DATABASE_USERNAME = ""
#DATABASE_PASSWORD = "" DATABASE_PASSWORD = ""
#DATABASE_CHARSET = "utf8" DATABASE_CHARSET = "utf8"
#DATABASE_ADAPTER = "MariaDB" DATABASE_ADAPTER = "MariaDB"
LEAN_RANDOM = "%RAND64%" LEAN_RANDOM = "%RAND64%"

0
skeleton/cli Executable file → Normal file
View File

View File

@ -25,20 +25,20 @@
"league/oauth2-client": "dev-master", "league/oauth2-client": "dev-master",
"php-di/php-di": "dev-master", "php-di/php-di": "dev-master",
"league/commonmark": "^2.7@dev", "league/commonmark": "^2.7@dev",
"assets-package/ace": "1.0.0", "assets-package/ace": "dev-master",
"mcnd/dump": "dev-master", "mcnd/dump": "dev-master",
"mcnd/storage": "dev-master", "mcnd/storage": "dev-master",
"mcnd/cli": "dev-master", "mcnd/cli": "dev-master",
"mcnd/event": "dev-master", "mcnd/event": "dev-master",
"mcnd/ulmus": "^1.0 || ^2.0", "mcnd/ulmus": "dev-master",
"mcnd/ulmus-api": "^1.3.0", "mcnd/ulmus-api": "dev-master",
"mcnd/ulmus-user": "~1.1.2", "mcnd/ulmus-user": "dev-master",
"mcnd/picea": "dev-master", "mcnd/picea": "dev-master",
"mcnd/picea-ui": "dev-master", "mcnd/picea-ui": "dev-master",
"mcnd/picea-asset": "~1.0.2", "mcnd/picea-asset": "dev-master",
"mcnd/cronard": "dev-master", "mcnd/cronard": "dev-master",
"mcnd/lean-api": "dev-master", "mcnd/lean-api": "dev-master",
"mcnd/lean-console": "~1.3.2", "mcnd/lean-console": "dev-master",
"mcnd/kash": "dev-master", "mcnd/kash": "dev-master",
"mcnd/taxus": "dev-master", "mcnd/taxus": "dev-master",
"mcnd/notes": "dev-master", "mcnd/notes": "dev-master",
@ -47,12 +47,100 @@
}, },
"repositories": [ "repositories": [
{ {
"type": "composer", "type": "vcs",
"url": "https://git.mcnd.ca/api/packages/mcndave/composer" "url": "https://git.mcnd.ca/mcndave/cronard.git"
}, },
{ {
"type": "composer", "type": "vcs",
"url": "https://git.mcnd.ca/api/packages/assets-package/composer" "url": "https://git.mcnd.ca/mcndave/cli.git"
},
{
"type": "vcs",
"url": "https://git.mcnd.ca/mcndave/dump.git"
},
{
"type": "vcs",
"url": "https://git.mcnd.ca/mcndave/storage.git"
},
{
"type": "vcs",
"url": "https://git.mcnd.ca/mcndave/lean.git"
},
{
"type": "vcs",
"url": "https://git.mcnd.ca/mcndave/lean-api.git"
},
{
"type": "vcs",
"url": "https://git.mcnd.ca/mcndave/lean-console.git"
},
{
"type": "vcs",
"url": "https://git.mcnd.ca/mcndave/ulmus.git"
},
{
"type": "vcs",
"url": "https://git.mcnd.ca/mcndave/ulmus-api.git"
},
{
"type": "vcs",
"url": "https://git.mcnd.ca/mcndave/ulmus-user.git"
},
{
"type": "vcs",
"url": "https://git.mcnd.ca/mcndave/ulmus-api-gitea.git"
},
{
"type": "vcs",
"url": "https://git.mcnd.ca/mcndave/picea.git"
},
{
"type": "vcs",
"url": "https://git.mcnd.ca/mcndave/storage.git"
},
{
"type": "vcs",
"url": "https://git.mcnd.ca/mcndave/picea-ui.git"
},
{
"type": "vcs",
"url": "https://git.mcnd.ca/mcndave/picea-asset.git"
},
{
"type": "vcs",
"url": "https://git.mcnd.ca/mcndave/notes.git"
},
{
"type": "vcs",
"url": "https://git.mcnd.ca/mcndave/the-bugs.git"
},
{
"type": "vcs",
"url": "https://git.mcnd.ca/mcndave/tell.git"
},
{
"type": "vcs",
"url": "https://git.mcnd.ca/mcndave/taxus.git"
},
{
"type": "vcs",
"url": "https://git.mcnd.ca/mcndave/dump.git"
},
{
"type": "vcs",
"url": "https://git.mcnd.ca/mcndave/kash.git"
},
{
"type": "vcs",
"url": "https://git.mcnd.ca/mcndave/event.git"
},
{
"type": "vcs",
"url": "https://git.mcnd.ca/mcndave/negundo-client.git"
},
{
"type": "vcs",
"url": "https://git.mcnd.ca/assets-package/ace.git"
} }
], ],
"autoload": { "autoload": {

View File

@ -10,7 +10,7 @@ return [
], ],
'keys' => (function() { 'keys' => (function() {
return explode(',', getenv('KEYS') ?? "") ; return explode(',', getenvonce('KEYS') ?? "") ;
})(), })(),
'meta' => [ 'meta' => [
@ -19,7 +19,7 @@ return [
'ulmus' => [ 'ulmus' => [
'connections' => [ 'connections' => [
/*'default' => [ 'default' => [
'adapter' => getenv("DATABASE_ADAPTER"), 'adapter' => getenv("DATABASE_ADAPTER"),
'host' => getenv("DATABASE_HOST"), 'host' => getenv("DATABASE_HOST"),
'port' => getenv("DATABASE_PORT"), 'port' => getenv("DATABASE_PORT"),
@ -29,9 +29,9 @@ return [
'settings' => [ 'settings' => [
'charset' => getenv("DATABASE_CHARSET"), 'charset' => getenv("DATABASE_CHARSET"),
], ],
],*/ ],
'default' => [ 'sqlite' => [
'adapter' => getenv("SQLITE_ADAPTER"), 'adapter' => getenv("SQLITE_ADAPTER"),
'path' => getenv('PROJECT_PATH') . DIRECTORY_SEPARATOR . getenv("SQLITE_PATH"), 'path' => getenv('PROJECT_PATH') . DIRECTORY_SEPARATOR . getenv("SQLITE_PATH"),
'pragma' => explode(',', getenv("SQLITE_PRAGMA")), 'pragma' => explode(',', getenv("SQLITE_PRAGMA")),

View File

@ -4,6 +4,7 @@ use function DI\autowire, DI\create, DI\get;
use %NAMESPACE%\Entity; use %NAMESPACE%\Entity;
use Psr\Container\ContainerInterface;
use Psr\Http\Message\ServerRequestInterface; use Psr\Http\Message\ServerRequestInterface;
use Ulmus\Entity\Field\Datetime, use Ulmus\Entity\Field\Datetime,
@ -21,16 +22,18 @@ use TheBugs\Email\{ EmailConfiguration, MailerInterface, SwiftMailer };
use Taxus\{ Taxus, PermissionGrantInterface }; use Taxus\{ Taxus, PermissionGrantInterface };
use Lean\Factory\HttpFactoryInterface;
return [ return [
\Ulmus\User\Entity\UserInterface::class => autowire(Entity\User::class), \Ulmus\User\Entity\UserInterface::class => autowire(Entity\User::class),
SecurityHandler::class => create(SecurityHandler::class)->constructor(function() { SecurityHandler::class => create(SecurityHandler::class)->constructor(function(ContainerInterface $c) {
return Lean\Factory\HttpFactory::createRedirectResponse(getenv("URL_BASE")."/login"); return $c->get(HttpFactoryInterface::class)::createRedirectResponse(getenv("URL_BASE")."/login");
}, get('authentication.unauthorize'), get(Taxus::class)), }, get('authentication.unauthorize'), get(Taxus::class)),
'authentication.unauthorize' => function($c, Picea $picea) { 'authentication.unauthorize' => function(ContainerInterface $c, Picea $picea) {
return function($message) use ($picea) { return function($message) use ($c, $picea) {
return Lean\Factory\HttpFactory::createHtmlResponse($picea->renderHtml('lean/error/401', [ return $c->get(HttpFactoryInterface::class)::createHtmlResponse($picea->renderHtml('lean/error/401', [
'title' => "", 'title' => "",
'subtitle' => "", 'subtitle' => "",
'message' => $message, 'message' => $message,
@ -40,7 +43,7 @@ return [
EmailConfiguration::class => function($c) { EmailConfiguration::class => function($c) {
$email = new EmailConfiguration( EmailConfiguration::AUTH_TYPE_SMTP ); $email = new EmailConfiguration( EmailConfiguration::AUTH_TYPE_SMTP );
$email->smtpHost = getenv('SMTP_HOST'); $email->smtpHost = getenv('SMTP_HOSTNAME');
$email->smtpPort = getenv('SMTP_PORT'); $email->smtpPort = getenv('SMTP_PORT');
$email->smtpUsername = getenv('SMTP_USERNAME'); $email->smtpUsername = getenv('SMTP_USERNAME');
$email->smtpPassword = getenv('SMTP_PASSWORD'); $email->smtpPassword = getenv('SMTP_PASSWORD');

View File

@ -4,7 +4,7 @@ use Picea\Picea;
use Negundo\Client\{ NegundoMiddleware, SoftwareConfig }; use Negundo\Client\{ NegundoMiddleware, SoftwareConfig };
use Lean\Factory\HttpFactory; use Lean\Factory\HttpFactoryInterface;
use Psr\Http\Server\MiddlewareInterface, use Psr\Http\Server\MiddlewareInterface,
Psr\Http\Message\ServerRequestInterface, Psr\Http\Message\ServerRequestInterface,
@ -13,7 +13,7 @@ use Psr\Http\Server\MiddlewareInterface,
use function DI\{ create, get, autowire }; use function DI\{ create, get, autowire };
error_reporting(getenv('ERROR_REPORTING') ?: ( E_ALL & ~E_USER_DEPRECATED & ~E_DEPRECATED & ~E_NOTICE )); error_reporting(getenv('ERROR_REPORTING') ?: ( E_ALL & ~E_USER_DEPRECATED & ~E_DEPRECATED & ~E_STRICT & ~E_NOTICE ));
return [ return [
/* do nothing in production !*/ /* do nothing in production !*/
@ -31,11 +31,11 @@ return [
"errorHandler" => create(NegundoMiddleware::class)->constructor(get(SoftwareConfig::class), null, get('app.errorhandler.html')), "errorHandler" => create(NegundoMiddleware::class)->constructor(get(SoftwareConfig::class), null, get('app.errorhandler.html')),
'app.errorhandler.html' => function($c, Picea $picea) { 'app.errorhandler.html' => function(\Psr\Container\ContainerInterface $c, Picea $picea) {
return function(\Throwable $exception) use ($picea) { return function(\Throwable $exception) use ($c, $picea) {
error_log($exception->getMessage()); error_log($exception->getMessage());
return HttpFactory::createHtmlResponse($picea->renderHtml('lean/error/500', [ return $c->get(HttpFactoryInterface::class)::createHtmlResponse($picea->renderHtml('lean/error/500', [
'title' => "Une erreur s'est produite lors de l'exécution du script.", 'title' => "Une erreur s'est produite lors de l'exécution du script.",
'subtitle' => "Êtes-vous connecté avec le bon compte ?", 'subtitle' => "Êtes-vous connecté avec le bon compte ?",
'message' => $exception->getMessage(), 'message' => $exception->getMessage(),

View File

@ -1,14 +1,8 @@
<?php <?php
try { try {
$projectPath = dirname(__DIR__); require_once(dirname(__DIR__)."/src/Kernel.php");
require_once $projectPath . '/vendor/autoload.php';
new class($projectPath) extends %NAMESPACE%\Kernel {};
} }
catch(\Throwable $t) { catch(\Throwable $t) {
echo sprintf("%s<hr><small>%s:%d</small><br><pre>%s</pre>", $t->getMessage(), $t->getFile(), $t->getLine(), getenv('DEBUG') ? var_export($t->getTrace(), true) : ""); echo sprintf("%s in <strong>%s</strong> <pre>%s</pre>", $t->getMessage(), $t->getFile() . ":" . $t->getLine(), $t->getTraceAsString());
error_log($t->getMessage());
header("HTTP/1.1 500 Internal Server Error");
} }

View File

@ -7,7 +7,6 @@ use Storage\Session;
use Ulmus\User\Entity\User; use Ulmus\User\Entity\User;
use Notes\Route\Attribute\Object\Route; use Notes\Route\Attribute\Object\Route;
use Notes\Security\Attribute\Security; use Notes\Security\Attribute\Security;
use DI\Attribute\Inject;
use %NAMESPACE%\{ Entity, Lib, Form }; use %NAMESPACE%\{ Entity, Lib, Form };
@ -19,9 +18,9 @@ use Notes\Attribute\Ignore;use Ulmus\User\Entity\UserInterface;
trait ControllerTrait { trait ControllerTrait {
use \Lean\ControllerTrait; use \Lean\ControllerTrait;
#[Inject] #[Ignore]
public ? UserInterface $user; public ? UserInterface $user;
#[Inject] #[Ignore]
protected EventManager $eventManager; protected EventManager $eventManager;
} }

View File

@ -38,4 +38,37 @@ class ApplicationStrategy extends Strategy\ApplicationStrategy {
{ {
return $this->getContainer()->has(MethodNotAllowedInterface::class) ? $this->getContainer()->get(MethodNotAllowedInterface::class) : parent::getMethodNotAllowedDecorator($exception); return $this->getContainer()->has(MethodNotAllowedInterface::class) ? $this->getContainer()->get(MethodNotAllowedInterface::class) : parent::getMethodNotAllowedDecorator($exception);
} }
/*
<<<<<<< HEAD
public function getMethodNotAllowedDecorator(MethodNotAllowedException $exception): MiddlewareInterface
{
return $this->getContainer()->has(MethodNotAllowedInterface::class) ? $this->getContainer()->get(MethodNotAllowedInterface::class) : parent::getMethodNotAllowedDecorator($exception);
=======
public function process(ServerRequestInterface $request, RequestHandlerInterface $handler): ResponseInterface
{
if (php_sapi_name() !== 'cli' and ! defined('STDIN')) {
return $this->throw404($request);
}
return $handler->handle($request);;
}
public function throw404(ServerRequestInterface $request) : ResponseInterface
{
if ( getenv('DEBUG') && $this->di->has(\Picea\Asset\Asset::class) ) {
$params = $request->getServerParams();
$scpName = basename(explode('?', $params['REQUEST_URI'] ?? "", 2)[0]);
list(, $ext) = array_pad(explode('.', $scpName), 2, null);
if ($ext && in_array($ext, ApplicationStrategy::ASSET_TRIGGER_UPDATE)) {
$this->di->get(\Picea\Asset\Asset::class)->launchInstall();
}
}
return $this->di->get('error.404');
}
};
>>>>>>> af8b686 (- WIP on ulmus-user mechanics updates)
}*/
} }

View File

@ -39,7 +39,7 @@ class NotFoundDecorator implements NotFoundDecoratorInterface
public function throw404(ServerRequestInterface $request) : ResponseInterface public function throw404(ServerRequestInterface $request) : ResponseInterface
{ {
return $this->checkAssetTrigger($request) ?: $this->httpFactory->createHtmlResponse($this->picea->renderHtml("lean/error/404", [], $this), 404); return $this->checkAssetTrigger($request) ?: $this->container->get('error.404');
} }
protected function checkAssetTrigger(ServerRequestInterface $request) : false|ResponseInterface protected function checkAssetTrigger(ServerRequestInterface $request) : false|ResponseInterface

View File

@ -27,8 +27,7 @@ class Composer
$source = static::createPath('vendor', 'mcnd', 'lean', 'skeleton'); $source = static::createPath('vendor', 'mcnd', 'lean', 'skeleton');
$dest = static::createPath('skeleton'); $dest = static::createPath('skeleton');
shell_exec("cp -a $source $dest"); `cp -a $source $dest`;
#`cp -a $source $dest`;
$iterator = new \RecursiveDirectoryIterator($dest); $iterator = new \RecursiveDirectoryIterator($dest);
$iterator->setFlags(\RecursiveDirectoryIterator::SKIP_DOTS); $iterator->setFlags(\RecursiveDirectoryIterator::SKIP_DOTS);

View File

@ -82,13 +82,6 @@ trait ControllerTrait {
return HttpFactory::createRedirectResponse($url, $code, $headers); return HttpFactory::createRedirectResponse($url, $code, $headers);
} }
#[Ignore]
protected function refresh(int $code = 204, array $headers = []) {
return static::renderNothing($code, [
'Refresh' => 0
] + $headers);
}
#[Ignore] #[Ignore]
public static function renderNothing(int $code = 204, array $headers = []) : ResponseInterface public static function renderNothing(int $code = 204, array $headers = []) : ResponseInterface
{ {

View File

@ -11,9 +11,9 @@ use Psr\Http\Message\StreamInterface;
class HttpFactory implements HttpFactoryInterface class HttpFactory implements HttpFactoryInterface
{ {
public static function createResponse(mixed $body = 'php://memory', int $code = 200, array $headers = []) : ResponseInterface public static function createResponse(string $url, int $code = 302, array $headers = []) : ResponseInterface
{ {
return new Response($body, $code, $headers); return new Response($url, $code, $headers);
} }
public static function createRedirectResponse(string $url, int $code = 302, array $headers = []) : ResponseInterface public static function createRedirectResponse(string $url, int $code = 302, array $headers = []) : ResponseInterface

View File

@ -2,9 +2,6 @@
namespace Lean\Factory; namespace Lean\Factory;
use Laminas\Diactoros\Response\{EmptyResponse, HtmlResponse, JsonResponse, RedirectResponse, TextResponse};
use Lean\Response\{ DownloadResponse, ImageResponse, FileDownloadResponse, PdfResponse };
use Laminas\Diactoros\Response;
use Psr\Http\Message\ResponseInterface; use Psr\Http\Message\ResponseInterface;
use Psr\Http\Message\StreamInterface; use Psr\Http\Message\StreamInterface;
@ -20,6 +17,5 @@ interface HttpFactoryInterface
public static function createDownloadableResponse(string $data, string $filename, int $code = 200, array $headers = []) : ResponseInterface; public static function createDownloadableResponse(string $data, string $filename, int $code = 200, array $headers = []) : ResponseInterface;
public static function createImageResponse(string $data, int $code = 200, array $headers = []) : ResponseInterface; public static function createImageResponse(string $data, int $code = 200, array $headers = []) : ResponseInterface;
public static function createFileDownloadResponse(string $path, int $code = 200, array $headers = []) : ResponseInterface; public static function createFileDownloadResponse(string $path, int $code = 200, array $headers = []) : ResponseInterface;
public static function createStream(string $content) : StreamInterface; public static function createStream(string $content) : StreamInterface;
} }

View File

@ -14,20 +14,20 @@ class File
$beginning = false; $beginning = false;
$text = array(); $text = array();
while ($counter && !$beginning) { while ($counter && ! $beginning) {
$t = ""; $t = "";
while ($t !== PHP_EOL) { while ($t !== PHP_EOL) {
if (fseek($handle, $pos, SEEK_END) == -1) { if(fseek($handle, $pos, SEEK_END) == -1) {
$beginning = true; $beginning = true;
break; break;
} }
$t = fgetc($handle); $t = fgetc($handle);
$pos--; $pos --;
} }
$counter--; $counter --;
if ($beginning) { if ($beginning) {
rewind($handle); rewind($handle);
@ -36,40 +36,8 @@ class File
$text[$lines - $counter - 1] = fgets($handle); $text[$lines - $counter - 1] = fgets($handle);
} }
fclose($handle); fclose ($handle);
return array_reverse($text); return array_reverse($text);
} }
public static function sanitizeFilePath($path) : string
{
// Remove null bytes
$path = str_replace("\0", "", $path);
$path = str_replace([ "\\", "/" ], DIRECTORY_SEPARATOR, $path);
$path = preg_replace('#' . DIRECTORY_SEPARATOR . '+#', DIRECTORY_SEPARATOR, $path);
// Remove . and .. directory traversal attempts
$path = preg_replace('#\.{1,2}/#', '', $path);
$path = trim($path, '/\\');
return $path;
}
public static function assertFileExists(string $filepath) : void
{
if (! is_file($filepath)) {
throw new \InvalidArgumentException("File does not exist: {$filepath}");
}
}
public static function assertFolderExists(string $path) : void
{
if (! is_dir($path)) {
throw new \InvalidArgumentException("Folder does not exist: {$path}");
}
}
} }

View File

@ -11,22 +11,23 @@ use League\Route\Strategy\ApplicationStrategy;
use Psr\Http\Message\ServerRequestInterface; use Psr\Http\Message\ServerRequestInterface;
use Tell\I18n;
use Ulmus\Container\AdapterProxy;
use Laminas\Diactoros\ServerRequestFactory, use Laminas\Diactoros\ServerRequestFactory,
Laminas\HttpHandlerRunner\Emitter\EmitterInterface; Laminas\HttpHandlerRunner\Emitter\EmitterInterface;
use Ulmus\Ulmus; use Ulmus\Ulmus;
class Kernel class Kernel {
{
protected Container $container; protected Container $container;
protected string $locale; protected string $locale;
public array $paths = []; public array $paths = [];
public int $errorReportingDev = -1; public int $errorReporting = E_ALL & ~E_USER_DEPRECATED & ~E_DEPRECATED & ~E_NOTICE;
public int $errorReportingProd = E_ALL & ~E_USER_DEPRECATED & ~E_DEPRECATED /*& ~E_NOTICE*/;
public array $definitionFilePaths; public array $definitionFilePaths;
@ -34,10 +35,7 @@ class Kernel
public function __construct( public function __construct(
public string $projectPath public string $projectPath
) ) {
{
# Still not sure about adding a folder check each call just to add a basic project setup error ...
# File::assertFolderExists($this->projectPath);
$this->setEnvironment(); $this->setEnvironment();
$this->initializeEngine(); $this->initializeEngine();
$this->setupContainer(); $this->setupContainer();
@ -45,27 +43,21 @@ class Kernel
$this->handleRequest(); $this->handleRequest();
} }
public static function putenv($var, $value) : void public static function putenv($var, $value)
{ {
putenv("$var=$value"); putenv("$var=$value");
$_ENV[$var] = $value; $_ENV[$var] = $value;
} }
protected function setEnvironment() : void protected function setEnvironment() {
{
static::putenv('PROJECT_PATH', $this->projectPath); static::putenv('PROJECT_PATH', $this->projectPath);
// Environment vars (accessible from \DI\env(), getenv(), $_ENV and $_SERVER) // Environment vars (accessible from \DI\env(), getenv(), $_ENV and $_SERVER)
Dotenv::create(getenv("PROJECT_PATH"))->load(); Dotenv::create(getenv("PROJECT_PATH"))->load();
// Override using headers // Override using headers
if (($keys = getenv('KEYS')) && ($auth = $_SERVER["HTTP_X_DEV_AUTH"] ?? null) && in_array($auth, explode(',', $keys))) { if ( ( $keys = getenv('KEYS') ) && ( $auth = $_SERVER["HTTP_X_DEV_AUTH"] ?? null ) && in_array($auth, explode(',', $keys)) ) {
unset($_SERVER["HTTP_X_DEV_AUTH"]); foreach (['APP_ENV', 'DEBUG',] as $env) {
unset($_ENV['KEYS'], $_SERVER['KEYS']);
putenv("KEYS=");
foreach(['APP_ENV', 'DEBUG',] as $env) {
if (null !== $value = $_SERVER["HTTP_X_$env"] ?? null) { if (null !== $value = $_SERVER["HTTP_X_$env"] ?? null) {
static::putenv($env, $value); static::putenv($env, $value);
} }
@ -74,7 +66,7 @@ class Kernel
// Paths and directories // Paths and directories
foreach($this->paths as $name => $envkey) { foreach($this->paths as $name => $envkey) {
if (!getenv($name)) { if ( ! getenv($name) ) {
$path = getenv("PROJECT_PATH") . DIRECTORY_SEPARATOR . getenv($envkey); $path = getenv("PROJECT_PATH") . DIRECTORY_SEPARATOR . getenv($envkey);
if (getenv('DEBUG') && ! file_exists($path)) { if (getenv('DEBUG') && ! file_exists($path)) {
@ -96,20 +88,15 @@ class Kernel
setlocale(LC_ALL, $this->locale = getenv("DEFAULT_LOCAL")); setlocale(LC_ALL, $this->locale = getenv("DEFAULT_LOCAL"));
setlocale(LC_TIME, getenv("DEFAULT_TIME"), getenv("DEFAULT_TIME_FALLBACK")); setlocale(LC_TIME, getenv("DEFAULT_TIME"), getenv("DEFAULT_TIME_FALLBACK"));
if (class_exists('Locale')) { if ( class_exists('Locale') ) {
\Locale::setDefault($this->locale); \Locale::setDefault($this->locale);
} }
ini_set("error_log", $this->errorLogPath ?? getenv("LOGS_PATH") . DIRECTORY_SEPARATOR. date("Y-m").".log"); ini_set("log_errors", "1");
ini_set("log_errors", true); ini_set("error_log", $this->errorLogPath);
ini_set('display_errors', getenv("DEBUG") ? 'on' : 'off'); ini_set('display_errors', getenv("DEBUG") ? 'on' : 'on');
if (getenv("DEBUG")) { error_reporting($this->errorReporting);
error_reporting(getenv('ERROR_REPORTING_DEV') ?: $this->errorReportingDev);
}
else {
error_reporting(getenv('ERROR_REPORTING_PROD') ?: $this->errorReportingProd);
}
return $this; return $this;
} }
@ -122,8 +109,7 @@ class Kernel
if (getenv("APP_ENV") === "prod") { if (getenv("APP_ENV") === "prod") {
if (getenv("CACHE_PATH")) { if (getenv("CACHE_PATH")) {
# check if ACPU is there first, # check if ACPU is there first, $containerBuilder->enableDefinitionCache();
# $containerBuilder->enableDefinitionCache(); # Do not work .. ?
$containerBuilder->enableCompilation(getenv("CACHE_PATH") . "/di/"); $containerBuilder->enableCompilation(getenv("CACHE_PATH") . "/di/");
# No proxies yet... $containerBuilder->writeProxiesToFile(true, getenv("CACHE_PATH") . "/di/"); # No proxies yet... $containerBuilder->writeProxiesToFile(true, getenv("CACHE_PATH") . "/di/");
@ -132,7 +118,7 @@ class Kernel
else { else {
$compiled = getenv("CACHE_PATH") . "/di/CompiledContainer.php"; $compiled = getenv("CACHE_PATH") . "/di/CompiledContainer.php";
if (file_exists($compiled)) { if ( file_exists($compiled) ) {
unlink($compiled); unlink($compiled);
} }
} }
@ -167,7 +153,8 @@ class Kernel
} }
# Must be removed from KERNEL ! # Must be removed from KERNEL !
$this->container->has('ulmus.caching') and (Ulmus::$cache = $this->container->get('ulmus.caching')); $this->container->has('ulmus.caching') and ( Ulmus::$cache = $this->container->get('ulmus.caching') );
# $this->container->has(AdapterProxy::class) and ( $ )
return $this; return $this;
} }
@ -190,4 +177,4 @@ class Kernel
return $this; return $this;
} }
} };

View File

@ -244,15 +244,4 @@ class Lean
return call_user_func($func); return call_user_func($func);
} }
public static function path(...$parts) : string
{
return implode(DIRECTORY_SEPARATOR, $parts);
}
public static function rawPath(...$parts) : string
{
return implode(DIRECTORY_SEPARATOR, $parts);
}
} }

View File

@ -43,6 +43,7 @@ class FileDownloadResponse extends Response
else { else {
$finfo = finfo_open(FILEINFO_MIME_TYPE); $finfo = finfo_open(FILEINFO_MIME_TYPE);
$mime = finfo_file($finfo, $filepath); $mime = finfo_file($finfo, $filepath);
finfo_close($finfo);
} }
parent::__construct( parent::__construct(

View File

@ -1,11 +0,0 @@
{% arguments array $contextList %}
{% if $contextList %}
<div class="message-wrapper">{% php
foreach($contextList as $name => $context) {
foreach($context->formContextMessages ?? [] as $message) {
echo $message->render();
}
}
%}</div>
{% endif %}

View File

@ -2,7 +2,6 @@
<!DOCTYPE html> <!DOCTYPE html>
<html> <html>
<head> <head>
<meta charset="UTF-8" />
<meta http-equiv="Content-Type" content="text/html; "> <meta http-equiv="Content-Type" content="text/html; ">
<meta name="viewport" content="width=device-width"> <meta name="viewport" content="width=device-width">
<title>{{ title() }}</title> <title>{{ title() }}</title>

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 2.3 KiB

After

Width:  |  Height:  |  Size: 40 KiB

View File

@ -22,7 +22,7 @@
{% slot "week.heading", $day, $month, $year %} {% slot "week.heading", $day, $month, $year %}
<div class="day-box"> <div class="day-box">
{# Random calendar date that starts on a sunday #} {# Random calendar date that starts on a sunday #}
{{ new Date("2019-12-$day")->formatLocaleIntl(\IntlDateFormatter::SHORT, \IntlDateFormatter::NONE, 'EEE') }} {{ substr(( new Date("2019-12-$day") )->formatLocale("%A"), 0, 3) }}
</div> </div>
{% endslot %} {% endslot %}
{% endforeach %} {% endforeach %}

View File

@ -5,4 +5,14 @@
if ($context && ! in_array($context, $messageList)) { if ($context && ! in_array($context, $messageList)) {
$messageList[] = $context; $messageList[] = $context;
} }
%}{% block "lean/block/message", $messageList %}{% endblock %} %}
{% if $messageList %}
<div class="message-wrapper">{% php
foreach($messageList as $name => $context) {
foreach($context->formContextMessages ?? [] as $message) {
echo $message->render();
}
}
%}</div>
{% endif %}